/* AutoSteward — design identity
 * =============================================================================
 * The brief was "I can still tell it was made by Claude." That is a fair read, and
 * it is diagnosable rather than vague. Measured on the running dashboard, every
 * container was the same object: border-radius 16, the same 1px border, the same
 * `0 12px 34px rgba(16,43,78,.08)` shadow. A four-figure KPI tile and a ten-row
 * warnings table were rendered identically, so nothing on the page told you what
 * mattered. Add the accent rail down the left of each card, the round tinted icon
 * chip, the uppercase letterspaced eyebrow over every title, and the fully-rounded
 * outlined pill around all sixteen nav rows, and you have the current house style
 * of machine-generated UI almost item for item.
 *
 * None of that is a colour problem, which is why the ten design presets could not
 * fix it. It is a problem of everything having the same weight.
 *
 * THE IDEA — the app is an instrument, not a brochure.
 * The mark is a steering wheel: a control surface. Flat, geometric, high contrast,
 * no gradients, no glow. A DMS is where a family lot keeps its money, its
 * contracts and its DMV paperwork; it should feel like a well-made instrument
 * panel — precise, dense where density helps, and quiet everywhere else.
 *
 * FOUR RULES, and they are the whole system:
 *
 *   1. ELEVATION MEANS FLOATING. A shadow is a claim that something sits above the
 *      page. Panels do not; menus, modals, popovers and toasts do. Panels get a
 *      hairline and nothing else. This one rule removes most of the generic look.
 *
 *   2. THE SPOKE. A 3px accent bar, lifted straight off the mark, marks the one
 *      thing that is current — the active nav row, the panel you are reading. One
 *      motif, repeated, carrying meaning. It is the only ornament in the system.
 *
 *   3. FIGURES ARE THE CONTENT. Money and counts get tabular numerals, tighter
 *      tracking and real size. Currency signs and units step back. A dealer reads
 *      this app for numbers; nothing should out-shout them.
 *
 *   4. STATE HAS A SHAPE. Severity, status and readiness read as chips, not as bold
 *      body text, so the page can be scanned rather than read.
 *
 * Colour is untouched. All ten presets and both appearances still own every hue
 * here — this layer only ever reaches for --accent, --ink, --surface and --line.
 * Geometry that contract tests pin (gap:10px, padding:18px, min-height:32px) is
 * likewise untouched; loosen those and test_v02314 and friends will say so.
 */

/* ════════════════════════════════════════════════════════════════════════════
   1 · ELEVATION — a shadow means the thing floats
   ════════════════════════════════════════════════════════════════════════════ */

:root{
  /* One hairline, one real elevation. Both derived from ink so they hold on a
     dark preset without a second declaration. */
  --id-hairline: color-mix(in srgb, var(--ink) 15%, transparent);
  --id-hairline-strong: color-mix(in srgb, var(--ink) 26%, transparent);
  --id-overlay-shadow: 0 16px 40px color-mix(in srgb, var(--ink) 30%, transparent),
                       0 2px 6px  color-mix(in srgb, var(--ink) 18%, transparent);
  --id-spoke: 3px;
}

/* Panels sit ON the page, so they are drawn with an edge rather than a shadow. */
:root :is(.panel, .parity-panel, .info-card, .kpi-card, .parity-kpi-card,
          .quick-card, .parity-quick-card, .auction-card, .toolbar){
  box-shadow: none;
  border-color: var(--id-hairline);
}

/* Things that genuinely overlay keep — and earn — their elevation. */
:root :is(.modal, .modal-card, .steward-dialog, .gs-panel, .account-menu,
          .system-nav-dropdown [role="menu"], .toast, [role="dialog"]){
  box-shadow: var(--id-overlay-shadow);
}

/* ════════════════════════════════════════════════════════════════════════════
   2 · THE SPOKE — the one ornament, and it always means "this one"
   ════════════════════════════════════════════════════════════════════════════ */

/* Sidebar rows were fully-rounded outlined pills, sixteen of them stacked. Sixteen
   competing outlines is noise, and it is the single most template-looking thing on
   the screen. They become flush rows; only the current row is marked, by the spoke. */
:root .sidebar-link{
  position: relative;
  border: 0;
  border-radius:var(--r-control);
  margin: 1px 0;
  padding-left: 12px;
  background: transparent;
  font-weight: 500;
}
:root .sidebar-link:hover{
  background: color-mix(in srgb, var(--sidebar-ink, #fff) 9%, transparent);
}
:root .sidebar-link.active{
  background: color-mix(in srgb, var(--accent, #1768b2) 24%, transparent);
  color: var(--sidebar-ink, #fff);
  font-weight: 600;
  box-shadow: none;
  border: 0;
}
/* The spoke itself. Sits in the row's own padding, so it never shifts the label. */
:root .sidebar-link.active::before{
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: var(--id-spoke);
  height: 18px;
  margin-top: -9px;
  border-radius:0 var(--r-control) var(--r-control) 0;
  background: var(--accent-glow, var(--accent, #1768b2));
}
:root .sidebar-link-icon{
  width: 18px; height: 18px; flex: 0 0 18px;
  color: color-mix(in srgb, var(--sidebar-ink, #fff) 62%, transparent);
}
:root .sidebar-link.active .sidebar-link-icon{ color: var(--sidebar-ink, #fff); }
:root .sidebar-link-icon .dms-ico{ width: 18px; height: 18px; display: block; }
/* The per-design raster duplicates exist for the "Original" preset only; in the
   sidebar they would double every icon. */
:root .sidebar-link-icon .dms-ico-raster{ display: none; }

/* Group labels step back so the rows themselves carry the rhythm. */
:root .sidebar-nav-group h2{
  color: color-mix(in srgb, var(--sidebar-ink, #fff) 46%, transparent);
  font-weight: 600;
  letter-spacing: .11em;
}

/* Panel titles take the same mark, which is what ties the chrome to the content. */
:root :is(.panel-heading, .desktop-panel-heading) h2{
  position: relative;
  padding-left: 11px;
}
:root :is(.panel-heading, .desktop-panel-heading) h2::before{
  content: "";
  position: absolute;
  left: 0; top: .18em; bottom: .18em;
  width: var(--id-spoke);
  border-radius:var(--r-control);
  background: var(--accent, #1768b2);
}

/* ════════════════════════════════════════════════════════════════════════════
   3 · FIGURES — the reason anyone opens this app
   ════════════════════════════════════════════════════════════════════════════ */

/* Digits line up in columns everywhere in a DMS: prices, costs, stock numbers,
   odometer, dates. Proportional figures make those columns ragged. */
:root :is(.kpi-copy b, .data-table td, .data-table th, .parity-table td,
          .detail-list dd, .money, .figure, .stat-value, .mi-figure,
          input[type="number"], .auction-cost-table td){
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* The KPI row was four floating cards, each with an accent rail, a round tinted
   icon chip, and its copy centred inside a 72px-offset grid — which is why the
   figures did not line up with anything. It becomes one ruled strip: hairline
   dividers, left-aligned, the number doing the talking. */
:root .kpi-grid, :root .parity-kpi-grid{
  gap: 0;
  border: 1px solid var(--id-hairline);
  border-radius: var(--radius, 10px);
  background: var(--surface);
  overflow: hidden;
}
:root :is(.kpi-card, .parity-kpi-card){
  min-height: 0;
  grid-template-columns: minmax(0, 1fr) 16px;
  align-items: center;
  gap: 0;
  padding: 15px 18px;
  border: 0;
  border-radius: 0;
  border-left: 1px solid var(--id-hairline);
  background: transparent;
}
:root :is(.kpi-card, .parity-kpi-card):first-child{ border-left: 0; }
:root :is(.kpi-card, .parity-kpi-card):hover{
  background: color-mix(in srgb, var(--ink) 4%, transparent);
  transform: none;
}
/* The rail and the icon chip both go. The card's own state is carried by the dot
   below, which costs 8px instead of 72. */
:root :is(.kpi-card, .parity-kpi-card)::before{ display: none; }
:root :is(.kpi-icon, .parity-kpi-asset){ display: none; }

:root :is(.kpi-card, .parity-kpi-card) .kpi-copy{
  align-items: flex-start;
  text-align: left;
  gap: 1px;
}
/* Label — small, muted, with the status dot in front of it. */
:root :is(.kpi-card, .parity-kpi-card) .kpi-copy strong{
  display: flex;
  align-items: center;
  gap: 7px;
  color: var(--muted);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: .01em;
}
:root :is(.kpi-card, .parity-kpi-card) .kpi-copy strong::before{
  content: "";
  width: 7px; height: 7px;
  flex: 0 0 7px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 34%, transparent);
}
:root .kpi-card.danger  .kpi-copy strong::before{ background: var(--red); }
:root .kpi-card.success .kpi-copy strong::before{ background: var(--green); }
:root .parity-kpi-card.danger  .kpi-copy strong::before{ background: var(--red); }
:root .parity-kpi-card.success .kpi-copy strong::before{ background: var(--green); }

/* The figure. Tight tracking and real size — this is the line people came for. */
:root :is(.kpi-card, .parity-kpi-card) .kpi-copy b{
  margin: 3px 0 0;
  color: var(--ink);
  font-size: var(--fs-h1);
  font-weight: 700;
  /* A single-line numeral, not prose: 1 keeps the tight optical fit the card was drawn for AND is
     a whole pixel by construction, which 1.05 was not (28px x 1.05 = 29.4px). */
  line-height: 1;
  letter-spacing: -.02em;
}
:root :is(.kpi-card, .parity-kpi-card) .kpi-copy small{
  color: var(--muted);
  font-size: var(--fs-small);
}
:root .parity-card-arrow{
  color: color-mix(in srgb, var(--ink) 38%, transparent);
  font-size: var(--fs-lead);
}

/* The third type role. A VIN is a machine code, not prose: mono disambiguates 0
   from O and 1 from I, which matters when somebody is reading one off a windscreen
   and typing it in. Stock numbers and reference codes join it, so anything you are
   expected to transcribe wears the same face and is recognisable as transcribable.
   --font-code is declared once in design-themes.css, so a preset can override it. */
:root :is(.vin, .vin-cell, .stock-hero-tag, .code, .ref-code, .backup-file){
  font-family: var(--font-code);
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
}
/* Technical identifiers intentionally keep the fixed-width code role; normal
   dealer-facing text does not use this face. */
:root :is(.vin, .vin-cell, .stock-hero-tag){
  font-size: var(--fs-small);
  color: var(--muted);
}

/* ════════════════════════════════════════════════════════════════════════════
   3b · TYPOGRAPHIC REGISTERS
   ────────────────────────────────────────────────────────────────────────────
   Picking a typeface is not an identity — every product on the internet picked
   one. The identity is in the registers: how many distinct voices the page has,
   and how far apart they sit. This app had one voice at four sizes, which is why
   it read as a default.

   Five registers, and nothing is allowed to invent a sixth:

     DISPLAY   professional UI stack          page titles, hero figures
     TITLE     professional UI stack          panel and section headings
     LABEL     professional UI stack          column heads, eyebrows, field names
     BODY      professional UI stack          prose, table cells
     CODE      fixed-width technical face     VIN, stock, hashes/reference numbers

   The distance between LABEL (wide, small, uppercase) and DISPLAY (large, tight)
   is deliberate and is most of the effect: it is the instrument-panel convention
   of an engraved label beside a big readout, which is also the honest description
   of what a DMS screen is.

   Sizes always come from the --fs-* scale, never a raw rem/px — see CLAUDE.md.
   Weights are only 400/500/600/700, because the faces are static files and any
   other value is synthesised. */

/* Heading tracking remains token-controlled so themes may adjust spacing without
   changing the shared professional UI typeface. */
:root :is(.page-heading, .dashboard-heading) h1,
:root .stat-hero, :root .mi-hero-figure{
  font-family: var(--font-head);
  font-weight: 700;
  letter-spacing: var(--head-spacing);
}

:root :is(.panel-heading, .desktop-panel-heading) h2,
:root .section-title h2, :root .info-card h2, :root .system-tab-heading h2{
  font-family: var(--font-ui);
  font-weight: 600;
  letter-spacing: -.01em;
}

/* LABEL — the engraved plate. Wide tracking is the whole character of this
   register; without it the words just look small. */
:root .eyebrow,
:root .data-table th,
:root .parity-table th,
:root .detail-list dt,
:root .sidebar-nav-group h2,
:root :is(.kpi-card, .parity-kpi-card) .kpi-copy strong{
  font-family: var(--font-ui);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .13em;
  font-size: var(--fs-micro);
}
/* The KPI label sits next to its status dot, so it keeps flex from section 3. */
:root :is(.kpi-card, .parity-kpi-card) .kpi-copy strong{
  display: flex;
  text-transform: none;      /* a metric name is a name, not a plate */
  letter-spacing: .01em;
  font-size: var(--fs-small);
}

/* DISPLAY applied to the figures themselves — the number is the headline. */
:root :is(.kpi-card, .parity-kpi-card) .kpi-copy b{
  font-family: var(--font-head);
  font-weight: 700;
  letter-spacing: -.015em;
}

:root body{ font-family: var(--font-ui); }

/* ════════════════════════════════════════════════════════════════════════════
   4 · STATE HAS A SHAPE — so the page can be scanned
   ════════════════════════════════════════════════════════════════════════════ */

/* Severity was plain bold text in the first column, which reads as emphasis but
   not as a category. As a chip it is legible at a glance and survives greyscale,
   because the three levels differ in fill as well as hue. */
:root .data-table td .sev,
:root .parity-table td .sev,
:root .severity{
  display: inline-flex;
  align-items: center;
  min-height: 20px;
  padding: 1px 9px;
  border: 1px solid transparent;
  border-radius:var(--r-stadium);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
}
:root .severity.high{
  color: color-mix(in srgb, var(--red) 58%, var(--ink));
  background: color-mix(in srgb, var(--red) 16%, var(--surface));
  border-color: color-mix(in srgb, var(--red) 42%, transparent);
}
:root .severity.medium{
  color: color-mix(in srgb, var(--amber) 58%, var(--ink));
  background: color-mix(in srgb, var(--amber) 15%, var(--surface));
  border-color: color-mix(in srgb, var(--amber) 40%, transparent);
}
:root .severity.low{
  color: color-mix(in srgb, var(--green) 58%, var(--ink));
  background: color-mix(in srgb, var(--green) 14%, var(--surface));
  border-color: color-mix(in srgb, var(--green) 36%, transparent);
}

/* ════════════════════════════════════════════════════════════════════════════
   5 · DENSITY — a lot owner wants to see rows, not padding
   ════════════════════════════════════════════════════════════════════════════ */

:root .data-table th{
  padding-top: 9px; padding-bottom: 9px;
  color: var(--muted);
  background: color-mix(in srgb, var(--ink) 4%, var(--surface));
  border-bottom: 1px solid var(--id-hairline-strong);
  font-weight: 600;
  letter-spacing: .06em;
}
:root .data-table td{
  padding-top: 9px; padding-bottom: 9px;
  border-bottom: 1px solid var(--id-hairline);
  vertical-align: middle;
}
:root .data-table tbody tr:last-child td{ border-bottom: 0; }
:root .data-table tbody tr:hover{
  background: color-mix(in srgb, var(--ink) 4%, transparent);
}
/* Selection is the spoke again rather than a fourth kind of highlight. */
:root .data-table tr.selected{
  background: color-mix(in srgb, var(--accent) 11%, transparent);
  box-shadow: inset var(--id-spoke) 0 0 var(--accent);
}

/* The eyebrow over every page title said "Daily command center" — a label that
   restates the heading in a louder voice. Keep the element (routes set it) but
   let it behave like the annotation it is. */
:root .eyebrow{
  color: var(--muted) !important;
  font-weight: 600;
  letter-spacing: .1em;
}

/* Page titles: tighter, so the figure below them stays the loudest thing. */
:root :is(.page-heading, .dashboard-heading) h1{
  letter-spacing: -.025em;
}

/* ════════════════════════════════════════════════════════════════════════════
   6 · QUIET SURFACES
   ════════════════════════════════════════════════════════════════════════════ */

/* Quick-action tiles carried a 145deg white gradient, which is invisible on a
   light preset and wrong on a dark one. */
:root :is(.quick-card, .parity-quick-card){
  background: color-mix(in srgb, var(--ink) 3%, var(--surface));
  background-image: none;
  border: 1px solid var(--id-hairline);
  box-shadow: none;
}
:root :is(.quick-card, .parity-quick-card):hover{
  background: color-mix(in srgb, var(--accent) 9%, var(--surface));
  border-color: color-mix(in srgb, var(--accent) 40%, var(--id-hairline));
  transform: none;
}

/* The app's own frame should recede: a flat canvas, not a tinted spotlight. */
:root body{
  background-image: none;
}

/* The mark needs no plate: its tile is the complement of the theme accent, so hue
   already separates it from the rail (see logoColors() in design-logos.js). A white
   knockout field here would sit between the two and mute exactly the contrast that
   makes it work. */

/* ════════════════════════════════════════════════════════════════════════════
   7 · POLARITY REPAIRS — light slabs stranded on dark designs
   ────────────────────────────────────────────────────────────────────────────
   The same defect controls.css was built to kill, in the surfaces around them:
   painted for light, corrected only under html[data-theme="dark"], and therefore
   never corrected at all on `midnight`, which is dark in BOTH appearances.

   Measured on midnight with a page luminance of 0.006, six light islands were
   floating on the near-black page. The worst was the background scrim, at
   1.1:1 against the page title — the heading was simply not there.

   Everything below derives from --canvas / --surface / --ink, so it is right for
   any design without knowing which appearance it is in. */

/* The scrim. --application-overlay-color already existed as a token and the rule
   ignored it, hardcoding rgba(238,244,250,…) — a near-white wash laid over every
   design. Mixing the design's own canvas instead keeps the dealer's photo readable
   on light presets and stops it bleaching dark ones. */
:root body:not(.security-locked) #app{
  background-color: var(--canvas);
}
:root body:not(.security-locked).application-background-image #app{
  background-image:
    linear-gradient(
      color-mix(in srgb, var(--canvas) calc(var(--application-overlay-opacity, .88) * 100%), transparent),
      color-mix(in srgb, var(--canvas) calc(var(--application-overlay-opacity, .88) * 100%), transparent)),
    var(--application-background-image);
}

/* Advisory notice — was #fff6df on #734a05, a cream slab. */
:root .notice{
  color: color-mix(in srgb, var(--amber) 58%, var(--ink));
  background: color-mix(in srgb, var(--amber) 11%, var(--surface));
  border-color: color-mix(in srgb, var(--amber) 42%, transparent);
}
:root .notice.info-notice{
  color: var(--ink);
  background: color-mix(in srgb, var(--accent) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--accent) 34%, transparent);
}

/* Panel footnote — was #fafbfd, i.e. white, giving 2.8:1 on a dark panel. */
:root .panel-footnote{
  color: var(--muted);
  background: color-mix(in srgb, var(--ink) 4%, var(--surface));
  border-top-color: var(--id-hairline);
}

/* Form fields. --input-bg / --input-ink are declared by every design and were
   simply not reaching the base rules, so inputs stayed white on a black page. */
:root :is(input[type="text"], input[type="search"], input[type="number"],
          input[type="date"], input[type="email"], input[type="tel"],
          input[type="password"], select, textarea){
  color: var(--input-ink, var(--ink));
  background: var(--input-bg, var(--surface-strong));
  border-color: var(--ctl-edge, var(--line));
}
:root :is(input, select, textarea)::placeholder{
  color: color-mix(in srgb, var(--ink) 45%, transparent);
}

/* Native surfaces — scrollbars, date pickers, autofill, select popups — follow
   `color-scheme`, which applyAppearanceTheme() sets inline from the light/dark
   appearance. `midnight` is dark in BOTH appearances, so on its light appearance
   that inline value says "light" and Windows draws a white scrollbar down the side
   of a near-black page. !important is load-bearing here: it is the only way a
   stylesheet outranks the inline style the applier writes. */
html[data-design="midnight"]{ color-scheme: dark !important; }

@media (prefers-reduced-motion: reduce){
  :root *{ scroll-behavior: auto; }
}

/* ════════════════════════════════════════════════════════════════════════════
   8 · THE ROLE FOCUS BLOCK
   ────────────────────────────────────────────────────────────────────────────
   Leads the dashboard with what this role actually needs. Two registers only:
   a short metric strip (the figures you open the day with) and a stack of
   signals (an observation, why it matters, and the button that fixes it).

   Signals are ordered by severity, and one that has nothing to say does not
   render — so a good day is a short page rather than a grid of zeroes. That is
   the difference between this and the counter wall it replaces. */

.role-focus{ margin: 0 0 16px; }

.rf-head{
  display: flex; align-items: baseline; gap: 10px;
  margin: 0 0 10px;
}
.rf-head h2{
  position: relative;
  margin: 0; padding-left: 11px;
  font-family: var(--font-ui);
  font-size: var(--fs-lead); font-weight: 600; letter-spacing: -.01em;
  color: var(--ink);
}
.rf-head h2::before{                     /* the spoke again — same motif, same meaning */
  content: ""; position: absolute; left: 0; top: .18em; bottom: .18em;
  width: var(--id-spoke); border-radius:var(--r-control); background: var(--accent);
}
.rf-role{
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
}

/* The metric strip reuses the KPI rhythm so the page has one system, not two. */
.rf-metrics{
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  border: 1px solid var(--id-hairline); border-radius: var(--radius, 10px);
  background: var(--surface); overflow: hidden; margin-bottom: 12px;
}
.rf-metric{ padding: 14px 18px; border-left: 1px solid var(--id-hairline); }
.rf-metric:first-child{ border-left: 0; }
.rf-metric-label{
  display: block; color: var(--muted);
  font-size: var(--fs-micro); font-weight: 600;
  letter-spacing: .13em; text-transform: uppercase;
}
.rf-metric-value{
  display: block; margin: 4px 0 1px;
  font-family: var(--font-head); font-weight: 700;
  font-size: var(--fs-h1); line-height: 1; letter-spacing: -.015em;
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.rf-metric small{ color: var(--muted); font-size: var(--fs-small); }

/* ONE object, not five. The metric strip and the signal list share a single frame
   with hairline rules between rows, so the page reads as a ledger rather than as a
   pile of floating cards. This is the structural half of the fix; recolouring the
   cards would not have changed what the page IS. */
.rf-metrics{ border-radius: var(--radius,10px) var(--radius,10px) 0 0; border-bottom: 0; margin-bottom: 0; }
.rf-signals{
  display: grid;
  border: 1px solid var(--id-hairline);
  border-top: 0;
  border-radius: 0 0 var(--radius,10px) var(--radius,10px);
  background: var(--surface);
  overflow: hidden;
}
/* A row. No box, no radius, and crucially no left accent rail — that rail is the
   single most recognisable tell in machine-made UI, and an earlier pass of this
   redesign put it back on every signal. */
.rf-signal{
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  column-gap: 20px;
  row-gap: 2px;
  padding: 13px 18px;
  border: 0;
  border-top: 1px solid var(--id-hairline);
  border-radius: 0;
  background: transparent;
}
.rf-signals > .rf-signal:first-child{ border-top: 0; }
.rf-signal:hover{ background: color-mix(in srgb, var(--ink) 3%, transparent); }

/* Severity is a dot against the headline. It costs 7px and survives greyscale,
   where a tinted card edge does not. */
.rf-signal h3{
  position: relative;
  margin: 0;
  padding-left: 16px;
  font-family: var(--font-ui);
  font-size: var(--fs-body);
  font-weight: 600;
  letter-spacing: -.005em;
  color: var(--ink);
}
.rf-signal h3::before{
  content: "";
  position: absolute;
  left: 0; top: .45em;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--ink) 34%, transparent);
}
.rf-signal.rf-act   h3::before{ background: var(--red); }
.rf-signal.rf-watch h3::before{ background: var(--amber); }
.rf-signal.rf-good  h3::before{ background: var(--green); }

/* The detail sits under the headline, indented to the dot, so the column of dots
   reads straight down the left edge. */
.rf-signal p{
  grid-column: 1;
  margin: 0;
  padding-left: 16px;
  color: var(--muted);
  font-size: var(--fs-small);
  line-height:var(--lh-small);
}
/* The action rides the headline line and is right-aligned, so every row resolves
   to the same place instead of the eye hunting for a link under each card. */
.rf-signal .rf-do{
  grid-column: 2;
  grid-row: 1;
  justify-self: end;
  white-space: nowrap;
  font-size: var(--fs-small);
}

.rf-clear{
  margin: 0; padding: 14px 16px;
  border: 1px solid var(--id-hairline); border-radius: var(--radius-sm, 8px);
  background: var(--surface); color: var(--muted); font-size: var(--fs-small);
}

@media (max-width: 900px){
  .rf-metrics{ grid-auto-flow: row; }
  .rf-metric{ border-left: 0; border-top: 1px solid var(--id-hairline); }
  .rf-metric:first-child{ border-top: 0; }
}

/* ════════════════════════════════════════════════════════════════════════════
   9 · THE SIGN-IN SCREEN — structure, not a floating card
   ────────────────────────────────────────────────────────────────────────────
   A centred rounded card dropped on a stock photo is the most templated auth
   layout there is, and it was ours: place-items:center, width:min(480px), radius
   18, a 60px drop shadow, and an uppercase eyebrow over the title.

   Replaced with an anchored split — the form sits on a solid panel held to the
   left edge, the photograph runs full-bleed beside it. The photo stops being
   wallpaper the card floats on and becomes one half of a composition. Nothing in
   the markup changes; this is the same DOM re-laid out. */

:root .security-gate{
  min-height: 100vh;
  display: grid;
  grid-template-columns: minmax(400px, 34%) 1fr;
  align-items: stretch;
  place-items: stretch;
  padding: 0;
  gap: 0;
}

/* The photograph, confined to the right column instead of sitting behind
   everything. The overlay is dropped to a light scrim: it no longer has to fight
   a card for legibility, because no text sits on it. */
:root .security-gate::before{
  grid-column: 2;
  grid-row: 1;
  position: relative;
  inset: auto;
  z-index: 0;
  background-image:
    linear-gradient(100deg, rgba(7, 25, 45, .34), rgba(10, 31, 52, .12) 60%),
    url("assets/signin-showroom.webp"),
    url("assets/signin-dealership.svg"),
    linear-gradient(135deg, #0b223b, #163f68);
}

/* The panel. No border, no radius, no shadow — it is a wall, not an object. */
:root .security-gate-card{
  grid-column: 1;
  grid-row: 1;
  z-index: 1;
  width: auto;
  max-width: none;
  align-content: center;
  padding: 0 clamp(38px, 5vw, 76px);
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: var(--surface-strong, #fff);
  gap: 18px;
}

/* The eyebrow said "AutoSteward Security" directly above a heading that already
   says "Sign in to AutoSteward" — the same sentence in a smaller, louder voice. */
:root .security-gate .eyebrow{ display: none; }

:root .security-gate-card h1{
  margin: 0;
  font-family: var(--font-head);
  font-size: var(--fs-display, var(--fs-h1));
  line-height: var(--lh-display, 1.1);
  letter-spacing: -.015em;
  color: var(--ink);
}

/* The dealership sign is absolutely positioned from percentages that positionLoginArtwork()
   computes against the whole gate. Giving it grid-column:2 re-based its containing block to
   that column, so its left offset was measured from the column start and it flew off-screen.
   It only needs to be raised above the photograph; the default x already lands it there. */
:root .security-gate .login-brand-sign{ z-index: 2; }

/* The actions row is left-aligned with the fields above it rather than pushed
   right, because nothing here is a dialog. */
:root .security-gate-card .modal-actions{ justify-content: flex-start; }

:root .security-gate-footnote{
  margin-top: 6px;
  padding-top: 16px;
  border-top: 1px solid var(--id-hairline);
  color: var(--muted);
  font-size: var(--fs-small);
}

/* Below 900px the photograph is a strip along the top rather than a column, so
   the form keeps the full width instead of being squeezed into a third of it. */
@media (max-width: 900px){
  :root .security-gate{ grid-template-columns: 1fr; grid-template-rows: 34vh 1fr; }
  :root .security-gate::before{ grid-column: 1; grid-row: 1; }
  :root .security-gate-card{ grid-column: 1; grid-row: 2; padding: 32px 22px; }
  :root .security-gate .login-brand-sign{ grid-column: 1; grid-row: 1; }
}

/* The eyebrow, finally deleted rather than muted. "DAILY COMMAND CENTER" sat directly
   above "Today's Work" — the same statement in a smaller, louder voice, and the single
   most reliable marker of generated layout. The element stays in the DOM because routes
   set it; it just no longer occupies the page. */
:root .dashboard-heading .eyebrow{ display: none; }

/* The role line replaces it: the one piece of information the heading does not
   already carry. Set in the LABEL register, so it reads as an annotation on the
   title rather than as a second title. */
:root .rf-head{ margin: -6px 0 12px; gap: 10px; align-items: baseline; }
:root .rf-head .rf-lead{
  color: var(--muted);
  font-size: var(--fs-small);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}
:root .rf-head .rf-role{
  padding: 2px 8px;
  border: 1px solid var(--id-hairline-strong);
  border-radius:var(--r-stadium);
  color: var(--ink);
}
