/* Apex design system - the shared stylesheet every platform screen loads.
   Lifted from docs/design/reference/apex.css (the owner's reviewed blend, 2026-09-21) and cleaned: page-specific
   dispatch-board rules moved out (they belong to the calendar screen), duplicates removed, sections named.
   Rules of the system are in web/shared/README.md; the short form: light Canvas look, white 12px cards on the
   blue-grey page, navy structure, ONE blue primary action per view, tags not prose, room around everything.
   Sections: 1 tokens · 2 reset · 3 layout · 4 rail nav · 5 command palette · 6 buttons · 7 pills · 8 tags · 9 cards
   · 10 record hero, journey, next box · 11 facts strip · 12 timeline · 13 tables · 14 peek panel · 15 assign, hold,
   toast · 16 forms · 17 empty / loading / error · 18 phone layer (always last so it wins) · 19 colour schemes
   (tokens only, appended after the phone layer because it holds no layout).
   Sections 20-24 (the elevation round, 2026-09-22) live in three files this one @imports, so each stays readable:
   ui-identity.css (20 identity: avatar, ident, plate, vehicle, row edges, hover actions, empty.compact, hintbar,
   card heads, now-line, thumbs), ui-stats.css (21 stats and charts: stat, delta, spark, ring, meter.lbl, segbar;
   22 strips and bars: needs, chipbar, selection bar, timeline upgrades) and ui-overlay.css (23 popovers, range
   picker, sign-in and error page; 24 motion). An imported sheet sits BEFORE this file in the cascade, so those
   files only add selectors; a rule that has to beat one written here (the peek's transition) is changed here. */
@import url("ui-identity.css");
@import url("ui-stats.css");
@import url("ui-overlay.css");
/* Fix round 2 (2026-09-22): section 25 lists, filters and the phone surfaces (listRow, filterBar, sheet, dockBar,
   overflowTools, stickyStrip); section 26 states, tiles and motion (staleLine, statRow, ratingTiles, diffChips,
   .thumb.nofile, card head .sub, .empty.compact.wrap, pulse / pop / crossfade, hovercard). */
@import url("ui-lists.css");
@import url("ui-states.css");
/* Fix round 3 (2026-09-23): section 27 choosing (pickerList, kindTiles, refusals, dayAxis / weekAxis); section 28 the
   adoption kit (record layout, history rows, missing originals, the peek's phone summary, the compact dock, the phone
   search, rate and Clear tiles, enter(), the Dispatch stack chip). */
@import url("ui-pick.css");
@import url("ui-kit3.css");
/* The second factor (2026-09-25): section 29, the authenticator enrolment, the code step and the recovery codes. */
@import url("ui-factor.css");

/* ============================== 1. TOKENS ============================== */
:root {
  /* surfaces */
  --page: #e7eef5;            /* the blue-grey page behind every card */
  --card: #fff;               /* card, peek, palette and input surface */
  --soft: #f2f6f9;            /* hover fill, quoted text, table head */
  --soft-2: #e9f0f6;          /* a step darker than soft: default tag fill, icon wells */
  /* ink */
  --ink: #102332;             /* body text */
  --ink-soft: #3d5468;        /* secondary text that still has to be read */
  --muted: #5b7082;           /* labels, captions, card headings */
  --faint: #8a9bab;           /* tertiary: ticks, timestamps, placeholders */
  /* lines */
  --line: #b8c6d3;            /* control borders (buttons, inputs, pills) */
  --line-soft: #dde5ec;       /* card and divider borders */
  --line-faint: #e9eff4;      /* hairlines inside a card */
  /* structure */
  --navy: #0b3152;            /* rail, hero, the selected thing */
  --navy-2: #12406a;          /* hover on navy */
  --navy-3: #1a4f7f;          /* pressed on navy */
  --navy-ink: #0b3152;        /* navy as text or an icon on a light surface (icon wells, the timeline's job dot, the wall clock): brightened on dark, where navy itself is a fill */
  /* the one action colour */
  --blue: #006fd6;            /* primary button, links, times, the current step */
  --blue-ink: #0058ab;        /* primary hover and blue text on light fills */
  --blue-soft: #ddecff;       /* blue tag fill */
  --blue-faint: #eef5ff;      /* selected row, next box fill */
  /* status colours: green = done/paid/ready, amber = needs attention, red = blocked/failed/owed */
  --green: #00865a;  --green-soft: #dcf6e9;
  --amber: #b96000;  --amber-soft: #fff0ce;  --amber-faint: #fff8e6;  --amber-line: #f1d59c;
  --red: #d12a22;    --red-soft: #ffe3e0;    --red-faint: #fff1f0;    --red-line: #f3c2be;
  /* service families in the validated categorical order: tint, ppf, ceramic, detail; Vinyl Wrap's violet joined 2026-10-06 */
  --f-tint: #2a78d6;  --f-tint-soft: #e3eefb;  --f-tint-ink: #1d5ca8;
  --f-ppf: #e06a1b;   --f-ppf-soft: #fdeadf;   --f-ppf-ink: #9a4408;
  --f-cer: #b03a8c;   --f-cer-soft: #f8e3f1;   --f-cer-ink: #8a2569;
  --f-det: #0f9a8a;   --f-det-soft: #dff4f1;   --f-det-ink: #0a6d61;
  --f-wrap: #6a4fc8;  --f-wrap-soft: #ece8fa;  --f-wrap-ink: #4c3399;
  /* sequential chart scale (light to dark blue) for bars and heatmap cells; --seq-0 is "nothing here" */
  --seq-0: #eef3f8;  --seq-1: #cfe1f7;  --seq-2: #86b6ef;  --seq-3: #4f93e0;  --seq-4: #2a78d6;  --seq-5: #104281;
  /* selection ring shared by focus, the selected card and drag targets */
  --sel-ring: 0 0 0 2px var(--card), 0 0 0 4px var(--blue);
  /* spacing scale: 4 / 8 / 12 / 16 / 24 / 32 - nothing between cards is ever below 16 */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 24px; --sp-6: 32px;
  /* type scale: 13 / 14 / 16 / 20 / 26 - body is 14 */
  --t-1: 13px; --t-2: 14px; --t-3: 16px; --t-4: 20px; --t-5: 26px;
  /* three radii: controls, cards, pills */
  --r-sm: 8px; --r: 12px; --r-pill: 999px;
  /* elevation: cards rest, floating things lift, the peek casts left */
  --shadow: 0 1px 2px rgba(16,35,50,.06), 0 8px 24px rgba(16,35,50,.06);
  --lift: 0 2px 4px rgba(16,35,50,.10), 0 18px 40px rgba(16,35,50,.22);
  --peek-shadow: 0 0 0 1px var(--line-soft), -12px 0 40px rgba(16,35,50,.14);
  --font: Inter, ui-sans-serif, system-ui, "Segoe UI", sans-serif; /* no web fonts: the system stack */
  --rail: 76px;               /* width of the navy rail on desktop */
  --topbar: 56px;             /* height of the white top bar */
  --tabbar: 64px;             /* height of the phone tab bar */
  /* scheme-aware extras (colour schemes, 2026-09-21 evening): every colour a rule used to write as #fff or an rgba()
     is one of these, so the dark block in section 19 can redefine it; light keeps the exact values of before */
  --control: #fff;            /* the fill of a button, input, pill, kbd, checkbox, outline tag: white here, raised on dark */
  --on-dark: #fff;            /* text, icons and tiles on navy, blue, a solid tag, the toast: stays white in every scheme */
  --rail-ink: #b9cfe3;        /* rail labels, the selected report's caption */
  --rail-ink-soft: #cfe0ef;   /* rail base text, hero meta, the toast's kbd */
  --hero-kicker: #9fbad3;     /* the small uppercase kicker on the hero */
  --scrim: rgba(11,49,82,.35);/* behind the palette and the sheets */
  --shade: 16, 35, 50;        /* the shadow colour as channels for rgba(var(--shade), .5): navy here, black on dark */
  --shadow-sm: 0 1px 2px rgba(16,35,50,.12);  /* the segmented control's raised button */
  --float: 0 16px 44px rgba(16,35,50,.18);    /* the assign / hold panel */
  /* fills behind white text: the same colour as the text token on light, so nothing changes here; on dark the text
     tokens brighten to stay readable on a dark card while these stay deep enough for white text (WCAG AA) */
  --blue-fill: #006fd6;  --blue-fill-2: #0058ab;  /* the primary button and its hover, the hold, a checked control */
  --green-fill: #00865a;  --amber-fill: #b96000;  --red-fill: #d12a22;   /* solid tags, badges, holds */
  --paper: #fff;  --paper-ink: #102332;  /* the same in every scheme: a signature pad is ink on paper, and the PNG it stores must print */
  /* identity tones (elevation round): five deep, desaturated fills for the initials disc, chosen by a hash of the
     name so the same person is always the same colour; none of them is a status colour, so a disc never reads as
     late or paid. White text on every one meets AA in both schemes (theme.test.mjs checks). */
  --av-1: #1a4f7f;  --av-2: #34568b;  --av-3: #2a6a6a;  --av-4: #5c4d8c;  --av-5: #7a4f6a;
  --f-ink-on-fill: #ffffff; /* initials on a family-coloured disc: white on the deep Light fills, the page colour on the bright Dark ones */
  --shadow-2: 0 2px 4px rgba(16,35,50,.08), 0 12px 28px rgba(16,35,50,.12);  /* one step above --shadow: a hovered .card.lift */
  /* motion: one language for hover, open, land and change; prefers-reduced-motion turns every use off (ui-overlay.css) */
  --t-fast: 120ms;  --t-base: 220ms;  --ease: cubic-bezier(.2,.7,.2,1);
  color-scheme: light;        /* scrollbars, native pickers and form controls follow the scheme */
}

/* ============================== 2. RESET ============================== */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; }
body { font: var(--t-2)/1.45 var(--font); color: var(--ink); background: var(--page); -webkit-font-smoothing: antialiased; }
h1, h2, h3, h4, p, ul, ol, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: var(--blue); text-decoration: none; }
img, svg { display: block; max-width: 100%; }
/* svg.i is the icon: stroke follows the text colour, 18px default, .s small */
svg.i { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
svg.i.s { width: 14px; height: 14px; }
.num { font-variant-numeric: tabular-nums; }       /* every number lines up */
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); } /* screen-reader only */
:focus-visible { outline: none; box-shadow: var(--sel-ring); }
.muted { color: var(--muted); } .soft { color: var(--ink-soft); } .small { font-size: 12.5px; } .tiny { font-size: 11.5px; }
.sp { flex: 1 1 0; min-width: var(--sp-2); }       /* flex spacer */
.hr { height: 1px; background: var(--line-faint); margin: var(--sp-3) 0; }
kbd { font: 600 11px var(--font); border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 5px; padding: 0 5px; background: var(--control); color: var(--ink-soft); line-height: 16px; white-space: nowrap; }

/* ============================== 3. LAYOUT ============================== */
/* .app: rail on the left, everything else in .main */
.app { display: grid; grid-template-columns: var(--rail) 1fr; min-height: 100vh; }
.main { min-width: 0; display: flex; flex-direction: column; }
/* .topbar: white, sticky, title + crumb on the left, search and tools on the right */
.topbar { display: flex; align-items: center; gap: 10px; padding: 0 var(--sp-5); height: var(--topbar); background: var(--card); border-bottom: 1px solid var(--line-soft); position: sticky; top: 0; z-index: 20; }
.topbar > * { flex-shrink: 0; }
.topbar h1 { font-size: 17px; font-weight: 700; letter-spacing: -.01em; white-space: nowrap; }
.topbar .crumb { color: var(--muted); font-weight: 500; white-space: nowrap; }
.topbar .crumb b { color: var(--ink); font-weight: 700; }
/* .search: the palette's visible trigger; a button styled as a field so it is keyboard reachable */
.search { display: flex; align-items: center; gap: var(--sp-2); background: var(--soft); border: 1px solid var(--line-soft); border-radius: var(--r-sm); padding: 0 10px; height: 34px; color: var(--muted); width: 300px; text-align: left; }
.search kbd { margin-left: auto; }
/* .page: the scrolling area; 24px gutters, 16px between children */
.page { padding: var(--sp-4) var(--sp-5) var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-4); }
.toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.toolbar .range { font-size: var(--t-3); font-weight: 700; letter-spacing: -.01em; }
.toolbar .range small { display: block; font-size: 12px; color: var(--muted); font-weight: 500; }
/* .cols: the three-column record layout; .col stacks cards 16px apart */
.cols { display: grid; grid-template-columns: 320px minmax(0, 1fr) 340px; gap: var(--sp-4); align-items: start; }
.cols.two { grid-template-columns: minmax(0, 1fr) 340px; }
.col { display: flex; flex-direction: column; gap: var(--sp-4); min-width: 0; }

/* ============================== 4. RAIL NAV ============================== */
/* .rail: navy, sticky, icon over label; the current section is a white tile */
.rail { background: var(--navy); color: var(--rail-ink-soft); display: flex; flex-direction: column; align-items: center; padding: 10px 8px 12px; gap: 2px; position: sticky; top: 0; height: 100vh; }
.rail .logo { width: 34px; height: 34px; border-radius: 9px; background: var(--on-dark); color: var(--navy); display: grid; place-items: center; font-weight: 800; font-size: var(--t-3); margin-bottom: 10px; }
.rail a { position: relative; display: flex; flex-direction: column; align-items: center; gap: 3px; width: 64px; padding: 8px 0 6px; border-radius: 9px; color: var(--rail-ink); font-size: 10.5px; font-weight: 600; }
.rail a .lbl { white-space: nowrap; } /* the longest label (Commission) is one word; it never breaks mid-word */
.rail a svg.i { width: 20px; height: 20px; }
.rail a:hover { background: color-mix(in srgb, var(--on-dark) 8%, transparent); color: var(--on-dark); }
.rail a.on { background: var(--on-dark); color: var(--navy); }
.rail a .n { position: absolute; top: 4px; right: 6px; background: var(--amber-fill); color: var(--on-dark); font-size: 10px; font-weight: 700; border-radius: var(--r-pill); padding: 0 5px; line-height: 15px; } /* count badge */
.rail .grow { flex: 1; }
.rail .me { width: 34px; height: 34px; border-radius: 50%; background: var(--navy-3); color: var(--on-dark); display: grid; place-items: center; font-weight: 700; font-size: 12px; border: 2px solid color-mix(in srgb, var(--on-dark) 25%, transparent); }

/* ============================== 5. COMMAND PALETTE ============================== */
/* .cmdk: full-screen navy scrim with a white box near the top; apex.js fills the list */
.cmdk { position: fixed; inset: 0; background: var(--scrim); z-index: 60; display: none; align-items: flex-start; justify-content: center; padding: 14vh var(--sp-4) 0; }
.cmdk.on { display: flex; }
.cmdk .box { width: 640px; max-width: 100%; background: var(--card); border-radius: 14px; box-shadow: var(--lift); overflow: hidden; }
.cmdk input { width: 100%; border: 0; border-bottom: 1px solid var(--line-soft); padding: var(--sp-4) 18px; font-size: var(--t-3); outline: none; background: transparent; }
.cmdk input:focus-visible { box-shadow: none; }
.cmdk ul { max-height: 50vh; overflow: auto; padding-bottom: var(--sp-2); }
.cmdk li { display: flex; align-items: center; gap: var(--sp-3); padding: 10px 18px; font-weight: 500; cursor: pointer; }
.cmdk li.on, .cmdk li:hover { background: var(--blue-faint); }
.cmdk li .k { margin-left: auto; font: 600 11px var(--font); border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 5px; padding: 0 5px; color: var(--ink-soft); line-height: 16px; }
.cmdk .grp { padding: 10px 18px 4px; font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); cursor: default; }
.cmdk .grp:hover { background: transparent; }
.cmdk .none { padding: 14px 18px; color: var(--muted); }

/* ============================== 6. BUTTONS ============================== */
/* .btn: outlined by default; ONE .btn.primary per view; .ghost/.quiet for text-only actions */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; font: 600 13.5px var(--font); border-radius: var(--r-sm); padding: 0 var(--sp-3); height: 34px; border: 1px solid var(--line); background: var(--control); color: var(--ink); white-space: nowrap; }
.btn:hover { background: var(--soft); }
.btn.primary { background: var(--blue-fill); border-color: var(--blue-fill); color: var(--on-dark); }
.btn.primary:hover { background: var(--blue-fill-2); border-color: var(--blue-fill-2); }
.btn.navy { background: var(--navy); border-color: var(--navy); color: var(--on-dark); }
.btn.navy:hover { background: var(--navy-2); }
.btn.danger { color: var(--red); border-color: var(--red-line); }
.btn.danger:hover { background: var(--red-faint); }
.btn.ghost { border-color: transparent; background: transparent; color: var(--blue); }
.btn.ghost:hover { background: var(--blue-faint); }
.btn.quiet { border-color: transparent; background: transparent; color: var(--ink-soft); }
.btn.sm { height: 28px; padding: 0 10px; font-size: 12.5px; }
.btn.lg { height: 40px; padding: 0 var(--sp-4); font-size: var(--t-2); }
.btn.icon { width: 34px; padding: 0; }
.btn.icon.sm { width: 28px; }
.btn.block { width: 100%; }
.btn[disabled], .btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; pointer-events: none; }
.btn kbd { margin-left: 2px; }
/* .seg: segmented control, one .on at a time */
.seg { display: inline-flex; background: var(--soft); border: 1px solid var(--line-soft); border-radius: var(--r-sm); padding: 2px; gap: 2px; }
.seg button { border: 0; background: transparent; border-radius: 6px; padding: 0 var(--sp-3); height: 28px; font-weight: 600; color: var(--ink-soft); display: inline-flex; align-items: center; }
.seg button.on { background: var(--control); color: var(--ink); box-shadow: var(--shadow-sm); }
.seg button kbd { margin-left: 6px; font-size: 10px; line-height: 14px; padding: 0 4px; }
.actions { display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap; } /* a row of buttons */

/* ============================== 7. PILLS ============================== */
/* .pill: filter chips with an optional count; .on is navy; .warn draws the eye to a late count */
.pills { display: flex; gap: var(--sp-2); flex-wrap: wrap; align-items: center; }
.pill { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--line); background: var(--control); border-radius: var(--r-pill); padding: 0 13px; height: 32px; font-weight: 600; color: var(--ink-soft); white-space: nowrap; }
.pill:hover { border-color: var(--ink-soft); }
.pill.on { background: var(--navy); border-color: var(--navy); color: var(--on-dark); }
.pill b { font-weight: 600; opacity: .7; }
.pill.on b { opacity: .8; }
.pill.warn { border-color: var(--amber-line); background: var(--amber-faint); color: var(--amber); }
.pill.warn b { opacity: 1; }
.pill.sm { height: 28px; font-size: 12.5px; padding: 0 11px; }
.pill[disabled] { opacity: .5; cursor: not-allowed; }

/* ============================== 8. TAGS ============================== */
/* .tag: a one-to-three-word status; colour means one thing (see tokens). .chip is the same thing under its
   older name so the reference pages and the four screens keep working */
.tag, .chip { display: inline-flex; align-items: center; gap: 4px; border-radius: var(--r-pill); padding: 0 8px; height: 20px; font-size: 11.5px; font-weight: 700; background: var(--soft-2); color: var(--ink-soft); white-space: nowrap; line-height: 20px; }
.tag svg.i, .chip svg.i { width: 12px; height: 12px; stroke-width: 2.2; }
.tag.green, .chip.green { background: var(--green-soft); color: var(--green); }
.tag.amber, .chip.amber { background: var(--amber-soft); color: var(--amber); }
.tag.red, .chip.red { background: var(--red-soft); color: var(--red); }
.tag.blue, .chip.blue { background: var(--blue-soft); color: var(--blue-ink); }
.tag.navy, .chip.navy { background: var(--navy); color: var(--on-dark); }
.tag.solid-green, .chip.solid-green { background: var(--green-fill); color: var(--on-dark); }
.tag.solid-amber, .chip.solid-amber { background: var(--amber-fill); color: var(--on-dark); }
.tag.solid-red, .chip.solid-red { background: var(--red-fill); color: var(--on-dark); }
.tag.outline, .chip.outline { background: var(--control); border: 1px solid var(--line); line-height: 18px; }
.tag.f-tint, .chip.f-tint { background: var(--f-tint-soft); color: var(--f-tint-ink); }
.tag.f-ppf, .chip.f-ppf { background: var(--f-ppf-soft); color: var(--f-ppf-ink); }
.tag.f-cer, .chip.f-cer { background: var(--f-cer-soft); color: var(--f-cer-ink); }
.tag.f-det, .chip.f-det { background: var(--f-det-soft); color: var(--f-det-ink); }
.tag.f-wrap, .chip.f-wrap { background: var(--f-wrap-soft); color: var(--f-wrap-ink); }
.tags { display: flex; gap: var(--sp-1); flex-wrap: wrap; align-items: center; }
.dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: none; background: currentColor; } /* status dot */
.avatar { width: 28px; height: 28px; border-radius: 50%; background: var(--navy-3); color: var(--on-dark); display: grid; place-items: center; font-weight: 700; font-size: 11px; flex: none; }
.plate { display: inline-block; font: 700 11px/17px var(--font); letter-spacing: .06em; border: 1.5px solid var(--ink-soft); border-radius: 4px; padding: 0 6px; color: var(--ink-soft); } /* licence plate */
.edge { border-left: 4px solid var(--line); } .edge.tint { border-left-color: var(--f-tint); } .edge.ppf { border-left-color: var(--f-ppf); } .edge.cer { border-left-color: var(--f-cer); } .edge.det { border-left-color: var(--f-det); } .edge.wrap { border-left-color: var(--f-wrap); }
.bg-tint { background: var(--f-tint); } .bg-ppf { background: var(--f-ppf); } .bg-cer { background: var(--f-cer); } .bg-det { background: var(--f-det); } .bg-wrap { background: var(--f-wrap); }
/* .meter: a thin progress bar; colour classes match the tags */
.meter { height: 6px; border-radius: 3px; background: var(--blue-soft); overflow: hidden; position: relative; }
.meter i { position: absolute; inset: 0 auto 0 0; background: var(--blue); border-radius: 3px; }
.meter.amber { background: var(--amber-soft); } .meter.amber i { background: var(--amber); }
.meter.red { background: var(--red-soft); } .meter.red i { background: var(--red); }
.meter.green { background: var(--green-soft); } .meter.green i { background: var(--green); }

/* ============================== 9. CARDS ============================== */
/* .card: white, 12px radius, resting shadow; header is a small uppercase label with an optional link */
.card { background: var(--card); border: 1px solid var(--line-soft); border-radius: var(--r); box-shadow: var(--shadow); min-width: 0; }
.card > header { display: flex; align-items: center; gap: 10px; padding: var(--sp-4) var(--sp-4) 0; }
.card > header h2, .card > header h3 { font-size: 12px; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
.card > header .lnk { font-size: 12.5px; font-weight: 600; color: var(--blue); }
.card > .body { padding: var(--sp-3) var(--sp-4) var(--sp-4); }
.card > .body + .body { padding-top: 0; }
.card > footer { padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--line-faint); display: flex; gap: var(--sp-2); align-items: center; }
.card.warn { border-color: var(--amber-line); box-shadow: 0 0 0 3px var(--amber-faint), var(--shadow); } /* an open case */
.card.warn > header h3 { color: var(--amber); }
.card.sel { box-shadow: var(--sel-ring); }
/* .row: one click target inside a card (vehicle, job, deferred item) */
.rows { display: grid; gap: var(--sp-2); }
.row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 10px; align-items: center; border: 1px solid var(--line-soft); border-radius: var(--r-sm); padding: 10px var(--sp-3); cursor: pointer; color: inherit; }
.row:hover { background: var(--soft); }
.row.sel { background: var(--blue-faint); border-color: var(--blue-soft); }
.row.dashed { border-style: dashed; background: var(--amber-faint); border-color: var(--amber-line); }
.row b { display: block; font-size: var(--t-1); line-height: 1.25; }
.row small { display: block; color: var(--muted); font-size: 11.5px; margin-top: 2px; }
.row .ico { width: 40px; height: 40px; border-radius: var(--r-sm); background: var(--soft-2); display: grid; place-items: center; color: var(--navy-ink); }
.row .ico svg.i { width: 22px; height: 22px; }
.row .end { text-align: right; font-size: 12px; }
.row .bar { width: 4px; border-radius: 2px; align-self: stretch; }
/* .banner: a one-line notice card with a left edge (duplicate, sync, warning) */
.banner { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--sp-3); align-items: center; background: var(--card); border: 1px solid var(--amber-line); border-left: 4px solid var(--amber); border-radius: var(--r); padding: 10px 14px; box-shadow: var(--shadow); }
.banner .ic { width: 34px; height: 34px; border-radius: 9px; background: var(--amber-soft); color: var(--amber); display: grid; place-items: center; }
.banner b { font-size: 13.5px; }
.banner p { font-size: 12.5px; color: var(--ink-soft); margin-top: 1px; }
.banner.red { border-color: var(--red-line); border-left-color: var(--red); } .banner.red .ic { background: var(--red-soft); color: var(--red); }
.banner.blue { border-color: var(--blue-soft); border-left-color: var(--blue); } .banner.blue .ic { background: var(--blue-soft); color: var(--blue-ink); }
/* .kv: label / value pairs */
.kv { display: grid; grid-template-columns: auto 1fr; gap: 4px 14px; font-size: var(--t-1); }
.kv dt { color: var(--muted); font-weight: 500; } .kv dd { margin: 0; font-weight: 500; }
.disclose > summary { cursor: pointer; color: var(--muted); font-size: 12.5px; font-weight: 600; list-style: none; display: inline-flex; gap: 6px; align-items: center; } /* the one disclosure per page */
.disclose > summary::-webkit-details-marker { display: none; }
.disclose[open] > summary { margin-bottom: var(--sp-2); }

/* ============================== 10. RECORD HERO, JOURNEY RAIL, NEXT BOX ============================== */
/* .hero: navy record header; identity left, the one next action right */
.hero { background: var(--navy); color: var(--on-dark); border-radius: var(--r); padding: var(--sp-4) var(--sp-5); display: flex; align-items: center; gap: var(--sp-5); }
.hero .who { min-width: 0; }
.hero .kicker { font-size: 11px; font-weight: 700; letter-spacing: .08em; color: var(--hero-kicker); text-transform: uppercase; }
.hero h2 { font-size: 21px; letter-spacing: -.01em; line-height: 1.2; }
.hero .meta { color: var(--rail-ink-soft); font-size: var(--t-1); }
.hero .tags { margin-top: var(--sp-2); gap: 6px; }
.hero .tags .tag, .hero .tags .chip { background: color-mix(in srgb, var(--on-dark) 14%, transparent); color: var(--on-dark); }
.hero .tags .money { background: var(--on-dark); color: var(--navy); }
.hero .tags .warn { background: var(--amber-fill); color: var(--on-dark); }
.hero .tags .bad { background: var(--red-fill); color: var(--on-dark); }   /* failed, blocked, owed: red means one thing on the hero too */
.hero .btn:not(.primary) { border-color: transparent; background: color-mix(in srgb, var(--on-dark) 12%, transparent); color: var(--on-dark); }
.hero .btn:not(.primary):hover { background: color-mix(in srgb, var(--on-dark) 20%, transparent); }
/* .next: "Next on this ..." box - the one thing to do and why; white inside the hero, blue-faint inside a card */
.next { background: var(--card); color: var(--ink); border: 1px solid var(--blue-soft); border-radius: 10px; padding: var(--sp-3) 14px var(--sp-3) var(--sp-4); display: flex; align-items: center; gap: var(--sp-4); flex: 0 1 620px; }
.next > div { min-width: 0; flex: 1; }
.next .k { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--blue-ink); }
.next .v { font-weight: 600; font-size: var(--t-2); line-height: 1.3; margin-top: 2px; }
.next .v small { display: block; color: var(--muted); font-weight: 500; font-size: 12.5px; }
.next .btn.primary { height: 42px; padding: 0 18px; font-size: 14.5px; flex: none; }
.card .next, .peek .next { background: var(--blue-faint); }
/* .journey: Inquiry > Quote > Booked > In shop > QA > Paid > Aftercare; progress that is also navigation. A stage is an
   <a> when it leads somewhere and a <span> when it does not; both draw the same (one rail on every record). */
.journey { display: grid; grid-template-columns: repeat(7, 1fr); background: var(--card); border: 1px solid var(--line-soft); border-radius: var(--r); box-shadow: var(--shadow); overflow: hidden; }
.journey > a, .journey > span { position: relative; display: block; padding: var(--sp-3) 14px var(--sp-3) 22px; color: var(--muted); border-left: 1px solid var(--line-soft); min-width: 0; }
.journey > :first-child { border-left: 0; }
.journey > a::before, .journey > span::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px; background: var(--line-soft); }
.journey > .done::before { background: var(--green); } .journey > .now::before { background: var(--blue); }
.journey > a .dot, .journey > span .dot { position: absolute; left: 8px; top: 15px; background: var(--line); }
.journey > .done .dot { background: var(--green); } .journey > .now .dot { background: var(--blue); box-shadow: 0 0 0 3px var(--blue-soft); }
.journey b { display: block; font-size: var(--t-1); color: var(--ink); }
.journey > .now b { color: var(--blue-ink); }
.journey small { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.journey > a:hover { background: var(--soft); }

/* ============================== 11. FACTS STRIP ============================== */
/* .facts: a row of label / big number / footnote tiles (money, counts); .due turns one red */
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: var(--sp-3); }
.fact { border: 1px solid var(--line-soft); border-radius: 10px; padding: 10px var(--sp-3); position: relative; background: var(--card); min-width: 0; }
.fact .l { font-size: 11.5px; color: var(--muted); font-weight: 600; display: flex; align-items: center; gap: 4px; }
.fact .l svg.i { width: 13px; height: 13px; color: var(--faint); }
.fact .v { font-size: 22px; letter-spacing: -.02em; font-weight: 700; margin-top: 2px; line-height: 1.1; font-variant-numeric: tabular-nums; }
.fact .s { font-size: 11.5px; color: var(--muted); margin-top: 3px; }
.fact.due { background: var(--red-faint); border-color: var(--red-line); } .fact.due .v { color: var(--red); }
.fact.good { background: var(--green-soft); border-color: var(--green-soft); } .fact.good .v { color: var(--green); }
.fact .def { display: none; position: absolute; left: 0; top: calc(100% + 6px); z-index: 5; width: 260px; background: var(--ink); color: var(--card); font-size: 12px; line-height: 1.4; padding: 8px 10px; border-radius: var(--r-sm); box-shadow: var(--lift); } /* definition on hover */
.fact:hover .def { display: block; }
/* .steps: a short checklist with done / now / todo bullets (case steps, QA) */
.steps { display: grid; gap: 4px; }
.steps .s { display: grid; grid-template-columns: 18px 1fr auto; gap: var(--sp-2); align-items: center; font-size: 12.5px; }
.steps .s .b { width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--line); }
.steps .s.done .b { background: var(--green-fill); border-color: var(--green-fill); }
.steps .s.now .b { border-color: var(--amber); background: radial-gradient(var(--amber) 40%, var(--card) 45%); }
.steps .s.done { color: var(--ink-soft); }
.steps .s .w { font-size: 11px; color: var(--faint); }

/* ============================== 12. TIMELINE ============================== */
/* .tl: newest first, a day label per group, an icon dot per event; .ev.job/.pay/.fail/.call/.case/.note colour the dot */
.tl { position: relative; display: grid; gap: 2px; }
.tl::before { content: ""; position: absolute; left: 15px; top: 8px; bottom: 8px; width: 2px; background: var(--line-faint); }
.tday { position: relative; font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); padding: 10px 0 4px 40px; }
.tday:first-child { padding-top: 2px; }
.ev { position: relative; display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; gap: var(--sp-2); align-items: start; padding: 7px var(--sp-2) 7px 0; border-radius: var(--r-sm); cursor: pointer; }
.ev:hover { background: var(--soft); }
.ev .d { width: 32px; height: 32px; border-radius: 50%; background: var(--card); border: 2px solid var(--line-soft); display: grid; place-items: center; color: var(--ink-soft); position: relative; z-index: 1; }
.ev .d svg.i { width: 15px; height: 15px; }
.ev.job .d { border-color: var(--navy-ink); color: var(--navy-ink); } .ev.pay .d { border-color: var(--green); color: var(--green); }
.ev.fail .d { border-color: var(--red); color: var(--red); background: var(--red-faint); }
.ev.call .d { border-color: var(--blue); color: var(--blue-ink); } .ev.case .d { border-color: var(--amber); color: var(--amber); } .ev.note .d { background: var(--soft); }
.ev .t { font-size: var(--t-1); line-height: 1.35; min-width: 0; }
.ev .t b { font-weight: 600; }
.ev .t small { display: block; color: var(--muted); font-size: 12px; margin-top: 1px; }
.ev .t .tag, .ev .t .chip { height: 18px; line-height: 18px; font-size: 10.5px; vertical-align: 1px; }
.ev .t .q { margin-top: 4px; background: var(--soft); border-left: 3px solid var(--line); padding: 5px 8px; border-radius: 0 6px 6px 0; font-size: 12.5px; color: var(--ink-soft); } /* quoted message */
.ev .w { font-size: 11.5px; color: var(--muted); white-space: nowrap; padding-top: 2px; font-variant-numeric: tabular-nums; }
.tl .more { text-align: center; padding: 10px 0 2px; font-size: 12.5px; }

/* ============================== 13. TABLES ============================== */
/* .table: uppercase muted head, hover rows, whole row is the click target; wrap in .tablewrap so it scrolls inside its card */
.tablewrap { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; font-size: var(--t-1); }
.table th { text-align: left; font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); font-weight: 700; padding: 8px var(--sp-3); border-bottom: 1px solid var(--line-soft); background: var(--soft); white-space: nowrap; }
.table td { padding: 10px var(--sp-3); border-bottom: 1px solid var(--line-faint); vertical-align: middle; }
.table tr:last-child td { border-bottom: 0; }
.table tbody tr { cursor: pointer; }
.table tbody tr:hover td { background: var(--soft); }
.table tbody tr.sel td { background: var(--blue-faint); }
.table th.num, .table td.num { text-align: right; }
.table td .sub { display: block; color: var(--muted); font-size: 11.5px; }
.table th.sort { color: var(--ink); } .table th.sort::after { content: " \2193"; }
.card > .tablewrap .table th:first-child, .card > .tablewrap .table td:first-child { padding-left: var(--sp-4); }
.card > .tablewrap .table th:last-child, .card > .tablewrap .table td:last-child { padding-right: var(--sp-4); }
.card > header + .tablewrap { margin-top: var(--sp-3); }
.card > .tablewrap:last-child { border-radius: 0 0 var(--r) var(--r); }

/* ============================== 14. PEEK PANEL ============================== */
/* .peek: slides in from the right so the board or list never disappears; .scrim closes it */
.peek { position: fixed; top: 0; right: 0; bottom: 0; width: 440px; max-width: 100%; background: var(--card); box-shadow: var(--peek-shadow); z-index: 40; display: flex; flex-direction: column; transform: translateX(105%); transition: transform var(--t-base) var(--ease); }
.peek.open { transform: none; }
.peek > header { display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--line-soft); }
.peek > header .kicker { font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.peek .body { overflow: auto; padding: var(--sp-4); flex: 1; }
.peek .body h2 { font-size: 18px; }
.peek .foot { padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--line-soft); display: flex; gap: var(--sp-2); align-items: center; background: var(--card); }
/* the shade behind the peek: a light wash so the board is still read through it; it fades in with the panel */
.scrim { position: fixed; inset: 0; z-index: 39; background: color-mix(in srgb, var(--scrim) 30%, transparent); opacity: 0; pointer-events: none; transition: opacity var(--t-base) var(--ease); }
.scrim.on { opacity: 1; pointer-events: auto; }
/* .hovercard: a small preview that follows the pointer */
.hovercard { position: fixed; z-index: 50; width: 300px; background: var(--card); border: 1px solid var(--line-soft); border-radius: var(--r); box-shadow: var(--lift); padding: var(--sp-3) 14px; pointer-events: none; opacity: 0; transition: opacity var(--t-fast); }
.hovercard.on { opacity: 1; }

/* ============================== 15. ASSIGN PANEL, HOLD BUTTON, TOAST ============================== */
/* .assign: the floating confirmation for a consequential action; it lists what was checked, then hold to confirm */
.assign { position: fixed; right: var(--sp-5); bottom: 96px; width: 380px; max-width: calc(100% - 2 * var(--sp-3)); background: var(--card); border: 1px solid var(--line-soft); border-radius: 14px; box-shadow: var(--float); padding: 18px 18px var(--sp-4); z-index: 60; }
.assign.static { position: static; width: auto; max-width: none; padding: 0; border: 0; box-shadow: none; z-index: auto; } /* inside a card or peek; z-index auto: as a flex or grid item the floating 60 still applied and painted it over a phone's docked Next box */
.assign .eyebrow { font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.assign h3 { margin: 4px 0 2px; font-size: var(--t-4); letter-spacing: -.01em; }
.assign .when { color: var(--ink-soft); margin-bottom: 10px; }
.assign .checks { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 0 0 14px; font-size: var(--t-1); color: var(--green); font-weight: 600; }
.assign .checks li::before { content: "\2713  "; }
.assign .checks li.no { color: var(--red); } .assign .checks li.no::before { content: "\2715  "; }
.assign .buttons { display: flex; gap: 10px; }
/* .hold: press and hold 700 ms; the fill grows across; letting go early cancels; .done turns green */
.hold { position: relative; flex: 1; overflow: hidden; border: 0; border-radius: 10px; background: var(--blue-fill); color: var(--on-dark); font: 700 15px/1.15 var(--font); padding: var(--sp-4) 18px; cursor: pointer; text-align: left; touch-action: none; user-select: none; -webkit-user-select: none; }
.hold .fill { position: absolute; inset: 0; width: 0; background: color-mix(in srgb, var(--on-dark) 28%, transparent); pointer-events: none; }
.hold .label { position: relative; z-index: 1; display: block; }
.hold small { display: block; font-weight: 500; opacity: .85; margin-top: 4px; font-size: 12.5px; }
.hold.danger { background: var(--red-fill); } /* a destructive hold (suspend, delete) reads as danger, not as the primary action */
.hold.done { background: var(--green-fill); }
.hold.done .fill { display: none; }
/* .hold.outline: a consequential hold on a view whose one blue is elsewhere (rule 1; the Sales board's Next box, a
   confirm under the Shop floor's primary): outlined like .btn, the press fills it with a tint; .danger outlines it red
   like .btn.danger; done still turns green. It was two private twins (Calendar, Shop floor) before 2026-09-24.
   The outline and the label are blue (rule 5: blue is the action colour), never a blue fill: a tall box with the plain
   1px --line border read as a card, not as the one thing to press (director, 2026-09-24). */
.hold.outline { background: var(--control); color: var(--blue-ink); border: 1.5px solid color-mix(in srgb, var(--blue-ink) 40%, var(--line)); }
.hold.outline .fill { background: var(--blue-faint); }
.hold.outline small { color: var(--ink-soft); opacity: 1; } /* the hint stays readable on the white control */
.hold.outline.danger { background: var(--control); color: var(--red); border-color: var(--red-line); }
.hold.outline.danger .fill { background: var(--red-soft); }
.hold.outline.done { background: var(--green-fill); border-color: var(--green-fill); color: var(--on-dark); }
.hold[disabled] { opacity: .5; cursor: not-allowed; }
.assign .cancel { border: 1px solid var(--line); background: var(--control); border-radius: 10px; padding: 0 var(--sp-4); font: 600 var(--t-2) var(--font); color: var(--ink); }
/* .toast: bottom-centre notice with Undo; apex.js toast() builds it */
.toast { position: fixed; left: 50%; bottom: 22px; transform: translate(-50%, 20px); opacity: 0; pointer-events: none; background: var(--navy); color: var(--on-dark); border-radius: var(--r); padding: 10px 10px 10px var(--sp-4); display: flex; align-items: center; gap: var(--sp-3); box-shadow: var(--lift); z-index: 70; transition: transform var(--t-base) var(--ease), opacity var(--t-base); font-weight: 500; max-width: calc(100% - 2 * var(--sp-3)); }
.toast.on { transform: translate(-50%, 0); opacity: 1; pointer-events: auto; }
.toast .btn { height: 30px; background: color-mix(in srgb, var(--on-dark) 12%, transparent); border-color: color-mix(in srgb, var(--on-dark) 35%, transparent); color: var(--on-dark); }
.toast .btn:hover { background: color-mix(in srgb, var(--on-dark) 22%, transparent); }
.toast .btn.icon { border-color: transparent; }
.toast kbd { background: transparent; border-color: color-mix(in srgb, var(--on-dark) 35%, transparent); color: var(--rail-ink-soft); }
/* .fab: floating action bar for a multi-select */
.fab { position: fixed; left: 50%; bottom: 22px; transform: translate(-50%, 20px); opacity: 0; pointer-events: none; background: var(--navy); color: var(--on-dark); border-radius: 14px; padding: 8px 10px 8px 14px; display: flex; align-items: center; gap: 6px; box-shadow: var(--lift); z-index: 45; transition: transform var(--t-base) var(--ease), opacity var(--t-base); white-space: nowrap; }
.fab.on { transform: translate(-50%, 0); opacity: 1; pointer-events: auto; }
.fab .count { font-weight: 700; margin-right: 6px; }
.fab .btn { background: color-mix(in srgb, var(--on-dark) 10%, transparent); border-color: transparent; color: var(--on-dark); height: 32px; }
.fab .btn.primary { background: var(--blue-fill); }
.fab kbd { background: transparent; border-color: color-mix(in srgb, var(--on-dark) 35%, transparent); color: var(--rail-ink-soft); margin-left: 4px; }
/* keyboard hints: data-key shows as a small key cap while the pointer is over a [data-keys] container (apex.js) */
[data-key] { position: relative; }
[data-key]::after { content: attr(data-key); position: absolute; top: -8px; right: -6px; font: 700 10px/14px var(--font); padding: 0 4px; border-radius: 4px; background: var(--ink); color: var(--card); opacity: 0; transition: opacity .12s; pointer-events: none; }
.keys-on [data-key]::after { opacity: 1; }
/* the row and card hover fill takes the fast step too */
.row, .table tbody tr td { transition: background-color var(--t-fast); }

/* wall mode (apex.js wallMode): the same page readable from across the shop; navigation goes, the clock shows */
body.wall .app { grid-template-columns: 1fr; }
body.wall .rail, body.wall .topbar { display: none !important; }
body.wall .page { zoom: 1.28; padding: var(--sp-3) var(--sp-4) var(--sp-4); }
.clock { display: none; font-weight: 800; font-size: var(--t-5); letter-spacing: -.02em; color: var(--navy-ink); font-variant-numeric: tabular-nums; }
body.wall .clock { display: inline-block; }

/* ============================== 16. FORMS ============================== */
/* .field: label over control; .hint under; .error paints the border red and shows the one-line message */
.field { display: grid; gap: 6px; min-width: 0; }
.field > label { font-size: 12.5px; font-weight: 600; color: var(--ink-soft); }
.field .hint { font-size: 12px; color: var(--muted); }
.field .msg { display: none; font-size: 12px; color: var(--red); font-weight: 600; }
.field.error .msg { display: block; }
.field.error .input, .field.error select, .field.error textarea { border-color: var(--red); }
.input, select, textarea { width: 100%; height: 36px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--control); padding: 0 10px; font-size: var(--t-2); color: var(--ink); }
.input::placeholder, textarea::placeholder { color: var(--faint); }
.input:hover, select:hover, textarea:hover { border-color: var(--ink-soft); }
.input:focus-visible, select:focus-visible, textarea:focus-visible { border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-soft); }
.input[disabled], select[disabled], textarea[disabled] { background: var(--soft); color: var(--muted); cursor: not-allowed; }
select { appearance: none; padding-right: 30px; background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%); background-position: calc(100% - 15px) 15px, calc(100% - 10px) 15px; background-size: 5px 5px; background-repeat: no-repeat; }
textarea { height: auto; min-height: 88px; padding: 8px 10px; resize: vertical; line-height: 1.45; }
.input.sm { height: 30px; font-size: var(--t-1); }
.form { display: grid; gap: var(--sp-4); } /* a stack of fields */
.form .two { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
/* .check: checkbox or radio with its label as one click target */
.check { display: inline-flex; align-items: center; gap: var(--sp-2); font-size: var(--t-2); cursor: pointer; }
.check input { appearance: none; width: 18px; height: 18px; margin: 0; border: 1.5px solid var(--line); border-radius: 5px; background: var(--control); display: grid; place-items: center; flex: none; }
.check input[type="radio"] { border-radius: 50%; }
.check input:checked { background: var(--blue-fill); border-color: var(--blue-fill); }
.check input[type="checkbox"]:checked::after { content: ""; width: 5px; height: 9px; border: solid var(--on-dark); border-width: 0 2px 2px 0; transform: translateY(-1px) rotate(45deg); }
.check input[type="radio"]:checked::after { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--on-dark); }
.check input[disabled] { background: var(--soft); border-color: var(--line-soft); }
.check input[disabled] + span { color: var(--muted); }
.check.block { display: flex; padding: 10px var(--sp-3); border: 1px solid var(--line-soft); border-radius: var(--r-sm); }
/* .switch: an on/off toggle for a setting */
.switch { position: relative; width: 36px; height: 20px; appearance: none; margin: 0; border-radius: var(--r-pill); background: var(--line); cursor: pointer; flex: none; transition: background .15s; }
.switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: var(--on-dark); transition: transform .15s; }
.switch:checked { background: var(--blue-fill); } .switch:checked::after { transform: translateX(16px); }

/* ============================== 17. EMPTY, LOADING, ERROR STATES ============================== */
/* .empty: one line that names the next step, with the one button; dashed so it reads as a placeholder */
.empty { border: 1px dashed var(--line); border-radius: var(--r-sm); padding: var(--sp-5) var(--sp-4); text-align: center; color: var(--muted); display: grid; gap: 10px; justify-items: center; }
.empty svg.i { width: 24px; height: 24px; color: var(--faint); }
.empty b { color: var(--ink-soft); font-weight: 600; }
/* .skel: skeleton block while loading; stack a few .skel.line inside a card */
.skel { background: linear-gradient(90deg, var(--soft-2) 25%, var(--soft) 50%, var(--soft-2) 75%); background-size: 400% 100%; border-radius: 6px; animation: skel 1.4s ease infinite; height: 14px; }
.skel.line { margin-top: 10px; } .skel.w60 { width: 60%; } .skel.w40 { width: 40%; } .skel.h32 { height: 32px; border-radius: var(--r-sm); }
@keyframes skel { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
/* .errline: one-line error with Retry; never a paragraph */
.errline { display: flex; align-items: center; gap: 10px; background: var(--red-faint); border: 1px solid var(--red-line); border-radius: var(--r-sm); padding: 10px var(--sp-3); color: var(--red); font-weight: 600; font-size: var(--t-1); }
.errline svg.i { flex: none; }
.errline span { flex: 1; min-width: 0; }
.errline .btn { height: 28px; }
.spinner { width: 18px; height: 18px; border: 2px solid var(--line-soft); border-top-color: var(--blue); border-radius: 50%; animation: spin .8s linear infinite; } /* inline wait */
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .skel, .spinner, .peek, .scrim, .toast, .fab { animation: none; transition: none; } }

/* ============================== 18. PHONE LAYER (last so it wins) ============================== */
/* Under 760px: the rail becomes a bottom tab bar, every multi-column layout stacks, wide things scroll inside
   their card, the page itself never scrolls sideways. */
@media (max-width: 760px) {
  html { overflow-x: hidden; } body { overflow-x: clip; } /* clip, not hidden: hidden makes body a scroll box and sticky headers inside it stop sticking */
  .app { grid-template-columns: 1fr; }
  .main { padding-bottom: calc(var(--tabbar) + env(safe-area-inset-bottom)); }
  /* tab bar: five tabs at most; the rest live in the command palette */
  .rail { position: fixed; top: auto; bottom: 0; left: 0; right: 0; height: auto; flex-direction: row; justify-content: space-around; padding: 6px 4px calc(6px + env(safe-area-inset-bottom)); z-index: 50; border-top: 1px solid color-mix(in srgb, var(--on-dark) 12%, transparent); }
  .rail .logo, .rail .grow, .rail .me { display: none; }
  .rail a { width: auto; min-width: 56px; padding: 6px 4px 4px; font-size: 10px; }
  .rail a:nth-child(n+7) { display: none; }
  /* top bar: title row first, then the search on its own full-width row */
  .topbar { position: static; height: auto; flex-wrap: wrap; gap: var(--sp-2); padding: 10px var(--sp-3); }
  .topbar h1 { font-size: var(--t-3); white-space: normal; }
  .topbar .crumb, .topbar .layout { display: none; }
  .topbar .sp { flex: 1; }
  .topbar .search { order: 10; width: 100%; }
  .page { padding: var(--sp-3) var(--sp-4) var(--sp-4); gap: var(--sp-4); }
  .cols, .cols.two, .facts, .form .two, .kv { grid-template-columns: 1fr; }
  .hero { display: block; padding: var(--sp-4); }
  .hero .sp { display: none; }
  .hero .next, .card .next { flex-direction: column; align-items: stretch; gap: 10px; margin-top: var(--sp-3); width: 100%; }
  .next .btn.primary { width: 100%; }
  /* A seven-dot stepper on one line, the current stage named once underneath (the Job workspace's phone rail,
     now the one rail every record uses; a sideways strip broke rule 11). */
  .journey { grid-template-columns: repeat(7, 1fr); position: relative; padding: 10px 8px 26px; overflow: visible; }
  /* Each stage stays its own positioning box, so its connector runs from its dot to the next one's; the current stage's
     name hangs centred under its own dot (a static stage would draw every connector from the rail's middle). */
  .journey > a, .journey > span { padding: 0; border-left: 0; display: grid; justify-items: center; min-height: 14px; }
  .journey > a::before, .journey > span::before { left: 50%; right: -50%; top: 6px; height: 2px; }
  .journey > :last-child::before { display: none; }
  .journey > a .dot, .journey > span .dot { position: static; width: 10px; height: 10px; border-radius: 50%; z-index: 1; }
  .journey b, .journey small { display: none; }
  .journey > .now b { display: block; position: absolute; left: 50%; top: 18px; transform: translateX(-50%); white-space: nowrap; font-size: 12.5px; }
  .journey > .now small { display: none; }
  /* an identity block's context line keeps two lines rather than losing its end (a phone column is narrow) */
  .ident .s { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; text-overflow: clip; }
  /* a pill strip scrolls sideways; its right edge fades so a cut pill ("Overdu") reads as more to swipe, not as clipped
     (T7); the padding keeps the last pill clear of the fade when the strip fits */
  .pills { overflow-x: auto; flex-wrap: nowrap; padding: 0 var(--sp-5) 4px 0; scrollbar-width: none; mask-image: linear-gradient(90deg, var(--ink) calc(100% - 36px), transparent); -webkit-mask-image: linear-gradient(90deg, var(--ink) calc(100% - 36px), transparent); }
  .pills > * { flex: 0 0 auto; }
  .toolbar { gap: var(--sp-2); }
  .banner { grid-template-columns: auto minmax(0, 1fr); }
  .banner > :nth-child(3) { grid-column: 1 / -1; }
  .peek { width: 100%; z-index: 52; }                     /* covers the tab bar: a detail is closed, not navigated away from */
  .scrim { z-index: 51; }
  .search kbd, .btn kbd { display: none; }                /* no keyboard on a phone */
  .assign { left: var(--sp-3); right: var(--sp-3); width: auto; max-width: none; bottom: calc(var(--tabbar) + var(--sp-4)); }
  .toast, .fab { bottom: calc(var(--tabbar) + var(--sp-3)); width: calc(100% - 2 * var(--sp-3)); max-width: none; justify-content: space-between; }
  .toast { white-space: normal; }
  .hovercard, [data-key]::after { display: none; }
  /* tables become a stacked list: each cell shows its column name from data-th */
  .table thead { display: none; }
  .table, .table tbody, .table tr, .table td { display: block; }
  .table tr { border-bottom: 1px solid var(--line-soft); padding: var(--sp-2) 0; }
  .table tr:last-child { border-bottom: 0; }
  .table tbody tr.sel { background: var(--blue-faint); }
  .table td { padding: 3px var(--sp-4); border: 0; display: flex; gap: var(--sp-3); }
  .table td::before { content: attr(data-th); flex: 0 0 96px; color: var(--muted); font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; }
  .table th.num, .table td.num { text-align: left; }
  .table td .sub { display: inline; margin-left: 4px; }
  h1 { font-size: 22px; } h2 { font-size: 18px; }
}

/* ============================== 19. COLOUR SCHEMES ============================== */
/* Dark is the same design: same spacing, structure, radii and the one blue primary; only the tokens change. Cards
   are elevated surfaces on a darker page, navy stays the structure (a step lighter so the rail and hero still stand
   off the page), the status colours brighten as text and keep their deeper fill behind white text, the sequential
   chart scale runs dark-to-bright so "more" still reads as "more". The whole scheme is this one block: a new scheme
   is another block like it and nothing else (docs/design/DESIGN_SYSTEM.md, "Colour schemes"). Light stays in :root.
   /shared/theme.js sets html[data-theme] before the first paint; the @media twin below covers "System" and keeps the
   two lists identical (web/tests/theme.test.mjs checks that and the WCAG AA pairs). Tokens only, no layout here.
   Both live under @media screen: paper is always light (print.css), whatever the person chose on screen. */
@media screen {
  :root[data-theme="dark"] {
    --page: #0c141c;  --card: #161f2a;  --soft: #1c2733;  --soft-2: #233241;  --control: #26364a;
    --ink: #e6edf3;  --ink-soft: #b8c7d5;  --muted: #93a6b8;  --faint: #6f8395;
    --line: #3d5166;  --line-soft: #2a3a4c;  --line-faint: #22303e;
    --navy: #163f69;  --navy-2: #1d4c7a;  --navy-3: #275c90;  --navy-ink: #b9cfe3;
    --blue: #5aa4f7;  --blue-ink: #8fc1ff;  --blue-soft: #1b3558;  --blue-faint: #142640;
    --blue-fill: #006fd6;  --blue-fill-2: #0a5fbd;
    --green: #3fcf93;  --green-soft: #10382a;  --green-fill: #00865a;
    --amber: #f0a44a;  --amber-soft: #3d2a10;  --amber-faint: #2a2114;  --amber-line: #6b4a15;  --amber-fill: #a85600;
    --red: #ff7b73;    --red-soft: #46201e;    --red-faint: #2c1917;    --red-line: #6e2b27;    --red-fill: #d12a22;
    --f-tint: #5b9df0;  --f-tint-soft: #1a2d47;  --f-tint-ink: #9dc4ff;
    --f-ppf: #f08a4a;   --f-ppf-soft: #3d2416;   --f-ppf-ink: #ffb083;
    --f-cer: #d66bb5;   --f-cer-soft: #3a1d33;   --f-cer-ink: #f2a3dc;
    --f-det: #3cc4b2;   --f-det-soft: #133330;   --f-det-ink: #7fe0d2;
    --f-wrap: #a08cf4;  --f-wrap-soft: #262044;  --f-wrap-ink: #cbbfff;
    --seq-0: #1a2532;  --seq-1: #1f3a5c;  --seq-2: #2b5c94;  --seq-3: #3b7fcc;  --seq-4: #5b9df0;  --seq-5: #a9cffa;
    --on-dark: #fff;  --rail-ink: #b9cfe3;  --rail-ink-soft: #cfe0ef;  --hero-kicker: #9fbad3;
    --scrim: rgba(0,0,0,.55);  --shade: 0, 0, 0;  --paper: #fff;  --paper-ink: #102332;
    --shadow: 0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.3);
    --lift: 0 2px 4px rgba(0,0,0,.4), 0 18px 40px rgba(0,0,0,.5);
    --peek-shadow: 0 0 0 1px var(--line-soft), -12px 0 40px rgba(0,0,0,.5);
    --shadow-sm: 0 1px 2px rgba(0,0,0,.4);  --float: 0 16px 44px rgba(0,0,0,.5);
    --av-1: #275c90;  --av-2: #40669f;  --av-3: #2f7b7b;  --av-4: #6a5aa0;  --av-5: #8a5a7a;
    --f-ink-on-fill: #0c141c;
    --shadow-2: 0 2px 4px rgba(0,0,0,.35), 0 12px 28px rgba(0,0,0,.4);
    color-scheme: dark;
  }
}
/* System: the same values when the device prefers dark and the person has not chosen Light. Keep identical to above. */
@media screen and (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --page: #0c141c;  --card: #161f2a;  --soft: #1c2733;  --soft-2: #233241;  --control: #26364a;
    --ink: #e6edf3;  --ink-soft: #b8c7d5;  --muted: #93a6b8;  --faint: #6f8395;
    --line: #3d5166;  --line-soft: #2a3a4c;  --line-faint: #22303e;
    --navy: #163f69;  --navy-2: #1d4c7a;  --navy-3: #275c90;  --navy-ink: #b9cfe3;
    --blue: #5aa4f7;  --blue-ink: #8fc1ff;  --blue-soft: #1b3558;  --blue-faint: #142640;
    --blue-fill: #006fd6;  --blue-fill-2: #0a5fbd;
    --green: #3fcf93;  --green-soft: #10382a;  --green-fill: #00865a;
    --amber: #f0a44a;  --amber-soft: #3d2a10;  --amber-faint: #2a2114;  --amber-line: #6b4a15;  --amber-fill: #a85600;
    --red: #ff7b73;    --red-soft: #46201e;    --red-faint: #2c1917;    --red-line: #6e2b27;    --red-fill: #d12a22;
    --f-tint: #5b9df0;  --f-tint-soft: #1a2d47;  --f-tint-ink: #9dc4ff;
    --f-ppf: #f08a4a;   --f-ppf-soft: #3d2416;   --f-ppf-ink: #ffb083;
    --f-cer: #d66bb5;   --f-cer-soft: #3a1d33;   --f-cer-ink: #f2a3dc;
    --f-det: #3cc4b2;   --f-det-soft: #133330;   --f-det-ink: #7fe0d2;
    --f-wrap: #a08cf4;  --f-wrap-soft: #262044;  --f-wrap-ink: #cbbfff;
    --seq-0: #1a2532;  --seq-1: #1f3a5c;  --seq-2: #2b5c94;  --seq-3: #3b7fcc;  --seq-4: #5b9df0;  --seq-5: #a9cffa;
    --on-dark: #fff;  --rail-ink: #b9cfe3;  --rail-ink-soft: #cfe0ef;  --hero-kicker: #9fbad3;
    --scrim: rgba(0,0,0,.55);  --shade: 0, 0, 0;  --paper: #fff;  --paper-ink: #102332;
    --shadow: 0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.3);
    --lift: 0 2px 4px rgba(0,0,0,.4), 0 18px 40px rgba(0,0,0,.5);
    --peek-shadow: 0 0 0 1px var(--line-soft), -12px 0 40px rgba(0,0,0,.5);
    --shadow-sm: 0 1px 2px rgba(0,0,0,.4);  --float: 0 16px 44px rgba(0,0,0,.5);
    --av-1: #275c90;  --av-2: #40669f;  --av-3: #2f7b7b;  --av-4: #6a5aa0;  --av-5: #8a5a7a;
    --f-ink-on-fill: #0c141c;
    --shadow-2: 0 2px 4px rgba(0,0,0,.35), 0 12px 28px rgba(0,0,0,.4);
    color-scheme: dark;
  }
}
