/* =============================================================================
   SonoForm stylesheet -- table of contents
   -----------------------------------------------------------------------------
   0.  Font faces                    -- self-hosted Inter variable font
   1.  Design tokens (:root)         -- colors, spacing, radius, type scale
   2.  Reset and base                -- *, body, h1-h3, code, kbd
   3.  Layout                        -- app-shell, topnav, page-heading
   4.  Components                    -- card, btn, form, alert, table, badge
   5.  Feature modules               -- protocol builder, exam form, report,
                                        canvas, keyboard help, dashboard,
                                        auth, landing
   6.  Dark mode                     -- [data-theme="dark"] overrides
   7.  Responsive                    -- @media (max-width: 1024px / 768px)
   8.  Guides / data tables          -- help pages, admin tables
   9.  Classification / canvas       -- classification badges, canvas tools
   10. Dashboard / report            -- chart bars, meta bar, reports page
   11. Utilities                     -- .flex, .hidden, spacing, text helpers
   12. Print                         -- @media print
   Note: `.hidden` is declared last in the utilities block so it wins
   against display-setting utilities via source order (equal specificity).
   ============================================================================= */

/* -- Font faces --
   Inter variable font (weights 400-800), self-hosted from static/fonts/ so no
   request leaves the origin. Latin + latin-ext subsets; the browser downloads
   only the ranges a page actually uses. Falls back to the system stack. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("../fonts/Inter-normal-latin.260c81a4759b.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("../fonts/Inter-normal-latin-ext.1ad231aac0a8.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter';
  font-style: italic;
  font-weight: 400 800;
  font-display: swap;
  src: url("../fonts/Inter-italic-latin.0a81fe197e0d.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: italic;
  font-weight: 400 800;
  font-display: swap;
  src: url("../fonts/Inter-italic-latin-ext.f877664ba06a.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* Font stacks. Inter (self-hosted above) with the system stack as fallback;
     the mono stack prefers the platform's native monospace UI font. */
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: ui-monospace, 'SF Mono', 'Cascadia Mono', 'Consolas', 'Courier New', monospace;

  /* Accent: calm clinical teal. --primary doubles as fill and link/text
     color; --primary-contrast is the text color on primary-filled surfaces
     (white in light mode, deep teal ink on the bright dark-mode accent). */
  --primary: #0f766e;
  --primary-dark: #115e59;
  --primary-contrast: #fff;
  --surface: #f4f7f7;
  --surface-alt: #edf2f2;
  --border: #dde6e5;
  --text: #16282c;
  --text-muted: #5d7275;
  --danger: #dc2626;
  --success: #16a34a;
  --warning: #d97706;
  --surface-warning: #fffbeb;
  --border-warning: #fcd34d;
  --text-warning: #92400e;
  --primary-surface: #e3f3f0;
  --canvas-pen: #e74c3c;
  --radius: 8px;
  --shadow: 0 1px 2px rgba(8,32,35,.05), 0 4px 14px rgba(8,32,35,.06);

  /* Bright accent for primary actions that sit on the always-dark chrome
     (topnav CTA, landing hero/CTA buttons). Same values in both themes;
     matches the dark-mode --primary family. */
  --accent-bright: #2dd4bf;
  --accent-bright-hover: #5eead4;
  --accent-bright-text: #053b34;
  /* Soft teal glow behind the auth card and landing hero. */
  --accent-glow: rgba(45,212,191,.13);

  /* Spacing scale (single source of truth for all gaps/margins/padding) */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;

  /* Named gap aliases reference the spacing scale (kept for existing call sites) */
  --gap-sm: var(--space-2);
  --gap-md: var(--space-5);

  /* Width of a numeric input sitting inline beside its label on the exam form */
  --inline-numeric-width: 130px;

  /* Radius scale (--radius: 8px already defined above) */
  --radius-xs: 4px;
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-pill: 999px;

  /* Font-size scale. Rescaled upward for legibility during long clinical
     reading sessions; --text-base is the true body size and body inherits it. */
  --text-2xs: 10px;
  --text-xs: 12px;
  --text-sm: 13px;
  --text-base: 15px;
  --text-md: 16px;
  --text-lg: 18px;
  --text-xl: 20px;
  --text-2xl: 24px;
  --text-3xl: 30px;
  --text-4xl: 44px;

  /* Font-weight scale */
  --font-weight-normal: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  --font-weight-heavy: 800;

  /* Line-height scale */
  --line-height-none: 1;
  --line-height-tight: 1.2;
  --line-height-snug: 1.35;
  --line-height-normal: 1.5;
  --line-height-relaxed: 1.6;
  --line-height-loose: 1.8;

  /* Transition timing */
  --transition-fast: .15s;
  --transition: .2s;

  /* Semantic palette (light) */
  --danger-surface: #fdf1f0;
  --danger-border: #f6c6c2;
  --danger-text: #9c1f15;
  --danger-dark: #b91c1c;
  --success-surface: #f0fdf4;
  --success-border: #bbf7d0;
  --success-text: #166534;
  --info-surface: #e9f4fb;
  --info-border: #bcdcf0;
  --info-text: #1c5d80;

  /* Badge palette */
  --badge-green-bg: #dcfce7;
  --badge-green-text: #166534;
  --badge-red-bg: #fee2e2;
  --badge-red-text: #991b1b;
  --badge-blue-bg: #dbeafe;
  --badge-blue-text: #1e40af;
  --badge-gray-bg: #e8eeee;
  --badge-gray-text: #3d5157;

  /* Focus rings */
  --focus-ring: rgba(15,118,110,.14);
  --focus-ring-danger: rgba(220,38,38,.12);

  /* Softer elevation for dense, frequently-repeated cards (annotations,
     guideline refs, worksheet/comment cards). Hero/auth cards keep --shadow. */
  --shadow-sm: 0 1px 2px rgba(8,32,35,.05);

  /* Subtle tint on the focused exam-finding row (dark value in dark block). */
  --field-focus-tint: rgba(15,118,110,.05);

  /* Empty structure-completion badge on the dark exam-structure header. */
  --progress-empty-bg: rgba(255,255,255,.18);

  /* Keyboard hint chip shadow (tips bar). */
  --kbd-shadow: rgba(0,0,0,.06);

  /* Outline button on always-dark marketing chrome (landing page). */
  --btn-outline-border: rgba(255,255,255,.4);
  --btn-outline-border-hover: rgba(255,255,255,.7);
  --btn-outline-hover-bg: rgba(255,255,255,.08);

  /* Dashboard stat figure size. */
  --stat-value-size: var(--text-3xl);

  /* Sticky side-column offset: the topnav + page-heading stack. app.js
     keeps the --sticky-*-h inputs synced to the rendered bar heights; the
     fallbacks match the fixed desktop topnav and a one-row heading. Used
     by the draft-preview, report, and builder side columns. */
  --sticky-offset: calc(var(--sticky-topnav-h, 52px) + var(--sticky-heading-h, 54px));

  /* Full sticky stack on the exam form: topnav + page-heading +
     section-nav-bar. Used by every scroll-margin that must keep a
     scroll target clear of the sticky chrome. */
  --sticky-stack-h: calc(var(--sticky-offset) + var(--sticky-navbar-h, 46px));

  /* Overlay chrome (kb help, dark-on-light surfaces that stay dark).
     Deep petrol family: the brand's dark chrome in both themes. */
  --overlay-surface: #10333a;
  --overlay-text: #cfe3e4;
  --overlay-heading: #fff;
  --overlay-muted: #8fb0b3;
  --overlay-subtle: #5d8388;
  --overlay-divider: #1e4a52;

  /* Secondary button surface (stays white in light mode) */
  --btn-secondary-bg: #fff;

  /* Elevated panel surface: pure white in light mode, surface-alt in dark
     (cards, report box, exam structures, auth/landing cards). */
  --surface-raised: #fff;

  /* Text on accent backgrounds (primary/danger/success buttons, active
     chips). Stays white in both themes. */
  --text-on-accent: #fff;

  /* Missing-required-field highlight (dark values set in the dark block). */
  --field-missing-bg: #fff7f7;
  --field-missing-border: #fca5a5;

  /* Light accent text on dark chrome (topnav active link). */
  --primary-light: #5eead4;

  /* Subtle row divider (lighter than --border). */
  --border-subtle: #ebf1f0;

  /* Sky-blue informational chips (finding-type badge, invite box border). */
  --badge-sky-bg: #e0f2fe;
  --badge-sky-text: #0369a1;

  /* Conditional-visibility callout border on the exam form. */
  --conditional-border: #8fd8cd;

  /* Report section heading text (deep teal on the pale teal band). */
  --report-heading-text: #134e4a;

  /* Inset panel inside a card (sub-field edit panel). */
  --panel-inset: #edf2f2;

  /* Dashboard chart bar sizing (data-driven height via --bar-ratio) */
  --chart-bar-max-height: 60px;
  --chart-bar-min-height: 3px;

  /* Product logo gradient (branded accent used on auth card) */
  --logo-gradient: linear-gradient(135deg, #2dd4bf 0%, #38bdf8 100%);

  /* Deep dark backdrops that stay dark in both themes (auth backdrop,
     landing nav/hero/cta, landing footer). Paired with the overlay
     family so the marketing chrome and overlay surfaces share one
     palette source. */
  --overlay-deep: #0a2227;
  --overlay-deepest: #06181c;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  color: var(--text);
  background: var(--surface);
  line-height: var(--line-height-normal);
  -webkit-font-smoothing: antialiased;
}

/* Bare anchors (help links, table links) pick up the accent instead of the
   browser default blue. Components that set their own color are unaffected. */
a { color: var(--primary); }

::selection { background: var(--primary-surface); }

/* -- Layout -- */
.app-shell { display: flex; flex-direction: column; min-height: 100vh; }

.topnav {
  background: var(--overlay-surface);
  color: var(--overlay-text);
  display: flex;
  align-items: center;
  gap: 0;
  height: 52px;
  padding: 0 20px;
  position: sticky;
  top: 0;
  z-index: 100;
  flex-shrink: 0;
}

.topnav-brand {
  white-space: nowrap;
  margin-right: 8px;
  font-size: var(--text-xl);
}

.topnav-tenant {
  font-size: var(--text-sm);
  color: var(--overlay-muted);
  white-space: nowrap;
  padding: 0 12px;
  border-left: 1px solid var(--overlay-divider);
  border-right: 1px solid var(--overlay-divider);
  margin-right: 8px;
  line-height: var(--line-height-none);
  /* The tenant name is the only flexible item on the desktop row: it
     shrinks and ellipsizes when the nav links and account controls need
     the space. min-width 0 lifts the min-content floor of the nowrap
     text so shrinking actually happens. */
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topnav-links {
  display: flex;
  align-items: stretch;
  /* Basis auto (not 0): the links report their real width, so a shortage
     of space shrinks the tenant name instead of letting link text overflow
     into the account controls. */
  flex: 1 0 auto;
  height: 100%;
}
.topnav-links a {
  display: flex;
  align-items: center;
  padding: 0 14px;
  color: var(--overlay-text);
  text-decoration: none;
  font-size: var(--text-base);
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  transition: color .15s, border-color .15s;
}
.topnav-links a:hover { color: var(--overlay-heading); }
.topnav-links a.active {
  color: var(--overlay-heading);
  font-weight: var(--font-weight-semibold);
  border-bottom-width: 3px;
  border-bottom-color: var(--primary-light);
}
/* Primary call-to-action in the nav: the app's main entry action stands out
   as a filled chip rather than a plain link. Bright accent with dark ink so
   it pops on the always-dark chrome in both themes. */
.topnav-links a.topnav-cta {
  background: var(--accent-bright);
  color: var(--accent-bright-text);
  font-weight: var(--font-weight-semibold);
  border-radius: var(--radius);
  border-bottom: none;
  padding: 6px 14px;
  margin: 0 6px;
}
.topnav-links a.topnav-cta:hover { background: var(--accent-bright-hover); color: var(--accent-bright-text); }

.topnav-right {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
  font-size: var(--text-base);
  /* Never squeeze the account controls; the tenant name yields instead. */
  flex-shrink: 0;
}

.topnav-username {
  color: var(--overlay-muted);
  padding: 0 8px;
}

.topnav-action {
  color: var(--overlay-muted);
  text-decoration: none;
  padding: 4px 8px;
  border-radius: var(--radius);
  transition: color .15s, background .15s;
}
.topnav-action:hover { color: var(--overlay-heading); background: var(--overlay-divider); }

/* Hamburger menu button (hidden on desktop, shown on mobile) */
.topnav-hamburger {
  display: none;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--overlay-text);
  padding: 4px 8px;
  font-size: var(--text-xl);
  line-height: var(--line-height-none);
}
.topnav-hamburger:hover { color: var(--overlay-heading); }

/* Utility menu (Account, Sign out, tenant switcher) */
.topnav-utility {
  display: contents;
}

/* Tenant switcher dropdown */
.topnav-tenant-switch {
  position: relative;
}
.topnav-tenant-switch > .topnav-username {
  cursor: pointer;
}
.topnav-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  background: var(--overlay-surface);
  border: 1px solid var(--overlay-divider);
  border-radius: var(--radius);
  min-width: 160px;
  box-shadow: 0 4px 16px rgba(0,0,0,.3);
  z-index: 200;
}
.topnav-tenant-switch:hover .topnav-dropdown { display: block; }
.topnav-dropdown a {
  display: block;
  padding: 8px 14px;
  color: var(--overlay-text);
  text-decoration: none;
  font-size: var(--text-base);
  white-space: nowrap;
  transition: background .12s;
}
.topnav-dropdown a:hover { background: var(--overlay-divider); color: var(--overlay-heading); }

.main-content {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.page-body { padding: 24px; max-width: 1200px; }

.page-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
  position: sticky;
  /* Below the topnav. app.js keeps --sticky-*-h synced to each bar's
     rendered height; the fallback is the fixed desktop topnav height. */
  top: var(--sticky-topnav-h, 52px);
  z-index: 90;
  background: var(--surface);
  padding: 12px 0 10px;
  border-bottom: 1px solid var(--border);
}
/* On the shared desktop row the title stays to one line and ellipsizes
   under pressure, so the action buttons never wrap raggedly. The collapsed
   layouts give the title its own row and restore wrapping. */
.page-title {
  font-weight: var(--font-weight-bold);
  font-size: var(--text-lg);
  letter-spacing: -0.01em;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* -- Action nav bar (sticky toolbar for page actions) -- */
.action-nav {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  /* Keep the buttons whole on the shared desktop row: shortage of space
     ellipsizes the page title instead of wrapping the last button onto a
     ragged second line. */
  flex-shrink: 0;
}

/* -- Cards -- */
.card {
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow);
}
.card-header {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  font-size: var(--text-md);
  font-weight: var(--font-weight-semibold);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.card-body { padding: 18px; }
/* Softer elevation for dense, frequently-repeated cards so pages read calmer.
   Hero/auth/primary cards keep the default --shadow. */
.card-soft { box-shadow: var(--shadow-sm); }

/* -- Buttons -- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border-radius: var(--radius);
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  border: 1px solid transparent;
  text-decoration: none;
  transition: all .15s;
  line-height: var(--line-height-snug);
}
.btn-primary { background: var(--primary); color: var(--primary-contrast); border-color: var(--primary); }
.btn-primary:hover { background: var(--primary-dark); border-color: var(--primary-dark); }
.btn-secondary { background: var(--btn-secondary-bg); color: var(--text); border-color: var(--border); }
.btn-secondary:hover { background: var(--surface); }
.btn-danger { background: var(--danger); color: var(--text-on-accent); border-color: var(--danger); }
.btn-danger:hover { background: var(--danger-dark); }
.btn-sm { padding: 4px 10px; font-size: var(--text-sm); }
.btn-ghost { background: transparent; border-color: transparent; color: var(--text-muted); }
.btn-ghost:hover { background: var(--surface); color: var(--text); }
.btn:disabled,
.btn[disabled] { opacity: .55; cursor: not-allowed; }
.btn:disabled:hover,
.btn[disabled]:hover { background: var(--btn-secondary-bg); color: var(--text); }
/* Consistent keyboard focus ring across all buttons (matches .btn-toggle and
   .form-control focus treatment). Theme-aware via --primary. */
.btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
/* Visible keyboard focus for all other interactive elements (links, plain
   buttons, summaries, anything tabbable). .btn/.btn-toggle keep their own
   higher-specificity rules above. Theme-aware via --primary. */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* -- Forms -- */
.form-group { margin-bottom: 16px; }
.form-label { display: block; font-weight: var(--font-weight-medium); margin-bottom: 4px; font-size: var(--text-base); }
.form-control {
  width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: var(--text-base);
  line-height: var(--line-height-normal);
  background: var(--surface-raised);
  color: var(--text);
  transition: border-color .15s;
}
.form-control:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--focus-ring); }
.form-hint { font-size: var(--text-sm); color: var(--text-muted); margin-top: 4px; }
select.form-control { cursor: pointer; }
.form-control.is-invalid { border-color: var(--danger); }
.form-control.is-invalid:focus { box-shadow: 0 0 0 3px var(--focus-ring-danger); }
.field-error { font-size: var(--text-sm); color: var(--danger); margin-top: 4px; }

/* -- Alerts / Messages -- */
.messages { padding: 0 24px; margin-top: 12px; }
.alert {
  padding: 10px 14px;
  border-radius: var(--radius);
  margin-bottom: 8px;
  font-size: var(--text-base);
  border: 1px solid transparent;
}
.alert-error { background: var(--danger-surface); border-color: var(--danger-border); color: var(--danger-text); }
.alert-success { background: var(--success-surface); border-color: var(--success-border); color: var(--success-text); }
.alert-info { background: var(--info-surface); border-color: var(--info-border); color: var(--info-text); }
.alert-warning { background: var(--surface-warning); border-color: var(--border-warning); color: var(--text-warning); }

/* Clinical-use disclaimer banner -- persistent non-dismissible warning */
.disclaimer-banner { margin-bottom: 12px; }
.disclaimer-banner strong { display: block; margin-bottom: 2px; }

/* Footer with legal links */
.app-footer {
  border-top: 1px solid var(--border);
  padding: 14px 24px;
  font-size: var(--text-sm);
  color: var(--text-muted);
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  justify-content: center;
  background: var(--surface);
}
.app-footer a { color: var(--text-muted); text-decoration: none; }
.app-footer a:hover { color: var(--primary); text-decoration: underline; }

/* Legal / documentation pages */
.legal-page { max-width: 780px; margin: 0 auto; }
.legal-page h1 { font-size: var(--text-2xl); margin-bottom: 8px; }
.legal-page h2 { font-size: var(--text-lg); margin-top: 24px; margin-bottom: 6px; }
.legal-page p { margin-bottom: 12px; line-height: var(--line-height-relaxed); }
.legal-page ul { margin: 0 0 12px 20px; }
.legal-page li { margin-bottom: 4px; line-height: var(--line-height-relaxed); }
.legal-page .legal-updated { color: var(--text-muted); font-size: var(--text-sm); margin-bottom: 20px; }

/* Error pages (400/403/404/500) */
.error-page { max-width: 480px; margin: 64px auto; text-align: center; }
.error-page-code { font-size: var(--text-3xl); font-weight: var(--font-weight-bold); color: var(--text-muted); margin-bottom: 8px; }
.error-page h1 { font-size: var(--text-2xl); margin-bottom: 8px; }
.error-page-message { color: var(--text-muted); line-height: var(--line-height-relaxed); margin-bottom: 24px; }

/* -- Tables -- */
/* Tabular figures keep measurement and date columns vertically aligned. */
.table { width: 100%; border-collapse: collapse; font-size: var(--text-base); font-variant-numeric: tabular-nums; }
.table th { text-align: left; padding: 9px 12px; border-bottom: 2px solid var(--border); font-weight: var(--font-weight-semibold); color: var(--text-muted); font-size: var(--text-sm); text-transform: uppercase; letter-spacing: .04em; }
.table td { padding: 10px 14px; border-bottom: 1px solid var(--border); }
.table tr:last-child td { border-bottom: none; }
.table tbody tr:hover { background: var(--surface); }
/* Two-line table cell: primary value on top, muted attribution beneath. Lets
   dense tables fold a value + its who/when pair into one column instead of two. */
.cell-stack { display: flex; flex-direction: column; line-height: var(--line-height-snug); }
.cell-stack-sub { font-size: var(--text-xs); color: var(--text-muted); }

/* -- Badges -- */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
}
.badge-green { background: var(--badge-green-bg); color: var(--badge-green-text); }
.badge-red { background: var(--badge-red-bg); color: var(--badge-red-text); }
.badge-blue { background: var(--badge-blue-bg); color: var(--badge-blue-text); }
.badge-gray { background: var(--badge-gray-bg); color: var(--badge-gray-text); }

/* -- Protocol Builder -- */
.structure-block {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 12px;
  background: var(--surface-raised);
}
.structure-header {
  background: var(--surface-alt);
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  border-radius: var(--radius) var(--radius) 0 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  font-weight: var(--font-weight-semibold);
}
/* Allow long structure names to break instead of forcing horizontal overflow */
.structure-header > span:first-child { min-width: 0; word-break: break-word; }
.finding-row {
  padding: 8px 14px;
  border-bottom: 1px solid var(--border-subtle);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  font-size: var(--text-base);
}
/* Allow inner left cluster (handle + name + badges) to wrap and shrink */
.finding-row > .flex { flex-wrap: wrap; min-width: 0; }
.finding-row:last-child { border-bottom: none; }
.finding-row:hover { background: var(--surface-alt); }
.finding-type-badge {
  font-size: var(--text-xs);
  padding: 2px 6px;
  background: var(--badge-sky-bg);
  color: var(--badge-sky-text);
  border-radius: var(--radius);
  margin-left: 8px;
}

/* Drag handle (replaces repeated inline styles) */
.drag-handle { cursor: grab; margin-right: 6px; color: var(--text-muted); }

/* Builder add-row footer */
.builder-add-row {
  padding: 10px 14px;
  border-top: 1px solid var(--border);
  background: var(--surface-alt);
}
/* Allow the add-finding form controls to wrap on narrow screens */
.builder-add-row form { flex-wrap: wrap; }

/* -- Exam Form -- */
.exam-structure {
  margin-bottom: 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  /* Keep jump-link targets below the sticky topnav + page-heading +
     section-nav-bar stack. Measured values from app.js win; the fallbacks
     match the desktop stack. */
  scroll-margin-top: var(--sticky-stack-h);
}
/* Keep auto-advance focus targets clear of the sticky stack: focus()
   scrolls the focused element into view honoring scroll-margin, so
   without this the field auto-advance lands on can sit hidden behind
   the sticky bars. Selectors mirror FOCUSABLE_SELECTOR in
   form_keyboard.js; --space-3 adds a visible gap below the chrome. */
.exam-structure .btn-toggle,
.exam-structure .form-control,
.exam-structure .sub-input {
  scroll-margin-top: calc(var(--sticky-stack-h) + var(--space-3));
}
.exam-structure-header {
  padding: 12px 16px;
  background: var(--overlay-surface);
  color: var(--overlay-heading);
  border-radius: var(--radius) var(--radius) 0 0;
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-base);
  letter-spacing: .02em;
}
/* Collapsed section (body folded away): round the header's bottom corners too */
.exam-structure:has(> .exam-structure-body.hidden) .exam-structure-header {
  border-radius: var(--radius);
}
.struct-toggle-icon { font-size: var(--text-xs); color: var(--overlay-text); }
/* Findings pack into a responsive grid: compact fields two-up on wide
   screens, one column when the main panel is narrow. Hairline cell outlines
   meet inside the 1px gaps to draw the row/column separators. */
.exam-structure-body {
  display: grid;
  /* 320px min gives two columns inside the ~680px main panel allowed by the
     1200px .page-body cap, one column anywhere narrower */
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 1px;
  border-radius: 0 0 var(--radius) var(--radius);
  overflow: hidden;
}
.exam-finding {
  padding: 14px 16px;
  background: var(--surface-raised);
  box-shadow: 0 0 0 1px var(--border);
}
/* Wide field types (text, dimensions, multi-instance) keep a full-width row */
.exam-finding-wide { grid-column: 1 / -1; }
/* Compact field types: label left, control right; the conditional sub-field
   block and the comment drawer wrap below at full cell width */
.exam-finding-inline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  /* Pack wrapped lines at the top when a taller grid neighbor stretches the cell */
  align-content: flex-start;
  gap: 8px 12px;
}
.exam-finding-inline .exam-finding-label { margin-bottom: 0; flex: 1 1 auto; }
.exam-finding-inline > input.form-control { flex: 0 0 auto; width: var(--inline-numeric-width); }
/* Long clinical values ("anteverted and anteflexed") must stay readable:
   a select that cannot fit beside the label wraps onto its own full-width
   line instead of clipping. */
.exam-finding-inline > select.form-control { flex: 0 1 auto; width: auto; max-width: 100%; }
.exam-finding-inline > .conditional-block,
.exam-finding-inline > .tech-comment-details { flex-basis: 100%; }
.exam-finding.field-focused { background: var(--field-focus-tint); transition: background .2s ease; }
.exam-finding-label {
  font-weight: var(--font-weight-semibold);
  margin-bottom: 6px;
  font-size: var(--text-md);
  display: flex;
  align-items: center;
  gap: 6px;
}
/* Calm at rest: light-weight amber text rather than a filled chip on every
   required field. The strong signal is reserved for the moment it matters --
   the JS-driven .field-missing highlight after a failed save. */
.required-label {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-warning);
  vertical-align: middle;
}

/* Unfilled required field after a failed save attempt. Applied to whichever
   wrapper holds the missing field: a parent .exam-finding, a sub-field
   .form-group, or a multi-instance .instance-grid-cell. */
.field-missing { background: var(--field-missing-bg); }
/* Dashed border distinguishes an unfilled-required field from an abnormal
   value (solid red border below): a non-color cue, not red-vs-red alone. */
.field-missing .form-control,
.field-missing .btn-toggle-group { border-color: var(--field-missing-border); border-style: dashed; }

/* Highlight for any finding the engine flags abnormal (numeric range,
   advanced rules, or boolean/choice). Mirrors .abnormal-value in the report. */
.input-abnormal.form-control {
  border-color: var(--danger);
  background: var(--danger-surface);
  color: var(--danger-text);
}
.input-abnormal.btn-toggle-group { border-color: var(--danger); }

.conditional-block {
  margin-left: var(--space-4);
  padding: 10px 14px;
  border-left: 3px solid var(--conditional-border);
  background: var(--primary-surface);
  border-radius: 0 var(--radius) var(--radius) 0;
  margin-top: 8px;
  display: none;
}
.conditional-block.visible { display: block; animation: conditional-reveal var(--transition) ease-out; }
/* Draw the eye to sub-fields the moment they appear (parent set abnormal),
   so they are not missed on a dense form. Plays on the display:block switch;
   the visibility toggle itself is unchanged. */
@keyframes conditional-reveal {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

/* -- Dimensions quick-entry field -- */
.dims-quick-entry { border-style: dashed; }
.dims-quick-entry::placeholder { font-style: italic; }

.instance-block {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 8px;
  padding: 12px;
  background: var(--surface-alt);
  position: relative;
}
.instance-header {
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-bottom: 10px;
  text-transform: uppercase;
  letter-spacing: .05em;
}
.instance-remove {
  position: absolute;
  top: 8px; right: 8px;
  font-size: var(--text-sm);
  color: var(--danger);
  cursor: pointer;
  background: none;
  border: none;
  padding: 2px 6px;
}

/* -- Compact instance layout -- grid of sub-fields -- */
.instance-compact { padding: 8px 10px; }
.instance-compact .instance-header {
  display: flex; align-items: center; margin-bottom: 6px;
}
.instance-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 6px 10px;
}
.instance-grid-cell { min-width: 0; }
.instance-grid-wide { grid-column: 1 / -1; }
.instance-grid-label {
  display: block;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--text-muted);
  margin-bottom: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.instance-grid-cell .form-control { font-size: var(--text-base); padding: 5px 8px; }
.instance-grid-cell select.form-control { padding: 5px 6px; }
.instance-grid-classification { margin-top: 6px; }

/* -- Sticky error banner -- */
/* Visibility is owned by the .hidden utility. JS toggles .hidden on
   #save-error-banner; the banner is initially hidden via the class in the
   template. */
.error-banner {
  position: sticky;
  top: var(--sticky-topnav-h, 52px);
  z-index: 9;
  background: var(--danger-surface);
  color: var(--danger-text);
  border: 1px solid var(--danger-border);
  border-radius: var(--radius);
  padding: 10px 16px;
  margin-bottom: 12px;
  font-size: var(--text-base);
}

/* -- Tips bar (dismissible first-visit hints) -- */
.tips-bar {
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 8px 14px;
  margin-bottom: 12px;
  font-size: var(--text-sm);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 8px;
}
.tips-bar kbd {
  display: inline-block;
  padding: 1px 5px;
  font-size: var(--text-xs);
  font-family: inherit;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-xs);
  box-shadow: 0 1px 0 var(--kbd-shadow);
  color: var(--text);
}
.tips-bar-text { flex: 1; }
.tips-bar-dismiss {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: var(--text-2xl);
  line-height: var(--line-height-none);
  padding: 0 2px;
  flex-shrink: 0;
}
.tips-bar-dismiss:hover { color: var(--text); }

/* -- Two-column page layout -- */
.page-cols { display: flex; gap: var(--gap-md); align-items: flex-start; }
/* Give the worksheet (where all the typing happens) a bit more room than the
   draft preview on wide screens. */
.page-col-main { flex: 1.5; min-width: 0; }
/* The draft preview sticks below the topnav and scrolls within its own panel
   so a long draft never grows past the viewport and out of reach. */
.page-col-side {
  flex: 1;
  min-width: 0;
  position: sticky;
  top: var(--sticky-offset);
  max-height: calc(100vh - var(--sticky-offset));
  overflow: auto;
}

/* -- Tech comment amber card -- */
.tech-comment-card { border-color: var(--border-warning); }
.tech-comment-card .card-header {
  background: var(--surface-warning);
  color: var(--text-warning);
  font-size: var(--text-base);
}

/* Abnormal Findings summary: danger-toned twin of the tech-comment card.
   The danger surface/border/text tokens carry their own dark overrides, so
   this needs no separate [data-theme="dark"] rule. */
.abnormal-summary-card { border-color: var(--danger-border); }
.abnormal-summary-card .card-header {
  background: var(--danger-surface);
  color: var(--danger-text);
  font-size: var(--text-base);
}

/* -- Report metadata bar -- */
.meta-bar { padding: 10px 18px; display: flex; gap: 24px; flex-wrap: wrap; align-items: center; }

/* -- Pagination info chip -- */
.pagination-info {
  padding: 4px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: var(--text-base);
  line-height: var(--line-height-loose);
}

/* -- Empty state -- */
.empty-state {
  text-align: center;
  padding: 32px 24px;
  color: var(--text-muted);
}

/* -- Report layout (side-by-side on wide screens) -- */
.report-layout {
  display: flex;
  gap: var(--gap-md);
  align-items: flex-start;
  max-width: 1100px;
}
.report-col-main { flex: 1.3; min-width: 0; }
.report-col-side { flex: 1; min-width: 0; position: sticky; top: var(--sticky-offset); }

/* -- Report -- */
.report-box {
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 20px;
  word-break: break-word;
}

.report-doc {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--line-height-relaxed);
  color: var(--text);
}

.report-meta {
  padding-bottom: 14px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--border);
}
.report-meta-line { line-height: var(--line-height-loose); }
.report-label {
  font-weight: var(--font-weight-bold);
  font-size: var(--text-sm);
  letter-spacing: .06em;
  color: var(--overlay-subtle);
  text-transform: uppercase;
  min-width: 100px;
  display: inline-block;
}

.report-section { margin-bottom: 16px; }
.report-section-heading {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-bold);
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--report-heading-text);
  padding: 5px 10px;
  background: var(--primary-surface);
  border-left: 3px solid var(--primary);
  border-radius: 0 var(--radius) var(--radius) 0;
  margin-bottom: 6px;
}
.report-section-body { padding-left: 4px; }
.report-line { padding: 2px 0; font-size: var(--text-base); line-height: var(--line-height-loose); }

.abnormal-value {
  color: var(--danger);
  font-weight: var(--font-weight-semibold);
}
.copy-btn { position: relative; }

/* -- Toggle button group (boolean + small choice fields) -- */
.btn-toggle-group {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  flex-wrap: wrap;
}
.btn-toggle {
  padding: 6px 18px;
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  background: var(--surface-raised);
  border: none;
  border-right: 1px solid var(--border);
  color: var(--text);
  transition: background .12s, color .12s;
  line-height: var(--line-height-snug);
  white-space: nowrap;
}
.btn-toggle:last-child { border-right: none; }
.btn-toggle:hover:not(.active) { background: var(--surface); }
.btn-toggle.active { background: var(--primary); color: var(--primary-contrast); }
/* A choice option's hint: muted guidance under the option label (grading
   criterion, etc.), shown on multi-select checkboxes and on the stacked
   choice layout below. */
.choice-hint-label {
  display: block;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-normal);
  color: var(--text-muted);
  line-height: var(--line-height-snug);
}

/* Stacked choice layout: a hinted pick list flows as full-width option rows
   (label over hint) instead of the compact horizontal button group, so each
   hint has its own space and clear separation from the next option and the
   next finding. Same toggle styling and active state, just vertical. */
.btn-toggle-group-stacked {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: 100%;
  max-width: 30rem;
}
.btn-toggle-group-stacked .btn-toggle {
  border-right: none;
  border-bottom: 1px solid var(--border);
  text-align: left;
  white-space: normal;
  padding: 10px 14px;
}
.btn-toggle-group-stacked .btn-toggle:last-child { border-bottom: none; }
/* A hinted row stacks its label over the hint sub-text. */
.btn-toggle-group-stacked .btn-toggle-hinted {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
}
/* Keep the hint readable on the accent-filled active row. */
.btn-toggle.active .choice-hint-label { color: var(--primary-contrast); opacity: .85; }

/* Multi-select (select all that apply): a wrapping list of checkboxes. */
.multi-select-group {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
}
.multi-select-option {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-base);
  color: var(--text);
  cursor: pointer;
  line-height: var(--line-height-snug);
}
.multi-select-option input {
  accent-color: var(--primary);
  cursor: pointer;
}
.btn-toggle:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: -2px;
  z-index: 1;
  position: relative;
}

/* -- Keyboard shortcuts overlay -- */
.kb-row { padding: 2px 0; color: var(--overlay-text); }
.kb-key {
  display: inline-block;
  padding: 1px 6px;
  background: var(--overlay-divider);
  border-radius: var(--radius);
  font-size: var(--text-sm);
  font-family: var(--font-mono);
  color: var(--overlay-text);
  margin-right: 2px;
}

/* -- Section nav sticky bar (wraps chips + shortcuts button) -- */
.section-nav-bar {
  position: sticky;
  /* Below the topnav + page-heading. Measured values from app.js win;
     the fallbacks match the fixed desktop topnav and a one-row heading. */
  top: calc(var(--sticky-topnav-h, 52px) + var(--sticky-heading-h, 54px));
  z-index: 50;
  background: var(--surface);
  padding: 8px 0 6px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 14px;
  flex-wrap: wrap;
  row-gap: 6px;
}
/* The chip strip shares the row with the utility buttons (Glove Mode /
   Shortcuts) when there is room, reclaiming vertical space at the top of the
   worksheet. Chips wrap internally (.section-nav is flex-wrap) and the whole
   bar wraps the buttons to a second row only when space runs out. */
.section-nav-bar > .section-nav {
  flex: 1 1 auto;
}

/* -- Section jump nav -- */
.section-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 0;
}
.section-nav-chip {
  display: inline-block;
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  font-size: var(--text-sm);
  text-decoration: none;
  color: var(--text-muted);
  background: var(--surface-raised);
  transition: all .12s;
}
.section-nav-chip:hover {
  border-color: var(--primary);
  color: var(--primary);
  background: var(--primary-surface);
}

/* -- Product name logo --
   Shared typography for the {{ PRODUCT_NAME }} wordmark across topnav,
   auth card, landing nav and help/public header. Individual usage sites
   set their own font-size; this rule owns weight, spacing and an accent
   dot rendered with the brand gradient. */
.topnav-brand,
.auth-logo,
.landing-brand,
.help-header-brand {
  font-weight: var(--font-weight-heavy);
  letter-spacing: -0.02em;
  line-height: var(--line-height-none);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.topnav-brand::before,
.auth-logo::before,
.landing-brand::before,
.help-header-brand::before {
  content: "";
  display: inline-block;
  width: 0.55em;
  height: 0.55em;
  border-radius: var(--radius-xs);
  background: var(--logo-gradient);
  flex-shrink: 0;
}

/* -- Auth pages -- */
/* Column flex so the shared footer stacks below the card instead of
   sitting beside it. margin:auto on the card absorbs the free space,
   centering it both axes and pushing the footer to the bottom. */
.auth-page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* Soft accent glow above the card on the deep petrol backdrop. */
  background: radial-gradient(1100px 520px at 50% -10%, var(--accent-glow), transparent 65%), var(--overlay-deep);
}
.auth-card {
  background: var(--surface-raised);
  border-radius: var(--radius-lg);
  padding: 36px;
  width: 100%;
  max-width: 440px;
  box-shadow: 0 24px 64px rgba(0,0,0,.35);
  margin: auto;
}
.auth-logo {
  display: flex;
  justify-content: center;
  margin-bottom: 24px;
  font-size: var(--text-3xl);
  color: var(--primary);
}
.auth-tabs {
  display: flex;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 20px;
}
.auth-tab {
  flex: 1;
  padding: 8px;
  text-align: center;
  cursor: pointer;
  font-size: var(--text-base);
  background: var(--surface);
  border: none;
  font-weight: var(--font-weight-medium);
  color: var(--text-muted);
}
.auth-tab.active { background: var(--primary); color: var(--primary-contrast); }

/* -- Required field star -- */
.required-star { color: var(--danger); font-weight: var(--font-weight-bold); }


/* -- Section nav active chip (scroll-spy) -- */
.section-nav-chip.active {
  background: var(--primary);
  color: var(--primary-contrast);
  border-color: var(--primary);
}

/* -- Structure completion badge -- */
.struct-progress {
  margin-left: auto;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  letter-spacing: .02em;
  transition: background var(--transition), color var(--transition);
}
.struct-progress-done { background: var(--success); color: var(--text-on-accent); }
.struct-progress-partial { background: var(--warning); color: var(--text-on-accent); }
.struct-progress-empty { background: var(--progress-empty-bg); color: var(--overlay-text); }

/* -- Tech comment disclosure -- */
.tech-comment-details { margin-top: 8px; }
.tech-comment-summary {
  cursor: pointer;
  color: var(--text-muted);
  font-size: var(--text-sm);
  user-select: none;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 4px;
}
.tech-comment-summary::-webkit-details-marker { display: none; }
.tech-comment-summary::before {
  content: '\25B6';
  font-size: var(--text-2xs);
  transition: transform .15s;
  display: inline-block;
}
details[open] .tech-comment-summary::before { transform: rotate(90deg); }
.subedit-panel { background: var(--panel-inset); }
.subedit-divider { border-top: 1px solid var(--border); }
.subfield-add-panel { background: var(--surface); }
.subfield-add-heading {
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sm);
  margin-bottom: 10px;
  color: var(--text-muted);
}

/* -- Landing page -- */
.btn-lg { padding: 12px 24px; font-size: var(--text-lg); font-weight: var(--font-weight-semibold); }
.btn-outline {
  background: transparent;
  color: var(--overlay-heading);
  border-color: var(--btn-outline-border);
}
.btn-outline:hover {
  background: var(--btn-outline-hover-bg);
  border-color: var(--btn-outline-border-hover);
}
/* Primary CTAs on the always-dark marketing chrome use the bright accent
   (matches the topnav CTA) so they stand out against the petrol backdrop. */
.landing-nav .btn-primary,
.landing-hero .btn-primary,
.landing-cta .btn-primary {
  background: var(--accent-bright);
  border-color: var(--accent-bright);
  color: var(--accent-bright-text);
}
.landing-nav .btn-primary:hover,
.landing-hero .btn-primary:hover,
.landing-cta .btn-primary:hover {
  background: var(--accent-bright-hover);
  border-color: var(--accent-bright-hover);
}

.landing-body {
  background: var(--surface);
  color: var(--text);
}
.landing-container {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 24px;
}

/* Landing top nav */
.landing-nav {
  background: var(--overlay-deep);
  border-bottom: 1px solid rgba(255,255,255,.08);
  position: sticky;
  top: 0;
  z-index: 100;
}
.landing-nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  row-gap: 6px;
  min-height: 60px;
}
.landing-brand {
  font-size: var(--text-2xl);
  color: var(--overlay-heading);
}
.landing-nav-links {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 22px;
  row-gap: 6px;
}
.landing-nav-link {
  color: var(--overlay-text);
  text-decoration: none;
  font-size: var(--text-base);
  font-weight: var(--font-weight-medium);
  transition: color .15s;
}
.landing-nav-link:hover { color: var(--overlay-heading); }
.landing-theme-toggle {
  background: transparent;
  border: none;
  color: var(--overlay-text);
  font-size: var(--text-2xl);
  cursor: pointer;
  padding: 4px 8px;
}
.landing-theme-toggle:hover { color: var(--overlay-heading); }

/* Hero */
.landing-hero {
  background: radial-gradient(1100px 520px at 50% -10%, var(--accent-glow), transparent 65%), linear-gradient(180deg, var(--overlay-deep) 0%, var(--overlay-surface) 100%);
  color: var(--overlay-heading);
  padding: 96px 0 112px;
  text-align: center;
}
.landing-hero-inner { max-width: 760px; margin: 0 auto; }
.landing-hero-title {
  font-size: var(--text-4xl);
  font-weight: var(--font-weight-heavy);
  line-height: var(--line-height-tight);
  letter-spacing: -0.02em;
  margin-bottom: 20px;
}
.landing-hero-sub {
  font-size: var(--text-2xl);
  line-height: var(--line-height-relaxed);
  color: var(--overlay-text);
  margin-bottom: 32px;
}
.landing-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}
.landing-hero-note {
  margin-top: 28px;
  font-size: var(--text-base);
  color: var(--overlay-muted);
}

/* Sections */
.landing-section { padding: 88px 0; }
.landing-section-light { background: var(--surface-alt); }
.landing-section-title {
  font-size: var(--text-3xl);
  font-weight: var(--font-weight-bold);
  text-align: center;
  margin-bottom: 12px;
  letter-spacing: -0.01em;
  color: var(--text);
}
.landing-section-sub {
  font-size: var(--text-xl);
  color: var(--text-muted);
  text-align: center;
  margin-bottom: 48px;
}

/* Feature grid */
.landing-features {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
}
.landing-card {
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 28px;
  box-shadow: var(--shadow);
  transition: transform .15s, box-shadow .15s;
}
.landing-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(0,0,0,.08);
}
.landing-card-icon {
  width: 44px;
  height: 44px;
  border-radius: var(--radius-lg);
  background: var(--primary-surface);
  color: var(--primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: var(--font-weight-bold);
  font-size: var(--text-2xl);
  margin-bottom: 16px;
}
.landing-card-title {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
  margin-bottom: 8px;
  color: var(--text);
}
.landing-card-body {
  font-size: var(--text-base);
  line-height: var(--line-height-relaxed);
  color: var(--text-muted);
}

/* Screenshots (static/img/marketing/, regenerated by scripts/regen_screenshots.sh) */
.landing-hero-shot {
  max-width: 960px;
  margin: 48px auto 0;
}
.landing-hero-shot img {
  display: block;
  width: 100%;
  border: 1px solid var(--overlay-divider);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 48px rgba(0,0,0,.35);
}
.landing-shots {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
.landing-shot { margin: 0; }
.landing-shot img {
  display: block;
  width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.landing-shot figcaption {
  margin-top: 10px;
  font-size: var(--text-base);
  color: var(--text-muted);
  line-height: var(--line-height-normal);
}

/* Steps */
.landing-steps {
  list-style: none;
  max-width: 720px;
  margin: 0 auto;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 28px;
}
.landing-step {
  display: flex;
  gap: 20px;
  align-items: flex-start;
}
.landing-step-num {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--primary);
  color: var(--primary-contrast);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: var(--font-weight-bold);
  font-size: var(--text-2xl);
}
.landing-step-body { flex: 1; }
.landing-step-title {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
  margin-bottom: 6px;
  color: var(--text);
}
.landing-step-text {
  font-size: var(--text-base);
  line-height: var(--line-height-relaxed);
  color: var(--text-muted);
}

/* Bottom CTA */
.landing-cta {
  background: var(--overlay-deep);
  color: var(--overlay-heading);
  padding: 80px 0;
  text-align: center;
}
.landing-cta-title {
  font-size: var(--text-3xl);
  font-weight: var(--font-weight-bold);
  margin-bottom: 12px;
  letter-spacing: -0.01em;
}
.landing-cta-sub {
  font-size: var(--text-xl);
  color: var(--overlay-text);
  margin-bottom: 28px;
}

/* Footer */
.landing-footer {
  background: var(--overlay-deepest);
  color: var(--overlay-muted);
  padding: 32px 0;
  border-top: 1px solid rgba(255,255,255,.06);
}
.landing-footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
}
.landing-footer-links {
  display: flex;
  gap: 22px;
}
.landing-footer-links a {
  color: var(--overlay-muted);
  text-decoration: none;
  font-size: var(--text-base);
}
.landing-footer-links a:hover { color: var(--overlay-heading); }

/* Public pricing page (/plans/) -- rendered inside _public_base.html */
.plans-hero {
  text-align: center;
  padding: 16px 0 28px;
}
.plans-hero-title {
  font-size: var(--text-3xl);
  font-weight: var(--font-weight-bold);
  color: var(--text);
  margin-bottom: 12px;
  letter-spacing: -0.01em;
}
.plans-hero-sub {
  font-size: var(--text-lg);
  color: var(--text-muted);
  max-width: 560px;
  margin: 0 auto;
  line-height: var(--line-height-relaxed);
}
.plans-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 20px;
  margin: 0 0 40px;
}
.plans-card {
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: var(--shadow);
}
.plans-card-title {
  font-size: var(--text-2xl);
  font-weight: var(--font-weight-semibold);
  color: var(--text);
}
.plans-card-price {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.plans-card-amount {
  font-size: var(--text-3xl);
  font-weight: var(--font-weight-bold);
  color: var(--text);
}
.plans-card-period {
  font-size: var(--text-base);
  color: var(--text-muted);
}
.plans-card-meter {
  font-size: var(--text-base);
  color: var(--text-muted);
  margin-bottom: 8px;
}
.plans-card-cta { margin-top: auto; align-self: flex-start; }
.plans-empty {
  grid-column: 1 / -1;
  text-align: center;
  color: var(--text-muted);
  padding: 40px 0;
}
.plans-cta {
  text-align: center;
  padding: 32px 0 8px;
  border-top: 1px solid var(--border);
}
.plans-cta-title {
  font-size: var(--text-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--text);
  margin-bottom: 8px;
}
.plans-cta-sub {
  font-size: var(--text-base);
  color: var(--text-muted);
  margin-bottom: 20px;
  max-width: 480px;
  margin-left: auto;
  margin-right: auto;
  line-height: var(--line-height-relaxed);
}

/* -- Dark mode -- */
[data-theme="dark"] {
  /* Bright teal accent with deep-teal ink on filled surfaces. As plain text
     on the dark background it clears AA on its own. */
  --primary: #2dd4bf;
  --primary-dark: #14b8a6;
  --primary-contrast: #053b34;
  --primary-light: #5eead4;
  --primary-surface: #123a37;
  --surface: #0b1a1d;
  --surface-alt: #12262b;
  --border: #24424a;
  --border-strong: #35545c;
  --text: #d7e5e6;
  --text-muted: #8fa9ac;
  --text-subtle: #5d7c80;
  --danger: #ef4444;
  --danger-light: #f87171;
  --danger-surface: #450a0a;
  --danger-border: #7f1d1d;
  --danger-text: #fca5a5;
  --success: #22c55e;
  --success-surface: #052e16;
  --success-border: #14532d;
  --success-text: #86efac;
  --surface-warning: #422006;
  --border-warning: #78350f;
  --text-warning: #fcd34d;
  --field-missing-bg: #2d1515;

  /* Info palette reuses dark primary surface */
  --info-surface: var(--primary-surface);
  --info-border: #1e5c56;
  --info-text: var(--primary-light);

  /* Badge palette maps onto semantic dark surfaces */
  --badge-green-bg: var(--success-surface);
  --badge-green-text: var(--success-text);
  --badge-red-bg: var(--danger-surface);
  --badge-red-text: var(--danger-text);
  --badge-blue-bg: var(--primary-surface);
  --badge-blue-text: var(--primary-light);
  --badge-gray-bg: var(--border);
  --badge-gray-text: var(--text);

  /* Focus rings tuned to dark theme primary/danger */
  --focus-ring: rgba(45,212,191,.22);
  --focus-ring-danger: rgba(239,68,68,.2);

  /* Danger hover darkens less on already-dim dark palette */
  --danger-dark: #dc2626;

  /* Secondary button surface reuses dark surface-alt */
  --btn-secondary-bg: var(--surface-alt);

  /* Elevated panels sit one step above surface-alt so cards lift off the
     page in dark mode (light mode uses #fff for the same effect). Petrol
     value between surface-alt #12262b and border #24424a. */
  --surface-raised: #18333a;

  /* Dark counterparts for the light-only tokens above */
  --field-missing-border: var(--danger);
  --border-subtle: var(--border);
  --badge-sky-bg: var(--primary-surface);
  --badge-sky-text: var(--primary-light);
  --conditional-border: #0f766e;
  --report-heading-text: var(--primary-light);
  --panel-inset: var(--surface-alt);
  --field-focus-tint: rgba(45,212,191,.07);
}
[data-theme="dark"] body { background: var(--surface); color: var(--text); }
[data-theme="dark"] .card { border-color: var(--border); }
[data-theme="dark"] .card-header { border-color: var(--border); }
[data-theme="dark"] .btn-secondary { background: var(--border); color: var(--text); border-color: var(--border-strong); }
[data-theme="dark"] .btn-secondary:hover { background: var(--border-strong); }
[data-theme="dark"] .btn-ghost:hover { background: var(--border); color: var(--text); }
[data-theme="dark"] .btn-toggle { background: var(--surface); color: var(--text-subtle); border-color: var(--border); }
[data-theme="dark"] .btn-toggle:hover:not(.active) { background: var(--surface-alt); color: var(--text-muted); }
[data-theme="dark"] .btn-toggle.active { background: var(--primary); color: var(--primary-contrast); font-weight: var(--font-weight-semibold); }
[data-theme="dark"] .btn-toggle-group { border-color: var(--border); }
[data-theme="dark"] .form-control { background: var(--surface); color: var(--text); border-color: var(--border); }
[data-theme="dark"] .form-control:focus { border-color: var(--primary); background: var(--surface); box-shadow: 0 0 0 3px var(--focus-ring); }
/* Renders the native calendar-picker icon light instead of dark-on-dark. */
[data-theme="dark"] .input-date { color-scheme: dark; }
[data-theme="dark"] .table th { color: var(--text-muted); border-color: var(--border); }
[data-theme="dark"] .table td { border-color: var(--border); }
[data-theme="dark"] .table tbody tr:hover { background: var(--surface-alt); }
[data-theme="dark"] .structure-block { border-color: var(--border); }
[data-theme="dark"] .structure-header { background: var(--surface); border-color: var(--border); }
[data-theme="dark"] .finding-row:hover { background: var(--surface); }
[data-theme="dark"] .dashboard-hero { border-color: var(--border-strong); }
[data-theme="dark"] .instance-block { background: var(--surface); border-color: var(--border); }
[data-theme="dark"] .exam-structure { border-color: var(--border); }
[data-theme="dark"] .exam-structure-header { background: var(--surface); }
[data-theme="dark"] .exam-finding.field-focused { background: var(--field-focus-tint); }
[data-theme="dark"] .report-box { border-color: var(--border); }
[data-theme="dark"] .report-meta { border-color: var(--border); }
[data-theme="dark"] .page-heading { background: var(--surface); border-bottom-color: var(--border); }
[data-theme="dark"] .section-nav-bar { border-bottom-color: var(--border); }
[data-theme="dark"] .section-nav-chip { color: var(--text-muted); border-color: var(--border); }
[data-theme="dark"] .section-nav-chip:hover { color: var(--primary-light); border-color: var(--primary); }
[data-theme="dark"] .section-nav-chip.active { background: var(--primary); color: var(--primary-contrast); }
[data-theme="dark"] .alert-error { background: var(--danger-surface); border-color: var(--danger-border); color: var(--danger-text); }
[data-theme="dark"] .alert-success { background: var(--success-surface); border-color: var(--success-border); color: var(--success-text); }
[data-theme="dark"] .alert-info { background: var(--primary-surface); border-color: var(--info-border); color: var(--primary-light); }
[data-theme="dark"] .alert-warning { background: var(--surface-warning); border-color: var(--border-warning); color: var(--text-warning); }
[data-theme="dark"] .app-footer { background: var(--surface); border-top-color: var(--border); color: var(--text-muted); }
[data-theme="dark"] .app-footer a { color: var(--text-muted); }
[data-theme="dark"] .app-footer a:hover { color: var(--primary-light); }
[data-theme="dark"] .badge-gray { background: var(--border); color: var(--text); }
[data-theme="dark"] .badge-green { background: var(--success-surface); color: var(--success-text); }
[data-theme="dark"] .badge-blue { background: var(--primary-surface); color: var(--primary-light); }
[data-theme="dark"] .badge-red { background: var(--danger-surface); color: var(--danger-text); }
[data-theme="dark"] .error-banner { background: var(--danger-surface); color: var(--danger-text); border-color: var(--danger-border); }
[data-theme="dark"] .pagination-info { border-color: var(--border); }
[data-theme="dark"] .topnav-dropdown { background: var(--surface); }
/* The collapsed topnav (links strip + utility menu) restyles onto app
   surfaces in dark mode. Scoped to the tablet breakpoint where the topnav
   actually collapses; on desktop the strip stays on the shared petrol
   chrome, so no banding appears mid-nav. */
@media (max-width: 1024px) {
  [data-theme="dark"] .topnav-links { background: var(--surface); border-top-color: var(--border); }
  [data-theme="dark"] .topnav-links a { border-bottom-color: var(--border); color: var(--text); }
  [data-theme="dark"] .topnav-utility { background: var(--surface); border-color: var(--border); }
}
[data-theme="dark"] select.form-control option { background: var(--surface); }
[data-theme="dark"] .form-control.is-invalid { border-color: var(--danger); }
[data-theme="dark"] .field-error { color: var(--danger-text); }
[data-theme="dark"] .abnormal-value { color: var(--danger-light); }
[data-theme="dark"] .report-label { color: var(--text-muted); }
[data-theme="dark"] .builder-add-row { background: var(--surface); border-color: var(--border); }
[data-theme="dark"] .subfield-add-panel { background: var(--surface-alt); }
[data-theme="dark"] .tips-bar kbd { background: var(--surface); border-color: var(--border-strong); color: var(--text); }

/* Landing dark mode overrides */
[data-theme="dark"] .landing-body { background: var(--surface); }
[data-theme="dark"] .landing-section-light { background: var(--surface-alt); }
[data-theme="dark"] .landing-card { border-color: var(--border); }
[data-theme="dark"] .landing-card:hover { box-shadow: 0 8px 20px rgba(0,0,0,.3); }
[data-theme="dark"] .landing-card-icon { background: var(--primary-surface); color: var(--primary-light); }

/* -- Responsive / Mobile -- */

/* Narrow desktop: the single-row topnav fits an admin's 7 links plus the
   account controls only from ~1150px up. Below that, drop the username
   (already hidden on the collapsed topnav; the Account page shows it) and
   tighten link padding so "Sign out" is never pushed off screen. */
@media (max-width: 1150px) {
  .topnav-right > .topnav-username { display: none; }
  .topnav-links a { padding: 0 10px; }
}

/* Tablet: equal-width two-column layout + collapsed topnav. The topnav
   collapses here (not at 768px) because the desktop single-row layout
   needs ~1024px+ to fit brand + tenant + 7 nav links + username +
   theme toggle + Account + Sign out without overflow/wrapping. */
@media (max-width: 1024px) {
  /* Load-time fallbacks for the sticky-stack heights while the topnav is
     wrapped. The base .page-heading / .section-nav-bar / .exam-structure
     rules derive every sticky `top` and scroll-margin from these variables;
     app.js measures each bar's rendered height (which varies with width,
     title wrapping, and glove mode) and keeps them in sync via
     ResizeObserver. */
  :root {
    --sticky-topnav-h: 88px;   /* 48px brand/icons row + 40px links row */
    --sticky-heading-h: 70px;  /* page-heading: title row + action-nav row */
    --sticky-navbar-h: 52px;   /* section-nav-bar: chip row + button row */
  }

  /* Stack the two-column form layout. The 50/50 split this rule used to
     produce never gave either column enough room (a 960 px viewport, ie
     half a 1920 monitor, left the form ~440 px wide). When the draft
     preview can no longer sit beside the form it drops to the bottom in
     natural DOM order (after the main column), so the form stays the
     primary focus instead of being pushed down by the preview. */
  .page-cols { flex-direction: column; }
  .page-col-main { width: 100%; flex: none; }
  .page-col-side { width: 100%; flex: none; position: static; top: auto; max-height: none; overflow: visible; }
  /* Builder: stack the editing columns with the live preview dropping to
     the bottom (it keeps its DOM order, after the main column). */
  .builder-cols { flex-direction: column; }
  .builder-col-main,
  .builder-col-side { width: 100%; flex: none; }
  .builder-col-side { position: static; top: auto; }
  /* Trim form chrome so more horizontal space goes to fields. */
  .page-body { padding: 8px; }
  .exam-finding { padding: 10px 12px; }
  .exam-structure-header { padding: 10px 14px; font-size: var(--text-base); }
  /* Section nav chips scroll horizontally instead of wrapping into 3-4
     rows that consume the top of the viewport. */
  .section-nav { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .section-nav::-webkit-scrollbar { display: none; }
  .section-nav-chip { flex-shrink: 0; }

  /* Page heading: wraps so the action-nav drops to its own row below the
     title. Sharing a row crams Save / View Draft / Back next to a
     potentially long protocol title and wraps leftover buttons onto a
     ragged second line. A dedicated row lets the buttons scroll across
     the full content width instead. */
  .page-heading {
    gap: 8px;
    row-gap: 4px;
    padding: 8px 0;
    flex-wrap: wrap;
  }
  /* Full-width row of its own here, so the title may wrap instead of
     truncating (keeps the accession visible). */
  .page-title { font-size: var(--text-base); flex-shrink: 0; white-space: normal; }

  /* Action nav: force to a second row with full width, then scroll its
     buttons horizontally if they overflow. Mirrors the section-nav scroll
     pattern so the heading height stays predictable. */
  .action-nav {
    flex: 1 0 100%;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    min-width: 0;
  }
  .action-nav::-webkit-scrollbar { display: none; }
  .action-nav .btn { flex-shrink: 0; padding: 6px 10px; font-size: var(--text-sm); }

  /* Topnav */
  .topnav { padding: 0; height: auto; flex-wrap: wrap; }
  .topnav-hamburger { display: flex; align-items: center; }

  /* Main nav links - always visible as scrollable horizontal strip */
  .topnav-links {
    flex: 0 0 100%;
    order: 10;
    height: 40px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    background: var(--overlay-surface);
    border-top: 1px solid var(--overlay-divider);
    scrollbar-width: none;
  }
  .topnav-links::-webkit-scrollbar { display: none; }
  .topnav-links a {
    padding: 0 14px;
    font-size: var(--text-base);
    white-space: nowrap;
    flex-shrink: 0;
    height: 40px;
  }
  .topnav-links a.active { color: var(--overlay-heading); border-bottom-color: var(--primary-light); }

  /* Hide username on collapsed topnav -- visible in Account page instead */
  .topnav-right > .topnav-username { display: none; }

  /* Utility menu - collapsible via hamburger */
  .topnav-utility {
    display: none;
    position: absolute;
    top: 100%;
    right: 0;
    width: 200px;
    flex-direction: column;
    background: var(--overlay-surface);
    border: 1px solid var(--overlay-divider);
    border-radius: 0 0 0 var(--radius);
    box-shadow: 0 4px 12px rgba(0,0,0,.3);
    z-index: 200;
  }
  .topnav-utility.is-open { display: flex; }
  .topnav-utility .topnav-action,
  .topnav-utility .topnav-tenant-switch {
    padding: 12px 16px;
    border-bottom: 1px solid var(--overlay-divider);
    display: block;
    text-align: left;
    width: 100%;
  }
  .topnav-utility .topnav-action:last-child,
  .topnav-utility .topnav-tenant-switch:last-child { border-bottom: none; }
  .topnav-utility form { display: block; }
  .topnav-utility form button {
    padding: 12px 16px;
    width: 100%;
    text-align: left;
    color: var(--overlay-muted);
  }

  .topnav-brand { font-size: var(--text-base); padding: 0 12px; height: 48px; display: flex; align-items: center; }
  /* flex-basis 0 (not auto): flex line-breaking uses the item's base size,
     so with basis auto a long tenant name pushes .topnav-right onto a third
     row on narrow phones. Basis 0 keeps brand + tenant + icons on one row;
     the tenant then grows into the leftover space and ellipsizes. */
  .topnav-tenant { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: var(--text-xs); height: 48px; padding: 0 8px; display: flex; align-items: center; }
  .topnav-right { height: 48px; padding-right: 12px; position: relative; }

}

/* Mobile: single-column stacked layout */
@media (max-width: 768px) {
  .page-body { padding: 12px; }

  /* Report layout: stack vertically on mobile.
     Form layout (.page-cols) is already stacked by the 1024px block. */
  .report-layout { flex-direction: column; }
  .report-col-side { position: static; }

  /* Larger touch targets for toggle buttons */
  .btn-toggle { padding: 10px 20px; font-size: var(--text-base); }
  .btn-toggle-group { flex-wrap: wrap; }

  /* Prevent iOS auto-zoom on input focus (requires 16px+; --text-md is 16px) */
  .form-control { font-size: var(--text-md); }
  select.form-control { font-size: var(--text-md); }

  /* Section nav bar: tighter padding on phones. The sticky `top` comes from
     the base rule's --sticky-*-h variables. */
  .section-nav-bar {
    row-gap: 4px;
    padding: 6px 0 4px;
  }
  /* Glove mode on mobile: taller section nav bar so enlarged chips have
     breathing room during sticky scroll (default mobile padding leaves the
     row cramped once chip padding/font grows). */
  [data-glove-mode="true"] .section-nav-bar {
    padding: 12px 0 10px;
    row-gap: 8px;
  }
  /* Section nav: horizontally scrollable on mobile rather than chip-wrap,
     so the nav stack stays short. */
  .section-nav-bar > .section-nav {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 4px;
  }
  .section-nav-chip { white-space: nowrap; flex-shrink: 0; }

  /* Exam structure header slightly taller for touch */
  .exam-structure-header { padding: 14px 16px; font-size: var(--text-base); }
  .exam-finding { padding: 14px 12px; }

  /* Compact instance grid: single column on mobile */
  .instance-grid { grid-template-columns: 1fr; }

  /* Canvas tool controls: wrap on mobile */
  #ref-images-body > div > div:last-child { flex-wrap: wrap; }

  /* Table: allow horizontal scroll */
  .table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }

  /* Dashboard stat cards: 2-column grid */
  .stats-grid { grid-template-columns: 1fr 1fr !important; }

  /* Meta bar: stack vertically */
  .meta-bar { flex-direction: column; gap: 6px; align-items: flex-start; }

  /* Auth card: full width on small screens */
  .auth-card { padding: 24px 16px; }

  /* Report box: tighter padding */
  .report-box { padding: 12px; }

  /* Landing page */
  .landing-hero { padding: 64px 0 72px; }
  .landing-hero-title { font-size: var(--text-3xl); }
  .landing-hero-sub { font-size: var(--text-xl); }
  .landing-section { padding: 56px 0; }
  .landing-section-title { font-size: var(--text-2xl); }
  .landing-features { grid-template-columns: 1fr; }
  .landing-shots { grid-template-columns: 1fr; }
  .landing-hero-shot { margin-top: 36px; }
  .landing-nav-links { gap: 12px; }
  .landing-nav-link { font-size: var(--text-base); }
  .landing-nav-link-hideable { display: none; }
  .landing-cta-title { font-size: var(--text-2xl); }
  .landing-footer-inner { flex-direction: column; text-align: center; }

  /* Filter rows: each labelled field gets its own row, status pill group
     drops to a dedicated full-width row at the bottom. Without this the
     `.ml-auto` group can land mid-stack when fields wrap. */
  .filter-field { width: 100%; }
  .filter-field .form-control { max-width: none; }
  .filter-field input[type="date"] { width: 100%; }
  .ml-auto.flex.gap-1 { margin-left: 0; width: 100%; }

  /* Protocol list: search form and import form should each take a row
     instead of fighting for ml-auto alignment when stacked. */
  .card-body > form.ml-auto { margin-left: 0; width: 100%; }

  /* Manage users header search shrinks and right-aligns naturally with
     flex-wrap, but cap the search input so the header does not span twice
     the title height when the form drops to its own row. */
  .card-header .form-control.max-w-search { max-width: 180px; }
}

/* -- Guide pages -- */
.guide-title { font-size: var(--text-2xl); margin-bottom: 4px; }
.guide-subtitle { color: var(--text-muted); margin-bottom: 28px; }
.guide-step-badge { margin-right: 10px; font-weight: var(--font-weight-bold); }
.guide-section-heading {
  font-size: var(--text-base); font-weight: var(--font-weight-semibold);
  margin: 20px 0 10px; padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
}
.guide-figure { margin: 0; }
.guide-figure img {
  max-width: 100%; border: 1px solid var(--border);
  border-radius: var(--radius);
}
.guide-figure figcaption {
  font-size: var(--text-sm); color: var(--text-muted); margin-top: 6px;
}
.guide-gallery { display: flex; flex-direction: column; gap: 16px; }
.guide-ol { margin-left: 20px; margin-bottom: 16px; line-height: var(--line-height-loose); }
.guide-back-link { color: var(--text-muted); font-size: var(--text-base); }
.guide-card-link { text-decoration: none; color: inherit; }
.guide-card-title { font-weight: var(--font-weight-semibold); font-size: var(--text-lg); margin-bottom: 4px; }
.guide-card-desc { color: var(--text-muted); font-size: var(--text-base); line-height: var(--line-height-normal); }
.guide-kbd {
  display: inline-block;
  padding: 1px 6px;
  font-size: var(--text-sm);
  font-family: var(--font-mono);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xs);
  box-shadow: 0 1px 0 rgba(0,0,0,.06);
  color: var(--text);
  white-space: nowrap;
}
.guide-syntax {
  display: block;
  padding: 10px 12px;
  margin: 8px 0 16px;
  font-family: var(--font-mono);
  font-size: var(--text-base);
  line-height: var(--line-height-normal);
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  white-space: pre-wrap;
  overflow-x: auto;
}

/* -- Data tables -- */
.data-table { width: 100%; border-collapse: collapse; font-size: var(--text-base); }
.data-table th,
.data-table td { text-align: left; padding: 8px 12px; }
.data-table th { border-bottom: 2px solid var(--border); }
.data-table td { border-bottom: 1px solid var(--border); }
.data-table .cell-label { font-weight: var(--font-weight-medium); white-space: nowrap; }

/* -- Protocol builder -- */
.field-row { display: flex; gap: 8px; align-items: flex-start; }
.field-row-item { flex: 1; min-width: 140px; }
.form-row { display: flex; gap: 8px; align-items: flex-end; flex-wrap: wrap; }
.form-divider { margin: 16px 0; border: none; border-top: 1px solid var(--border); }
.rule-card {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 10px 12px; margin-bottom: 12px;
}
.rule-card-head { display: flex; align-items: center; gap: 4px; margin-bottom: 6px; }
.rule-add-form {
  margin-top: 8px; padding: 10px 12px;
  border: 1px dashed var(--border); border-radius: var(--radius);
}
.cross-add-form {
  gap: 8px; align-items: flex-end; flex-wrap: wrap;
  padding-top: 8px; margin-top: 4px;
}
.checkbox-label { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.checkbox-label-sm { display: flex; align-items: center; gap: 6px; cursor: pointer; font-size: var(--text-base); }
.radio-label { display: flex; align-items: center; gap: 4px; cursor: pointer; }
.ref-image-thumb {
  width: 60px; height: 60px; object-fit: cover;
  border-radius: var(--radius-sm); border: 1px solid var(--border); flex-shrink: 0;
}
/* Per-structure heading switch in the builder structure header. Reuses the
   toggle-switch visual (.setting-toggle-input) from the protocol settings card,
   wrapped in a compact pill that sits inline beside the row actions and tints
   when on, so each structure's heading state reads at a glance. */
.heading-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 5px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface-raised);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-normal);
  color: var(--text-muted);
  white-space: nowrap;
  cursor: pointer;
  transition: border-color var(--transition-fast), background var(--transition-fast), color var(--transition-fast);
}
.heading-toggle:hover { border-color: var(--primary); }
.heading-toggle:has(.setting-toggle-input:checked) {
  border-color: var(--primary);
  background: var(--primary-surface);
  color: var(--primary);
}
.heading-toggle-text { font-weight: var(--font-weight-medium); }

/* Protocol settings: boolean output options as labelled toggle switches.
   Two-or-more identical rows, so one rule drives both. */
.settings-options-label {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-muted);
  margin-bottom: 10px;
}
.settings-options {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 12px;
}
.setting-toggle {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  cursor: pointer;
  transition: border-color var(--transition-fast), background var(--transition-fast);
}
.setting-toggle:hover { border-color: var(--primary); }
/* Tint the whole row when its option is on, so state reads at a glance.
   The switch carries the state on its own where :has is unsupported. */
.setting-toggle:has(.setting-toggle-input:checked) {
  border-color: var(--primary);
  background: var(--primary-surface);
}
.setting-toggle-input {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  width: 40px;
  height: 22px;
  margin: 1px 0 0;
  border-radius: var(--radius-pill);
  background: var(--border);
  cursor: pointer;
  position: relative;
  transition: background var(--transition-fast);
}
.setting-toggle-input::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--text-on-accent);
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-fast);
}
.setting-toggle-input:checked { background: var(--primary); }
.setting-toggle-input:checked::before { transform: translateX(18px); }
.setting-toggle-input:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.setting-toggle-body { display: flex; flex-direction: column; gap: 2px; }
.setting-toggle-title { font-weight: var(--font-weight-medium); color: var(--text); }
.setting-toggle-desc {
  font-size: var(--text-sm); color: var(--text-muted);
  line-height: var(--line-height-snug);
}

/* Form-group sizing (finding_edit / reference_edit field grids) */
.fg-xxs { min-width: 80px; }
.fg-xs  { min-width: 90px; max-width: 120px; }
.fg-sm  { min-width: 120px; flex: 1; }
.fg-md  { min-width: 160px; flex: 1; }
.fg-lg  { min-width: 190px; flex: 1; }
.fg-xl  { min-width: 280px; flex: 1; }
.fg-fit { min-width: 150px; }
.fg-cond { flex: 1; min-width: 140px; }
.fg-cond-sm { flex: 1; min-width: 100px; }
.fg-0   { margin: 0; }

/* Input widths */
.input-quick-entry { width: 170px; font-size: var(--text-sm); }
.input-quick-entry-sm { width: 130px; font-size: var(--text-sm); }
.input-dims { width: 76px; }
.input-dims-sm { width: 68px; }
.input-ga { width: 64px; }
.input-date { width: 170px; }
.input-color {
  width: 28px; height: 24px; padding: 1px;
  border: 1px solid var(--border); border-radius: var(--radius-xs); cursor: pointer;
}
.input-range { width: 70px; cursor: pointer; }

/* Axis labels editor */
.axis-labels-editor .axis-preset { margin-bottom: 6px; }
.axis-inputs {
  display: flex; gap: 4px; align-items: center; flex-wrap: wrap;
}
.axis-chip {
  display: inline-flex; align-items: center; gap: 2px;
}
.axis-chip input {
  width: 60px; padding: 4px 6px; text-align: center;
  font-size: var(--text-base);
}
.axis-chip-remove {
  background: none; border: none; cursor: pointer;
  color: var(--text-muted); font-size: var(--text-base); line-height: var(--line-height-none);
  padding: 0 2px;
}
.axis-chip-remove:hover { color: var(--danger); }
.axis-add-btn {
  background: none; border: none; cursor: pointer;
  color: var(--primary); font-size: var(--text-sm); padding: 4px 6px;
}
.axis-add-btn:hover { text-decoration: underline; }
.axis-chip input.axis-chip-error {
  border-color: var(--danger);
}

/* Choices editor: "Sonographer sees" label + optional "Report draft" value rows */
/* Wider gap between option rows than within a row, so a row's optional hint
   line stays grouped with its own inputs and clearly separated from the next
   option. */
.choices-editor { display: flex; flex-direction: column; gap: 12px; }
.choice-head { display: flex; gap: 6px; }
.choice-head-label, .choice-head-value {
  font-size: var(--text-xs); color: var(--text-muted);
}
.choice-head-label { flex: 2; }
.choice-head-value { flex: 1; }
/* Room for the two trailing icon buttons (hint toggle + remove). */
.choice-head-spacer { width: 42px; }
/* Wrap so the optional hint input drops to a full-width second line; the tight
   row-gap keeps that hint line hugging its own row (see .choices-editor gap). */
.choice-row { display: flex; column-gap: 6px; row-gap: 3px; align-items: center; flex-wrap: wrap; }
.choice-row .choice-label { flex: 2; }
.choice-row .choice-value { flex: 1; }
.choice-row-remove,
.choice-hint-toggle {
  width: 18px; text-align: center; flex-shrink: 0;
  background: none; border: none; cursor: pointer;
  color: var(--text-muted); font-size: var(--text-base);
  line-height: var(--line-height-none); padding: 0;
}
.choice-row-remove:hover { color: var(--danger); }
.choice-hint-toggle { font-size: var(--text-sm); }
.choice-hint-toggle:hover { color: var(--primary); }
/* The hint input is the full-width second line of its row. */
.choice-row .choice-hint {
  flex-basis: 100%;
  font-size: var(--text-sm);
}
/* A hinted option's inputs and its hint line share one subtly shaded, padded
   block, so the hint unambiguously belongs to that option and not the row
   below. Only rows with a revealed hint are boxed; plain rows stay flush. */
.choice-row:has(.choice-hint:not(.hidden)) {
  background: var(--surface-alt);
  border-radius: var(--radius);
  padding: 8px;
}
.choice-add-btn {
  align-self: flex-start;
  background: none; border: none; cursor: pointer;
  color: var(--primary); font-size: var(--text-sm); padding: 4px 0;
}
.choice-add-btn:hover { text-decoration: underline; }

/* Placeholder picker: clickable "insert token" chips + live preview */
.placeholder-picker {
  display: flex; flex-wrap: wrap; gap: 4px;
  margin: 4px 0 6px;
}
.placeholder-chip {
  font-size: var(--text-xs);
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  background: var(--badge-sky-bg);
  color: var(--badge-sky-text);
  border: 1px solid transparent;
  cursor: pointer;
  line-height: var(--line-height-tight);
}
.placeholder-chip:hover {
  background: var(--primary-surface);
  color: var(--primary);
  border-color: var(--primary);
}
/* Singular/plural helper: dashed outline signals an editable template */
.placeholder-chip-cond {
  background: transparent;
  color: var(--badge-sky-text);
  border: 1px dashed var(--badge-sky-text);
}
.placeholder-chip-cond:hover {
  background: var(--primary-surface);
  color: var(--primary);
  border-color: var(--primary);
}
.placeholder-picker-label {
  align-self: center;
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.placeholder-preview {
  margin: 4px 0 6px;
  padding: 6px 10px;
  font-size: var(--text-sm);
  font-style: italic;
  color: var(--text-muted);
  background: var(--info-surface);
  border-left: 3px solid var(--info-border);
  border-radius: var(--radius-sm);
}
/* Caption via ::before so the JS innerHTML write never clears it */
.placeholder-preview::before {
  content: "Preview";
  display: block;
  margin-bottom: 2px;
  font-style: normal;
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: .04em;
}
/* Shown when the preview cannot reflect unsaved name/type edits yet */
.placeholder-preview-stale {
  border-left-color: var(--warning);
}
.placeholder-preview-stale::before {
  content: "Unsaved";
}

/* Max/min width constraints */
.max-w-xs  { max-width: 200px; }
.max-w-sm  { max-width: 240px; }
.max-w-md  { max-width: 280px; }
.max-w-lg  { max-width: 340px; }
.max-w-xl  { max-width: 560px; }

/* Finding edit page layout */
.finding-edit-main { flex: 1.2; min-width: 420px; }
.finding-edit-side { flex: 1; min-width: 280px; }

/* Sub-field edit panel */
.subedit-panel-open { width: 100%; padding: 10px; border-radius: var(--radius-sm); margin-top: 4px; }
/* Save/Cancel footer pinned to the end of the sub-field edit form */
.subedit-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

/* Card header annotation text */
.card-header-note { font-weight: normal; font-size: var(--text-sm); }

/* Badge variants */
.badge-light { font-weight: normal; }

/* Collapsed section body */
.collapse-body { padding-top: 10px; }
.cross-divider { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); }
.aggregation-row { gap: 14px; font-size: var(--text-base); }
.sub-gap { gap: 4px; }

/* Reference preview in builder */
.ref-preview {
  white-space: pre-line; max-height: 3.6em;
  overflow: hidden; max-width: 600px;
}

/* Border helpers */
.panel-border-top { border-top: 1px solid var(--border); }

/* -- Classification spec editor (finding editor) -- */
.classifier-editor { display: flex; flex-direction: column; gap: 10px; }
.classifier-editor-section { display: flex; flex-direction: column; gap: 8px; }
.classifier-editor-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.classifier-input-block {
  padding: 6px 10px; border: 1px solid var(--border);
  border-radius: var(--radius); background: var(--surface-alt);
}
.classifier-points-grid {
  display: grid; grid-template-columns: 1fr 80px;
  gap: 4px 10px; align-items: center; margin-top: 6px;
}
.classifier-points-option { font-size: var(--text-sm); color: var(--text-muted); }
.classifier-points-input { width: 80px; }
.classifier-category-card {
  padding: 8px 10px; border: 1px solid var(--border);
  border-radius: var(--radius); background: var(--surface-alt);
  display: flex; flex-direction: column; gap: 6px;
}
.classifier-label-input { flex: 1; min-width: 140px; }
.classifier-band-input { width: 90px; }
.classifier-conditions { display: flex; flex-direction: column; gap: 6px; }
.classifier-condition-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.classifier-condition-row select { max-width: 200px; }
/* "When"/"and" joiner word; fixed width keeps the selects aligned. */
.classifier-condition-joiner {
  font-size: var(--text-sm); color: var(--text-muted);
  min-width: 38px; text-align: right;
}
.classifier-prose-input { font-size: var(--text-sm); }
.classifier-missing-input { display: flex; align-items: center; gap: 8px; }

/* -- Calculated classification display -- */
.classification-display {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 6px 12px; border-radius: var(--radius);
  background: var(--surface-alt); border: 1px solid var(--border); min-width: 180px;
}
.classification-badge { padding: 8px 14px; }
.classification-pts { font-size: var(--text-2xl); font-weight: var(--font-weight-bold); color: var(--text-muted); }
.classification-pts-sm { font-size: var(--text-xl); font-weight: var(--font-weight-bold); color: var(--text-muted); }
.classification-label { font-size: var(--text-sm); color: var(--text-muted); }
.classification-active { border-color: var(--primary); background: var(--primary-surface); }
/* Mirrors .input-abnormal on inputs: the engine flagged this classification's line. */
.classification-display.input-abnormal { border-color: var(--danger); background: var(--danger-surface); }
.classification-display.input-abnormal .classification-label,
.classification-display.input-abnormal .classification-pts,
.classification-display.input-abnormal .classification-pts-sm { color: var(--danger-text); }

/* -- Canvas / annotation tools -- */
.blank-canvas-wrapper { display: flex; flex-direction: column; gap: 6px; max-width: 100%; }
.canvas-tools { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.canvas-draw { cursor: crosshair; }
.canvas-block { cursor: crosshair; display: block; max-width: 100%; }
.img-canvas { max-width: min(600px, 100%); display: block; }
.canvas-tool-label {
  font-size: var(--text-sm); color: var(--text-muted);
  display: flex; align-items: center; gap: 4px;
}
.canvas-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }

/* -- Keyboard help overlay -- */
.kb-overlay {
  position: fixed; bottom: 24px; right: 24px; z-index: 200;
  background: var(--overlay-surface); color: var(--overlay-text); border-radius: var(--radius-lg);
  padding: 16px 18px; font-size: var(--text-sm); line-height: var(--line-height-relaxed);
  box-shadow: 0 8px 40px rgba(0,0,0,.35); min-width: 260px;
}
.kb-overlay-header {
  font-weight: var(--font-weight-bold); font-size: var(--text-base); color: var(--overlay-heading);
  margin-bottom: 10px; display: flex;
  justify-content: space-between; align-items: center;
}
.kb-overlay-close {
  background: none; border: none; color: var(--overlay-muted);
  cursor: pointer; font-size: var(--text-2xl); line-height: var(--line-height-none); padding: 0 2px;
}
.kb-section-label {
  font-size: var(--text-xs); color: var(--overlay-subtle); text-transform: uppercase;
  letter-spacing: .05em; margin-bottom: 4px;
}
.kb-section-label-gap { margin-top: 8px; }

/* -- Reference panel -- */
.ref-name { font-weight: var(--font-weight-semibold); font-size: var(--text-base); }
.ref-text { font-size: var(--text-sm); line-height: var(--line-height-normal); }

/* -- Dimension inputs -- */
.dims-separator { color: var(--text-muted); font-size: var(--text-xl); }
.dims-label { font-size: var(--text-sm); color: var(--text-muted); min-width: 20px; }
.dims-unit { font-size: var(--text-sm); color: var(--text-muted); }
.dims-volume-label { font-style: italic; margin-left: 4px; }

/* -- Dashboard -- */
.dashboard-hero {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  background: var(--primary-surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--primary);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-4);
}
.dashboard-hero-title { font-size: var(--text-lg); font-weight: var(--font-weight-semibold); }
.dashboard-hero-sub { font-size: var(--text-sm); margin-top: 2px; }
.stat-card { flex: 1; min-width: 140px; }
.stat-card .card-body { text-align: center; }
.stat-value { font-size: var(--stat-value-size); font-weight: var(--font-weight-bold); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.stat-value-primary { color: var(--primary); }
.stat-value-warning { color: var(--warning); }
.stat-value-success { color: var(--success); }
.chart-card { flex: 2; min-width: 300px; }
.chart-area { height: 80px; }
.sidebar-card { flex: 1; min-width: 220px; }
.pagination-bar { display: flex; justify-content: center; gap: 6px; margin-top: 16px; flex-wrap: wrap; }
.chart-bar-col {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; gap: 3px; min-width: 0;
}
.chart-bar-count { font-size: var(--text-2xs); color: var(--text-muted); line-height: var(--line-height-none); }
.chart-bar {
  width: 100%; background: var(--primary);
  border-radius: var(--radius-xs) var(--radius-xs) 0 0; opacity: 0.85;
  /* Height is data-driven: JS sets --bar-ratio on each .chart-bar,
     and CSS scales it against --chart-bar-max-height. */
  height: calc(var(--bar-ratio, 0) * var(--chart-bar-max-height));
  min-height: 0;
}
.chart-bar.has-count { min-height: var(--chart-bar-min-height); }
.chart-bar-label {
  font-size: var(--text-2xs); color: var(--text-muted); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; width: 100%; text-align: center;
}
/* -- Report page -- */
.badge-finalized {
  background: var(--success-surface); color: var(--success-text);
  border: 1px solid var(--success-border);
  padding: 4px 10px; border-radius: var(--radius-sm); font-size: var(--text-base); font-weight: var(--font-weight-semibold);
}
.btn-disabled { opacity: 0.5; cursor: not-allowed; }
.disabled-row { opacity: 0.5; }
.report-img-col { display: flex; flex-direction: column; gap: 6px; max-width: 100%; }
.report-image-frame {
  position: relative; display: inline-block; line-height: 0;
  border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden;
}
.report-image-overlay {
  position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none;
}
.max-w-report { max-width: 1100px; }
.report-box-inline {
  min-height: 200px; border: none;
  border-radius: 0 0 var(--radius-md) var(--radius-md);
}
.report-box-preview {
  min-height: 300px; border: none;
  border-radius: 0 0 var(--radius-md) var(--radius-md);
}
/* Builder body: editing columns beside a pinned live preview. On wide
   screens the preview sticks to the right of the editing area so it stays
   visible while structures are edited; it drops below the editing columns
   on narrow screens (the 1024px block reorders it to the bottom). */
.builder-cols { display: flex; gap: var(--gap-md); align-items: flex-start; }
.builder-col-main { flex: 1.6; min-width: 0; }
.builder-col-side { flex: 1; min-width: 0; position: sticky; top: var(--sticky-offset); }
/* Builder's live-preview iframe: the real exam form, isolated in its own
   document. Full width with its own internal scroll. */
.builder-preview-frame {
  width: 100%;
  height: 75vh;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
/* Chrome-less embed layout (the iframe document) drops the app shell's
   max-width and centering so the form uses the full frame. */
.main-content-embed { padding: 16px; }
/* The exam form's sticky elements use top-offsets sized to clear the app
   topnav. The preview iframe has no topnav, so those offsets float them over
   the content. Disable sticky entirely inside the embed so the preview just
   scrolls. Covers every sticky element that can appear in the embedded form:
   the page heading, its action nav, the section-nav bar, the report column,
   and the error banner. */
.main-content-embed .page-heading,
.main-content-embed .action-nav,
.main-content-embed .section-nav-bar,
.main-content-embed .page-col-side,
.main-content-embed .error-banner {
  position: static;
  top: auto;
  max-height: none;
}
.finalize-overlay {
  position: fixed; inset: 0; background: rgba(0,0,0,.45); z-index: 200;
  display: flex; align-items: center; justify-content: center;
}
.finalize-modal {
  background: var(--surface); border-radius: var(--radius-md); padding: 28px 32px;
  max-width: 440px; width: 90%; box-shadow: 0 8px 30px rgba(0,0,0,.2);
}

/* -- Utilities -- */
/* Note: `.hidden` is declared at the end of this block so its `display: none`
   always wins against display-setting utilities (`.flex`, `.inline-flex`,
   `.d-block`, etc.) under equal specificity via source order. */
.flex { display: flex; }
.flex-col { display: flex; flex-direction: column; }
.flex-between { display: flex; justify-content: space-between; align-items: center; }
.flex-wrap { flex-wrap: wrap; }
.inline-flex { display: inline-flex; }
.items-center { align-items: center; }
.items-start { align-items: flex-start; }
.justify-center { justify-content: center; }
.flex-1 { flex: 1; }
.gap-1 { gap: var(--space-1); }
.gap-2 { gap: var(--space-2); }
.gap-3 { gap: var(--space-3); }
.gap-4 { gap: var(--space-4); }
.mt-1 { margin-top: var(--space-1); }
.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: var(--space-1); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }
.mb-5 { margin-bottom: var(--space-5); }
.mb-6 { margin-bottom: var(--space-6); }
.mr-2 { margin-right: var(--space-2); }
.mr-3 { margin-right: var(--space-3); }
.ml-auto { margin-left: auto; }
.p-0 { padding: 0; }
.p-3 { padding: var(--space-3); }
.p-4 { padding: var(--space-4); }
.p-6 { padding: var(--space-6); }
.px-3 { padding-left: var(--space-3); padding-right: var(--space-3); }
.py-2 { padding-top: var(--space-2); padding-bottom: var(--space-2); }
.text-xs { font-size: var(--text-xs); }
.text-sm { font-size: var(--text-sm); }
.text-base { font-size: var(--text-base); }
.text-lg { font-size: var(--text-lg); }
.text-xl { font-size: var(--text-xl); }
.text-2xl { font-size: var(--text-2xl); }
.text-center { text-align: center; }
.text-left { text-align: left; }
.text-right { text-align: right; }
.text-muted { color: var(--text-muted); }
.text-danger { color: var(--danger); }
.text-success { color: var(--success); }
.text-warning { color: var(--warning); }
.fw-500 { font-weight: var(--font-weight-medium); }
.fw-600 { font-weight: var(--font-weight-semibold); }
.fw-700 { font-weight: var(--font-weight-bold); }
.fw-normal { font-weight: var(--font-weight-normal); }
.lh-loose { line-height: var(--line-height-loose); }
.lh-normal { line-height: var(--line-height-normal); }
.text-13 { font-size: var(--text-base); }
.text-uppercase { text-transform: uppercase; letter-spacing: .03em; }
.w-100 { width: 100%; }
.w-auto { width: auto; }
.min-w-0 { min-width: 0; }
.ml-1 { margin-left: var(--space-1); }
.mr-1 { margin-right: var(--space-1); }
.px-1 { padding-left: var(--space-1); padding-right: var(--space-1); }
.pt-2 { padding-top: var(--space-2); }
.gap-5 { gap: var(--space-5); }
.border-b { border-bottom: 1px solid var(--border); }
.border-b-2 { border-bottom: 2px solid var(--border); }
.no-border { border: none; }
.nowrap { white-space: nowrap; }
.pointer { cursor: pointer; }
.justify-end { justify-content: flex-end; }
.flex-shrink-0 { flex-shrink: 0; }
.img-block { max-width: 100%; display: block; }
.pre-line { white-space: pre-line; }
.d-block { display: block; }
.hidden { display: none; }
.bg-none { background: none; }
.bg-white { background: #fff; }
.p-card { padding: 10px 16px; }
.missing-field-link { color: var(--danger-text); font-weight: var(--font-weight-semibold); text-decoration: underline; cursor: pointer; }
.badge-finalized-sm { padding: 4px 12px; font-size: var(--text-base); }
.inline-form { display: inline; }
.btn-reset { background: none; font: inherit; color: inherit; padding: 0; }
.btn-save { font-size: var(--text-lg); padding: 8px 20px; font-weight: var(--font-weight-semibold); }
.kb-row-divider { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--overlay-divider); }
.max-w-search { max-width: 220px; }
.max-w-date { max-width: 150px; }
.filter-field { display: flex; flex-direction: column; gap: 2px; }
.filter-field .form-label { margin: 0; }
.max-w-role { max-width: 140px; }
.max-w-uses { max-width: 72px; }
.max-w-form-sm { max-width: 420px; }
.max-w-form { max-width: 480px; }
.max-w-form-md { max-width: 500px; }
.max-w-content { max-width: 700px; }
.panel-main { flex: 1.5; min-width: 300px; }
.panel-side { flex: 1; min-width: 260px; }
.invite-border { border-color: var(--badge-sky-bg); }
.font-mono { font-family: var(--font-mono); }
.text-primary { color: var(--primary); }
.word-break-all { word-break: break-all; }
.auth-heading { font-size: var(--text-2xl); }
.center-card { margin: 40px auto; }
.p-10 { padding: 40px; }
.theme-toggle-btn { background: none; font-size: var(--text-lg); padding: 4px 8px; color: var(--overlay-text); }
.help-brand-link { color: var(--overlay-heading); }
.quick-pick-active { background: var(--primary); color: var(--primary-contrast); }
.help-header {
  background: var(--overlay-surface);
  color: var(--overlay-text);
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 52px;
  padding: 0 20px;
  position: sticky;
  top: 0;
  z-index: 100;
}
.help-header-brand {
  font-size: var(--text-xl);
  color: var(--overlay-heading);
}
.help-header-right { display: flex; align-items: center; gap: 12px; }
.help-container {
  max-width: 800px;
  margin: 0 auto;
  padding: 32px 20px 60px;
}
.py-half { padding-top: 2px; padding-bottom: 2px; }

/* -- Glove Mode -- larger touch targets for gloved / gel hands -- */
[data-glove-mode="true"] .btn-toggle { padding: 14px 24px; font-size: var(--text-xl); }
[data-glove-mode="true"] .btn-toggle-group { gap: 2px; }
[data-glove-mode="true"] .form-control { padding: 12px 14px; font-size: var(--text-xl); min-height: 48px; }
[data-glove-mode="true"] select.form-control { min-height: 48px; }
[data-glove-mode="true"] .btn { padding: 12px 20px; font-size: var(--text-lg); }
[data-glove-mode="true"] .btn-sm { padding: 10px 16px; font-size: var(--text-base); }
/* The nav-bar utility toggles (Glove Mode / Shortcuts) are chrome, not
   gloved data-entry targets. Keep them at the base .btn-sm size so the
   sticky bar does not grow an extra row in glove mode. */
[data-glove-mode="true"] .section-nav-bar .btn-sm { padding: 4px 10px; font-size: var(--text-sm); }
[data-glove-mode="true"] .exam-finding { padding: 18px 16px; }
/* Glove mode is for touch entry: one column keeps targets large and distinct */
[data-glove-mode="true"] .exam-structure-body { grid-template-columns: 1fr; }
[data-glove-mode="true"] .exam-finding-label { font-size: var(--text-lg); margin-bottom: 10px; }
[data-glove-mode="true"] .section-nav-chip { padding: 8px 16px; font-size: var(--text-base); }
[data-glove-mode="true"] .instance-block { padding: 16px; }
[data-glove-mode="true"] .instance-compact { padding: 12px 14px; }
[data-glove-mode="true"] .instance-grid { gap: 10px 12px; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
[data-glove-mode="true"] .instance-grid-cell .form-control { font-size: var(--text-xl); padding: 10px 12px; min-height: 44px; }
[data-glove-mode="true"] .instance-grid-label { font-size: var(--text-base); }
[data-glove-mode="true"] .instance-remove { padding: 6px 10px; font-size: var(--text-base); }
[data-glove-mode="true"] .dims-axis-input { min-height: 44px; }
[data-glove-mode="true"] .tech-comment-summary { padding: 10px 0; font-size: var(--text-lg); }
[data-glove-mode="true"] .tech-comment-input { min-height: 48px; }
#glove-mode-btn.active,
#glove-mode-btn[aria-pressed="true"] {
  background: var(--primary); color: var(--primary-contrast); border-color: var(--primary);
}
#glove-mode-btn.active:hover,
#glove-mode-btn[aria-pressed="true"]:hover {
  background: var(--primary-dark);
}

/* Print header -- hidden on screen, shown on print */
.print-header { display: none; }

/* Worksheet styling */
.worksheet-structure { border-bottom: 1px solid var(--border); }
.worksheet-structure:last-child { border-bottom: none; }
.worksheet-structure-name {
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sm);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .03em;
  padding: 8px 16px 4px;
  background: var(--surface-alt);
}
.worksheet-entry {
  display: flex;
  padding: 4px 16px;
  font-size: var(--text-base);
  gap: 8px;
}
.worksheet-entry-name {
  color: var(--text-muted);
  flex-shrink: 0;
  min-width: 140px;
}
.worksheet-entry-name::after { content: ':'; }
.worksheet-entry-value { color: var(--text); }
/* Sub-field rows sit indented under their parent entry; the name width
   shrinks by the indent so values stay aligned with parent values. */
.worksheet-entry-sub { padding-left: 32px; }
.worksheet-entry-sub .worksheet-entry-name { min-width: 124px; }
/* Inline tech comment row: amber italic, matching the Sonographer Comments
   card tone so it reads as a note, not an entered value. The warning tokens
   carry their own dark overrides. */
.worksheet-entry-comment .worksheet-entry-name,
.worksheet-entry-comment .worksheet-entry-value {
  color: var(--text-warning);
  font-style: italic;
}
/* A group row (multi-instance instance header) has no value, so no colon. */
.worksheet-entry-group .worksheet-entry-name::after { content: none; }

@media print {
  /* Print sizing intentionally uses pt (physical paper units), not the
     px-based screen type scale, so it is excluded from the design tokens. */
  /* Hide all UI chrome */
  .no-print, .topnav, .page-heading, .messages { display: none !important; }

  /* Reset page */
  html, body {
    background: #fff !important;
    color: #000 !important;
    font-family: 'Georgia', 'Times New Roman', serif;
    font-size: 11pt;
    line-height: var(--line-height-normal);
  }
  .app-shell, .main-content, .page-body { padding: 0 !important; margin: 0 !important; }
  .page-body { max-width: 100% !important; }

  /* Single-column print layout */
  .report-layout { display: block; max-width: 100% !important; }
  .report-col-main, .report-col-side { display: block; }
  .report-section-comments { margin-top: 0 !important; }

  /* Cards: clean borders for print */
  .card {
    border: none !important;
    box-shadow: none !important;
    background: #fff !important;
    page-break-inside: avoid;
  }
  .card + .card, .card.mt-3 { margin-top: 18pt !important; }
  .card-header {
    border-bottom: 1.5pt solid #999 !important;
    font-weight: var(--font-weight-bold);
    font-size: 10pt;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0 0 4pt !important;
    background: none !important;
    color: #000 !important;
  }
  .card-body { padding: 8pt 0 !important; }

  /* Print header */
  .print-header {
    display: block !important;
    margin-bottom: 20pt;
    border-bottom: 2pt solid #000;
    padding-bottom: 10pt;
  }
  .print-header-title {
    font-family: 'Georgia', 'Times New Roman', serif;
    font-size: 18pt;
    font-weight: var(--font-weight-bold);
    margin-bottom: 8pt;
    letter-spacing: 0.02em;
  }
  .print-header-exam-title {
    font-family: 'Georgia', 'Times New Roman', serif;
    font-size: 14pt;
    font-weight: var(--font-weight-semibold);
    margin: -4pt 0 8pt;
    letter-spacing: 0.02em;
  }
  .print-header-meta {
    font-size: 9.5pt;
    border-collapse: collapse;
    width: 100%;
  }
  .print-header-meta td { padding: 2pt 14pt 2pt 0; }
  .print-header-meta strong { font-weight: var(--font-weight-bold); }

  /* Report body text */
  .report-box {
    border: none !important;
    background: #fff !important;
    padding: 0 !important;
    min-height: unset !important;
  }
  .report-doc {
    color: #000 !important;
    font-family: 'Georgia', 'Times New Roman', serif;
    font-size: 11pt;
    line-height: var(--line-height-relaxed);
  }
  .report-section { margin-bottom: 12pt; page-break-inside: avoid; }
  .report-section-impression .report-line { min-height: 24pt; }
  .report-section-heading {
    background: none !important;
    border-left: 3pt solid #000 !important;
    color: #000 !important;
    padding: 2pt 8pt !important;
    font-family: var(--font-sans);
    font-size: 10pt;
    font-weight: var(--font-weight-bold);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 6pt;
  }
  .report-line {
    font-size: 11pt;
    line-height: var(--line-height-relaxed);
    padding: 1pt 0;
  }
  .abnormal-value { color: var(--danger) !important; font-weight: var(--font-weight-bold) !important; }

  /* Images */
  img { max-width: 100% !important; page-break-inside: avoid; }
  .report-section-images .card-body { gap: 12pt !important; }

  /* Worksheet -- compact two-column reference. The structures flow into two
     columns to cut the page count, and each value sits at the right edge of
     its column instead of stretching a write-on line across the whole page.
     Structures MAY split across a column break: break-inside: avoid on a
     block taller than one column hangs WeasyPrint's column layout in an
     endless placement loop (Generate PDF never returns), so only the
     heading is kept with the first row below it. */
  .worksheet-columns {
    column-count: 2;
    column-gap: 22pt;
  }
  .worksheet-structure {
    margin: 0 0 7pt;
  }
  .worksheet-structure-name {
    /* A column never ends on a bare structure name. */
    break-after: avoid;
    background: none !important;
    color: #000 !important;
    font-weight: var(--font-weight-bold);
    border-bottom: 0.75pt solid #999;
    font-size: 9.5pt;
    letter-spacing: 0.04em;
    padding: 2pt 0;
  }
  .worksheet-entry {
    font-size: 10pt;
    padding: 1pt 0;
    /* Block instead of flex: WeasyPrint cannot break a flex row across a
       column, so one text value wrapping taller than a column would hang
       the same placement loop an unbreakable structure did. A floated
       name plus right-aligned value text keeps the name-left/value-right
       look while long values stay breakable. */
    display: block;
    text-align: right;
  }
  /* Clears the floated name; also gives group rows (name only, no value)
     their height. */
  .worksheet-entry::after { content: ''; display: block; clear: both; }
  /* Name and value sit at opposite edges of the column; no colon or write
     line, so short values (No, 2 mm) do not waste a full-width row. */
  .worksheet-entry-name {
    color: #333 !important;
    float: left;
    text-align: left;
    min-width: 0;
  }
  .worksheet-entry-name::after { content: none; }
  .worksheet-entry-value { color: #000 !important; }
  .worksheet-entry-sub { padding-left: 12pt; }
  /* A comment can be long; left-align it so it reads as a sentence instead
     of a right-edge value. Italic (from the screen rule) marks it as a note
     in the monochrome print. */
  .worksheet-entry-comment { justify-content: flex-start; }
  .worksheet-entry-comment .worksheet-entry-value { text-align: left; }

  /* Sonographer comments */
  .tech-comment-card { border-color: #ccc !important; }
  .tech-comment-card .card-header { background: none !important; color: #000 !important; }

  /* Page setup */
  @page { margin: 20mm 18mm 20mm 18mm; }
}
