/* Vendored copy of Detailed-Proposal's design-system/components.css, synced 2026-08-13.
   Source versions at sync time: tokens.css?v=1 components.css?v=4 layer2.css?v=1 pages.css?v=2 styles-live.css?v=40
   This dashboard's permanent approach, re-synced on demand (#20). Do not edit
   here; edit upstream in Detailed-Proposal and re-run scripts/sync-design-system.sh. */

/* ============================================================
   Phase B Components — Stylesheet
   Styles for shared infra + B3 / S2 / S3 across three variants.
   ============================================================ */

/* ─── Shared infra ─────────────────────────────────────────── */

.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 8px;
  border-radius: var(--r-pill);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
  line-height: 1;
  background: var(--status-not-yet-bg);
  color: var(--status-not-yet-fg);
}
.status-badge--sm { padding: 3px 8px 3px 7px; font-size: var(--text-xs); gap: 5px; }
.status-badge__dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; opacity: 0.85; flex-shrink: 0;
}
.status-badge__label { letter-spacing: 0.01em; }
.status-badge__info {
  display: inline-grid; place-items: center;
  width: 14px; height: 14px; border-radius: 50%;
  background: rgba(46,46,46,0.12); color: inherit;
  font-family: var(--font-display); font-size: var(--text-3xs); font-weight: var(--fw-medium);
  font-style: italic; line-height: 1; cursor: help;
}
.status-badge--qualification-not-yet         { background: var(--status-not-yet-bg);          color: var(--status-not-yet-fg); }
.status-badge--qualification-tier1            { background: var(--status-tier1-bg);             color: var(--status-tier1-fg); }
.status-badge--qualification-tier2-booked     { background: var(--status-tier2-booked-bg);      color: var(--status-tier2-booked-fg); }
.status-badge--qualification-tier2-confirmed  { background: var(--status-tier2-confirmed-bg);   color: var(--status-tier2-confirmed-fg); }
.status-badge--qualification-tier2-failed     { background: var(--status-tier2-failed-bg);      color: var(--status-tier2-failed-fg); }
.status-badge--readiness-ready                { background: var(--readiness-ready-bg);          color: var(--readiness-ready-fg); }
.status-badge--readiness-awaiting             { background: var(--readiness-awaiting-bg);       color: var(--readiness-awaiting-fg); }
.status-badge--readiness-excluded             { background: var(--readiness-excluded-bg);       color: var(--readiness-excluded-fg); }
/* Operational status — separate seven-state set (capitalised labels) */
.status-badge--operational-complete      { background: var(--op-complete-bg);     color: var(--op-complete-fg); }
.status-badge--operational-in-progress   { background: var(--op-in-progress-bg);  color: var(--op-in-progress-fg); }
.status-badge--operational-issues        { background: var(--op-issues-bg);       color: var(--op-issues-fg); }
.status-badge--operational-not-started   { background: var(--op-not-started-bg);  color: var(--op-not-started-fg); }
.status-badge--operational-awaiting      { background: var(--op-awaiting-bg);     color: var(--op-awaiting-fg); }
.status-badge--operational-scheduled     { background: var(--op-scheduled-bg);    color: var(--op-scheduled-fg); }
.status-badge--operational-not-required  { background: var(--op-not-required-bg); color: var(--op-not-required-fg); }
.status-badge--dim { opacity: 0.45; }

.config-pill {
  display: inline-flex; align-items: center;
  padding: 3px 9px; border-radius: var(--r-xs);
  font-family: var(--font-ui); font-size: var(--text-xs);
  font-weight: var(--fw-semibold); letter-spacing: 0.04em;
  background: rgba(46, 46, 46, 0.06);
  color: var(--tf-offblack);
  text-transform: uppercase;
  border: 1px solid transparent;
}
/* Tariff structure pair — locked semantic colours (decisions log v5).
   Solid hue fill, dark text, soft rounded corners, no border or dot.
   Matches the established 10-yr warranty style in the codebase.
   Modelled / undecided unchanged. */
.config-pill--fixed {
  background: var(--tf-fixed);
  color: var(--tf-offblack);
  border: none;
  border-radius: var(--r-sm);
  padding: 4px 10px;
}
.config-pill--dynamic {
  background: var(--tf-dynamic);
  color: var(--tf-offblack);
  border: none;
  border-radius: var(--r-sm);
  padding: 4px 10px;
}
.config-pill--undecided,
.config-pill--modelled {
  background: rgba(46,46,46,0.04);
  color: var(--tf-muted);
  border-color: var(--tf-border);
}
.config-pill--dynamic.config-pill--dim {
  /* Same hex, but blended with white to reduce saturation without going grey.
     Matches the dimmed-logo treatment for "modelled" state. Qualified to
     --dynamic so a dimmed neutral pill (modelled/undecided) is not blue-tinted. */
  background: color-mix(in srgb, var(--tf-dynamic) 55%, var(--tf-white));
}
.config-pill--fixed.config-pill--dim {
  background: color-mix(in srgb, var(--tf-fixed) 55%, var(--tf-white));
}

/* ─── Icon mask assets ───
   Inline SVG data URIs for the masked glyphs below (status marks and caveat
   glyphs). Inline rather than external files so this canonical stylesheet is
   self-contained and carries its own icons into every consumer — the live app,
   the visual kit and the handoff pack — with no separate asset dependency. The
   glyph colour here is irrelevant: these are alpha masks and the rendered colour
   is always the element's currentColor. */
:root {
  --ic-ring:   url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><circle cx='8' cy='8' r='5.5' fill='none' stroke='%23000' stroke-width='1.6'/></svg>");
  --ic-search: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><circle cx='7' cy='7' r='3.3' fill='none' stroke='%23000' stroke-width='1.5'/><path d='M9.5 9.5 13 13' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round'/></svg>");
  --ic-cal:    url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><rect x='3' y='4.2' width='10' height='8.8' rx='1.2' fill='none' stroke='%23000' stroke-width='1.3'/><path d='M3 6.6h10M6 3.2v2.2M10 3.2v2.2' fill='none' stroke='%23000' stroke-width='1.3' stroke-linecap='round'/></svg>");
  --ic-check:  url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path d='M3 8.4 6.2 11.6 13 4.6' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --ic-cross:  url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path d='M4.5 4.5 11.5 11.5M11.5 4.5 4.5 11.5' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/></svg>");
  --ic-clock:  url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><circle cx='8' cy='8' r='5.6' fill='none' stroke='%23000' stroke-width='1.4'/><path d='M8 4.8V8.2L10.4 9.6' fill='none' stroke='%23000' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --ic-warn:   url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path d='M8 3.2 13.6 12.8H2.4Z' fill='none' stroke='%23000' stroke-width='1.4' stroke-linejoin='round'/><path d='M8 6.6V9.4' fill='none' stroke='%23000' stroke-width='1.4' stroke-linecap='round'/><circle cx='8' cy='11.3' r='0.75' fill='%23000'/></svg>");
  --ic-dyn:    url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path d='M2.5 7.5 5.5 3.5 8 7.5 10.5 3.5 13.5 7.5' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/><path d='M3 11h10' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round'/></svg>");
  --ic-rules:  url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path d='M3 6.2h10M3 9.8h10' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round'/></svg>");
  --ic-loop:   url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path d='M12.5 8a4.5 4.5 0 1 1-1.4-3.2' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/><path d='M11.4 2.6 11.4 5.3 8.7 5.3' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --ic-buy:    url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path d='M10.3 5.4a2.4 2.4 0 0 0-4.1 1.7V11.5' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/><path d='M4.8 8.6H9.6' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/><path d='M4.8 11.5H11' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'/></svg>");
  --ic-caveat-warning: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><defs><mask id='m'><path d='M8 1.6 L15 14 L1 14 Z' fill='white' stroke='white' stroke-width='1.2' stroke-linejoin='round'/><path d='M8 6 V9.6' stroke='black' stroke-width='1.6' stroke-linecap='round'/><circle cx='8' cy='11.7' r='0.95' fill='black'/></mask></defs><rect width='16' height='16' fill='black' mask='url(%23m)'/></svg>");
  --ic-caveat-error:   url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><defs><mask id='m'><circle cx='8' cy='8' r='7' fill='white'/><path d='M5.5 5.5 L10.5 10.5 M10.5 5.5 L5.5 10.5' stroke='black' stroke-width='1.6' stroke-linecap='round'/></mask></defs><rect width='16' height='16' fill='black' mask='url(%23m)'/></svg>");
}

/* ─── Colour-independent status marks ───
   Status is told apart by shape, not colour alone, so each state stays legible
   when desaturated: the site status dot, the toolbar count chips, the tariff
   config pills and the funding-route names each carry a distinct icon. The mark
   is a currentColor shape masked by an inline icon (see the assets above), so it
   inherits its surrounding colour — same delivery mechanism as .caveat-icon
   below. Status marks are scoped to the qualification badge kind; other kinds
   keep the plain dot. */
.status-badge--qualification-not-yet .status-badge__dot,
.status-badge--qualification-tier1 .status-badge__dot,
.status-badge--qualification-tier2-booked .status-badge__dot,
.status-badge--qualification-tier2-confirmed .status-badge__dot,
.status-badge--qualification-tier2-failed .status-badge__dot {
  width: 13px; height: 13px; min-width: 13px; border-radius: 0; opacity: 1;
  background: currentColor;
  -webkit-mask-size: contain; -webkit-mask-repeat: no-repeat; -webkit-mask-position: center;
  mask-size: contain; mask-repeat: no-repeat; mask-position: center;
}
.v-count__label::before,
.config-pill--dynamic::before,
.config-pill--fixed::before,
.v-route[data-row="baas"] .v-route__name::before,
.v-route[data-row="purchase"] .v-route__name::before {
  content: ''; display: inline-block; opacity: 1;
  background: currentColor;
  -webkit-mask-size: contain; -webkit-mask-repeat: no-repeat; -webkit-mask-position: center;
  mask-size: contain; mask-repeat: no-repeat; mask-position: center;
}
.v-count__label::before { width: 13px; height: 13px; margin-right: 6px; vertical-align: -2px; }
.config-pill--dynamic::before,
.config-pill--fixed::before { width: 12px; height: 12px; margin-right: 6px; vertical-align: -1px; }
.v-route[data-row="baas"] .v-route__name::before,
.v-route[data-row="purchase"] .v-route__name::before { width: 15px; height: 15px; margin-right: 9px; vertical-align: -2px; }

/* per-state mark: status dots — ring / magnifier / calendar / check / cross */
.status-badge--qualification-not-yet .status-badge__dot        { -webkit-mask-image: var(--ic-ring);   mask-image: var(--ic-ring); }
.status-badge--qualification-tier1 .status-badge__dot          { -webkit-mask-image: var(--ic-search); mask-image: var(--ic-search); }
.status-badge--qualification-tier2-booked .status-badge__dot   { -webkit-mask-image: var(--ic-cal);    mask-image: var(--ic-cal); }
.status-badge--qualification-tier2-confirmed .status-badge__dot { -webkit-mask-image: var(--ic-check); mask-image: var(--ic-check); }
.status-badge--qualification-tier2-failed .status-badge__dot   { -webkit-mask-image: var(--ic-cross);  mask-image: var(--ic-cross); }
/* per-state mark: toolbar counts — ring / clock / warning / check */
.v-count[data-state="pending"] .v-count__label::before { -webkit-mask-image: var(--ic-ring);  mask-image: var(--ic-ring); }
.v-count[data-state="ontrack"] .v-count__label::before { -webkit-mask-image: var(--ic-clock); mask-image: var(--ic-clock); }
.v-count[data-state="blocked"] .v-count__label::before { -webkit-mask-image: var(--ic-warn);  mask-image: var(--ic-warn); }
.v-count[data-state="ready"]   .v-count__label::before { -webkit-mask-image: var(--ic-check); mask-image: var(--ic-check); }
/* per-state mark: config pills — Dynamic wave-over-rule / Fixed two rules */
.config-pill--dynamic::before { -webkit-mask-image: var(--ic-dyn);   mask-image: var(--ic-dyn); }
.config-pill--fixed::before   { -webkit-mask-image: var(--ic-rules); mask-image: var(--ic-rules); }
/* per-state mark: funding-route names — BaaS loop / Purchase pound */
.v-route[data-row="baas"] .v-route__name::before     { -webkit-mask-image: var(--ic-loop); mask-image: var(--ic-loop); }
.v-route[data-row="purchase"] .v-route__name::before { -webkit-mask-image: var(--ic-buy);  mask-image: var(--ic-buy); }

.caveat-icon {
  display: inline-grid; place-items: center;
  width: 16px; height: 16px;
  margin-left: 0; cursor: help;
  background: transparent;
  flex: 0 0 auto;
}
.caveat-icon--warning { color: var(--tf-ink); }
.caveat-icon--error   { color: var(--status-tier2-failed-fg); }
.caveat-icon svg { display: block; }
/* Glyph delivery for consumers that do not supply their own inline <svg> (the live
   renderer draws it with a mask on ::before). The :not(:has(svg)) guard ensures a
   consumer that does provide an inline <svg> never also gets the mask, so the two
   delivery paths never double up. */
.caveat-icon:not(:has(svg))::before {
  content: '';
  display: block;
  width: 14px; height: 14px;
  background: currentColor;
  -webkit-mask-size: contain; -webkit-mask-repeat: no-repeat; -webkit-mask-position: center;
  mask-size: contain; mask-repeat: no-repeat; mask-position: center;
}
.caveat-icon--warning:not(:has(svg))::before {
  -webkit-mask-image: var(--ic-caveat-warning);
  mask-image: var(--ic-caveat-warning);
}
.caveat-icon--error:not(:has(svg))::before {
  -webkit-mask-image: var(--ic-caveat-error);
  mask-image: var(--ic-caveat-error);
}

.info-explainer { position: relative; display: inline-flex; }
.info-explainer__trigger { display: inline-flex; }
/* Portal-positioned via JS: the popup is appended to document.body on show, so
   position: fixed is viewport-relative and the renderer sets top/left. No static
   bottom/transform — those would offset the JS-placed popup off-screen. */
.info-explainer__pop {
  position: fixed; top: 0; left: 0;
  background: var(--tf-ink); color: var(--tf-offwhite);
  font-family: var(--font-ui); font-size: var(--text-xs); font-weight: var(--fw-regular);
  padding: 8px 12px; border-radius: var(--r-sm);
  width: max-content; white-space: normal; min-width: 120px; max-width: 240px;
  line-height: 1.4; letter-spacing: 0;
  box-shadow: var(--shadow-pop);
  z-index: 1000; pointer-events: none;
  text-transform: none;
}
/* --arrow-x is set by the renderer to keep the arrow over the trigger after
   horizontal viewport clamping. */
.info-explainer__pop::after {
  content: ""; position: absolute; top: 100%; left: var(--arrow-x, 50%); transform: translateX(-50%);
  border: 5px solid transparent; border-top-color: var(--tf-ink);
}
.info-explainer__pop--below::after {
  top: auto; bottom: 100%;
  border-top-color: transparent; border-bottom-color: var(--tf-ink);
}

/* ─── KPI tile ─────────────────────────────────────────────── */
.kpi-tile {
  display: flex; flex-direction: column; gap: 10px;
  padding: 0;
}
.kpi-tile__head {
  display: flex; align-items: center; gap: 8px;
}
.kpi-tile__label {
  font-family: var(--font-ui); font-size: var(--text-xs); font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; color: var(--tf-muted);
}
.kpi-tile__badge {
  display: inline-flex; align-items: center;
  padding: 2px 6px; border-radius: var(--r-xs);
  background: rgba(46,46,46,0.06); color: var(--tf-muted);
  font-size: var(--text-3xs); font-weight: var(--fw-semibold); letter-spacing: 0.1em; text-transform: uppercase;
}
.kpi-tile__value {
  font-size: clamp(28px, 3vw, 40px);
  font-weight: var(--fw-regular);
  letter-spacing: -0.02em; line-height: 1.04;
  color: var(--tf-offblack);
}
.kpi-tile__unit {
  font-size: 0.42em; color: var(--tf-muted);
  font-weight: var(--fw-regular); margin-left: 2px;
  letter-spacing: 0;
}
.kpi-tile__sub {
  font-size: var(--text-sm); color: var(--tf-muted);
}

/* ─── Buttons ───────────────────────────────────────────────
   System (locked Phase B v2):
     .btn--primary   solid charcoal, white text       — primary action, takes user somewhere new
     .btn--secondary outlined charcoal, charcoal text — in-place / supporting action
     .btn--text      transparent + arrow + underline  — inline tertiary link
     .btn--accent    yellow fill, charcoal text       — reserved (final CTA only)
   Modifiers: --lg (taller), --block (full width)
   .btn--ghost retained as alias of --secondary for back-compat. */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 8px; min-height: 40px; padding: 8px 18px;
  font-family: var(--font-ui); font-size: var(--text-base); font-weight: var(--fw-semibold);
  border-radius: var(--r-pill); border: 1px solid transparent;
  cursor: pointer; transition: all var(--dur-quick) var(--ease-out);
  white-space: nowrap; text-decoration: none;
}
.btn--primary { background: var(--tf-offblack); color: var(--tf-offwhite); border-color: var(--tf-offblack); }
.btn--primary:hover { background: var(--tf-ink); border-color: var(--tf-ink); }
.btn--secondary,
.btn--ghost   { background: transparent; color: var(--tf-offblack); border-color: var(--tf-border-strong); }
.btn--secondary:hover,
.btn--ghost:hover { background: rgba(46,46,46,0.04); border-color: var(--tf-offblack); }
.btn--text { background: transparent; color: var(--tf-offblack); padding: 6px 0; min-height: auto; border: 0; border-radius: 0; box-shadow: inset 0 -1px 0 var(--tf-offblack); gap: 6px; }
.btn--text:hover { box-shadow: inset 0 -1px 0 var(--tf-offblack), 0 1px 0 var(--tf-offblack); }
.btn--text-lg { font-size: var(--text-lg); padding-bottom: 4px; }
.btn--lg { min-height: 48px; padding: 10px 22px; font-size: var(--text-lg); }
.btn--block { width: 100%; }
.btn--accent { background: var(--tf-yellow); color: var(--tf-offblack); border-color: var(--tf-yellow); }
.btn--accent:hover { background: var(--tf-yellow-deep); border-color: var(--tf-yellow-deep); }
.btn__arrow { transition: transform 120ms ease; font-family: var(--font-ui); }
.btn:hover .btn__arrow { transform: translateX(2px); }

/* ═════════ B3 — REFINED ═════════ */
.b3 { font-family: var(--font-ui); color: var(--tf-offblack); }
.b3--refined {
  background: var(--tf-paper);
  border: 1px solid var(--tf-border);
  border-radius: var(--r-lg);
  padding: 24px 28px;
}
.b3__header { margin-bottom: 28px; display: flex; flex-direction: column; gap: 8px; }
.b3__title {
  font-family: var(--font-display); font-size: var(--text-3xl); font-weight: var(--fw-regular);
  letter-spacing: var(--tracking-heading); margin: 4px 0 0;
}
.b3__sub { color: var(--tf-muted); font-size: var(--text-base); margin: 0; }
.b3__table {
  width: 100%; border-collapse: separate; border-spacing: 0 4px;
  table-layout: fixed;
  font-size: var(--text-base);
}
.b3__table thead th {
  text-align: left; padding: 12px 16px;
  font-size: var(--text-xs); font-weight: var(--fw-semibold);
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--tf-muted);
  border-bottom: 1px solid var(--tf-border-strong);
  white-space: nowrap;
}
.b3__th-num { text-align: right !important; }
.b3__th-num--left { text-align: left !important; }
.b3__th-savings { text-align: left !important; }
.b3__th-site { width: 30%; }
.b3__th-config { width: 13%; }
.b3__th-savings { width: 12%; }
.b3__col-payback { width: 10%; }
.b3__col-capex { width: 12%; }
.b3__th-status { width: 19%; }
.b3__th-action { width: 4%; }
.b3__sort-arrow { color: var(--tf-offblack); }
.b3__row {
  background: var(--tf-white);
  cursor: pointer; transition: background var(--dur-quick) var(--ease-out);
}
/* Hover outline split across the td edges so it tracks the row's rounded corners;
   a box-shadow on the <tr> ignores the cells' border-radius and draws a hard rectangle. */
.b3__row:hover { background: rgba(255,255,255,0.6); }
.b3__row:hover td { box-shadow: inset 0 1px 0 var(--tf-border-strong), inset 0 -1px 0 var(--tf-border-strong); }
.b3__row:hover td:first-child { box-shadow: inset 0 1px 0 var(--tf-border-strong), inset 0 -1px 0 var(--tf-border-strong), inset 1px 0 0 var(--tf-border-strong); }
.b3__row:hover td:last-child  { box-shadow: inset 0 1px 0 var(--tf-border-strong), inset 0 -1px 0 var(--tf-border-strong), inset -1px 0 0 var(--tf-border-strong); }
.b3__row td { padding: 18px 16px; vertical-align: middle; }
.b3__row td:first-child { border-top-left-radius: var(--r-md); border-bottom-left-radius: var(--r-md); }
.b3__row td:last-child  { border-top-right-radius: var(--r-md); border-bottom-right-radius: var(--r-md); }
.b3__cell-site { max-width: 320px; }
.b3__site-name { font-size: var(--text-lg); font-weight: var(--fw-semibold); margin-bottom: 4px; line-height: 1.2; }
.b3__site-meta { font-size: var(--text-sm); color: var(--tf-muted); line-height: 1.4; }
.b3__cell-num { text-align: right; }
.b3__cell-capex-left { text-align: left; padding-left: 56px !important; }
.b3__col-capex { padding-left: 56px !important; }
.b3__cell-savings-left { text-align: left; }
.b3__cell-savings { font-size: var(--text-lg); }
.b3__cell-suffix { font-size: var(--text-xs); color: var(--tf-muted); margin-left: 2px; }
.b3__cell-muted { color: var(--tf-muted); }
.b3__cell-action { color: var(--tf-grey-03); font-size: var(--text-2xl); padding-right: 8px !important; padding-left: 0 !important; }
.b3__row--excluded td { opacity: 0.5; }
.b3__row--excluded td.b3__cell-status { opacity: 1; }
.b3__cell-status {
  vertical-align: middle;
  padding-left: 32px !important;
}
.b3__th-status { padding-left: 32px !important; }
.b3__cell-status-inner { display: inline-flex; align-items: center; gap: 10px; vertical-align: middle; padding-right: 8px; }

/* ═════════ B3 — EDITORIAL ═════════ */
.b3--editorial { padding-top: 8px; }
.b3-ed__header {
  display: grid; grid-template-columns: 1fr auto;
  align-items: end; gap: 32px;
  padding-bottom: 32px;
  border-bottom: 2px solid var(--tf-offblack);
  margin-bottom: 0;
}
.b3-ed__title {
  font-family: var(--font-display); margin: 8px 0 0;
  font-size: clamp(40px, 5vw, 64px); font-weight: var(--fw-regular);
  line-height: 0.96; letter-spacing: -0.03em;
}
.b3-ed__head-aggregate { text-align: right; }
.b3-ed__aggregate-value {
  display: block; font-size: var(--text-3xl); font-weight: var(--fw-regular);
  letter-spacing: -0.02em; margin-top: 6px;
}
.b3-ed__aggregate-value span { font-size: var(--text-sm); color: var(--tf-muted); margin-left: 6px; }
.b3-ed__list { list-style: none; margin: 0; padding: 0; }
.b3-ed__row {
  display: grid;
  grid-template-columns: 56px 1fr 360px 160px 24px;
  align-items: center; gap: 32px;
  padding: 28px 0; border-bottom: 1px solid var(--tf-border);
  cursor: pointer; transition: background var(--dur-quick) var(--ease-out);
}
.b3-ed__row:hover { background: linear-gradient(90deg, color-mix(in srgb, var(--tf-yellow) 8%, transparent), transparent 70%); }
.b3-ed__row--excluded { opacity: 0.45; }
.b3-ed__index { font-size: var(--text-md); color: var(--tf-muted); letter-spacing: 0.06em; }
.b3-ed__name {
  font-family: var(--font-display); margin: 0 0 4px;
  font-size: var(--text-3xl); font-weight: var(--fw-regular); letter-spacing: var(--tracking-heading);
  line-height: 1.1;
}
.b3-ed__meta { margin: 0; font-size: var(--text-sm); color: var(--tf-muted); }
.b3-ed__metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.b3-ed__m-label {
  display: block; font-size: var(--text-xs); font-weight: var(--fw-semibold);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--tf-muted); margin-bottom: 6px;
}
.b3-ed__m-value { font-size: var(--text-xl); font-weight: var(--fw-regular); letter-spacing: -0.01em; }
.b3-ed__status-col { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.b3-ed__chevron { font-size: var(--text-2xl); color: var(--tf-offblack); }

/* ═════════ B3 — DASHBOARD ═════════ */
.b3--dash { background: var(--tf-paper); border: 1px solid var(--tf-border); border-radius: var(--r-lg); padding: 32px; }
.b3-dash__header {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: 24px; margin-bottom: 28px;
}
.b3-dash__title {
  font-family: var(--font-display); margin: 8px 0 0;
  font-size: var(--text-3xl); font-weight: var(--fw-regular); letter-spacing: var(--tracking-heading);
}
.b3-dash__totals { display: flex; gap: 32px; }
.b3-dash__total { display: flex; flex-direction: column; gap: 4px; align-items: flex-end; }
.b3-dash__total-v { font-size: var(--text-2xl); font-weight: var(--fw-regular); letter-spacing: -0.02em; }
.b3-dash__total-v small { font-size: var(--text-xs); color: var(--tf-muted); margin-left: 2px; }
.b3-dash__table { display: grid; gap: 0; }
.b3-dash__head-row, .b3-dash__row {
  display: grid;
  grid-template-columns: 1.4fr 90px 200px 130px 130px 180px;
  align-items: center; gap: 16px;
  padding: 12px 0;
}
.b3-dash__head-row {
  font-size: var(--text-xs); font-weight: var(--fw-semibold);
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--tf-muted);
  border-bottom: 1px solid var(--tf-border-strong); padding: 0 0 12px;
}
.b3-dash__num { text-align: right; font-variant-numeric: tabular-nums; }
.b3-dash__capex-col { text-align: left; font-variant-numeric: tabular-nums; }
.b3-dash__savings-col { text-align: left; font-variant-numeric: tabular-nums; }
.b3-dash__row {
  border-bottom: 1px solid var(--tf-border);
  cursor: pointer; transition: background var(--dur-quick) var(--ease-out);
  font-size: var(--text-base);
}
.b3-dash__row:hover { background: rgba(46,46,46,0.025); }
.b3-dash__row--excluded { opacity: 0.45; }
.b3-dash__site { display: flex; flex-direction: column; gap: 2px; }
.b3-dash__site-name { font-weight: var(--fw-semibold); font-size: var(--text-base); }
.b3-dash__site-meta { font-size: var(--text-xs); color: var(--tf-muted); font-family: var(--font-mono); }
.b3-dash__savings-cell { display: flex; align-items: center; gap: 12px; justify-content: flex-start; }
.b3-dash__bar-bg {
  width: 90px; height: 6px; border-radius: 3px;
  background: rgba(46,46,46,0.08); overflow: hidden;
}
.b3-dash__bar-fill { height: 100%; background: var(--tf-offblack); border-radius: 3px; }
.b3-dash__savings-v { font-size: var(--text-base); font-weight: var(--fw-semibold); }
.b3-dash__unit-suffix { font-size: var(--text-xs); color: var(--tf-muted); font-weight: var(--fw-regular); margin-left: 1px; }
.b3-dash__muted { color: var(--tf-muted); }
.b3-dash__status { display: flex; align-items: center; gap: 6px; }

/* ═════════ B3 — TWO SITES (enlarged) ═════════ */
.b3-two__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 16px; }
.b3-two__row {
  display: grid; grid-template-columns: 1fr 540px 24px;
  gap: 32px; align-items: center;
  padding: 32px;
  background: var(--tf-white); border: 1px solid var(--tf-border); border-radius: var(--r-lg);
  cursor: pointer; transition: all var(--dur-base) var(--ease-out);
}
.b3-two__row:hover { box-shadow: var(--shadow-card-hover); border-color: var(--tf-border-strong); }
.b3-two__row--excluded {
  /* Translucent excluded-row treatment with no token equivalent: --tf-white has
     no alpha variant and the border scale stops at --tf-border (0.14). */
  background: rgba(255, 255, 255, 0.6);
  border-color: rgba(46, 46, 46, 0.07);
}
.b3-two__row--excluded .b3-two__name,
.b3-two__row--excluded .b3-two__meta,
.b3-two__row--excluded .b3-two__metrics { opacity: 0.5; }
.b3-two__name {
  font-family: var(--font-display); margin: 0 0 8px;
  font-size: var(--text-3xl); font-weight: var(--fw-regular); letter-spacing: var(--tracking-heading);
}
.b3-two__meta { margin: 0 0 16px; color: var(--tf-muted); font-size: var(--text-base); }
.b3-two__sub { display: flex; gap: 8px; align-items: center; }
.b3-two__metrics { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; align-items: start; }
.b3-two__metric { display: flex; flex-direction: column; gap: 8px; }
.b3-two__m-value { font-size: var(--text-2xl); font-weight: var(--fw-regular); letter-spacing: -0.02em; }
.b3-two__m-value--lead {
  font-family: var(--font-mono);
  font-size: clamp(28px, 3vw, 36px);
  letter-spacing: -0.025em;
}
.b3-two__m-value small { font-size: var(--text-xs); color: var(--tf-muted); margin-left: 2px; }
.b3-two__chev { font-size: var(--text-3xl); color: var(--tf-grey-03); }

/* ═════════ B3 — SINGLE COLLAPSED ═════════ */
.b3-single__header { margin-bottom: 20px; }
.b3-single__title {
  font-family: var(--font-display); margin: 6px 0 6px;
  font-size: clamp(36px, 5vw, 56px); font-weight: var(--fw-regular); letter-spacing: -0.025em;
  line-height: 1;
}
.b3-single__meta { margin: 0; color: var(--tf-muted); font-size: var(--text-base); }
.b3-single__chips { display: inline-flex; align-items: center; gap: 10px; margin-top: 14px; }
.b3-single__kpis {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 0;
  padding: 22px 0; margin-bottom: 16px;
  border-top: 1px solid var(--tf-border);
  border-bottom: 1px solid var(--tf-border);
}
.b3-single__kpis .kpi-tile {
  gap: 6px;
  padding: 0 24px 0 0;
  border-right: 1px solid var(--tf-border);
}
.b3-single__kpis .kpi-tile + .kpi-tile { padding-left: 24px; }
.b3-single__kpis .kpi-tile:last-child { border-right: none; padding-right: 0; }
.b3-single__kpis .kpi-tile:first-child { padding-left: 0; }
.b3-single__hint { color: var(--tf-muted); font-size: var(--text-sm); margin: 16px 0 0; }

/* ═══════════════════════════════════════════════════════════════
   S2 + S3 shared anatomy (locked Phase B v2)
   Both cards use a light surface so they pair without one dominating
   the other. Same internal grid: head → rule → body → foot.
   ═══════════════════════════════════════════════════════════════ */

.s2, .s3 {
  display: flex; flex-direction: column;
  background: var(--tf-white); border: 1px solid var(--tf-border); border-radius: var(--r-lg);
  padding: 28px 28px 24px;
  min-height: 480px;
}
.s2 > .card__head, .s3 > .card__head { margin-bottom: 16px; }
.card__title {
  font-family: var(--font-display); margin: 8px 0 6px;
  font-size: var(--text-3xl); font-weight: var(--fw-regular);
  letter-spacing: var(--tracking-heading); line-height: 1.15;
}
.card__title--sm {
  font-size: var(--text-2xl); margin: 8px 0 6px;
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 10px;
}
.card__meta {
  margin: 0; font-size: var(--text-base); color: var(--tf-muted);
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px; line-height: 1.5;
}
.card__sep { color: var(--tf-grey-03); }
.card__rule { height: 1px; background: var(--tf-border); margin: 16px 0; }
.card__foot {
  margin-top: auto; padding-top: 20px;
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
}
/* Shared card spec list (S2 + S3 paired rows) */
.card__specs { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.card__specs li {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  font-size: var(--text-base);
  padding-bottom: 10px; border-bottom: 1px solid var(--tf-border);
}
.card__specs li:last-child { border-bottom: none; padding-bottom: 0; }
.card__specs > li > span:first-child { color: var(--tf-muted); }
.card__specs b { font-weight: var(--fw-medium); color: var(--tf-offblack); text-align: right; }

/* ─── S2 — Refined ─── */
.s2__specs { margin: 0; padding: 0; display: grid; gap: 14px; }
.s2__specs > div { display: grid; grid-template-columns: 180px 1fr; gap: 12px; align-items: baseline; }
.s2__specs dt { font-size: var(--text-base); color: var(--tf-muted); margin: 0; }
.s2__specs dd { margin: 0; font-size: var(--text-base); font-weight: var(--fw-medium); }

/* ─── S2 — Editorial (light, typographic) ─── */
.s2--editorial { padding: 32px 32px 24px; }
.s2-ed__name {
  font-family: var(--font-display); margin: 8px 0 0;
  font-size: var(--text-4xl); font-weight: var(--fw-regular);
  letter-spacing: var(--tracking-heading); line-height: 1.05;
}
.s2-ed__hero {
  display: flex; align-items: baseline; gap: 10px;
  margin: 22px 0 6px;
}
.s2-ed__hero-value {
  font-size: clamp(64px, 8vw, 96px); font-weight: var(--fw-regular);
  letter-spacing: -0.04em; line-height: 0.92; color: var(--tf-offblack);
}
.s2-ed__hero-unit {
  font-size: var(--text-2xl); color: var(--tf-muted);
  font-family: var(--font-display); letter-spacing: var(--tracking-heading);
}
.s2-ed__sub { margin: 0; color: var(--tf-muted); font-size: var(--text-base); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.s2-ed__specs { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.s2-ed__specs li {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  font-size: var(--text-base);
  padding-bottom: 10px; border-bottom: 1px solid var(--tf-border);
}
.s2-ed__specs li:last-child { border-bottom: none; padding-bottom: 0; }
.s2-ed__specs > li > span:first-child { color: var(--tf-muted); }
.s2-ed__specs b { font-weight: var(--fw-medium); color: var(--tf-offblack); text-align: right; }

/* ─── S2 — Editorial v1: Capacity hero (mirrors S3 editorial) ─── */
.s2-ed.s2-ed--v1 .s2-ed__hero,
.s2-ed.s2-ed--v2 .s2-ed__hero {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin: 22px 0 6px;
}
.s2-ed.s2-ed--v1 .s2-ed__hero-value,
.s2-ed.s2-ed--v2 .s2-ed__hero-value {
  font-family: var(--font-display);
  font-size: clamp(44px, 6vw, 72px); font-weight: var(--fw-regular);
  letter-spacing: -0.04em; line-height: 0.92; color: var(--tf-offblack);
}
.s2-ed.s2-ed--v1 .s2-ed__hero-unit,
.s2-ed.s2-ed--v2 .s2-ed__hero-unit {
  font-size: var(--text-2xl); color: var(--tf-muted);
  font-family: var(--font-display); letter-spacing: var(--tracking-heading);
}

/* ─── v3: Pair display — capacity + power, equal weight ─── */
/* Flex column so spec list can push down to bottom-align with S3's last row */
.s2-ed--v3 { display: flex; flex-direction: column; }
.s2-ed--v3 .s2-ed__specs { margin-top: auto; }
.s2-ed--v3 .card__specs { margin-top: auto; }
.s2-ed--v3 .s2-ed__pair {
  display: grid; grid-template-columns: 1fr 1fr; gap: 24px;
  margin: 22px 0 6px;
  border-bottom: 1px solid var(--tf-border); padding-bottom: 22px;
}
.s2-ed--v3 .s2-ed__pair-cell { display: flex; flex-direction: column; gap: 4px; }
.s2-ed--v3 .s2-ed__pair-label {
  font-family: var(--font-ui); font-size: var(--text-xs); font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; color: var(--tf-muted);
}
.s2-ed--v3 .s2-ed__pair-value {
  display: flex; align-items: baseline; gap: 8px;
  font-family: var(--font-display);
  font-size: clamp(36px, 4.5vw, 56px); font-weight: var(--fw-regular);
  letter-spacing: -0.04em; line-height: 0.95; color: var(--tf-offblack);
}
.s2-ed--v3 .s2-ed__pair-unit {
  font-size: var(--text-xl); color: var(--tf-muted);
  font-family: var(--font-display); letter-spacing: var(--tracking-heading);
}

/* ─── v4: Footprint hero — system dimensions are the lead ─── */
.s2-ed--v4 .s2-ed__footprint {
  margin: 22px 0 6px;
  font-family: var(--font-display);
  font-size: clamp(28px, 3.5vw, 40px); font-weight: var(--fw-regular);
  letter-spacing: -0.02em; line-height: 1.1; color: var(--tf-offblack);
}
.s2-ed--v4 .s2-ed__footprint-x { color: var(--tf-muted); padding: 0 4px; font-weight: var(--fw-regular); }

/* Shared: brand mark sits in card-head top-right */
.s2-ed__brand-mark {
  font-family: var(--font-ui); font-size: var(--text-xs);
  font-weight: var(--fw-semibold); letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--tf-offblack);
  background: var(--tf-fixed);
  border: none;
  padding: 6px 10px; border-radius: var(--r-xs);
  white-space: nowrap;
}

/* ─── End S2 editorial v1–v4 ─── */

/* ─── S2 — Dashboard (compact, KPI cells) ─── */
.s2--dash { padding: 24px 24px 20px; min-height: 420px; }
.s2-dash__grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
  margin: 0;
}
.s2-dash__cell {
  padding: 12px 14px; background: var(--tf-paper); border-radius: var(--r-sm);
  display: flex; flex-direction: column; gap: 4px;
}
.s2-dash__cell--wide { grid-column: span 2; }
.s2-dash__cell > span {
  font-size: var(--text-2xs); font-weight: var(--fw-semibold);
  color: var(--tf-muted); letter-spacing: 0.08em; text-transform: uppercase;
}
.s2-dash__cell > b { font-size: var(--text-lg); font-weight: var(--fw-medium); }
.s2-dash__cell > b small { font-size: var(--text-sm); color: var(--tf-muted); margin-left: 2px; font-weight: var(--fw-regular); }

/* ═══════════════════════════════════════════════════════════════
   S3 — Tariff card (cost is the lede)
   ═══════════════════════════════════════════════════════════════ */

/* ─── S3 — Refined ─── */
.s3__headline-value {
  font-family: var(--font-display); margin: 8px 0 6px;
  font-size: clamp(36px, 4vw, 52px); font-weight: var(--fw-regular);
  letter-spacing: -0.02em; line-height: 1;
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
}
.s3__supplier-line { font-weight: var(--fw-medium); color: var(--tf-offblack); }
.s3__estimated-badge {
  display: inline-flex; align-items: center;
  background: var(--status-not-yet-bg);
  color: var(--status-not-yet-fg);
  padding: 4px 10px; border-radius: var(--r-xs);
  font-size: var(--text-xs); font-weight: var(--fw-medium);
  letter-spacing: 0.04em; text-transform: uppercase;
  font-family: var(--font-ui);
  align-self: center;
}

/* Supplier mark — inline logo (or wordmark fallback) used in S3 meta line.
   Sits with subtle "via" relationship to the supplier wordmark. */
.supplier-mark {
  display: inline-flex; align-items: center; gap: 8px;
  font-weight: var(--fw-medium); color: var(--tf-offblack);
}
.supplier-mark__logo {
  display: inline-flex; align-items: center; justify-content: center;
  height: 22px; width: auto;
}
.supplier-mark__logo svg, .supplier-mark__logo img { height: 100%; width: auto; display: block; }
.supplier-mark__name { font-weight: var(--fw-medium); }

/* Top-right corner logo — uses negative space in the card head */
.card__head-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }
.card__head-titles { flex: 1 1 auto; min-width: 0; }
.card__head-logo {
  flex: 0 0 auto;
  display: inline-flex; align-items: center;
  height: 28px; max-width: 140px;
  margin-top: 2px;
}
.card__head-logo svg, .card__head-logo img { height: 100%; width: auto; display: block; }
.card__head-logo--dim { opacity: 0.6; }

/* Larger logo treatment for editorial S3 */
.s3-ed .card__head-logo { height: 34px; max-width: 180px; }
.s3__specs { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.s3__specs li {
  display: grid; grid-template-columns: 140px 1fr; gap: 12px;
  align-items: center; font-size: var(--text-base);
}
.s3__specs > li > span:first-child { color: var(--tf-muted); }
.s3__specs b { font-weight: var(--fw-medium); display: inline-flex; align-items: center; gap: 8px; }
.s3__desc { margin: 16px 0 0; color: var(--tf-muted); font-size: var(--text-base); line-height: 1.55; }

/* ─── S3 — Editorial (mirrors S2 editorial; cost is hero) ─── */
.s3--editorial { padding: 32px 32px 24px; }
.s3-ed { display: flex; flex-direction: column; }
.s3-ed .card__specs { margin-top: auto; }
.s3-ed__intermediary {
  margin: 4px 0 0;
  font-size: var(--text-sm); color: var(--tf-muted); font-style: italic;
}
.s3-ed__hero {
  font-family: var(--font-display);
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin: 22px 0 6px;
  font-size: clamp(44px, 6vw, 72px); font-weight: var(--fw-regular);
  letter-spacing: -0.04em; line-height: 1;
  min-height: 1em;
}
.s3-ed__estimated-slot {
  display: flex;
  flex-basis: 100%; margin-top: 14px; align-self: flex-start;
  /* Reserves exact height of the chip so confirmed (empty slot) and modelled
     (chip-occupied slot) cards align row-for-row. */
  min-height: 26px; align-items: center;
}
.s3-ed__hero-value { letter-spacing: -0.04em; }
.s3-ed__hero-unit {
  font-size: var(--text-2xl); color: var(--tf-muted);
  letter-spacing: var(--tracking-heading);
}
.s3-ed__supplier { margin: 0; font-size: var(--text-base); color: var(--tf-muted); font-weight: var(--fw-medium); }
.s3-ed__supplier-tbc { color: var(--tf-muted); font-weight: var(--fw-medium); }

/* ─── S3 — Dashboard (compact) ─── */
.s3--dash { padding: 24px 24px 20px; min-height: 420px; }
.s3-dash__specs li { grid-template-columns: 110px 1fr; font-size: var(--text-sm); }
.s3-dash__chips { display: flex; gap: 8px; flex-wrap: wrap; }
.s3-dash__chip {
  padding: 4px 10px; background: var(--tf-paper); border: 1px solid var(--tf-border);
  border-radius: var(--r-pill); font-size: var(--text-xs); color: var(--tf-muted);
}

/* Canvas/page layout helpers */
.page-shell {
  min-height: 100vh; background: var(--tf-offwhite);
}
.page-section { padding: 64px 0; }
.page-inner { width: min(1200px, calc(100% - 64px)); margin: 0 auto; }
.page-divider {
  height: 1px; background: var(--tf-border-strong);
  width: 100%; margin: 64px 0;
}

/* ============================================================
   Batch 3 — Cover, KPI intro and portfolio status vocabulary
   New canonical classes for the Detailed Proposal cover and KPI
   snapshot. Design anatomy only: page widths, view show/hide and
   responsive behaviour are composition and live in styles-live.css.
   The route-accent colour resolves to transparent until the accent
   colour lands; the mechanism is defined here.
   ============================================================ */

/* ─── TopbarStatus — single badge and portfolio count chips ─── */
.v-rollup { display: inline-flex; align-items: center; gap: 8px; }
/* .v-badge takes its shape from .status-badge in markup; only the
   operational-state colour is set here */
.v-badge[data-state="pending"] { background: var(--status-not-yet-bg);  color: var(--status-not-yet-fg); }
.v-badge[data-state="ontrack"] { background: var(--op-in-progress-bg);  color: var(--op-in-progress-fg); }
.v-badge[data-state="blocked"] { background: var(--op-issues-bg);       color: var(--op-issues-fg); }
.v-badge[data-state="ready"]   { background: var(--readiness-ready-bg);  color: var(--readiness-ready-fg); }

.v-counts { display: inline-flex; align-items: center; gap: 8px; }
.v-count {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 4px 10px 4px 4px; border-radius: var(--r-pill);
  background: var(--tf-white); border: 1px solid var(--tf-border);
}
.v-count__num {
  display: inline-grid; place-items: center;
  min-width: 22px; height: 22px; padding: 0 6px; border-radius: var(--r-pill);
  background: var(--tf-offblack); color: var(--tf-offwhite);
  font-family: var(--font-mono); font-size: var(--text-sm); font-variant-numeric: tabular-nums;
}
.v-count__label { font-size: var(--text-sm); font-weight: var(--fw-medium); }
.v-count[data-state="pending"] { background: var(--status-not-yet-bg); border-color: transparent; }
.v-count[data-state="pending"] .v-count__label { color: var(--status-not-yet-fg); }
.v-count[data-state="ontrack"] { background: var(--op-in-progress-bg); border-color: transparent; }
.v-count[data-state="ontrack"] .v-count__label { color: var(--op-in-progress-fg); }
.v-count[data-state="blocked"] { background: var(--op-issues-bg); border-color: transparent; }
.v-count[data-state="blocked"] .v-count__label { color: var(--op-issues-fg); }
.v-count[data-state="blocked"] .v-count__num { background: var(--op-issues-fg); }
.v-count[data-state="ready"] { background: var(--readiness-ready-bg); border-color: transparent; }
.v-count[data-state="ready"] .v-count__label { color: var(--readiness-ready-fg); }
/* a count of zero reads quieter */
.v-count[data-zero="true"] { opacity: 0.4; }

/* ─── Cover — brand row, title, partner lockup, hero, footer ─── */
.cf-cover {
  display: flex; flex-direction: column; min-height: 100dvh;
  background: radial-gradient(circle at 18% 115%, color-mix(in srgb, var(--tf-blue-02) 20%, transparent), transparent 46%), var(--tf-offblack);
  color: var(--tf-offwhite);
}
.cf-cover__inner { margin: 0 auto; flex: 1; display: flex; flex-direction: column; padding: 40px 0 44px; }
.cf-cover__main { flex: 1; display: flex; flex-direction: column; justify-content: center; padding: 40px 0; gap: 4px; }
.cf-brandrow {
  display: flex; justify-content: space-between; align-items: center; gap: 24px;
  padding-bottom: 26px; border-bottom: 2px solid color-mix(in srgb, var(--tf-offwhite) 18%, transparent);
}
.cf-cta-row { display: flex; align-items: center; gap: 18px; margin-top: 8px; }
.cf-coverfoot {
  display: flex; justify-content: space-between; align-items: baseline; flex-wrap: nowrap;
  gap: 12px 28px; margin-top: 28px; padding-top: 18px;
  border-top: 1px solid color-mix(in srgb, var(--tf-offwhite) 16%, transparent);
  color: color-mix(in srgb, var(--tf-offwhite) 62%, transparent); font-family: var(--font-ui);
}
.cf-coverfoot__note {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px;
  font-size: var(--text-xs); margin-left: auto;
}

.v-wordmark { height: 38px; width: auto; display: block; }
.v-title {
  font-family: var(--font-display); margin: 0 0 8px;
  font-size: clamp(40px, 5.2vw, 64px); line-height: 0.98; letter-spacing: -0.03em; font-weight: var(--fw-regular);
}
.v-subtitle { margin: 0; font-size: var(--text-lg); color: var(--tf-muted); }
.v-subtitle b { color: var(--tf-offblack); font-weight: var(--fw-medium); }

.v-partner { display: flex; flex-direction: row; align-items: center; gap: 12px; text-align: right; flex-shrink: 0; }
.v-partner__label {
  max-width: 7em; line-height: 1.25;
  font-size: var(--text-2xs); letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; color: var(--tf-muted);
}
.v-partner__logo { display: inline-flex; align-items: center; }
.v-partner__logo img { height: 52px; width: auto; display: block; }

.v-hero { display: grid; grid-template-columns: 1.35fr 1fr; gap: 28px; align-items: stretch; margin: 28px 0 8px; }
.v-hero__image { border-radius: var(--r-lg); min-height: 200px; position: relative; overflow: hidden; }
.v-hero__context { display: flex; flex-direction: column; justify-content: center; gap: 12px; }
/* the cover title above the lede sits at the 32px step so it stands
   out without rivalling the client name */
.v-hero__label {
  font-family: var(--font-display); font-size: var(--text-4xl); font-weight: var(--fw-regular);
  letter-spacing: var(--tracking-heading); color: var(--tf-muted);
}
.v-hero__body { margin: 0; font-size: var(--text-md); line-height: var(--leading-relaxed); }

/* ─── Gate form — Magic Link sign-in (issue #199) ───
   Inline email form inside the dark .gate-card (styles-live.css), replacing
   the old Cloudflare Access redirect button. No dedicated dark-surface
   input/status pair existed yet, so colours compose --tf-offwhite via
   color-mix at the same opacities .gate-copy/.gate-identity already use on
   this panel, plus the existing --tf-yellow / --tf-status-red-fg tokens.
   .gate-card .gate-form .button's extra specificity is deliberate: it must
   beat .gate-card .button (styles-live.css) regardless of which stylesheet
   the cascade loads last. */
.gate-form {
  width: 100%;
  margin-top: 24px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
}

.gate-form-label {
  text-align: left;
  font-size: var(--text-sm);
  color: color-mix(in srgb, var(--tf-offwhite) 62%, transparent);
}

.gate-email {
  width: 100%;
  padding: 11px 14px;
  border-radius: var(--r-sm);
  border: 1px solid color-mix(in srgb, var(--tf-offwhite) 30%, transparent);
  background: color-mix(in srgb, var(--tf-offwhite) 6%, transparent);
  color: var(--tf-offwhite);
  font-size: var(--text-md);
  font-family: inherit;
}

.gate-email::placeholder {
  color: color-mix(in srgb, var(--tf-offwhite) 40%, transparent);
}

.gate-email:focus {
  outline: none;
  border-color: var(--tf-yellow);
}

.gate-card .gate-form .button {
  margin-top: 4px;
}

.gate-message {
  margin: 4px 0 0;
  min-height: 1.4em;
  font-size: var(--text-sm);
}

.gate-message.success {
  color: var(--tf-yellow);
}

.gate-message.error {
  color: var(--tf-status-red-fg);
}

/* ─── KpiHeader — executive-summary eyebrow and aggregation line ─── */
.v-exec {
  display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap;
  gap: 6px 16px; margin: 16px auto 32px; padding-left: 20px;
}
.v-exec__lead { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; }
.v-exec__eyebrow {
  display: inline-flex; align-items: center;
  background: var(--tf-offblack); color: var(--tf-offwhite);
  padding: 4px 10px; border-radius: var(--r-sm);
  font-family: var(--font-ui); font-size: var(--text-xs); font-weight: var(--fw-semibold);
  letter-spacing: 0.04em; text-transform: uppercase;
}
/* "Funding routes" secondary sub-header — the khaki sibling of the eyebrow chip
   (khaki fill, off-black text; same anatomy otherwise). */
.v-section__tag {
  display: inline-flex; align-items: center;
  background: var(--tf-khaki); color: var(--tf-offblack);
  padding: 4px 10px; border-radius: var(--r-sm);
  font-family: var(--font-ui); font-size: var(--text-xs); font-weight: var(--fw-semibold);
  letter-spacing: 0.04em; text-transform: uppercase;
}
.v-agg {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: var(--text-sm); color: var(--tf-offblack); font-weight: var(--fw-medium);
  border-left: 1px solid var(--tf-border); padding-left: 14px;
}
.v-agg b { font-weight: var(--fw-semibold); }

/* ─── ConfigTitles — Optima Dynamic / Fixed column headings ───
   display:contents so the two chips become grid items of the KPI
   track grid and align to the savings columns */
.v-coltitles { display: contents; }
.v-coltitle { justify-self: start; align-self: end; margin-bottom: 14px; }
.v-coltitle--dynamic { grid-column: 3; }
.v-coltitle--fixed   { grid-column: 5; }

/* ─── KpiRoute — funding-route metric rows ─── */
.v-route {
  grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: start;
  padding: 44px 0; border-bottom: 1px solid var(--tf-border);
  transition: opacity var(--dur-base) var(--ease-out), filter var(--dur-base) var(--ease-out);
}
.v-route__label {
  grid-column: 1; display: flex; flex-direction: column; gap: 8px;
  border-left: 4px solid var(--route-accent, transparent); padding-left: 16px;
}
.v-route__metrics { display: contents; }
.v-route__metrics > .v-metric:nth-child(1) { grid-column: 3; }
.v-route__metrics > .v-metric:nth-child(2) { grid-column: 5; }
.v-route__metrics > .v-metric:nth-child(3) { grid-column: 7; }
.v-route__metrics > .v-metric:nth-child(4) { grid-column: 9; }
.v-route__name {
  font-family: var(--font-display); font-size: var(--text-3xl); font-weight: var(--fw-regular);
  letter-spacing: var(--tracking-heading); line-height: 1; color: var(--tf-offblack);
}
.v-route__desc {
  margin: 2px 0 0; font-size: var(--text-xs); color: var(--tf-muted);
  line-height: 1.5; max-width: 30ch; text-wrap: balance;
}
/* chosen-route tag; shown on the selected route by the KpiRoute build */
.v-route__chosen {
  display: none; width: fit-content; padding: 3px 9px; border-radius: var(--r-xs);
  background: var(--route-accent, var(--tf-yellow)); color: var(--tf-offblack);
  font-size: var(--text-2xs); font-weight: var(--fw-semibold); letter-spacing: 0.1em; text-transform: uppercase;
}

.v-metric { min-width: 0; }
.v-metric--spacer { display: none; }
.v-metric__label {
  display: flex; align-items: center; gap: 8px; min-height: 18px; margin-bottom: 10px;
  font-size: var(--text-xs); font-weight: var(--fw-medium); letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase; color: var(--tf-muted);
}
.v-metric__value {
  font-size: clamp(24px, 2.4vw, 34px); font-weight: var(--fw-regular);
  letter-spacing: -0.02em; line-height: 1.04; font-variant-numeric: tabular-nums;
}
.v-metric__value small { font-size: 0.42em; color: var(--tf-muted); margin-left: 3px; letter-spacing: 0; }
.v-metric__sub { margin-top: 6px; font-size: var(--text-sm); color: var(--tf-muted); }
.v-metric__sub b { color: var(--tf-offblack); font-weight: var(--fw-semibold); }
/* Purchase route: payback / IRR pair below the net-savings figure */
.v-metric__pairrow { display: flex; gap: 32px; }
.v-metric__pairrow .v-metric__stat .v-metric__label { margin-bottom: 10px; }
.v-metric__belowpair { margin-top: 16px; }
/* qualifier inside an uppercase metric label, e.g. "NET SAVINGS (after ROI)" */
.v-metric__qual { text-transform: none; font-weight: var(--fw-regular); }
