/* LabFlow theme — design_tokens_reference.md applied as a pure styling layer on top of Bootstrap
   5.3.3 (loaded via CDN in the layout templates; this file is included right after it).

   Nothing here touches routes, models, or template logic — see design_tokens_reference.md at the
   repo root for the source system this file implements section-by-section. Every rule below is
   traceable to a specific section of that document; nothing is invented beyond it (per explicit
   instruction: don't extend documented patterns to cases they don't cover).
*/

/* ---- Section 8: quick-reference token block, verbatim ---- */
:root{
  --paper:#F2F4F0; --surface:#FFFFFF; --surface-2:#FAFBF9;
  --ink:#1B231F; --ink-soft:#4C564E; --ink-faint:#7C877E;
  --line:#DBE0D7; --line-strong:#C3CABD;
  --teal:#0E6E63; --teal-dark:#0A4F47; --teal-tint:#E3EFED;
  --amber:#AD7A1E; --amber-tint:#F7ECD8;
  --rust:#A6402E; --rust-tint:#F5E2DE;
  --sky:#33636D; --sky-tint:#E5EEEF;
  /* Dynamic variant only — the new-section draft form's own border color (see
     .dyn-new-section-card in the uniform-styling-pass block below), distinct from --teal
     (already used everywhere for the active/primary accent) so the in-progress draft visually
     stands apart from committed content. Originally its own separate, later :root block
     (byte-identical to this one otherwise) — collapsed in here, TODO.md item 13. */
  --green:#2E7D32; --green-tint:#E5F0E6;
  --font-display:'Space Grotesk', sans-serif;
  --font-body:'IBM Plex Sans', sans-serif;
  --font-mono:'JetBrains Mono', monospace;

  /* ---- Section 2: Bootstrap variable redirect — ONLY the 7 properties the reference names.
     Bootstrap's other semantic colors (secondary/success/danger/warning/info) are deliberately
     left untouched (confirmed with the user) — existing alert-danger, btn-outline-success, etc.
     keep stock Bootstrap colors everywhere. */
  --bs-body-bg: var(--paper);
  --bs-body-color: var(--ink);
  --bs-body-font-family: var(--font-body);
  --bs-primary: var(--teal);
  --bs-primary-rgb: 14,110,99;
  --bs-border-color: var(--line);
  --bs-link-color: var(--teal-dark);
}

body{ font-family:var(--font-body); font-size:14.5px; background:var(--paper); color:var(--ink); }
h1,h2,h3,h4,h5{ font-family:var(--font-display); letter-spacing:-0.01em; }
code, .mono{ font-family:var(--font-mono); }

/* ---------- Sticky footer — keeps the footer at the bottom of the viewport on short pages
   (empty Calendar tab, Settings > Approval Chain, etc.) and in normal document flow below the
   content on long pages (never position:fixed, which would float over content instead). Every
   layout's <body> has exactly three direct children in source order — header, <main>, <footer>
   (layouts/base_app.html, layouts/base_public.html; layouts/bare.html has no footer at all, so
   nothing to pin there) — so this is just the standard flex-column-with-one-growing-child
   pattern, no wrapper div needed. The `.app-main`/`.app-footer` class selectors are a no-op
   fallback for this codebase today (every layout's content/footer are real <main>/<footer>
   elements already matched by the bare tag selectors) kept in case a future layout wraps them
   in a differently-tagged element instead. ---------- */
html { height: 100%; }
body {
  min-height: 100vh;
  min-height: 100dvh; /* mobile browsers with a collapsing toolbar */
  display: flex;
  flex-direction: column;
}
body > main,
body > .app-main {
  flex: 1 0 auto; /* grows to fill the free space */
}
body > footer,
body > .app-footer {
  flex-shrink: 0; /* stays at the bottom, pushed by the grown <main> above it */
}

/* ---- Section 3: border radius, by container type — applied directly to Bootstrap's own
   classes rather than guessed per-component Bootstrap 5.3 variable names (version-independent). */

/* Small controls: buttons, inputs, small cards -> 4-5px */
.btn, .form-control, .form-select{ border-radius: 5px; }

/* Standard cards/sections -> .5-.6rem */
.card{ border-radius: .55rem; }

/* Popovers/dropdowns -> .5rem */
.dropdown-menu{ border-radius: .5rem; }

/* Pills/badges/chips -> fully rounded */
.badge{ border-radius: 999px; }

/* ---- Section 6: component patterns ---- */

/* Buttons — pill family (quiet destructive actions, e.g. "Remove step/note/observation").
   Not applied anywhere in this pass — no inline add/remove-list-item UI exists in the app today
   that matches this pattern's documented use case. Defined here for future use. */
.pill-btn{
  font-family:var(--font-mono); font-size:.7rem; border:1px solid var(--line-strong);
  background:var(--surface-2); color:var(--ink-soft); border-radius:999px; padding:.3rem .75rem;
}
.pill-btn:hover{ border-color:var(--rust); color:var(--rust); }

/* Badge/chip family — pill radius + tint-background formula (section 2's pattern note). */
.mono-chip{
  font-family:var(--font-mono); font-size:.75rem; background:var(--surface);
  border:1px solid var(--line); color:var(--ink-soft); border-radius:999px; padding:.2rem .6rem;
}
/* Item-count indicator (e.g. notebook_ui.js's Usage Log entry count) — square corners, not the
   pill radius the rest of the chip family uses, per explicit "badge for Number of items should be
   in square not circle." A modifier on .mono-chip rather than changing that shared class, since
   .mono-chip is also used for non-count chips (checksum display, etc.) that weren't flagged. */
.mono-chip.count-chip{ border-radius:4px; padding:.2rem .5rem; }
.badge-soft{
  font-weight:500; border-radius:999px; padding:.35em .65em; border:1px solid transparent;
}
.badge-soft.badge-status{ background:var(--teal-tint); color:var(--teal-dark); border-color:var(--teal-tint); }
.badge-soft.badge-domain{ background:var(--sky-tint); color:var(--sky); border-color:var(--sky-tint); }
.badge-soft.badge-critical{ background:var(--rust-tint); color:var(--rust); border-color:var(--rust-tint); }
.badge-soft.badge-caution{ background:var(--amber-tint); color:var(--amber); border-color:var(--amber-tint); }

/* Same tint formula, used for the critical/safety/pause quick-glance flags described in section 6. */
.flag-badge{
  display:inline-block; border-radius:999px; padding:.35em .65em; font-weight:500;
  border:1px solid transparent; cursor:default;
}
.flag-badge.flag-critical{ background:var(--rust-tint); color:var(--rust); }
.flag-badge.flag-caution{ background:var(--amber-tint); color:var(--amber); }
.flag-badge.flag-pause{ background:var(--sky-tint); color:var(--sky); }

/* Alert/callout — critical/safety/pause note content that's always paired with a real, editable
   textarea (not static read-only text). */
.note-callout{
  background:var(--rust-tint); border:1px solid var(--rust-tint); border-radius:.35rem;
  padding:.85rem 1rem;
}
.note-callout textarea{
  background:var(--surface); border:1px solid var(--line-strong); border-radius:5px;
}

/* Cards — white/near-white surface, subtle border, standard radius. */
.data-card, .field-section{
  background:var(--surface); border:1px solid var(--line); border-radius:.55rem;
  padding:1.1rem 1.25rem;
}

/* Step-card — same card treatment plus a left-border "sequential item" cue (teal by default,
   rust when the step represents a critical/rejected outcome). */
.step-card{
  background:var(--surface); border:1px solid var(--line); border-left:4px solid var(--teal);
  border-radius:.55rem; padding:.9rem 1.1rem;
}
.step-card.step-card-critical{ border-left-color: var(--rust); }

/* Tabs — flat-bottomed rounded-top buttons, sitting slightly "behind" the active tab at rest
   (the asymmetric radius is the one deliberate signature detail of this system). Labels use the
   mono font (per explicit instruction — "in protocol tab and other tab use jetbrains mono"),
   matching the same --font-mono already used for chips/badges/code elsewhere in this system.
   Pure CSS selector, zero template edits — applies to every .nav-tabs on the site (group_detail's
   own top-level tabs and Configurations' sub-tabs, protocol_subnav.html's tabs, etc.). */
.nav-tabs .nav-link{
  border-radius: 10px 10px 0 0;
  transform: translateY(3px);
  transition: transform .12s ease;
  font-family: var(--font-mono);
}
.nav-tabs .nav-link:hover, .nav-tabs .nav-link.active{
  transform: translateY(0);
}

/* Sticky side navigation — not applicable in this pass; the app has no sidebar/sidenav anywhere
   to apply it to. Left undefined rather than manufacturing a sidenav that doesn't exist. */


/* =====================================================================================
   UNIFORM STYLING PASS (uniform_styling branch) — everything below this line is Dynamic
   protocol's own complete stylesheet (protocol_ui_v2.css), merged in verbatim so it applies
   APP-WIDE via this file (loaded by every layout — base_app.html/base_public.html/bare.html),
   not just the protocol_ui page family that links protocol_ui_v2.css directly.

   Per explicit instruction, this is a CSS-only pass — no template/JS edits. Appending after
   this file's own pre-existing rules above means any selector both files already defined
   (.data-card, .step-card, .pill-btn, .mono-chip, .badge-soft + variants, .nav-tabs .nav-link,
   the :root token block) resolves to THIS block's values, since a later same-specificity rule
   wins the cascade — i.e. Dynamic protocol's actual rendered look (not this file's own earlier,
   sometimes-slightly-different copies of the "same" rule) is now what the whole app gets.

   FOLLOW-UP (TODO.md item 13, done in a later pass): protocol_ui_v2.css's own <link> tag was
   removed from every template that only ever loaded it for this exact content (generic_v2.html,
   structured_v2.html, dynamic_v2.html, protocol_fork.html) — genuinely redundant once this file
   carries the same rules app-wide. protocol_ui.css — the OLDER, separate stylesheet — is NOT
   touched by this: it has real rules with no equivalent here (no heading size scale, no .fs-*
   utilities, no .btn size overrides, no .data-card/.step-card padding — see that file's own
   header), so notebook_ui.html/calendar_entry_new.html/calendar_entry_edit.html keep loading it.
   The pre-v2 generic.html/structured.html templates were confirmed unreachable (protocols.
   detail() only ever renders the _v2 variants) and retired outright, rather than left in place.

   Original file header, preserved verbatim below for provenance:
   ===================================================================================== */

/* Protocol UI v2 — styling rebuilt directly from the two reference files given
   (protocol_ui_simple.html = the generic/simple variant, protocol_ui_structured.html = the
   "Protocol Binder" structured variant), NOT from generic_protocol/structured_protocol (the
   earlier prototypes) and NOT invented. This file only restyles — it targets the EXACT SAME
   class names the current app's components already generate (protocol_ui_generic.js /
   protocol_ui_structured.js are untouched); nothing here changes what renders, only how it looks.

   Where the two reference files disagree on a value (they're independent files, so a few numbers
   differ slightly — e.g. .nav-tabs font-size .85rem vs .8rem, .form-label .7rem vs .68rem), the
   structured reference's value was used as the single shared value, since one CSS file serves
   both variants and the two references are otherwise near-identical. Called out inline wherever
   it happens. Where NEITHER reference defines a class my components actually use (e.g.
   .pill-btn, .repeater-card, .accordion-*, .segmented-control, .table-premium's own richer
   look, the structured variant's critical/caution/pause step-number-badge colors) — that rule is
   left exactly as it already was; there's nothing in the reference to copy for it.

   This block originally had its own :root token block, byte-for-byte identical to Section 8's
   own quick-reference block at the top of this file except for two genuinely new tokens
   (--green/--green-tint) — collapsed into that single top block (TODO.md item 13's style-audit
   follow-up) rather than kept as a confusing duplicate two same-specificity :root rules would
   otherwise resolve identically. See Section 8's own block for --green/--green-tint now.
*/

/* Reference: body{ font-size:14.5px; } — no explicit background/color/padding override; the
   --bs-body-bg/--bs-body-color redirect above (plus Bootstrap's own reboot) already covers it. */
body {
  font-size: 14.5px;
}

/* Reference: h1..h6{ font-family:var(--font-display); color:var(--ink); letter-spacing:-0.01em; }
   — deliberately NO font-weight override and NO per-level font-size scale here. Every specific
   title/heading element (page title, section h2, sub-headings) gets its OWN explicit size below,
   exactly the way both reference files do it — nothing relies on a blanket h1-h6 size scale. */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  color: var(--ink);
  letter-spacing: -0.01em;
}

code, .mono, .font-monospace, pre, .mono-chip {
  font-family: var(--font-mono);
}

/* ---------- Form controls (reference: both files, identical) ---------- */
.form-label {
  font-size: 0.7rem;
  font-family: var(--font-mono);
  color: var(--ink-faint);
  letter-spacing: 0.02em;
}
.form-control, .form-select {
  background-color: var(--surface-2);
  border-color: var(--line);
  font-size: 0.9rem;
}
.form-control:focus, .form-select:focus {
  border-color: var(--teal);
  box-shadow: 0 0 0 0.2rem rgba(14, 110, 99, 0.15);
  background-color: var(--surface);
}
/* BUG FIX: the generic/simple protocol variant's Edit Mode / View Mode toggle works by adding/
   removing readonly (inputs/textareas) and disabled (selects) — see applyEditLockForSection() in
   protocol_ui_generic.js — but nothing here gave that any visual difference; both states used the
   exact same background/border, so toggling modes looked like it "had no effect" even though
   fields genuinely were (un)editable. The structured variant doesn't need this — its view mode
   swaps to entirely different, non-input markup, so this only actually matters for generic/simple. */
.form-control:read-only, .form-select:disabled, .form-control:disabled {
  background-color: var(--paper);
  border-style: dashed;
  color: var(--ink-soft);
  cursor: not-allowed;
}
.input-group-text {
  background-color: var(--surface-2);
  border-color: var(--line);
  color: var(--ink-soft);
}
/* Reference has no .btn/.btn-sm/.btn-lg size override at all — dropped here too; Bootstrap's own
   default button sizing applies, exactly as given. Same for .btn-outline-secondary: neither
   reference recolors it, so it stays stock Bootstrap secondary-outline. */

/* ---------- Layout shell ---------- */
.app-container {
  max-width: 1180px;
  margin: 0 auto;
  padding: 26px 20px 80px;
}

/* ---------- Header / topbar (reference: .topbar) ---------- */
.protocol-header {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  padding: 1.25rem 1.5rem;
  margin-bottom: 14px;
  position: relative;
  box-shadow: 0 1px 2px rgba(20, 30, 25, 0.06);
}
.protocol-header::before {
  content: "";
  position: absolute;
  top: 0; left: 1.5rem; right: 1.5rem;
  height: 3px;
  background: linear-gradient(90deg, var(--teal), var(--sky) 60%, var(--amber));
  border-radius: 0 0 3px 3px;
}
.protocol-title-display {
  font-size: 1.65rem;
  font-weight: 600;
  line-height: 1.15;
}
.protocol-eyebrow, .eyebrow {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
/* metadata-banner and friends have no reference equivalent (the reference lays badges directly
   in the topbar via flex, not a separate sub-box) — kept as they already were. */
.metadata-banner {
  background-color: var(--surface-2);
  border-radius: 0.5rem;
  padding: 0.7rem 1.1rem;
  border: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.metadata-field-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  /* Anchors the version-history dropdown below (moved here from the toolbar per explicit
     instruction — the version chip + its "previous versions" caret both live in this first row
     now, right after the title, instead of being split across here and the toolbar). */
  position: relative;
}
.metadata-item {
  display: inline-flex;
  align-items: center;
  margin-right: 1.5rem;
  font-size: 0.9rem;
}
.metadata-label {
  font-family: var(--font-mono);
  color: var(--ink-faint);
  margin-right: 0.4rem;
  font-size: 0.8rem;
  text-transform: uppercase;
}
/* Reference's closest analog is .chip-version, a modifier meant to sit on top of the shared
   .badge-soft base rule (mono font, .7rem, weight 500, pill radius, .3rem .7rem padding) — folded
   directly in here since this component is used standalone, plus the click/hover behavior this
   component actually has (opens the version popup) that the reference's version isn't wired to. */
.version-chip {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 500;
  background-color: var(--teal-tint);
  color: var(--teal-dark);
  border: 1px solid #BFDDD8;
  border-radius: 999px;
  padding: 0.3rem 0.7rem;
  cursor: pointer;
  transition: all 0.15s ease;
  display: inline-flex;
  width: fit-content;
}
.version-chip:hover {
  background-color: var(--teal);
  color: var(--surface);
  border-color: var(--teal);
}

/* ---------- .version-chip-lg: used to widen a second, toolbar-only version chip that duplicated
   the metaheader's own — that toolbar chip was removed per explicit "redundant, mentioned twice"
   feedback, so nothing currently applies this modifier. Left defined (unused) rather than deleted,
   in case a wider chip is wanted again somewhere. ---------- */
.version-chip-lg {
  min-width: 12rem;
  justify-content: center;
}

/* ---------- Version-history caret + dropdown (now in the metaheader's own first row, next to the
   version chip — see renderHeader() in protocol_ui_generic.js/protocol_ui_structured.js) — no
   reference equivalent. The caret is a plain ">" character rotated via CSS (no icon font, per
   explicit instruction), toggled by toggleVersionHistoryDropdown() in protocol_ui_shared.js.
   Anchored by .metadata-field-row's own position:relative, above. ---------- */
.version-history-toggle {
  transform: rotate(90deg);
  line-height: 1;
  padding: 0.3rem 0.55rem;
}
.version-history-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 0.25rem;
  z-index: 20;
  min-width: 320px;
  max-height: 320px;
  overflow-y: auto;
  background-color: var(--surface);
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  box-shadow: 0 4px 16px rgba(20, 30, 25, 0.12);
  padding: 0.5rem;
}
.version-history-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.25rem;
  border-bottom: 1px solid var(--line);
}
.version-history-row:last-child {
  border-bottom: none;
}

/* ---------- Global field search bar (reference: .search-wrap / .search-results-panel /
   .search-result-row — this component uses dedicated .search-input/.search-results/
   .search-result-item classes rather than descendant selectors off .form-control, so the
   reference's values are applied directly onto those instead). ---------- */
.search-wrap {
  position: relative;
  margin-bottom: 14px;
}
.search-wrap svg {
  position: absolute;
  left: 1.1rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--ink-faint);
  pointer-events: none;
}
.search-input {
  width: 100%;
  border: 1px solid var(--line);
  background-color: var(--surface);
  border-radius: 999px;
  padding: 0.375rem 0.75rem 0.375rem 2.6rem;
  font-size: 0.9rem;
  color: var(--ink);
}
.search-input:focus {
  outline: none;
  border-color: var(--teal);
  background-color: var(--surface);
  box-shadow: 0 0 0 0.2rem rgba(14, 110, 99, 0.15);
}
.search-results {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background-color: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 0.5rem;
  box-shadow: 0 8px 24px rgba(20,30,25,.14);
  max-height: 340px;
  overflow-y: auto;
  z-index: 1050;
  display: none;
}
.search-results.show {
  display: block;
}
.search-result-item {
  padding: 0.6rem 1rem;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
}
.search-result-item:last-child {
  border-bottom: none;
}
.search-result-item:hover {
  background-color: var(--teal-tint);
}
.search-result-tab {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--sky);
}
.search-result-snippet {
  font-size: 0.82rem;
  color: var(--ink-soft);
}
.search-result-snippet mark {
  background-color: #FCE7B5;
  border-radius: 2px;
  padding: 0 2px;
}
/* Not in either reference file at all — kept as it already was. */
.search-empty {
  padding: 0.8rem 0.9rem;
  font-size: 0.82rem;
  color: var(--ink-faint);
  font-style: italic;
  text-align: center;
}

/* Wrapper div for horizontal tab scrolling — the reference puts overflow-x directly on
   .nav-tabs; this component wraps it in its own div instead, so kept as it already was (same
   visible effect, different implementation). */
.tab-scroll-wrap {
  overflow-x: auto;
  scrollbar-width: thin;
  margin-bottom: 1.5rem;
}
.tab-scroll-wrap::-webkit-scrollbar {
  height: 6px;
}
.tab-scroll-wrap::-webkit-scrollbar-thumb {
  background-color: var(--line-strong);
  border-radius: 999px;
}
.tab-scroll-wrap .nav-tabs {
  margin-bottom: 0;
  flex-wrap: nowrap;
}
.tab-scroll-wrap .nav-item {
  flex-shrink: 0;
}

.stacked-section {
  width: 100%;
}
.stacked-field-group {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

/* ---------- Tabs — per explicit instruction, a real four-sided border on every tab (active or
   not), not just the bottom-accent-on-active "binder tab" look this used to be (border-bottom:
   none on both the container and the tab itself, relying on box-shadow for the active tab's own
   accent) — that made an inactive tab look borderless until clicked. Top corners still rounded
   (the one part of that look kept); every side now gets a real, always-visible border. ---------- */
.nav-tabs {
  margin-bottom: 1.5rem;
  gap: 4px;
}
.nav-tabs .nav-link {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 0.8rem;
  border: 1px solid var(--line);
  background-color: var(--surface-2);
  color: var(--ink-soft);
  border-radius: 10px 10px 0 0;
  padding: 0.65rem 1rem 0.75rem;
  transform: translateY(3px);
  transition: transform 0.14s, color 0.14s;
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.nav-tabs .nav-link:hover {
  color: var(--ink);
  transform: translateY(0);
  border-color: var(--line);
}
.nav-tabs .nav-link.active {
  background-color: var(--surface);
  color: var(--ink);
  border-color: var(--line-strong);
  transform: translateY(0);
  box-shadow: 0 -3px 0 var(--teal) inset;
}

/* Group homepage's own tab bars (#groupTabs — Overview/Protocols/Notebook/Inventory/Calendar/
   Members/Configurations — #configSubTabs, its Configurations sub-tabs, and #membersSubTabs, the
   Members tab's own Members/Teams segmented control added for Slice 2 — teams are just another
   sub-tab of this same page, so they follow this page's own established tab convention rather than
   the generic boxed look) — per explicit instruction, restyled to look like Dynamic protocol's
   Structured/Text/Files switcher (.mode-tab-bar/.mode-tab-btn) instead of the boxed .nav-tabs look
   above: flat underline, mono font, teal bottom line only on the active tab, no box border at all.
   Scoped by ID (all already real ids in group_detail.html's own markup) rather than editing that
   template — an ID selector already outranks the plain `.nav-tabs .nav-link` class rule above on
   specificity, so no `!important` is needed.
   #protocolSubnav (partials/protocol_subnav.html — Overview/Versions/Compare/Sharing, shown on
   protocol_shares.html/protocol_compare.html/protocol_versions.html) gets the same treatment per
   explicit follow-up instruction, for visual consistency with the group homepage — originally
   deliberately excluded ("every OTHER page's .nav-tabs keeps the boxed style"), now included by
   request. Scoped to the tab BUTTONS only, per explicit "tabs buttons" wording —
   #groupTabsContent/#configSubTabsContent's own boxed .tab-content panel below is left as-is.
   Per explicit instruction, this is the one tab style to use everywhere in the app going forward —
   any new tab bar added later should be scoped into this same selector, not left on the generic
   boxed .nav-tabs look two rules above. */
#groupTabs .nav-link, #configSubTabs .nav-link, #protocolSubnav .nav-link, #membersSubTabs .nav-link, #protocolsPageTabs .nav-link {
  background: none;
  border: none;
  border-radius: 0;
  padding: 0.4rem 0.9rem;
  font-size: 0.75rem;
  font-family: var(--font-mono);
  color: var(--ink-faint);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transform: none;
  box-shadow: none;
}
#groupTabs .nav-link:hover, #configSubTabs .nav-link:hover, #protocolSubnav .nav-link:hover, #membersSubTabs .nav-link:hover, #protocolsPageTabs .nav-link:hover {
  color: var(--ink);
  transform: none;
}
#groupTabs .nav-link.active, #configSubTabs .nav-link.active, #protocolSubnav .nav-link.active, #membersSubTabs .nav-link.active, #protocolsPageTabs .nav-link.active {
  background: none;
  color: var(--teal-dark);
  border-bottom-color: var(--teal);
  font-weight: 500;
  box-shadow: none;
}

/* Reference: .tab-content — this file previously had no rule for it at all, so the content pane
   under the tabs had no card treatment whatsoever. Added now, matching the reference. */
.tab-content {
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 0 0.5rem 0.5rem 0.5rem;
  padding: 1.6rem 1.75rem 2rem;
  box-shadow: 0 1px 2px rgba(20, 30, 25, 0.06);
}

/* ---------- Cards (reference: .data-card — no padding/margin/shadow on the base rule; those
   come from the p-2/p-3/mb-2 utility classes this component's own markup already adds inline,
   which this file's OLD padding/margin was actually silently overriding — dropped here, fixing
   that along with matching the reference). ---------- */
.data-card {
  background-color: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 0.5rem;
}
.data-card-title {
  font-family: var(--font-display);
  font-size: 1.05rem;
  margin-bottom: 1rem;
  /* BUG FIX: this used to be border-bottom: 1px solid var(--surface-2) — the same color as the
     card's own background, so the underline was invisible everywhere it was used. var(--line)
     is the app's actual visible divider color (used by .subhead-row, cards, etc.). */
  border-bottom: 1px solid var(--line);
  padding-bottom: 0.5rem;
}

/* ---------- Step cards (reference: .step-card — same reasoning on dropped padding/margin/
   shadow: this component's markup already adds p-3/mb-3 inline). Structured variant's
   critical/caution/pause left-border color-coding has no reference equivalent (reference only
   defines a single .has-critical state) — kept as it already was. ---------- */
.step-card {
  background-color: var(--surface-2);
  border: 1px solid var(--line);
  border-left: 4px solid var(--teal);
  border-radius: 0.5rem;
  position: relative;
}
.step-card.step-critical {
  border-left-color: var(--rust);
}
.step-card.step-caution {
  border-left-color: var(--amber);
}
.step-card.step-pause {
  border-left-color: var(--sky);
}
.step-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.8rem;
}
/* Generic variant's step badge (reference: .step-num-badge — flat ink/white chip). */
.step-num-badge {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  background: var(--ink);
  color: #fff;
  border-radius: 0.3rem;
  padding: 0.15rem 0.5rem;
}
.step-top-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin-bottom: 0.6rem;
}
.step-top-right {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.step-top-right .step-timing-input {
  width: 120px;
  text-align: center;
}
/* Structured variant's richer step badge with critical/caution/pause color states — no reference
   equivalent (the reference's single .step-num-badge has no color variants), kept as it already
   was. */
.step-number-badge {
  font-family: var(--font-mono);
  background-color: var(--teal-tint);
  color: var(--teal);
  font-size: 0.85rem;
  font-weight: 600;
  padding: 0.25rem 0.6rem;
  border-radius: 4px;
}
.step-number-badge.critical {
  background-color: var(--rust-tint);
  color: var(--rust);
}
.step-number-badge.caution {
  background-color: var(--amber-tint);
  color: var(--amber);
}
.step-number-badge.pause {
  background-color: var(--sky-tint);
  color: var(--sky);
}

/* ---------- Buttons with no reference equivalent — kept exactly as they already were. ---------- */
.btn-teal {
  background-color: var(--teal);
  color: var(--surface);
  border: 1px solid var(--teal-dark);
}
.btn-teal:hover {
  background-color: var(--teal-dark);
  color: var(--surface);
}
.pill-btn {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  border: 1px solid var(--line-strong);
  background: var(--surface-2);
  color: var(--ink-soft);
  border-radius: 999px;
  padding: 0.25rem 0.6rem;
  transition: all 0.2s ease;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.pill-btn:hover {
  border-color: var(--rust);
  color: var(--rust);
  background: var(--rust-tint);
}

/* ---------- Badges & chips (reference: .badge-soft + .badge-status/.badge-domain/
   .badge-critical/.badge-caution — the explicit hex border colors below are exact, from the
   reference, not approximated via var(--line-strong) like this file's previous version). ---------- */
.badge-soft {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 500;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.badge-status {
  background-color: var(--teal-tint);
  color: var(--teal-dark);
  border: 1px solid #BFDDD8;
}
.badge-domain {
  background-color: var(--sky-tint);
  color: var(--sky);
  border: 1px solid #CFE0E2;
}
.badge-critical {
  background-color: var(--rust-tint);
  color: var(--rust);
  border: 1px solid #EAC5BC;
}
.badge-caution {
  background-color: var(--amber-tint);
  color: var(--amber);
  border: 1px solid #EAD3A4;
}
.mono-chip {
  background-color: var(--surface);
  border: 1px solid var(--line);
  color: var(--ink-soft);
  font-size: 0.68rem;
  padding: 0.15rem 0.5rem;
  border-radius: 0.3rem;
}
.mono-chip b {
  color: var(--ink);
  font-weight: 500;
}

/* ---------- Callouts — no reference equivalent (the reference's own note-callout styling is
   for a different component shape than this one), kept exactly as they already were. ---------- */
.note-callout {
  background-color: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 0.35rem;
  padding: 0.8rem 1rem;
  margin-top: 0.8rem;
}
.note-callout.critical {
  background-color: var(--rust-tint);
  border-color: rgba(166, 64, 46, 0.2);
}
.note-callout.caution {
  background-color: var(--amber-tint);
  border-color: rgba(173, 122, 30, 0.2);
}
.note-callout.pause {
  background-color: var(--sky-tint);
  border-color: rgba(51, 99, 109, 0.2);
}
.note-callout.troubleshooting {
  background-color: var(--teal-tint);
  border-color: rgba(14, 110, 99, 0.2);
}

.notes-toggle-btn {
  background: none;
  border: none;
  padding: 0.3rem 0;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--ink-soft);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.notes-toggle-btn:hover {
  color: var(--ink);
}
.notes-collapse-body {
  display: none;
}
.notes-collapse-body.show {
  display: block;
}

.segmented-control {
  display: flex;
  background-color: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 3px;
  width: fit-content;
}
.segmented-btn {
  border: none;
  background: none;
  font-family: var(--font-body);
  font-size: 0.9rem;
  padding: 0.4rem 1rem;
  border-radius: 4px;
  color: var(--ink-soft);
  transition: all 0.2s ease;
}
.segmented-btn.active {
  background-color: var(--teal);
  color: var(--surface);
  font-weight: 500;
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

.repeater-card {
  border: 1px dashed var(--line-strong);
  background-color: var(--surface-2);
  border-radius: 0.5rem;
  padding: 1rem;
  margin-bottom: 1rem;
  position: relative;
}
.repeater-card:hover {
  background-color: var(--surface);
  border-style: solid;
}

.equation-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  background: var(--surface-2);
  padding: 0.5rem;
  border-radius: 4px;
  margin-bottom: 0.5rem;
  font-family: var(--font-mono);
}

/* Reference targets plain .table (thead th font/letter-spacing/color + a uniform border-bottom
   color on every cell); this component uses its own .table-premium class instead, so those
   values are applied there. Cell padding/vertical-align/background aren't in the reference at
   all (kept as they already were — reference is silent, not contradicting). */
.table-premium {
  background-color: var(--surface);
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
}
.table-premium th {
  background-color: var(--surface-2);
  color: var(--ink-faint);
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border-bottom: 2px solid var(--ink);
  padding: 0.75rem 1rem;
}
.table-premium td {
  border-bottom: 1px solid var(--line);
  padding: 0.75rem 1rem;
  vertical-align: middle;
}
.table-premium tr:last-child td {
  border-bottom: none;
}

/* Bootstrap accordion overrides — no reference equivalent (reference doesn't use accordions at
   all), kept exactly as they already were. */
.accordion-item {
  border-color: var(--line);
}
.accordion-button {
  font-size: 0.82rem;
  font-family: var(--font-body);
  font-weight: 500;
  padding: 0.55rem 1rem;
  background-color: var(--surface-2);
  color: var(--ink);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.2rem;
}
.accordion-title-text {
  margin-right: 0.2rem;
}
.accordion-title-badges {
  margin-left: auto;
  display: flex;
  gap: 0.4rem;
  margin-right: 0.5rem;
}
.accordion-button:not(.collapsed) {
  background-color: var(--teal-tint);
  color: var(--teal-dark);
  box-shadow: none;
}
.accordion-button:focus {
  box-shadow: none;
  border-color: var(--line);
}
.accordion-button::after {
  width: 1rem;
  height: 1rem;
  background-size: 1rem;
}
.accordion-body {
  font-size: 0.85rem;
}

/* Reference: .subhead-row (structured file's version — the ::after divider line, sky color,
   .08em letter-spacing; the simple file's own subhead-row differs slightly but this file already
   matched structured's version, so no change was needed here). */
.subhead-row {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sky);
  margin: 1.2rem 0 0.6rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.subhead-row::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

/* Reference: .mode-tab-bar/.mode-tab-btn — already matched exactly; only margin-bottom added
   for fidelity (reference has it, this file didn't). */
.mode-tab-bar {
  display: flex;
  gap: 4px;
  margin-bottom: 0.9rem;
  border-bottom: 1px solid var(--line);
}
.mode-tab-btn {
  background: none;
  border: none;
  padding: 0.4rem 0.9rem;
  font-size: 0.75rem;
  font-family: var(--font-mono);
  color: var(--ink-faint);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.mode-tab-btn.active {
  color: var(--teal-dark);
  border-bottom-color: var(--teal);
  font-weight: 500;
}
.mode-tab-btn:hover {
  color: var(--ink);
}

/* No reference equivalent (KaTeX math preview is a structured-variant-only feature not present
   in either reference file) — kept exactly as it already was. */
.math-editor-preview {
  min-height: 80px;
  border: 1px solid var(--line);
  background-color: var(--surface-2);
  border-radius: 4px;
  padding: 0.75rem;
  margin-top: 0.5rem;
}

/* ---------- Generic-variant single-scroll layout (reference: protocol_ui_simple.html) ---------- */
.tab-pane { display: none; }
.tab-pane.active { display: block; }

.field-section {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  padding: 1.1rem 1.3rem;
  margin-bottom: 1.1rem;
}
.field-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.3rem;
  flex-wrap: wrap;
}

/* Dynamic variant only — the new-section draft form itself (renderNewSectionForm()), on top of
   .data-card's own background/radius — a distinct green border per explicit instruction, so an
   in-progress, not-yet-added draft is visually unmistakable from the already-committed section
   boxes below it (which stay plain .data-card/.step-card/.field-section). */
.dyn-new-section-card {
  border: 2px solid var(--green) !important;
  background-color: var(--green-tint);
}

/* Dynamic variant only — the file-remove × (Files tab, both the draft and already-inserted item
   cards) keeps .pill-btn's colors/hover but square instead of pill-shaped, per explicit
   instruction, to read as distinct from every other ×/remove control on this page. */
.pill-btn-square {
  border-radius: 0.3rem;
  width: 1.6rem;
  height: 1.6rem;
  padding: 0;
  font-size: 1rem;
  line-height: 1;
  align-items: center;
  justify-content: center;
}

/* Dynamic variant only — dynamic_new_section_form_changes.md §4/§10: the Files tab's drop zone.
   Explicitly called out as needing its own styling (everything else in that document reuses
   existing classes) — dashed border + hover/dragover state, same radius/surface tokens as every
   other bordered box on this page so it still reads as part of the same visual system. */
.dyn-dropzone {
  border: 2px dashed var(--line);
  border-radius: 0.6rem;
  background: var(--surface-2);
  padding: 1.25rem;
  text-align: center;
  margin-bottom: 0.75rem;
}
.dyn-dropzone.dyn-dropzone-active {
  border-color: var(--teal);
  background: var(--green-tint);
}

/* Dynamic variant only — a sub-type heading inside a .field-section (e.g. "Material" under the
   "Requirements & Observables" box), one notch smaller/quieter than .field-head's own h2, so the
   type/sub-type hierarchy reads clearly without a second identically-weighted heading. */
.dyn-subheading {
  font-family: var(--font-display);
  font-size: 0.88rem;
  color: var(--ink-soft);
  margin: 1rem 0 0.6rem;
  padding-bottom: 0.3rem;
  border-bottom: 1px dashed var(--line);
}
.field-head h2 {
  font-size: 1.02rem;
  font-family: var(--font-display);
  margin: 0;
}
.field-hint {
  font-size: 0.73rem;
  color: var(--ink-faint);
  font-style: italic;
  margin-bottom: 0.7rem;
}
.section-controls {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* Not in either reference file — kept exactly as it already was. */
.empty-note {
  font-size: 0.75rem;
  color: var(--ink-faint);
  font-style: italic;
}

.protocol-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.1rem;
}
.add-section-wrap {
  position: relative;
}
.add-section-dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 0.5rem;
  box-shadow: 0 8px 24px rgba(20,30,25,.14);
  min-width: 230px;
  z-index: 30;
  padding: 0.4rem;
}
.add-section-option {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 0.5rem 0.7rem;
  font-size: 0.82rem;
  border-radius: 0.35rem;
  color: var(--ink);
}
.add-section-option:hover {
  background: var(--surface-2);
}
.add-section-empty {
  font-size: 0.78rem;
  color: var(--ink-faint);
  font-style: italic;
  padding: 0.5rem 0.7rem;
}

.protocol-layout {
  display: grid;
  grid-template-columns: 190px 1fr;
  gap: 2rem;
  align-items: start;
}
.protocol-sidenav {
  position: sticky;
  top: 1rem;
  border-left: 2px solid var(--line);
  padding-left: 0.9rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.protocol-sidenav a {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-faint);
  text-decoration: none;
  border-left: 2px solid transparent;
  margin-left: -0.92rem;
  padding-left: 0.86rem;
  transition: color 0.12s, border-color 0.12s;
  line-height: 1.3;
}
.protocol-sidenav a:hover { color: var(--ink); }
.protocol-sidenav a.side-active { color: var(--teal-dark); border-left-color: var(--teal); font-weight: 500; }
@media (max-width: 720px) {
  .protocol-layout { grid-template-columns: 1fr; }
  .protocol-sidenav { position: static; flex-direction: row; flex-wrap: wrap; border-left: none; padding-left: 0; gap: 0.9rem; }
  .protocol-sidenav a { border-left: none; margin-left: 0; padding-left: 0; border-bottom: 2px solid transparent; }
  .protocol-sidenav a.side-active { border-left: none; border-bottom-color: var(--teal); }
}

/* Reference: .edit-toggle-btn — already matched exactly, no change. */
.edit-toggle-btn {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  border: 1px solid var(--line-strong);
  background: var(--surface-2);
  color: var(--ink-soft);
  border-radius: 999px;
  padding: 0.35rem 0.85rem;
}
.edit-toggle-btn.active { background: var(--teal); color: #fff; border-color: var(--teal); }

/* Reference: .field-locked — already matched exactly, no change. */
.field-locked { background: #ECEEE9 !important; color: var(--ink-faint); cursor: not-allowed; }

/* =====================================================================================
   RUN VIEW — design_changes_dynamic_protocol.md. New, additive block; nothing above this
   line is touched or overridden. Everything here is scoped under .rv-root (Run view's own
   container, #dynamic-run-view in dynamic_v2.html) or .rv-viewmode-*/.rv-inv-popover-* (the
   View Mode dropdown + Inventory popover, which sit just outside .rv-root since they're
   reachable from/anchor to the toolbar and float above the page). Full view, the "+ New"
   section form, and every other existing class are unaffected — this is a new display
   surface, not a restyle. STEPS_SPEC.md (the doc's own companion reference for the
   "labflow-ds" row/numbering/CSS conventions this extends) was not present in the repo when
   this was built, so the .rv-row/.rv-num numbered-row pattern below is a new, from-scratch
   component — built to the same tokens/spirit (--ink/--teal/--rust/--amber/--line, existing
   badge-soft/note-callout treatment) rather than a literal reuse of STEPS_SPEC.md's own
   classes. Flagged back rather than presented as a drop-in match.
   ===================================================================================== */

/* ---------- §1 — View Mode dropdown (chevron lives inside #mode-btn-view itself). Box/position/
   hover styling is deliberately NOT redeclared here — .rv-viewmode-wrap/.rv-viewmode-dropdown/
   .rv-viewmode-option are applied ALONGSIDE .add-section-wrap/.add-section-dropdown/
   .add-section-option (dynamic_v2.html) and inherit that existing dropdown's look wholesale, per
   explicit instruction ("use same css styles unless a different style specified in spec" — this
   spec doesn't ask for a different one). Only what that existing component has no concept of at
   all — the checkmark on the active option, and the chevron flip — is added below. ---------- */
.rv-viewmode-chevron {
  display: inline-block;
  margin-left: 0.4rem;
  transition: transform 0.15s ease;
}
.rv-viewmode-chevron.rv-open {
  transform: rotate(180deg);
}
.rv-viewmode-option.active {
  color: var(--teal-dark);
  font-weight: 500;
}
.rv-viewmode-check {
  visibility: hidden;
  font-size: 0.8rem;
}
.rv-viewmode-option.active .rv-viewmode-check {
  visibility: visible;
}

/* ---------- §3 — Font: JetBrains Mono (cdnjs) across all of Run view, fallback stack ---------- */
.rv-root {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  --rv-navy: #1F3A5F;
  --rv-navy-dark: #142942;
}

/* ---------- Section shell — one per Materials & Reagents / Equipment / Safety Notes /
   Procedure / Observations, in that fixed order (§2). ---------- */
.rv-section {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  padding: 1.1rem 1.3rem;
  margin-bottom: 1.1rem;
}
.rv-section-title {
  font-family: inherit;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sky);
  margin: 0 0 0.8rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--line);
}
.rv-empty {
  font-size: 0.8rem;
  color: var(--ink-faint);
  font-style: italic;
  margin: 0;
}

/* ---------- Numbered row pattern — every item in every Run view section is one of these.
   .rv-num is the same "flat chip to the left of the row" idea STEPS_SPEC.md's own .sn is
   described as using for Steps; recreated here from scratch (see file-header note above). ---------- */
.rv-row {
  display: flex;
  gap: 0.75rem;
  padding: 0.65rem 0;
  border-bottom: 1px solid var(--line);
}
.rv-row:last-child {
  border-bottom: none;
}
.rv-num {
  flex: 0 0 auto;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--ink-faint);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 0.3rem;
  min-width: 1.6rem;
  height: 1.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
}
.rv-row-body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.rv-line {
  font-size: 0.85rem;
  color: var(--ink);
}
.rv-name {
  font-weight: 600;
}
.rv-muted {
  color: var(--ink-faint);
  font-style: italic;
}
.rv-line-badges {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}
/* Labelled Qty/Conc/Duration badges (§4/§7) — reuses .badge-soft's own base rule, this just
   adds the mono-on-mono treatment specific to Run view's badges. */
.rv-badge {
  font-family: inherit;
  font-size: 0.68rem;
  font-weight: 500;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--line-strong);
  color: var(--ink-soft);
}

/* ---------- Plain rows (§5 — Safety Notes: text only, no badges) ---------- */
.rv-row-plain .rv-plain-text {
  margin: 0;
  font-size: 0.85rem;
  color: var(--ink);
}

/* ---------- §6 — Inventory link + popover ---------- */
.rv-inventory-link {
  color: var(--teal-dark);
  text-decoration: underline dotted;
  cursor: pointer;
}
.rv-inventory-link:hover {
  color: var(--teal);
}
.rv-inv-popover {
  position: fixed;
  z-index: 1060;
  min-width: 260px;
  max-width: 320px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 0.5rem;
  box-shadow: 0 10px 30px rgba(20, 30, 25, .2);
  padding: 0.75rem 0.9rem;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
}
.rv-inv-popover-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.5rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--line);
  font-size: 0.88rem;
}
.rv-inv-popover-close {
  background: none;
  border: none;
  font-size: 1rem;
  line-height: 1;
  color: var(--ink-faint);
  padding: 0 0.2rem;
}
.rv-inv-popover-body {
  font-size: 0.8rem;
  color: var(--ink-soft);
}
.rv-inv-label {
  color: var(--ink-faint);
  margin-right: 0.3rem;
}

/* ---------- §7 — Procedure step rows ---------- */
.rv-step-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--sky);
}
.rv-step-instruction {
  font-size: 0.88rem;
}
.rv-step-badges {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
/* §7b — tap/click-to-reveal note indicator: badge-soft/badge-critical/badge-caution already set
   this <button>'s border/background/color; only the button-chrome bits those classes don't touch
   need resetting here (browser default border is already overruled by badge-critical/caution's
   own `border` declaration, so this deliberately does NOT redeclare border). No title attribute
   anywhere, so it works identically on touch and pointer. Reuses .notes-collapse-body's own
   show/hide mechanism. */
.rv-note-toggle {
  cursor: pointer;
  font-family: inherit;
}
.rv-note-reveal.notes-collapse-body {
  margin-top: 0.3rem;
}

/* ---------- §8 — Observations section ---------- */
.rv-obs-run {
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  padding: 0.8rem 1rem;
  margin-bottom: 0.9rem;
  background: var(--surface-2);
}
.rv-obs-run-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.5rem;
}
.rv-obs-step-row {
  border-top: 1px solid var(--line);
  padding-top: 0.6rem;
  margin-top: 0.6rem;
}
.rv-obs-step-row:first-of-type {
  border-top: none;
  padding-top: 0;
  margin-top: 0;
}
.rv-obs-identity {
  font-size: 0.8rem;
  color: var(--ink-soft);
  margin-bottom: 0.4rem;
}
.rv-obs-history {
  font-size: 0.78rem;
  color: var(--ink-faint);
  margin-bottom: 0.4rem;
}
/* §8 — "Save observation", filled navy, distinct from the app's teal primary accent so it reads
   as its own action (the doc calls this out by name, `.btn-tl`, but the class didn't exist
   anywhere in the codebase yet — introduced here, scoped to .rv-root only). */
.rv-root .btn-tl {
  background-color: var(--rv-navy);
  color: #fff;
  border: 1px solid var(--rv-navy-dark);
  font-family: inherit;
  font-size: 0.8rem;
}
.rv-root .btn-tl:hover {
  background-color: var(--rv-navy-dark);
  color: #fff;
}
.rv-run-status-pill {
  font-size: 0.68rem;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink-soft);
}
.rv-run-status-pill.completed {
  background: var(--teal-tint);
  color: var(--teal-dark);
  border-color: #BFDDD8;
}

/* Dynamic protocol format (Full view) only — per explicit "grey/washed-out text is hard to read"
   instruction: every existing rule in this file that reads var(--ink-faint)/var(--ink-soft), plus
   Bootstrap's own .text-muted (via --bs-secondary-color, never redirected above), picks these up
   automatically since custom properties cascade. Scoped to .dyn-protocol-page (set on dynamic_v2.
   html's root wrapper) so generic_v2.html/structured_v2.html, which load this same stylesheet,
   keep their existing colors — this is not a global contrast change. */
.dyn-protocol-page {
  --ink-faint: var(--ink);
  --ink-soft: var(--ink);
  --bs-secondary-color: var(--ink);
}

/* feat/md_editor branch — Dynamic protocol's Text tab, WYSIWYG editor (dyn_text_editor.js).
   Every rule below reuses an existing token/pattern from elsewhere in this same file rather than
   inventing new ones: toolbar buttons are .pill-btn (Deviations/Setup-notes "+ Add" precedent),
   the active-mark highlight copies .mode-tab-btn.active's teal treatment (no active variant of
   .pill-btn existed yet), tables reuse .table-premium, blockquote reuses .note-callout, code
   reuses the file's own existing `code, .mono, .font-monospace, pre` font-mono rule. Headings
   inside .dyn-text-editor-body already pick up the top-of-file blanket h1-h6 rule (font-display/
   ink/letter-spacing) — nothing new needed there either.

   .dyn-text-editor-body is used for BOTH the live ProseMirror-mounted editor AND the read-only
   fallback view (raw text shown if the editor fails to load) — same stylesheet, so the two can
   never visually drift apart, per explicit instruction. */
.dyn-text-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  padding-bottom: 0.6rem;
  margin-bottom: 0.8rem;
  border-bottom: 1px solid var(--line);
}
/* Active-mark state (bold/italic/etc. currently on at the caret) — no existing .pill-btn active
   variant to reuse verbatim, so this borrows .mode-tab-btn.active's exact teal treatment instead
   of inventing a new color. */
.dyn-text-toolbar .pill-btn.active {
  background: var(--teal-tint);
  border-color: var(--teal);
  color: var(--teal-dark);
}
/* Disabled state (Table-insert when a table can't be inserted, Undo/Redo when there's nothing to
   undo/redo) — no existing .pill-btn disabled variant either; derived from the same washed-out
   treatment Bootstrap's own disabled buttons already use elsewhere in this app (reduced opacity,
   default cursor), just applied to .pill-btn's own colors instead of inventing a new palette. */
.dyn-text-toolbar .pill-btn:disabled,
.dyn-text-toolbar .pill-btn.disabled {
  opacity: 0.45;
  cursor: default;
  pointer-events: none;
}
/* No existing "vertical divider inside a horizontal toolbar" component anywhere in this app to
   copy verbatim — derived from the nearest existing pattern instead: a plain 1px line in the same
   --line token every other border/divider in this stylesheet already uses (.mode-tab-bar's own
   border-bottom, .note-callout's border, etc.), sized to the toolbar's own button height. Flagged
   as the one genuinely new (if minimal) piece this toolbar needed. */
.dyn-text-toolbar-divider {
  width: 1px;
  align-self: stretch;
  background-color: var(--line);
  margin: 0.15rem 0.1rem;
}
/* Block-type dropdown menu items preview their own styling (heading sizes, monospace for Code
   block) — Bootstrap's own .dropdown-item, just wrapping a real h1/h2/h3 (picking up
   .dyn-text-editor-body's own heading rules below) or <code> instead of plain text. */
.dyn-text-toolbar .dropdown-item .dyn-text-editor-body h1,
.dyn-text-toolbar .dropdown-item .dyn-text-editor-body h2,
.dyn-text-toolbar .dropdown-item .dyn-text-editor-body h3 {
  margin: 0;
}
.dyn-text-save-indicator {
  font-family: var(--font-body);
  font-size: 0.8rem; /* same as Bootstrap's own .small, the "Edited: ..." timestamp convention every Dynamic item card already uses for muted secondary text */
  color: var(--ink-faint);
  margin-left: auto;
  white-space: nowrap;
}
.dyn-text-save-indicator.is-unsaved {
  color: var(--amber);
}
.dyn-text-save-indicator.is-error {
  color: var(--rust);
}
.dyn-text-save-indicator .btn-link {
  font-size: inherit;
  text-decoration: underline;
}

/* Editor card wrapper (#dynamic-text-view itself, holding both the toolbar and the editor body)
   — per explicit instruction: wider, with a real border and margin around it instead of sitting
   flush against the rest of the page. Same card treatment .data-card already uses elsewhere
   (surface-2 background, --line border, existing radius scale), not a new visual language. */
#dynamic-text-view {
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  background-color: var(--surface-2);
  padding: 1.25rem 1.5rem;
  margin: 0.5rem 0 1rem;
}
/* Toolbar buttons: square, not the pill/oval .pill-btn shape used elsewhere — per explicit
   instruction. Reuses .pill-btn-square's own existing radius value (0.3rem, already in this
   stylesheet for the file-remove × button) rather than inventing a new one; unlike
   .pill-btn-square this doesn't force a fixed icon-sized width/height, since these buttons carry
   varying text labels, not a single glyph. */
.dyn-text-toolbar .pill-btn {
  border-radius: 0.3rem;
}
.dyn-text-editor-body {
  font-family: var(--font-body);
  font-size: 0.92rem;
  line-height: 1.65;
  color: var(--ink);
  max-width: 68rem; /* widened per explicit instruction — was 46rem */
  /* Its own padding, separate from #dynamic-text-view's outer padding around toolbar+body
     together — per explicit instruction, so the actual text content always has breathing room
     from whichever border it's shown inside (the editor's own #dynamic-text-view card, or the
     Import review Text tab's .data-card preview, which both use this same class). */
  padding: 0.5rem 0.25rem;
}
/* BUG FIX: .dyn-text-editor-body is TipTap's own `element` option — a plain wrapper div; TipTap/
   ProseMirror mounts its REAL contenteditable surface as a CHILD .ProseMirror div inside it. The
   wrapper itself is never actually focused, so a rule scoped to .dyn-text-editor-body:focus never
   applied at all — the browser's own default focus outline was showing around .ProseMirror
   directly instead, flush against its edge with none of the padding above (only the WRAPPER had
   padding, not the element that actually receives focus while editing). Both the outline removal
   and the padding now target .ProseMirror itself too, not just its wrapper. */
.dyn-text-editor-body .ProseMirror {
  padding: 0.5rem 0.25rem;
}
.dyn-text-editor-body .ProseMirror:focus {
  outline: none; /* ProseMirror's own gapcursor/selection styling already shows focus state */
}
.dyn-text-editor-body h1, .dyn-text-editor-body h2, .dyn-text-editor-body h3 {
  margin-top: 1.4rem;
  margin-bottom: 0.6rem;
}
.dyn-text-editor-body p {
  margin-bottom: 0.9rem;
}
.dyn-text-editor-body ul, .dyn-text-editor-body ol {
  margin-bottom: 0.9rem;
  padding-left: 1.4rem;
}
.dyn-text-editor-body blockquote {
  background-color: var(--surface-2);
  border: 1px solid var(--line);
  border-left: 3px solid var(--teal);
  border-radius: 0.35rem;
  padding: 0.8rem 1rem;
  margin: 0 0 0.9rem;
  color: var(--ink-soft);
}
.dyn-text-editor-body pre {
  background-color: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 0.35rem;
  padding: 0.8rem 1rem;
  margin-bottom: 0.9rem;
  overflow-x: auto;
}
.dyn-text-editor-body pre code {
  background: none;
  border: none;
  padding: 0;
}
.dyn-text-editor-body code {
  background-color: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 0.25rem;
  padding: 0.05rem 0.3rem;
}
.dyn-text-editor-body a {
  color: var(--bs-link-color);
}
.dyn-text-editor-body table {
  background-color: var(--surface);
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
  margin-bottom: 0.9rem;
}
.dyn-text-editor-body th {
  background-color: var(--surface-2);
  color: var(--ink-faint);
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border-bottom: 2px solid var(--ink);
  padding: 0.6rem 0.8rem;
  text-align: left;
}
.dyn-text-editor-body td {
  border-bottom: 1px solid var(--line);
  padding: 0.6rem 0.8rem;
  vertical-align: top;
}
.dyn-text-editor-body tr:last-child td {
  border-bottom: none;
}
/* ProseMirror's own gap-cursor caret (placed before/after a table) — thin teal bar, matches the
   app's one accent color rather than ProseMirror's own default black. */
.dyn-text-editor-body .ProseMirror-gapcursor:after {
  border-top-color: var(--teal);
}
/* Task list (TipTap's TaskList/TaskItem) — no bullet marker (the checkbox itself is the marker),
   same spacing/measure as every other list in .dyn-text-editor-body above. */
.dyn-text-editor-body ul[data-type="taskList"] {
  list-style: none;
  padding-left: 0.2rem;
}
.dyn-text-editor-body ul[data-type="taskList"] li {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
}
.dyn-text-editor-body ul[data-type="taskList"] li > label {
  margin-top: 0.2rem;
}
.dyn-text-editor-body ul[data-type="taskList"] li > div {
  flex: 1;
}

/* =====================================================================================
   DASHBOARD REDESIGN (base_app.html header/footer, dashboard.html, protocols_list.html) —
   md_and_others/dashboard-redesign-audit.md / mockup-vs-backend-crossref.md. Converted from the
   approved static mockup (labflow-home-option-b.html) — every color is one of this file's own
   existing tokens (the mockup's own --hdr-bg/--hdr-fg/etc. were literally --teal-tint/--teal-dark
   restated under new names; not reintroduced here, used directly instead). Built with Bootstrap's
   own dropdown component (already loaded app-wide) for the bell/account/create menus, not the
   mockup's custom popover JS — and server-side Jinja + GET query params for the protocols table's
   filters, matching group_detail.html's own established Protocols-tab convention, not the
   mockup's client-side table filtering.
   ===================================================================================== */

/* Fixes a real bug: base_app.html's existing footer markup has used class="text-teal" for a
   while with no matching rule anywhere in this file — it was rendering as plain inherited ink
   color, not teal. */
.text-teal { color: var(--teal); }

/* ---------- Header ---------- */
.hdr-lf {
  position: sticky; top: 0; z-index: 1030;
  background: var(--teal-tint); color: var(--teal-dark);
  border-bottom: 1px solid #C3DBD6;
}
.hdr-lf .container { display: flex; align-items: center; gap: 18px; height: 60px; }
.hdr-lf .navbar-brand { color: var(--teal-dark); display: flex; align-items: center; gap: 8px; }
.hdr-nav { display: flex; gap: 2px; margin-left: 8px; flex-wrap: wrap; }
.hdr-nav a {
  padding: 7px 12px; border-radius: 6px; font-weight: 500; font-size: 0.9rem;
  color: var(--sky); display: flex; gap: 6px; align-items: center; text-decoration: none;
}
.hdr-nav a:hover { background: #CDE3DF; color: var(--teal-dark); }
.hdr-nav a.active { background: var(--surface); color: var(--teal-dark); box-shadow: 0 0 0 1px #C3DBD6; }
.hdr-nav a.disabled { opacity: .6; pointer-events: none; }
.hdr-nav .soon-tag {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em; text-transform: uppercase;
  border: 1px solid #C3DBD6; border-radius: 999px; padding: 0 6px; line-height: 16px;
}
.hdr-nav .count-badge {
  font-family: var(--font-mono); font-size: 11px; background: var(--amber); color: #1B1305;
  border-radius: 999px; padding: 0 7px; line-height: 17px;
}
.hdr-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.hdr-icon-btn {
  position: relative; width: 38px; height: 38px; border-radius: 7px; border: none; background: none;
  display: grid; place-items: center; color: var(--sky); font-size: 1.1rem;
}
.hdr-icon-btn:hover { background: #CDE3DF; color: var(--teal-dark); }
.hdr-badge-dot {
  position: absolute; top: 4px; right: 4px; min-width: 17px; height: 17px; border-radius: 999px;
  background: var(--rust); color: #fff; font-family: var(--font-mono); font-size: 10.5px;
  line-height: 17px; text-align: center; padding: 0 4px; border: 2px solid var(--teal-tint);
}
.hdr-acct-btn {
  display: flex; align-items: center; gap: 8px; padding: 3px 10px 3px 3px; border-radius: 999px;
  border: none; background: none; color: var(--teal-dark);
}
.hdr-acct-btn:hover { background: #CDE3DF; }
.hdr-avatar {
  width: 30px; height: 30px; border-radius: 50%; background: var(--teal); color: #fff;
  display: grid; place-items: center; font-family: var(--font-display); font-weight: 700; font-size: 12px;
}
/* PrecisOmics logo — app/static/img/precisomics-logo.png (assests/images/"transparent logo file
   (1).png") is a white-silhouette-on-transparent cutout, by design meant to be recolored, not
   shown as-is (plain <img> rendered invisible on this app's light backgrounds — confirmed: every
   visible pixel is RGB 255,255,255 with only the alpha channel carrying the shape). Same CSS-mask
   technique the approved mockup itself used (-webkit-mask + background:currentColor) rather than
   a plain <img>, using the real asset file instead of the mockup's own embedded base64 copy. */
.po-logo {
  display: inline-block;
  aspect-ratio: 2120 / 1174;
  background-color: currentColor;
  -webkit-mask-image: url('../img/precisomics-logo.png');
  mask-image: url('../img/precisomics-logo.png');
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-position: center;
  mask-position: center;
}
.hdr-po-logo { height: 24px; width: auto; margin-left: 4px; color: var(--teal-dark); }
.hdr-vsep { width: 1px; height: 28px; background: #C3DBD6; margin: 0 4px; }

/* ---------- Footer ---------- */
.ftr-lf { border-top: 1px solid var(--line); background: var(--surface); padding: 28px 0 18px; }
.ftr-lf-row {
  display: flex; flex-wrap: wrap; gap: 24px 40px; align-items: center; justify-content: space-between;
}
.ftr-links { display: flex; flex-wrap: wrap; gap: 8px 22px; font-size: 13.5px; }
.ftr-links a { color: var(--ink-soft); text-decoration: none; }
.ftr-links a:hover { color: var(--teal); }
.ftr-po {
  display: flex; align-items: center; gap: 10px; color: var(--ink-faint); font-family: var(--font-mono);
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
}
.ftr-po-logo { height: 26px; width: auto; color: var(--teal); }
.ftr-bot {
  margin-top: 22px; padding-top: 14px; border-top: 1px solid var(--line); display: flex;
  flex-wrap: wrap; gap: 8px 20px; justify-content: space-between; font-size: 12.5px; color: var(--ink-faint);
}

/* ---------- Dashboard page ---------- */
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.dash-top { display: flex; flex-wrap: wrap; gap: 16px; justify-content: space-between; align-items: flex-end; }
.dash-eyebrow { font-family: var(--font-mono); font-size: 12px; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); }

.card-hd h2 { font-size: 1.08rem; font-weight: 600; }
.card-ft { padding: 12px 18px; border-top: 1px solid var(--line); display: flex; justify-content: space-between; gap: 10px; flex-wrap: wrap; font-size: 13px; color: var(--ink-faint); }
.tbl-wrap { overflow-x: auto; }

.tabs { display: flex; gap: 20px; padding: 0 18px; border-bottom: 1px solid var(--line); overflow-x: auto; }
.tabs button { font-family: var(--font-mono); font-size: 12.5px; color: var(--ink-faint); padding: 10px 0; border: none; background: none; border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; display: flex; gap: 6px; align-items: center; }
.tabs button.active, .tabs button[aria-selected="true"] { color: var(--teal-dark); border-bottom-color: var(--teal); }
.tabs button:disabled { opacity: .55; cursor: default; }
.tabs .n { font-size: 11px; background: var(--surface-2); border: 1px solid var(--line); border-radius: 4px; padding: 0 6px; line-height: 16px; color: var(--ink-soft); }
.tabs .soon { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; border: 1px dashed var(--line-strong); border-radius: 999px; padding: 0 6px; line-height: 16px; }

.search { background: var(--surface-2); border: 1px solid var(--line); border-radius: 5px; padding: 0 10px; height: 34px; }
.search input { border: 0; background: transparent; outline: 0; }
.gsel select { height: 34px; }

.groups-rail { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; }
.gcard {
  background: var(--surface); border: 1px solid var(--line); border-radius: .55rem; padding: 14px;
  display: flex; flex-direction: column; gap: 10px; min-width: 0; text-decoration: none; color: inherit;
}
.gcard:hover { border-color: var(--teal); }
.gcard-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; }
.gav {
  width: 34px; height: 34px; border-radius: 8px; display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 700; font-size: 12.5px; flex: none;
}
.gav.sm { width: 24px; height: 24px; border-radius: 6px; font-size: 10px; }
.gcard-name { font-weight: 600; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gcard-meta { font-family: var(--font-mono); font-size: 11.5px; color: var(--ink-faint); display: flex; gap: 10px; }
.gcard-new {
  border-style: dashed; align-items: center; justify-content: center; color: var(--ink-soft);
  font-weight: 500; text-align: center; background: transparent;
}
.gcard-new svg, .gcard-new .plus { color: var(--teal); }
@media (max-width: 1100px) { .groups-rail { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 600px) { .groups-rail { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.dash-grid { display: grid; grid-template-columns: minmax(0, 2.15fr) minmax(0, 1fr); gap: 22px; align-items: stretch; }
.dash-grid > .card { display: flex; flex-direction: column; }
@media (max-width: 920px) { .dash-grid { grid-template-columns: minmax(0, 1fr); } }

.notif-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 8px; list-style: none; margin: 0; padding: 6px 0; }
@media (max-width: 760px) { .notif-list { grid-template-columns: minmax(0, 1fr); } }
.nrow {
  display: grid; grid-template-columns: 30px minmax(0, 1fr) auto; gap: 10px; padding: 10px 18px;
  text-decoration: none; color: inherit;
}
.nrow:hover { background: var(--surface-2); }
.nic { width: 30px; height: 30px; border-radius: 7px; display: grid; place-items: center; }
.nic.i-amber { background: var(--amber-tint); color: var(--amber); }
.nic.i-teal { background: var(--teal-tint); color: var(--teal); }
.nic.i-sky { background: var(--sky-tint); color: var(--sky); }
.nic.i-rust { background: var(--rust-tint); color: var(--rust); }
.nt { font-size: 13.5px; line-height: 1.4; color: var(--ink-soft); }
.nrow.unread .nt { color: var(--ink); font-weight: 600; }
.nw { font-size: 12px; color: var(--ink-faint); margin-top: 2px; }
.nw b { font-weight: 500; color: var(--ink-soft); }
.udot { width: 8px; height: 8px; border-radius: 50%; background: var(--teal); margin-top: 6px; }
.nrow:not(.unread) .udot { visibility: hidden; }

.work-toolbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: space-between; padding: 12px 18px; }
.work-seg { display: inline-flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; margin-left: auto; }
.work-seg a {
  font-family: var(--font-mono); font-size: 12px; padding: 6px 10px; color: var(--ink-soft);
  border-left: 1px solid var(--line); text-decoration: none;
}
.work-seg a:first-child { border-left: 0; }
.work-seg a.active { background: var(--teal-tint); color: var(--teal); }
.work-seg .cnt { font-size: 10.5px; background: var(--amber-tint); color: var(--amber); border-radius: 999px; padding: 0 6px; margin-left: 4px; }

.work-table td .pn { font-weight: 600; color: var(--ink); display: block; text-decoration: none; }
.work-table td .pn:hover { color: var(--teal); }
.work-table td .ver {
  font-family: var(--font-mono); font-size: 11.5px; color: var(--ink-soft); background: var(--surface-2);
  border: 1px solid var(--line); border-radius: 4px; padding: 0 5px; line-height: 17px; display: inline-block; margin-top: 4px;
}
.work-table tr.need td { background: color-mix(in srgb, var(--amber-tint) 45%, transparent); }
.work-table tr.need td:first-child { box-shadow: inset 3px 0 0 var(--amber); }
.gchip { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.gchip .gname { font-size: 13px; color: var(--ink-soft); line-height: 1.3; }
.role-l { display: inline-flex; gap: 8px; align-items: flex-start; font-size: 13px; }
.role-l b { font-weight: 500; color: var(--ink); display: block; white-space: nowrap; }
.role-l small { display: block; font-size: 12px; color: var(--ink-faint); }

.week-strip { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; padding: 14px 18px 6px; }
.wd {
  display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 8px 0 7px;
  border-radius: 7px; border: 1px solid transparent;
}
.wd .dn { font-family: var(--font-mono); font-size: 10.5px; text-transform: uppercase; color: var(--ink-faint); }
.wd .dd { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; font-variant-numeric: tabular-nums; }
.wd .dots { display: flex; gap: 3px; height: 6px; justify-content: center; }
.wd .dots i { width: 5px; height: 5px; border-radius: 50%; background: var(--teal); display: inline-block; }
.wd.today .dd { color: var(--teal); }
.agenda-lbl { display: flex; justify-content: space-between; padding: 6px 18px 0; font-size: 12.5px; color: var(--ink-faint); }
.tl { list-style: none; margin: 0; padding: 8px 18px 14px; }
.ev { display: grid; grid-template-columns: 58px 14px minmax(0, 1fr); gap: 10px; padding: 7px 0; align-items: start; }
.ev .tm { font-family: var(--font-mono); font-size: 12px; color: var(--ink-soft); text-align: right; padding-top: 1px; line-height: 1.3; }
.ev .tm small { display: block; font-size: 10.5px; color: var(--ink-faint); }
.ev .rail-dot { position: relative; height: 100%; }
.ev .rail-dot::before { content: ""; position: absolute; left: 6px; top: 14px; bottom: -14px; width: 1.5px; background: var(--line); }
.ev:last-child .rail-dot::before { display: none; }
.ev .rail-dot i { position: absolute; left: 2px; top: 4px; width: 10px; height: 10px; border-radius: 50%; border: 2px solid var(--teal); background: var(--surface); display: block; }
.ev .et { font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.ev .es { font-size: 12.5px; color: var(--ink-faint); }
.ev .es a { color: var(--teal); }
.dash-empty { padding: 20px 18px; color: var(--ink-faint); font-size: 13.5px; text-align: center; }
