:root {
  /* Cool neutral technical palette */
  --bg: #eceff3;
  --panel: #ffffff;
  --panel-strong: #ffffff;
  --surface-2: #f3f5f8;
  --line: #d4dae1;
  --line-strong: #aeb7c2;
  --text: #1b2733;
  --muted: #57626f;
  --accent: #0d6b78;
  --accent-soft: #dbeef1;
  --accent-strong: #0a5862;
  --warm: #9d5324;
  --warm-strong: #8b4b1f;
  --warm-soft: #f3e2d4;

  /* Ink that sits on saturated accent/-strong FILLS (primary buttons, active
     tabs/pills, the startup banner). White in light; near-black in dark, where
     the accent is a light tint and white ink fails AA (DESIGN-REVIEW-2026-07
     F2) - the fill keeps its color, the ink flips. */
  --fill-ink: #ffffff;

  /* Channel triplets of the tokens above, for alpha tints. Need a translucent
     tint of a token? Write rgba(var(--X-rgb), a) - never restate the RGB. */
  --text-rgb: 27, 39, 51;
  --accent-rgb: 13, 107, 120;
  --warm-strong-rgb: 139, 75, 31;

  /* Tooltip / inverse-surface ground: a dark chip with white ink in BOTH
     themes. Its own token (not --text) so Q9 dark mode can restyle the chip
     without inverting --text - whose -rgb twin also backs the table edge-fade
     and must track --text. Light values equal the old --text ground (no
     visual change); dark mode overrides both below. */
  --tooltip-bg: #1b2733;
  --tooltip-bg-rgb: 27, 39, 51;

  /* Sketch "paper": the 2D CAD/colour sheet is a light drawing document that
     stays light in BOTH themes (Q13) - its black INK/DIM_INK linework must sit
     on light paper, and the HQ/PNG/print artifacts are always white. Not
     overridden in the dark blocks below; in dark mode the sheet reads as a
     document floating on the dark panel "mat". */
  --sketch-paper: #ffffff;
  --sketch-paper-edge: #cbd3dc;

  /* Semantic status palette — success / caution / error. Use these (never
     raw hexes) for pass/fail verdicts, stale/error states, and status dots. */
  --ok: #15733d;
  --ok-strong: #176b3b;
  --ok-soft: #e6f4ea;
  --warn: #95590f;
  --warn-strong: #7b401b;
  --warn-soft: #f7edda;
  --danger: #b23327;
  --danger-strong: #8a2c1c;
  --danger-soft: #fbe3df;
  --danger-rgb: 178, 51, 39;

  /* Spacing scale */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 48px;

  /* Radius scale */
  --radius: 7px;
  --radius-sm: 5px;
  --radius-lg: 12px;
  --radius-pill: 999px;

  /* Right-corner room the header keeps clear for the fixed .session-bar
     (username + role + actions). A flex spacer consumes it, not a padding
     hack; it collapses when the bar goes static on narrow screens. */
  --session-bar-clearance: 172px;

  /* Type scale */
  --fs-xs: 0.72rem;
  --fs-sm: 0.8125rem;
  --fs-base: 0.875rem;
  --fs-lg: 1rem;
  --fs-h1: 1.35rem;
  --fs-h2: 1.1rem;
  --fs-h3: 0.95rem;

  --shadow: 0 1px 2px rgba(20, 30, 45, 0.08);
  --shadow-soft: 0 1px 3px rgba(20, 30, 45, 0.06);
}

/*
 * Dark mode (Q9 of PREMIUM-QUALITY-PLAN-2026-07). TOKEN LAYER ONLY: every rule
 * below overrides a :root custom property, so the whole app themes with no
 * per-component dark rules. The same override block is applied two ways:
 *
 *   - @media (prefers-color-scheme: dark) :root:not([data-theme="light"])
 *       OS-auto dark, unless the user has forced light via the toggle.
 *   - :root[data-theme="dark"]
 *       manual dark, winning even under an OS light preference.
 *
 * The manual toggle (session bar) stamps data-theme + persists it in
 * localStorage; when nothing is stored, no attribute is set and the media
 * query alone governs. The two selectors carry an identical body - keep them
 * in sync. Reports/print (CO2 report, sketch CAD sheet) stay light by design.
 *
 * The status -strong tints invert their role for dark: in light they are dark
 * INK on a pale -soft ground; in dark the -soft grounds go deep and -strong
 * becomes the LIGHT ink on them. Where accent/-strong is instead a filled
 * background (primary buttons + hover, active tabs, the startup banner), the
 * text on it comes from --fill-ink - white in light, near-black here - so the
 * fill keeps AA contrast in both themes (DESIGN-REVIEW-2026-07 F2; this
 * retired the old "weak white on light -strong" trade-off). --*-rgb twins
 * track their tokens so alpha tints stay on-palette.
 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0e141b;
    --surface-2: #151d26;
    --panel: #1b242e;
    --panel-strong: #212c37;
    --line: #303b47;
    --line-strong: #47535f;
    --text: #e7edf3;
    --muted: #9aa6b3;
    --text-rgb: 231, 237, 243;

    --accent: #30abbc;
    --accent-soft: #123840;
    --accent-strong: #4fb3c1;
    --accent-rgb: 48, 171, 188;
    --fill-ink: #10161c;

    --warm: #d98a4f;
    --warm-strong: #e0a56e;
    --warm-soft: #3a2a1b;
    --warm-strong-rgb: 224, 165, 110;

    --ok: #46b877;
    --ok-strong: #6fd39a;
    --ok-soft: #14301f;
    --warn: #d99a3f;
    --warn-strong: #e6b775;
    --warn-soft: #33260f;
    --danger: #e5675a;
    --danger-strong: #f0958b;
    --danger-soft: #3a1d1a;
    --danger-rgb: 229, 103, 90;

    --tooltip-bg: #2a343f;
    --tooltip-bg-rgb: 42, 52, 63;

    --shadow: 0 1px 2px rgba(0, 0, 0, 0.44);
    --shadow-soft: 0 1px 3px rgba(0, 0, 0, 0.34);
  }
}

:root[data-theme="dark"] {
  --bg: #0e141b;
  --surface-2: #151d26;
  --panel: #1b242e;
  --panel-strong: #212c37;
  --line: #303b47;
  --line-strong: #47535f;
  --text: #e7edf3;
  --muted: #9aa6b3;
  --text-rgb: 231, 237, 243;

  --accent: #30abbc;
  --accent-soft: #123840;
  --accent-strong: #4fb3c1;
  --accent-rgb: 48, 171, 188;
  --fill-ink: #10161c;

  --warm: #d98a4f;
  --warm-strong: #e0a56e;
  --warm-soft: #3a2a1b;
  --warm-strong-rgb: 224, 165, 110;

  --ok: #46b877;
  --ok-strong: #6fd39a;
  --ok-soft: #14301f;
  --warn: #d99a3f;
  --warn-strong: #e6b775;
  --warn-soft: #33260f;
  --danger: #e5675a;
  --danger-strong: #f0958b;
  --danger-soft: #3a1d1a;
  --danger-rgb: 229, 103, 90;

  --tooltip-bg: #2a343f;
  --tooltip-bg-rgb: 42, 52, 63;

  --shadow: 0 1px 2px rgba(0, 0, 0, 0.44);
  --shadow-soft: 0 1px 3px rgba(0, 0, 0, 0.34);
}


/*
 * ===== Named palettes (R6 of DESIGN-REVIEW-2026-07) ==========================
 * data-palette on <html> selects a palette; ABSENT = the default Field Teal
 * palette above. Palettes COMPOSE with the light/dark mode machinery: each has
 * a light block plus the same two dark selectors as the base theme (OS-auto
 * and manual), which win by specificity over both the base dark blocks and
 * the palette's own light block. Every palette block overrides the SAME
 * property set (color families + their --X-rgb twins + --fill-ink +
 * --tooltip-bg); anything else (spacing, radii, shadows, sketch paper) falls
 * through to the base theme - shadows deliberately resolve from the base dark
 * blocks in dark mode. The palette light/dark blocks must stay
 * property-identical (enforced by dark-sync.test.js) and every ink/ground
 * pair AA-clean per palette (enforced by token-contrast.test.js). The picker
 * lives in the session bar (app.js initThemeToggle); the choice persists in
 * localStorage["ev2-palette-v1"] and is pre-paint-stamped by the index.html
 * head script (CSP-hash coupled - see server.py _DEFAULT_CSP).
 */

/* ----- Graphite — neutral enterprise; steel-blue accent ----- */
:root[data-palette="graphite"] {
  --bg: #f0f1f3;
  --surface-2: #f4f5f7;
  --panel: #ffffff;
  --panel-strong: #ffffff;
  --line: #d7dade;
  --line-strong: #b0b6bd;
  --text: #1d2530;
  --text-rgb: 29, 37, 48;
  --muted: #57626e;
  --accent: #3d4d61;
  --accent-rgb: 61, 77, 97;
  --accent-soft: #e4e9ef;
  --accent-strong: #2c3a4b;
  --warm: #9d5324;
  --warm-strong: #8b4b1f;
  --warm-strong-rgb: 139, 75, 31;
  --warm-soft: #f3e6da;
  --ok: #15733d;
  --ok-strong: #176b3b;
  --ok-soft: #e6f4ea;
  --warn: #95590f;
  --warn-strong: #7b401b;
  --warn-soft: #f7edda;
  --danger: #b23327;
  --danger-rgb: 178, 51, 39;
  --danger-strong: #8a2c1c;
  --danger-soft: #fbe3df;
  --fill-ink: #ffffff;
  --tooltip-bg: #1d2530;
  --tooltip-bg-rgb: 29, 37, 48;
}
@media (prefers-color-scheme: dark) {
  :root[data-palette="graphite"]:not([data-theme="light"]) {
    --bg: #111418;
    --surface-2: #15191f;
    --panel: #1a1f26;
    --panel-strong: #212832;
    --line: #2e353e;
    --line-strong: #454e59;
    --text: #e6eaef;
    --text-rgb: 230, 234, 239;
    --muted: #9aa3ae;
    --accent: #93aac4;
    --accent-rgb: 147, 170, 196;
    --accent-soft: #242e3a;
    --accent-strong: #b3c6da;
    --warm: #d98a4f;
    --warm-strong: #e0a56e;
    --warm-strong-rgb: 224, 165, 110;
    --warm-soft: #332817;
    --ok: #4bbd7c;
    --ok-strong: #6fd39a;
    --ok-soft: #14301f;
    --warn: #d9a04a;
    --warn-strong: #e6b775;
    --warn-soft: #33260f;
    --danger: #e56d60;
    --danger-rgb: 229, 109, 96;
    --danger-strong: #f0958b;
    --danger-soft: #3a1d1a;
    --fill-ink: #10161c;
    --tooltip-bg: #262e38;
    --tooltip-bg-rgb: 38, 46, 56;
  }
}
:root[data-palette="graphite"][data-theme="dark"] {
  --bg: #111418;
  --surface-2: #15191f;
  --panel: #1a1f26;
  --panel-strong: #212832;
  --line: #2e353e;
  --line-strong: #454e59;
  --text: #e6eaef;
  --text-rgb: 230, 234, 239;
  --muted: #9aa3ae;
  --accent: #93aac4;
  --accent-rgb: 147, 170, 196;
  --accent-soft: #242e3a;
  --accent-strong: #b3c6da;
  --warm: #d98a4f;
  --warm-strong: #e0a56e;
  --warm-strong-rgb: 224, 165, 110;
  --warm-soft: #332817;
  --ok: #4bbd7c;
  --ok-strong: #6fd39a;
  --ok-soft: #14301f;
  --warn: #d9a04a;
  --warn-strong: #e6b775;
  --warn-soft: #33260f;
  --danger: #e56d60;
  --danger-rgb: 229, 109, 96;
  --danger-strong: #f0958b;
  --danger-soft: #3a1d1a;
  --fill-ink: #10161c;
  --tooltip-bg: #262e38;
  --tooltip-bg-rgb: 38, 46, 56;
}

/* ----- Indigo — modern SaaS; violet-blue accent ----- */
:root[data-palette="indigo"] {
  --bg: #eef0f6;
  --surface-2: #f4f5fa;
  --panel: #ffffff;
  --panel-strong: #ffffff;
  --line: #d6dae6;
  --line-strong: #aeb5c9;
  --text: #1c2333;
  --text-rgb: 28, 35, 51;
  --muted: #59627a;
  --accent: #4552c7;
  --accent-rgb: 69, 82, 199;
  --accent-soft: #e4e7fb;
  --accent-strong: #3742a0;
  --warm: #9d5324;
  --warm-strong: #8b4b1f;
  --warm-strong-rgb: 139, 75, 31;
  --warm-soft: #f3e4d6;
  --ok: #15733d;
  --ok-strong: #176b3b;
  --ok-soft: #e6f4ea;
  --warn: #95590f;
  --warn-strong: #7b401b;
  --warn-soft: #f7edda;
  --danger: #b23327;
  --danger-rgb: 178, 51, 39;
  --danger-strong: #8a2c1c;
  --danger-soft: #fbe3df;
  --fill-ink: #ffffff;
  --tooltip-bg: #1c2333;
  --tooltip-bg-rgb: 28, 35, 51;
}
@media (prefers-color-scheme: dark) {
  :root[data-palette="indigo"]:not([data-theme="light"]) {
    --bg: #101322;
    --surface-2: #14172a;
    --panel: #191d31;
    --panel-strong: #202640;
    --line: #2b3150;
    --line-strong: #434b6e;
    --text: #e7e9f3;
    --text-rgb: 231, 233, 243;
    --muted: #9ba3b8;
    --accent: #94a3f2;
    --accent-rgb: 148, 163, 242;
    --accent-soft: #252b4d;
    --accent-strong: #b3bdf6;
    --warm: #d99a5f;
    --warm-strong: #e0ac78;
    --warm-strong-rgb: 224, 172, 120;
    --warm-soft: #33251a;
    --ok: #4bbd7c;
    --ok-strong: #6fd39a;
    --ok-soft: #14301f;
    --warn: #d9a04a;
    --warn-strong: #e6b775;
    --warn-soft: #33260f;
    --danger: #e56d60;
    --danger-rgb: 229, 109, 96;
    --danger-strong: #f0958b;
    --danger-soft: #3a1d1a;
    --fill-ink: #10131f;
    --tooltip-bg: #272d49;
    --tooltip-bg-rgb: 39, 45, 73;
  }
}
:root[data-palette="indigo"][data-theme="dark"] {
  --bg: #101322;
  --surface-2: #14172a;
  --panel: #191d31;
  --panel-strong: #202640;
  --line: #2b3150;
  --line-strong: #434b6e;
  --text: #e7e9f3;
  --text-rgb: 231, 233, 243;
  --muted: #9ba3b8;
  --accent: #94a3f2;
  --accent-rgb: 148, 163, 242;
  --accent-soft: #252b4d;
  --accent-strong: #b3bdf6;
  --warm: #d99a5f;
  --warm-strong: #e0ac78;
  --warm-strong-rgb: 224, 172, 120;
  --warm-soft: #33251a;
  --ok: #4bbd7c;
  --ok-strong: #6fd39a;
  --ok-soft: #14301f;
  --warn: #d9a04a;
  --warn-strong: #e6b775;
  --warn-soft: #33260f;
  --danger: #e56d60;
  --danger-rgb: 229, 109, 96;
  --danger-strong: #f0958b;
  --danger-soft: #3a1d1a;
  --fill-ink: #10131f;
  --tooltip-bg: #272d49;
  --tooltip-bg-rgb: 39, 45, 73;
}

/* ----- High Contrast — pure grounds, near-black ink, heavier lines ----- */
:root[data-palette="contrast"] {
  --bg: #ffffff;
  --surface-2: #f2f2f2;
  --panel: #ffffff;
  --panel-strong: #ffffff;
  --line: #8a929c;
  --line-strong: #4d545c;
  --text: #0d1117;
  --text-rgb: 13, 17, 23;
  --muted: #3d444d;
  --accent: #0a4d57;
  --accent-rgb: 10, 77, 87;
  --accent-soft: #d4eef2;
  --accent-strong: #06343b;
  --warm: #8a4415;
  --warm-strong: #6b3d0d;
  --warm-strong-rgb: 107, 61, 13;
  --warm-soft: #f3e2d4;
  --ok: #0e5e30;
  --ok-strong: #0b4c27;
  --ok-soft: #e6f4ea;
  --warn: #6b3d0d;
  --warn-strong: #59330b;
  --warn-soft: #f7edda;
  --danger: #98261b;
  --danger-rgb: 152, 38, 27;
  --danger-strong: #7a1f15;
  --danger-soft: #fbe3df;
  --fill-ink: #ffffff;
  --tooltip-bg: #0d1117;
  --tooltip-bg-rgb: 13, 17, 23;
}
@media (prefers-color-scheme: dark) {
  :root[data-palette="contrast"]:not([data-theme="light"]) {
    --bg: #000000;
    --surface-2: #161b22;
    --panel: #0d1117;
    --panel-strong: #161b22;
    --line: #4d545c;
    --line-strong: #8a929c;
    --text: #f5f8fa;
    --text-rgb: 245, 248, 250;
    --muted: #b8c2cc;
    --accent: #4fd0e2;
    --accent-rgb: 79, 208, 226;
    --accent-soft: #0f3a42;
    --accent-strong: #8ae0ec;
    --warm: #e8a55c;
    --warm-strong: #f0bc80;
    --warm-strong-rgb: 240, 188, 128;
    --warm-soft: #33260f;
    --ok: #57d68d;
    --ok-strong: #7ee3aa;
    --ok-soft: #14301f;
    --warn: #e8b45c;
    --warn-strong: #f0c780;
    --warn-soft: #33260f;
    --danger: #f28b7f;
    --danger-rgb: 242, 139, 127;
    --danger-strong: #f6aca3;
    --danger-soft: #3a1d1a;
    --fill-ink: #00171c;
    --tooltip-bg: #1c232b;
    --tooltip-bg-rgb: 28, 35, 43;
  }
}
:root[data-palette="contrast"][data-theme="dark"] {
  --bg: #000000;
  --surface-2: #161b22;
  --panel: #0d1117;
  --panel-strong: #161b22;
  --line: #4d545c;
  --line-strong: #8a929c;
  --text: #f5f8fa;
  --text-rgb: 245, 248, 250;
  --muted: #b8c2cc;
  --accent: #4fd0e2;
  --accent-rgb: 79, 208, 226;
  --accent-soft: #0f3a42;
  --accent-strong: #8ae0ec;
  --warm: #e8a55c;
  --warm-strong: #f0bc80;
  --warm-strong-rgb: 240, 188, 128;
  --warm-soft: #33260f;
  --ok: #57d68d;
  --ok-strong: #7ee3aa;
  --ok-soft: #14301f;
  --warn: #e8b45c;
  --warn-strong: #f0c780;
  --warn-soft: #33260f;
  --danger: #f28b7f;
  --danger-rgb: 242, 139, 127;
  --danger-strong: #f6aca3;
  --danger-soft: #3a1d1a;
  --fill-ink: #00171c;
  --tooltip-bg: #1c232b;
  --tooltip-bg-rgb: 28, 35, 43;
}

* {
  box-sizing: border-box;
}

/* The hidden attribute always wins. Any author `display:` on a class beats the
   UA's `[hidden] { display: none }` (author rules outrank UA rules regardless
   of specificity), which has repeatedly leaked "hidden" elements into the page
   - an inert Autosave toggle, and an empty .pw-tag (#country-drift) rendering
   as an orange band behind the EV2 Project Materials card. This global rule
   makes `hidden` an invariant; the older per-class [hidden] guards below are
   now redundant defense. */
[hidden] {
  display: none !important;
}

/* The page must never scroll horizontally (DESIGN.md) - wide content scrolls
   inside its own wrapper. This backstop makes that an invariant: a positioned
   box poking past the right edge (e.g. an open .has-help bubble on a phone)
   otherwise inflates the page's scroll width, and iOS Safari then lets the
   whole page zoom out to the inflated width - the "app squeezed into 60% of
   the screen" state. `clip` (unlike `hidden`) creates no scroll container, so
   the sticky tab nav is unaffected; `hidden` is the fallback for engines
   without `clip`. */
html {
  overflow-x: hidden;
  overflow-x: clip;
}

body {
  margin: 0;
  font-family: "Source Sans 3", sans-serif;
  font-size: var(--fs-base);
  line-height: 1.45;
  color: var(--text);
  background: var(--bg);
}

.page-shell {
  width: min(1400px, calc(100vw - 32px));
  margin: 0 auto;
  padding: var(--space-4) 0 var(--space-7);
}

.project-gate {
  min-height: 100vh;
  padding: var(--space-7) var(--space-4);
}

.project-gate[hidden],
.page-shell[hidden] {
  display: none !important;
}

.project-gate-inner {
  width: min(1180px, 100%);
  margin: 0 auto;
}

.project-gate-copy {
  padding: var(--space-6) 0;
}

.project-choice-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
  align-items: stretch;
}

.project-choice-card,
.project-bar {
  border: 1px solid var(--line);
  background: var(--panel);
  box-shadow: var(--shadow);
}

.project-choice-card {
  display: grid;
  align-content: start;
  gap: 14px;
  padding: var(--space-5);
  border-radius: var(--radius);
}

.project-choice-card p,
.project-meta {
  margin: 0;
  color: var(--muted);
  font-weight: 600;
}

.choice-card-header {
  display: flex;
  align-items: center;
  gap: 12px;
}

.choice-card-header h2 {
  margin: 0;
}

.choice-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--fill-ink);
  font-family: "Space Grotesk", sans-serif;
  font-weight: 700;
}

.project-form,
.saved-projects-list {
  display: grid;
  gap: 12px;
}

/* Full-width "Start new project" card: lay the form out as one horizontal row
   so the card stays short. Falls back to wrapping on narrow screens. */
.project-form-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-end;
}

.project-form-row .field {
  flex: 1 1 220px;
  min-width: 0;
}

.project-form-row .field-note {
  flex-basis: 100%;
  order: 1; /* keep the note on its own line below the input row */
  margin: 0;
}

.storage-note {
  color: var(--muted);
  font-weight: 700;
}

.project-bar {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  align-items: center;
  margin-top: var(--space-4);
  padding: var(--space-4);
  border-radius: var(--radius);
}

.project-bar strong {
  display: block;
  margin-top: 4px;
  font-family: "Space Grotesk", sans-serif;
  font-size: var(--fs-h2);
}

.project-bar-actions,
.saved-project-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* Inside the projects table, keep both buttons on the row's single line. */
.saved-projects-table .saved-project-actions {
  flex-wrap: nowrap;
  justify-content: flex-end;
}

.project-save-status {
  color: var(--accent);
  font-weight: 700;
}

/* Transient "Saved ✓" confirmation after a successful save (Q4). */
.project-save-status.is-flash {
  color: var(--ok);
}

/* Unresolved save conflict — the status reads as a caution, next to the two
   recovery actions. */
.project-save-status.is-warn {
  color: var(--warn-strong);
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes save-status-flash-in {
    from { opacity: 0; }
    to { opacity: 1; }
  }

  .project-save-status.is-flash {
    animation: save-status-flash-in 0.3s ease-out;
  }
}

.project-conflict-actions {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.autosave-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 600;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

/* The display above beats the UA's [hidden] { display: none } (author rules
   win over UA rules), so without this the toggle renders even after app.js
   hides it - e.g. an inert Autosave checkbox in a "Just calc" session. */
.autosave-toggle[hidden] {
  display: none;
}

.autosave-toggle input {
  cursor: pointer;
  accent-color: var(--accent);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.saved-projects-search {
  display: block;
  margin: 0;
}

.saved-projects-search input {
  width: 100%;
}

.saved-projects-empty-search {
  margin: 0;
  padding: 14px;
  color: var(--muted);
  font-weight: 600;
}

.saved-projects-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  box-shadow: var(--shadow);
}

.saved-projects-trash {
  display: grid;
  gap: 10px;
  border-top: 1px solid var(--line);
  padding-top: 12px;
}

.saved-projects-trash > summary {
  cursor: pointer;
  font-weight: 700;
  color: var(--muted);
}

.saved-projects-trash-count {
  font-weight: 600;
}

.saved-projects-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}

.saved-projects-table th,
.saved-projects-table td {
  padding: 10px 14px;
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;
  border-bottom: 1px solid var(--line);
}

.saved-projects-table thead th {
  position: sticky;
  top: 0;
  background: var(--panel);
  color: var(--muted);
  font-family: "Space Grotesk", sans-serif;
  font-weight: 700;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.saved-projects-table tbody tr:last-child th,
.saved-projects-table tbody tr:last-child td {
  border-bottom: none;
}

.saved-projects-table tbody tr:hover {
  background: var(--accent-soft);
}

.saved-projects-table tbody th[scope="row"] {
  font-family: "Space Grotesk", sans-serif;
  font-weight: 700;
}

.saved-projects-table td {
  color: var(--muted);
  font-weight: 600;
}

.saved-projects-actions-col {
  width: 1%;
}

/* ===== Q11: shared page anatomy (DESIGN.md §7) =====
   Structural slots every tool view follows, in order:
   [.tool-link-banner] -> .tool-header -> inputs -> .tool-actions
   (holding the .tool-status line) -> .tool-results.
   The classes ride alongside each tool's own classes; this block sits
   deliberately EARLY in the stylesheet so per-tool rules win ties — it is
   only the default a NEW tool inherits before writing any CSS of its own.
   .tool-header / .tool-results / .tool-link-banner are structural markers
   (styling stays per-tool). Enforced by tests/js/anatomy.test.js. */
.tool-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* ===== Reports hub ===== */
.reports-panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.reports-heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
}

.reports-heading p {
  margin: var(--space-1) 0 0;
  color: var(--muted);
  max-width: 70ch;
}

.reports-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  box-shadow: var(--shadow);
}

.reports-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}

.reports-table th,
.reports-table td {
  padding: 12px 16px;
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--line);
}

.reports-table thead th {
  background: var(--panel);
  color: var(--muted);
  font-family: "Space Grotesk", sans-serif;
  font-weight: 700;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

.reports-table tbody tr:last-child th,
.reports-table tbody tr:last-child td {
  border-bottom: none;
}

.reports-table tbody tr:hover {
  background: var(--accent-soft);
}

.reports-table tbody th[scope="row"] {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.reports-row-label {
  font-family: "Space Grotesk", sans-serif;
  font-weight: 700;
  color: var(--text);
}

.reports-row-sub {
  font-size: var(--fs-xs);
  color: var(--muted);
  font-weight: 600;
}

.reports-table td {
  color: var(--muted);
  font-weight: 600;
  white-space: nowrap;
}

.reports-action-col {
  width: 1%;
}

.reports-source-link {
  border: none;
  background: none;
  padding: 0;
  color: var(--accent);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.reports-source-link:hover {
  color: var(--accent-strong);
}

.reports-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 700;
  white-space: nowrap;
}

.reports-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: none;
  background: var(--line-strong);
}

.reports-status-ready { color: var(--accent-strong); }
.reports-status-ready .reports-dot { background: var(--ok); }

.reports-status-stale { color: var(--warm); }
.reports-status-stale .reports-dot { background: var(--warm); }

.reports-status-empty { color: var(--muted); }
.reports-status-empty .reports-dot { background: var(--line-strong); }

.reports-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.reports-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin: 0;
  font-size: var(--fs-xs);
}

@media (max-width: 640px) {
  .reports-footer {
    flex-direction: column;
    align-items: stretch;
  }
}

.tab-nav {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  gap: var(--space-1);
  margin: var(--space-3) 0 0;
  padding: var(--space-2) 0;
  flex-wrap: wrap;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}

/* One tab language for the whole suite: the top-level nav (.tab-button) plus
   the panel sub-tab pills, which all carry the .subtab component class (R1 of
   DESIGN-REVIEW-2026-07: one class instead of four per-tool selector groups).
   The per-tool names (.ev2-subtab, .co2-subtab, .sketch-view-tab,
   .mif-chart-tab) remain in the markup as JS behavior hooks only — no CSS
   binds to them anymore. */
/* On a short viewport (a phone held in landscape: ~330-430px of visible
   height) the sticky row would permanently pin a large share of the screen -
   let the nav scroll away with the page there instead. Portrait keeps the
   sticky one-tap row. */
@media (max-height: 500px) {
  .tab-nav {
    position: static;
  }
}

.tab-button,
.subtab {
  cursor: pointer;
  font-family: "Space Grotesk", sans-serif;
  color: var(--muted);
  user-select: none;
}

.tab-button {
  border: 1px solid transparent;
  background: transparent;
  border-radius: var(--radius-sm);
  padding: 7px 13px;
  font-weight: 600;
  font-size: var(--fs-sm);
}

.tab-button:hover {
  background: var(--surface-2);
  color: var(--text);
}

.subtab {
  padding: 9px 18px;
  border: 1px solid var(--line);
  background: var(--panel);
  font-weight: 700;
  border-radius: var(--radius-pill);
}

.tab-button.active,
.subtab.active {
  background: var(--accent);
  color: var(--fill-ink);
  border-color: var(--accent);
}

/* Action menu: one trigger button that drops a stacked list of related actions
   (e.g. the Sketch tab's four export formats). A native <details> disclosure -
   keyboard accessible with no JS required to open; Ev2Util.initActionMenu adds
   the expected menu behaviors (close on selection / outside click / Escape).
   Style the <summary> by giving it the usual .button classes. Add .drop-up
   when the menu sits in a bottom-anchored bar so the list opens upward. */
.action-menu {
  position: relative;
  display: inline-block;
}

.action-menu > summary {
  /* UA default is list-item (full-width block in a flex column) - render it
     like the .button it carries. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  list-style: none;
}

.action-menu > summary::-webkit-details-marker {
  display: none;
}

.action-menu-list {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 50;
  display: grid;
  gap: 4px;
  min-width: 180px;
  padding: 6px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 10px 24px rgba(var(--accent-rgb), 0.18);
}

.action-menu.drop-up .action-menu-list {
  top: auto;
  bottom: calc(100% + 6px);
}

.action-menu-list .button {
  width: 100%;
  text-align: left;
}

.tab-panel {
  margin-top: var(--space-4);
}

.tab-panel[hidden] {
  display: none !important;
}

.app-header {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  box-shadow: var(--shadow);
}

/* Reserve the fixed session bar's top-right corner with a flex spacer pushed
   to the right edge (margin-left:auto) instead of a hardcoded padding-right.
   Header content stays left; the spacer collapses at the breakpoint where the
   session bar leaves fixed positioning (see the max-width: 820px block). */
.app-header::after {
  content: "";
  flex: 0 0 var(--session-bar-clearance);
  align-self: stretch;
  margin-left: auto;
}

.app-header-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

/* PRS brand mark — persistent across the suite. The source PNG has a white
   background, so it sits flush on white panels and is framed as a card on
   the tinted gate screens. */
.prs-logo {
  display: block;
  height: 64px;
  width: auto;
  flex-shrink: 0;
}

.gate-logo {
  height: 64px;
  margin-bottom: 8px;
  padding: 12px 16px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  box-sizing: content-box;
}

@media (max-width: 640px) {
  .prs-logo {
    height: 48px;
  }
}

.app-header h1 {
  font-size: var(--fs-h1);
  line-height: 1.15;
  max-width: none;
}

.app-header .eyebrow {
  margin: 0;
}

.app-header-sub {
  margin: 0;
  color: var(--muted);
  font-size: var(--fs-sm);
}

.eyebrow,
.stat-label,
.field span,
.chart-heading p,
.panel-heading p,
.hero-text,
.layer-hint,
.method-card li {
  color: var(--muted);
}

.eyebrow {
  margin: 0 0 4px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: var(--fs-xs);
  font-weight: 700;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  font-family: "Space Grotesk", sans-serif;
}

h1 {
  font-size: var(--fs-h1);
  line-height: 1.1;
  max-width: none;
}

h2 {
  font-size: var(--fs-h2);
}

h3 {
  font-size: var(--fs-h3);
}

.hero-text {
  margin: 8px 0 0;
  max-width: 72ch;
  font-size: var(--fs-base);
}

.panel,
.chart-card,
.method-card {
  border: 1px solid var(--line);
  background: var(--panel);
  box-shadow: var(--shadow);
}

.layout {
  display: grid;
  grid-template-columns: minmax(340px, 460px) minmax(0, 1fr);
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.calculator-flow {
  display: grid;
  grid-template-columns: minmax(280px, 320px) minmax(0, 1fr);
  gap: var(--space-3);
  margin-top: var(--space-4);
  padding-bottom: 76px;
  align-items: start;
}

.calculator-flow > .controls-panel {
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: start;
}

.calculator-flow > .results-panel {
  grid-column: 2;
  grid-row: 1;
}

@media (max-width: 1000px) {
  .calculator-flow {
    /* minmax(0, 1fr), not 1fr: a bare 1fr track keeps an `auto` minimum and
       grows to the widest table's content, pushing the page sideways. The 0
       minimum lets the stacked panels shrink so their table wrappers scroll. */
    grid-template-columns: minmax(0, 1fr);
  }

  .calculator-flow > .controls-panel,
  .calculator-flow > .results-panel {
    grid-column: 1;
    grid-row: auto;
    min-width: 0;
  }
}

/* Floating action cluster (the SHARED .tool-actions position, DESIGN.md par.7):
   a tab's primary action + exports + status float bottom-right, always
   reachable on long pages. Formerly EV2-only (.calc-fab-bar); any tool's
   .tool-actions row opts in by carrying this class. A hidden ancestor panel
   hides the bar with it ([hidden] => display:none), so only the active tab's
   bar shows. A subtle backing keeps the ghost buttons legible above scrolling
   content. */
.tool-fab-bar {
  position: fixed;
  bottom: calc(var(--space-5) + env(safe-area-inset-bottom, 0px));
  right: calc(var(--space-5) + env(safe-area-inset-right, 0px));
  z-index: 45;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: calc(var(--radius) + 8px);
  box-shadow: 0 8px 22px rgba(var(--accent-rgb), 0.22);
}

.tool-fab-bar > .button {
  min-width: 0;
}

.tool-fab-bar > .button.primary {
  padding: 10px 22px;
  font-size: var(--fs-base);
  border-radius: var(--radius);
  box-shadow: 0 6px 18px rgba(var(--accent-rgb), 0.32);
}

.tool-fab-bar > .button.primary:hover {
  transform: translateY(-1px);
}

/* Q3: the calculator/report status line shares the fab bar with the export
   buttons - cap it so long error copy wraps instead of stretching the bar.
   (Empty-state hiding moved to the global .tool-status:empty rule, Q11.) */
.tool-fab-bar > .tool-status {
  max-width: 320px;
  text-align: right;
}

.panel,
.method-card {
  border-radius: var(--radius);
  padding: var(--space-4);
}

.panel-heading {
  margin-bottom: var(--space-3);
}

.panel-heading.compact {
  margin-top: var(--space-4);
  margin-bottom: var(--space-2);
}

.controls-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-3);
}

.optimization-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

/* Plain-language optimization questionnaire */
.optimizer-mode {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px;
  margin-bottom: var(--space-4);
}

.optimizer-mode-option {
  display: grid;
  gap: 4px;
  padding: 14px 16px;
  border-radius: var(--radius-lg);
  border: 1.5px solid var(--line);
  background: var(--panel-strong);
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}

.optimizer-mode-option:hover {
  border-color: var(--line-strong);
}

.optimizer-mode-option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  /* Clip the visually-hidden radio to 1px so its intrinsic box can't extend
     the page's scroll width on narrow screens (the label + :has() carry all
     the visuals; the input stays focusable). */
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.optimizer-mode-option:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: 0 0 0 1px var(--accent) inset;
}

.optimizer-mode-option:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.optimizer-mode-title {
  font-weight: 700;
  color: var(--text);
}

.optimizer-mode-sub {
  font-size: var(--fs-sm);
  color: var(--muted);
}

.questionnaire {
  display: grid;
  gap: var(--space-4);
}

.question-block {
  border: none;
  margin: 0;
  padding: 0;
}

.question-block legend {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0;
  margin-bottom: 12px;
  font-size: var(--fs-h2);
  font-weight: 700;
  color: var(--text);
}

.question-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--fill-ink);
  font-size: var(--fs-base);
  font-weight: 700;
}

.choice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
}

.choice-card {
  display: grid;
  gap: 4px;
  padding: 14px 16px;
  border-radius: var(--radius-lg);
  border: 1.5px solid var(--line);
  background: var(--panel-strong);
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}

.choice-card:hover {
  border-color: var(--line-strong);
}

.choice-card input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  /* Clip the visually-hidden radio to 1px (see .optimizer-mode-option input):
     an unsized absolute input takes a viewport-wide intrinsic box that pushes
     the questionnaire sideways on narrow screens. */
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.choice-card:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: 0 0 0 1px var(--accent) inset;
}

.choice-card:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.choice-title {
  font-weight: 700;
  font-size: var(--fs-lg);
}

.choice-sub {
  font-size: var(--fs-sm);
  color: var(--muted);
}

.opt-custom-cbr-field {
  margin-top: 12px;
  max-width: 220px;
}

.material-checkboxes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px;
}

.material-checkbox {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-radius: var(--radius-lg);
  border: 1.5px solid var(--line);
  background: var(--panel-strong);
  cursor: pointer;
  font-weight: 600;
}

.material-checkbox:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.material-checkbox input {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
}

.advanced-panel {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-2);
  padding: 0 16px;
}

.advanced-panel summary {
  cursor: pointer;
  padding: 14px 0;
  font-weight: 700;
  color: var(--accent);
  list-style-position: inside;
}

.advanced-content {
  padding-bottom: 16px;
  display: grid;
  gap: 14px;
}

.advanced-note {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--muted);
}

.advanced-subhead {
  margin: 6px 0 0;
  font-size: var(--fs-lg);
}

.field {
  display: grid;
  gap: var(--space-1);
}

.field span {
  font-size: var(--fs-sm);
  font-weight: 600;
}

input,
select,
button {
  font: inherit;
}

input,
select {
  width: 100%;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--text);
  font-size: var(--fs-sm);
}

/* Checkboxes/radios opt out of the text-field sizing above. width: 100% is
   harmless in a shrink-wrapped desktop label, but in a stretched mobile label
   (the <=720px one-column .project-bar-actions grid) the box balloons to fill
   the row and shoves its own label text past the right viewport edge - the
   measured "Autosave at the side" overflow on iPhone. */
input[type="checkbox"],
input[type="radio"] {
  width: auto;
  padding: 0;
}

input:focus,
select:focus {
  outline: 2px solid rgba(var(--accent-rgb), 0.18);
  border-color: var(--accent);
}

/* Numeric fields only ever hold a few digits — don't let them stretch */
input[type="number"] {
  max-width: 160px;
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: var(--space-3) 0 var(--space-4);
}

.toolbar .button,
.scenario-toolbar .button {
  flex: 1 1 180px;
}

.collapsible {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  overflow: hidden;
}

.collapsible > summary {
  cursor: pointer;
  list-style: none;
  padding: 9px 14px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  position: relative;
}

.collapsible > summary::-webkit-details-marker {
  display: none;
}

.collapsible > summary::after {
  content: "";
  position: absolute;
  right: 20px;
  top: 18px;
  width: 9px;
  height: 9px;
  border-right: 2px solid var(--line-strong);
  border-bottom: 2px solid var(--line-strong);
  transform: rotate(45deg);
  transition: transform 0.2s ease;
}

.collapsible[open] > summary::after {
  transform: rotate(-135deg);
}

.collapsible-title {
  font-family: "Space Grotesk", sans-serif;
  font-weight: 700;
  font-size: var(--fs-h2);
}

.collapsible-hint {
  color: var(--muted);
  font-size: var(--fs-base);
  padding-right: var(--space-6);
}

.collapsible > *:not(summary) {
  margin: 0 var(--space-4) var(--space-4);
}

.sketch-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 14px;
  align-items: flex-end;
}

.sketch-source-field {
  flex: 1 1 220px;
}

.sketch-source-field select {
  width: 100%;
}

.scenario-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 16px;
}

.scenario-list {
  display: grid;
  gap: 12px;
}

.scenario-card {
  padding: 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--panel);
  cursor: pointer;
}

.scenario-card:hover {
  border-color: rgba(var(--accent-rgb), 0.4);
}

.suite-link {
  margin-top: 12px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  border: 1px dashed var(--accent);
  background: var(--accent-soft);
}

.suite-link-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 8px;
}

.suite-link-title {
  font-weight: 600;
  color: var(--accent-strong);
}

.suite-link-hint {
  font-size: var(--fs-sm);
  color: var(--muted);
}

.suite-link-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

@media (max-width: 560px) {
  .suite-link-row {
    grid-template-columns: 1fr;
  }
}

.co2-link-banner {
  margin: 0 0 14px;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--surface-2);
}

.co2-link-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

/* The scenario-link consumer badge (scenario-consumer.js renders it in every
   consumer tab's banner — CO2, Unpaved, Load Distribution, Sketch; renamed
   from the .co2-link-status misnomer in R2 of DESIGN-REVIEW-2026-07). */
.link-status {
  font-size: var(--fs-base);
  color: var(--muted);
}

.link-status.fresh {
  color: var(--accent-strong);
}

.link-status.stale {
  color: var(--warn);
  font-weight: 600;
}

.scenario-card.active {
  border-color: rgba(var(--accent-rgb), 0.6);
  box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), 0.15);
}

.scenario-card-top,
.scenario-actions {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: center;
}

.scenario-select {
  padding: 0;
  border: none;
  background: transparent;
  color: var(--text);
  font-family: "Space Grotesk", sans-serif;
  font-size: var(--fs-lg);
  font-weight: 700;
  text-align: left;
  cursor: pointer;
}

.scenario-visibility {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--muted);
  font-weight: 600;
}

.scenario-visibility input {
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
}

.scenario-meta {
  margin: 8px 0 12px;
  color: var(--muted);
  font-size: var(--fs-base);
}

.optimization-materials {
  display: grid;
  gap: 12px;
}

.material-row {
  display: grid;
  grid-template-columns: 1.2fr auto 120px;
  gap: 14px;
  align-items: end;
  padding: 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--panel);
}

.material-include {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
}

.material-include input {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
}

.material-meta {
  color: var(--muted);
  font-weight: 600;
}

.toggle {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: var(--space-4);
  color: var(--muted);
  font-weight: 600;
}

.toggle input {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
}

.button {
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 7px 14px;
  font-weight: 600;
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease, opacity 140ms ease;
}

.button:hover:not(:disabled) {
  opacity: 0.9;
}

.button.primary {
  background: var(--accent);
  color: var(--fill-ink);
}

.button.primary:hover:not(:disabled) {
  background: var(--accent-strong);
  opacity: 1;
}

.button.secondary {
  background: var(--surface-2);
  border-color: var(--line);
  color: var(--text);
}

.button.secondary:hover:not(:disabled) {
  background: var(--panel);
  border-color: var(--line-strong);
  opacity: 1;
}

.button.ghost,
.button.tiny {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--text);
}

.button.tiny {
  padding: 5px 10px;
  font-size: var(--fs-xs);
}

/* Q2 (PREMIUM-QUALITY-PLAN-2026-07.md): shared feedback states on every button. */
.button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* The same ring on the tab/pill/segment families, which are not .button and
   used to fall back to the browser default (inconsistent across engines) -
   DESIGN-REVIEW-2026-07 F7. One ring language everywhere. */
.tab-button:focus-visible,
.subtab:focus-visible,
.sketch-style-opt:focus-visible,
.let-seg:focus-visible,
.unpaved-mode-btn:focus-visible,
.bearing-units-btn:focus-visible,
.skip-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Skip link (DESIGN-REVIEW-2026-07 F7): first tab stop, visually hidden until
   focused; app.js points it at the active tool panel. Token-styled chip. */
.skip-link {
  position: fixed;
  top: var(--space-2);
  left: var(--space-2);
  z-index: 2000;
  padding: 8px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--accent);
  background: var(--panel);
  color: var(--text);
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: none;
  transform: translateY(-200%);
}

.skip-link:focus-visible {
  transform: none;
}

.button:active:not(:disabled) {
  transform: translateY(1px);
}

.button:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* The busy spinner: Ev2Util.createBusy stamps .is-busy on the buttons it
   disables while a server call is in flight. The ring renders even under
   reduced motion (a static busy marker); only the rotation is gated. */
.button.is-busy::after {
  content: "";
  display: inline-block;
  width: 0.85em;
  height: 0.85em;
  margin-left: 8px;
  vertical-align: -0.12em;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  opacity: 0.8;
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes busy-spin {
    to { transform: rotate(360deg); }
  }

  .button.is-busy::after {
    animation: busy-spin 700ms linear infinite;
  }
}

.layers-header {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  align-items: end;
  margin-bottom: var(--space-2);
}

.layers-container {
  margin-bottom: var(--space-3);
}

/* One editable table per scenario (the active one + every scenario marked Compare) */
.scenario-editor + .scenario-editor {
  margin-top: var(--space-4);
}

.scenario-editor-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}

.scenario-editor-title {
  padding: 0;
  border: none;
  background: transparent;
  color: var(--text);
  font-family: "Space Grotesk", sans-serif;
  font-size: var(--fs-h2);
  font-weight: 700;
  text-align: left;
  cursor: pointer;
}

.scenario-editor:not(.active) .scenario-editor-title:hover {
  color: var(--accent-strong);
  text-decoration: underline;
}

.scenario-editor-badge {
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  background: rgba(var(--accent-rgb), 0.14);
  color: var(--accent-strong);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.scenario-editor-toolbar {
  margin-top: 10px;
}

/* Woven-geotextile interface toggle: a per-scenario control under the layer
   table (injected by app.js, not part of the shared LayerEditor). */
.scenario-geotextile {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  margin-top: 10px;
  padding: var(--space-2) var(--space-3);
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  font-size: var(--fs-base);
}
.geotextile-toggle-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
}
.geotextile-pct-label {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--muted);
}
.geotextile-pct {
  width: 4.5rem;
}
.summary-note {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--muted);
}

.project-materials-table {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: var(--space-2);
}
.project-materials-table th,
.project-materials-table td {
  padding: var(--space-1) var(--space-2);
  text-align: left;
  vertical-align: middle;
}
.project-materials-table th {
  font-size: var(--fs-sm);
  color: var(--muted);
  font-weight: 600;
}
.project-materials-table .pm-cbr-col {
  width: 8rem;
}
.project-materials-table .pm-name,
.project-materials-table .pm-cbr {
  width: 100%;
}

/* ===== UNIFIED LAYER EDITOR TABLE (B1) ===== */
.layer-editor-wrapper {
  overflow-x: auto;
}

.layer-editor-table {
  width: 100%;
  min-width: 720px;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

.layer-editor-table thead th {
  background: rgba(var(--accent-rgb), 0.08);
  font-family: "Space Grotesk", sans-serif;
  text-align: left;
  padding: 6px 8px;
  font-size: var(--fs-sm);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

/* Group header row: "Inputs" vs "Computed EV2" */
.layer-grouprow th {
  font-size: var(--fs-xs);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  background: transparent;
  border-bottom: none;
  padding-bottom: 2px;
}

.layer-grouprow .grp-editable {
  color: var(--accent);
}

.layer-grouprow .grp-computed {
  color: var(--warm-strong);
  border-left: 2px solid var(--line);
}

.layer-grouprow .grp-blank {
  background: transparent;
}

/* Heavier divider separating editable inputs from computed columns */
.layer-headrow .col-computed,
.layer-editor-table tbody .layer-cell-computed {
  border-left: 2px solid var(--line);
}

.layer-editor-table tbody td {
  padding: 5px 8px;
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-sm);
  vertical-align: middle;
}

.layer-editor-table select,
.layer-editor-table input {
  width: 100%;
  min-width: 0;
  padding: 5px 7px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  font-size: var(--fs-sm);
  font-family: inherit;
}

.layer-cell-narrow {
  width: 88px;
}

.layer-cell-narrow input {
  text-align: right;
}

.layer-cell-index {
  white-space: nowrap;
  font-weight: 600;
  color: var(--muted);
}

.layer-cell-computed {
  text-align: right;
  font-weight: 600;
  background: rgba(var(--warm-strong-rgb), 0.05);
}

/* Dim the computed columns while inputs are ahead of the last calc */
.layer-editor-table.is-stale .layer-cell-computed {
  opacity: 0.4;
}

.layer-cell-handle {
  width: 28px;
  text-align: center;
  padding-left: 4px;
  padding-right: 0;
}

.layer-drag-handle {
  border: none;
  background: transparent;
  color: var(--muted);
  cursor: grab;
  font-size: var(--fs-lg);
  line-height: 1;
  padding: 2px 4px;
}

.layer-drag-handle:active {
  cursor: grabbing;
}

.layer-cell-actions {
  width: 34px;
  text-align: center;
}

.remove-layer {
  padding: 2px 8px;
}

.layer-row.dragging {
  opacity: 0.4;
}

.layer-row.drop-before td {
  box-shadow: inset 0 2px 0 0 var(--accent);
}

.layer-row.drop-after td {
  box-shadow: inset 0 -2px 0 0 var(--accent);
}

/* Pinned, read-only subgrade row at the base of the stack */
.subgrade-row td {
  background: rgba(var(--accent-rgb), 0.06);
}

.subgrade-row .layer-cell-index {
  color: var(--accent-strong);
}

.pill.subgrade {
  background: rgba(var(--accent-rgb), 0.16);
  color: var(--accent-strong);
}

.layer-thickness:read-only {
  background: rgba(0, 0, 0, 0.05);
  color: var(--muted);
  cursor: not-allowed;
}

/* Inline reinforcement expander sub-row */
.layer-expander-cell {
  background: rgba(var(--accent-rgb), 0.03);
  padding: 8px 10px 12px !important;
}

.layer-expander-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: var(--space-3);
}

.layer-expander-inner > .field {
  flex: 0 0 auto;
  width: 190px;
}

.layer-expander-inner > .field:has(.layer-neoloy-overfill) {
  width: 110px;
}

.layer-hint {
  flex: 1 1 260px;
  margin: 0;
  align-self: center;
  font-size: var(--fs-sm);
  color: var(--muted);
}

/* The author display:grid would otherwise beat the UA [hidden] rule, leaving the
   single-scenario cards visible in comparison mode. */
.summary-cards[hidden] {
  display: none !important;
}

.summary-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.summary-card {
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--surface-2);
}

.summary-card strong {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-h2);
  font-variant-numeric: tabular-nums;
}

.table-wrapper {
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
}

table {
  width: 100%;
  border-collapse: collapse;
  min-width: 760px;
  font-variant-numeric: tabular-nums;
}

th,
td {
  padding: 5px 10px;
  text-align: left;
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-sm);
}

th {
  font-family: "Space Grotesk", sans-serif;
  background: rgba(var(--accent-rgb), 0.08);
}

.chart-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin-top: var(--space-4);
}

.chart-card {
  border-radius: var(--radius);
  padding: var(--space-4);
}

.chart-heading {
  margin-bottom: 12px;
}

.chart-body {
  min-height: 380px;
  overflow-x: auto;
}

.chart-body svg {
  width: 100%;
  height: auto;
  display: block;
}

.method-card {
  margin-top: var(--space-4);
}

.method-card ul {
  margin: 12px 0 0;
  padding-left: var(--space-4);
}

.comparison-section {
  display: grid;
  gap: var(--space-4);
}

.comparison-table table {
  min-width: 980px;
}

.comparison-insights {
  margin-top: 0;
}

.optimization-results {
  display: grid;
  gap: 16px;
  margin-top: var(--space-4);
}

.optimization-card {
  padding: var(--space-4);
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--panel);
}

.optimization-card.recommended {
  border-color: rgba(var(--accent-rgb), 0.55);
  box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), 0.12);
}

.optimization-card-top {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  align-items: center;
}

.optimization-badge {
  display: inline-flex;
  align-items: center;
  padding: 6px 10px;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent-strong);
  font-size: var(--fs-sm);
  font-weight: 700;
}

.optimization-metrics {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  margin: 16px 0;
}

.optimization-metric {
  padding: 12px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}

.optimization-metric strong {
  display: block;
  margin-top: 6px;
  font-size: var(--fs-h2);
}

.optimization-layer-list {
  display: grid;
  gap: 10px;
}

.optimization-layer-item {
  display: grid;
  grid-template-columns: 110px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--panel);
  border: 1px solid var(--line);
}

.optimization-layer-item p {
  margin: 0;
  color: var(--muted);
}

.optimization-layer-item .pill {
  justify-self: start;
}

.optimization-insights {
  margin-top: 0;
}

.optimization-insights ul {
  margin: 12px 0 0;
  padding-left: var(--space-4);
}

.sketch-table-wrapper input {
  width: 100%;
  min-width: 160px;
}

/* The dark "mat" the sheet sits on: --surface-2 recesses slightly behind the
   white paper in both themes, so the drawing reads as a framed document (Q13). */
.sketch-canvas-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  padding: var(--space-4);
}

/* The drawing sheet: always-light paper (--sketch-paper) with an edge + shadow
   so the black CAD linework is legible on the dark mat as well as the light. */
#sketch-svg {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  background: var(--sketch-paper);
  border: 1px solid var(--sketch-paper-edge);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}

.sketch-total-thickness {
  font-size: var(--fs-h2);
  font-weight: 700;
  margin: 14px 0 12px;
}

.sketch-legend {
  margin-top: 16px;
  font-size: var(--fs-lg);
  line-height: 1.5;
}

/* ===== Sketch tab: editable layer table ===== */
.sketch-table-wrapper table {
  width: 100%;
}

.sketch-table-wrapper select,
.sketch-table-wrapper input[type="number"] {
  width: 100%;
  min-width: 0;
}

.sketch-table-wrapper .hatch-select,
.sketch-table-wrapper .density-select {
  min-width: 84px;
}

.sketch-table-wrapper button {
  padding: 4px 10px;
}

.sketch-table-wrapper button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ===== Sketch tab: 2D / 3D sub-tabs ===== */
.sketch-view-tabs {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 12px;
}

/* .sketch-view-tab is a JS behavior hook only - the pill styling is the shared
   .subtab component (one tab language next to .tab-button). */

/* Sketch tab: drawing title-block editor */
.sketch-titleblock {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  padding: 10px 14px;
  margin: 4px 0 8px;
}

.sketch-titleblock > summary {
  cursor: pointer;
  font-weight: 700;
  font-size: var(--fs-lg);
  color: var(--accent-strong);
}

.sketch-titleblock-hint {
  margin: 6px 0 12px;
  font-size: var(--fs-sm);
  color: var(--muted);
}

.sketch-titleblock-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 10px 14px;
}

.sketch-titleblock-grid .field span {
  font-size: var(--fs-xs);
  font-weight: 600;
}

/* 2D presentation-style toggle (CAD vs Colour). The options are shared .subtab
   pills (same component as the 2D/3D tabs beside them); "Style" is a plain
   caption OUTSIDE any pill so it cannot read as a third, clickable option. */
.sketch-style-toggle {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.sketch-style-label {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.sketch-view-panel {
  display: none;
}

.sketch-view-panel.active {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  flex-wrap: wrap;
}

/* ===== Sketch tab: 2D notes ===== */
.sketch-notes-wrap {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1 1 320px;
}

#sketch-notes {
  width: 100%;
  min-height: 220px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  font: 15px Arial, sans-serif;
  resize: vertical;
  white-space: pre-wrap;
}

.sketch-notes-count {
  color: var(--muted);
  font-size: var(--fs-xs);
  text-align: right;
}

/* ===== Sketch tab: 3D view ===== */
.sketch-view3d-controls {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 10px;
  width: 100%;
}

.sketch-view3d-controls label {
  font-size: var(--fs-sm);
  font-weight: 700;
}

.sketch-view3d-controls input {
  width: 72px;
}

.sketch-3d-stage {
  display: flex;
  gap: var(--space-4);
  flex-wrap: wrap;
  align-items: flex-start;
  width: 100%;
}

/* Matches the 2D sheet's framed-document treatment (Q13): its own light
   gradient already stays light, so it only needs the shared edge + shadow to
   read as the same floating document surface on the dark mat. */
#sketch-canvas-3d-wrap {
  position: relative;
  background: radial-gradient(circle at 50% 32%, #ffffff 0%, #eef1f5 42%, #cfd6df 78%, #b4bcc7 100%);
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--sketch-paper-edge);
  box-shadow: var(--shadow);
}

#sketch-canvas-3d {
  display: block;
}

.sketch-canvas3d-hint {
  position: absolute;
  bottom: 10px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.5);
  color: #ddd;
  font-size: 12px;
  padding: 4px 12px;
  border-radius: var(--radius);
  pointer-events: none;
  white-space: nowrap;
}

.sketch-legend-3d {
  font-size: var(--fs-base);
  line-height: 1.6;
  background: var(--panel);
  padding: 10px 14px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  min-width: 240px;
}

.sketch-legend-3d h3 {
  margin: 0 0 6px;
  font-size: var(--fs-lg);
}

.sketch-legend-3d .legend3d-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.sketch-legend-3d .legend3d-swatch {
  width: 22px;
  height: 14px;
  border: 1px solid #999;
  border-radius: 3px;
  flex-shrink: 0;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 9px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-sm);
  font-weight: 700;
}

.pill.reinforced {
  background: var(--accent-soft);
  color: var(--accent-strong);
}

.pill.reinforced-geogrid {
  background: #d6e9c6;
  color: #2f5d1f;
}

.pill.reinforced-combined {
  background: #cfe8e0;
  color: #1d5a4b;
}

.pill.non-reinforced {
  background: var(--warm-soft);
  color: var(--warm-strong);
}

.empty-state {
  padding: var(--space-6);
  border-radius: var(--radius-sm);
  background: var(--panel);
  border: 1px dashed var(--line-strong);
  color: var(--muted);
}

@media (max-width: 1100px) {
  .layout,
  .project-choice-grid,
  .chart-grid {
    /* minmax(0, 1fr) so a wide table/canvas child scrolls inside its wrapper
       instead of stretching the single column past the viewport. */
    grid-template-columns: minmax(0, 1fr);
  }

  .layout > * {
    min-width: 0;
  }

  .summary-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .optimization-metrics {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* R3 (DESIGN-REVIEW-2026-07 F6): one scrollable chip row instead of the old
     11-row vertical stack (which cost ~2 screens before any tool content and
     spread tap targets under the fixed FAB bar). The nav keeps its sticky-top
     behaviour; the right-edge fade marks the overflow the same way the
     .table-wrapper edge-fade does. Scrollbar hidden - the fade is the cue, and
     renderTabNav() scrolls the active chip into view.
     Lives at this breakpoint (not 720px) so landscape phones and small
     tablets (721-1100px) get the same single row instead of 2-3 wrapped
     sticky rows - the wrapped block plus the fixed FAB bar consumed roughly
     half of a landscape phone's visible height. */
  .tab-nav {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }

  .tab-nav::-webkit-scrollbar {
    display: none;
  }

  /* Scroll-aware right-edge fade: a sticky zero-space flex item pinned to the
     visible right edge while there is content to scroll toward (same visual
     as the table-wrapper ::after fade). */
  .tab-nav::after {
    content: "";
    position: sticky;
    right: 0;
    flex: 0 0 22px;
    margin-left: -22px;
    align-self: stretch;
    pointer-events: none;
    background: linear-gradient(to right, transparent, rgba(var(--text-rgb), 0.1));
  }

  .tab-button {
    flex: 0 0 auto;
  }
}

@media (max-width: 720px) {
  .page-shell {
    width: min(100vw - 16px, 1400px);
    padding-top: 12px;
  }

  .panel,
  .chart-card,
  .method-card {
    padding: var(--space-4);
    border-radius: var(--radius);
  }

  .controls-grid,
  .optimization-grid,
  .summary-cards {
    grid-template-columns: 1fr;
  }

  .toolbar,
  .scenario-toolbar,
  .sketch-toolbar,
  .project-bar,
  .scenario-card-top,
  .scenario-actions {
    flex-direction: column;
    align-items: stretch;
  }

  .toolbar .button,
  .scenario-toolbar .button,
  .sketch-toolbar .button,
  .scenario-actions .button {
    width: 100%;
    flex: none;
    min-width: 0;
  }

  .tool-fab-bar {
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    right: calc(16px + env(safe-area-inset-right, 0px));
    left: calc(16px + env(safe-area-inset-left, 0px));
    flex-wrap: wrap;
  }

  /* With the FAB spanning the viewport bottom, scroll-into-view (keyboard
     focus, anchor jumps, assistive tech) must not park its target behind the
     bar - the measured tap-interception of DESIGN-REVIEW-2026-07 F6. Reserve
     the bar's strip (up to two wrapped button rows + margins) as scroll
     padding; taller than the bar is harmless, it only biases scroll stops. */
  html {
    scroll-padding-bottom: 132px;
  }

  .tool-fab-bar > .button {
    flex: 1 1 auto;
  }

  .scenario-visibility {
    justify-content: space-between;
  }

  .project-bar-actions {
    display: grid;
    grid-template-columns: 1fr;
  }

  .summary-card strong {
    font-size: var(--fs-h2);
  }

  th,
  td {
    padding: 10px 12px;
    font-size: var(--fs-base);
  }

  .material-row,
  .optimization-card-top,
  .optimization-layer-item {
    grid-template-columns: 1fr;
    flex-direction: column;
    align-items: stretch;
  }

  .optimization-metrics {
    grid-template-columns: 1fr;
  }

  .chart-card {
    padding: 14px;
  }

  .chart-body {
    min-height: 280px;
  }

  .chart-body svg {
    min-width: 520px;
  }

  .layers-header,
  .layer-row-header {
    flex-direction: column;
    align-items: stretch;
  }
}

/* (The resting-tooltip display:none rule that lived here for <=820px was
   promoted to the base .has-help rules — the same laid-out-while-invisible
   bubble also inflated DESKTOP scroll width on the LET/Bearing/CO2/Unpaved
   tabs; DESIGN-REVIEW-2026-07 F4.) */

/* ===========================================================================
   Q5 — Phone reflow (<=640px). Two table strategies live here:
     1. .as-cards wrappers restack row-per-record results tables into cards
        (label from each cell's data-label, header row hidden).
     2. Every other data table stays tabular but pins its first (label) column
        and shows a right-edge fade so the sideways scroll reads as deliberate.
   All rules are scoped inside this breakpoint — desktop layout is untouched.
   =========================================================================== */
@media (max-width: 640px) {
  /* The fixed export/calculate cluster wraps to more rows on a phone; give the
     EV2 flow enough bottom room that the last results never hide behind it. */
  .calculator-flow {
    padding-bottom: 148px;
  }

  /* ---- Strategy 1: card-restack (opt-in via .as-cards on the wrapper) ---- */
  .as-cards {
    overflow: visible;
    border: none;
    box-shadow: none;
    background: transparent;
  }

  .as-cards table,
  .as-cards tbody,
  .as-cards tr,
  .as-cards td {
    display: block;
    width: auto;
  }

  .as-cards table {
    min-width: 0;
  }

  .as-cards thead {
    display: none;
  }

  .as-cards tbody tr {
    margin-bottom: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--panel);
    box-shadow: var(--shadow-soft);
  }

  .as-cards tbody tr:last-child {
    margin-bottom: 0;
  }

  .as-cards tbody td {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--space-4);
    padding: 5px 0;
    border: none;
    white-space: normal;
    text-align: right;
  }

  .as-cards tbody td::before {
    content: attr(data-label);
    flex: none;
    font-family: "Space Grotesk", sans-serif;
    font-weight: 700;
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted);
    text-align: left;
  }

  /* A card whose title is a <th scope="row"> (the Reports table) reads as a
     full-width heading, not a label/value row — keep its stacked layout. */
  .as-cards tbody th[scope="row"] {
    padding: 0 0 var(--space-1);
    margin-bottom: var(--space-1);
    border-radius: 0;
    border-bottom: 1px solid var(--line);
  }

  /* ---- Strategy 2: sticky label column + edge-fade on remaining tables ---- */
  .table-wrapper:not(.as-cards),
  .layer-editor-wrapper {
    position: relative;
  }

  .table-wrapper:not(.as-cards) tbody td:first-child,
  .table-wrapper:not(.as-cards) tbody th:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--panel);
  }

  .table-wrapper:not(.as-cards) thead th:first-child {
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--surface-2);
  }

  .table-wrapper:not(.as-cards)::after,
  .layer-editor-wrapper::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 22px;
    pointer-events: none;
    background: linear-gradient(to right, transparent, rgba(var(--text-rgb), 0.1));
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  }

  /* Single-column result grids (LET/Bearing) size their implicit column to
     content; pin them to a shrinkable track so a wide child scrolls/wraps
     instead of nudging the page sideways. */
  .let-results {
    grid-template-columns: minmax(0, 1fr);
  }

  .let-results > * {
    min-width: 0;
  }

  /* ---- Phone-usable layer editor: roomier tap targets, a little less scroll --- */
  .layer-editor-table {
    min-width: 560px;
  }

  .layer-editor-table select,
  .layer-editor-table input {
    padding: 7px;
    font-size: var(--fs-base);
  }
}

.match-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.match-note {
  margin-bottom: var(--space-4);
}

.match-note ul {
  margin: 12px 0 0;
  padding-left: var(--space-4);
}

.match-layers {
  display: grid;
  gap: 14px;
}

/* The Reinforced Match rows reuse the .layer-row class for a card layout (they are
   separate from the unified EV2 layer table, which restyles .layer-row as table rows). */
.match-layer-row {
  padding: var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  border: 1px solid var(--line);
}

.match-layer-row .layer-row-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
}

.match-layer-grid {
  display: grid;
  grid-template-columns: 1fr 1.2fr auto;
  gap: 12px;
  margin-top: 14px;
  align-items: end;
}

.match-cbr-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 96px;
  padding: 10px 12px;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-family: "Space Grotesk", sans-serif;
  font-weight: 700;
}

.match-comparison-stack {
  display: grid;
  gap: 16px;
}

.match-layer-cell {
  min-width: 240px;
}

@media (max-width: 820px) {
  .match-grid,
  .match-layer-grid {
    grid-template-columns: 1fr;
  }

  .match-cbr-chip {
    width: 100%;
  }
}

/* ---------------------------------------------------------------------------
   Authentication, session bar, and admin user management
--------------------------------------------------------------------------- */

.session-bar {
  position: fixed;
  top: calc(12px + env(safe-area-inset-top, 0px));
  right: calc(16px + env(safe-area-inset-right, 0px));
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: var(--panel-strong);
  box-shadow: var(--shadow);
  font-weight: 600;
  font-size: var(--fs-base);
}

.session-bar[hidden] {
  display: none !important;
}

.session-user {
  color: var(--muted);
}

.session-user strong {
  color: var(--text);
}

.session-role {
  margin-left: 6px;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--accent-soft);
  color: var(--accent);
}

.session-role.is-admin {
  background: var(--warm-soft);
  color: var(--warn-strong);
}

/* Theme toggle: an icon-only tiny button in the session bar. Icon swapped by
   app.js to mirror the active theme; sizing only (colors inherit .button). */
.theme-toggle {
  padding: 6px 8px;
  line-height: 0;
}

.theme-toggle-icon {
  display: inline-flex;
}

.theme-toggle-icon svg {
  width: 16px;
  height: 16px;
  display: block;
}

.auth-gate {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: var(--space-7) var(--space-4);
}

.auth-gate[hidden],
.admin-gate[hidden] {
  display: none !important;
}

.auth-card {
  width: min(420px, 100%);
  display: grid;
  gap: 14px;
  padding: var(--space-7);
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--panel);
  box-shadow: var(--shadow);
}

.auth-card h1 {
  margin: 0;
}

.auth-form {
  display: grid;
  gap: 14px;
  margin-top: 6px;
}

.auth-form .button {
  margin-top: 4px;
}

.auth-error {
  margin: 0;
  padding: 10px 14px;
  border-radius: var(--radius-lg);
  background: var(--danger-soft);
  color: var(--danger-strong);
  font-weight: 600;
  font-size: var(--fs-base);
}

.auth-error[hidden] {
  display: none !important;
}

/* external.js writes its auth errors via textContent (no hidden toggling), so
   an idle error line must collapse the same way .tool-status does. */
.auth-error:empty {
  display: none;
}

/* Account-security screen (2FA enrollment / disable). The QR SVG brings its
   own white ground + quiet zone (vendor/qrcode.js), so it stays scannable in
   dark mode - the frame only sizes and borders it. */
.security-card {
  width: min(520px, 100%);
}

.totp-status {
  margin: 0;
  font-weight: 600;
}

.totp-qr {
  justify-self: start;
}

.totp-qr svg {
  display: block;
  width: min(240px, 100%);
  height: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.totp-secret-note code {
  display: inline-block;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  border: 1px solid var(--line);
  user-select: all;
  overflow-wrap: anywhere;
}

.totp-backup-codes {
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface-2);
  font-size: var(--fs-base);
  line-height: 1.7;
  user-select: all;
}

.totp-backup-actions {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.security-back {
  justify-self: start;
}

.field-note {
  margin: 0;
  color: var(--muted);
  font-weight: 600;
  font-size: var(--fs-base);
}

.field-note[hidden] {
  display: none !important;
}

.field[hidden] {
  display: none !important;
}

.admin-gate {
  min-height: 100vh;
  padding: var(--space-7) var(--space-4);
}

.admin-inner {
  width: min(980px, 100%);
  margin: 0 auto;
  display: grid;
  gap: var(--space-4);
}

/* Let the admin panels shrink below the tables' min-width so the .table-wrapper
   scroll strategy engages instead of the whole page panning sideways on a phone
   (grid items otherwise refuse to shrink below content; measured +302px at
   390px — DESIGN-REVIEW-2026-07 F5). */
.admin-inner > *,
.admin-section > * {
  min-width: 0;
}

/* R7 (DESIGN-REVIEW-2026-07): the admin screen groups its panels into two
   anchor-addressable sections behind a sticky pill nav (the same .subtab
   language as everywhere else, as links). */
.admin-section {
  display: grid;
  gap: var(--space-4);
}

.admin-nav {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  gap: var(--space-1);
  padding: var(--space-2) 0;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}

.admin-nav .subtab {
  text-decoration: none;
}

/* Anchor jumps land below the sticky nav, not underneath it. */
.admin-section {
  scroll-margin-top: 64px;
}

/* The optional CBA rate card collapses behind a native <details> so the
   create/edit form reads at a glance; beginCountryEdit opens it when the
   profile actually carries rates. */
.admin-rates summary {
  cursor: pointer;
  font-family: "Space Grotesk", sans-serif;
  font-weight: 700;
  font-size: var(--fs-h3);
  color: var(--text);
  padding: var(--space-2) 0;
}

.admin-rates summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.admin-rates-note {
  margin: 0 0 var(--space-3);
  color: var(--muted);
  font-size: var(--fs-sm);
}

.admin-rates[open] {
  padding-bottom: var(--space-2);
}

/* Row headers in the admin tables (username / country code) keep the shared
   th row-header look; left-aligned like the LET criterion rows. */
.users-table tbody th[scope="row"] {
  text-align: left;
}

/* Section separators inside an admin panel (was two one-off inline styles in
   index.html — the markup stays style-free). */
.admin-inner .panel-heading:not(:first-child) {
  margin-top: var(--space-4);
}

.admin-header {
  display: flex;
  justify-content: space-between;
  align-items: end;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.admin-header h1 {
  margin: 6px 0;
}

.users-table {
  min-width: 640px;
}

.users-table .user-role-select {
  padding: 6px 10px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--text);
}

.users-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.button.danger {
  border: 1px solid #d98b7e;
  color: var(--danger-strong);
  background: transparent;
}

.button.danger:hover {
  background: var(--danger-soft);
}

.self-tag,
.pw-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.self-tag {
  background: var(--accent-soft);
  color: var(--accent);
}

.pw-tag {
  background: var(--warm-soft);
  color: var(--warn-strong);
}

.status-active {
  color: var(--accent);
  font-weight: 700;
}

.status-inactive {
  color: var(--danger-strong);
  font-weight: 700;
}

/* 1100px (not 820) so the breakpoint matches the tab-nav's single scrollable
   row: in the 721-1100px band the sticky row spans the full width, and a
   fixed pill would float over its right end as soon as the page scrolls. */
@media (max-width: 1100px) {
  .session-bar {
    position: static;
    margin: 12px auto 0;
    width: fit-content;
    /* The bar's actions (user + palette picker + theme + admin + logout) can
       exceed a phone's width on one line — wrap instead of widening the page
       (R7 re-measure caught +94px at 390px after R6 added the picker). */
    max-width: calc(100vw - 24px);
    flex-wrap: wrap;
    justify-content: center;
    /* Respect a notch/cutout when it flows at the very top of the page. */
    margin-top: calc(12px + env(safe-area-inset-top, 0px));
  }

  /* The bar no longer floats over the header corner, so drop the reservation. */
  .app-header::after {
    display: none;
  }
}

/* ===================== Carbon (CO2) tab ===================== */
/* All rules scoped under .co2-scope so nothing leaks into the rest of the app. */
.co2-subtabs {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}

/* .co2-subtab is a JS behavior hook only - the pill styling is the shared
   .subtab component (one tab language next to .tab-button). */

.co2-subpanel {
  display: none;
}

.co2-subpanel.active {
  display: block;
}

.co2-scope .panel {
  margin-bottom: var(--space-4);
}

.co2-summary-bar {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.co2-topbar-actions {
  display: grid;
  gap: 10px;
  min-width: 240px;
}

.co2-topbar-summary {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  padding: 14px var(--space-4);
  display: grid;
  gap: 2px;
}

.co2-topbar-summary span {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--muted);
}

.co2-topbar-summary strong {
  font-size: 2.2rem;
  line-height: 1;
  color: var(--accent);
}

.co2-topbar-summary small {
  color: var(--muted);
}

.co2-geometry-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  max-width: 720px;
}

.co2-unit-input {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
}

.co2-unit-input strong {
  min-width: 48px;
  color: var(--muted);
  font-size: var(--fs-sm);
  white-space: nowrap;
}

.co2-scenario-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
}

.co2-layer-stack {
  display: grid;
  gap: 12px;
}

.co2-layer-card {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  padding: 16px;
}

.co2-data-card {
  background: var(--surface-2);
}

.co2-scenario-head-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}

.co2-scenario-hint {
  flex: 1 1 320px;
  color: var(--muted);
  font-size: var(--fs-base);
}

.co2-scenario-head {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  margin-bottom: 14px;
}

.co2-scenario-title-field {
  flex: 1 1 auto;
}

.co2-role-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 8px;
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: var(--fs-xs);
  font-style: normal;
  font-weight: 700;
}

.co2-layer-title {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}

.co2-layer-title .co2-layer-name {
  flex: 1 1 auto;
  min-width: 0;
}

.co2-layer-name {
  font-weight: 700;
}

.co2-input-chip,
.co2-data-heading span {
  flex: 0 0 auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--panel);
  color: var(--muted);
  padding: 5px 10px;
  font-size: var(--fs-xs);
  font-weight: 700;
  white-space: nowrap;
}

.co2-simple-inputs {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(140px, 0.8fr);
  gap: 12px;
}

.co2-data-inputs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}

.co2-simple-note {
  margin-top: 10px;
  border: 1px dashed var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-2);
  color: var(--muted);
  padding: 9px 11px;
  font-size: var(--fs-sm);
  font-weight: 600;
}

.co2-data-heading {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

.co2-layer-results-block {
  margin-top: 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--accent-soft);
  padding: 12px;
}

.co2-mini-heading {
  margin-bottom: 8px;
  color: var(--accent-strong);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.co2-layer-results {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px;
}

.co2-layer-results span {
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel);
  padding: 8px;
  color: var(--muted);
  font-size: var(--fs-sm);
}

.co2-layer-results strong {
  display: block;
  color: var(--text);
  font-size: var(--fs-lg);
}

.co2-metric-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: var(--space-4);
}

.co2-metric span {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--muted);
}

.co2-metric small {
  display: block;
  margin-top: 4px;
  color: var(--muted);
}

.co2-metric.highlight {
  background: linear-gradient(180deg, var(--accent-soft), var(--panel));
  border-color: var(--accent);
}

.co2-dashboard-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-bottom: var(--space-4);
}

.co2-chart-panel {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  padding: 16px;
}

.co2-bar-chart {
  display: grid;
  gap: 12px;
}

.co2-bar-row {
  display: grid;
  grid-template-columns: 130px minmax(0, 1fr) 110px;
  gap: 12px;
  align-items: center;
}

.co2-bar-label {
  font-weight: 600;
  font-size: var(--fs-base);
}

.co2-bar-track {
  height: 18px;
  overflow: hidden;
  border-radius: var(--radius-pill);
  background: var(--line);
}

.co2-bar-fill {
  height: 100%;
  border-radius: inherit;
}

.co2-bar-row strong {
  text-align: right;
  font-size: var(--fs-base);
}

.co2-info-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.co2-citation-list {
  display: grid;
  gap: 12px;
}

.co2-citation-list a {
  display: inline-block;
  margin-top: 8px;
  color: var(--accent);
  font-weight: 700;
  text-decoration: none;
}

.co2-citation-list a:hover {
  text-decoration: underline;
}

.co2-formula-box {
  display: grid;
  gap: 6px;
  margin: 10px 0 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--accent-soft);
  padding: 12px;
}

.co2-formula-box span {
  color: var(--accent-strong);
  font-family: Consolas, "Courier New", monospace;
  font-size: var(--fs-base);
  line-height: 1.35;
}

/* Tooltip — shared "?" help badge + hover bubble, used across all tabs.
   Usage: <span class="has-help" data-help="...">Label</span>.
   Add .help-right when the element sits near the right edge (e.g. last table
   columns) so the bubble opens leftward instead of overflowing. */
.has-help {
  position: relative;
  display: inline-flex;
  width: fit-content;
  align-items: center;
  gap: 6px;
  cursor: help;
}

.has-help::after {
  content: "?";
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: var(--panel);
  color: var(--muted);
  font-size: var(--fs-xs);
  font-weight: 700;
  line-height: 1;
}

/* The resting bubble is display:none, not just opacity:0 — an invisible bubble
   is still laid out (left:0, width min(300px,76vw)), and one anchored on a
   right-edge label inflates the PAGE's scroll width (a phantom horizontal
   scrollbar; measured +47..+159px on four desktop tabs — DESIGN-REVIEW-2026-07
   F4). @starting-style keeps the fade-in on engines that support transitioning
   from display:none; elsewhere the bubble simply appears (the long-standing
   <=820px behaviour). */
.has-help::before {
  content: attr(data-help);
  display: none;
  position: absolute;
  z-index: 30;
  left: 0;
  bottom: calc(100% + 8px);
  width: min(300px, 76vw);
  padding: 10px 12px;
  border-radius: var(--radius-lg);
  background: var(--tooltip-bg);
  color: #fff;
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.22);
  font-size: var(--fs-sm);
  font-weight: 500;
  line-height: 1.4;
  text-transform: none;
  letter-spacing: 0;
  pointer-events: none;
  transition: opacity 0.14s ease, transform 0.14s ease;
}

.has-help:hover::before,
.has-help:focus-visible::before {
  display: block;
  opacity: 1;
  transform: translateY(0);
}

@starting-style {
  .has-help:hover::before,
  .has-help:focus-visible::before {
    opacity: 0;
    transform: translateY(4px);
  }
}

.has-help.help-right::before {
  left: auto;
  right: 0;
}

/* Opens the bubble below the label — for table headers inside scrollable
   wrappers, where an upward bubble would be clipped by the container. */
.has-help.help-down::before {
  bottom: auto;
  top: calc(100% + 8px);
  transform: translateY(-4px);
}

/* On a phone the label-anchored bubble (left: 0, width min(300px, 76vw))
   overflows the viewport for any label in the right two-thirds of the
   screen — html's overflow-x backstop would clip it mid-sentence. Pin the
   open bubble to the viewport instead: full-width under the sticky tab row,
   above every sticky/fixed bar (tabs z-40, session z-50). The .help-right /
   .help-down variants collapse into the same placement, so their
   label-relative offsets (viewport-relative once fixed) are reset here.
   (Must come after the base .has-help rules — same specificity, order wins.) */
@media (max-width: 720px) {
  .has-help::before,
  .has-help.help-right::before,
  .has-help.help-down::before {
    position: fixed;
    left: calc(12px + env(safe-area-inset-left, 0px));
    right: calc(12px + env(safe-area-inset-right, 0px));
    top: calc(72px + env(safe-area-inset-top, 0px));
    bottom: auto;
    width: auto;
    z-index: 60;
  }
}

@media (max-width: 1100px) {
  .co2-metric-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .co2-data-inputs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 860px) {
  .co2-scenario-grid,
  .co2-dashboard-grid {
    grid-template-columns: 1fr;
  }
  .co2-geometry-grid,
  .co2-metric-grid,
  .co2-data-inputs,
  .co2-simple-inputs {
    grid-template-columns: 1fr;
  }
  .co2-layer-results {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ===== CO2 print report ===== */
.co2-print-report {
  display: none;
}

.co2-report-page {
  padding: 14mm;
  color: #17211f;
  background: #fff;
  display: flex;
  flex-direction: column;
  gap: 7mm;
}

.co2-report-brand span {
  color: var(--accent);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.co2-report-brand strong {
  display: block;
  font-size: 18px;
}

.co2-report-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 56mm;
  gap: 8mm;
  align-items: center;
  padding: 8mm;
  border: 1px solid #cfded9;
  border-radius: 10px;
  background: #f7faf9;
}

.co2-report-hero p {
  margin-bottom: 4mm;
  color: #62706c;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 10px;
}

.co2-report-hero h2 {
  font-size: 26px;
  line-height: 1.05;
}

.co2-report-score {
  border-left: 5px solid var(--accent);
  padding-left: 6mm;
}

.co2-report-score span,
.co2-report-metric span,
.co2-report-metric small,
.co2-report-strip span,
.co2-report-note p {
  color: #62706c;
}

.co2-report-score strong {
  display: block;
  margin: 2mm 0;
  color: var(--accent);
  font-size: 36px;
  line-height: 1;
}

.co2-report-metric-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 4mm;
}

.co2-report-metric {
  padding: 4mm;
  border: 1px solid #dbe3e0;
  border-radius: 10px;
  background: #f8faf9;
}

.co2-report-metric span,
.co2-report-metric small {
  display: block;
  font-size: 10px;
  font-weight: 700;
}

.co2-report-metric strong {
  display: block;
  margin: 2mm 0 1mm;
  font-size: 18px;
}

.co2-report-two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4mm;
}

.co2-report-panel {
  border: 1px solid #dbe3e0;
  border-radius: 10px;
  padding: 4mm;
  background: #fbfdff;
}

.co2-report-panel h3 {
  margin-bottom: 3mm;
}

.co2-report-bar-row {
  display: grid;
  grid-template-columns: 26mm minmax(0, 1fr) 24mm;
  gap: 3mm;
  align-items: center;
  margin-bottom: 2.6mm;
  font-size: 9.5px;
}

.co2-report-bar-row span {
  font-weight: 700;
}

.co2-report-bar-row strong {
  text-align: right;
}

.co2-report-bar-track {
  height: 5mm;
  overflow: hidden;
  border-radius: var(--radius-pill);
  background: #e7ecea;
}

.co2-report-bar-track div {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), #3378a4);
}

.co2-report-strip {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 3mm;
}

.co2-report-strip div {
  padding: 3mm;
  border: 1px solid #dbe3e0;
  border-radius: 10px;
  background: #fff;
}

.co2-report-strip span {
  display: block;
  margin-bottom: 1.5mm;
  font-size: 8.5px;
  font-weight: 700;
  text-transform: uppercase;
}

.co2-report-strip strong {
  display: block;
  font-size: 11px;
}

.co2-report-note {
  padding: 4mm;
  border-left: 5px solid var(--accent);
  background: #eef8f5;
  border-radius: 0 10px 10px 0;
}

.co2-report-note strong {
  display: block;
  margin-bottom: 2mm;
}

.co2-report-note p {
  line-height: 1.35;
  font-size: 10px;
}

@media print {
  body.co2-printing .page-shell,
  body.co2-printing .session-bar,
  body.co2-printing .project-gate,
  body.co2-printing .auth-gate,
  body.co2-printing .admin-gate {
    display: none !important;
  }
  body.co2-printing .co2-print-report {
    display: block;
  }
}

/* ===== Unpaved road calculator ===== */
.unpaved-scope {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.unpaved-intro h2 {
  margin: 4px 0 2px;
}

.unpaved-intro .panel-heading.compact-intro {
  margin-bottom: var(--space-3);
}

.unpaved-intro .panel-heading.compact-intro p:last-child {
  margin: 0;
}

.unpaved-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.unpaved-grid.shared {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px 16px;
}

.unpaved-grid .field[hidden] {
  display: none;
}

.unpaved-compare {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
  align-items: start;
}

.unpaved-col {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.unpaved-col-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}

.unpaved-col-head h3 {
  margin: 0;
  font-size: var(--fs-h2);
}

.unpaved-tag {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  background: rgba(0, 0, 0, 0.04);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  padding: 4px 10px;
}

.unpaved-tag.reinforced {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: var(--accent-soft);
}

.unpaved-mode {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  background: rgba(0, 0, 0, 0.04);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  width: fit-content;
}

.unpaved-mode-btn {
  border: none;
  background: transparent;
  color: var(--muted);
  font-weight: 700;
  padding: 8px 16px;
  border-radius: 10px;
  cursor: pointer;
}

.unpaved-mode-btn.active {
  background: var(--panel-strong);
  color: var(--accent);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

/* headline */
.unpaved-headline {
  background: var(--panel-strong);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 16px;
}

.unpaved-h-pair {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 12px;
  align-items: end;
}

.unpaved-h-main span,
.unpaved-h-target span {
  display: block;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 2px;
}

.unpaved-h-main strong {
  font-size: 2.2rem;
  line-height: 1;
  font-weight: 700;
}

.unpaved-h-target strong {
  font-size: var(--fs-h1);
  line-height: 1;
  color: var(--muted);
}

.unpaved-h-main i,
.unpaved-h-target i {
  font-style: normal;
  font-size: var(--fs-base);
  font-weight: 600;
  margin-left: 4px;
  color: var(--muted);
}

.unpaved-h-main.matched strong {
  color: var(--ok);
}

.unpaved-hint {
  margin: 10px 0 0;
  font-size: var(--fs-base);
  color: var(--muted);
}

.unpaved-hint.ok {
  color: var(--ok);
  font-weight: 600;
}

.unpaved-hint.warn {
  color: var(--warn);
}

.unpaved-hint.error {
  color: var(--danger);
  font-weight: 600;
  margin: 0;
}

.unpaved-s-value input.over-limit {
  border-color: var(--danger);
  color: var(--danger);
  box-shadow: 0 0 0 2px rgba(var(--danger-rgb), 0.15);
}

/* rutting control */
.unpaved-s-control {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
}

.unpaved-s-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.unpaved-s-value {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 700;
}

.unpaved-s-value input {
  width: 86px;
  padding: 8px 10px;
  text-align: right;
}

.unpaved-s-range {
  width: 100%;
  accent-color: var(--accent);
  cursor: pointer;
  padding: 0;
}

.button.tiny.unpaved-solve {
  align-self: flex-start;
  padding: 6px 12px;
  font-size: var(--fs-sm);
}

/* collapsed design-inputs dropdown (reuses the .collapsible pattern) */
.unpaved-inputs > summary {
  padding: 8px 12px;
}

.unpaved-inputs .collapsible-title {
  font-size: var(--fs-lg);
}

.unpaved-inputs .collapsible-hint {
  font-size: var(--fs-sm);
}

.unpaved-inputs > summary::after {
  top: 15px;
  right: 16px;
  width: 8px;
  height: 8px;
}

.unpaved-inputs > *:not(summary) {
  margin: 2px 12px 14px;
}

/* Editable mirror of the linked EV2 scenario pair (reuses the EV2 tab's
   .scenario-editor / .layer-editor-table styles wholesale). */
.unpaved-mirror-blocks {
  margin-top: var(--space-3);
}

/* Mirror block titles are plain labels, not scenario-select buttons. */
.scenario-editor-title.is-static {
  cursor: default;
}

.scenario-editor:not(.active) .scenario-editor-title.is-static:hover {
  color: var(--text);
  text-decoration: none;
}

/* details */
.unpaved-details-toggle {
  align-self: flex-start;
  border: none;
  background: transparent;
  color: var(--accent);
  font-weight: 700;
  cursor: pointer;
  padding: 4px 0;
}

.unpaved-details {
  border-top: 1px dashed var(--line);
  padding-top: 12px;
}

.unpaved-detail-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2) var(--space-4);
  margin: 0;
}

.unpaved-detail-grid div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  border-bottom: 1px solid var(--line);
  padding-bottom: 4px;
}

.unpaved-detail-grid dt {
  color: var(--muted);
  font-size: var(--fs-sm);
}

.unpaved-detail-grid dd {
  margin: 0;
  font-weight: 700;
  font-size: var(--fs-base);
}

/* comparison summary */
.unpaved-summary-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
}

/* calculation summary report */
.unpaved-report-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
}

/* .unpaved-report-status is a JS behavior hook only — styling is the shared
   .tool-status component. */

.unpaved-report-narrative {
  display: grid;
  gap: 8px;
  margin-bottom: var(--space-4);
}

.unpaved-report-narrative p {
  margin: 0;
  padding: 12px 14px;
  border-radius: var(--radius-lg);
  border-left: 4px solid var(--line-strong);
  background: var(--surface-2);
  font-size: var(--fs-lg);
  line-height: 1.5;
}

.unpaved-report-narrative p.matched {
  border-left-color: var(--ok);
  background: var(--ok-soft);
}

.unpaved-report-narrative p.unmatched {
  border-left-color: var(--warn);
  background: var(--warn-soft);
}

.unpaved-report-block {
  margin-top: var(--space-4);
}

.unpaved-report-block h4,
.unpaved-report-design h4 {
  margin: 0 0 10px;
  font-size: var(--fs-lg);
}

.unpaved-report-design h5 {
  margin: 14px 0 8px;
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.unpaved-report-designs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  margin-top: var(--space-4);
}

@media (max-width: 980px) {
  .unpaved-compare {
    grid-template-columns: 1fr;
  }
  .unpaved-grid.shared {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 980px) {
  .unpaved-report-designs {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 620px) {
  .unpaved-grid,
  .unpaved-grid.shared,
  .unpaved-detail-grid,
  .unpaved-summary-grid {
    grid-template-columns: 1fr;
  }
}

/* ===== Preliminary Design tool (redacted external one-pager) ===== */
.preliminary-intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.preliminary-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}

.preliminary-tag {
  flex: none;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--accent-strong);
  background: var(--accent-soft);
  border-radius: var(--radius-pill);
  padding: 4px 12px;
}

.preliminary-input-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--space-3);
}

.preliminary-actions {
  align-items: center;
  gap: var(--space-3);
}

.preliminary-hint {
  margin: var(--space-2) 0 0;
  font-size: var(--fs-sm);
  color: var(--muted);
}

/* .preliminary-status is a JS behavior hook only — styling is the shared
   .tool-status component. (Its old .is-error override was already dead: the
   later-in-file .tool-status.is-error won the cascade at equal specificity.) */

.preliminary-results {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-top: var(--space-4);
}

.preliminary-metrics {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}

.preliminary-metric.is-good strong {
  color: var(--accent-strong);
}

.preliminary-metric.is-review strong {
  color: var(--warm);
}

.preliminary-design-grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: var(--space-4);
}

.preliminary-layer-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.preliminary-layer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-size: var(--fs-sm);
}

.preliminary-layer-row.is-toughcell {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-strong);
}

.preliminary-layer-row.is-subgrade {
  border-style: dashed;
  color: var(--muted);
}

.preliminary-layer-name em {
  color: inherit;
  opacity: 0.8;
  font-style: normal;
}

.preliminary-layer-thickness {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.preliminary-total {
  margin-top: var(--space-3);
  font-size: var(--fs-sm);
  color: var(--muted);
}

.preliminary-svg {
  display: block;
  max-width: 360px;
  margin: 0 auto;
}

.preliminary-disclaimer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.preliminary-disclaimer p {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--muted);
}

@media (max-width: 720px) {
  .preliminary-design-grid {
    grid-template-columns: 1fr;
  }
  .preliminary-metrics {
    grid-template-columns: 1fr;
  }
}

/* ===== Load Distribution tab ===== */
/* All rules scoped under .load-distribution-scope so nothing leaks elsewhere. */
.load-distribution-scope {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.ld-intro h2 {
  margin: 4px 0 2px;
}

.ld-intro .panel-heading.compact-intro {
  margin-bottom: var(--space-3);
}

.ld-intro .panel-heading.compact-intro p:last-child {
  margin: 0;
}

.ld-group {
  margin-top: var(--space-3);
}

.ld-group .panel-heading.compact {
  margin-bottom: var(--space-2);
}

.ld-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px 16px;
  align-items: end;
}

/* Shape dimension fields are injected at runtime; render them as ordinary
   items of the Load grid so the footprint sits right next to the shape. */
.ld-shape-inputs {
  display: contents;
}

.ld-force-note {
  margin: 10px 0 0;
  font-size: var(--fs-sm);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  min-height: 1.2em;
}

.ld-group-heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.ld-group-heading .panel-heading.compact {
  margin-bottom: var(--space-2);
}

.ld-group-heading .button {
  flex: 0 0 auto;
  margin-top: 4px;
}

/* EV2 source selector + pull button, right of the layer-stack heading. */
.ld-source-controls {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
  flex: 0 0 auto;
}

.ld-source-field select {
  min-width: 190px;
}

.ld-layers {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.ld-layer-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr) auto;
  align-items: end;
  gap: 12px;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.ld-layer-index {
  align-self: center;
  font-size: var(--fs-sm);
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 8px;
}

.ld-chip {
  width: 12px;
  height: 12px;
  border-radius: 4px;
  flex: 0 0 auto;
  background: var(--warm);
}

.ld-chip.reinforced {
  background: var(--accent);
}

.ld-layer-row .ld-remove-layer {
  margin-bottom: 1px;
}

.ld-layers-toolbar {
  margin: var(--space-2) 0 0;
}

.ld-layers-toolbar .button {
  flex: 0 1 220px;
}

.ld-assumptions {
  margin-top: var(--space-3);
}

.ld-assumptions-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 16px;
}

.ld-error {
  margin: 0 0 var(--space-2);
  color: var(--danger);
  font-weight: 600;
}

.co2-calc-error {
  margin: 0 0 var(--space-2);
  color: var(--danger);
  font-weight: 600;
}

.ld-sketch-card {
  margin-top: var(--space-2);
}

.ld-sketch-heading {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  flex-wrap: wrap;
}

.ld-compare-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  padding-top: 4px;
}

.ld-compare-toggle input {
  accent-color: var(--accent);
  width: 16px;
  height: 16px;
  margin: 0;
}

.ld-svg-wrap {
  width: 100%;
}

.ld-svg-wrap svg {
  width: 100%;
  height: auto;
  display: block;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
}

.ld-svg-wrap:empty {
  display: none;
}

.ld-table-details {
  margin-top: var(--space-3);
}

.ld-results-toolbar {
  margin: var(--space-3) 0 0;
}

.ld-results-toolbar .button {
  flex: 0 1 220px;
}

.ld-delta-card {
  border-color: var(--accent);
}

/* tooltips: the .has-help / data-help pattern is global (see "explanatory tooltips" block) */

@media (max-width: 980px) {
  .ld-grid,
  .ld-assumptions-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 720px) {
  .ld-layer-row {
    grid-template-columns: 1fr;
    align-items: stretch;
  }
  .ld-grid,
  .ld-assumptions-grid {
    grid-template-columns: 1fr;
  }
  .ld-group-heading {
    flex-direction: column;
  }
}

/* ===== Cost-Benefit Analysis (CBA) tab ===== */
.cba-scope .cba-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cba-summary-bar { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-4); flex-wrap: wrap; }
.cba-topbar-actions { display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; }
.cba-topbar-summary { text-align: right; }
.cba-topbar-summary span { display: block; font-size: var(--fs-xs); color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; }
.cba-topbar-summary strong { font-family: "Space Grotesk", sans-serif; font-size: var(--fs-h1); color: var(--accent); display: block; }
.cba-topbar-summary small { color: var(--muted); }

.cba-link-banner { padding: 0; border: 0; background: transparent; box-shadow: none; }
.cba-link-inner { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; background: var(--accent-soft); border: 1px solid #b9dde2; border-radius: var(--radius); padding: 10px 14px; }
.cba-link-inner button { margin-left: auto; }

.cba-sections-table input, .cba-manual-table input, .cba-manual-table select, .cba-maint-table input { width: 100%; padding: 6px 8px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); font-family: "Space Grotesk", sans-serif; font-size: var(--fs-sm); background: var(--panel); color: var(--text); }
.cba-sections-table .cba-sec-dim { max-width: 110px; }
.cba-sections-table td, .cba-manual-table td, .cba-maint-table td { vertical-align: middle; }
.cba-manual-table .cba-num-input, .cba-maint-table .cba-num-input { text-align: right; }
.cba-maint-table .cba-num-input { max-width: 110px; }
.cba-lcc-params { display: flex; gap: var(--space-4); flex-wrap: wrap; margin-bottom: var(--space-4); }
.cba-lcc-params .field { max-width: 200px; }
.cba-sections-foot { display: flex; align-items: flex-end; gap: var(--space-4); flex-wrap: wrap; margin-top: var(--space-3); }
.cba-currency-field { margin-left: auto; max-width: 160px; }
.cba-derived { display: flex; gap: var(--space-5); flex-wrap: wrap; margin-top: var(--space-4); padding-top: var(--space-3); border-top: 1px dashed var(--line); }
.cba-derived div span { display: block; font-size: var(--fs-xs); color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; }
.cba-derived div strong { font-family: "Space Grotesk", sans-serif; font-size: var(--fs-lg); }

.cba-rate-actions { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-4); }
.cba-import-status { font-size: var(--fs-sm); color: var(--accent-strong); }
.cba-rate-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--space-4); }
.cba-rate-card { border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }
.cba-rate-cap { background: var(--surface-2); padding: 7px 11px; font-family: "Space Grotesk", sans-serif; font-size: var(--fs-sm); font-weight: 600; border-bottom: 1px solid var(--line); }
.cba-rate-cap small { color: var(--muted); font-weight: 400; }
.cba-rate-row { display: flex; align-items: center; gap: var(--space-2); padding: 6px 11px; border-top: 1px solid #eef1f4; }
.cba-rate-row:first-of-type { border-top: 0; }
.cba-rate-row span:first-child { flex: 1; font-size: var(--fs-sm); }
.cba-rate-row .cba-cur { color: var(--muted); font-family: "Space Grotesk", sans-serif; }
.cba-rate-input { width: 78px; padding: 4px 7px; border: 1px solid var(--line-strong); border-radius: 4px; text-align: right; font-family: "Space Grotesk", sans-serif; font-size: var(--fs-sm); background: var(--panel); }

.cba-boq-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); margin-bottom: var(--space-4); }
.cba-boq { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-soft); }
.cba-boq > header { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-2); padding: 11px 14px; }
.cba-boq.base > header { background: var(--warm-soft); border-bottom: 1px solid #e6cdb8; }
.cba-boq.reinf > header { background: var(--accent-soft); border-bottom: 1px solid #b9dde2; }
.cba-boq > header h3 { margin: 0; font-family: "Space Grotesk", sans-serif; font-size: var(--fs-h3); }
.cba-tag { font-family: "Space Grotesk", sans-serif; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em; padding: 2px 8px; border-radius: var(--radius-pill); background: var(--panel); }
.cba-boq.base .cba-tag { color: var(--warm); }
.cba-boq.reinf .cba-tag { color: var(--accent); }
.cba-boq .cba-grp td { background: var(--surface-2); font-family: "Space Grotesk", sans-serif; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.cba-boq tfoot td { font-family: "Space Grotesk", sans-serif; font-weight: 600; border-top: 2px solid var(--line-strong); }
.cba-empty-row td { color: var(--muted); font-style: italic; text-align: center; }

.cba-metric-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--space-4); margin-bottom: var(--space-4); }
.cba-balance-table .cba-good { color: var(--ok); }
.cba-balance-table .cba-bad { color: var(--warm); }
.cba-balance-table .cba-grp td { background: var(--surface-2); font-family: "Space Grotesk", sans-serif; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.cba-balance-subtotal td { font-weight: 600; border-top: 1px solid var(--line-strong); }
.cba-tier-table { margin-bottom: var(--space-4); }
.cba-balance-total td { font-weight: 600; border-top: 2px solid var(--line-strong); background: var(--surface-2); }
.cba-note { font-size: var(--fs-sm); color: var(--muted); margin-top: var(--space-3); }

@media (max-width: 860px) {
  .cba-boq-grid { grid-template-columns: 1fr; }
}

/* ===== Layered Elastic Analysis tab ===== */
.let-intro .hero-text { max-width: 70ch; }
.let-load-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px 16px;
  align-items: end;
}
.let-check { flex-direction: row; align-items: center; gap: 8px; }
.let-check input[type="checkbox"] { width: auto; }
.let-hint { color: var(--muted); font-size: var(--fs-sm); margin: 8px 0 0; }
.let-designs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 16px;
  margin: 16px 0;
}
.let-design-name {
  font-weight: 600; font-size: var(--fs-h2); width: 100%;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  padding: 4px 6px; margin-bottom: 10px; background: transparent; color: var(--text);
}
.let-design-name:hover, .let-design-name:focus { border-color: var(--line); background: var(--surface-2); }
.let-layer-head, .let-layer-row {
  display: grid;
  grid-template-columns: 1.4fr 1fr 0.8fr 1fr 40px 28px;
  gap: 8px; align-items: center;
}
.let-layer-head { color: var(--muted); font-size: var(--fs-xs); padding: 0 2px 6px; }
.let-layer-row { margin-bottom: 6px; }
.let-layer-row.is-subgrade { opacity: 0.95; }
.let-layer-row input, .let-layer-row select { width: 100%; }
.let-semiinf { color: var(--muted); font-size: var(--fs-sm); text-align: center; font-style: italic; }
.let-row-x {
  border: none; background: transparent; color: var(--muted);
  font-size: var(--fs-h2); cursor: pointer; line-height: 1; padding: 2px;
}
.let-row-x:hover { color: var(--danger); }
.let-row-x-spacer { display: inline-block; }
.let-row-move { display: inline-flex; gap: 2px; justify-content: center; }
.let-row-arrow {
  border: none; background: transparent; color: var(--muted);
  font-size: var(--fs-base); cursor: pointer; line-height: 1; padding: 2px;
}
.let-row-arrow:hover:not(:disabled) { color: var(--text); }
.let-row-arrow:disabled { opacity: 0.3; cursor: default; }
.let-row-move-spacer { display: inline-block; }
.let-add { margin-top: 8px; }
.let-actions { align-items: center; gap: 16px; flex-wrap: wrap; }
.let-critx-toggle { margin-left: auto; }
/* .let-status is a JS behavior hook only (R2 of DESIGN-REVIEW-2026-07) — the
   status-line styling is the shared .tool-status component below. */

/* The generic per-tool status line (Q2). Every status line carries this class;
   per-tool names (.let-status, .sm-status, .preliminary-status,
   .unpaved-report-status) are JS hooks with no styling of their own. */
.tool-status {
  margin: 0;
  align-self: center;
  color: var(--muted);
  font-size: var(--fs-base);
}
.tool-status.is-error { color: var(--danger); }
/* Q11: an idle status line takes no space (matters in flex rows with gap —
   an empty span would still claim a gap slot). Statuses are written via
   textContent, so cleared lines are truly :empty. */
.tool-status:empty { display: none; }
.let-results { margin-top: 16px; display: grid; gap: 16px; }
/* min-width:0 defeats the global `table { min-width: 760px }` floor (meant for
   the wide EV2 results table in its scrollable wrapper) so these tables fit the
   narrow side-by-side LET/NTI cards instead of overflowing them. */
.let-table { width: 100%; min-width: 0; border-collapse: collapse; font-size: var(--fs-base); }
.let-table th, .let-table td { padding: 7px 10px; text-align: right; border-bottom: 1px solid var(--line); }
.let-table thead th { color: var(--muted); font-weight: 600; }
.let-crit-table th[scope="row"] { text-align: left; font-weight: 500; }
.let-crit-table th[scope="row"] small { color: var(--muted); font-weight: 400; }
.let-crit-table td { font-variant-numeric: tabular-nums; }
.let-delta { font-weight: 600; color: var(--accent-strong); }
.let-detail-bar { justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; }
.let-viewsel { display: inline-flex; gap: 4px; }
.let-viewsel .button.is-on, .let-dtab.is-on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-strong); }
.let-table-scroll { overflow-x: auto; }
.let-detail-table td, .let-detail-table th { font-variant-numeric: tabular-nums; white-space: nowrap; }
.let-detail-table thead th small { color: var(--muted); font-weight: 400; }
.let-detail-one h4 { margin: 12px 0 6px; }
.let-critx-legend { display: flex; gap: 20px; margin: 2px 0 8px; font-size: var(--fs-sm); color: var(--muted); }
.let-critx-legend i { display: inline-block; width: 12px; height: 12px; border-radius: 3px; margin-right: 6px; vertical-align: -1px; }
.let-critx-block { margin-top: 16px; }
.let-critx-block h4 { margin: 0 0 4px; }
.let-critx-block h4 small { color: var(--muted); font-weight: 400; }
.let-critx-readouts { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-5); font-size: var(--fs-base); margin-bottom: 6px; font-variant-numeric: tabular-nums; }
.let-critx-svg { width: 100%; max-width: 560px; height: auto; display: block; }

/* ---- LET vertical-displacement heat map ---- */
.let-map-controls { align-items: center; gap: 12px; flex-wrap: wrap; }
.let-map-toggle { display: inline-flex; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.let-map-toggle .let-seg {
  border: 0; background: var(--panel); color: var(--muted);
  padding: 6px 14px; cursor: pointer; font: inherit; font-size: var(--fs-base);
}
.let-map-toggle .let-seg + .let-seg { border-left: 1px solid var(--line); }
.let-map-toggle .let-seg.is-active { background: var(--accent); color: var(--fill-ink); }
.let-map-mount { margin-top: 14px; min-height: 8px; position: relative; }
.let-map-canvas { display: block; height: auto; border-radius: 6px; }
.let-map-tooltip {
  position: absolute; z-index: 5; pointer-events: none;
  background: rgba(var(--tooltip-bg-rgb), 0.92); color: #fff;
  padding: 4px 9px; border-radius: 6px;
  font-size: var(--fs-sm); font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* ---- LET sub-tabs (LET Analysis / NTI) + the NTI pavement check ---- */
/* The sub-tab bar supplies the top spacing the panel content used to get
   directly from .tab-panel (same trick as #ev2-calc-view). */
#let-analysis-view, #let-nti-view { margin-top: var(--space-3); }
.nti-design-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px 16px;
  margin-bottom: 12px;
}
.nti-layer-head, .nti-layer-row {
  display: grid;
  grid-template-columns: 1.3fr 1fr 0.7fr 1fr 28px;
  gap: 8px; align-items: center;
}
.nti-layer-head { color: var(--muted); font-size: var(--fs-xs); padding: 0 2px 6px; }
.nti-layer-row { margin-bottom: 6px; }
.nti-layer-row input, .nti-layer-row select { width: 100%; }
.nti-layer-row input[type="checkbox"] { width: auto; justify-self: center; }
.nti-table td, .nti-table th { font-variant-numeric: tabular-nums; }
.nti-cell-left { text-align: left !important; }
.nti-fatigue-table th[scope="row"] { font-weight: 500; }
.nti-fatigue-table th[scope="row"] small { color: var(--muted); font-weight: 400; }
.nti-result h4 { margin: 14px 0 6px; }
.nti-flag {
  display: inline-block; padding: 1px 8px; border-radius: var(--radius-pill);
  font-size: var(--fs-xs); font-weight: 600; white-space: nowrap;
  background: var(--surface-2); border: 1px solid var(--line); color: var(--muted);
}
.nti-flag-neoloy { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-strong); }
.nti-verdict {
  display: inline-block; padding: 2px 10px; border-radius: var(--radius-pill);
  font-size: var(--fs-xs); font-weight: 700; margin-left: 8px;
}
.nti-pass { background: var(--ok-soft); color: var(--ok); }
.nti-fail { background: var(--danger-soft); color: var(--danger); }
.nti-warnings {
  margin: 10px 0 0; padding-left: var(--space-4);
  color: var(--warn); font-size: var(--fs-sm);
}
.nti-warnings li { margin-bottom: 2px; }
.nti-informational { margin-top: 10px; }

/* Design editor head: free-text name + the fixed variant identity pill. */
.nti-design-head {
  display: flex; align-items: center; gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.nti-design-head .let-design-name { flex: 1 1 auto; min-width: 0; }
/* Placeholder in the Neoloy column of the unreinforced design's rows. */
.nti-novariant { justify-self: center; color: var(--muted); }

/* Results: verdict summary cards + the A/B/delta comparison table. */
.nti-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: var(--space-3); }
.nti-card strong { font-size: var(--fs-h3); }
.nti-card-pass { border-color: var(--ok); }
.nti-card-fail { border-color: var(--danger); }
.nti-card-note { display: block; margin-top: 2px; color: var(--muted); font-size: var(--fs-sm); }
.nti-compare { margin-top: var(--space-3); }
.nti-delta-worse { color: var(--danger); }

/* ===== Ground Bearing Capacity tab ===== */
.bearing-table th[scope="row"] { font-weight: 500; }
.bearing-group th {
  padding-top: 14px; color: var(--muted); font-size: var(--fs-xs);
  text-transform: uppercase; letter-spacing: 0.04em; border-bottom: 1px solid var(--line-strong);
}
.bearing-primary td { font-size: var(--fs-lg); }

/* Geometry panel: inputs left, live footing schematic right. */
.bearing-geo-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 400px);
  gap: 20px;
  align-items: start;
}
.bearing-svg-wrap { width: 100%; }
.bearing-svg-wrap svg {
  width: 100%; height: auto; display: block;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--panel);
}
.bearing-diagram-empty {
  margin: 0; padding: 16px;
  border: 1px dashed var(--line); border-radius: var(--radius-sm);
}

/* Results heading row with the unit toggle. */
.bearing-results-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
}
.bearing-units {
  display: inline-flex; gap: 4px; padding: 3px;
  background: rgba(0, 0, 0, 0.04);
  border: 1px solid var(--line); border-radius: var(--radius-lg);
}
.bearing-units-btn {
  border: none; background: transparent; color: var(--muted);
  font-weight: 600; font-size: var(--fs-sm); padding: 5px 12px;
  border-radius: var(--radius); cursor: pointer;
}
.bearing-units-btn.active {
  background: var(--panel-strong); color: var(--accent);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

/* Per-method summary cards; the governing (lowest q_all) card is highlighted. */
.bearing-cards {
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  margin: 12px 0 4px;
}
.bearing-cards .summary-card.highlight { border-color: var(--accent); background: var(--accent-soft); }
.bearing-cards .summary-card small { color: var(--muted); }
.bearing-card-na { opacity: 0.75; }
.bearing-card-na strong { color: var(--muted); }
.bearing-governing-tag {
  display: inline-block; margin-left: 8px; padding: 1px 8px; border-radius: var(--radius-pill);
  font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  background: var(--accent); color: var(--fill-ink); vertical-align: 1px;
}

/* Inline client-side validation. */
.bearing-field-error { color: var(--danger); font-size: var(--fs-xs); }
#bearing-capacity-tab-panel .field.field-invalid input { border-color: var(--danger); }

/* Guidance / factor-detail disclosures + Hansen verdicts. */
.bearing-method-note ul { margin: 0 0 10px; padding-left: var(--space-4); }
.bearing-method-note li { margin-bottom: 4px; }
.bearing-factor-details { margin-top: 4px; }
.bearing-checks .nti-verdict { margin-left: 0; }
.bearing-check { margin-right: 12px; white-space: nowrap; }
.bearing-fs-field input { border-color: var(--accent); }

@media (max-width: 900px) {
  /* minmax(0, 1fr) so the stacked geometry column can shrink below its table's
     content width instead of pushing the page sideways. */
  .bearing-geo-layout { grid-template-columns: minmax(0, 1fr); }
}

/* Build/version stamp footer */
.app-footer {
  margin-top: var(--space-5);
  padding: var(--space-3) var(--space-4);
  text-align: center;
  font-size: var(--fs-xs);
  color: var(--muted);
  border-top: 1px solid var(--line);
}

/* Startup load-order failure banner (see assertRequiredGlobals in app.js) */
.startup-error {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  padding: var(--space-3) var(--space-4);
  background: var(--danger-strong);
  color: var(--fill-ink);
  font-size: var(--fs-base);
  text-align: center;
}

/* ===================== EV2 tab: Calculator / MIF Chart sub-tabs ===================== */
.ev2-subtabs {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin: var(--space-2) 0 0;
}

/* .ev2-subtab is a JS behavior hook only - the pill styling is the shared
   .subtab component (one tab language next to .tab-button). */

/* The sub-tab bar supplies the top spacing the two views used to get from
   .tab-panel / .calculator-flow directly. */
#ev2-calc-view.calculator-flow {
  margin-top: var(--space-3);
}

/* .calculator-flow's display:grid would otherwise override the hidden
   attribute (the same gotcha .tab-panel[hidden] guards against). */
#ev2-calc-view[hidden],
#ev2-mif-view[hidden] {
  display: none !important;
}

/* ===================== MIF Chart sub-tab ===================== */
/* Scoped under .mif-scope so nothing leaks into the rest of the app. */
.mif-scope {
  margin-top: var(--space-3);
  /* Chart series roles (validated palette): ordered blue ramp for the three
     reference support curves + the app's warm accent for the design curve. */
  --mif-curve-40: #86b6ef;
  --mif-curve-80: #2a78d6;
  --mif-curve-120: #104281;
  --mif-design: #bf6d3a;
}

.mif-layout {
  display: grid;
  grid-template-columns: minmax(250px, 310px) minmax(0, 1fr);
  gap: var(--space-4);
  align-items: start;
  margin-top: var(--space-3);
}

@media (max-width: 1000px) {
  .mif-layout {
    grid-template-columns: 1fr;
  }
}

.mif-controls {
  display: grid;
  gap: var(--space-3);
  align-content: start;
}

.mif-readout {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  padding: var(--space-4);
}

.mif-readout .mif-value-label {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}

.mif-readout .mif-value {
  font-family: "Space Grotesk", sans-serif;
  font-size: 2.6rem;
  font-weight: 700;
  line-height: 1.1;
  color: var(--mif-design);
  font-variant-numeric: tabular-nums;
}

.mif-readout .mif-meta {
  margin: var(--space-2) 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-sm);
  color: var(--muted);
}

.mif-readout .mif-meta li {
  margin-top: 2px;
}

.mif-readout .mif-meta strong {
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.mif-readout.mif-readout-empty,
.mif-readout.mif-readout-error {
  color: var(--muted);
  font-size: var(--fs-sm);
}

.mif-readout.mif-readout-error {
  border-color: #d9a1a1;
  background: var(--danger-soft);
  color: var(--danger-strong);
}

.mif-note-tag {
  display: inline-block;
  margin-top: var(--space-2);
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--warm);
  color: var(--warm);
  background: var(--warm-soft);
  font-size: var(--fs-xs);
  font-weight: 600;
}

.mif-chart-panel {
  min-width: 0;
}

.mif-chart-tabs {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 12px;
}

/* .mif-chart-tab is a JS behavior hook only - the pill styling is the shared
   .subtab component (one tab language next to .tab-button). */

.mif-chart {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  padding: var(--space-2);
}

.mif-chart svg {
  width: 100%;
  height: auto;
  display: block;
}

.mif-chart-placeholder {
  padding: var(--space-8) var(--space-4);
  text-align: center;
  color: var(--muted);
  font-size: var(--fs-sm);
}

.mif-tooltip {
  position: absolute;
  pointer-events: none;
  background: rgba(var(--tooltip-bg-rgb), 0.94);
  color: #fff;
  border-radius: var(--radius-sm);
  padding: 7px 10px;
  font-size: var(--fs-xs);
  line-height: 1.5;
  white-space: nowrap;
  z-index: 5;
  font-variant-numeric: tabular-nums;
}

.mif-tooltip .mif-tip-swatch {
  display: inline-block;
  width: 10px;
  height: 3px;
  border-radius: 2px;
  margin-right: 6px;
  vertical-align: 2px;
}

.mif-export-bar {
  margin-top: var(--space-3);
  display: flex;
  gap: var(--space-2);
}

.mif-footnote {
  color: var(--muted);
  font-size: var(--fs-xs);
  margin: var(--space-2) 0 0;
}

/* ===== Solutions Matrix generator (Optimizer sub-tab) ===== */
.solutions-scope .sm-block {
  margin-top: var(--space-4);
}
.solutions-scope .sm-block h3 {
  margin: 0 0 var(--space-2);
}
.solutions-scope .sm-matrix-wrap {
  overflow-x: auto;
}
.solutions-scope .sm-matrix {
  border-collapse: collapse;
  width: 100%;
  font-size: var(--fs-sm);
}
.solutions-scope .sm-matrix th,
.solutions-scope .sm-matrix td {
  border: 1px solid var(--line);
  padding: var(--space-2);
  text-align: center;
  vertical-align: middle;
}
.solutions-scope .sm-matrix thead th,
.solutions-scope .sm-matrix tbody th {
  background: var(--surface-2);
  font-weight: 600;
}
.solutions-scope .sm-matrix .sm-corner {
  background: var(--panel);
  text-align: start;
  white-space: nowrap;
}
.solutions-scope .sm-matrix thead th small {
  display: block;
  color: var(--muted);
  font-weight: 400;
  font-size: var(--fs-xs);
}
.solutions-scope .sm-matrix td {
  background: var(--panel);
}
.solutions-scope .sm-track {
  color: var(--accent);
}
.solutions-scope .sm-legend {
  color: var(--muted);
  font-size: var(--fs-xs);
  margin: var(--space-3) 0 0;
  line-height: 1.5;
}
/* P2 editable inputs */
.solutions-scope .sm-inputs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--space-4);
  margin: var(--space-3) 0;
}
.solutions-scope .sm-editor h3 {
  margin: 0 0 var(--space-2);
  font-size: var(--fs-sm);
}
.solutions-scope .sm-soil-head,
.solutions-scope .sm-soil-row {
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.solutions-scope .sm-traf-head,
.solutions-scope .sm-traf-row {
  display: grid;
  grid-template-columns: 0.8fr 1fr 1fr 1.2fr 1fr auto;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}
.solutions-scope .sm-soil-head,
.solutions-scope .sm-traf-head {
  color: var(--muted);
  font-size: var(--fs-xs);
}
.solutions-scope .sm-crit-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-2);
}
.solutions-scope .sm-crit-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--fs-xs);
}
.solutions-scope .sm-actions {
  margin-top: var(--space-3);
}
/* .sm-status is a JS behavior hook only — status styling (incl. .is-error)
   is the shared .tool-status component. */
.solutions-scope .sm-cell-flag {
  background: rgba(var(--warm-strong-rgb), 0.14);
}
.solutions-scope .sm-esal td:first-child,
.solutions-scope .sm-esal th {
  white-space: nowrap;
}

/* The session-bar palette picker (R6) - sized to sit with the .button.tiny
   session actions. */
.palette-select {
  flex: none;
  width: auto;
  padding: 5px 8px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--text);
  font-size: var(--fs-xs);
  font-weight: 600;
}

/* ===== Confirmation dialog (R4 of DESIGN-REVIEW-2026-07) =====================
   The one <dialog> behind Ev2Util.confirmAsync - deliberately as spartan as
   the window.confirm it replaced: message + two verbs. Native showModal()
   supplies focus trapping and Esc-to-cancel; the backdrop tints with the
   inverse-chip token so it stays a dark scrim in both themes. */
.confirm-dialog {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--panel);
  color: var(--text);
  box-shadow: var(--shadow);
  padding: var(--space-5);
  max-width: min(420px, 90vw);
}

.confirm-dialog::backdrop {
  background: rgba(var(--tooltip-bg-rgb), 0.55);
}

.confirm-message {
  margin: 0 0 var(--space-5);
  font-size: var(--fs-base);
  line-height: 1.5;
}

.confirm-actions {
  display: flex;
  gap: var(--space-2);
  justify-content: flex-end;
}

/* ===== External shell (external.html — the public Preliminary Design box) ====
   Moved out of external.html's embedded <style> block in R2 of
   DESIGN-REVIEW-2026-07 so every page styles from this one sheet. The page is
   also served by the internal box; these classes exist nowhere else. Its old
   .ext-error became the shared .auth-error component. */
.ext-shell { max-width: 920px; margin: 0 auto; padding: 24px 16px 48px; }
.ext-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 24px; }
.ext-brand { display: flex; align-items: center; gap: 10px; }
.ext-brand img { height: 34px; width: auto; }
.ext-brand strong { font-size: 1.05rem; color: var(--text); }
.ext-brand span { display: block; font-size: var(--fs-xs); color: var(--muted); }
.ext-auth-card { max-width: 420px; margin: 8vh auto 0; }
.ext-auth-card .field { margin-bottom: var(--space-3); }
.ext-auth-card .button { width: 100%; }
.ext-auth-card .auth-error { margin: 0 0 var(--space-2); }
#ext-logout { flex: none; }
