/* ===========================================================================
   EVSIM — theme and component foundation
   ---------------------------------------------------------------------------
   Adopted 17 ส.ค. 69 on Byrd's instruction, from the presales artefact
   "EV Bus Simulation (standalone).html" (BUS KM · จัดเที่ยววิ่งรองรับรถ EV ·
   Simulation, รุ่น 2.0). Every value below was READ OFF THE RUNNING PAGE via
   getComputedStyle / canvas metrics, not transcribed from a screenshot.

   This SUPERSEDES parts of `06_UI_DESIGN_SYSTEM.md` — see §Typography below,
   which reverses a documented and previously-verified finding. Read that note
   before changing a font or removing `font-variant-numeric`.

   What is NOT in here, deliberately:
     * the @font-face rules. They live in `fonts.css`, which is GENERATED from
       `fonts/MANIFEST.json` so the unicode ranges cannot drift from the files.
       Six self-hosted WOFF2 files, ~155 KB — `06` §7 requires self-hosting
       because the system may run with no external network and a CDN font is
       both an availability dependency and a data-leak vector.
     * component markup. The artefact styles almost everything with inline React
       style objects — there are only 9 CSS classes in the whole bundle. The
       classes below are re-authored from the observed design, not lifted.
   =========================================================================== */

:root {
  /* -- ground ------------------------------------------------------------- */
  --color-bg: #f3f2f2;
  --color-surface: #eae9e9;
  --color-panel: #ffffff;
  --color-text: #201e1d;
  --color-divider: color-mix(in srgb, #201e1d 40%, transparent);
  --color-rule: color-mix(in srgb, #201e1d 25%, transparent);

  /* -- neutrals ----------------------------------------------------------- */
  --color-neutral-100: #f8f4f4;
  --color-neutral-200: #eae7e7;
  --color-neutral-300: #d7d3d3;
  --color-neutral-400: #bab6b6;
  --color-neutral-500: #9b9797;
  --color-neutral-600: #7d7979;
  --color-neutral-700: #605d5d;
  --color-neutral-800: #444141;
  --color-neutral-900: #2d2b2b;

  /* -- accent: action only ------------------------------------------------ */
  /* #ec3013 is the artefact's action colour. It is NOT a BMTA CI colour and is
     never used to encode data — see the semantic rules below. */
  --color-accent: #ec3013;
  --color-accent-2: #e15b47;
  --color-accent-100: #fff2ef;
  --color-accent-500: #ff563c;
  --color-accent-600: #dd2b0f;
  --color-accent-700: #ae1800;

  /* -- BMTA CI: brand and data semantics ---------------------------------- */
  --bmta-blue: #102e8e;   /* masthead, sidebar, active nav, ◆ ปัจจัย         */
  --bmta-green: #00a14e;  /* ● ผลลัพธ์ — the model's own output              */
  --bmta-green-deep: #0a6b37;
  --color-warn: #c77a00;
  --color-bad: #c02b32;
  --color-limit: var(--color-neutral-500);  /* ■ ขีดจำกัด                     */

  /* -- type --------------------------------------------------------------- */
  /* Archivo carries Latin and the figures; Noto Sans Thai carries Thai. Both
     are loaded at 400/600/800 in the source artefact, so Thai headings at 800
     are a REAL weight, not a synthesised one. Weight 700 is NOT loaded — the
     artefact requests it in two places and gets faux bold. Use 600 or 800. */
  --font-body: Archivo, "Noto Sans Thai", system-ui, sans-serif;
  --font-heading: Archivo, "Noto Sans Thai", system-ui, sans-serif;
  --font-mono: ui-monospace, Menlo, monospace;
  --font-heading-weight: 800;

  /* -- space -------------------------------------------------------------- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-6: 24px;
  --space-8: 32px;

  /* -- radius: flat by design --------------------------------------------- */
  /* All three are 0. This is the single most visible departure from `06`,
     which specified 8/6/6. Do not reintroduce rounding piecemeal — a mix of
     square panels and rounded chips is what makes an interface look assembled
     rather than designed. */
  --radius-sm: 0px;
  --radius-md: 0px;
  --radius-lg: 0px;

  --shadow-sm: 0 1px 2px color-mix(in srgb, #2d2b2b 14%, transparent);
  --shadow-md: 0 3px 10px color-mix(in srgb, #2d2b2b 16%, transparent);
  --shadow-lg: 0 12px 32px color-mix(in srgb, #2d2b2b 22%, transparent);

  /* Measured off the artefact: 236px, not the 326 first transcribed. */
  --sidebar-width: 236px;
}

/* ===========================================================================
   TYPOGRAPHY — and the finding that reverses `06` §3.1
   ---------------------------------------------------------------------------
   `06` §3.1 verified that Sarabun ships NO `tnum` feature and does not need
   one, because all ten of its digits already share a 550/1000 advance. That
   research does not transfer. Measured on the running artefact:

     Archivo 400        8 DISTINCT digit widths — "1" is 52.13, "8" is 57.37
     Archivo 800        3 distinct widths
     Noto Sans Thai     uniform at 400 and at 800, like Sarabun
     Archivo `tnum`     PRESENT and effective — "1111111111" goes 521.3 -> 568.4

   So under Archivo, `font-variant-numeric: tabular-nums` is MANDATORY on any
   figure that sits in a column or updates in place. Without it every numeric
   table jitters. This is the exact opposite of the Sarabun conclusion, and the
   reason `06` §3.1 must be rewritten rather than amended.

   The source artefact gets this right: 81 of its 83 numeric elements carry
   tabular-nums. The two that do not are a route code ("356") and a year
   ("2565") — identifiers, not quantities. Copy that distinction: tnum is for
   things you compare down a column, not for labels that happen to be digits.
   =========================================================================== */

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, .u-heading {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  letter-spacing: -0.02em;
  line-height: 1.12;
  margin: 0;
}

h1 { font-size: 28px; }
h2 { font-size: 19px; }
h3 { font-size: 15px; }

/* Quantities. Never put this on an identifier. */
.u-num {
  font-variant-numeric: tabular-nums;
}

/* The eyebrow above a page title. */
.u-eyebrow {
  font-size: 10.5px;
  font-weight: 400;
  color: var(--color-neutral-600);
  letter-spacing: 0.02em;
}

.u-caption {
  font-size: 11px;
  color: var(--color-neutral-600);
}

/* ===========================================================================
   THE ◆ ● ■ SEMANTIC SYSTEM — the load-bearing idea in this template
   ---------------------------------------------------------------------------
   The whole interface is organised around three kinds of number, and the same
   three marks appear in the sidebar groups, the legend, the KPI cards AND the
   table column headers. It is what makes the model readable in one direction:

     ◆  ปัจจัย     an input WE choose            black / --bmta-blue
     ●  ผลลัพธ์    what the model computes       --bmta-green
     ■  ขีดจำกัด   a contract or resource cap    --color-limit (grey)

   Consequences worth stating, because they are easy to violate:
     * colour here ENCODES DATA. --color-accent is for actions only; never use
       it to mark a value, or red reads as "bad result" rather than "click me".
     * a KPI card's top rule takes the colour of its own class of number. A card
       with no rule is unclassified, which should not happen.
     * if a number cannot be classified into one of the three, it does not
       belong on the dashboard.
   =========================================================================== */

.mark-factor   { color: var(--color-text); }
.mark-result   { color: var(--bmta-green); }
.mark-limit    { color: var(--color-limit); }

.mark-factor::before   { content: "◆ "; }
.mark-result::before   { content: "● "; }
.mark-limit::before    { content: "■ "; }

/* ===========================================================================
   LAYOUT
   =========================================================================== */

/* `hidden` is an attribute the UA styles as `display: none` at the very lowest
   specificity, so ANY class rule that sets `display` silently defeats it —
   `.app { display: grid }` and `.login { display: flex }` both did. That is the
   whole of the "dead shell": the JS set `.hidden = true` correctly, the element
   stayed on screen, and the app grid painted over the login form beneath it.
   Both symptoms Byrd reported were this one rule, missing. */
[hidden] { display: none !important; }

.app {
  display: grid;
  grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
  min-height: 100vh;
}

/* ---------------------------------------------------------------------------
   SIDEBAR — re-measured off the running artefact, 17 ส.ค. 69.
   The first transcription had the rail at 326px and the masthead at 17px; the
   artefact is 236px and 15px. 90px of extra rail makes every glyph in it read
   large even where the px value matched, which is what Byrd saw. Values below
   are getComputedStyle output, not estimates — including the ones that look
   arbitrary (ls -0.15px, lh 23.25px, the 22px mark gutter).
   --------------------------------------------------------------------------- */

.sidebar {
  background: var(--bmta-blue);
  color: var(--color-bg);
  display: flex;
  flex-direction: column;
  padding: 0;
}

.sidebar__head { padding: 20px 18px 16px; }

.sidebar__title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 800;
  font-size: 15px;
  line-height: 23.25px;
  letter-spacing: -0.15px;
}

/* The 16px white square before the wordmark. Not decoration — it is the same
   square the ■ ขีดจำกัด mark uses, and it sets the rail's optical left edge. */
.sidebar__title::before {
  content: "";
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  background: var(--color-bg);
}

.sidebar__sub {
  font-size: 11px;
  line-height: 15.95px;
  color: rgb(243 242 242 / 0.6);
}

.sidebar__nav { padding: 14px 0 20px; }

.sidebar__group {
  font-size: 10px;
  line-height: 15.5px;
  letter-spacing: 1.2px;
  color: rgb(243 242 242 / 0.45);
  padding: 16px 18px 6px;
}

.sidebar__group:first-child { padding-top: 10px; }

.sidebar__item {
  display: flex;
  align-items: center;
  padding: 9px 18px;
  /* A transparent left border, not a margin: the active state thickens it to
     3px of BMTA green, and a border that appears on selection would shift
     every label 3px right as the reader moves down the menu. */
  border-left: 3px solid transparent;
  color: rgb(243 242 242 / 0.82);
  text-decoration: none;
  font-size: 13px;
}

/* Fixed gutter for the ◆ ● ■ mark, so labels align whether or not one is set. */
.sidebar__item::before {
  content: attr(data-mark);
  width: 22px;
  flex: 0 0 22px;
  font-size: 10px;
}

.sidebar__item:hover { color: var(--color-bg); }

.sidebar__item[aria-current="page"] {
  background: var(--color-bg);
  border-left-color: var(--bmta-green);
  color: var(--bmta-blue);
  font-weight: 800;
}

/* The provenance block that closes the sidebar: draft badge + data vintage.
   `06` §5.11 already required a provenance strip; this is where it lives. */
.sidebar__foot {
  margin-top: auto;
  padding: 14px 18px;
  font-size: 10px;
  color: rgb(243 242 242 / 0.8);
  border-top: 2px solid rgb(243 242 242 / 0.25);
}

.sidebar__foot #draftBadge { font-weight: 800; color: var(--color-bg); }

.main { min-width: 0; }

.page-head {
  padding: var(--space-4) var(--space-6) var(--space-3);
  background: var(--color-panel);
}

/* ===========================================================================
   SCENARIO BAR — the assumption set, always on screen
   ---------------------------------------------------------------------------
   This is the component that makes the model honest: the assumptions that
   produced the numbers below are never more than a glance away, and the escape
   hatch to change them sits at the right in the action colour. Keep it pinned;
   a figure without its basis visible is the thing this whole project is trying
   not to ship.
   =========================================================================== */

.scenario-bar {
  display: flex;
  align-items: stretch;
  background: var(--color-panel);
  border-top: 1px solid var(--color-rule);
  border-bottom: 1px solid var(--color-rule);
}

.scenario-bar__label {
  padding: var(--space-3) var(--space-4);
  font-size: 11px;
  color: var(--color-neutral-600);
  white-space: nowrap;
}

.scenario-chip {
  padding: var(--space-3) var(--space-4);
  border-left: 1px solid var(--color-rule);
  /* Do NOT shrink. Flex items shrink by default, so when the derivation panel
     opens and the main column narrows, the chips squash and every value wraps
     onto four lines — observed. The bar scrolls instead: an assumption that is
     hard to read is an assumption nobody checks. */
  flex: 0 0 auto;
  white-space: nowrap;
}

.scenario-chip__k {
  display: block;
  font-size: 9.5px;
  color: var(--color-neutral-600);
  text-transform: none;
}

.scenario-chip__v {
  display: block;
  font-size: 12.5px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.scenario-bar__day {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 11px;
  font-weight: 700;
  color: var(--color-neutral-600);
  white-space: nowrap;
}

.scenario-bar__day-select {
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  padding: 3px 6px;
  border: 1px solid var(--color-neutral-300);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-neutral-900);
}

.scenario-bar__day-note {
  font-size: 10px;
  font-weight: 400;
  color: var(--color-neutral-500);
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.scenario-bar__action {
  margin-left: var(--space-4);
  padding: 0 var(--space-6);
  display: flex;
  align-items: center;
  color: var(--color-accent);
  font-weight: 800;
  font-size: 12px;
  background: none;
  border: 0;
  border-radius: var(--radius-md);
  cursor: pointer;
  font-family: inherit;
}

.legend-bar {
  display: flex;
  gap: var(--space-6);
  align-items: center;
  padding: var(--space-2) var(--space-4);
  background: var(--color-panel);
  border-bottom: 1px solid var(--color-rule);
  font-size: 9.5px;
}

.legend-bar__swatch {
  display: inline-block;
  width: 22px;
  height: 3px;
  vertical-align: middle;
  margin-right: var(--space-1);
}

/* ===========================================================================
   KPI CARD
   ---------------------------------------------------------------------------
   Flat, no fill, separated by hairlines rather than boxed. The top rule is the
   semantic mark (see above). The value carries a dotted underline when it is
   drillable — which is the affordance for the derivation panel.
   =========================================================================== */

.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  background: var(--color-panel);
}

.kpi {
  padding: 16px 18px 18px;
  border-right: 1px solid var(--color-rule);
  border-top: 3px solid transparent;
  border-radius: var(--radius-md);
  min-width: 0;
}

.kpi--result { border-top-color: var(--bmta-green); }
.kpi--limit  { border-top-color: var(--color-limit); }
.kpi--factor { border-top-color: var(--color-text); }

.kpi__label {
  font-size: 11px;
  color: var(--color-neutral-700);
}

.kpi__value {
  font-size: 31.68px;
  font-weight: 800;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
  margin-top: var(--space-2);
}

.kpi__unit {
  font-size: 13px;
  font-weight: 400;
  color: var(--color-neutral-700);
  margin-left: var(--space-1);
}

.kpi__sub {
  margin-top: var(--space-2);
  font-size: 11px;
  color: var(--color-neutral-600);
}

/* Drillable value: dotted underline, and it must be a real button for keyboard
   and screen-reader users — `06` §6 requires it and a <span onclick> fails. */
.drillable {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  border-bottom: 1px dotted var(--color-neutral-500);
}

/* ===========================================================================
   DERIVATION PANEL (ที่มาของตัวเลข)
   ---------------------------------------------------------------------------
   `06` §5.2 called for this; the artefact shows what it should contain. Four
   parts, in this order, and none of them is optional:
     1. the value restated large, with its unit
     2. สูตร — the formula, in mono, as it was actually evaluated
     3. ตัวแปรที่ใช้ — each input with its value AND a source chip (X1, X4 …)
     4. แหล่งข้อมูลต้นทาง — the originating dataset and its vintage
   This is the single most important component in the product: it is what turns
   a number into a defensible number.
   =========================================================================== */

/* The derivation panel OVERLAYS the right edge; it is not a layout column.
   As a third grid track it widened the page beyond the viewport, so on a
   normal-width window the panel opened OFF-SCREEN — the click worked, the
   request returned 200, and the reader saw nothing happen. Byrd hit exactly
   that. Fixed positioning makes it visible at any width, and it costs the
   layout nothing when closed.

   It deliberately does not move the content behind it: the reader must still
   see the number they just clicked. */
.derivation {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 20;
  width: min(520px, 92vw);
  height: 100vh;
  overflow-y: auto;
  background: var(--color-panel);
  border-left: 1px solid var(--color-rule);
  box-shadow: var(--shadow-lg);
  padding: var(--space-4) var(--space-6);
}

.derivation__value {
  font-size: 40px;
  font-weight: 800;
  color: var(--bmta-green-deep);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
}

.derivation__section {
  margin-top: var(--space-6);
  font-size: 11px;
  font-weight: 800;
  color: var(--color-neutral-700);
}

.derivation__formula {
  font-family: var(--font-mono);
  font-size: 12.5px;
  background: var(--color-neutral-100);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-top: var(--space-2);
  white-space: pre;
  overflow-x: auto;
}

.derivation__var {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--color-neutral-200);
  font-size: 12px;
}

.derivation__var-value {
  margin-left: auto;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

/* The source chip — how many places this value came from. */
.source-chip {
  display: inline-block;
  padding: 1px var(--space-2);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-sm);
  background: var(--color-neutral-100);
  font-size: 10px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

/* ===========================================================================
   DATA TABLE
   ---------------------------------------------------------------------------
   The column-group rule above the header repeats the ◆ ● ■ classification, so
   a reader can see at a glance which columns they control and which the model
   produced. Numeric columns are right-aligned and tabular; identifier columns
   (route code) are left-aligned and NOT tabular.
   =========================================================================== */

.table-wrap {
  overflow-x: auto;
  background: var(--color-panel);
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
}

.table thead th {
  position: sticky;
  top: 0;
  background: var(--color-panel);
  text-align: right;
  font-size: 10.5px;
  font-weight: 800;
  color: var(--color-neutral-700);
  padding: var(--space-2) var(--space-3);
  white-space: nowrap;
  border-bottom: 1px solid var(--color-text);
}

/* the group rule: a 3 px band above the header, coloured by class */
.table .colgroup-rule { height: 3px; padding: 0; }
.table .colgroup-rule--factor { background: var(--color-text); }
.table .colgroup-rule--limit  { background: var(--color-limit); }
.table .colgroup-rule--result { background: var(--bmta-green); }

.table td {
  padding: var(--space-2) var(--space-3);
  text-align: right;
  font-variant-numeric: tabular-nums;
  border-bottom: 1px solid var(--color-neutral-200);
}

.table td.is-label,
.table th.is-label {
  text-align: left;
  font-variant-numeric: normal;   /* identifiers, not quantities */
}

.table tbody tr:hover td { background: var(--color-surface); }

/* A cell whose figure carries an explanation — a variant counted at its base,
   a line topped up from the shortfall. The same dotted underline as a
   derivable KPI value, deliberately: it means "there is more here", and a
   second visual language for one idea teaches the reader two rules where one
   would do. */
.table td.has-note {
  text-decoration: underline dotted var(--color-neutral-400);
  text-underline-offset: 3px;
  cursor: help;
}

/* ===========================================================================
   CONTROLS
   =========================================================================== */

.seg {
  display: inline-flex;
  border: 1px solid var(--color-text);
  border-radius: var(--radius-md);
}

.seg-opt {
  padding: 7px 12px;
  font-size: 13px;
  font-family: inherit;
  background: none;
  border: 0;
  border-right: 1px solid var(--color-rule);
  cursor: pointer;
  color: inherit;
}

.seg-opt:last-child { border-right: 0; }

.seg-opt[aria-pressed="true"] {
  background: var(--color-text);
  color: var(--color-bg);
  font-weight: 800;
}

.btn {
  font-family: inherit;
  font-size: 12px;
  font-weight: 800;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  cursor: pointer;
  border: 1px solid transparent;
}

.btn-primary   { background: var(--bmta-blue); color: #fff; }
.btn-secondary { background: var(--color-panel); color: var(--color-text); border-color: var(--color-text); }
.btn-ghost     { background: none; color: var(--color-accent); border: 0; }

/* ===========================================================================
   SOURCE CHIPS AND THE REGISTER — the spine of the whole design
   ---------------------------------------------------------------------------
   On the ปัจจัยนำเข้าทั้งหมด screen EVERY value carries a chip naming where it
   came from, in two namespaces:

     X1..Xn   a document or dataset behind a ◆ ปัจจัย
     C1..Cn   a contract or resource behind a ■ ขีดจำกัด

   and the chips resolve in a ทะเบียนแหล่งข้อมูล table at the foot of the page:
   รหัส · เอกสาร/ชุดข้อมูล · ลงวันที่ · ใช้กับ · สถานะ.

   The status column is the part to copy hardest. The artefact marks X9
   (สิงคโปร์ / ลอนดอน benchmarks) as `อยู่ระหว่างยืนยัน` rather than hiding it,
   which is precisely the "benchmarks do not ship uncited" ruling rendered as
   UI. An unconfirmed source is SHOWN as unconfirmed; it is never quietly
   dropped and never quietly promoted.

   Rule for EVSIM: a value with no chip does not go on the screen.
   =========================================================================== */

.chip-x, .chip-c {
  display: inline-block;
  padding: 1px var(--space-2);
  border-radius: var(--radius-sm);
  font-size: 10px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.chip-x { border: 1px solid var(--bmta-green); color: var(--bmta-green-deep); background: #fff; }
.chip-c { border: 1px solid var(--color-neutral-500); color: var(--color-neutral-800); background: #fff; }

.status {
  display: inline-block;
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  font-size: 11px;
  font-weight: 800;
}

/* Always the word, never the colour alone — `06` §5.4. */
.status--confirmed { background: #e0f3e8; color: var(--bmta-green-deep); border: 1px solid #bfe5cf; }
.status--pending   { background: #fdf3e3; color: #7a4c02;               border: 1px solid #eed9b0; }
.status--breach    { background: #fbe9ea; color: var(--color-bad);      border: 1px solid #f0c4c6; }

/* ===========================================================================
   FACTOR / CONSTRAINT CARD GRID
   ---------------------------------------------------------------------------
   Four columns under a heavy section rule. Labels are bilingual — Thai first,
   English in parentheses — e.g. "เป้าหมายและขอบเขต (Targets & scope)". Keep
   that: the audience reads Thai, the reviewers of the TOR read both.
   =========================================================================== */

.section-rule {
  border-top: 3px solid var(--color-text);
  margin-top: var(--space-8);
  padding-top: var(--space-3);
  font-weight: 800;
  font-size: 14px;
}

.section-rule--limit { border-top-color: var(--color-limit); }

.factor-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  background: var(--color-panel);
}

.factor-col {
  padding: var(--space-4);
  border-right: 1px solid var(--color-rule);
}

.factor-row {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--color-neutral-200);
  font-size: 12px;
}

.factor-row__v {
  margin-left: auto;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ===========================================================================
   OCCUPANCY BAR — used for the overnight charger queue
   ---------------------------------------------------------------------------
   A horizontal track with a filled portion and an "n / total" readout. In the
   artefact the fill turns amber at saturation (62/62) and stays blue below it.
   Saturation is a FACT about the depot, not a failure, so it is amber and not
   red — consistent with the rule that today's operation is never painted red.
   =========================================================================== */

.occupancy {
  display: grid;
  grid-template-columns: 56px 1fr 64px;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-1) 0;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.occupancy__track {
  height: 12px;
  background: var(--color-neutral-200);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.occupancy__fill { height: 100%; background: var(--bmta-blue); }
.occupancy__fill--full { background: var(--color-warn); }
.occupancy__count { text-align: right; font-weight: 800; }

/* ===========================================================================
   FINDINGS BLOCK (● ข้อค้นพบ)
   ---------------------------------------------------------------------------
   A short bulleted read-out under a chart, with the operative figures bolded
   inline. This is where the model says what it MEANS, in Thai, in sentences.
   Sits under a green rule because a finding is a ● ผลลัพธ์.
   =========================================================================== */

.findings {
  border-top: 3px solid var(--bmta-green);
  padding-top: var(--space-3);
  margin-top: var(--space-4);
}

.findings__title { font-weight: 800; font-size: 12px; }
.findings ul { margin: var(--space-2) 0 0; padding-left: 1.1em; }
.findings li { font-size: 12.5px; line-height: 1.9; }
.findings b { font-weight: 800; }

/* Two-column split used by the depot screen: table left, chart right. */
.split-2 {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-6);
  padding: var(--space-6);
}

@media (max-width: 1100px) {
  .split-2 { grid-template-columns: 1fr; }
}

/* ===========================================================================
   ACCESSIBILITY / MOTION
   =========================================================================== */

:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--bmta-blue);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}
