/* Pulsar Styles */

/* ── Theme tokens — round-2b palettes (design review 2026-08-10):
      light "Andromeda core" · dark "closer to dawn" · dusk "Andromeda".
      Colors sampled from David Dayag's M31 photograph; option sets and
      side-by-sides in the review artifact, adoption record in
      docs/BACKLOG.md #66. ──────────────────────────────────────────────── */
:root {
    --bg: #f0f2f4;            /* cool-biased SaaS gray (round 4): reads
                                 neutral even on warm-shifted displays */
    --surface: #ffffff;       /* true white cards — standard issue */
    --surface-alt: #f6f4ee;   /* insets, inputs, hover headers */
    --row-hover: #efece4;
    --border: #dcd9d0;
    --border-strong: #a3a094;
    --text: #241f2e;          /* space ink, violet-black */
    --text-2: #4f4859;        /* secondary */
    --text-muted: #837c8a;    /* hints, meta */
    --accent: #0c7489;        /* Pulsar signal teal, held from round 1 */
    --accent-hover: #0a5c6d;
    --accent-tint: #dcede7;
    --on-accent: #ffffff;     /* text painted on accent backgrounds */
    --link: #0f6478;          /* readable facility-name teal */
    --thead-bg: #f2ecdc;      /* faint gold (v3) — the lone strong-amber band
                                 on Browser read as out of place */
    --thead-text: #71603b;
    --ok: #337a4d;     --ok-bg: #e2f0e0;     --ok-bd: #badcba;
    --warn: #9c6a1a;   --warn-bg: #f8ecd2;   --warn-bd: #ead5a0;
    --star: #a8770f;   --star-tint: #f8ecd2; /* favorite stars: gold, not signal-blue */
    --danger: #ac3a30; --danger-bg: #f9e4de; --danger-bd: #edc2b7;
    --major: #7a5498;  --major-bg: #eee4f4;  --major-bd: #d7c4e6;
    --shadow-sm: 0 1px 2px rgba(40,38,32,.08), 0 4px 10px rgba(40,38,32,.08);
    --shadow-md: 0 8px 22px rgba(40,38,32,.13);
    --panel-overlay: rgba(255, 255, 255, 0.95);  /* floating panels over the map */

    /* ── Instrument scale (frontend-refresh chunk 1) ──────────────────
       Type: eight named steps — pick the nearest, never a new literal.
       Radii: three shapes. Spacing: use in new/edited rules. */
    --fs-nano: .62rem;      /* densest chrome */
    --fs-caption: .70rem;   /* captions, hints, pills */
    --fs-small: .76rem;     /* buttons, chips, meta */
    --fs-data: .82rem;      /* table cells, inputs */
    --fs-body: .88rem;      /* body copy */
    --fs-title: 1.05rem;    /* panel titles */
    --fs-heading: 1.35rem;  /* screen headings */
    --fs-display: 2rem;     /* KPI figures */
    --r-sm: 6px;
    --r-md: 10px;
    --r-pill: 999px;
    --radius: var(--r-md);
    --sp-1: 4px; --sp-2: 8px; --sp-3: 12px;
    --sp-4: 16px; --sp-5: 24px; --sp-6: 32px;
    /* One face across app + landing (Linux-first, like landing.css);
       --font-data carries instrument readouts — tabular digits. */
    --font-ui: "Liberation Sans", "DejaVu Sans", "Helvetica Neue", Arial, sans-serif;
    --font-data: "Liberation Mono", "DejaVu Sans Mono", Consolas, monospace;
    /* KPI slot accents + permit chip (were hardcoded + dark-patched) —
       galaxy quartet: steel blue / violet / amber / rust */
    --kpi-1: #46608f; --kpi-2: #8a5f9e; --kpi-3: #9c6a2e; --kpi-4: #a85450;
    --chip-fg: #6d5b8c; --chip-bd: #ddd8ca;

    --header-h: 52px;   /* header band */
    --fnav-h: 46px;     /* facility view-tab band under the header */

    /* Flow-line palette — MUST match the canvas literals in
       facility-map.js _flowStyles (the canvas doesn't read CSS tokens);
       change both together. Same values in every theme today. */
    --flow-gas: #c0392b; --flow-vapor: #e67e22;
    --flow-oil: #27ae60; --flow-mixed: #f1c40f;
}

/* ── Dark theme — Pulsar "void" palette (docs/archive/stellar-branding-plan.md):
      near-black canvas, signal-cyan accent. Data surfaces keep their
      contrast; the brand lives in the chrome. ─────────────────────────── */
:root[data-theme="dark"] {
    --bg: #0c1322;            /* "closer to dawn" — lifted off the void */
    --surface: #1a2540;
    --surface-alt: #253352;
    --row-hover: #2f4066;
    --border: #35466a;
    --border-strong: #5a6f9c;
    --text: #f2f5fc;
    --text-2: #b0bcd4;
    --text-muted: #7787a3;
    --accent: #62d9e8;        /* signal cyan — bright, so on-accent is dark */
    --accent-hover: #8ce6f2;
    --accent-tint: #143c50;
    --on-accent: #05070d;
    --link: #7fdcea;
    --thead-bg: #253352;
    --thead-text: #8fdcec;
    --ok: #4fdd8a;     --ok-bg: #16402a;     --ok-bd: #276b48;
    --warn: #ffc94d;   --warn-bg: #473913;   --warn-bd: #745d1c;
    --star: #ffc94d;   --star-tint: #473913; /* favorite stars: gold */
    --danger: #ff8078; --danger-bg: #4b2222; --danger-bd: #773636;
    --major: #c9b3ff;  --major-bg: #342857;  --major-bd: #534086;
    --shadow-sm: 0 1px 2px rgba(0,0,0,.45), 0 5px 14px rgba(0,0,0,.34);
    --shadow-md: 0 10px 26px rgba(0,0,0,.50);
    --panel-overlay: rgba(26, 37, 64, 0.95);
    --kpi-1: #8cb2f4; --kpi-2: #bda6f6; --kpi-3: #5ed3ba; --kpi-4: #f79c92;
    --chip-fg: #93dcea; --chip-bd: #35466a;
}

/* ── Dusk theme — "Andromeda" (round 2b; replaced #42's blue-hour slate,
      whose token block is archived in docs/BACKLOG.md #66): violet space
      ground, dust-lane mauve surfaces, core gold on table headers, warm
      disk-colored status hues. The amber core glow at the bottom of the
      window replaces the blue-hour wash. Signal cyan at full brightness —
      dusk no longer dims it. ─────────────────────────────────────────── */
:root[data-theme="dusk"] {
    /* Option A "blue hour" RESTORED 2026-08-11 — Kyle: the Andromeda
       violet ground was "hard on the eyes from a contrast perspective".
       B's token block is archived in docs/BACKLOG.md #66. */
    --bg: #252e55;            /* real blue-hour indigo */
    --surface: #2f3a68;
    --surface-alt: #394779;
    --row-hover: #43538c;
    --border: #4a5a95;
    --border-strong: #6d80bd;
    --text: #f2f4fc;
    --text-2: #c6cfe8;
    --text-muted: #8f9ac0;
    --accent: #5fd7e8;        /* full-brightness signal */
    --accent-hover: #8ae4f1;
    --accent-tint: #1d4360;
    --on-accent: #0a1520;
    --link: #86dcec;
    --thead-bg: #394779;
    --thead-text: #9fe0ee;
    --ok: #5fd695;     --ok-bg: #1d4a38;     --ok-bd: #2f6e50;
    --warn: #ffca66;   --warn-bg: #4d3d1a;   --warn-bd: #776028;
    --star: #ffca66;   --star-tint: #4d3d1a; /* favorite stars: gold */
    --danger: #ff8f86; --danger-bg: #56262c; --danger-bd: #7e3a42;
    --major: #c7b5ff;  --major-bg: #3d3268;  --major-bd: #5c4a94;
    --shadow-sm: 0 1px 2px rgba(6,9,22,.40), 0 4px 12px rgba(6,9,22,.34);
    --shadow-md: 0 8px 24px rgba(6,9,22,.50);
    --panel-overlay: rgba(47, 58, 104, 0.95);
    --kpi-1: #95b5f8; --kpi-2: #bda9f4; --kpi-3: #68d2c2; --kpi-4: #f7a29a;
    --chip-fg: #9fe0ee; --chip-bd: #4a5a95;
}

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

html { background: var(--bg); }

/* ── Native-control baseline (#65 theme-correctness sweep) ─────────────
   Every "white box in dark mode" bug traced to ONE cause: no themed base
   rule for bare input/select/textarea, so unclassed controls (Modeling's
   Run Title, History's filter, the dp-input date fields, GHG/library/
   packages selects) fell back to UA white. :where() keeps specificity at
   ZERO so every existing component class still wins unchanged. */
:where(input:not([type="checkbox"], [type="radio"], [type="range"],
                 [type="color"], [type="file"]), select, textarea) {
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    font-family: var(--font-ui);
    font-size: var(--fs-data);
    padding: 5px 8px;
}
/* color-scheme drives everything the page can't style directly: native
   select popups, date spinners, and the OS scrollbars — the light-gray
   bars that were the brightest pixels on every dark screen. */
:root { color-scheme: light; }
:root[data-theme="dark"], :root[data-theme="dusk"] { color-scheme: dark; }
:root[data-theme="dark"], :root[data-theme="dusk"] {
    scrollbar-color: var(--border-strong) transparent;
}
/* The imports upload control was raw UA chrome in every theme. */
input[type="file"]::file-selector-button {
    background: var(--surface-alt); color: var(--text);
    border: 1px solid var(--border-strong); border-radius: var(--r-sm);
    padding: 5px 10px; margin-right: 10px;
    font: 600 var(--fs-small) var(--font-ui); cursor: pointer;
}
input[type="file"]::file-selector-button:hover { background: var(--row-hover); }
/* Unclassed anchors (Compliance filing links) rendered UA colors — the
   "salmon links": color-scheme dark's VISITED default. */
:where(a) { color: var(--link); }
:where(a:visited) { color: var(--link); }
/* The "‹ Permits" back-chip had no rule at all — UA gray in every theme. */
.crumb-back {
    background: var(--surface-alt); color: var(--text-2);
    border: 1px solid var(--border); border-radius: var(--r-sm);
    padding: 3px 10px; cursor: pointer;
    font: 600 var(--fs-small) var(--font-ui); white-space: nowrap;
}
.crumb-back:hover { background: var(--row-hover); color: var(--text); }

body {
    font-family: var(--font-ui);
    background: var(--bg);
    color: var(--text);
    min-height: 100vh;
}

/* ── Faint starfield, dark + dusk themes (experiment, 2026-07-21;
   dusk added in task #42). The landing page's sky, dialed WAY down, fixed
   behind the data surfaces. Same star shadow lists as landing.css .f1/.f3
   so the pages share one sky. Dusk shows the same stars dimmer — first
   stars out — over the amber core-glow wash. Light gets a chart of M31
   instead (round 2b). */
:root[data-theme="dark"] body { background: transparent; }
/* Dusk: the blue-hour horizon wash — warm rose into steel blue pooling
   along the bottom of the WINDOW (fixed attachment); option A's sky. */
:root[data-theme="dusk"] body {
    background: linear-gradient(to top,
        rgba(206, 126, 122, .34) 0%, rgba(148, 118, 182, .26) 12%,
        rgba(84, 118, 196, .18) 27%, rgba(37, 46, 85, 0) 46%) fixed;
}
:root[data-theme="dark"] body::before,
:root[data-theme="dark"] body::after,
:root[data-theme="dusk"] body::before,
:root[data-theme="dusk"] body::after {
    content: ""; position: fixed; top: 0; left: 0; width: 1px; height: 1px;
    z-index: -1; pointer-events: none;
}
/* the sparser layer carries the COLOR: 2px stars + a soft glow, like
   the landing's .f2/.f4 accent layers — hue is invisible at 1px */
:root[data-theme="dark"] body::after,
:root[data-theme="dusk"] body::after {
    width: 2px; height: 2px;
    filter: drop-shadow(0 0 3px rgba(238, 242, 250, .55));
}
:root[data-theme="dark"] body::before,
:root[data-theme="dusk"] body::before {
    opacity: .68;   /* round 2c: Kyle asked for more drama, twice */
    animation: star-blink-a 6s ease-in-out infinite alternate;
    box-shadow:
        760px 110px #ffd9a3, 1020px 320px #8fb8ff, 1250px 90px #eef2fa,
        1400px 380px #7fdcea, 940px 480px #ffe9c4, 1180px 560px #9ec1ff,
        60px 760px #ff8a66, 380px 840px #d9c9ff, 660px 780px #ffd9a3,
        930px 880px #62d9e8, 1180px 800px #cfe2ff, 1390px 720px #ffe9c4,
        160px 90px #eef2fa, 340px 40px #ffc76e, 90px 300px #8fb8ff,
        1330px 940px #ff9d7e, 720px 940px #eef2fa, 240px 950px #a5e8f0,
        1660px 240px #cfe2ff, 1820px 520px #ffd9a3, 1560px 700px #eef2fa,
        1740px 880px #a5e8f0, 1900px 130px #ffe9c4,
        520px 220px #cfe2ff, 1140px 40px #ffe9c4, 460px 560px #d9c9ff,
        840px 690px #cfe2ff, 1480px 850px #ffc76e, 2050px 340px #eef2fa,
        2240px 90px #cfe2ff, 2180px 620px #ffe9c4, 2400px 460px #a5e8f0,
        130px 1080px #cfe2ff, 690px 1160px #ffd9a3, 1240px 1100px #eef2fa,
        1830px 1140px #a5e8f0, 2300px 1060px #ff9d7e,
        /* round-2b densification (dark-drama experiment; diverges from
           the landing sky deliberately — dusk shows these too, dimmer) */
        250px 180px #ffe9c4, 470px 350px #cfe2ff, 610px 480px #eef2fa,
        790px 240px #a5e8f0, 1060px 470px #ffd9a3, 1310px 260px #cfe2ff,
        1500px 140px #ffe9c4, 1620px 460px #eef2fa, 1760px 640px #ffd9a3,
        1930px 380px #cfe2ff, 2110px 780px #a5e8f0, 2330px 260px #ffe9c4,
        2470px 660px #cfe2ff, 350px 660px #eef2fa, 560px 900px #ffd9a3,
        980px 1060px #cfe2ff, 1420px 1000px #ffe9c4, 1700px 1090px #8fb8ff,
        2010px 960px #eef2fa, 2440px 1140px #ffd9a3,
        /* round 2c: second densification pass */
        180px 420px #cfe2ff, 430px 130px #ffe9c4, 700px 620px #eef2fa,
        920px 340px #ffd9a3, 1230px 620px #cfe2ff, 1450px 320px #a5e8f0,
        1590px 880px #ffe9c4, 1880px 760px #cfe2ff, 2150px 480px #ffd9a3,
        2390px 880px #eef2fa, 300px 1150px #ffe9c4, 810px 1120px #cfe2ff,
        1360px 1160px #ffd9a3, 1960px 1120px #a5e8f0, 2520px 320px #ffe9c4,
        2540px 940px #cfe2ff;
}
:root[data-theme="dark"] body::after,
:root[data-theme="dusk"] body::after {
    opacity: .54;   /* round 2c: more drama */
    animation: star-blink-b 8.5s ease-in-out 1.4s infinite alternate;
    box-shadow:
        820px 60px #a5e8f0, 1090px 120px #ffbe5c, 1355px 210px #cfe2ff,
        985px 250px #d9c9ff, 700px 300px #ffe9c4, 1230px 420px #ff8a66,
        880px 620px #cfe2ff, 1440px 550px #ffd9a3, 200px 820px #a5e8f0,
        540px 890px #eef2fa, 810px 860px #cfe2ff, 1260px 880px #ffe9c4,
        40px 480px #ffd9a3, 300px 640px #8fb8ff,
        1620px 90px #eef2fa, 1780px 360px #cfe2ff, 1560px 940px #ffd9a3,
        260px 400px #ffe9c4, 610px 130px #cfe2ff, 1010px 780px #ffd9a3,
        1960px 760px #9ec1ff, 2120px 220px #e3d6ff, 2350px 890px #ffe9c4,
        420px 1120px #cfe2ff, 980px 1180px #62d9e8, 1540px 1090px #ffc76e,
        2060px 1170px #eef2fa,
        /* round-2b densification */
        150px 250px #ffd9a3, 640px 520px #cfe2ff, 1180px 300px #eef2fa,
        1520px 420px #ffe9c4, 1860px 200px #a5e8f0, 2260px 420px #ffd9a3,
        360px 1010px #cfe2ff, 900px 990px #ffe9c4, 1360px 760px #62d9e8,
        1700px 900px #ffd9a3, 2160px 980px #cfe2ff, 2420px 780px #ffe9c4,
        760px 150px #d9c9ff, 2510px 180px #eef2fa,
        /* round 2c: second densification pass */
        250px 540px #ffe9c4, 540px 340px #cfe2ff, 1060px 620px #ffd9a3,
        1290px 140px #a5e8f0, 1620px 660px #cfe2ff, 1990px 520px #ffe9c4,
        2340px 250px #ffd9a3, 470px 1060px #eef2fa, 1120px 1080px #ffe9c4,
        1760px 1140px #cfe2ff, 2260px 1140px #ffd9a3, 2550px 620px #a5e8f0;
}
/* Dusk: the same stars, dimmed to "first stars out" (Brighter option from
   the #42 mockup — both layers awake at ~.36, shallower twinkle). */
:root[data-theme="dusk"] body::before {
    opacity: .34; animation-name: star-blink-dusk-a;
}
:root[data-theme="dusk"] body::after {
    opacity: .36; animation-name: star-blink-dusk-b;
}
/* a LITTLE twinkle — slow, shallow, and frozen for reduced-motion */
@keyframes star-blink-a { from { opacity: .66; } to { opacity: .96; } }
@keyframes star-blink-b { from { opacity: .52; } to { opacity: .82; } }
@keyframes star-blink-dusk-a { from { opacity: .30; } to { opacity: .46; } }
@keyframes star-blink-dusk-b { from { opacity: .32; } to { opacity: .50; } }
@media (prefers-reduced-motion: reduce) {
    :root[data-theme="dark"] body::before,
    :root[data-theme="dark"] body::after,
    :root[data-theme="dusk"] body::before,
    :root[data-theme="dusk"] body::after { animation: none; }
}

/* ── Light theme's sky (backdrop C, 2026-08-12): the Milky Way band +
   a nebulous Andromeda pinned bottom-right. Both generated by
   docs/mockups/make_milkyway.py — edit the parameters there and re-run
   to retune. The band ships as a PRE-RASTERIZED WebP, not the SVG it
   is drawn as: its three big feGaussianBlur filters cost ~65ms of
   full-viewport rasterization per load (2.5× the other themes' first
   paint), where the raster just decodes. Regen recipe lives in
   make_milkyway.py's docstring. Andromeda stays SVG — pixel-art rects,
   no filters, free. ─────────────────────────────────────────────── */
:root[data-theme="light"] body {
    background:
        url("../assets/andromeda-light.svg?v=3")
            right -60px bottom -70px / 420px auto no-repeat fixed,
        url("../assets/milkyway-light.webp?v=1") center / cover no-repeat fixed;
    /* NO color layer: html paints var(--bg). */
}

header {
    background: var(--surface);
    padding: 12px 24px;
    display: flex;
    align-items: center;
    gap: 24px;
    border-bottom: 2px solid var(--border);
}

header h1 {
    color: var(--accent);
    font-size: var(--fs-heading);
    white-space: nowrap;
}

.facility-info {
    /* Lives in the facility view-tab band, not the top bar (task #53
       chunk 1c). Since 2026-08-04 a CHIP centered in the free space
       between the tabs and the Focus/Power slider (Kyle: "more
       noticeable and readable"). One line, ellipsized, full on hover. */
    flex: 1; min-width: 0; padding: 0 14px;
    display: flex; align-items: center; justify-content: center;
}
.fac-desc-chip {
    /* plain text, no pill (Kyle 2026-08-04) — keep the readable size,
       bold accent name, centered placement */
    max-width: 100%; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--fs-data); color: var(--text);
}
.fac-desc-chip b { color: var(--accent); font-weight: 700; }
.fac-desc-rest { color: var(--text-2); }

main {
    display: flex;
    height: calc(100vh - var(--header-h) - var(--fnav-h));
}

/* Equipment Toolbar */
.equipment-toolbar {
    width: 170px;
    background: var(--surface);
    border-right: 2px solid var(--border);
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    flex-shrink: 0;
}

.toolbar-title {
    padding: 12px 12px 2px;
    font-size: var(--fs-data);
    font-weight: 600;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.toolbar-hint {
    padding: 0 12px 10px;
    font-size: var(--fs-caption);
    color: var(--text-muted);
}

.toolbar-items {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 0 8px 12px;
}

.toolbar-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 8px;
    background: var(--surface-alt);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    cursor: grab;
    user-select: none;
    font-size: var(--fs-small);
    color: var(--text);
    transition: border-color 0.15s, background 0.15s;
}

.toolbar-item:hover {
    border-color: var(--accent);
    background: var(--bg);
}

.toolbar-item:active {
    cursor: grabbing;
}

.toolbar-item .item-color {
    width: 14px;
    height: 14px;
    border-radius: 3px;
    flex-shrink: 0;
}

.toolbar-item .item-icon {
    width: 22px;
    height: 22px;
    object-fit: contain;
    flex-shrink: 0;
}

.eq-field .type-icon {
    height: 16px;
    vertical-align: -3px;
    margin-right: 5px;
}

/* Facility Map */
.facility-map-container {
    flex: 1;
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 16px;
    /* BOTH axes must ignore content floors. min-width matters most: the
       canvas bitmap (= box × devicePixelRatio) is the canvas's intrinsic
       width, and with min-width:auto this container's width floors at it —
       at any browser zoom > 100% that is an EXPONENTIAL feedback loop
       (box → bitmap ×dpr → intrinsic → wider box → …) that ran the canvas
       to 33 million px and a blank screen (2026-08-10, dpr 1.25). */
    min-height: 0;
    min-width: 0;
}

#facility-map {
    background: var(--surface-alt);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    cursor: pointer;
    flex: 1;
    /* CRITICAL: a canvas's bitmap is its intrinsic size, and flex's
       default min-height:auto refuses to shrink below it — so the box
       could grow (bitmap follows via ResizeObserver) but never shrink
       again: a one-way ratchet. Boot alone triggers it (the facility
       tab band appears after the first sizing pass and steals 46px),
       leaving the canvas overflowing its container — borderless bottom
       edge, phantom page scroll, and it compounds with every resize.
       min-height/width:0 hands the box entirely to flexbox. */
    min-height: 0;
    min-width: 0;
}

.map-legend {
    position: absolute;
    top: 24px;
    right: 24px;
    background: var(--panel-overlay);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    box-shadow: var(--shadow-sm);
    padding: 12px 16px;
    font-size: var(--fs-data);
}

.map-legend h3 {
    color: var(--accent);
    margin-bottom: 8px;
    font-size: var(--fs-data);
}

.legend-item {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 4px;
}

.legend-color {
    width: 14px;
    height: 14px;
    border-radius: 3px;
    /* the applicability chips carry a mark (! / – / ?), #55 ch 7 */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    font-weight: 700;
    box-sizing: border-box;
}

.legend-icon {
    width: 20px;
    height: 20px;
    object-fit: contain;
    flex-shrink: 0;
}

.legend-line {
    width: 20px;
    height: 3px;
    border-radius: 1px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: var(--fs-nano);
    color: white;
}
.legend-line.flow-gas   { background: var(--flow-gas); }
.legend-line.flow-vapor { background: var(--flow-vapor); }
.legend-line.flow-oil   { background: var(--flow-oil); }
.legend-line.flow-mixed { background: var(--flow-mixed); }

.legend-separator {
    border-top: 1px solid var(--border);
    margin: 8px 0;
}

/* Detail Panel */
.detail-panel {
    width: 380px;
    background: var(--surface);
    border-left: 2px solid var(--border);
    display: flex;
    flex-direction: column;
    overflow-y: auto;
}

.panel-header {
    padding: 16px;
    border-bottom: 1px solid var(--border);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.panel-header h2 {
    font-size: var(--fs-title);
    color: var(--accent);
}

.panel-title-wrap {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;   /* let long titles ellipsis instead of pushing the close btn */
}

#panel-icon {
    width: 34px;
    height: 34px;
    object-fit: contain;
    flex-shrink: 0;
}

.close-btn {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: var(--fs-heading);
    cursor: pointer;
    padding: 4px 8px;
    border-radius: var(--r-sm);
}

.close-btn:hover {
    color: var(--danger);
    background: rgba(231, 76, 60, 0.1);
}

.panel-content {
    padding: 16px;
    flex: 1;
}

/* Lists are content, not empty-state copy — never center their items
   (#69: GHG's obligation bullets sat detached from centered text). */
ul.hint, ol.hint { text-align: left; margin-top: 8px; }
.hint {
    color: var(--text-muted);
    font-style: italic;
    text-align: center;
    margin-top: 40px;
}

/* Equipment detail sections */
.eq-section {
    margin-bottom: 16px;
}

.eq-section h3 {
    color: var(--accent);
    font-size: var(--fs-data);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 8px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--border);
}

.eq-field {
    display: flex;
    justify-content: space-between;
    padding: 4px 0;
    font-size: var(--fs-data);
}

.eq-field .label {
    color: var(--text-2);
}

.eq-field .value {
    color: var(--text);
    font-weight: 500;
}

.status-active {
    color: var(--ok);
}

.status-inactive {
    color: var(--danger);
}

/* Emissions table */
.emissions-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--fs-data);
    margin-top: 4px;
}

.emissions-table th {
    text-align: left;
    color: var(--text-2);
    padding: 4px 8px;
    border-bottom: 1px solid var(--border);
}

.emissions-table td {
    padding: 4px 8px;
}

/* Run Determination Button */

/* Modal */
.modal-overlay {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.7);
    /* Above Leaflet's internal panes/controls (they go up to 1000) and the
       slide-over detail panel (1200); below toasts (3000). */
    z-index: 2000;
    justify-content: center;
    align-items: center;
}

.modal-overlay.active {
    display: flex;
}

.modal {
    background: var(--surface);
    border: 2px solid var(--border);
    border-radius: var(--r-md);
    width: 680px;
    max-height: 85vh;
    overflow-y: auto;
}

.modal-header {
    padding: 16px 20px;
    border-bottom: 1px solid var(--border);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.modal-header h2 {
    color: var(--accent);
    font-size: var(--fs-title);
}

.modal-body {
    padding: 20px;
}

/* Determination result styling */
.determination-result {
    font-size: var(--fs-body);
}

.result-badge {
    display: inline-block;
    padding: 6px 16px;
    border-radius: var(--r-pill);
    font-weight: 700;
    font-size: var(--fs-title);
    margin-bottom: 16px;
}

/* Applicability palette (#55 ch 7): accent = act, neutral = no action —
   the red/green pair (and its two hardcoded rgba()s) retired; red/green
   is reserved for genuinely good/bad states like OVER CAP. */
.result-badge.applicable {
    background: var(--accent-tint);
    color: var(--accent);
    border: 1px solid var(--accent);
}

.result-badge.not-applicable {
    background: var(--surface-alt);
    color: var(--text-2);
    border: 1px solid var(--border-strong);
}

.result-badge.indeterminate {
    background: var(--warn-bg);
    color: var(--warn);
    border: 1px solid var(--warn-bd);
}

/* ── The notice system (2026-08-18, Kyle's pick: signal rule on a glow
   tint). ONE family for every attention strip — the twelve one-off
   banner classes (wb-error, indet-banner, stale-banner, ghg-banner,
   fleet-gap, permit-mismatch, burn-warning/-ok, modal-burn-warning,
   wb-custom-banner) are retired onto it; old names may survive on
   elements as unstyled hooks for drivers. Anatomy: a faint color-mix
   fill (never the heavy *-bg tints), hairline --border, an inset
   "signal rule" with a status dot at its head (the pulsar-beacon
   motif), a small-caps eyebrow naming the state, and body copy that is
   ALWAYS --text. Intent modifiers: .warn (default) / .danger (broken)
   / .major (regulatory fact — required is not the same as broken) /
   .ok / .neutral. ONE loudness level by design: never border with the
   saturated hue, never color body copy. Danger dots pulse; reduced
   motion stills them. Deliberate survivors OUTSIDE the family: toasts
   (same recipe, floating), the pill/badge chips, .cov-missing/.rd-chip
   action chips, the readiness empty-state card, .stale-notice (quiet
   text + inline action). Markup via window.noticeHtml (app.js). */
.notice {
    --hue: var(--warn);
    position: relative; margin: 0 0 12px; padding: 9px 13px 9px 20px;
    font-size: var(--fs-small); line-height: 1.45; color: var(--text);
    background: color-mix(in srgb, var(--hue) 9%, var(--surface));
    border: 1px solid var(--border); border-radius: var(--r-sm);
    text-align: left;
}
.notice::before {
    content: ""; position: absolute; left: 8px; top: 15%; bottom: 15%;
    width: 2px; border-radius: 2px; background: var(--hue);
}
.notice.danger  { --hue: var(--danger); }
.notice.major   { --hue: var(--major); }
.notice.ok      { --hue: var(--ok); }
.notice.neutral { --hue: var(--text-muted); }
.notice-eyebrow {
    display: flex; align-items: center; gap: 7px;
    font-size: var(--fs-nano); font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--hue); margin-bottom: 3px;
}
.notice-dot { width: 7px; height: 7px; border-radius: 50%;
    background: var(--hue); flex: none; }
.notice.danger .notice-dot { animation: notice-beacon 1.8s ease-out infinite; }
@keyframes notice-beacon {
    0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--hue) 55%, transparent); }
    70%, 100% { box-shadow: 0 0 0 6px transparent; }
}
@media (prefers-reduced-motion: reduce) {
    .notice.danger .notice-dot { animation: none; }
}
.notice-body ul { margin: 6px 0 4px 18px; }
/* multi-line server messages keep their line breaks (wbError only —
   call-site template literals must NOT pre-wrap their indentation) */
#wb-error .notice-body { white-space: pre-wrap; }

.det-section {
    margin-bottom: 16px;
}

.det-section h4 {
    color: var(--accent);
    font-size: var(--fs-data);
    margin-bottom: 8px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.det-section p {
    margin-bottom: 4px;
    line-height: 1.5;
}

.det-section ul {
    padding-left: 20px;
}

.det-section li {
    margin-bottom: 6px;
    line-height: 1.4;
}

.standards-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 8px;
    margin-top: 8px;
}

.standard-card {
    background: var(--surface-alt);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    padding: 12px;
    text-align: center;
}

.standard-card .pollutant {
    font-size: var(--fs-data);
    color: var(--text-2);
    margin-bottom: 4px;
}

.standard-card .limit {
    font-size: var(--fs-heading);
    font-weight: 700;
    color: var(--text);
}

.standard-card .unit {
    font-size: var(--fs-caption);
    color: var(--text-muted);
}

/* Decision tree walkthrough steps */
.tree-step {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin-bottom: 12px;
    padding: 8px 12px;
    background: var(--surface-alt);
    border-radius: var(--r-sm);
    border-left: 3px solid var(--accent);
}

.tree-step .step-number {
    background: var(--accent);
    color: var(--on-accent);
    width: 24px;
    height: 24px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--fs-small);
    font-weight: 700;
    flex-shrink: 0;
}

.tree-step .step-content {
    flex: 1;
}

.tree-step .step-question {
    color: var(--text-2);
    font-size: var(--fs-data);
}

.tree-step .step-answer {
    color: var(--text);
    font-weight: 500;
}

/* Gap engines: the finding is called out by this chip alone. Recolouring the
   whole step (the first attempt) shouted louder than the finding warrants —
   it is an explanation of the verdict, not a warning about it. */
/* One determination per row: name · status · action. Replaced a badge list
   plus a separate stack of full-width Run buttons, where each subpart
   appeared twice and its status sat far from its button. */
.det-row {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 0;
    border-bottom: 1px solid var(--border);
}
.det-row:last-of-type { border-bottom: none; }
.det-row-name {
    flex: 1 1 auto; min-width: 0;
    font-size: var(--fs-data); color: var(--text);
    overflow-wrap: anywhere;
}
.det-row-status { flex: 0 0 auto; display: flex; align-items: center; gap: 4px; }
.det-row-run { flex: 0 0 auto; min-width: 56px; }

.gap-chip {
    display: inline-block;
    background: var(--warn); color: var(--on-accent);
    border-radius: var(--r-sm);
    padding: 1px 7px; margin-right: 6px;
    font-size: var(--fs-caption); font-weight: 700;
    letter-spacing: .04em; white-space: nowrap;
    vertical-align: 1px;
}

.tree-step .step-note {
    margin-top: 4px;
    font-size: var(--fs-caption);
    color: var(--text-muted);
    line-height: 1.45;
}

/* Flow lines on the map */
.flow-line {
    stroke: var(--border);
    stroke-width: 2;
}

/* Toggle switch */
.toggle-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 6px 0;
    font-size: var(--fs-data);
}

.toggle-row .label {
    color: var(--text-2);
}

.toggle-switch {
    position: relative;
    width: 42px;
    height: 22px;
    cursor: pointer;
}

.toggle-switch input {
    opacity: 0;
    width: 0;
    height: 0;
}

.toggle-slider {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    background: var(--border);
    border-radius: var(--r-pill);
    transition: 0.2s;
}

.toggle-slider::before {
    content: "";
    position: absolute;
    width: 16px;
    height: 16px;
    left: 3px;
    bottom: 3px;
    background: var(--text-2);
    border-radius: 50%;
    transition: 0.2s;
}

.toggle-switch input:checked + .toggle-slider {
    background: var(--border);
}

.toggle-switch input:checked + .toggle-slider::before {
    transform: translateX(20px);
    background: var(--accent);
}

/* O2% input field */
.ecfr-fav-below { color: var(--warn); font-size: var(--fs-nano); margin-left: 6px;
    vertical-align: 2px; }

.spec-help-mark { display: inline-block; width: 13px; height: 13px; padding: 0;
    border: 0; border-radius: 50%; background: var(--accent-tint); color: var(--accent);
    font: inherit; font-size: var(--fs-nano); font-weight: 700; text-align: center;
    line-height: 13px; cursor: help; vertical-align: 1px; position: relative; }
.spec-help-mark.open { background: var(--accent); color: var(--bg); }
/* hover / keyboard-focus tooltip from data-help; click pins the same
   text as .spec-help-text under the row (toggleSpecHelp) */
.spec-help-mark::after { content: attr(data-help); display: none; position: absolute;
    left: 0; top: 17px; z-index: 40; width: max-content; max-width: 280px;
    padding: 6px 8px; border-radius: 6px; background: var(--bg-elev, var(--bg));
    color: var(--text); border: 1px solid var(--border); box-shadow: 0 4px 14px rgba(0,0,0,.18);
    font-size: var(--fs-caption); font-weight: 400; line-height: 1.35; text-align: left;
    white-space: normal; pointer-events: none; }
.spec-help-mark:hover::after, .spec-help-mark:focus-visible::after { display: block; }
.spec-help-mark.open:hover::after { display: none; }
/* calculated stats of an analysis sheet (2026-08-28) */
.fa-stats { margin: 6px 0 8px; }
.fa-stats-table { width: 100%; table-layout: fixed; font-size: var(--fs-data); }
.fa-stats-table td { padding: 3px 6px; white-space: normal; }
.fa-stats-table td:nth-child(2) { width: 34%; }
/* fugitive panel count tables (2026-08-28) */
.fug-counts .fug-hint { color: var(--text-muted); font-size: var(--fs-caption); margin: 0 0 6px; line-height: 1.35; }
.fug-table { width: 100%; table-layout: fixed; font-size: var(--fs-data); }
.fug-table th, .fug-table td { padding: 4px 6px; vertical-align: middle; white-space: normal; }
.fug-table th:last-child, .fug-table td:last-child { width: 96px; text-align: right; }
.fug-table .fug-muted { margin-top: 1px; line-height: 1.3; }
/* outrank the base .spec-input width (150px) and .fac-table's nowrap first cell */
.eq-section .fug-table input.fug-count-input { width: 84px; min-width: 0; }
.eq-section .fug-table td:first-child, .eq-section .fug-table th:first-child { white-space: normal; }
.fug-muted { color: var(--text-muted); font-size: var(--fs-caption); }
.fug-wait { color: var(--text-muted); font-style: italic; }
.spec-help-text { grid-column: 1 / -1; margin: -2px 0 6px; padding: 6px 8px; border-radius: 6px;
    background: var(--accent-tint); color: var(--text); font-size: var(--fs-caption);
    line-height: 1.35; white-space: normal; }

.o2-input-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 6px 0;
    font-size: var(--fs-data);
}

.o2-input-row .label {
    color: var(--text-2);
}

.o2-input {
    width: 72px;
    padding: 4px 8px;
    background: var(--surface-alt);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    color: var(--text);
    font-size: var(--fs-data);
    text-align: right;
}

.o2-input:focus {
    outline: none;
    border-color: var(--accent);
}

/* Editable spec fields in the detail panel — numbers right-align
   (readouts), text and selects read left. */
.spec-input,
.spec-select {
    width: 150px;
    padding: 4px 8px;
    background: var(--surface-alt);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    color: var(--text);
    font-size: var(--fs-data);
}

.spec-input { text-align: right; }

.spec-select,
.spec-input.spec-text {
    text-align: left;
}

.spec-input:focus,
.spec-select:focus {
    outline: none;
    border-color: var(--accent);
}

/* ── Date picker (js/datepicker.js) ───────────────────────────────────
   Replaced <input type="date"> everywhere 2026-08-09. The native control
   is browser chrome: unthemeable, and Firefox's month/year sub-panel does
   not collapse on selection. The rules that used to sit here only chose a
   color-scheme for that chrome; they are gone with it.
   .dp-input is a plain text input — no wrapper — so the six call sites
   keep their existing layout. The glyph is a background image. */
.dp-input {
    background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M8 3v4M16 3v4M3 10h18'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 7px center;
    background-size: 14px 14px;
    padding-right: 26px !important;
}
/* Restates the GEOMETRY as well as the image. This selector outranks a
   container's `input` rule (0,2,0 vs 0,1,1), so declaring the image alone
   let the glyph win while repeat/size lost — which is precisely how it
   ended up tiled across the box. Image and geometry travel together. */
:root[data-theme="dark"] .dp-input,
:root[data-theme="dusk"] .dp-input {
    background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M8 3v4M16 3v4M3 10h18'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 7px center;
    background-size: 14px 14px;
}

.dp-pop {
    position: fixed; z-index: 4000;
    width: 252px; padding: 8px;
    background: var(--surface); color: var(--text);
    border: 1px solid var(--border-strong); border-radius: var(--r-md);
    box-shadow: var(--shadow-md);
    font-size: var(--fs-small);
    user-select: none;
}
.dp-head { display: flex; align-items: center; gap: 2px; margin-bottom: 6px; }
.dp-title {
    flex: 1; text-align: center; font-weight: 600;
    font-size: var(--fs-body); color: var(--text);
    display: inline-flex; align-items: center; justify-content: center; gap: 4px;
    background: none; border: 1px solid transparent; border-radius: var(--r-sm);
    font-family: inherit; padding: 2px 6px; cursor: pointer;
}
.dp-title:hover { background: var(--accent-tint); color: var(--accent-hover); }
.dp-caret { font-size: 8px; color: var(--text-muted); }
.dp-title:hover .dp-caret { color: var(--accent-hover); }

/* One fixed-height body for BOTH views, so switching between the day grid
   and the month/year chooser cannot resize the popup — same reason the grid
   always renders six rows. */
.dp-body { height: 190px; overflow: hidden; }

.dp-my { display: flex; gap: 6px; height: 100%; }
.dp-my-col {
    flex: 1; overflow-y: auto; overscroll-behavior: contain;
    display: flex; flex-direction: column; gap: 2px;
    padding-right: 2px;
}
.dp-my-col[data-col="month"] { flex: 0 0 40%; }
.dp-my-opt {
    flex: 0 0 auto;
    background: none; border: 1px solid transparent; border-radius: var(--r-sm);
    color: var(--text); cursor: pointer;
    font-family: inherit; font-size: var(--fs-small);
    padding: 5px 4px; text-align: center;
}
.dp-my-opt:hover { background: var(--accent-tint); color: var(--accent-hover); }
.dp-my-sel {
    background: var(--accent); color: var(--on-accent); font-weight: 600;
}
.dp-my-sel:hover { background: var(--accent-hover); color: var(--on-accent); }
.dp-nav {
    background: none; border: 1px solid transparent; border-radius: var(--r-sm);
    color: var(--text-2); cursor: pointer;
    font-size: var(--fs-body); line-height: 1; padding: 3px 7px;
}
.dp-nav:hover { background: var(--accent-tint); color: var(--accent-hover); }
.dp-dow, .dp-grid {
    display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px;
}
.dp-dow span {
    text-align: center; font-size: var(--fs-caption);
    color: var(--text-muted); padding-bottom: 2px;
}
.dp-day {
    /* Fixed box, centred content. The empty pad cells carry no text, so
       letting height come from content made a row of pads shorter than a row
       of dates — the popup then still changed height month to month even
       after the grid was padded to a constant 42 cells. */
    box-sizing: border-box;
    min-height: 26px;
    display: flex; align-items: center; justify-content: center;
    background: none; border: 1px solid transparent; border-radius: var(--r-sm);
    color: var(--text); cursor: pointer;
    font-family: inherit; font-size: var(--fs-small);
    padding: 0; text-align: center;
}
.dp-day:hover { background: var(--accent-tint); color: var(--accent-hover); }
.dp-pad { cursor: default; }
.dp-pad:hover { background: none; }
.dp-today { border-color: var(--border-strong); font-weight: 600; }
.dp-cursor { outline: 2px solid var(--accent); outline-offset: -2px; }
.dp-sel { background: var(--accent); color: var(--on-accent); font-weight: 600; }
.dp-sel:hover { background: var(--accent-hover); color: var(--on-accent); }
.dp-foot {
    display: flex; gap: 6px; margin-top: 8px;
    padding-top: 8px; border-top: 1px solid var(--border);
}
.dp-act {
    flex: 1; padding: 5px 8px;
    background: var(--surface); color: var(--text);
    border: 1px solid var(--border-strong); border-radius: var(--r-sm);
    font-family: inherit; font-size: var(--fs-caption); font-weight: 500;
    cursor: pointer;
}
.dp-act:hover { background: var(--accent-tint); color: var(--accent-hover); }
.dp-done {
    background: var(--accent); color: var(--on-accent);
    border-color: var(--accent); font-weight: 600;
}
.dp-done:hover { background: var(--accent-hover); color: var(--on-accent); }

/* Partial precision, offered only on construction/manufacture dates. */
.dp-foot-partial {
    align-items: center;
    margin-top: 6px; padding-top: 6px;
    border-top: 1px dashed var(--border);
}
.dp-partial-label {
    flex: 0 0 auto;
    font-size: var(--fs-caption); color: var(--text-muted);
    cursor: help;
}
.dp-foot-partial .dp-act { flex: 1 1 0; }

.o2-hint {
    font-size: var(--fs-small);
    color: var(--text-muted);
    padding: 2px 0 4px;
    text-align: right;
}



/* Performance testing card in modal */
.testing-card {
    background: var(--surface-alt);
    border: 2px solid var(--border);
    border-radius: var(--r-sm);
    padding: 16px;
    margin-top: 8px;
}

.testing-card.testing-required {
    border-color: var(--warn);
}

.testing-card.testing-not-required {
    border-color: var(--ok);
}

.testing-badge {
    display: inline-block;
    padding: 4px 14px;
    border-radius: var(--r-md);
    font-weight: 700;
    font-size: var(--fs-body);
    margin-bottom: 10px;
}

.testing-badge.yes {
    background: rgba(230, 126, 34, 0.2);
    color: var(--warn);
    border: 1px solid var(--warn);
}

.testing-badge.no {
    background: rgba(46, 204, 113, 0.2);
    color: var(--ok);
    border: 1px solid var(--ok);
}

.testing-freq {
    font-size: var(--fs-body);
    color: var(--text);
    margin-bottom: 8px;
    font-weight: 500;
}

.testing-details-list {
    padding-left: 18px;
    font-size: var(--fs-data);
    color: var(--text-muted);
}

.testing-details-list li {
    margin-bottom: 4px;
    line-height: 1.4;
}


/* --- Facility Setup Wizard --- */
.wizard-overlay {
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0, 0, 0, 0.8);
    display: none;
    justify-content: center;
    align-items: center;
    z-index: 2000;   /* see .modal-overlay — must clear Leaflet's 1000 */
}

.wizard-overlay.active {
    display: flex;
}

.wizard {
    background: var(--surface);
    border: 2px solid var(--border);
    border-radius: var(--r-md);
    width: 720px;
    max-width: 95vw;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
}

.wizard-header {
    display: flex;
    align-items: center;
    padding: 16px 24px;
    border-bottom: 1px solid var(--border);
    gap: 16px;
}

.wizard-header h2 {
    color: var(--accent);
    font-size: var(--fs-heading);
    white-space: nowrap;
}

.wizard-steps {
    display: flex;
    gap: 8px;
    margin-left: auto;
    margin-right: 16px;
}

.wizard-step {
    padding: 4px 12px;
    border-radius: var(--r-md);
    font-size: var(--fs-data);
    color: var(--text-2);
    background: var(--surface-alt);
    transition: all 0.2s;
}

.wizard-step.active {
    color: var(--accent);
    background: rgba(74, 144, 217, 0.15);
    font-weight: 700;
}

.wizard-step.completed {
    color: var(--ok);
    background: rgba(46, 204, 113, 0.1);
}

.wizard-body {
    padding: 24px;
    overflow-y: auto;
    flex: 1;
}

.wizard-footer {
    display: flex;
    justify-content: space-between;
    padding: 16px 24px;
    border-top: 1px solid var(--border);
}


/* Wizard Form Fields */
.wizard-form {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.wizard-row {
    display: flex;
    gap: 16px;
}

.wizard-row > .wizard-field {
    flex: 1;
}

.wizard-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.wizard-field label {
    font-size: var(--fs-data);
    color: var(--text-muted);
    font-weight: 600;
}

.wizard-field label .required {
    color: var(--danger);
}

.wizard-field input,
.wizard-field select {
    background: var(--surface-alt);
    border: 1px solid var(--border);
    color: var(--text);
    border-radius: var(--r-sm);
    padding: 10px 12px;
    font-size: var(--fs-body);
    font-family: inherit;
    transition: border-color 0.2s;
}

.wizard-field input:focus,
.wizard-field select:focus {
    outline: none;
    border-color: var(--accent);
}

.wizard-section-title {
    font-size: var(--fs-body);
    color: var(--accent);
    font-weight: 700;
    margin-bottom: 4px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--border);
}

/* Source Selection Cards */
.source-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 8px;
}

.source-card {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--surface-alt);
    border: 2px solid var(--border);
    border-radius: var(--r-sm);
    padding: 12px 14px;
    cursor: pointer;
    transition: all 0.2s;
    user-select: none;
}

.source-card:hover {
    border-color: var(--border);
}

.source-card.checked {
    border-color: var(--accent);
    background: rgba(74, 144, 217, 0.08);
}

.source-card input[type="checkbox"] {
    display: none;
}

.source-check {
    width: 20px;
    height: 20px;
    border: 2px solid var(--border-strong);
    border-radius: var(--r-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: all 0.2s;
    font-size: var(--fs-small);
    color: transparent;
}

.source-card.checked .source-check {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
}

.source-info {
    flex: 1;
    min-width: 0;
}

.source-name {
    font-size: var(--fs-data);
    font-weight: 600;
    color: var(--text);
}

.source-desc {
    font-size: var(--fs-caption);
    color: var(--text-muted);
    margin-top: 2px;
}

.source-qty {
    display: none;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

.source-card.checked .source-qty {
    display: flex;
}

.source-qty label {
    font-size: var(--fs-caption);
    color: var(--text-2);
}

.source-qty input {
    width: 48px;
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--text);
    border-radius: var(--r-sm);
    padding: 4px 6px;
    font-size: var(--fs-data);
    text-align: center;
}

.source-suboptions {
    display: none;
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px solid var(--border);
}

.source-card.checked .source-suboptions {
    display: flex;
    gap: 12px;
}

.source-suboptions label {
    font-size: var(--fs-small);
    color: var(--text-2);
    display: flex;
    align-items: center;
    gap: 4px;
    cursor: pointer;
}

.source-suboptions input[type="radio"] {
    accent-color: var(--accent);
}

.suggested-label {
    font-size: var(--fs-data);
    color: var(--text-2);
    font-style: italic;
    margin-top: 16px;
    margin-bottom: 4px;
}

/* --- Facility Emissions Summary --- */

.source-badge {
    display: inline-block;
    padding: 6px 14px;
    border-radius: var(--r-sm);
    font-weight: bold;
    font-size: var(--fs-data);
    letter-spacing: 0.5px;
}

.source-badge.major {
    background: var(--danger-bg);
    color: var(--danger);
    border: 1px solid var(--danger);
}

.source-badge.area {
    background: var(--ok-bg);
    color: var(--ok);
    border: 1px solid var(--ok);
}

.source-badge.unknown {
    background: var(--warn-bg);
    color: var(--warn);
    border: 1px solid var(--warn);
}

/* Citation hyperlinks to rule text (Cornell LII / EPA AP-42) */
.cite-link {
    color: var(--accent-hover);
    text-decoration: none;
    border-bottom: 1px dotted var(--accent);
}

.cite-link:hover {
    color: var(--accent);
    border-bottom-style: solid;
}

/* [VERIFY] audit flags on state-rule thresholds */
.verify-tag {
    background: var(--warn-bg);
    color: var(--warn);
    border: 1px solid var(--warn);
    border-radius: 3px;
    padding: 0 5px;
    font-size: var(--fs-caption);
    font-weight: bold;
    white-space: nowrap;
}

/* --- Facilities Manager --- */
.facilities-table { width: 100%; border-collapse: collapse; font-size: var(--fs-data); }
.facilities-table th {
    text-align: left; padding: 8px; color: var(--accent);
    border-bottom: 2px solid var(--border-strong); position: sticky; top: 0; background: var(--surface);
}
.facilities-table td { padding: 8px; border-bottom: 1px solid var(--border); }
.facility-row { cursor: pointer; }
.facility-row:hover { background: var(--row-hover); }
.screen-chip {
    display: inline-block; padding: 1px 6px; border-radius: 3px;
    font-size: var(--fs-nano); font-weight: bold; margin: 1px;
}
.screen-ok { background: var(--ok-bg); color: var(--ok); }
.screen-no { background: var(--danger-bg); color: var(--danger); }
.screen-tbd { background: var(--warn-bg); color: var(--warn); }

/* --- Facility nav (level-2 view tabs under the header) + Equipment Grid ---
   Same pill language as the header's Facilities/Permits workspace-nav so
   both levels read as one navigation system. */
.facility-nav {
    display: flex; align-items: center; height: var(--fnav-h);
    box-sizing: border-box; padding: 6px 24px; overflow-x: auto;
    background: var(--surface); border-bottom: 2px solid var(--border);
    /* #68: the band can overflow (12 tabs at 1280) — it still scrolls,
       but the permanent native scrollbar is gone; wheel-scroll + hover
       chevrons (app.js) replace it. overflow-y hidden: the auto value
       implied by overflow-x let the band scroll vertically by a few
       phantom px on wide windows (Kyle, 2026-08-11). */
    scrollbar-width: none;
    overflow-y: hidden;
}
.facility-nav::-webkit-scrollbar { display: none; }
.view-toggle {
    display: flex; align-items: center; gap: 2px; padding: 3px;
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: var(--r-md);
}
.view-toggle-btn {
    background: transparent; border: none; border-radius: var(--r-sm);
    color: var(--text-2); font-size: var(--fs-data); font-weight: 600;
    padding: 6px 14px; cursor: pointer; white-space: nowrap; position: relative;
}
.view-toggle-btn:hover { color: var(--text); }
.view-toggle-btn.active {
    background: var(--surface); color: var(--accent);
    box-shadow: var(--shadow-sm);
}
.fnav-sep { width: 1px; height: 18px; background: var(--border-strong);
    margin: 0 8px; flex-shrink: 0; }
.facility-map-container { position: relative; }
.equipment-grid-container {
    position: absolute; inset: 0; overflow-y: auto; background: var(--surface-alt);
    padding: 12px;
}
.grid-toolbar {
    display: flex; justify-content: space-between; align-items: center;
    margin-bottom: 10px; gap: 10px;
}
.grid-section { margin-bottom: 26px; }
.grid-section-header {
    display: flex; justify-content: space-between; align-items: center;
    border-bottom: 1px solid var(--border-strong); margin-bottom: 4px;
}
.grid-section-header h3 { color: var(--accent); font-size: var(--fs-title); padding: 6px 0; }
.grid-scroll { overflow-x: auto; }
/* Equipment grid (redesigned 2026-07-22): pinned column grid via
   per-table <colgroup> — Unit/Description/Status align across every
   section; tables hug content instead of stretching sparse columns
   across the screen. */
.grid-table { border-collapse: collapse; font-size: var(--fs-data);
    table-layout: fixed; width: auto;
    font-variant-numeric: tabular-nums; }
.grid-table th {
    text-align: left; padding: 8px 6px; color: var(--text-2);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    border-bottom: 1px solid var(--border-strong); font-weight: 600;
    font-size: var(--fs-caption); text-transform: uppercase;
    letter-spacing: .04em;
}
.grid-table td { padding: 5px 4px; border-bottom: 1px solid var(--border);
    overflow: hidden; }
.grid-table tbody tr:nth-child(even) { background: var(--bg); }
.grid-table tbody tr:hover { background: var(--row-hover); }
.grid-unit {
    color: var(--accent); font-weight: bold; cursor: pointer;
    white-space: nowrap; padding: 5px 8px !important;
}
.grid-unit:hover { text-decoration: underline; }
.grid-input {
    background: var(--surface); color: var(--text); border: 1px solid transparent;
    padding: 7px 8px; width: 100%; box-sizing: border-box;
    font-size: var(--fs-data); border-radius: var(--r-sm);
}
.grid-input.grid-num { text-align: right; }
.grid-input:hover { border-color: var(--border-strong); }
.grid-input:focus { border-color: var(--accent); outline: none; background: var(--accent-tint); }
.grid-calc { color: var(--ok); text-align: right; padding: 5px 8px !important; white-space: nowrap; }

/* Equipment sub-tab BAND — full-width strip at the top of the pane,
   sticky while sections scroll; same nav language as the facility
   view-tab band, one size down. Icons ride along from the palette. */
/* Once the old Equipment tab's sticky band (negative margins bled into
   its padded panel, opaque ground). Its only consumer now is the Great
   Filter's Sites/Equipment toggle on the TRANSPARENT Analytics page,
   where the band rendered as a stray full-width white frame (Kyle,
   2026-08-13) — the pill container below is the whole look. */
.grid-type-nav { margin: 0 0 12px; }
.grid-type-tabs { display: flex; gap: 3px; background: var(--surface-alt);
    border: 1px solid var(--border); border-radius: var(--r-md);
    padding: 4px; flex-wrap: wrap; width: fit-content; }
.grid-tab { display: inline-flex; align-items: center; gap: 7px;
    background: transparent; border: none; color: var(--text-2);
    font-size: var(--fs-data); font-weight: 600; padding: 8px 16px;
    border-radius: var(--r-sm); cursor: pointer; position: relative;
    white-space: nowrap; }
.grid-tab-icon { width: 20px; height: 20px; flex: none; }
.grid-tab-n { font-size: var(--fs-caption); font-weight: 700;
    color: var(--text-muted); background: var(--surface-alt);
    border-radius: var(--r-pill); padding: 1px 7px; }
.grid-tab.active .grid-tab-n { color: var(--accent); background: var(--accent-tint); }
.grid-tab:hover { color: var(--text); }
.grid-tab.active { background: var(--surface); color: var(--accent);
    box-shadow: var(--shadow-sm); }
.grid-tab.active::after {
    content: ""; position: absolute; left: 22%; right: 22%; bottom: 2px;
    height: 2px; background: var(--accent); border-radius: 2px;
}
:root[data-theme="dark"] .grid-tab.active::after {
    box-shadow: 0 0 7px rgba(98, 217, 232, .9);
}
:root[data-theme="dusk"] .grid-tab.active::after {
    box-shadow: 0 0 6px rgba(76, 200, 218, .75);
}
.grid-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ── Equipment "signal console" (task #37) ────────────────────────────
   The Equipment tab is contained so it floats on the starfield like every
   other page, and re-skinned in the instrument vocabulary: level bars read
   each unit's emissions against the permit cap. Signal-bar colours: */
:root { --sig-site: #5bb6c6; --sig-unit: #0e7490; --sig-track: #e2e8f2; }
:root[data-theme="dark"] { --sig-site: #3aa9bd; --sig-unit: #eafbff; --sig-track: #1b2740; }
:root[data-theme="dusk"] { --sig-site: #3fa8bc; --sig-unit: #d9f6fb; --sig-track: #2c3850; }

/* Containment: the grid pane goes transparent so the console floats; the
   inner column caps its width, centres, and is a self-contained surface
   card — letting the void (dark) / slate (light) show in the gutters. */
#equipment-grid { background: transparent; }
/* Reveal the SKY behind contained data views: the center container
   paints an opaque --bg over the body's sky (starfield at night, the
   Milky Way band + pixel Andromeda in light) — drop it in EVERY theme
   whenever a data tab is contained (light added 2026-08-12: Kyle,
   "background details disappear after navigating Browser>Viewer").
   Plan View / Site Map keep their backdrop (data-contained=""). */
#facility-screen[data-contained="1"] .facility-map-container {
    background: transparent;
}
/* Every OTHER data-view pane (Equipment has its own .equip-console card)
   becomes a centered card floating on the backdrop — the app-page feel. */
#facility-screen[data-contained="1"] .equipment-grid-container:not(#equipment-grid) {
    position: relative; inset: auto; flex: 1 1 auto; width: 100%;
    max-width: 1160px; margin: 0 auto;
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: 14px; box-shadow: var(--shadow-md);
    padding: 16px 18px; overflow-y: auto;
}
.equip-console { max-width: 1160px; margin: 0 auto; display: flex;
    /* same frame width as every contained sibling card (Kyle's
       mismatchformats.png standardization, 2026-08-12) */
    flex-direction: column; gap: 12px;
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: 14px; padding: 14px; box-shadow: var(--shadow-md); }

/* Master "SITE SIGNAL" bus */
.equip-master { display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--r-md); padding: 11px 16px; box-shadow: var(--shadow-sm); }
.sig-label { font-family: var(--font-data); font-size: var(--fs-caption);
    letter-spacing: .18em; color: var(--accent); font-weight: 700; flex-shrink: 0; }
.master-bars { display: flex; gap: 20px; flex: 1; min-width: 260px; flex-wrap: wrap; }
.mbar { display: flex; align-items: center; gap: 9px; min-width: 210px; flex: 1; }
.mbar .mp { font-size: var(--fs-caption); letter-spacing: .08em;
    color: var(--text-muted); font-weight: 700; width: 34px; }
.mbar .lvl { flex: 1; }
.mbar .mval { font-family: var(--font-data); font-size: var(--fs-data);
    color: var(--text); width: 84px; text-align: right; }
.mbar .mval small { color: var(--text-muted); }
.sig-status { display: flex; align-items: center; gap: 7px; font-family: var(--font-data);
    font-size: var(--fs-caption); letter-spacing: .1em; font-weight: 700; white-space: nowrap; }
.st-ok { color: var(--ok); } .st-warn { color: var(--warn); } .st-crit { color: var(--danger); }
/* #68: metric fractions never break ("120.60 / 100"), and the status
   word travels as one unit with its dot when the strip wraps. */
.mbar .mval { white-space: nowrap; }
.sig-status { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }

/* (#68 tier-1 media queries live at the END of this file — they must
   follow the base rules they override, or source order wins.) */

/* Level bar: 0→cap track, site fill + glowing unit slice */
.lvl { display: flex; align-items: center; gap: 7px; }
.cap0, .capN { font-family: var(--font-data); font-size: var(--fs-caption);
    color: var(--text-muted); flex-shrink: 0; }
.lvl-track { position: relative; flex: 1; height: 9px; border-radius: 3px;
    background: var(--sig-track); overflow: hidden; background-image:
    repeating-linear-gradient(90deg, transparent 0 calc(10% - 1px),
        rgba(128,150,180,.16) calc(10% - 1px) 10%); }
.lvl-site { position: absolute; left: 0; top: 0; height: 100%; background: var(--sig-site);
    border-radius: 3px 0 0 3px; transition: width .7s cubic-bezier(.2,.7,.3,1), background .3s; }
.lvl-site.warn { background: var(--warn); }
.lvl-site.crit { background: var(--danger); }
.lvl-unit { position: absolute; top: 0; height: 100%; min-width: 3px; background: var(--sig-unit);
    border-right: 1px solid var(--sig-unit);
    transition: left .7s cubic-bezier(.2,.7,.3,1), width .7s cubic-bezier(.2,.7,.3,1); }
:root[data-theme="dark"] .lvl-unit { box-shadow: 0 0 7px rgba(234,251,255,.9); }
:root[data-theme="dusk"] .lvl-unit { box-shadow: 0 0 6px rgba(217,246,251,.7); }
:root[data-theme="light"] .lvl-unit { box-shadow: 0 0 5px rgba(14,116,144,.55); }

/* Control row: BASIS toggle + Console/Grid toggle */
.equip-ctrls { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.ctrl-group { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ctrl-label { font-family: var(--font-data); font-size: var(--fs-caption);
    letter-spacing: .14em; color: var(--text-muted); font-weight: 700; }
.ctrl-hint { font-size: var(--fs-caption); color: var(--text-muted); }
.eq-seg { display: flex; gap: 2px; background: var(--surface-alt);
    border: 1px solid var(--border); border-radius: var(--r-md); padding: 3px; }
.ctrl-view-group { margin-left: auto; }

/* Equipment page header (title + Add / Recalculate) */
.equip-head { display: flex; align-items: baseline; gap: 10px;
    margin-bottom: 10px; }
.equip-title { margin: 0; font-size: var(--fs-heading); font-weight: 700;
    letter-spacing: -.3px; color: var(--text); }
.equip-count { font-size: var(--fs-small); font-weight: 500; color: var(--text-muted); }
.equip-head-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-shrink: 0; }

/* "Show" (type filter) row, clearly labelled above the sections */
.equip-show { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding-top: 10px; border-top: 1px solid var(--border); }
.eq-sbtn { position: relative; background: transparent; border: none; color: var(--text-2);
    cursor: pointer; font-family: inherit; font-size: var(--fs-small); font-weight: 600;
    padding: 6px 14px; border-radius: var(--r-sm); white-space: nowrap; }
.eq-sbtn:hover { color: var(--text); }
.eq-sbtn.active { background: var(--surface); color: var(--accent); box-shadow: var(--shadow-sm); }
.eq-sbtn.active::after { content: ""; position: absolute; left: 22%; right: 22%;
    bottom: 2px; height: 2px; background: var(--accent); border-radius: 2px; }
:root[data-theme="dark"] .eq-sbtn.active::after { box-shadow: 0 0 7px rgba(98,217,232,.9); }
:root[data-theme="dusk"] .eq-sbtn.active::after { box-shadow: 0 0 6px rgba(76,200,218,.75); }

/* Band row (type tabs + Add dropdown + recalc); neutralise the old bleed */
.equip-bandrow { display: flex; align-items: center; gap: 12px; }
.equip-console .grid-type-nav { position: static; margin: 0; padding: 0;
    background: transparent; border: none; }
.equip-band-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.equip-recalc { flex-shrink: 0; }

/* Add-Equipment dropdown (replaces the docked palette rail) */
.eq-add-wrap { position: relative; }
.eq-add-menu { position: absolute; right: 0; top: calc(100% + 6px);
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
    box-shadow: var(--shadow-md); padding: 6px; min-width: 264px; display: none; z-index: 400;
    grid-template-columns: 1fr 1fr; gap: 2px; }
.eq-add-menu.open { display: grid; }
.eq-add-item { display: flex; align-items: center; gap: 8px; padding: 7px 9px;
    border-radius: var(--r-sm); cursor: pointer; font-size: var(--fs-small); color: var(--text-2);
    background: none; border: none; text-align: left; font-family: inherit; }
.eq-add-item:hover { background: var(--surface-alt); color: var(--text); }
.eq-add-item .grid-tab-icon { width: 18px; height: 18px; flex: none; }

/* Channel strips */
.equip-bus { display: flex; flex-direction: column; gap: 10px; }
.bus-label { display: flex; align-items: center; gap: 9px; }
.bus-label .grid-tab-icon { width: 22px; height: 22px; flex: none; }
.bus-label h3 { margin: 0; font-size: var(--fs-title); letter-spacing: 0;
    text-transform: none; color: var(--text); font-weight: 700; }
.bus-label .cnt { font-family: var(--font-data); font-size: var(--fs-caption); color: var(--text-muted);
    background: var(--surface-alt); border-radius: var(--r-pill); padding: 1px 9px; }
.bus-label .line { flex: 1; height: 1px; background: var(--border); }
.equip-strips { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 11px; }
/* Tank battery band (task #53 chunk 6d): a full-width header row inside
   the strips grid grouping the battery's size-group cards below it. */
.battery-band { grid-column: 1 / -1; display: flex; align-items: center;
    gap: 10px; flex-wrap: wrap; padding: 7px 12px; margin-top: 4px;
    background: var(--surface-alt); border: 1px solid var(--border);
    border-left: 3px solid var(--accent); border-radius: var(--r-md); }
.battery-band .battery-name { font-weight: 700; font-size: var(--fs-body);
    color: var(--text); white-space: nowrap; }
.battery-band .battery-meta { color: var(--text-muted);
    font-size: var(--fs-small); flex: 1; min-width: 0; }
.battery-band .battery-actions { display: flex; align-items: center;
    gap: 6px; margin-left: auto; }
.battery-band .battery-actions input { width: 130px; }
.equip-strip { background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--r-md); padding: 12px 13px; display: flex; flex-direction: column;
    gap: 9px; cursor: pointer; transition: border-color .15s, transform .15s, box-shadow .15s; }
.equip-strip:hover { border-color: var(--accent); transform: translateY(-2px);
    box-shadow: var(--shadow-sm); }
.strip-top { display: flex; align-items: center; gap: 8px; }
.strip-id { font-family: var(--font-data); font-weight: 700; color: var(--accent); font-size: var(--fs-title); }
.strip-status { margin-left: auto; }
.strip-meta { display: flex; justify-content: space-between; gap: 8px;
    font-size: var(--fs-small); color: var(--text-muted); margin-top: -2px; }
.srow { display: flex; flex-direction: column; gap: 4px; }
.srow .rowtop { display: flex; justify-content: space-between; font-size: var(--fs-small); letter-spacing: .04em; }
.srow .rp { color: var(--text-muted); font-weight: 700; }
.srow .rv { font-family: var(--font-data); color: var(--text-2); }
.srow .rv b { color: var(--text); }

/* ── Attached inline editor: an open unit spans the strip grid as one
   bordered element (its own title bar + summary card + editor body), so
   neighbouring cards reflow below it (task #39). */
.equip-unit { grid-column: 1 / -1; background: var(--surface);
    border: 1px solid var(--accent); border-radius: var(--r-md); overflow: hidden;
    box-shadow: 0 0 0 1px var(--accent), var(--shadow-md); }
/* the unfold plays on FIRST OPEN only (#57): the console rebuilds on
   every committed edit, and replaying the fade there was the "screen
   flash" — the .emanate class is granted once by toggleEquipDetail */
.equip-unit.emanate { animation: unit-emanate .16s ease; }
@keyframes unit-emanate { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
.unit-topbar { display: flex; align-items: center; gap: 8px; padding: 7px 10px 7px 13px;
    background: var(--accent-tint); border-bottom: 1px solid var(--border); }
.unit-tb-id { font-family: var(--font-data); font-weight: 700; font-size: var(--fs-small);
    letter-spacing: .05em; text-transform: uppercase; color: var(--accent); }
.unit-ctrls { margin-left: auto; display: flex; align-items: center; gap: 6px; }
.pin-btn { background: var(--surface); border: 1px solid var(--border); color: var(--text-muted);
    font: 600 var(--fs-small)/1 inherit; padding: 4px 11px 4px 8px; border-radius: var(--r-pill);
    cursor: pointer; display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.pin-btn:hover { border-color: var(--accent); color: var(--accent); }
.pin-btn.on { background: var(--surface); border-color: var(--accent); color: var(--accent);
    box-shadow: 0 0 11px -2px var(--accent); }
.anchor-ic { display: block; } .pin-btn.on .anchor-ic { filter: drop-shadow(0 0 3px var(--accent)); }
.u-x { background: none; border: none; color: var(--text-muted); font-size: 1.25rem;
    line-height: 1; cursor: pointer; padding: 0 4px; }
.u-x:hover { color: var(--danger); }
.unit-card { padding: 12px 15px 13px; cursor: pointer; }
.unit-card .strip-id { font-size: var(--fs-title); }
.unit-panel { padding: 16px 16px 15px; border-top: 1px solid var(--border); background: var(--surface); }
@media (prefers-reduced-motion: reduce) { .equip-unit.emanate { animation: none; } }

/* Grid body panel (keeps the editable spreadsheet, contained) */
.equip-panel { background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: var(--r-md); padding: 12px 14px; }
.equip-grid-hint { margin-bottom: 10px; }

/* Header mute button */
.mute-btn { font-size: 1rem; line-height: 1; }
.mute-btn.muted { opacity: .55; }

/* In-view tools strip — the re-homed rail for contained data views
   (#39 Phase 1). Rail builders' vertical markup, laid out horizontally. */
.view-rail { display: flex; flex-wrap: wrap; align-items: center; gap: 7px 10px;
    margin: 0 0 14px; padding: 9px 12px; background: var(--surface);
    border: 1px solid var(--border); border-radius: var(--r-md); }
.view-rail:empty { display: none; }
.view-rail .rail-group { font-size: var(--fs-caption); font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase; color: var(--text-muted); }
.view-rail .rail-group:not(:first-child) { border-left: 1px solid var(--border); padding-left: 10px; }
.view-rail .rail-chip { background: var(--surface-alt); border: 1px solid var(--border);
    color: var(--text-2); font-size: var(--fs-small); font-weight: 600;
    padding: 5px 11px; border-radius: var(--r-pill); cursor: pointer; }
.view-rail .rail-chip:hover { border-color: var(--accent); color: var(--accent); }
.view-rail .rail-chip.on { background: var(--accent-tint); color: var(--accent); border-color: var(--accent); }
.view-rail .rail-note { flex-basis: 100%; font-size: var(--fs-caption); color: var(--text-muted); margin: 0; }
.view-rail select, .view-rail input { background-color: var(--surface-alt); border: 1px solid var(--border);
    color: var(--text); border-radius: var(--r-sm); padding: 5px 8px; font-size: var(--fs-small); }
.view-rail .src-select { min-width: 280px; max-width: 100%; }

/* PTE Calcs — Summary / Equation Editor delineation (#39 review) */
#calcs-view .equip-head { margin-bottom: 12px; }
.mode-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.mode-hint { font-size: var(--fs-caption); color: var(--text-muted); }
.scope-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.calc-src-strip { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.calc-src-chip { display: flex; flex-direction: column; gap: 2px; min-width: 130px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 9px;
    padding: 9px 13px; cursor: pointer; transition: border-color .15s, transform .12s; }
.calc-src-chip:hover { border-color: var(--accent); transform: translateY(-1px); }
.calc-src-chip.sel { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.calc-src-chip .cid { font-family: var(--font-data); font-weight: 700; color: var(--accent); font-size: var(--fs-data); }
.calc-src-chip .cmeta { font-size: var(--fs-caption); color: var(--text-muted); }
.pte-src.calc-jump { cursor: pointer; }
.pte-src.calc-jump:hover { color: var(--accent); text-decoration: underline; }

/* The unit panel's Equation Editor jump (#81 — replaced the Calculation
   Method dropdown): current method stated read-only, one prominent
   button into the studio. */
.calc-method-cell { display: flex; align-items: center; gap: 8px; min-width: 0; }
.calc-method-current {
    color: var(--text-2); font-size: .72rem; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis; max-width: 180px;
}
.btn.eq-editor-jump {
    color: var(--accent); border: 1px solid var(--accent);
    background: var(--accent-tint); font-weight: 700; white-space: nowrap;
    padding: 4px 10px; border-radius: var(--r-sm); cursor: pointer;
}
.btn.eq-editor-jump:hover { background: var(--accent); color: var(--bg); }
.view-rail .rail-limit-form { display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
    /* #69: the docked-toolbar variant of this class (further down) is a
       COLUMN — and since this rule never set a direction, the column
       leaked in here and stacked the controls into the "broken" narrow
       pile on the Actuals card. In the wide in-view rail this form is a
       ROW that never shrinks below its content; it wraps to its own
       line instead. */
    flex-direction: row; flex-shrink: 0; max-width: 100%; }
.view-rail .rail-limit-form .btn-block { width: auto; }
.view-rail .rail-limit-row { font-size: var(--fs-small); color: var(--text-2); }
.view-rail .rail-source { display: inline-flex; align-items: center; gap: 6px;
    background: var(--surface-alt); border: 1px solid var(--border); border-radius: var(--r-sm);
    padding: 5px 9px; cursor: pointer; font-size: var(--fs-small); color: var(--text-2); }
.view-rail .rail-source.selected { border-color: var(--accent); color: var(--accent); }
.view-rail .rail-source .item-icon { width: 16px; height: 16px; }
.view-rail .rail-tpy { color: var(--text-muted); font-size: var(--fs-caption); margin-left: 4px; }
.view-rail .wb-method { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-small); }

/* ── Window canvas (Spread mode) — task #39 Phase 2 ─────────────────── */
.layout-toggle { display: flex; gap: 2px; margin-left: auto; background: var(--surface-alt);
    border: 1px solid var(--border); border-radius: var(--r-md); padding: 3px; flex-shrink: 0; }
.layout-btn { background: transparent; border: none; color: var(--text-2); cursor: pointer;
    font: 600 var(--fs-small) inherit; padding: 5px 12px; border-radius: var(--r-sm); white-space: nowrap; }
.layout-btn:hover { color: var(--text); }
.layout-btn.active { background: var(--surface); color: var(--accent); box-shadow: var(--shadow-sm); }

#facility-screen[data-layout="spread"] .facility-map-container { overflow: hidden; }
#facility-screen[data-layout="spread"] .facility-map-container { background: transparent; }
/* Scrollable canvas: a viewport over a 2×-viewport surface (windows live on
   the surface, so you can push one off-screen and scroll to it). */
.wm-viewport { position: absolute; inset: 0; overflow: auto; }
.wm-surface { position: relative; }
.wm-gather { position: absolute; top: 12px; right: 16px; z-index: 1901;
    background: var(--surface); border: 1px solid var(--border); color: var(--text-2);
    font: 600 var(--fs-small) inherit; padding: 6px 12px; border-radius: var(--r-md);
    box-shadow: var(--shadow-md); cursor: pointer; }
.wm-gather:hover { border-color: var(--accent); color: var(--accent); }
.wm-window { position: absolute; display: flex; flex-direction: column; overflow: hidden;
    background: var(--surface-alt); border: 1px solid var(--border); border-radius: var(--r-md);
    box-shadow: var(--shadow-md); min-width: 320px; min-height: 200px; }
.wm-window.wm-focused { border-color: var(--accent); }
:root[data-theme="dark"] .wm-window.wm-focused,
:root[data-theme="dusk"] .wm-window.wm-focused { box-shadow: var(--shadow-md), 0 0 0 1px var(--accent); }
.wm-title { display: flex; align-items: center; gap: 8px; padding: 8px 11px; background: var(--surface);
    border-bottom: 1px solid var(--border); cursor: move; user-select: none; flex: none; }
.wm-name { font-size: var(--fs-data); font-weight: 700; color: var(--accent);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wm-btns { margin-left: auto; display: flex; gap: 2px; }
.wm-b { background: none; border: none; color: var(--text-muted); width: 24px; height: 22px;
    border-radius: 5px; cursor: pointer; font-size: 1rem; line-height: 1; }
.wm-b:hover { background: var(--surface-alt); color: var(--text); }
.wm-b.wm-close:hover { background: var(--danger); color: #fff; }
.wm-body { flex: 1; overflow: auto; min-height: 0; background: var(--surface); }
/* Detail (emissions-item editor) window body — its own scrolling surface */
.wm-detail-body { padding: 6px 14px 16px; }
.wm-resize { position: absolute; right: 0; bottom: 0; width: 18px; height: 18px; cursor: nwse-resize; z-index: 3; }
.wm-resize::after { content: ""; position: absolute; right: 3px; bottom: 3px; width: 8px; height: 8px;
    border-right: 2px solid var(--border-strong); border-bottom: 2px solid var(--border-strong); }
.wm-taskbar { position: absolute; left: 10px; right: 10px; bottom: 10px; z-index: 1900;
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
    box-shadow: var(--shadow-md); padding: 6px 12px; }
.wm-tb-lab { font-size: var(--fs-caption); color: var(--text-muted); font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase; }
.wm-tb-chip { background: var(--surface-alt); border: 1px solid var(--border); color: var(--text-2);
    font: 600 var(--fs-small) inherit; padding: 4px 11px; border-radius: var(--r-sm); cursor: pointer; }
.wm-tb-chip:hover { border-color: var(--accent); color: var(--accent); }

/* Adopted panes fill their window (override single-view absolute/contained rules) */
.wm-window .equipment-grid-container { position: static !important; inset: auto !important;
    max-width: none !important; margin: 0 !important; width: auto !important; height: auto !important;
    border: none !important; border-radius: 0 !important; box-shadow: none !important;
    background: transparent !important; padding: 12px !important; overflow: visible !important; }

/* Obligations tables: fixed layout so columns line up across category groups,
   with a wide wrapping Obligation column. Status is sized for the widest
   pill ("DUE SOON" ≈ 92px — 8% overflowed it, Kyle 2026-08-13); the date
   rule targets .dp-input, the class the custom picker actually renders
   (input[type=date] was a dead selector). */
.obl-table { table-layout: fixed; width: 100%; }
.obl-table th, .obl-table td { vertical-align: top; }
.obl-table th:nth-child(1), .obl-table td:nth-child(1) { width: 28%; white-space: normal; word-break: break-word; }
.obl-table th:nth-child(2), .obl-table td:nth-child(2) { width: 9%; }   /* Frequency */
.obl-table th:nth-child(3), .obl-table td:nth-child(3) { width: 9%; }   /* Next Due */
.obl-table th:nth-child(4), .obl-table td:nth-child(4) { width: 12%; }  /* Status */
.obl-table th:nth-child(5), .obl-table td:nth-child(5) { width: 9%; }   /* Last Done */
.obl-table th:nth-child(6), .obl-table td:nth-child(6) { width: 14%; }  /* Mark Done (date) */
.obl-table th:nth-child(7), .obl-table td:nth-child(7) { width: 11%; white-space: normal; word-break: break-word; }  /* Citation */
.obl-table th:nth-child(8), .obl-table td:nth-child(8) { width: 8%; white-space: normal; word-break: break-word; }   /* Applies To */
.obl-table .dp-input { width: 100%; max-width: 120px; box-sizing: border-box; }
/* Pills stay inside the fixed Status cell at narrow pane widths. */
.obl-table .pill { padding: 2px 7px; font-size: 0.62rem; max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; }

/* Plain number entry — no increment/decrement spinners */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

/* Collapsible equipment toolbar */
.equipment-toolbar.collapsed .toolbar-items,
.equipment-toolbar.collapsed .toolbar-hint {
    display: none;
}
.equipment-toolbar.collapsed {
    min-width: 0;
}
.toolbar-collapse-btn {
    float: right;
    background: none;
    border: none;
    color: var(--text-2);
    cursor: pointer;
    font-size: var(--fs-body);
    padding: 0 4px;
}
.toolbar-collapse-btn:hover { color: #fff; }

/* Derived control column in the grid (set via Routing tab) */
.grid-routed {
    font-size: var(--fs-small);
    white-space: nowrap;
    cursor: pointer;
    padding: 4px 8px !important;
}
.grid-routed:hover { text-decoration: underline; }

/* --- PTE summary (Calcs tab) --- */
.pte-table { border-collapse: collapse; font-size: var(--fs-small); min-width: 100%; }
.pte-table th {
    background: var(--border); color: var(--thead-text); padding: 4px 8px;
    border: 1px solid var(--border-strong); text-align: center; white-space: nowrap;
}
.pte-table td { border: 1px solid var(--border); padding: 3px 8px; }
.pte-src { font-weight: bold; color: var(--accent); white-space: nowrap; }
.pte-desc { color: var(--text-2); font-size: var(--fs-caption); }
.pte-num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.pte-unc td { color: var(--text-muted); font-size: var(--fs-caption); border-top: none; }
.pte-total td {
    border-top: 2px solid var(--accent); font-weight: bold; color: var(--text);
    background: var(--accent-tint);
}

/* Change-history chips (History tab + detail panel) */
.change-chip {
    display: inline-block; padding: 0 7px; border-radius: 3px;
    font-size: var(--fs-nano); font-weight: bold; border: 1px solid;
    text-transform: uppercase; letter-spacing: 0.5px;
}

/* Determination staleness warnings */
.stale-chip {
    display: inline-block; padding: 0 6px; border-radius: 3px;
    font-size: var(--fs-nano); font-weight: bold; letter-spacing: 0.5px;
    background: var(--warn-bg); color: var(--warn); border: 1px solid var(--warn);
}
/* Slim stale notice for the Obligations tab */
.stale-notice {
    font-size: var(--fs-small); color: var(--warn); margin: 2px 0 10px 0;
    display: flex; align-items: center; gap: 12px;
    justify-content: space-between;
}
.rerun-link {
    background: none; border: none; color: var(--accent); cursor: pointer;
    font-size: var(--fs-small); padding: 0 2px; text-decoration: underline;
}
.rerun-link:hover { color: var(--accent-hover); }

/* ═══════════════════════════════════════════════════════════════════════
   Light-theme restyle overrides + Facilities Home browser
   ═══════════════════════════════════════════════════════════════════════ */

/* App bar / header */
header {
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-sm);
    gap: 16px;
    /* NO overflow-x escape hatch here (tried in #55 chunk 6, reverted in
       #58): any non-visible overflow makes the header CLIP its absolute
       descendants — the settings dropdown hangs below the bar and was
       cut off. A too-narrow window just overflows the bar visibly. */
}
header h1, .brand {
    color: var(--text); font-size: var(--fs-title); font-weight: 700;
    cursor: pointer; white-space: nowrap;
}
/* Pulsar wordmark: glyph + tracked caps, same language as the landing page */
.brand { display: flex; align-items: center; gap: 10px; letter-spacing: .30em; }
.brand svg { display: block; flex-shrink: 0; }
.brand .mark { color: var(--accent); }
.global-search {
    flex: 1; max-width: 440px; padding: 8px 12px;
    border: 1px solid var(--border-strong); border-radius: var(--r-sm);
    background: var(--bg); color: var(--text); font-size: var(--fs-data);
}
.global-search::placeholder { color: var(--text-muted); }
/* min-width:0 lets the select inside shrink below its content width when
   the header gets tight (#55 chunk 6) — the nav tabs stay one-line. */
.facility-context { display: flex; align-items: center; gap: 10px; min-width: 0; }
.header-actions { margin-left: auto; display: flex; gap: 8px; }


/* View toggle (segmented) */

/* Panels / cards elevation */
.detail-panel, .wizard, .modal { box-shadow: var(--shadow-md); }
.facility-map-container { background: var(--bg); }

/* ── Facilities Home browser ─────────────────────────────────────────── */
.facilities-home { display: none; padding: 22px; max-width: 1340px; margin: 0 auto;
    height: calc(100vh - 54px); overflow-y: auto; }
.home-title { font-size: var(--fs-heading); font-weight: 700; letter-spacing: -.4px;
    color: var(--text); margin-bottom: 14px; }
.kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 18px; }
/* #67 G4: ONE quiet card family. The four-hue top borders + tinted
   numerals (navy/purple/green/red on every strip) fought the one-signal
   rule on every page; now the only KPI that carries color is one that
   needs attention (.kpi-value.danger/.warn — set by the renderers). */
.kpi { background: var(--surface); border: 1px solid var(--border);
    border-top: 3px solid var(--border-strong);
    border-radius: var(--radius); padding: 16px 18px; box-shadow: var(--shadow-sm); }
.kpi:has(.kpi-value.danger) { border-top-color: var(--danger); }
.kpi:has(.kpi-value.warn) { border-top-color: var(--warn); }
.kpi-label { font-size: var(--fs-caption); font-weight: 600; text-transform: uppercase;
    letter-spacing: .5px; color: var(--text-2); }
.kpi-value { font-size: var(--fs-display); font-weight: 700; margin-top: 6px;
    font-family: var(--font-data); font-variant-numeric: tabular-nums;
    letter-spacing: -.5px; color: var(--text); }
.kpi-value.danger { color: var(--danger); }
.kpi-value.warn { color: var(--warn); }
.kpi-value .unit { font-size: var(--fs-body); font-weight: 500; color: var(--text-muted); }
.kpi-sub { font-size: var(--fs-small); color: var(--text-muted); margin-top: 4px; }

.home-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.home-toolbar select { padding: 8px 10px; border: 1px solid var(--border-strong);
    border-radius: 8px; background: var(--surface); color: var(--text-2); font-size: var(--fs-data); cursor: pointer; }
.home-toolbar input[type="search"] { flex: 1; min-width: 220px; padding: 8px 12px;
    border: 1px solid var(--border-strong); border-radius: var(--r-sm);
    background: var(--surface); color: var(--text); font-size: var(--fs-data); }

/* Compliance workspace: company filings tier */
.comp-section-head { font-size: var(--fs-body); font-weight: 700; color: var(--text);
    text-align: left; margin: 18px 0 8px; }
.comp-section-sub { font-size: var(--fs-caption); font-weight: 400; color: var(--text-muted);
    margin-left: 10px; }
.cf-done { white-space: nowrap; }
.cf-done input[type="date"] { padding: 4px 6px; border: 1px solid var(--border);
    border-radius: var(--r-sm); background: var(--surface); color: var(--text);
    font-size: var(--fs-small); margin-right: 6px; }
.cf-roster-row td { background: var(--surface-alt); }
.cf-roster { display: flex; flex-direction: column; gap: 6px; padding: 6px 10px;
    text-align: left; }
.cf-roster-fac { font-size: var(--fs-small); }
.cf-roster-fac a { color: var(--link); font-weight: 600; margin-right: 8px; }
.cf-unit { display: inline-block; font-size: var(--fs-caption); padding: 1px 8px;
    margin: 1px 3px; border: 1px solid var(--border); border-radius: var(--r-md);
    background: var(--surface); color: var(--text-2); }
.home-count { margin-left: auto; font-size: var(--fs-data); color: var(--text-muted); }
.home-count b { color: var(--text); }

.fac-table-card {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); box-shadow: var(--shadow-sm);
    /* #68: contain wide tables — the table scrolls in its card, the page
       never scrolls sideways, and columns stop squeezing dates into
       mid-value wraps. (overflow-x must come AFTER the shorthand.) */
    overflow: hidden; overflow-x: auto; }
/* Systems board (task #31): status beacon, KPI strip, grouped tables */
.sys-head { display: flex; align-items: baseline; gap: 18px; margin-bottom: 2px; }
.sys-beacon { font-size: var(--fs-small); font-weight: 700; letter-spacing: .18em; }
.sys-beacon.ok { color: var(--ok); }
.sys-beacon.warn { color: var(--warn); }
.sys-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px;
    margin-bottom: 10px; }
.sys-kpis .kpi > div:first-child { font-size: var(--fs-caption); letter-spacing: .14em;
    color: var(--text-muted); }
.sys-group { margin: 22px 0 8px; font-size: var(--fs-body); letter-spacing: .06em; }
.sys-table td { vertical-align: top; }
.sys-cite { color: var(--text-2); font-size: var(--fs-small); }
.sys-caveats { color: var(--text-muted); font-size: var(--fs-small); margin-top: 4px;
    line-height: 1.5; }
.ei-bulk td { white-space: nowrap; }
.ei-cell { width: 96px; text-align: right; padding: 3px 6px; font-size: var(--fs-small); }
.ei-notrep td { opacity: .45; }
.ei-notrep td:first-child::after { content: " (not reported)"; font-size: var(--fs-caption);
    color: var(--text-muted); }


.sys-badge { display: inline-block; border-radius: var(--r-pill); padding: 2px 10px;
    font-size: var(--fs-caption); font-weight: 600; white-space: nowrap; }
.sys-badge.ok { color: var(--ok); background: var(--ok-bg); border: 1px solid var(--ok-bd); }
.sys-badge.warn { color: var(--warn); background: var(--warn-bg); border: 1px solid var(--warn-bd); }
.sys-badge.danger { color: var(--danger); background: var(--danger-bg); border: 1px solid var(--danger-bd); }
.sys-badge.neutral { color: var(--text-2); background: var(--surface-alt); border: 1px solid var(--border); }

/* Imports workspace (backlog #25): upload card + column-name chips */
.imports-upload { background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 18px; box-shadow: var(--shadow-sm); }
.imports-controls { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.imports-source { padding: 8px 12px; border: 1px solid var(--border-strong);
    border-radius: 8px; background: var(--bg); color: var(--text); font-size: var(--fs-data); }
.import-col-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.import-col-chip { background: var(--accent-tint); color: var(--accent);
    border: 1px solid var(--border); border-radius: var(--r-pill); padding: 4px 12px;
    font-size: var(--fs-small); font-weight: 600; }
.import-preview-scroll { overflow-x: auto; border: 1px solid var(--border);
    border-radius: var(--radius); }
.import-preview-table td, .import-preview-table th { white-space: nowrap; }
.import-samples { color: var(--text-muted); font-size: var(--fs-small); max-width: 320px;
    overflow: hidden; text-overflow: ellipsis; }

/* Staged-row grid: retheme the vendored Tabulator skin through the app's
   tokens so dark mode needs no second rule set. */
/* NOTE: new Tabulator("#import-grid") adds .tabulator to that very div —
   the widget root is #import-grid.tabulator, NOT a descendant. */
#import-grid.tabulator { background: var(--surface); color: var(--text);
    border: 1px solid var(--border); font-size: var(--fs-data); border-radius: var(--radius); }
#import-grid .tabulator-header,
#import-grid .tabulator-header .tabulator-col { background: var(--accent-tint);
    color: var(--text); border-color: var(--border); }
#import-grid .tabulator-tableholder { background: var(--surface); }
#import-grid .tabulator-row { background: var(--surface); color: var(--text);
    border-color: var(--border); }
#import-grid .tabulator-row.tabulator-row-even { background: var(--bg); }
#import-grid .tabulator-row.tabulator-selectable:hover { background: var(--accent-tint); }
#import-grid .tabulator-row .tabulator-cell { border-color: var(--border); }
#import-grid .tabulator-row.import-grid-rejected,
#import-grid .tabulator-row.import-grid-rejected.tabulator-row-even {
    background: var(--danger-bg); }
#import-grid .tabulator-row.import-grid-approved,
#import-grid .tabulator-row.import-grid-approved.tabulator-row-even {
    background: var(--ok-bg); }

/* Mapping selects living inside the grid's column headers */
#import-grid .grid-col-name { font-weight: 700; overflow: hidden;
    text-overflow: ellipsis; }
#import-grid .grid-map { width: 100%; margin-top: 4px;
    font-size: var(--fs-small); padding: 5px 6px; text-align: left; }
#import-grid .tabulator-col { vertical-align: top; }

/* Per-row review actions */
.grid-act { border: 1px solid var(--border-strong); background: var(--surface);
    border-radius: var(--r-sm); cursor: pointer; padding: 1px 8px;
    font-size: var(--fs-small); color: var(--text); }
.grid-act.ok { color: var(--ok); border-color: var(--ok-bd); }
.grid-act.bad { color: var(--danger); border-color: var(--danger-bd); }
.grid-act:hover { background: var(--surface-alt); }

.fac-table { width: 100%; border-collapse: collapse; font-size: var(--fs-data);
    font-variant-numeric: tabular-nums; }
.fac-table thead th { text-align: left; font-size: var(--fs-caption); font-weight: 600; text-transform: uppercase;
    letter-spacing: .4px; color: var(--thead-text); background: var(--thead-bg);
    padding: 10px 14px; border-bottom: 1px solid var(--border); white-space: nowrap;
    cursor: pointer; user-select: none; position: sticky; top: 0; }
.fac-table thead th.num { text-align: right; }
.fac-table thead th.sorted { color: var(--accent); }
.fac-table tbody td { padding: 11px 14px; border-bottom: 1px solid var(--border);
    color: var(--text); vertical-align: middle; }
.fac-table tbody tr:last-child td { border-bottom: none; }
.fac-table tbody tr:hover { background: var(--surface-alt); cursor: pointer; }
.fac-table td.num { text-align: right; font-variant-numeric: tabular-nums; color: var(--text-2); }
.fac-table td.muted { color: var(--text-muted); font-size: var(--fs-small); white-space: nowrap; }
.fac-name { font-weight: 600; color: var(--link); }
.fac-op { font-size: var(--fs-small); color: var(--text-muted); margin-top: 1px; }
.permit-chip { font-size: var(--fs-small); color: var(--chip-fg); background: var(--accent-tint);
    border: 1px solid var(--chip-bd); padding: 2px 8px; border-radius: var(--r-sm); white-space: nowrap; }

.pill { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-caption); font-weight: 600;
    padding: 3px 9px; border-radius: var(--r-pill); white-space: nowrap; }
.pill .dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }

/* The beacon (chunk 5): the lighthouse pulse on OVERDUE signals only.
   Same dot, breathing — frozen for reduced-motion users. */
.dot.beacon { animation: beacon-pulse 2s ease-in-out infinite; }
@keyframes beacon-pulse {
    0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(248, 113, 113, .55); }
    50%      { opacity: .55; box-shadow: 0 0 0 5px rgba(248, 113, 113, 0); }
}
@media (prefers-reduced-motion: reduce) {
    .dot.beacon { animation: none; }
}
.pill.ok { color: var(--ok); background: var(--ok-bg); border: 1px solid var(--ok-bd); }
.pill.warn { color: var(--warn); background: var(--warn-bg); border: 1px solid var(--warn-bd); }
.pill.danger { color: var(--danger); background: var(--danger-bg); border: 1px solid var(--danger-bd); }
.pill.major { color: var(--major); background: var(--major-bg); border: 1px solid var(--major-bd); }
.pill.neutral { color: var(--text-2); background: var(--surface-alt); border: 1px solid var(--border); }
.pill.applicable { color: var(--accent); background: var(--accent-tint); border: 1px solid var(--border-strong); }

/* Regulatory Coverage tree */
.cov-summary { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; }
.cov-program { margin-bottom: 16px; }
.cov-program-h { font-size: var(--fs-caption); font-weight: 700; text-transform: uppercase;
    letter-spacing: .6px; color: var(--text-2); padding: 6px 0; border-bottom: 1px solid var(--border);
    margin-bottom: 8px; }
.cov-subpart { background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--r-md); box-shadow: var(--shadow-sm); margin-bottom: 8px; overflow: hidden; }
.cov-subpart > summary { list-style: none; cursor: pointer; padding: 10px 14px;
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cov-subpart > summary::-webkit-details-marker { display: none; }
.cov-subpart > summary::before { content: "▸"; color: var(--text-muted); font-size: var(--fs-data); }
.cov-subpart[open] > summary::before { content: "▾"; }
.cov-sp-code { font-weight: 700; color: var(--accent); font-size: var(--fs-data); white-space: nowrap; }
.cov-sp-title { color: var(--text); font-size: var(--fs-data); }
.cov-sp-chips { margin-left: auto; display: flex; gap: 6px; }
.cov-count { font-size: var(--fs-caption); font-weight: 600; padding: 2px 8px; border-radius: 20px; }
.cov-count.applicable { color: var(--accent); background: var(--accent-tint); }
.cov-count.warn { color: var(--warn); background: var(--warn-bg); border: 1px solid var(--warn-bd); }
.cov-count.neutral { color: var(--text-2); background: var(--surface-alt); }
.cov-sp-body { padding: 0 14px 12px; border-top: 1px solid var(--border); }
.cov-desc { font-size: var(--fs-small); color: var(--text-muted); margin: 8px 0 10px; }
.cov-unit { color: var(--link); font-weight: 600; cursor: pointer; }
.cov-unit:hover { text-decoration: underline; }
.cov-basis { font-size: var(--fs-small); color: var(--text-2); }
/* Jump-to-fix chips (coverage + readiness checklists): cyan ACTION
   chips (Kyle, 2026-08-18 — actions are cyan; the missing/entered
   STATUS lives on the checklist's ○/✓ marks, not the chip). */
.cov-missing { display: inline-block; font-size: var(--fs-caption); font-weight: 600;
    color: var(--accent); background: var(--accent-tint);
    border: 1px solid var(--border); border-radius: var(--r-sm);
    padding: 2px 8px; margin: 2px 4px 2px 0; cursor: pointer; }
.cov-missing:hover { color: var(--accent-hover); border-color: var(--accent); }

/* Shared primary button */
/* ── Button system (frontend-refresh chunk 2) ─────────────────────────
   ONE family, intent + size modifiers. Always pair an intent with .btn:
   .btn-primary (the main action) · .btn-quiet (secondary) ·
   .btn-danger (destructive) · .btn-ok (additive) ·
   .btn-sm (compact) · .btn-block (stacked full-width action).
   .btn-warn RETIRED 2026-08-18 (Kyle folded the amber recalc CTAs into
   cyan — actions are cyan, amber is a status hue, and the notice
   system owns status).
   Specialized survivors, deliberately NOT in this family: .ws-btn /
   .view-toggle-btn (navigation, chunk 3), .ecfr-btn (armed-toolbar
   system), .close-btn (icon button), .theme-opt. */
.btn {
    display: inline-flex; align-items: center; justify-content: center;
    gap: 6px; padding: 7px 14px;
    border: 1px solid transparent; border-radius: var(--r-sm);
    font-family: inherit; font-size: var(--fs-small); font-weight: 600;
    line-height: 1.2; cursor: pointer; white-space: nowrap;
    transition: background .15s, color .15s, border-color .15s;
}
.btn:hover { box-shadow: var(--shadow-sm); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.btn:disabled { opacity: .5; cursor: not-allowed; box-shadow: none; }
.btn-primary { background: var(--accent); color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-hover); }
.btn-quiet { background: var(--surface); color: var(--text); border-color: var(--border-strong); }
.btn-quiet:hover { background: var(--accent-tint); color: var(--accent-hover); }
.btn-danger { background: var(--danger-bg); color: var(--danger); border-color: var(--danger-bd); }
.btn-danger:hover { background: var(--danger-bd); }
.btn-ok { background: var(--ok-bg); color: var(--ok); border-color: var(--ok-bd); }
.btn-ok:hover { background: var(--ok-bd); }
.btn-sm { padding: 4px 10px; font-size: var(--fs-caption); font-weight: 500; }
.btn-block { display: flex; width: 100%; margin: 12px 0 8px; }

/* House dialogs (chunk 4): small focused modals; each is its own
   overlay so they never fight the determination modal for content. */
.dlg-overlay { z-index: 3000; }
.dlg { width: min(400px, calc(100vw - 40px)); }
.dlg .modal-body { padding: 4px 16px 8px; }
.dlg-body-text { font-size: var(--fs-small); color: var(--text-2); line-height: 1.5; margin: 6px 0; }
.dlg-label { display: block; font-size: var(--fs-small); color: var(--text-2); margin-top: 6px; }
.dlg-actions { display: flex; justify-content: flex-end; gap: var(--sp-2);
    padding: var(--sp-3) var(--sp-4) var(--sp-4); }

/* App-level workspace switcher (header).
   flex-shrink:0 + nowrap (#55 chunk 6): entering a facility swaps the
   elastic search box for the rigid facility-context, and the nav used to
   absorb the squeeze by wrapping its two-word tabs onto two lines
   (tier1/tier2 screenshots) — the whole bar changed height. The nav now
   refuses to shrink; the facility select shrinks instead, and the header
   scrolls as the last resort. */
.workspace-nav { display: flex; gap: 2px; background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: var(--r-md); padding: 3px; flex-shrink: 0; }
.ws-btn { background: transparent; border: none; color: var(--text-2); font-size: var(--fs-data); font-weight: 600;
    padding: 5px 14px; border-radius: var(--r-sm); cursor: pointer; position: relative; white-space: nowrap; }
.ws-btn:hover { color: var(--text); }
.ws-btn:disabled { color: var(--text-muted); opacity: .55; cursor: default; }
.ws-btn:disabled:hover { color: var(--text-muted); }
.ws-btn.active { background: var(--surface); color: var(--accent); box-shadow: var(--shadow-sm); }
.ws-btn:focus-visible, .view-toggle-btn:focus-visible {
    outline: 2px solid var(--accent); outline-offset: -2px; }

/* ── The beam (frontend-refresh chunk 3) ──────────────────────────────
   ONE mark of "you are here" at every navigation level: a thin accent
   bar on the active item's leading edge — bottom edge for tabs, left
   edge for rail rows. The shape of the item itself never changes.
   The glow is dark-theme only (light theme keeps the instrument calm). */
.ws-btn.active::after, .view-toggle-btn.active::after {
    content: ""; position: absolute; left: 22%; right: 22%; bottom: 2px;
    height: 2px; background: var(--accent); border-radius: 2px;
}
:root[data-theme="dark"] .ws-btn.active::after,
:root[data-theme="dark"] .view-toggle-btn.active::after,
:root[data-theme="dark"] .rail-source.selected::before {
    box-shadow: 0 0 7px rgba(98, 217, 232, .9);
}
:root[data-theme="dusk"] .ws-btn.active::after,
:root[data-theme="dusk"] .view-toggle-btn.active::after,
:root[data-theme="dusk"] .rail-source.selected::before {
    box-shadow: 0 0 6px rgba(76, 200, 218, .75);
}

/* Permits editor */
.permit-editor { max-width: 1100px; margin: 0 auto; }
.permit-editor-head { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.permit-controls { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.permit-controls label, .permit-modal-form label { display: flex; flex-direction: column; gap: 3px;
    font-size: var(--fs-caption); font-weight: 600; color: var(--text-2); }
.permit-controls select, .permit-modal-form select {
    padding: 7px 10px; border: 1px solid var(--border-strong); border-radius: var(--r-sm);
    background: var(--surface); color: var(--text); font-size: var(--fs-data); min-width: 180px; }
.permit-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 20px; }
.permit-field { display: flex; flex-direction: column; gap: 3px; }
.permit-field-wide { grid-column: 1 / -1; }
.permit-field label { font-size: var(--fs-caption); font-weight: 600; color: var(--text-2); }
.permit-field input { padding: 7px 10px; border: 1px solid var(--border-strong); border-radius: var(--r-sm);
    background: var(--surface); color: var(--text); font-size: var(--fs-data); }
.permit-field input.missing { border-color: var(--warn); background: var(--warn-bg); }
.permit-auto { font-size: var(--fs-nano); font-weight: 700; text-transform: uppercase; letter-spacing: .5px;
    color: var(--accent); background: var(--accent-tint); padding: 1px 6px; border-radius: var(--r-md); }
.permit-auto-val { padding: 7px 10px; border: 1px dashed var(--border); border-radius: var(--r-sm);
    background: var(--surface-alt); color: var(--text); font-size: var(--fs-data); min-height: 34px; }
.permit-auto-val.missing { color: var(--text-muted); }
.permit-reset { font-size: var(--fs-nano); color: var(--accent); cursor: pointer; margin-left: 6px;
    text-decoration: none; }
.permit-reset:hover { text-decoration: underline; }
.profile-card { border: 1px solid var(--border); border-radius: var(--r-sm); padding: 10px 12px;
    margin-bottom: 10px; }
.permit-req { color: var(--danger); }
/* Shared options-menu dropdown (task #48 S1; styled after .eq-add-menu —
   kept separate so the equipment palette menu stays untouched) */
.opt-wrap { position: relative; }
.opt-menu { position: absolute; right: 0; top: calc(100% + 6px); display: none;
    min-width: 220px; background: var(--surface); border: 1px solid var(--border-strong);
    border-radius: var(--r-sm); box-shadow: var(--shadow-md); padding: 6px; z-index: 60; }
.opt-menu.open { display: grid; gap: 2px; }
.opt-item { text-align: left; padding: 8px 10px; border: none; background: none;
    color: var(--text); font-size: var(--fs-data); border-radius: var(--r-sm); cursor: pointer; }
.opt-item:hover:not(:disabled) { background: var(--row-hover); }
.opt-item:disabled { color: var(--text-muted); cursor: default; }
.opt-sep { border-top: 1px solid var(--border); margin: 4px 2px; }
.opt-danger { color: var(--danger); }
/* Two-line menu items (Kyle, 2026-08-18): a label with a small muted
   description underneath lets page-scoped actions live in the ONE
   hamburger without losing their explanations. */
.opt-label { font-size: var(--fs-nano); font-weight: 700;
    text-transform: uppercase; letter-spacing: .08em;
    color: var(--text-muted); padding: 4px 10px 0; }
.opt-item .opt-desc { display: block; font-size: var(--fs-nano);
    font-weight: 400; color: var(--text-muted); margin-top: 2px;
    white-space: normal; max-width: 250px; line-height: 1.4; }
.permit-head-actions { margin-left: auto; }
/* Narrative Library (task #48 S4) */
.nl-grid { display: grid; grid-template-columns: 320px minmax(0, 1fr); gap: 14px;
    align-items: start; }
@media (max-width: 1000px) { .nl-grid { grid-template-columns: 1fr; } }
.nl-list { display: flex; flex-direction: column; gap: 2px; }
.nl-group-head { font-size: var(--fs-nano); font-weight: 700; text-transform: uppercase;
    letter-spacing: .5px; color: var(--text-muted); margin: 10px 0 4px; }
.nl-item { display: flex; flex-direction: column; gap: 1px; text-align: left;
    padding: 7px 10px; border: 1px solid transparent; background: none;
    border-radius: var(--r-sm); cursor: pointer; color: var(--text); }
.nl-item:hover { background: var(--row-hover); }
.nl-item.active { background: var(--surface); border-color: var(--accent);
    box-shadow: var(--shadow-sm); }
.nl-item-title { font-size: var(--fs-data); }
.nl-item-key { font-size: var(--fs-nano); color: var(--text-muted); }
.nl-label { display: flex; flex-direction: column; gap: 3px; margin-bottom: 10px;
    font-size: var(--fs-caption); font-weight: 600; color: var(--text-2); }
.nl-label input, .nl-label textarea { padding: 7px 10px; border: 1px solid var(--border-strong);
    border-radius: var(--r-sm); background: var(--surface); color: var(--text);
    font-size: var(--fs-data); font-family: var(--font-ui); resize: vertical; }
.nl-preview-head { display: flex; justify-content: space-between; align-items: center;
    font-size: var(--fs-caption); font-weight: 600; color: var(--text-2); margin-bottom: 4px; }
.nl-preview-head select { padding: 3px 8px; border-radius: var(--r-sm);
    border: 1px solid var(--border-strong); background: var(--surface); color: var(--text); }
.nl-preview { padding: 10px 12px; border: 1px dashed var(--border-strong);
    border-radius: var(--r-sm); background: var(--surface-alt); font-size: var(--fs-data);
    min-height: 44px; }
.nl-preview-note { margin-top: 6px; font-size: var(--fs-nano); color: var(--text-muted); }
.nl-saved { color: var(--ok); font-size: var(--fs-caption); font-weight: 700; }
/* Package composer (task #48 S7) */
.pkg-rows { display: flex; flex-direction: column; gap: 4px; }
.pkg-row { display: flex; align-items: center; gap: 12px; padding: 8px 12px;
    border: 1px solid var(--border); border-radius: var(--r-sm);
    background: var(--surface); }
.pkg-row-off { opacity: .55; }
.pkg-row.dragging { opacity: .5; }
.pkg-row.drag-over { outline: 2px dashed var(--accent); outline-offset: -2px; }
.pkg-grip { cursor: grab; color: var(--text-muted); font-size: 14px; user-select: none; }
.pkg-updown { display: flex; flex-direction: column; gap: 1px; }
.pkg-move { border: 1px solid var(--border); background: var(--surface-alt);
    color: var(--text-2); border-radius: 3px; font-size: 9px; line-height: 1;
    padding: 2px 5px; cursor: pointer; }
.pkg-move:disabled { opacity: .35; cursor: default; }
.pkg-check { display: flex; align-items: center; gap: 5px;
    font-size: var(--fs-caption); color: var(--text-2); }
.pkg-name { font-size: var(--fs-data); font-weight: 600; flex: 1; }
.pkg-title-toggle { margin-left: auto; }
/* Cover Letter view (task #48 S5) */
.pl-card { margin-bottom: 10px; }
.pl-card-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.pl-actions { margin-left: auto; display: flex; gap: 12px; }
.pl-badge { font-size: var(--fs-nano); font-weight: 700; text-transform: uppercase;
    letter-spacing: .5px; padding: 2px 8px; border-radius: var(--r-pill);
    background: var(--surface-alt); color: var(--text-muted); border: 1px solid var(--border); }
.pl-badge-fee { color: var(--accent); border-color: var(--accent); background: var(--accent-tint); }
.pl-badge-manual { color: var(--warn); border-color: var(--warn-bd); background: var(--warn-bg); }
.pl-text { font-size: var(--fs-data); line-height: 1.5; }
.pl-card textarea { width: 100%; padding: 8px 10px; border: 1px solid var(--border-strong);
    border-radius: var(--r-sm); background: var(--surface); color: var(--text);
    font-size: var(--fs-data); font-family: var(--font-ui); resize: vertical; }
/* Permit control panel (task #48 S2) */
.permit-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.permit-chip { display: flex; flex-direction: column; gap: 1px; padding: 6px 12px;
    background: var(--surface-alt); border: 1px solid var(--border); border-radius: var(--r-sm); }
.permit-chip-label { font-size: var(--fs-nano); font-weight: 700; text-transform: uppercase;
    letter-spacing: .5px; color: var(--text-muted); }
.permit-chip-value { font-family: var(--font-data); font-size: var(--fs-data); color: var(--text); }
.permit-ladder { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.permit-rung { font-size: var(--fs-caption); padding: 3px 10px; border-radius: var(--r-pill);
    border: 1px solid var(--border); cursor: help; }
.permit-rung-ok { color: var(--ok); border-color: var(--ok-bd); background: var(--ok-bg); }
.permit-rung-bad { color: var(--danger); border-color: var(--danger-bd); background: var(--danger-bg); }
.permit-rung-warn { color: var(--warn); border-color: var(--warn-bd); background: var(--warn-bg); }
.permit-rec-pill { font-size: var(--fs-caption); font-weight: 700; padding: 4px 12px;
    border-radius: var(--r-pill); background: var(--accent-tint); color: var(--accent);
    border: 1px solid var(--accent); }
.permit-rec-none { background: var(--warn-bg); color: var(--warn); border-color: var(--warn-bd); }
.permit-basis { font-size: var(--fs-nano); color: var(--text-muted); cursor: help; }
/* Legal-description source toggle (task #48 S1) */
.legal-mode-row { display: flex; align-items: center; gap: 12px; }
.legal-mode-row label { font-size: var(--fs-caption); font-weight: 600; color: var(--text-2); }
/* Generated-packages manifest table (task #47 chunk 3d) */
.permit-pkg-table { width: 100%; border-collapse: collapse; font-size: var(--fs-data); }
.permit-pkg-table th { text-align: left; font-size: var(--fs-caption); font-weight: 600;
    color: var(--text-2); padding: 6px 10px; border-bottom: 1px solid var(--border-strong); }
.permit-pkg-table td { padding: 6px 10px; border-bottom: 1px solid var(--border); }
.permit-pkg-table code { font-family: var(--font-data); font-size: var(--fs-caption); }
.permit-pkg-skips { font-size: var(--fs-caption); color: var(--text-2); cursor: help; }
.permit-modal-form { display: flex; flex-direction: column; gap: 14px; }
.permit-modal-form .hint { font-weight: 400; }

/* Smooth theme switch */
body, header, .detail-panel, .equipment-toolbar, .kpi, .fac-table-card,
.view-toggle-btn { transition: background-color .15s ease, color .15s ease, border-color .15s ease; }

/* Settings menu (gear dropdown) */
.settings-wrap { position: relative; }
#settings-btn { padding: 6px 10px; font-size: var(--fs-title); line-height: 1; }
.settings-menu { position: absolute; right: 0; top: calc(100% + 8px);
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md);
    box-shadow: var(--shadow-md); padding: 12px; min-width: 210px; display: none; z-index: 400; }
.settings-menu.open { display: block; }
.settings-section + .settings-section { margin-top: 12px; }
.settings-label { font-size: var(--fs-caption); text-transform: uppercase; letter-spacing: .5px;
    color: var(--text-2); font-weight: 600; margin-bottom: 8px; }
.theme-toggle { display: flex; gap: 6px; }
.theme-opt { flex: 1; padding: 7px 10px; border: 1px solid var(--border-strong);
    border-radius: var(--r-sm); background: var(--surface); color: var(--text-2);
    font-size: var(--fs-data); font-weight: 600; cursor: pointer; }
.theme-opt:hover { background: var(--surface-alt); }
.theme-opt.active { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }

/* Modeling (SCREEN3) tab */
.modeling-cards { display: flex; gap: 12px; flex-wrap: wrap; margin: 8px 0; }
.modeling-card { border: 1px solid var(--border); border-radius: var(--r-md);
    padding: 12px 16px; background: var(--surface-alt); min-width: 170px; }
.modeling-card-value { font-size: var(--fs-heading); font-weight: 700; color: var(--accent); }
.modeling-card-label { font-size: var(--fs-caption); color: var(--text-2); margin-top: 3px; }

/* Forecast tab */
.fc-ladder td { height: 18px; min-width: 18px; }
.fc-ladder .fc-ok { background: var(--ok-bg); border: 1px solid var(--ok-bd); }
.fc-ladder .fc-no { background: var(--danger-bg); border: 1px solid var(--danger-bd); }
.fc-ladder .fc-unk { background: var(--surface-alt); border: 1px dashed var(--border); }
.fc-key { display: inline-block; width: 12px; height: 12px; vertical-align: -2px;
    border-radius: 3px; }
.fc-key.fc-ok { background: var(--ok-bg); border: 1px solid var(--ok-bd); }
.fc-key.fc-no { background: var(--danger-bg); border: 1px solid var(--danger-bd); }
.fc-key.fc-unk { background: var(--surface-alt); border: 1px dashed var(--border); }

/* Site Map & Fleet Map (Leaflet) */
#site-map-canvas { height: calc(100vh - 240px); min-height: 420px;
    border: 1px solid var(--border); border-radius: var(--r-sm); }
/* Leaflet assigns z-indexes (panes 400-700, controls 1000) that resolve
   against the PAGE stacking context unless the map's container makes its
   own. isolation:isolate contains them, so no dialog/panel ever has to
   out-bid Leaflet again. Applies to every Leaflet host. */
#fleet-map-canvas, #site-map-canvas { isolation: isolate; }
#fleet-map-canvas { height: 380px; border: 1px solid var(--border);
    border-radius: var(--r-sm); }
.sitemap-wrap { display: flex; flex-direction: column; gap: 8px; }
.sitemap-controls { align-items: center; }
.ring-toggle { flex-direction: row !important; align-items: center; gap: 6px !important;
    font-size: var(--fs-small); }
.sitemap-unplaced { text-align: left; margin: 0; font-style: normal; }
/* Leaflet popups/controls readable in dark mode */
:root[data-theme="dark"] .leaflet-popup-content-wrapper,
:root[data-theme="dark"] .leaflet-popup-tip,
:root[data-theme="dark"] .leaflet-control-layers,
:root[data-theme="dark"] .leaflet-bar a,
:root[data-theme="dusk"] .leaflet-popup-content-wrapper,
:root[data-theme="dusk"] .leaflet-popup-tip,
:root[data-theme="dusk"] .leaflet-control-layers,
:root[data-theme="dusk"] .leaflet-bar a {
    background: var(--surface); color: var(--text); }

/* The muted map frame (graphics program G2, adopted from the round-2
   prototype): the USGS tiles only come in light, so night themes remap
   the whole tile pane — dark chart ground, labels still legible, pins
   (marker pane) untouched. Containers go theme-dark so tile-load gaps
   never flash white. */
:root[data-theme="dark"] .leaflet-tile-pane,
:root[data-theme="dusk"] .leaflet-tile-pane {
    filter: brightness(.62) invert(1) hue-rotate(185deg) saturate(.55) contrast(.92);
}
:root[data-theme="dark"] .leaflet-container { background: #0b1020; }
:root[data-theme="dusk"] .leaflet-container { background: #262538; }

/* Unplaced-equipment overlay floating on the site map */
.sitemap-map-wrap { position: relative; }
.sitemap-overlay {
    position: absolute; top: 12px; left: 56px;   /* clear of the zoom control */
    z-index: 1100;
    background: var(--panel-overlay);
    border: 1px solid var(--border); border-radius: var(--r-sm);
    box-shadow: var(--shadow-sm);
    padding: 8px 12px; max-width: 240px;
    display: flex; flex-direction: column; gap: 4px; align-items: flex-start;
    font-size: var(--fs-small);
}
.sitemap-overlay-title { font-weight: 700; color: var(--accent);
    font-size: var(--fs-caption); text-transform: uppercase; letter-spacing: .5px; }
.sitemap-overlay-hint { color: var(--text-muted); font-style: italic; }


/* Sources rail (PTE Calcs) */
.rail-group { font-size: var(--fs-nano); font-weight: 700; text-transform: uppercase;
    letter-spacing: .5px; color: var(--text-muted); padding: 8px 4px 2px; }
.rail-source { cursor: pointer; position: relative; }
.rail-source.selected { border-color: var(--accent); background: var(--accent-tint); }
.rail-source.selected::before {
    content: ""; position: absolute; left: 0; top: 15%; bottom: 15%;
    width: 2px; background: var(--accent); border-radius: 2px;
}
.rail-source-text { display: flex; flex-direction: column; line-height: 1.25;
    overflow: hidden; }
.rail-tpy { font-size: var(--fs-nano); color: var(--text-muted); white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis; }
.calc-breakdown { text-align: left; font-size: var(--fs-small); background: var(--surface-alt);
    border: 1px solid var(--border); border-radius: var(--r-sm); padding: 10px 12px;
    overflow-x: auto; white-space: pre-wrap; }

/* Calculation Studio (PTE Calcs per-source workbench) —
   methodology/worksheet LEFT, page preview RIGHT */
.calc-studio { display: grid; grid-template-columns: minmax(380px, 46%) 1fr;
    gap: 14px; align-items: start; }
@media (max-width: 1200px) { .calc-studio { grid-template-columns: 1fr; } }
.calc-page-col { min-width: 0; }
.calc-page-head { display: flex; align-items: baseline; gap: 10px;
    text-align: left; padding: 2px 4px 8px; }
.calc-page-head h3 { margin: 0; font-size: .92rem; }
.calc-page-sub { font-size: .7rem; color: var(--text-muted); }
.calc-page-wrap { background: var(--surface-alt); border-radius: 10px;
    padding: 18px; }
.calc-page {   /* paper: stays light even in dark mode, like print preview */
    position: relative; background: #ffffff; color: #1a1a1a;
    box-shadow: 0 2px 14px rgba(0,0,0,.25); border-radius: 3px;
    padding: 30px 36px; min-height: 500px; text-align: left;
    font-size: .84rem; line-height: 1.45; }
.calc-page .cp-kicker { font-size: .64rem; letter-spacing: 1.2px;
    text-transform: uppercase; color: #666; }
.calc-page .cp-title { font-family: Georgia, "Times New Roman", serif;
    font-size: 1.25rem; margin: 4px 0 2px; color: #111; }
.calc-page .cp-method { color: #555; font-size: .78rem; margin: 0 0 14px;
    border-bottom: 2px solid #222; padding-bottom: 10px; }
.calc-page .cp-h { font-family: Georgia, serif; font-size: .95rem;
    margin: 16px 0 6px; color: #222; }
.calc-page .cp-table { width: 100%; border-collapse: collapse; font-size: .78rem; }
.calc-page .cp-table td, .calc-page .cp-table th {
    border: 1px solid #ccc; padding: 4px 8px; text-align: left; color: #222; }
.calc-page .cp-table th { background: #f0f0f0; }
.calc-page .cp-results td:not(:first-child) { text-align: right; }
.calc-page .cp-subst { font-family: "Consolas", "Menlo", monospace;
    font-size: .72rem; background: #f7f7f5; border: 1px solid #ddd;
    padding: 10px 12px; white-space: pre-wrap; }
.calc-page .cp-notes { font-size: .76rem; padding-left: 18px; color: #333; }
.calc-page .cp-notes li { margin: 3px 0; }
.calc-page .cp-stamp { font-size: .68rem; color: #888; margin-top: 16px;
    border-top: 1px solid #ddd; padding-top: 8px; }
.calc-page .meq { text-align: center; margin: 12px 0;
    font-family: Georgia, "Times New Roman", serif; font-size: 1rem; color: #111; }
.calc-page .meq sub, .calc-page .meq sup { font-size: .62em; }
.calc-page .frac { display: inline-block; vertical-align: middle;
    text-align: center; margin: 0 3px; }
.calc-page .frac .top { display: block; padding: 0 6px 1px;
    border-bottom: 1.4px solid #111; }
.calc-page .frac .bot { display: block; padding: 1px 6px 0; }
.calc-page .eqlabel { float: right; color: #999; font-size: .68rem;
    font-family: "Segoe UI", sans-serif; }
.wb-watermark { position: absolute; top: 10px; right: 12px;
    font-size: .66rem; font-weight: 800; letter-spacing: 1px;
    color: var(--warn); border: 2px solid var(--warn-bd);
    border-radius: 4px; padding: 2px 8px; transform: rotate(2deg);
    opacity: .85; }

/* Right column */
.wb-method { display: flex; gap: 10px; align-items: flex-start;
    border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px;
    margin: 6px 0; cursor: pointer; font-size: .78rem; text-align: left; }
.wb-method.selected { border-color: var(--accent); background: var(--accent-tint); }
.wb-method .wb-cite { color: var(--text-muted); font-size: .7rem; }
.wb-param { margin: 6px 0 6px 26px; text-align: left; }
/* Fleet workspace — the Great Filter (task #56) */
.fleet-bar { align-items: center; }
.fleet-axis-label { font-size: var(--fs-caption); font-weight: 700;
    text-transform: uppercase; letter-spacing: .08em; color: var(--text-muted);
    margin-left: 6px; }
.fleet-bar .fleet-axis-label:first-child { margin-left: 0; }
.fleet-gap .rerun-link { font-size: var(--fs-small); }

/* emission-point group heading between method params (#55 chunk 3) */
.wb-param-group { margin: 10px 0 2px; font-size: .66rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted);
    border-bottom: 1px solid var(--border); padding-bottom: 2px; }
.wb-param label { display: block; font-size: .68rem; color: var(--text-2);
    margin-bottom: 2px; }
/* background-COLOR, not the shorthand: the shorthand resets
   background-image/repeat/size and tore .dp-input's calendar glyph apart
   (the icon tiled across the field in dark/dusk, and vanished in light). */
.wb-param input, .wb-param textarea { width: 100%; max-width: 340px;
    padding: 5px 8px; border: 1px solid var(--border); border-radius: 6px;
    background-color: var(--surface); color: var(--text); font-size: .78rem; }
.wb-actions { display: flex; gap: 10px; align-items: center; margin-top: 10px; }
.wb-dirty { font-size: .7rem; color: var(--warn); font-style: italic; }
.wb-grid input { width: 100%; border: 1px solid transparent; background: none;
    color: var(--text); font-size: .76rem; padding: 2px 4px; }
.wb-grid input:focus { border-color: var(--accent); background: var(--surface); }
.wb-fx-head { font-size: .66rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .5px; color: var(--text-muted); margin: 12px 0 4px;
    text-align: left; }
.fx-row { display: flex; align-items: center; gap: 6px; margin: 4px 0;
    font-family: "Consolas", "Menlo", monospace; font-size: .76rem; }
.fx-pollutant { width: 110px; flex-shrink: 0; font-weight: 700;
    border: 1px solid var(--border); border-radius: 6px; padding: 4px 8px;
    background: var(--surface-alt); color: var(--text); }
.fx-eq { color: var(--text-muted); }
.fx-expr { flex: 1; border: 1px solid var(--border); border-radius: 6px;
    padding: 4px 8px; background: var(--surface); color: var(--text);
    font-family: inherit; }
.fx-expr.ro { border-style: dashed; color: var(--text-2); background: var(--surface-alt); }

/* Toast notifications (non-blocking replacement for alert()) */
#toast-box { position: fixed; right: 18px; bottom: 18px; z-index: 3000;
    display: flex; flex-direction: column; gap: 8px; max-width: 380px; }
.toast { display: flex; align-items: flex-start; gap: 10px;
    padding: 10px 14px; border-radius: 8px; font-size: .8rem;
    line-height: 1.4; border: 1px solid var(--border);
    background: var(--surface); color: var(--text);
    box-shadow: var(--shadow-md); animation: toast-in .18s ease; }
/* Toasts follow the notice recipe (faint mix fill, hairline border,
   body in --text) — the floating channel matches the family. */
.toast-error { background: color-mix(in srgb, var(--danger) 9%, var(--surface));
    border-left: 3px solid var(--danger); }
.toast-success { background: color-mix(in srgb, var(--ok) 9%, var(--surface));
    border-left: 3px solid var(--ok); }
.toast.fade { opacity: 0; transition: opacity .4s ease; }
.toast-x { background: none; border: none; color: inherit; cursor: pointer;
    font-size: .72rem; margin-left: auto; padding: 0 2px; flex-shrink: 0; }
@keyframes toast-in { from { transform: translateY(8px); opacity: 0; } }

/* Workbench: inline error strip, method dropdown, compare table */
.wb-method-select { width: 100%; max-width: 420px; padding: 6px 8px;
    border: 1px solid var(--border); border-radius: 6px;
    background: var(--surface); color: var(--text); font-size: .8rem; }
.wb-compare { margin-top: 8px; font-size: .72rem; }
.wb-compare th .rerun-link { font-weight: 700; }
.wb-compare th.cur, .wb-compare td.cur { background: var(--accent-tint); }
.wb-compare td:not(:first-child) { text-align: right; }
.calc-unsupported { text-align: left; }
.calc-unsupported p { font-size: .82rem; color: var(--text-2); max-width: 640px; }

/* Equation plate: textbook-white editable governing equation with red diff.
   The <pre> mirror renders the colored text and defines the plate's size;
   the transparent textarea sits exactly on top and receives the typing. */
.eq-block { margin: 10px 0 14px; text-align: left; }
.eq-pol { font-size: .7rem; font-weight: 700; color: var(--text-2);
    margin-bottom: 4px; }
.eq-plate { position: relative; background: #ffffff;
    border: 1px solid #cfd4da; border-radius: 6px;
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, .06); }
.eq-plate:focus-within { border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-tint); }
.eq-mirror, .eq-input { font-family: "STIX Two Math", "Cambria Math",
    "Latin Modern Math", Georgia, serif; font-size: 1.02rem; line-height: 1.5;
    padding: 10px 12px; margin: 0; box-sizing: border-box;
    white-space: pre-wrap; word-break: break-word; text-align: left; }
.eq-mirror { color: #1a1a1a; min-height: calc(1.5em + 20px); }
.eq-mirror .eq-mod { color: #c0392b; font-weight: 700; }
.eq-input { position: absolute; inset: 0; width: 100%; height: 100%;
    background: transparent; color: transparent; caret-color: #1a1a1a;
    border: none; resize: none; overflow: hidden; outline: none; }
.eq-input::selection { background: rgba(52, 152, 219, .28); }
.eq-vars { display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: center;
    font-size: .72rem; color: var(--text-muted); margin-top: 4px; }
.eq-var i { font-family: Georgia, serif; }
.eq-caption { font-size: .7rem; color: var(--text-muted); font-style: italic;
    text-align: left; margin: 8px 0 4px; border-left: 3px solid #c0392b;
    padding-left: 8px; line-height: 1.5; }

/* Per-tab rail widgets */
.rail-note { font-size: .72rem; color: var(--text-2); text-align: left;
    padding: 2px 4px 6px; line-height: 1.45; }
.rail-chip { display: inline-block; margin: 2px 2px; padding: 4px 10px;
    border: 1px solid var(--border); border-radius: 12px; background: var(--surface-alt);
    color: var(--text); font-size: .7rem; cursor: pointer; }
.rail-chip.on { border-color: var(--chip, var(--accent)); color: var(--chip, var(--accent));
    background: var(--accent-tint); font-weight: 700; }
.rail-reg summary { font-size: .74rem; font-weight: 600; cursor: pointer;
    padding: 4px 2px; color: var(--text); }
.rail-limit-form { display: flex; flex-direction: column; gap: 4px; padding: 0 2px; }
.rail-limit-form select, .rail-limit-form input { padding: 4px 6px; font-size: .72rem;
    border: 1px solid var(--border); border-radius: 6px; background: var(--surface);
    color: var(--text); }
.rail-limit-row { font-size: .72rem; text-align: left; padding: 2px 2px; }

/* Right panel as slide-over on non-docked tabs */
.detail-panel.overlay { position: fixed; right: 0;
    top: calc(var(--header-h) + var(--fnav-h)); bottom: 0;
    z-index: 1200; box-shadow: -8px 0 24px rgba(0,0,0,.25);
    border-left: 2px solid var(--accent); }

/* ── AI chat assistant drawer (task #83) ───────────────────────────── */
.chat-drawer { width: min(420px, 92vw); display: flex; flex-direction: column;
    background: var(--surface); top: var(--header-h); }
.chat-head { display: flex; align-items: center; gap: 6px; padding: 10px 12px;
    border-bottom: 1px solid var(--border); }
.chat-title { font-weight: 700; color: var(--text); }
.chat-body { flex: 1; overflow-y: auto; padding: 12px; display: flex;
    flex-direction: column; gap: 8px; }
.chat-msg { max-width: 85%; padding: 8px 11px; border-radius: 12px;
    font-size: .85rem; line-height: 1.45; overflow-wrap: break-word; }
.chat-msg.user { align-self: flex-end; background: var(--accent);
    color: var(--on-accent); border-bottom-right-radius: 4px; }
.chat-msg.assistant { align-self: flex-start; background: var(--surface-alt);
    color: var(--text); border: 1px solid var(--border);
    border-bottom-left-radius: 4px; }
.chat-msg.error { align-self: stretch; max-width: none; background: none;
    border: 1px solid var(--danger); color: var(--danger); }
.chat-tool-note { align-self: flex-start; font-size: .72rem;
    color: var(--text-muted); padding: 0 4px; }
.chat-thinking { align-self: flex-start; color: var(--text-muted);
    font-size: .8rem; padding: 2px 4px;
    animation: chat-pulse 1.2s ease-in-out infinite; }
.chat-thinking::after { content: "…"; }
@keyframes chat-pulse { 50% { opacity: .35; } }
.chat-form { display: flex; gap: 8px; padding: 10px 12px;
    border-top: 1px solid var(--border); }
.chat-form textarea { flex: 1; resize: none; padding: 7px 9px;
    font: inherit; font-size: .85rem; color: var(--text);
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: var(--r-sm); }
.chat-form textarea:focus { outline: none; border-color: var(--accent); }
.chat-empty { padding: 16px 14px; color: var(--text-2); font-size: .85rem; }
.chat-empty p { margin: 0 0 10px; }
.chat-hint { color: var(--text-muted); font-style: italic; }
.chat-code { background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: 6px; padding: 8px 10px; font-family: monospace;
    font-size: .75rem; color: var(--text); overflow-x: auto; }
.chat-proposal { align-self: stretch; background: var(--surface);
    border: 1px solid var(--accent); border-radius: 10px;
    padding: 10px 12px; font-size: .8rem; }
.chat-proposal-head { font-weight: 700; color: var(--text);
    margin-bottom: 6px; }
.chat-proposal-id { color: var(--text-muted); font-weight: 400;
    font-size: .72rem; margin-left: 4px; }
.chat-diff-row { display: flex; align-items: baseline; gap: 6px;
    padding: 2px 0; flex-wrap: wrap; }
.chat-diff-label { color: var(--text-2); min-width: 40%; }
.chat-diff-old { color: var(--text-muted); text-decoration: line-through; }
.chat-diff-arrow { color: var(--text-muted); }
.chat-diff-new { color: var(--text); font-weight: 600; }
.chat-proposal-actions { display: flex; gap: 8px; margin-top: 8px; }
.chat-proposal-status { margin-top: 8px; font-size: .72rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: .04em;
    color: var(--text-muted); }
.chat-proposal-status.applied { color: var(--accent); }
.chat-proposal-status.rejected, .chat-proposal-status.superseded {
    color: var(--danger); }

/* ── Command palette (task #83 M5) — Ctrl+K ────────────────────────── */
.palette-overlay { position: fixed; inset: 0; z-index: 2600;
    background: rgba(0,0,0,.35); display: flex;
    justify-content: center; align-items: flex-start;
    padding-top: 14vh; }
.palette-box { width: min(640px, 92vw); background: var(--surface);
    border: 1px solid var(--border); border-radius: var(--r-md, 10px);
    box-shadow: var(--shadow-md, 0 12px 40px rgba(0,0,0,.35));
    overflow: hidden; }
.palette-form { display: flex; align-items: center; gap: 8px;
    padding: 12px 14px; border-bottom: 1px solid var(--border); }
.palette-glyph { color: var(--accent); font-size: 1rem; }
.palette-input { flex: 1; border: none; outline: none; background: none;
    font: inherit; font-size: .95rem; color: var(--text); }
.palette-input::placeholder { color: var(--text-muted); }
.palette-results { max-height: 46vh; overflow-y: auto; display: flex;
    flex-direction: column; gap: 8px; padding: 10px 14px; }
.palette-results:empty { display: none; }
.palette-status { color: var(--text-muted); font-size: .85rem;
    animation: chat-pulse 1.2s ease-in-out infinite; }
.palette-answer { color: var(--text); font-size: .88rem;
    line-height: 1.5; overflow-wrap: break-word; }
/* The current turn (echoed request + answer/cards) sits ABOVE the rail
   and is the only thing a new request resets. */
.palette-turn { display: flex; flex-direction: column; gap: 8px; }
.palette-turn:empty { display: none; }
.palette-echo { color: var(--text-muted); font-size: .85rem;
    border-left: 2px solid var(--accent); padding-left: 8px;
    overflow-wrap: break-word; }
/* Quick-actions rail ("fix next") — deterministic jump rows under the
   input when the palette opens on a facility. Rows are actions → cyan
   accent on hover, matching the jump-chip idiom. */
.palette-rail { display: flex; flex-direction: column; gap: 4px; }
.palette-rail-head { font-size: .72rem; text-transform: uppercase;
    letter-spacing: .04em; color: var(--text-muted); padding: 2px 0 4px; }
.palette-rail-row { display: flex; align-items: baseline; gap: 10px;
    width: 100%; text-align: left; cursor: pointer;
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: var(--r-sm, 6px); padding: 7px 10px; font: inherit; }
.palette-rail-row:hover { border-color: var(--accent); }
.palette-rail-row:hover .palette-rail-label { color: var(--accent); }
.palette-rail-label { color: var(--text); font-size: .85rem; flex: 1;
    min-width: 0; }
.palette-rail-where { color: var(--text-muted); font-size: .72rem;
    white-space: nowrap; }
.palette-rail-more { color: var(--text-muted); font-size: .75rem;
    padding: 2px 0; }
/* Header nudge (Kyle, 2026-08-22): tempt people into trying the
   palette. Clicking it delivers what it advertises. */
.palette-hint { border: 1px solid var(--border); background: var(--surface-alt);
    color: var(--text-muted); font: inherit; font-size: .72rem;
    padding: 4px 10px; border-radius: 999px; cursor: pointer;
    white-space: nowrap; }
.palette-hint:hover { color: var(--accent); border-color: var(--accent); }

/* ── eCFR viewer ─────────────────────────────────────────────────────── */
.ecfr-code { background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: 6px; padding: 10px 14px; font-family: monospace; font-size: var(--fs-data);
    color: var(--text); margin: 8px 0; }

/* THE reason ~40% of a wide window sat unused. Every app-level workspace
   shares .facilities-home, whose max-width:1340px is right for the card
   dashboards (a centred column of KPIs and tables) but wrong for the reader,
   which is a full-height three-pane workspace that should use the glass it
   is given. Measured before this rule: the reader stuck at 1296px at any
   window size, and past ~1500px the rails hit their max while the reading
   pane SHRANK to 548px — 16% of a 3440px screen. Scoped with :has() so the
   eCFR dashboard on the same element keeps the shared cap. */
#ecfr-workspace:has(.ecfr-reader) { max-width: none; }

/* Fills the window at any width: the rails scale with the viewport but stay
   inside sane bounds, and the reading pane takes everything left over. The
   46rem cap that used to live here capped the middle column itself; the
   reading measure now belongs to the frame instead (see .ecfr-frames below),
   so it only constrains the text, never the layout. */
.ecfr-reader { display: grid; min-height: 0; height: 100%; gap: 14px;
    grid-template-columns: clamp(240px, 18vw, 340px) minmax(0, 1fr) clamp(280px, 21vw, 380px); }
.ecfr-toc, .ecfr-pane, .ecfr-annotations { background: var(--surface);
    border: 1px solid var(--border); border-radius: var(--radius);
    box-shadow: var(--shadow-sm); overflow-y: auto; min-height: 0; }
/* Reserve the scrollbar's width permanently. Without it the bar appears only
   once you scroll — and lands directly on top of the row stars, which sit at
   the same right edge. Worse: the stars are invisible until hover, and
   hovering the right edge is exactly what summons the bar, so the two arrive
   together in the same pixels. `stable` keeps the gutter there always, so the
   layout can't shift under the cursor mid-reach. */
.ecfr-toc { scrollbar-gutter: stable; }
/* The pane itself no longer scrolls — each frame body does, so the two
   sides can be scrolled to matching places independently. */
.ecfr-pane { display: flex; flex-direction: column; overflow: hidden; padding: 14px; }

/* Search sits above everything: it's the fastest way into 10,812 sections. */
.ecfr-search { display: flex; align-items: center; gap: 4px; padding: 10px 10px 8px;
    border-bottom: 1px solid var(--border); }
.ecfr-search-input { flex: 1; min-width: 0; font-size: var(--fs-small); padding: 5px 8px;
    background: var(--surface-alt); color: var(--text);
    border: 1px solid var(--border); border-radius: var(--r-sm); }
.ecfr-search-input:focus { outline: none; border-color: var(--accent); }
.ecfr-search-x { flex: none; background: none; border: none; cursor: pointer;
    color: var(--text-muted); font-size: var(--fs-data); padding: 4px 6px; }
.ecfr-search-x:hover { color: var(--text); }
.ecfr-search-count { font-size: var(--fs-nano); color: var(--text-muted); padding: 8px 12px 4px;
    text-transform: uppercase; letter-spacing: .04em; font-weight: 700; }
.ecfr-search-hit { display: block; width: calc(100% - 16px); margin: 0 8px 3px;
    text-align: left; background: none; border: none; border-radius: var(--r-sm);
    padding: 6px 8px; cursor: pointer; }
.ecfr-search-hit:hover { background: var(--surface-alt); }
.ecfr-search-hit.current { background: var(--accent-tint); }
.ecfr-search-head { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; font-size: var(--fs-small); font-weight: 600; color: var(--text);
    line-height: 1.3; }
.ecfr-search-snip { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
    overflow: hidden; font-size: var(--fs-caption); color: var(--text-2); line-height: 1.4;
    margin-top: 2px; }
/* The matched terms, marked by the FTS snippet sentinels. */
.ecfr-search-snip b { color: var(--accent); font-weight: 700; }
.ecfr-search-more { display: block; width: calc(100% - 16px); margin: 6px 8px 10px;
    padding: 5px; background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: 5px; color: var(--text-2); font-size: var(--fs-caption); cursor: pointer; }
.ecfr-search-more:hover:not(:disabled) { color: var(--text); }
.ecfr-search-more:disabled { opacity: .5; cursor: default; }

/* Reader controls. These were .rerun-link — underlined blue text — which
   reads as "this navigates away" when every one of them acts on the page you
   are already on. Scoped to the reader rather than restyling .rerun-link,
   which the workbench and obligations screens also use. */
.ecfr-btn { display: inline-flex; align-items: center; gap: 5px;
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: var(--r-sm); color: var(--text-2); cursor: pointer;
    font-size: var(--fs-caption); line-height: 1; padding: 5px 9px;
    text-decoration: none; white-space: nowrap; }
.ecfr-btn:hover:not(:disabled) { background: var(--surface); color: var(--text);
    border-color: var(--text-muted); }
/* .rerun-link had no :disabled rule at all, so a dead prev/next still looked
   like a live link. Three call sites pass `disabled`. */
.ecfr-btn:disabled { opacity: .45; cursor: default; }
.ecfr-btn.on { background: var(--accent); border-color: var(--accent);
    color: var(--on-accent); font-weight: 700; }
/* Prev/next carry a section heading and must not shove the row's other
   controls off; they truncate instead. */
.ecfr-btn.ecfr-btn-nav { max-width: 22ch; overflow: hidden;
    text-overflow: ellipsis; display: inline-block; }

.ecfr-toc-head { font-size: var(--fs-caption); font-weight: 700; text-transform: uppercase;
    letter-spacing: .04em; color: var(--text-muted); padding: 12px 12px 6px; }

/* A TOC row is the node's own control plus its star. The star must not be
   inside the button (invalid, and it would swallow the click), so the row
   is the flex parent and the button takes the slack. */
/* The row is inset from the scroll container's edge so the star has room to
   be clicked; scrollbar-gutter above reserves the bar's width, this keeps the
   star off the gutter. .ecfr-search-hit already worked this way — the tree
   rows just never got the same treatment. */
.ecfr-toc-row { display: flex; align-items: flex-start; gap: 2px;
    padding-right: 6px; }
.ecfr-toc-row > button { flex: 1; min-width: 0; }
/* 24px, not 20: a 20px glyph box is under the ~24px minimum that a pointer
   target wants, and this one is small, low-contrast and only appears on hover. */
.ecfr-star { flex: none; width: 24px; padding: 4px 0; cursor: pointer;
    text-align: center; font-size: var(--fs-data); line-height: 1.2; border-radius: 4px;
    color: var(--text-muted); opacity: 0; transition: opacity .12s ease; }
/* Invisible until you go looking for it, or until it's on — 10,812 rows of
   permanently-visible stars would be noise, not affordance. */
.ecfr-toc-row:hover .ecfr-star, .ecfr-toc-subpart summary:hover .ecfr-star,
.ecfr-star:focus-visible { opacity: 1; }
.ecfr-star.on { opacity: 1; color: var(--star); }
.ecfr-star:hover { color: var(--star); background: var(--surface-alt); }
.ecfr-toc-subpart summary .ecfr-star { margin-left: auto; }

/* Collapsible groups: the pinned favorites, and the whole tree. */
.ecfr-toc-favs > summary, .ecfr-toc-root > summary { display: flex; align-items: center;
    gap: 6px; cursor: pointer; list-style: none; }
.ecfr-toc-favs > summary::-webkit-details-marker,
.ecfr-toc-root > summary::-webkit-details-marker { display: none; }
.ecfr-toc-favs > summary::before, .ecfr-toc-root > summary::before {
    content: "▾"; width: 10px; flex: none; font-weight: 400; }
.ecfr-toc-favs:not([open]) > summary::before,
.ecfr-toc-root:not([open]) > summary::before { content: "▸"; }
.ecfr-toc-favs > summary:hover, .ecfr-toc-root > summary:hover { color: var(--text-2); }
.ecfr-toc-favs { border-bottom: 1px solid var(--border); padding-bottom: 6px; }
.ecfr-toc-fav { display: flex; align-items: baseline; gap: 6px; width: 100%;
    text-align: left; background: none; border: none; border-radius: var(--r-sm);
    padding: 5px 8px; cursor: pointer; font-size: var(--fs-data); color: var(--text-2); }
.ecfr-toc-fav:hover { background: var(--surface-alt); color: var(--text); }
.ecfr-toc-fav.current { background: var(--accent-tint); color: var(--accent); font-weight: 700; }
.ecfr-toc-fav-icon { flex: none; width: 12px; color: var(--text-muted); }
.ecfr-toc-fav-label { display: -webkit-box; -webkit-line-clamp: 2;
    -webkit-box-orient: vertical; overflow: hidden; line-height: 1.35; }

/* "Applies to your equipment": the reverse cross-link, rule text -> your units. */
.ecfr-eq-row { display: block; width: calc(100% - 16px); margin: 0 8px 3px;
    text-align: left; background: none; border: 1px solid var(--border);
    border-radius: var(--r-sm); padding: 6px 8px; cursor: pointer; }
.ecfr-eq-row:hover { background: var(--surface-alt); }
.ecfr-eq-top { display: flex; align-items: center; gap: 6px; }
.ecfr-eq-unit { font-size: var(--fs-small); font-weight: 700; color: var(--text); }
.ecfr-eq-badge { margin-left: auto; font-size: var(--fs-nano); font-weight: 700;
    letter-spacing: .04em; padding: 1px 5px; border-radius: 999px; }
.ecfr-eq-badge.yes { background: var(--danger-bg); color: var(--danger); }
.ecfr-eq-badge.no { background: var(--ok-bg); color: var(--ok); }
.ecfr-eq-desc { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; font-size: var(--fs-caption); color: var(--text-2); line-height: 1.35; }
.ecfr-eq-fac { display: block; font-size: var(--fs-nano); color: var(--text-muted); margin-top: 2px; }

/* The ↗ beside an in-corpus citation: the viewer link is primary, this is
   the escape hatch to the authoritative text. */
.cite-ext { margin-left: 3px; font-size: .8em; text-decoration: none; }

/* --- Version diff (local -> live) ---------------------------------- */
/* Insertion green / deletion red, the convention everyone already reads.
   Deletions keep the strike so the two are still distinguishable without
   colour — the marks must survive a colourblind reader and a mono printout. */
.ecfr-diff-ins { background: var(--ok-bg); color: var(--ok); text-decoration: none;
    border-bottom: 2px solid var(--ok); border-radius: 2px; padding: 0 1px; }
.ecfr-diff-del { background: var(--danger-bg); color: var(--danger);
    text-decoration: line-through; opacity: .75; border-radius: 2px; padding: 0 1px; }
/* The armed state comes from .ecfr-btn.on (accent fill). An accent-COLOURED
   rule here would land on that accent fill and vanish — same specificity,
   later in the file, so it would win. */
.ecfr-diff-badge { display: inline-block; font-size: var(--fs-nano); font-weight: 700;
    letter-spacing: .04em; text-transform: uppercase; padding: 2px 7px;
    border-radius: 999px; margin-bottom: 6px; }
.ecfr-diff-badge.added { background: var(--ok-bg); color: var(--ok); }
.ecfr-diff-badge.removed { background: var(--danger-bg); color: var(--danger); }
.ecfr-diff-badge.changed { background: var(--accent-tint); color: var(--accent); }
/* Tables are badged whole rather than cell-diffed — a half-aligned table is
   unreadable, so the badge marks the boundary of what we're claiming. */
.ecfr-diff-table { border-left: 3px solid var(--border); padding-left: 10px; margin: 14px 0; }
.ecfr-diff-table.added { border-left-color: var(--ok); }
.ecfr-diff-table.removed { border-left-color: var(--danger); }
.ecfr-diff-table.changed { border-left-color: var(--accent); }
.ecfr-diff-none { padding: 10px 12px; margin-bottom: 12px; border-radius: var(--r-sm);
    background: var(--surface-alt); color: var(--text-2); font-size: var(--fs-small); }
/* Nothing is annotatable here, so don't offer a text cursor that implies it. */
.ecfr-frame-body.diffing { cursor: default; }
.ecfr-toc-part-head { display: flex; align-items: baseline; gap: 6px; width: 100%;
    text-align: left; background: none; border: none; padding: 6px 10px; cursor: pointer;
    font-size: var(--fs-data); color: var(--text); border-radius: 4px; }
.ecfr-toc-part-head:hover { background: var(--surface-alt); }
.ecfr-toc-part-head.current { color: var(--accent); font-weight: 700; }
.ecfr-toc-caret { width: 12px; color: var(--text-muted); flex: none; }
.ecfr-toc-num { font-weight: 600; flex: none; }
.ecfr-toc-title { color: var(--text-2); overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; }
.ecfr-toc-children { padding-left: 22px; }
.ecfr-toc-loading { padding: 6px 12px; font-size: var(--fs-small); color: var(--text-muted); }
/* Subpart rows carry the full heading, so they wrap. The default disclosure
   marker would sit oddly next to a multi-line block; use the same ▸/▾ caret
   the part rows above use instead. */
.ecfr-toc-subpart summary { display: flex; gap: 6px; align-items: baseline;
    font-size: var(--fs-data); font-weight: 600; color: var(--text-2);
    cursor: pointer; padding: 5px 8px; line-height: 1.35; list-style: none; }
.ecfr-toc-subpart summary::-webkit-details-marker { display: none; }
.ecfr-toc-subpart summary::before { content: "▸"; flex: none; width: 10px;
    color: var(--text-muted); font-weight: 400; }
.ecfr-toc-subpart[open] summary::before { content: "▾"; }
.ecfr-toc-subpart summary:hover { color: var(--text); }
/* A few headings run past 250 chars — clamp so one subpart can't swallow the
   sidebar; the full text is in the summary's title tooltip. */
.ecfr-toc-subpart-label { display: -webkit-box; -webkit-line-clamp: 3;
    -webkit-box-orient: vertical; overflow: hidden; }
/* Section rows carry the full heading ("§ 60.21 Definitions."), so they wrap
   rather than truncate at one line; two lines covers most, and the full text
   is in the title tooltip. */
.ecfr-toc-section { display: -webkit-box; -webkit-line-clamp: 2;
    -webkit-box-orient: vertical; width: calc(100% - 8px); text-align: left;
    background: none; border: none; padding: 4px 8px 4px 20px; margin: 0 0 0 4px;
    cursor: pointer; font-size: var(--fs-data); color: var(--text-2); border-radius: 4px;
    line-height: 1.35; overflow: hidden; }
.ecfr-toc-section:hover { background: var(--surface-alt); color: var(--text); }
.ecfr-toc-section.current { background: var(--accent-tint); color: var(--accent); font-weight: 700; }
.ecfr-toc-section.appendix { font-style: italic; }
/* An appendix is a top-level division of the part, so it sits at the same
   indent as a subpart's summary rather than inside one. */
.ecfr-toc-appendix { display: -webkit-box; -webkit-line-clamp: 2;
    -webkit-box-orient: vertical; overflow: hidden; width: 100%; text-align: left;
    background: none; border: none; padding: 5px 8px 5px 18px; cursor: pointer;
    font-size: var(--fs-data); font-style: italic; color: var(--text-2);
    border-radius: var(--r-sm); line-height: 1.35; }
.ecfr-toc-appendix:hover { background: var(--surface-alt); color: var(--text); }
.ecfr-toc-appendix.current { background: var(--accent-tint); color: var(--accent);
    font-weight: 700; }

.ecfr-empty { display: flex; align-items: center; justify-content: center; height: 100%; }
.ecfr-pane-nav { display: flex; justify-content: space-between; gap: 12px; flex: none;
    padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px solid var(--border);
    font-size: var(--fs-small); }
.ecfr-pane-nav button { max-width: 40%; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; }
/* Annotation toolbar: armed-tool model, so the armed state has to be
   unmistakable — it changes what a drag in the text does. */
.ecfr-toolbar { display: flex; align-items: center; gap: 4px; flex: none;
    flex-wrap: wrap; padding: 0 0 10px; margin-bottom: 10px;
    border-bottom: 1px solid var(--border); }
.ecfr-toolbar:empty { display: none; }
.ecfr-tool { min-width: 28px; height: 26px; padding: 0 6px; background: var(--surface-alt);
    border: 1px solid var(--border); border-radius: var(--r-sm); color: var(--text-2);
    font-size: var(--fs-data); line-height: 1; cursor: pointer; }
.ecfr-tool:hover:not(:disabled) { background: var(--surface); color: var(--text); }
.ecfr-tool:disabled { opacity: .4; cursor: default; }
.ecfr-tool.armed { background: var(--accent); border-color: var(--accent); color: var(--on-accent);
    font-weight: 700; }
.ecfr-tool.tool-underline { text-decoration: underline; }
.ecfr-tool.tool-strike { text-decoration: line-through; }
.ecfr-tool-swatches { display: flex; gap: 3px; margin-left: 4px; }
.ecfr-tool-sep { width: 1px; height: 18px; background: var(--border); margin: 0 4px; }
.ecfr-swatch { width: 18px; height: 18px; border-radius: 50%; cursor: pointer;
    border: 2px solid transparent; padding: 0; }
.ecfr-swatch.armed { border-color: var(--text); }
.ecfr-tool-hint { margin-left: 10px; color: var(--text-2); font-size: var(--fs-caption); }

/* Reading frames: 1 (single) or 2 (compare) side by side, each scrolling
   independently under a header that names the version it's showing. */
.ecfr-frames { display: flex; gap: 12px; flex: 1; min-height: 0;
    overflow-x: auto; scroll-snap-type: x proximity; }
/* The reading measure lives here rather than on the grid column, so a wide
   window is actually filled (rails, chrome, a second frame) while a single
   column of running text still stops at a comfortable line length instead
   of stretching to 1400px. Two frames are each narrow enough already. */
.ecfr-frames[data-count="1"] .ecfr-section { max-width: 60rem; margin: 0 auto; }
/* flex-basis 40% is what puts ~2.5 frames on screen at three or more: they
   can't shrink below it, so the row overflows and scrolls instead of
   squeezing every frame into an unreadable column. One or two frames still
   divide the width evenly, because there's slack to grow into. */
.ecfr-frame { flex: 1 0 40%; min-width: 300px; scroll-snap-align: start;
    display: flex; flex-direction: column;
    border: 1px solid var(--border); border-radius: var(--r-sm); overflow: hidden; }
.ecfr-frame.dragging { opacity: .5; }
.ecfr-frame.drag-over { outline: 2px dashed var(--accent); outline-offset: -2px; }
.ecfr-frame-grip { flex: none; cursor: grab; color: var(--text-muted);
    font-size: var(--fs-data); line-height: 1; letter-spacing: -1px; }
.ecfr-frame-head[draggable="true"] { cursor: grab; }
.ecfr-frame-head:active { cursor: grabbing; }
/* A live frame is visually distinct at a glance: its text is not the
   snapshot the rest of the app reasons about. */
.ecfr-frame.live { border-left: 3px solid var(--accent); }
/* nowrap is load-bearing: every frame's header must be exactly one line tall,
   or a frame carrying the scratch warning pushes its body down and its text
   stops lining up with the frame beside it. The provenance label ellipsises
   to make room instead. */
.ecfr-frame-head { display: flex; align-items: center; gap: 8px; flex: none;
    flex-wrap: nowrap; padding: 7px 10px; background: var(--surface-alt);
    border-bottom: 1px solid var(--border); }
/* Scratch-mark warning, in the live frame's OWN header, beside the label that
   says it's live — a fact about this frame, stated on this frame. Persistent
   chrome, not a toast: a toast fades and the mark outlives it, at which point
   a scratch mark looks exactly like a saved one. The full sentence is in the
   tooltip; this stays short so the header stays one line. */
.ecfr-scratch-warn { flex: none; padding: 2px 7px; border-radius: 999px;
    background: var(--warn-bg); color: var(--warn); border: 1px solid var(--warn-bd);
    font-size: var(--fs-nano); font-weight: 700; line-height: 1.4; white-space: nowrap;
    cursor: help; }
/* The picker only has to be pickable — it names the source, which the
   provenance beside it names again along with the exact version. Capped so it
   stops stealing width from the one label that carries information the other
   doesn't: the date. */
.ecfr-frame-source { flex: 0 1 auto; max-width: 8.5rem; font-size: var(--fs-caption);
    padding: 2px 4px; }
/* This must name the exact version on screen, never just the source — it's
   the whole reason a frame has a header. It gets the slack. */
.ecfr-frame-provenance { flex: 1 1 auto; min-width: 0; font-size: var(--fs-caption);
    font-weight: 700; color: var(--text-2); white-space: nowrap; overflow: hidden;
    text-overflow: ellipsis; }
.ecfr-frame-body { flex: 1; min-height: 0; overflow-y: auto; padding: 16px 22px 40px; }
/* Only ever on the frame the annotator is bound to — a paint tool is armed
   and dragging here will mark the text up. */
.ecfr-frame-body.annotating { cursor: crosshair; }
/* A frame holds a whole unit now: one article per section, stacked. The rule
   between them is what makes a subpart read as a sequence of sections rather
   than one undifferentiated wall. */
.ecfr-section + .ecfr-section { margin-top: 30px; padding-top: 24px;
    border-top: 2px solid var(--border); }
.ecfr-section.current > .ecfr-section-head .ecfr-citation { color: var(--accent); }
.ecfr-section-head { display: flex; align-items: center; gap: 6px; }
.ecfr-section-head .ecfr-star { opacity: 0; }
.ecfr-section:hover .ecfr-star, .ecfr-section-head .ecfr-star.on { opacity: 1; }
/* Reserve space for text that hasn't been filled in yet, so the scrollbar
   doesn't lurch as sections resolve under you. */
.ecfr-section-pending { min-height: 90px; }
/* Which unit this frame is showing. Frame CHROME, outside the scroller —
   sticky inside it stuck to the padding edge and let text scroll through the
   gap above it. It doesn't move, because what it says doesn't change as you
   scroll: the unit is the page. */
.ecfr-unit-label { flex: none; display: flex; align-items: baseline; gap: 8px;
    padding: 6px 12px; background: var(--surface-alt);
    border-bottom: 1px solid var(--border); }
.ecfr-unit-part { font-size: var(--fs-caption); font-weight: 700; color: var(--accent);
    text-transform: uppercase; letter-spacing: .04em; }
.ecfr-unit-name { font-size: var(--fs-caption); color: var(--text-2); flex: 1; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ecfr-unit-count { font-size: var(--fs-nano); color: var(--text-muted); }

.ecfr-citation { font-size: var(--fs-small); font-weight: 600; color: var(--text-muted);
    text-transform: uppercase; letter-spacing: .03em; }
.ecfr-heading { font-size: var(--fs-heading); font-weight: 700; color: var(--text);
    margin: 4px 0 10px; line-height: 1.35; }
.ecfr-meta { font-size: var(--fs-small); color: var(--text-muted); line-height: 1.6;
    margin-bottom: 18px; }
.ecfr-meta b { color: var(--text-2); font-weight: 600; }
.ecfr-blocks { font-size: var(--fs-body); line-height: 1.65; color: var(--text); }
.ecfr-block { margin: 0 0 12px; }
.ecfr-table-wrap { margin: 16px 0; overflow-x: auto; }
.ecfr-table { border-collapse: collapse; width: 100%; font-size: var(--fs-data); }
.ecfr-table caption { text-align: left; font-weight: 600; font-size: var(--fs-data);
    color: var(--text-2); margin-bottom: 6px; caption-side: top; }
.ecfr-table th, .ecfr-table td { border: 1px solid var(--border); padding: 6px 9px;
    text-align: left; vertical-align: top; }
.ecfr-table th { background: var(--thead-bg); color: var(--thead-text); font-weight: 600; }
.ecfr-table-footnotes { font-size: var(--fs-caption); color: var(--text-muted); margin-top: 6px;
    line-height: 1.5; }

.ecfr-annotations-head { font-size: var(--fs-caption); font-weight: 700; text-transform: uppercase;
    letter-spacing: .04em; color: var(--text-muted); padding: 12px 14px 6px; }

/* Right-panel accordion. Native <details> so open/close needs no JS; the
   open state is mirrored into ecfrAccOpen purely so a re-render can restore
   it. Sections stack, and each body scrolls with the panel as a whole. */
.ecfr-acc { border-top: 1px solid var(--border); }
.ecfr-acc summary { display: flex; align-items: center; gap: 6px; cursor: pointer;
    padding: 9px 12px; list-style: none; font-size: var(--fs-caption); font-weight: 700;
    text-transform: uppercase; letter-spacing: .04em; color: var(--text-2); }
.ecfr-acc summary::-webkit-details-marker { display: none; }
.ecfr-acc summary::before { content: "▸"; width: 10px; flex: none;
    color: var(--text-muted); font-weight: 400; }
.ecfr-acc[open] > summary::before { content: "▾"; }
.ecfr-acc summary:hover { color: var(--text); }
.ecfr-acc-n { margin-left: auto; background: var(--surface-alt); border-radius: 999px;
    padding: 1px 7px; font-size: var(--fs-nano); color: var(--text-muted); font-weight: 600; }
.ecfr-acc-body { padding-bottom: 10px; }

/* The annotation tree: every mark in Title 40, part > subpart > section,
   browsable from wherever you happen to be standing. */
.ecfr-tree-node { display: flex; align-items: baseline; gap: 6px; width: 100%;
    text-align: left; background: none; border: none; border-radius: var(--r-sm);
    padding: 4px 8px; cursor: pointer; font-size: var(--fs-small); color: var(--text-2); }
.ecfr-tree-node:hover { background: var(--surface-alt); color: var(--text); }
/* Where you already are, so the tree tells you that without you working it out. */
.ecfr-tree-node.here { color: var(--accent); font-weight: 700; }
.ecfr-tree-caret { flex: none; width: 10px; color: var(--text-muted); font-size: var(--fs-caption); }
.ecfr-tree-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; }
.ecfr-tree-sub { margin-left: 6px; color: var(--text-muted); font-weight: 400; }
.ecfr-tree-n { flex: none; background: var(--surface-alt); border-radius: 999px;
    padding: 0 6px; font-size: var(--fs-nano); color: var(--text-muted); font-weight: 700; }
.ecfr-tree-subpart { padding-left: 12px; }
.ecfr-tree-section { padding-left: 12px; }
.ecfr-tree-row { display: flex; align-items: baseline; gap: 6px;
    width: calc(100% - 20px); margin-left: 20px; text-align: left; background: none;
    border: none; border-radius: var(--r-sm); padding: 3px 6px; cursor: pointer; }
.ecfr-tree-row:hover { background: var(--surface-alt); }
.ecfr-tree-dot { flex: none; width: 9px; height: 9px; border-radius: 2px;
    font-size: var(--fs-nano); line-height: 9px; text-align: center; color: var(--text-muted); }
.ecfr-tree-dot.note { background: none; }
.ecfr-tree-quote { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; font-size: var(--fs-caption); color: var(--text-2); font-style: italic; }

/* Scope filter: widest → narrowest, left to right, mirroring the tree. */
.ecfr-scope-bar { display: flex; flex-wrap: wrap; gap: 4px; padding: 0 12px 10px;
    border-bottom: 1px solid var(--border); margin-bottom: 10px; }
.ecfr-scope { display: inline-flex; align-items: center; gap: 5px; padding: 3px 7px;
    background: var(--surface-alt); border: 1px solid var(--border); border-radius: 999px;
    color: var(--text-2); font-size: var(--fs-caption); cursor: pointer; max-width: 100%; }
.ecfr-scope:hover { color: var(--text); }
.ecfr-scope.active { background: var(--accent-tint); border-color: var(--accent);
    color: var(--accent); font-weight: 700; }
.ecfr-scope-n { background: var(--border); color: var(--text-2); border-radius: 999px;
    padding: 0 5px; font-size: var(--fs-nano); font-weight: 600; min-width: 14px; text-align: center; }
.ecfr-scope.active .ecfr-scope-n { background: var(--accent); color: #fff; }
/* Which section a row lives in — only rendered when that isn't the open one. */
.ecfr-hl-where { display: block; background: none; border: none; padding: 0 0 2px;
    color: var(--accent); font-size: var(--fs-nano); font-weight: 600; cursor: pointer;
    text-align: left; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; }
.ecfr-hl-where:hover { text-decoration: underline; }

.ecfr-bookmark-star { display: block; width: calc(100% - 24px); margin: 0 12px 10px;
    padding: 7px 10px; background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: 6px; color: var(--text-2); font-size: var(--fs-small); text-align: left;
    cursor: pointer; }
.ecfr-bookmark-star.on { background: var(--star-tint); border-color: var(--star);
    color: var(--star); font-weight: 600; }
.ecfr-annot-section-head { font-size: var(--fs-caption); font-weight: 700; text-transform: uppercase;
    letter-spacing: .04em; color: var(--text-muted); padding: 10px 12px 4px;
    border-top: 1px solid var(--border); margin-top: 4px; }
.ecfr-highlight-item { display: flex; align-items: flex-start; gap: 6px;
    padding: 6px 12px; font-size: var(--fs-small); }
.ecfr-highlight-item.orphaned { opacity: .7; }
.ecfr-highlight-item:not(.orphaned):not(.editing) { cursor: pointer; }
.ecfr-highlight-item:not(.orphaned):not(.editing):hover { background: var(--surface-alt); }
.ecfr-highlight-item.editing { display: block; background: var(--surface-alt); }
.ecfr-hl-body { flex: 1; min-width: 0; }
.ecfr-highlight-quote { flex: 1; color: var(--text-2); font-style: italic;
    border-left: 3px solid #fde68a; padding-left: 8px; line-height: 1.4; display: block; }
.ecfr-highlight-item.orphaned .ecfr-highlight-quote { border-left-color: var(--text-muted); }
/* Colour/kind at a glance, so the list mirrors what's painted in the text. */
.ecfr-hl-swatch { flex: none; width: 10px; height: 10px; border-radius: 2px;
    margin-top: 3px; border: 1px solid rgba(0, 0, 0, .25); }
.ecfr-hl-swatch.kind-underline { height: 3px; border-radius: 0; margin-top: 7px; }
.ecfr-hl-swatch.kind-strike { height: 3px; border-radius: 0; margin-top: 7px; opacity: .8; }
.ecfr-hl-comment { font-size: var(--fs-caption); color: var(--text); line-height: 1.45;
    margin: 4px 0 0 8px; white-space: pre-wrap; }
.ecfr-hl-controls { display: flex; align-items: center; gap: 4px; margin: 8px 0 6px; }
.ecfr-hl-controls .spec-select { margin-left: auto; font-size: var(--fs-caption); }
.ecfr-annot-x { flex: none; background: none; border: none; color: var(--text-muted);
    cursor: pointer; font-size: var(--fs-caption); padding: 2px 4px; }
.ecfr-annot-x:hover { color: var(--danger); }
.ecfr-orphan-note { font-size: var(--fs-caption); color: var(--text-muted); padding: 4px 12px;
    line-height: 1.4; }
.ecfr-note-item { padding: 8px 12px; border-bottom: 1px solid var(--border); }
.ecfr-note-item:last-child { border-bottom: none; }
.ecfr-note-text { font-size: var(--fs-small); color: var(--text); line-height: 1.5;
    white-space: pre-wrap; margin-bottom: 4px; }
.ecfr-note-textarea { width: 100%; min-height: 56px; resize: vertical;
    font-family: inherit; font-size: var(--fs-small); padding: 6px 8px; border: 1px solid var(--border);
    border-radius: var(--r-sm); background: var(--surface); color: var(--text); box-sizing: border-box; }
.ecfr-note-actions { display: flex; align-items: center; gap: 10px; margin-top: 4px; }
.ecfr-note-new { background: var(--surface-alt); }

/* The annotator paints absolutely-positioned spans in an overlay layer, so
   the reading text itself is never mutated. The layer blends with
   mix-blend-mode:multiply (vendor CSS), which is why dark theme needs the
   lighter touch below rather than the same opacities. */
.ecfr-frame-body .r6o-annotation { border-radius: 2px; }
:root[data-theme="dark"] .ecfr-frame-body .r6o-span-highlight-layer,
:root[data-theme="dusk"] .ecfr-frame-body .r6o-span-highlight-layer {
    mix-blend-mode: screen; }

/* Part 60 Subpart A modal (task #22 ①) */
.p60-h { font-size: var(--fs-small); text-transform: uppercase;
    letter-spacing: .06em; color: var(--thead-text); margin: 14px 0 6px; }
.p60-list { margin: 0 0 4px 18px; padding: 0; }
.p60-list li { font-size: var(--fs-data); color: var(--text-2);
    margin-bottom: 7px; line-height: 1.5; }

/* Data workspace sub-band: full-width strip, one line down from the
   equipment band so it reads as the same nav family at workspace level. */
.data-subnav { position: static; margin: 0 0 16px; padding: 12px 0;
    background: transparent; border-bottom: 2px solid var(--border); }
.num { text-align: right; font-variant-numeric: tabular-nums; }

/* Fired-source emission line items (task #36) */
/* Emissions summary: basis toggle + regulatory-gate checkboxes (r5) */
.pte-basis-row {
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    margin: 0 0 10px 0;
}
.pte-gate {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: 0.72rem; color: var(--text-2); cursor: pointer;
    user-select: none;
}
.pte-gate input { accent-color: var(--accent); }
.pte-gate-hint {
    flex-basis: 100%; color: var(--text-muted); font-size: 0.66rem;
}

.pte-comp { display: inline-block; font-size: var(--fs-nano);
    font-weight: 600; color: var(--accent); background: var(--accent-tint);
    border-radius: var(--r-pill); padding: 0 6px; margin-left: 4px; }
/* Never-calculated units sit in the PTE table as zero rows (Kyle's
   rule) — the tag keeps their dashes from reading as "zero emissions". */
.pte-uncalc { color: var(--warn);
    background: color-mix(in srgb, var(--warn) 14%, transparent); }
.cp-line { margin: 8px 0; }
.cp-line-h { font-size: var(--fs-small); margin: 6px 0 3px; color: #1a1a1a; }
.cp-line-method { font-weight: 400; color: #666; font-size: var(--fs-caption); }
/* The citation under a factor value (#77-E3): engine factors layer per
   pollutant, so each row names the document its factor came from. Left
   aligned against the right-aligned number so the two don't run together. */
.cp-factor-cite {
    font-size: var(--fs-caption); color: #666; font-weight: 400;
    text-align: left; margin-top: 2px; line-height: 1.25;
}
.cp-line-total .cp-line-h { border-top: 1px solid #ccc; padding-top: 6px; }

/* Fired-source emission-point sections (detail panel) */
.eq-collapse { border: 1px solid var(--border); border-radius: var(--r-sm);
    margin-bottom: 8px; overflow: hidden; }
.eq-collapse-head { display: flex; align-items: center; gap: 8px;
    padding: 7px 10px; background: var(--surface-alt); cursor: pointer;
    font-size: var(--fs-data); user-select: none; }
.eq-collapse-head:hover { background: var(--row-hover); }
.eq-collapse-caret { color: var(--accent); font-size: var(--fs-small); width: 10px; }
.eq-collapse-rate { margin-left: auto; font-family: var(--font-data);
    font-size: var(--fs-caption); color: var(--ok); }
.eq-collapse-body { padding: 8px 10px; }
.eq-collapse.collapsed .eq-collapse-body { display: none; }

/* Facilities-page tools row (#57 — replaced the global header button) */
.home-tools { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }

/* Inactive/removed units grey out on the Equipment page (#57 follow-up):
   the inventory still lists them, but they must not read as live sources
   — their stored rates are stale and they're excluded from PTE. */
.equip-strip.eq-inactive, .grid-table tr.eq-inactive td {
    opacity: .45; filter: grayscale(.8); }
.equip-strip.eq-inactive:hover { opacity: .7; }
.eq-off-tag { font-size: var(--fs-nano); font-weight: 700;
    letter-spacing: .08em; color: var(--text-muted);
    border: 1px solid var(--border-strong); border-radius: var(--r-pill);
    padding: 1px 7px; vertical-align: middle; }

/* Facility Info pane (#59, card redo after facilitycritique.png):
   section cards with responsive field grids + a footer action bar. */
.facinfo-pane { padding: 4px 2px 20px; }
    /* no own max-width (was 940px): the contained pane already caps the
       frame — Facility Info now spans the same width as Equipment
       (Kyle's mismatchformats.png, 2026-08-12) */
.fi-card { background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--r-md); padding: 14px 18px 16px; margin-bottom: 14px; }
.fi-card h3 { color: var(--accent); font-size: var(--fs-title); font-weight: 700;
    /* One section-header idiom app-wide: same face as .grid-section-header
       h3 (the small-caps caption style read as a third language next to
       the Equipment view — Kyle, 2026-08-11). */
    border-bottom: 1px solid var(--border-strong);
    padding-bottom: 6px; margin-bottom: 12px; }
.fi-card-hint { margin: -4px 0 10px; }
.fi-grid { display: grid; gap: 12px 18px;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.fi-grid-compact { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.fi-field label { display: block; font-size: var(--fs-caption);
    font-weight: 600; color: var(--text-2); margin-bottom: 4px; }
.fi-field input, .fi-field select { width: 100%; padding: 7px 10px;
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: var(--r-sm); color: var(--text);
    font-size: var(--fs-data); box-sizing: border-box; }
.fi-field input:focus, .fi-field select:focus {
    outline: none; border-color: var(--accent); }
.fi-span2 { grid-column: span 2; }
.fi-hint { font-size: var(--fs-caption); color: var(--text-muted);
    margin-top: 4px; line-height: 1.45; }
.fi-static { font-size: var(--fs-data); color: var(--text);
    padding: 6px 0 8px; }
.fi-btn-field { display: flex; align-items: flex-end; }
.fi-btn-field .btn { width: auto; }
.fi-footer { display: flex; justify-content: space-between;
    align-items: center; margin-top: 4px; padding: 0 2px; }
/* Autosave indicator (replaced the Save Changes button) — quiet by
   default, so it reads as reassurance rather than a status alarm. */
.fi-saved { font-size: var(--fs-hint, .78rem); color: var(--text-muted); }
.fi-saved-ok { color: var(--ok, var(--text-muted)); }
@media (max-width: 640px) { .fi-span2 { grid-column: auto; } }

/* Facilities tier segment + greyed view tabs (#59) */
.fac-tier { flex-shrink: 0; }
.fac-dim { opacity: .35; pointer-events: none; }

/* Battery dialog checkbox rows (#57) */
.bat-cb-row { display: flex; align-items: center; gap: 8px;
    padding: 5px 2px; font-size: var(--fs-data); cursor: pointer; }
.bat-cb-row:hover { background: var(--row-hover); }

/* Facility switcher dialog (#57 — replaced the header dropdown) */
.fac-switcher-bar { display: flex; gap: 8px; margin-bottom: 10px; }
.fac-switcher-bar input[type="search"] { flex: 1; padding: 7px 10px;
    border: 1px solid var(--border-strong); border-radius: var(--r-sm);
    background: var(--bg); color: var(--text); font-size: var(--fs-data); }
.fac-switcher-bar select { padding: 6px 10px; background: var(--surface-alt);
    color: var(--text); border: 1px solid var(--border); border-radius: var(--r-sm);
    font-size: var(--fs-data); }
.fac-switch-table tr { cursor: pointer; }
.fac-switch-table td { padding: 8px 10px; }
.fac-switch-sub { font-size: var(--fs-caption); color: var(--text-muted); }
.fac-switch-current td { background: var(--accent-tint); }

/* Section method hint (#57 — tank groups' AP-42 vs ProMax notes) */
.sec-note { font-size: var(--fs-caption); color: var(--text-muted);
    margin: 6px 0 2px; font-style: italic; }

/* Inline calculation detail (#55 chunk 9 — the old popup's math, in place) */
.eq-line-calc { margin-top: 6px; padding: 6px 8px; background: var(--surface-alt);
    border-left: 2px solid var(--accent); border-radius: 0 var(--r-sm) var(--r-sm) 0;
    font-size: var(--fs-caption); color: var(--text-2); }
.eq-line-calc-method { font-weight: 600; margin-bottom: 3px; }
.eq-line-calc ul { margin: 3px 0 0; padding-left: 16px; }
.eq-line-calc li { margin-bottom: 2px; font-family: var(--font-data); }
.calc-detail { margin-top: 6px; }
.calc-detail summary { cursor: pointer; font-size: var(--fs-small);
    color: var(--accent); user-select: none; }

/* Emission-point child rows in the equipment grid */
.grid-table tr.grid-child { color: var(--text-2); }
.grid-table tr.grid-child td { border-bottom: 1px dashed var(--border);
    font-size: var(--fs-caption); padding-top: 3px; padding-bottom: 3px; }
.grid-child-name { padding-left: 18px !important; color: var(--accent); white-space: nowrap; }
.grid-child-desc { color: var(--text-muted); font-style: italic; }
/* Data > Documents (task #48 S8) */
.doc-link-chip { display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px;
    font-size: var(--fs-caption); background: var(--accent-tint); color: var(--accent);
    border: 1px solid var(--accent); border-radius: var(--r-pill); }
.doc-unlink { cursor: pointer; font-weight: 700; }
.doc-link-sel { margin-left: 6px; padding: 2px 6px; font-size: var(--fs-caption);
    border: 1px solid var(--border-strong); border-radius: var(--r-sm);
    background: var(--surface); color: var(--text-2); }
/* Appendix manager panel (task #48 S9) */
.apx-panel { margin: 2px 0 6px 46px; padding: 8px 12px; border: 1px dashed var(--border-strong);
    border-radius: var(--r-sm); background: var(--surface-alt); display: flex;
    flex-direction: column; gap: 5px; }
.apx-row { display: flex; align-items: center; gap: 10px; font-size: var(--fs-caption); }
.apx-row-avail { opacity: .75; }
.apx-name { font-weight: 600; color: var(--text); }
.apx-kind { font-size: var(--fs-nano); text-transform: uppercase; letter-spacing: .5px;
    color: var(--text-muted); }
.apx-reason { color: var(--text-2); font-style: italic; margin-left: auto; }
.apx-attach { display: flex; align-items: center; gap: 8px; margin-top: 4px;
    padding-top: 6px; border-top: 1px solid var(--border); }
/* Verify Placement split view (task #48 S10) */
#permits-workspace:has(.permit-split) { max-width: none; }
.permit-split-wrap { max-width: none; }
.permit-split { display: grid; grid-template-columns: minmax(340px, 38%) 1fr;
    gap: 14px; align-items: start; }
@media (max-width: 1100px) { .permit-split { grid-template-columns: 1fr; } }
.split-side { position: sticky; top: 10px; max-height: calc(100vh - 130px);
    overflow-y: auto; }
.split-fields { display: flex; flex-direction: column; gap: 2px; }
.split-field { display: flex; justify-content: space-between; gap: 10px;
    padding: 6px 10px; border: 1px solid transparent; background: none;
    text-align: left; border-radius: var(--r-sm); cursor: pointer; color: var(--text); }
.split-field:hover { background: var(--row-hover); }
.split-field.active { border-color: var(--accent); background: var(--accent-tint); }
.split-field-name { font-size: var(--fs-caption); color: var(--text-2); }
.split-field-val { font-family: var(--font-data); font-size: var(--fs-caption); }
.split-paper { display: flex; flex-direction: column; gap: 12px; }
.split-page { position: relative; width: 100%; background: #fff;
    border: 1px solid var(--border-strong); border-radius: 3px;
    box-shadow: var(--shadow-md); }
.split-page img { position: absolute; inset: 0; width: 100%; height: 100%; }
.split-hl { position: absolute; border: 2px solid #e0342e;
    background: rgba(224, 52, 46, .12); border-radius: 3px; pointer-events: none; }
.split-hl.pulse { animation: split-pulse 1.2s ease-out 2; }
@keyframes split-pulse {
    0% { box-shadow: 0 0 0 0 rgba(224, 52, 46, .55); }
    100% { box-shadow: 0 0 0 14px rgba(224, 52, 46, 0); }
}
@media (prefers-reduced-motion: reduce) { .split-hl.pulse { animation: none; } }
/* docx hybrid mock (task #48 S11) */
.mock-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
    gap: 14px; align-items: start; }
.mock-card { margin: 0; }
.mock-head { display: flex; align-items: center; justify-content: space-between;
    border-bottom: 2px solid var(--border-strong); padding-bottom: 6px; margin-bottom: 8px; }
.mock-head h3 { margin: 0; text-transform: uppercase; letter-spacing: .5px;
    font-size: var(--fs-caption); }
.mock-row { display: flex; justify-content: space-between; gap: 12px;
    padding: 4px 0; border-bottom: 1px solid var(--border); font-size: var(--fs-caption); }
.mock-label { color: var(--text-2); }
.mock-val { font-family: var(--font-data); text-align: right; }
.mock-page { margin-top: 10px; }
.mock-page img { width: 100%; border: 1px solid var(--border-strong);
    border-radius: 3px; background: #fff; box-shadow: var(--shadow-md); }

/* --- Login (#15) ---------------------------------------------------- */
/* Standalone page (login.html), but on the app's tokens rather than
   landing.css's fixed dark palette — signing in should look like the
   place you are signing in TO, in whichever theme you left it in. */
.login-body { display: flex; align-items: center; justify-content: center;
    min-height: 100vh; margin: 0; padding: 24px;
    background: var(--bg); color: var(--text); }
/* display/height reset first: this is a <main>, and the app-shell rule
   `main { display: flex; height: calc(100vh - …) }` above would otherwise
   lay the card's children out in a ROW and stretch it to the viewport. */
.login-card { display: block; height: auto;
    width: 100%; max-width: 340px; padding: 28px 28px 22px;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--r-md); box-shadow: var(--shadow-md); }
.login-brand { justify-content: center; font-size: var(--fs-title); }
.login-sub { margin: 4px 0 20px; text-align: center;
    font-size: var(--fs-caption); color: var(--text-muted); }
.login-label { display: block; margin-bottom: 4px;
    font-size: var(--fs-caption); color: var(--text-2); }
.login-input { width: 100%; margin-bottom: 14px; box-sizing: border-box; }
/* Reserves no space until it has something to say, so the button doesn't
   jump down the page on the first failed attempt. */
.login-error { margin: 0; font-size: var(--fs-caption); color: var(--danger);
    display: none; }
.login-error.visible { display: block; margin-bottom: 10px; }
.login-submit { width: 100%; margin-top: 4px; }
.login-foot { margin: 18px 0 0; text-align: center;
    font-size: var(--fs-nano); color: var(--text-muted); }
.login-foot code { font-family: var(--font-data); }

/* The signed-in chip in the header (index.html → .header-actions). */
.auth-chip { display: inline-flex; align-items: center; gap: 6px;
    padding-left: 8px; margin-left: 2px; border-left: 1px solid var(--border);
    font-size: var(--fs-caption); color: var(--text-2); }
.auth-chip[hidden] { display: none; }
.auth-chip .auth-user { max-width: 12ch; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; }

/* ── #68 tier-1 responsive (kept LAST: these override base rules that
      appear above, and at equal specificity source order decides) ────── */
/* #94 (2026-08-26): between 1100px and ~1320px the header was WIDER than the
   window — ten workspace tabs + the "Try Ctrl-K" pill + the account chip —
   so the settings gear clipped off the right edge and the PAGE grew a
   horizontal scrollbar (found by ecfr_reader_layout at 1280, but it is the
   header, not the reader). Two savings buy the row ~185px: the pill is only
   a hint (the chat button's title still says Ctrl+K), and the tabs can
   lose 4px of padding each. Wrapping is the last resort and is now
   unconditional — flex-wrap only acts when the row does not fit, and
   --header-h follows the header's REAL height via app.js's ResizeObserver,
   so the wrap can be any number of rows. Never let the header overflow the
   page: the reader's frame strip is the one thing meant to scroll sideways
   (.ecfr-frames), and it scrolls inside itself. */
@media (max-width: 1320px) {
    .palette-hint { display: none; }
    .ws-btn { padding: 5px 10px; }
}
header { flex-wrap: wrap; row-gap: 4px; }
@media (max-width: 1100px) {
    /* Workspace tabs themselves wrap once even the tightened row is too
       wide for the band. */
    .workspace-nav { flex-wrap: wrap; }
}
@media (max-width: 1000px) {
    .kpis { grid-template-columns: repeat(2, 1fr); }   /* 2x2, not a crush */
}
@media (max-width: 800px) {
    .permit-fields { grid-template-columns: 1fr; }     /* readable form fields */
}

/* #68: first columns of the shared tables are short identifiers/dates
   (DUE, module, facility, batch #) — never let them break mid-value. */
.fac-table td:first-child, .fac-table th:first-child { white-space: nowrap; }

/* #69: unit IDs never break ("TK-"/"1" across lines in the coverage
   matrix); the routing table earns its card's width. */
.cov-unit { white-space: nowrap; }
#routing-view .grid-table { width: 100%; }

/* #69: a KPI slot with no value yet shows a prompt, not a fake numeral
   ("set rate" used to render in the mono KPI face). */
.kpi .kpi-cta { font: italic var(--fs-small) var(--font-ui); color: var(--text-muted);
    margin-top: 6px; }

/* ── Empty states (#67 G3) ──────────────────────────────────────────── */
.empty-state { display: flex; flex-direction: column; align-items: center;
    gap: 7px; padding: 42px 20px 36px; text-align: center;
    color: var(--text-muted); }
.empty-state .es-glyph { width: 44px; height: 44px; opacity: .5; }
.empty-state .es-title { font-weight: 700; color: var(--text-2);
    font-size: var(--fs-title); }
.empty-state .es-hint { font-size: var(--fs-small); font-style: italic;
    max-width: 52ch; margin: 0; }
.empty-state .es-cta { margin-top: 10px; }

/* ── Workspace glyphs (#67 G1) ──────────────────────────────────────── */
.ws-glyph { width: 21px; height: 21px; margin-right: 9px;
    vertical-align: -3.5px; color: var(--accent); flex-shrink: 0; }
.sys-head .ws-glyph { align-self: center; }

/* ── #68 rev 2: tab-band scroll hints + narrow Plan View ────────────── */
.fnav-arrow { position: fixed; z-index: 2500; width: 28px; height: 28px;
    display: flex; align-items: center; justify-content: center;
    /* Bare beam-language chevrons (Kyle 2026-08-11): no chip, just the
       signal — SVG strokes (text ‹ › sat off-center in their em-box),
       with a tight contrast HALO that hugs the glyph shape so it reads
       over tab labels, then the beam glow in the night themes. */
    background: none; border: none; padding: 0;
    color: var(--accent); cursor: pointer;
    --arrow-halo: rgba(255, 255, 255, .95);
    filter: drop-shadow(0 0 1px var(--arrow-halo))
            drop-shadow(0 0 1px var(--arrow-halo));
    opacity: 0; pointer-events: none; transition: opacity .18s ease; }
.fnav-arrow:hover { color: var(--accent-hover); }
:root[data-theme="dark"] .fnav-arrow,
:root[data-theme="dusk"] .fnav-arrow {
    --arrow-halo: rgba(5, 9, 18, .95);
    filter: drop-shadow(0 0 1px var(--arrow-halo))
            drop-shadow(0 0 1px var(--arrow-halo))
            drop-shadow(0 0 6px rgba(98, 217, 232, .8)); }
.fnav-arrow.show { opacity: 1; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) { .fnav-arrow { transition: none; } }
.view-toggle .fnav-sep:last-child { display: none; }  /* no orphaned rules */
@media (max-width: 1100px) {
    /* Plan View narrow mode: the legend is reference info — give its
       width back to the canvas (toolbar auto-collapses in app.js). */
    .map-legend { display: none; }
}

/* ── Equipment glyphs (#67 G5): sizing per context ───────────────────── */
.eq-glyph { display: inline-block; vertical-align: -4px; flex-shrink: 0; }
.eq-glyph.item-icon { width: 19px; height: 19px; margin-right: 8px; }
.eq-glyph.grid-tab-icon { width: 17px; height: 17px; margin-right: 6px; vertical-align: -3.5px; }
.eq-glyph.type-icon { width: 17px; height: 17px; margin-right: 6px; }
#panel-icon .eq-glyph { width: 20px; height: 20px; }

/* ── Routing tab: per-line control trains (task #54) ─────────────────
   Split sources render one sub-row per process line; the Control Train
   column carries the per-hop audit trail (print-friendly plain text). */
.routing-table td { vertical-align: top; }
.route-split-btn { display: block; margin-top: 4px; font-size: 0.66rem; }
.route-line-row td { border-bottom-style: dotted; }
.route-line-row.route-line-first td:first-child {
    border-bottom-style: solid;   /* the rowspanned source cell */
}
.route-line-name {
    font-size: 0.74rem; color: var(--text-2); white-space: nowrap;
    padding-left: 12px !important;
}
.route-trail { font-size: 0.72rem; line-height: 1.5; }
.route-trail .route-origin { color: var(--text-2); font-weight: 600; }
.route-trail .route-hop { padding-left: 8px; white-space: nowrap; }
.route-trail .route-hop-note {
    color: var(--text-muted); font-size: 0.66rem; margin-left: 6px;
}
.route-trail .route-math {
    margin-top: 2px; padding: 1px 6px; display: inline-block;
    border-left: 2px solid var(--accent); color: var(--text-2);
    font-variant-numeric: tabular-nums;
}

/* Print = the permit-file audit trail: selects become their chosen text
   via the route trail (already plain), chrome and controls drop out. */
@media print {
    .route-split-btn, .routing-table select { display: none; }
    .route-trail .route-hop, .route-line-name { white-space: normal; }
    .routing-table td, .routing-table th {
        border-bottom: 1px solid #999; color: #000;
    }
}

/* ── Routing board v2 (task #54 + Kyle's diagram rework): the full
   process-train diagram. Board and table BOTH render; the mode class
   hides one, and @media print always gets the table (the audit
   surface). Tokens sit in stage columns inside a two-axis scrollable
   canvas; SVG wires are colored by stream (the Plan View legend). ── */
.routing-mode-board .routing-table-wrap { display: none; }
.routing-mode-table .rb-viewport,
.routing-mode-table .rb-toolbar,
.routing-mode-table .rb-hint { display: none; }
.routing-mode-toggle { margin-left: auto; }

.rb-toolbar {
    display: flex; align-items: center; gap: 14px;
    margin: 10px 0 8px 0;
}
.rb-legend { display: flex; gap: 12px; font-size: 0.68rem; color: var(--text-2); }
.rb-leg { display: inline-flex; align-items: center; gap: 5px; }
.rb-leg::before {
    content: ""; width: 16px; height: 0;
    border-top: 2px dashed currentColor;
}
.rb-leg-gas { color: #c0392b; }
.rb-leg-oil { color: #27ae60; }
.rb-leg-water { color: #3498db; }
.rb-leg-vapor { color: #e67e22; }
#rb-autoroute { margin-left: auto; }

.rb-viewport {
    overflow: auto; max-height: max(420px, calc(100vh - 340px));
    border: 1px solid var(--border); border-radius: 10px;
    background:
        radial-gradient(circle, color-mix(in srgb, var(--border) 55%, transparent) 1px,
                        transparent 1px) 0 0 / 22px 22px,
        var(--bg);
}
.rb-canvas {
    position: relative; display: flex; align-items: flex-start;
    gap: 90px; min-width: max-content; padding: 16px 26px 24px 26px;
}
.rb-wires {
    position: absolute; inset: 0; overflow: visible; z-index: 1;
    pointer-events: none;
}
.rb-wire {
    fill: none; stroke-width: 1.7; opacity: 0.85;
    stroke-dasharray: 7 4; pointer-events: none;
    animation: rb-flow 1.6s linear infinite;
}
/* The invisible fat twin under each wire takes the pointer — the
   visible 1.7px stroke was nearly unclickable (Kyle, 2026-08-13). */
.rb-wire-hit {
    fill: none; stroke: transparent; stroke-width: 16;
    pointer-events: stroke; cursor: pointer;
}
.rb-wire-gas   { stroke: #c0392b; }
.rb-wire-oil   { stroke: #27ae60; }
.rb-wire-water { stroke: #3498db; }
.rb-wire-vapor { stroke: #e67e22; }
.rb-wire-mixed { stroke: #f1c40f; }
.rb-wireg:hover .rb-wire, .rb-wire-hot .rb-wire { stroke-width: 2.8; opacity: 1; }
.rb-spotlight .rb-wireg:not(.rb-wire-hot) .rb-wire { opacity: 0.18; }
@keyframes rb-flow { to { stroke-dashoffset: -22; } }
@media (prefers-reduced-motion: reduce) { .rb-wire { animation: none; } }
.rb-wire-label {
    fill: var(--text-2); font-size: 0.64rem; font-weight: 600;
    paint-order: stroke; stroke: var(--bg); stroke-width: 3px;
    font-variant-numeric: tabular-nums;
}
.rb-col { display: flex; flex-direction: column; min-width: 150px; }
.rb-col-head {
    font-size: 0.62rem; letter-spacing: 0.09em; text-transform: uppercase;
    color: var(--text-muted); margin-bottom: 24px;   /* vent-arrow headroom */
}
.rb-token {
    position: relative; z-index: 2;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: 8px; padding: 6px 8px; margin-bottom: 38px;
    width: 150px; box-shadow: 0 1px 3px rgba(10, 14, 24, 0.06);
}
.rb-token-head { display: flex; align-items: center; gap: 6px; }
.rb-token-glyph { width: 15px; height: 15px; color: var(--accent); flex: none; }
.rb-token-title { font-weight: 600; font-size: 0.75rem; flex: 1; }
.rb-token-type { color: var(--text-muted); font-size: 0.62rem; margin: 1px 0 2px 21px; }
.rb-venting {
    width: 9px; height: 9px; border-radius: 50%; flex: none;
    background: var(--warn);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--warn) 25%, transparent);
}
.rb-split { font-size: 0.62rem; padding: 1px 7px; flex: none; }
.rb-badge {
    display: inline-block; font-size: 0.6rem; color: var(--text-2);
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: 5px; padding: 1px 6px; margin: 2px 0 2px 21px;
}
/* The tank's −2% breathing loss draws as a vent arrow rising off the
   token (SVG, vapor wire style) — no text badge on the card. */
.rb-vent-line {
    fill: none; stroke: #e67e22; stroke-width: 1.4;
    stroke-dasharray: 3 3; opacity: 0.85; pointer-events: none;
    animation: rb-flow 1.6s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .rb-vent-line { animation: none; } }
.rb-vent-head { fill: none; stroke: #e67e22; stroke-width: 1.4; }
.rb-vent-label { font-size: 0.56rem; fill: #a8672a; }
:root[data-theme="dark"] .rb-vent-label,
:root[data-theme="dusk"] .rb-vent-label { fill: #e8b06a; }
.rb-chip {
    display: flex; align-items: center; gap: 6px;
    margin: 5px 0 0 21px; padding: 2px 8px; border-radius: 999px;
    border: 1px solid var(--border-strong); background: var(--surface-alt);
    font-size: 0.68rem; cursor: grab; user-select: none;
    width: max-content; max-width: calc(100% - 21px);
}
.rb-chip:active { cursor: grabbing; }
.rb-chip-dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--text-muted); flex: none;
}
.rb-chip-routed .rb-chip-dot { background: #e67e22; }
.rb-chip-sales .rb-chip-dot { background: var(--ok); }
.rb-chip-loose .rb-chip-dot {
    background: var(--warn);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--warn) 30%, transparent);
}
.rb-ports {
    display: flex; flex-wrap: wrap; gap: 5px; margin: 6px 0 1px 21px;
}
.rb-port {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 0.6rem; color: var(--text-2); cursor: grab;
    border: 1px solid var(--border); border-radius: 999px;
    padding: 1px 7px; background: var(--surface); user-select: none;
}
.rb-port:active { cursor: grabbing; }
.rb-port-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.rb-port-gas .rb-port-dot { background: #c0392b; }
.rb-port-oil .rb-port-dot { background: #27ae60; }
.rb-port-water .rb-port-dot { background: #3498db; }
.rb-selected, .rb-chip:focus-visible, .rb-port:focus-visible {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent);
}
.rb-token.rb-drop-hot, .rb-token:focus-visible {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 35%, transparent);
}
/* Inline parameter editor (click a device/tank token): DRE on
   flare/combustor, per-pass loss on tanks — writes the same columns
   as the Equipment panel (dre_pct / vapor_loss_pct). */
.rb-inline-edit {
    margin: 5px 0 2px 21px; padding: 5px 8px;
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: 6px; font-size: 0.66rem; color: var(--text-2);
}
.rb-inline-edit label { display: flex; align-items: center; gap: 6px; font-weight: 600; }
.rb-inline-edit input {
    width: 64px; padding: 1px 5px; font-size: 0.7rem;
    border: 1px solid var(--border-strong); border-radius: 4px;
    background: var(--surface); color: var(--text);
    font-variant-numeric: tabular-nums;
}
.rb-inline-hint { display: block; margin-top: 3px; color: var(--text-muted); }

.rb-token-sales { border-style: solid; }
.rb-token-atmo { border-style: dashed; background: transparent; }
.rb-hint { color: var(--text-muted); font-size: 0.7rem; margin-top: 8px; }

/* One stream per tab (Kyle's scope-back): the canvas carries
   .rb-stream-<stream>; everything not of that stream hides. */
.rb-tabs { display: inline-flex; gap: 2px; }
.rb-tab {
    border: 1px solid var(--border); background: var(--surface);
    color: var(--text-2); font-size: 0.68rem; padding: 3px 12px;
    cursor: pointer; border-radius: 6px;
    display: inline-flex; align-items: center; gap: 6px;
}
.rb-tab::before {
    content: ""; width: 8px; height: 8px; border-radius: 50%;
    background: currentColor; opacity: 0.65;
}
.rb-tab-vapor::before { background: #e67e22; }
.rb-tab-oil::before   { background: #27ae60; }
.rb-tab-gas::before   { background: #c0392b; }
.rb-tab-water::before { background: #3498db; }
.rb-tab.active {
    border-color: var(--accent); color: var(--text);
    box-shadow: inset 0 -2px 0 var(--accent);
}
#rb-clear { margin-left: auto; }
#rb-autoroute { margin-left: 0; }

.rb-canvas:not(.rb-stream-vapor) .rb-chip,
.rb-canvas:not(.rb-stream-vapor) .rb-split,
.rb-canvas:not(.rb-stream-vapor) .rb-venting,
.rb-canvas:not(.rb-stream-vapor) .rb-token-atmo { display: none; }
.rb-stream-vapor .rb-ports { display: none; }
.rb-stream-oil .rb-port:not(.rb-port-oil),
.rb-stream-gas .rb-port:not(.rb-port-gas),
.rb-stream-water .rb-port:not(.rb-port-water) { display: none; }

/* Re-route grab handles at each wire's destination end. */
.rb-endpoint {
    stroke: var(--surface); stroke-width: 1.6;
    pointer-events: all; cursor: grab;
}
.rb-endpoint:hover, .rb-endpoint:focus-visible { r: 6.5; }
.rb-endpoint-vapor { fill: #e67e22; }
.rb-endpoint-oil   { fill: #27ae60; }
.rb-endpoint-gas   { fill: #c0392b; }
.rb-endpoint-water { fill: #3498db; }
.rb-endpoint-mixed { fill: #f1c40f; }

@media print {
    /* the table is the audit surface — force it regardless of mode */
    .routing-mode-board .routing-table-wrap { display: block; }
    .rb-viewport, .rb-toolbar, .rb-hint,
    .routing-mode-toggle { display: none !important; }
}

/* Facility sub-tabs (2026-08-13): Facility Info | Gas Analysis | Unit ID
   Prefixes inside the one "Facility" tab, with the actions menu riding in
   the same row. Reuses .grid-type-tabs/.grid-tab so there is no third tab
   style; only the row layout and the menu button's descriptor are new. */
.facility-subtab-row { display: flex; align-items: flex-start; gap: 12px;
    flex-wrap: wrap; margin: 0 0 12px; }
.facility-subtabs { margin: 0; }
.facility-actions-wrap { margin-left: auto; text-align: center; }
/* Same box as a sub-tab so it reads as part of the row, but bordered so
   it is clearly an action rather than a fourth tab. */
.facility-actions-btn { border: 1px solid var(--border-strong) !important;
    background: var(--surface-alt); }
.facility-actions-btn:hover { background: var(--row-hover); }
.facility-actions-hint { margin: 3px 0 0; font-size: var(--fs-caption);
    color: var(--text-muted); text-align: center; }
/* Inline legal-description editor: the readout becomes these boxes. */
.legal-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 6px; margin-bottom: 6px; }
@media (max-width: 640px) { .legal-grid { grid-template-columns: repeat(2, 1fr); } }

/* ── Calcs worksheet: factor table + shared governing equation (#77-F) ──
   Replaced sixteen per-constituent equation editors that all held the same
   equation with a different factor substituted. The factors vary, so they
   get a table; the equation is stated once with a worked example per unit
   basis. */
.wb-factors td:nth-child(2) { min-width: 92px; }
.wb-factors input { width: 100%; }
.wb-factors select { width: 100%; font-size: .72rem; padding: 1px 2px;
    background-color: var(--surface); color: var(--text);
    border: 1px solid transparent; border-radius: 4px; }
.wb-factors select:hover { border-color: var(--border); }
.wb-factors td:nth-child(4) { color: var(--text-2); font-size: .72rem; }
/* A factor the user typed: it is no longer the published number, and that
   difference is the whole reason the source column exists. */
.wb-factors input.fx-edited { color: var(--accent); font-weight: 700; }

.eq-shared {
    background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: var(--r-sm); padding: 8px 10px; margin: 4px 0 8px;
}
.eq-line { font-size: .78rem; line-height: 1.6; }
.eq-worked { margin: 0 0 10px 10px; padding-left: 10px;
    border-left: 2px solid var(--border); }
.eq-worked-h { font-size: .7rem; color: var(--text-2); margin-bottom: 2px; }
.eq-advanced { margin-top: 10px; }
.eq-advanced > summary {
    cursor: pointer; font-size: .7rem; color: var(--text-muted);
    text-transform: uppercase; letter-spacing: .5px; font-weight: 700;
    padding: 4px 0;
}
.eq-advanced > summary:hover { color: var(--accent); }

/* Incomplete calculation (#78-A → input readiness 2026-08-17): the amber
   .wb-incomplete banner became the calm .empty-state + readiness
   checklist (Kyle: no bars, no toasts). Only the stale-record note keeps
   its own class. */
.wb-incomplete-stale {
    margin: 6px auto 14px; font-size: .74rem; color: var(--text-2);
    max-width: 52ch; text-align: center; font-style: italic;
}

/* Readiness checklist (requirements.py): ✓ entered / ○ missing (chip
   jumps to the field's home) / ⋯ gated with its why-not sentence. */
.readiness-list {
    display: flex; flex-direction: column; gap: 6px; margin-top: 6px;
    text-align: left; font-size: .78rem;
}
.rd-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.rd-mark { width: 1.1em; text-align: center; flex: none; }
.rd-ok { color: var(--text-2); }
.rd-ok .rd-mark { color: var(--ok); }
.rd-miss .rd-mark { color: var(--warn); }
.rd-gated { color: var(--text-muted); font-size: .74rem; }
.rd-any { color: var(--text-2); font-style: italic; }
.rd-chip { font: inherit; }          /* .cov-missing carries the look */
.rd-pill { cursor: pointer; }

/* Design board (Systems › Design system, 2026-08-18): the living style
   guide's own scaffolding ONLY — every sample on it renders through
   production classes/helpers, so a token edit re-tints the board and
   the app together. */
.ds-board { max-width: 1100px; }
.ds-board .fi-card { margin-bottom: 14px; }
.ds-swatches { display: grid; gap: 4px 18px;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.ds-group { display: contents; }
.ds-group-h { grid-column: 1 / -1; font-size: var(--fs-nano);
    font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
    color: var(--text-muted); margin: 10px 0 2px; }
.ds-swatch { display: flex; align-items: center; gap: 8px;
    font-size: var(--fs-caption); }
.ds-chip { width: 22px; height: 16px; border-radius: 4px;
    border: 1px solid var(--border); flex: none; }
.ds-val { color: var(--text-muted); margin-left: auto; }
.ds-play { display: grid; gap: 6px 18px; margin-bottom: 10px;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.ds-play-row { display: flex; align-items: center; gap: 10px;
    font-size: var(--fs-caption); }
.ds-play-row input[type="color"] { margin-left: auto; width: 44px;
    height: 24px; padding: 0; border: 1px solid var(--border);
    border-radius: 4px; background: none; cursor: pointer; }
.ds-type-row { line-height: 1.6; white-space: nowrap; overflow: hidden;
    text-overflow: ellipsis; }
.ds-type-row code { color: var(--text-muted); font-size: var(--fs-caption); }

/* Project board (Systems › Project, 2026-08-24): the management
   dashboard's own scaffolding — cards, KPI strip and tables are the
   production classes (.fi-card, .kpi, .fac-table); only layout and the
   in-app markdown reader are new. */
.pj-board { max-width: 1100px; }
.pj-board .sys-group { margin-top: 26px; }
.pj-section-hint { margin: -2px 0 10px; }
.pj-kpis { grid-template-columns: repeat(4, 1fr); }
.pj-grid { display: grid; gap: 14px;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.pj-card h3 { margin-bottom: 4px; }
.pj-card h3 code { font-size: var(--fs-small); }
.pj-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
    font-size: var(--fs-caption); margin-bottom: 6px; }
.pj-card-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.pj-table tbody tr[onclick] { cursor: pointer; }
.pj-table td.pj-num { width: 3.5em; color: var(--text-muted);
    font-variant-numeric: tabular-nums; }
.pj-two { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.pj-two h4 { margin: 0 0 6px; font-size: var(--fs-caption); letter-spacing: .08em;
    text-transform: uppercase; color: var(--text-muted); }
.pj-list { list-style: none; padding: 0; margin: 0 0 10px; font-size: var(--fs-small); }
.pj-list li { padding: 4px 0; border-bottom: 1px solid var(--border); }
.pj-list li .hint { margin-right: 8px; font-variant-numeric: tabular-nums; }
/* Atlas figures: inline SVG so currentColor / the teal vars follow the theme */
.pj-atlas { --teal: var(--accent); --teal-soft: var(--accent-tint); color: var(--text); }
.pj-fig { margin-bottom: 14px; overflow-x: auto; }
.pj-fig figcaption { font-size: var(--fs-caption); color: var(--text-muted);
    margin-bottom: 8px; }
.pj-fig svg { display: block; width: 100%; max-width: 900px; height: auto; margin: 0 auto; }
/* The reader: the house dialog, widened, with the markdown-lite output */
.dlg.pj-wide { width: min(940px, calc(100vw - 40px)); }
.pj-reader { max-height: 70vh; overflow: auto; text-align: left;
    font-size: var(--fs-data); line-height: 1.55; padding-right: 6px; }
.pj-reader h2, .pj-reader h3, .pj-reader h4, .pj-reader h5 { margin: 18px 0 6px; }
.pj-reader h2 { font-size: var(--fs-heading); }
.pj-reader h3 { font-size: var(--fs-title); }
.pj-reader h4, .pj-reader h5 { font-size: var(--fs-body); }
.pj-reader p { margin: 6px 0; }
.pj-reader ul, .pj-reader ol { margin: 6px 0 6px 22px; }
.pj-reader pre { background: var(--surface-alt); border: 1px solid var(--border);
    border-radius: 6px; padding: 10px 12px; overflow-x: auto;
    font-size: var(--fs-caption); line-height: 1.45; }
.pj-reader code { font-size: 0.92em; }
.pj-reader table { margin: 8px 0; font-size: var(--fs-small); }
.pj-reader table td, .pj-reader table th { padding: 6px 8px; vertical-align: top; }
.pj-reader hr { border: 0; border-top: 1px solid var(--border); margin: 16px 0; }

/* Jump-and-focus pulse: draws the eye to the field a readiness chip
   landed on (same restart idiom as the permit split highlight). */
@keyframes field-pulse {
    0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--warn) 60%, transparent); }
    100% { box-shadow: 0 0 0 9px transparent; }
}
.field-pulse { animation: field-pulse 900ms ease-out 2; }
@media (prefers-reduced-motion: reduce) {
    .field-pulse { animation: none; outline: 2px solid var(--warn); }
}

/* Manufacturer emission factors — the one collapsible home, open under any
   methodology (#32). The summary reads at wb-fx-head weight, NOT the tiny
   eq-advanced treatment (Kyle: "make the title more visible") — this is
   primary data entry, not an escape hatch. Dimmed when the selected
   methodology doesn't read manufacturer data; still editable ("enter at
   any time" stands). */
details.wb-mfg { margin: 4px 0 12px; }
details.wb-mfg > summary {
    cursor: pointer; font-size: .78rem; color: var(--text);
    text-transform: uppercase; letter-spacing: .5px; font-weight: 700;
    padding: 6px 0; border-bottom: 1px solid var(--border);
}
details.wb-mfg > summary:hover { color: var(--accent); }
.wb-custom-offer button { margin-left: 4px; }
/* A stored vendor factor the selected methodology ignores (#32 round 5):
   the row shows the published value in use; the entry survives here. */
.fx-stored-note { color: var(--text-muted); font-style: italic; }
.wb-mfg-n {
    font-size: var(--fs-caption); font-weight: 700; text-transform: none;
    letter-spacing: 0; color: var(--accent); background: var(--accent-tint);
    border-radius: 8px; padding: 1px 7px; margin-left: 6px;
}
.wb-mfg-table { margin-top: 6px; }
.wb-mfg-status { font-size: .72rem; }
.wb-mfg-status.in-use { color: var(--ok); font-weight: 600; }
.wb-mfg-status.stored { color: var(--text-muted); }

/* Method switches repaint ONCE, on the preview response (#32): until it
   lands the stale panes keep their DOM (and height) but visibly dim, so
   the pane never changes shape twice per click. */
.wb-refreshing { opacity: .55; transition: opacity .15s ease; }
#wb-worksheet { min-height: 320px; }

/* Incomplete units show the FULL page greyed from a reference run of the
   published hierarchy (#32 round 4) — the human sees what filling the
   Manufacturer factors section unlocks, instead of a dead end. Inert:
   entry happens in the live section above it. */
.wb-reference { opacity: .5; pointer-events: none; user-select: none; }
.wb-reference-tag {
    font-size: .7rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .5px; color: var(--text-muted);
    padding: 10px 0 2px; border-top: 1px dashed var(--border);
    margin-top: 14px;
}

/* Calc studio tabs (#78-B). The methodology card, worksheet and page
   preview used to render side by side and all at once — Kyle: "too much
   going on all at once". One pane at a time now, preview last. */
.calc-tabs { margin: 10px 0 12px; }
.calc-pane { min-width: 0; }
/* The preview gets the full width and a real viewport it can be zoomed and
   panned inside, because the deliverable is heading for a landscape table
   that will not fit a column. Same shape as .rb-viewport on the routing
   board: fixed frame, oversized canvas. */
#calc-pane-preview .calc-page-wrap {
    overflow: auto;
    max-height: max(460px, calc(100vh - 330px));
}
#calc-pane-preview .calc-page { min-width: 760px; }
.calc-page-head { display: flex; align-items: baseline; gap: 10px; }
.calc-zoom { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; }
.calc-zoom .rerun-link { padding: 0 6px; }
#calc-zoom-pct { font-size: var(--fs-caption); color: var(--text-2); min-width: 38px;
    text-align: center; }

/* Criteria / HAP section rows in the factor table (#78-C). Sixteen
   constituents in one flat list read as noise; the two classes answer
   different regulatory questions. */
.wb-factors tr.fx-section td {
    background: var(--surface-alt); font-weight: 700;
    font-size: .66rem; text-transform: uppercase; letter-spacing: .5px;
    color: var(--text-muted); padding: 6px 8px 4px;
}

/* Units beside a value in the calc page's Inputs table (#78-E) */
.calc-page .cp-unit { color: #667; font-size: .9em; }

/* The substitution matrix (#78-E): constituents down, equation terms
   across. Replaces a monospace dump on a permit deliverable. */
.calc-page .cp-matrix th { font-size: .72rem; line-height: 1.25; vertical-align: bottom; }
.calc-page .cp-matrix td:not(:first-child),
.calc-page .cp-matrix th:not(:first-child) { text-align: right; }
.cp-trail { margin-top: 8px; }
.cp-trail > summary { cursor: pointer; font-size: .72rem; color: #667; }

/* The factor cells LOOK like fields (Kyle: "we need a visual indicator that
   they are editable. i wasn't sure before I clicked on it"). .wb-grid input
   is deliberately chromeless for the dense worksheet grids; the factor table
   is the one place a value is meant to invite a click, so it opts back in. */
.wb-factors input[type="number"] {
    border: 1px solid var(--border); background-color: var(--surface);
    border-radius: 4px; padding: 3px 6px; text-align: right;
    cursor: text; transition: border-color .12s, box-shadow .12s;
}
.wb-factors input[type="number"]:hover {
    border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-ghost, rgba(90,140,200,.14));
}
.wb-factors input[type="number"]:focus {
    border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-ghost, rgba(90,140,200,.22));
    outline: none;
}
/* an edited value stays distinguishable from a published one */
.wb-factors input.fx-edited { border-color: var(--accent); }
.wb-factors select { border: 1px solid var(--border); cursor: pointer; }
.wb-factors select:hover { border-color: var(--accent); }
/* say so once, in the header, as well as showing it */
.wb-factors th:nth-child(2)::after,
.wb-factors th:nth-child(3)::after {
    content: " ✎"; color: var(--text-muted); font-weight: 400;
}
/* Keep the factor boxes the size of the numbers they hold, not the column */
.wb-factors td:nth-child(2) { width: 34%; }
.wb-factors td:nth-child(3) { width: 26%; }
.wb-factors input[type="number"] { max-width: 150px; margin-left: auto; display: block; }
.wb-factors select { max-width: 130px; }
/* the unit chip also appears in the worksheet's Inputs table */
.wb-grid .cp-unit { color: var(--text-muted); font-size: .9em; }
/* why a compare column is empty (#78-F) */
.wb-compare .cmp-err { font-size: .66rem; font-weight: 400; color: var(--warn);
    line-height: 1.25; margin-top: 2px; max-width: 190px; white-space: normal; }

/* ── Scaffolded values (#97) ──────────────────────────────────────────
   A value Pulsar placed from an archetype, which nobody has confirmed.
   COLOUR IS NOT THE ONLY SIGNAL: --warn resolves differently in each of
   the three themes, and print, screenshots and colour-blind users lose
   colour entirely — hence the dotted underline. The title attribute (set
   in scaffoldAttrs) names the archetype and says how to accept it. */
.val-scaffold,
input.val-scaffold,
select.val-scaffold {
    color: var(--warn);
    border-color: var(--warn-bd);
    text-decoration: underline dotted var(--warn);
    text-underline-offset: 3px;
}
.val-scaffold:focus {
    /* While you are in the box the marking would fight the focus ring,
       and leaving the box is what accepts it anyway. */
    text-decoration: none;
}

.scaffold-notice {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin: 0 0 10px;
    padding: 7px 11px;
    font-size: 0.78rem;
    color: var(--warn);
    background: var(--warn-bg);
    border: 1px solid var(--warn-bd);
    border-radius: 6px;
}
.scaffold-notice b { font-weight: 600; }

/* Grouped proposal cards (#97): a scaffold is a dozen records, so groups
   past the first two collapse — an open 60-row card is unusable in the
   chat drawer. */
.chat-diff-group { margin: 4px 0; }
.chat-diff-group-head {
    cursor: pointer;
    font-size: 0.74rem;
    font-weight: 600;
    color: var(--text-2);
    padding: 3px 0;
}
.chat-diff-n {
    opacity: 0.65;
    font-weight: 400;
    margin-left: 4px;
}
.chat-diff-gap {
    color: var(--warn);
    font-weight: 400;
    margin-left: 6px;
}
.chat-proposal-note {
    font-size: 0.72rem;
    color: var(--warn);
    background: var(--warn-bg);
    border: 1px solid var(--warn-bd);
    border-radius: 5px;
    padding: 5px 8px;
    margin: 4px 0 6px;
}

/* Production hierarchy (#87) */
.prod-breakdown { margin-top: 6px; }
.prod-row {
    display: grid;
    grid-template-columns: minmax(90px, 1fr) 90px 2fr;
    gap: 8px;
    align-items: center;
    padding: 3px 0;
    font-size: 0.76rem;
}
.prod-name { color: var(--text-2); }
.prod-input { width: 84px; }
.prod-derived { color: var(--text-muted); }
.prod-members { color: var(--text-muted); font-size: 0.72rem; }
.prod-note { margin-top: 8px; }

/* Fluid Analysis tab (#101): the read-only sheet shares .gas-sheet with the
   editor so both tables look the same; the derived line is the read-only
   value idiom. */
.gas-sheet .num { text-align: right; font-family: var(--font-data); font-variant-numeric: tabular-nums; }
.gas-sheet-ro tbody td { padding: 6px 14px; }
.gas-sheet-ro tbody tr:hover { cursor: default; }
.gas-sheet-derived { margin: 10px 0 4px; }
#fa-new > summary .cov-sp-title { font-weight: 400; }
