/* CMHP theme — v4 (design/DESIGN-V4-SPEC.md, distilled from design/CMHP-v4.dc.html).
   Light theme only; the dark surfaces (rail, hero, primary button) are deliberate
   accents, not a dark mode.

   The OneBloc controls (datagrid / ob-ui / ob-select / ob-lookup / ob-daterange /
   ob-tabs / OBModal / OBNotify / OBTip) are COPIED VERBATIM and are never edited or
   forked. They are matched to this design two ways only:
     1. retuning the tokens they read, scoped to their own root class, and
     2. additive host CSS below (".dg …" rules that add to, never replace, the control).
   Nothing here reaches inside a control's behaviour or DOM. */

/* ============================================================ tokens ===== */
:root {
  /* Brand accent trio. Names KEPT — the scoped control overrides below and 40-odd
     pages read them. Values retuned to the v4 crimson family. */
  --acc: #B91F27;         /* links, agreement numbers, primary accent */
  --acc-deep: #A2161D;    /* gradient bottom, control hover/ink */
  --acc-soft: #F9E9EA;    /* ~8% tint — active states, chips */
  --acc-soft2: #FCF4F5;
  --acc-bright: #E13843;  /* gradient top, lit nav dot, delta accents */
  --acc-ink: #8E1720;     /* deepest — link hover */
  --acc-line: #F0D0D2;    /* accent-tinted border (control "on" states) */

  /* ob-ui.css and the daterange/select/lookup/tabs controls read --ob-accent */
  --ob-accent: var(--acc);

  /* Ground + ink */
  --page: #F1F2F5;
  --gutter: 14px;
  --ink-deep: #0C0D10;    /* rail, hero, primary button */
  --ink-deep-2: #22242A;  /* hover on dark */
  --ink-deep-3: #25272E;  /* CTA hover */
  --ink: #101720;
  --ink-2: #3A4453;
  --muted: #9AA3AF;

  /* Rules + surfaces */
  --line: #E8E9EF;        /* card borders */
  --line-2: #F2F3F7;      /* inner dividers, row rules */
  --line-3: #EAEBF0;      /* light rules */
  --line-4: #DFE3E9;      /* stronger borders */
  --line-5: #C9CFD8;      /* hover borders, faint glyphs */
  --surface: #FFFFFF;
  --surface-2: #FAFAFC;   /* row hover, total rows */
  --surface-3: #F4F5F8;   /* inset tracks: search pill, chip rail, tiles */

  /* Semantic. --danger is the semantic red and is deliberately distinct from the
     brand crimson — a failed row must not read as "branded". */
  --success: #0F7A52;        --success-soft: #EAF7F1;   --success-bright: #3DDC97;
  --warning: #96631A;        --warning-soft: #FDF3E0;
  --danger:  #C8472F;        --danger-soft:  #FBEAE6;
  --info:    #2563EB;        --info-soft:    #EAF1FF;
  --neutral: #5A6472;        --neutral-soft: #EEF0F3;

  /* Shape */
  --r-card: 20px;
  --r-hero: 24px;
  --r-rail: 22px;
  --r-head: 18px;
  --r-tile: 18px;
  --r-control: 12px;
  --r-pill: 999px;

  /* Elevation */
  --shadow-card:  0 1px 2px rgba(16,23,32,0.03);
  --shadow-float: 0 18px 40px rgba(12,13,16,0.22);
  --shadow-hero:  0 20px 46px rgba(12,13,16,0.20);
  --shadow-cta:   0 8px 20px rgba(12,13,16,0.22);
  --shadow-head:  0 2px 10px rgba(16,23,32,0.04);

  /* The stock OneBloc neutrals the copied controls and 40 pages still read —
     realigned onto the v4 palette so a page using var(--ob-line) lands on the
     v4 rule colour instead of the old one. */
  --ob-ink: var(--ink);
  --ob-slate: var(--ink-2);
  --ob-muted: #6A7482;
  --ob-faint: var(--muted);
  --ob-line: var(--line);
  --ob-line-soft: var(--line-2);
  --ob-bg: var(--page);
  --ob-card: var(--surface);
  --ob-success: var(--success);  --ob-success-soft: var(--success-soft);
  --ob-warning: var(--warning);  --ob-warning-soft: var(--warning-soft);
  --ob-danger:  var(--danger);   --ob-danger-soft:  var(--danger-soft);
  --ob-r-control: var(--r-control);
  --ob-r-card: var(--r-card);
}

@keyframes rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* ===================================== control theming (scoped tokens) ===== */
/* Each control declares its own tokens on its root class; overriding them there
   is the sanctioned path. The copied .css files stay untouched. */
.dg, .obdr, .obsel, .oblk, .obtabs, .obsteps {
  --accent: var(--acc);
  --accent2: var(--acc-deep);
  --accent-ink: var(--acc-deep);
  --accent-weak: var(--acc-soft);
  --accent-weak2: var(--acc-soft2);
}

/* datagrid.css ships an Accounting-emerald palette and its own neutral ramp —
   retune the whole scoped set onto v4 so the grid reads like the design's table. */
/* NOTE: .dg declares its own --ink and --line, which SHADOW the :root tokens of the
   same name. Writing `--ink: var(--ink)` here would be a self-reference — invalid at
   computed-value time, which would strip every border datagrid.css draws with
   var(--line). Those two carry literals on purpose; the rest resolve to :root names
   that .dg does not shadow. */
.dg {
  --card: var(--surface);
  --ink: #101720;          /* = --ink   (literal: shadowed name, see note) */
  --ink2: var(--ink-2);
  --ink3: var(--muted);
  --ink4: var(--line-5);
  --line: #E8E9EF;         /* = --line  (literal: shadowed name, see note) */
  --line2: var(--surface-3);
  --r: var(--r-card);
  --shadow: var(--shadow-card);
  --ok-bg: var(--success-soft);   --ok-ink: var(--success);
  --info-bg: var(--info-soft);    --info-ink: var(--info);
  --warn-bg: var(--warning-soft); --warn-ink: var(--warning);
  --bad-bg: var(--danger-soft);   --bad-ink: var(--danger);
  --mute-bg: var(--neutral-soft); --mute-ink: var(--neutral);
}

/* ================================================= app shell (v4) ========= */
* { box-sizing: border-box; }
html { height: 100%; }
body {
  margin: 0;
  min-height: 100%;
  font-family: var(--ob-font, "Plus Jakarta Sans", system-ui, sans-serif);
  color: var(--ink);
  background: var(--page);
  -webkit-font-smoothing: antialiased;
}
.mono { font-family: var(--ob-mono, "JetBrains Mono", monospace); font-variant-numeric: tabular-nums; }
button { font-family: inherit; cursor: pointer; }
a { color: var(--acc); text-decoration: none; }
a:hover { color: var(--acc-ink); }

/* Page scrollbar (the design's, 10px with a 3px transparent inset) */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line-5); border-radius: 8px; border: 3px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: #BFC5CF; }

/* The shell is ordinary document flow with a sticky rail — NOT a 100vh /
   overflow:hidden box. Deliberate: the five print pages position #printArea
   absolutely against the initial containing block, so nothing in the chain
   body > .app > .shell > .content may become a containing block. Never add
   position/transform/filter/contain to those three. */
.app { display: block; min-height: 100vh; }
.shell { display: flex; gap: var(--gutter); padding: var(--gutter); align-items: flex-start; }

/* ---------- the floating dark rail ---------- */
.sidebar {
  width: 252px; flex: 0 0 252px;
  position: sticky; top: var(--gutter);
  height: calc(100vh - (var(--gutter) * 2));
  background: var(--ink-deep);
  border-radius: var(--r-rail);
  display: flex; flex-direction: column;
  overflow: hidden;
  box-shadow: var(--shadow-float);
}
.sidebar .brand { padding: 22px 20px 18px; display: flex; align-items: center; gap: 11px; text-decoration: none; }
/* The gradient tile is the design's mark for the initials fallback. When the real
   e-ONE roundel is present it IS the mark — a crimson logo on a crimson gradient
   just reads as a red blob — so `.mark.logo` drops the fill and keeps the glow. */
.sidebar .brand .mark {
  width: 32px; height: 32px; flex: 0 0 32px; border-radius: 10px;
  background: linear-gradient(150deg, var(--acc-bright), var(--acc-deep));
  color: #fff; display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 800; overflow: hidden;
  box-shadow: 0 8px 20px rgba(225, 56, 67, .4);
}
.sidebar .brand .mark.logo { background: none; border-radius: 0; box-shadow: none; }
.sidebar .brand .mark img {
  width: 100%; height: 100%; object-fit: contain; display: block;
  filter: drop-shadow(0 6px 16px rgba(225, 56, 67, .45));
}
.sidebar .brand .nm { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sidebar .brand .nm b { font-size: 13.5px; font-weight: 800; color: #fff; letter-spacing: -.2px; }
.sidebar .brand .nm small {
  font-size: 9.5px; font-weight: 700; color: rgba(255,255,255,.34);
  letter-spacing: .16em; text-transform: uppercase; white-space: nowrap;
}

.sidebar nav { flex: 1; overflow-y: auto; padding: 4px 12px 16px; display: flex; flex-direction: column; }
.sidebar nav::-webkit-scrollbar-thumb { background: rgba(255,255,255,.14); }

.navsec {
  font-size: 9.5px; font-weight: 700; color: rgba(255,255,255,.28);
  letter-spacing: .16em; text-transform: uppercase; padding: 20px 12px 8px;
}
.navsec:first-child { padding-top: 6px; }

.navItem {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 10px 12px; border-radius: var(--r-control);
  font-size: 13px; font-weight: 600; color: rgba(255,255,255,.62);
  text-decoration: none; border: 0; background: transparent;
  transition: background .14s, color .14s;
}
.navItem .dot {
  width: 6px; height: 6px; flex: 0 0 6px; border-radius: 50%;
  background: rgba(255,255,255,.18); transition: background .14s, box-shadow .14s;
}
.navItem .lb { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.navItem:hover { background: rgba(255,255,255,.06); color: #fff; }
.navItem:hover .dot { background: rgba(255,255,255,.4); }
.navItem.active { background: rgba(255,255,255,.10); color: #fff; font-weight: 700; }
.navItem.active .dot { background: var(--acc-bright); box-shadow: 0 0 0 4px rgba(225,56,67,.20); }
.navItem:focus-visible { outline: 2px solid var(--acc-bright); outline-offset: 2px; }

/* Rail footer — the session card. Carries the sign-out form. */
.sidebar .foot {
  margin: 0 12px 14px; padding: 14px; border-radius: 16px;
  background: linear-gradient(160deg, rgba(255,255,255,.10), rgba(255,255,255,.04));
  display: flex; flex-direction: column; gap: 9px;
}
.sidebar .foot .cap {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: 9.5px; font-weight: 700; color: rgba(255,255,255,.44);
  letter-spacing: .14em; text-transform: uppercase;
}
.sidebar .foot .live {
  width: 7px; height: 7px; flex: 0 0 7px; border-radius: 50%;
  background: var(--success-bright); box-shadow: 0 0 0 4px rgba(61,220,151,.16);
}
.sidebar .foot .nm {
  font-size: 13px; font-weight: 700; color: #fff;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sidebar .foot .sub { font-size: 11px; font-weight: 600; color: rgba(255,255,255,.48); }
.sidebar .foot form { display: block; }
.btn-signout {
  width: 100%; margin-top: 3px; display: inline-flex; align-items: center;
  justify-content: center; gap: 7px;
  background: rgba(255,255,255,.12); border: 0; color: #fff;
  border-radius: var(--r-pill); padding: 9px 0; font-size: 11.5px; font-weight: 700;
  transition: background .14s;
}
.btn-signout:hover { background: rgba(255,255,255,.2); }
.btn-signout svg { width: 14px; height: 14px; }

/* ---------- main column ---------- */
.maincol { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--gutter); }

/* ---------- glass header ---------- */
/* backdrop-filter makes THIS element a containing block for its own absolutely
   positioned descendants. It has none, and it is not an ancestor of any page
   content, so #printArea is unaffected. */
.apphead {
  position: sticky; top: var(--gutter); z-index: 20;
  background: rgba(255,255,255,.82);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  backdrop-filter: saturate(180%) blur(14px);
  border: 1px solid var(--line); border-radius: var(--r-head);
  padding: 12px 16px 12px 22px;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  box-shadow: var(--shadow-head);
}
.apphead .titles { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 100%; max-width: 100%; }
.apphead .crumb {
  font-size: 9.5px; font-weight: 700; color: var(--muted);
  letter-spacing: .16em; text-transform: uppercase; white-space: nowrap;
}
.apphead .ttl { font-size: 19px; font-weight: 800; letter-spacing: -.5px; text-wrap: pretty; }

/* The header agreement picker. OBLookup builds its own .ctrl/.pop markup inside this
   element, so the pill styles the CONTROL rather than the box: no padding or background
   of its own here, or the pill would sit inside a pill. The kit's file is untouched -
   this is theming only, per the OneBloc control rules. */
.apphead .searchpill { flex: 1 1 190px; min-width: 0; max-width: 340px; position: relative; }
.apphead .searchpill .ctrl {
  display: flex; align-items: center; gap: 9px;
  background: var(--surface-3); border: 0; border-radius: var(--r-pill);
  padding: 10px 16px; min-width: 0;
  font-size: 13px; font-weight: 500; color: var(--muted);
  transition: background .14s;
}
.apphead .searchpill:hover .ctrl,
.apphead .searchpill.open .ctrl { background: var(--line); color: var(--ink-2); }
.apphead .searchpill .ctrl .ic { flex: 0 0 auto; display: flex; align-items: center; }
.apphead .searchpill .ctrl input {
  flex: 1 1 auto; min-width: 0; background: none; border: 0; outline: 0; padding: 0;
  font: inherit; color: var(--ink-2);
}
.apphead .searchpill .ctrl input::placeholder { color: var(--muted); opacity: 1; }

.apphead .cta {
  background: var(--ink-deep); border: 0; color: #fff;
  border-radius: var(--r-pill); padding: 12px 20px;
  font-size: 13px; font-weight: 700; white-space: nowrap;
  text-decoration: none; box-shadow: var(--shadow-cta); transition: background .14s;
}
.apphead .cta:hover { background: var(--ink-deep-3); color: #fff; }

.apphead .who {
  display: flex; align-items: center; gap: 10px;
  padding-left: 14px; margin-left: auto; border-left: 1px solid var(--line-3);
}
.apphead .who .nm { font-size: 12.5px; font-weight: 700; white-space: nowrap; }
.apphead .who small { display: block; font-size: 10.5px; font-weight: 600; color: var(--muted); white-space: nowrap; }
.avatar {
  width: 34px; height: 34px; flex: 0 0 34px; border-radius: 12px;
  background: linear-gradient(150deg, var(--acc-bright), var(--acc-ink));
  color: #fff; display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 800;
}

/* ---------- content ---------- */
.content { flex: 1; min-width: 0; padding: 0 0 20px; animation: rise .26s ease both; }

/* The page title now lives in the glass header (from ViewData["Title"], which every
   page sets to the same words as its own h1). The h1 stays in the document for
   assistive tech and is only hidden visually — no page markup changes, no lost
   heading. `.sub` and `.actions` keep rendering. */
.pageHead { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; margin-bottom: 16px; }
.pageHead h1 {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.pageHead .sub { color: var(--muted); font-size: 12.5px; font-weight: 500; margin-top: 0; text-wrap: pretty; }
.pageHead .actions { margin-left: auto; display: flex; gap: 10px; flex-wrap: wrap; }
/* A page head holding nothing but the (now visually hidden) h1 must not leave a gap. */
.pageHead:not(:has(.sub)):not(:has(.actions)) { margin-bottom: 0; }

/* ===================================================== components ========= */

/* ---------- card / section ---------- */
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: 22px 24px; margin-bottom: var(--gutter);
  box-shadow: var(--shadow-card);
}
.card h2 { font-size: 16px; font-weight: 800; letter-spacing: -.3px; margin: 0 0 14px; }
.card h3 { font-size: 13.5px; font-weight: 700; margin: 0 0 10px; }
/* A card whose first child is a header strip gets the design's divided anatomy. */
.card > .cardhead {
  margin: -22px -24px 20px; padding: 18px 24px;
  border-bottom: 1px solid var(--line-2);
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
}
.card > .cardhead h2 { margin: 0; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 38px; padding: 0 16px; border-radius: var(--r-pill);
  font-weight: 700; font-size: 12.5px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  transition: .15s; text-decoration: none; white-space: nowrap;
}
.btn:hover { border-color: var(--line-5); background: var(--surface); color: var(--ink); }
.btn svg { width: 16px; height: 16px; }
/* Primary = the design's dark pill. */
.btn.primary {
  background: var(--ink-deep); border-color: var(--ink-deep); color: #fff;
  box-shadow: var(--shadow-cta);
}
.btn.primary:hover { background: var(--ink-deep-3); border-color: var(--ink-deep-3); color: #fff; }
/* Brand-crimson call to action, for the one action a screen is really about. */
.btn.accent { background: var(--acc); border-color: var(--acc); color: #fff; box-shadow: 0 8px 20px rgba(185,31,39,.24); }
.btn.accent:hover { background: var(--acc-deep); border-color: var(--acc-deep); color: #fff; }
/* Quiet fill — "Change", "Print statement" in the design. */
.btn.soft { background: var(--surface-3); border-color: transparent; color: var(--ink); }
.btn.soft:hover { background: var(--line); border-color: transparent; color: var(--ink); }
.btn.danger { color: var(--danger); border-color: #F0D4CD; background: var(--surface); }
.btn.danger:hover { background: var(--danger-soft); border-color: #E8C4BC; color: var(--danger); }
.btn:disabled { opacity: .5; cursor: not-allowed; }

/* ---------- status chips (pill + dot) ---------- */
/* Used by 34 pages, including inside DataGrid cells — sized to sit in a dense row. */
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 11.5px; font-weight: 700; padding: 5px 11px;
  border-radius: var(--r-pill);
  background: var(--neutral-soft); color: var(--neutral);
  white-space: nowrap;
}
.chip .d { width: 6px; height: 6px; flex: 0 0 6px; border-radius: 50%; background: currentColor; opacity: .75; }
.chip.ok   { background: var(--success-soft); color: var(--success); }
.chip.warn { background: var(--warning-soft); color: var(--warning); }
.chip.bad  { background: var(--danger-soft);  color: var(--danger); }
.chip.info { background: var(--info-soft);    color: var(--info); }
.chip.acc  { background: var(--acc-soft);     color: var(--acc-deep); }
a .chip { cursor: pointer; }

/* ---------- filter chip rail ---------- */
.chiprail {
  display: inline-flex; gap: 6px; background: var(--surface-3);
  border-radius: var(--r-pill); padding: 4px; flex-wrap: wrap;
}
.chiprail button, .chiprail a {
  display: inline-flex; align-items: center; gap: 7px;
  border: 0; background: transparent; color: var(--ink-2);
  border-radius: var(--r-pill); padding: 8px 14px;
  font-size: 12.5px; font-weight: 700; text-decoration: none; transition: .14s;
}
.chiprail button:hover, .chiprail a:hover { color: var(--ink); }
.chiprail button.on, .chiprail a.on { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-card), 0 1px 3px rgba(16,23,32,.06); }
.chiprail .n { font-family: var(--ob-mono, monospace); font-size: 10.5px; opacity: .6; }

/* ---------- stat tiles ---------- */
.statgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--gutter); margin-bottom: var(--gutter); }
.stat {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-tile); padding: 18px 20px;
  display: flex; flex-direction: column; gap: 9px;
  box-shadow: var(--shadow-card);
}
.stat .lbl {
  font-size: 9.5px; font-weight: 700; color: var(--muted);
  letter-spacing: .14em; text-transform: uppercase;
}
.stat .val {
  font-family: var(--ob-mono, monospace); font-size: 24px; font-weight: 600;
  letter-spacing: -1px; margin-top: 0; font-feature-settings: "tnum";
}
.stat .note { font-size: 11.5px; font-weight: 600; color: var(--muted); }

/* ---------- clickable tile card (report runner, launcher grids) ---------- */
.tilecard {
  display: block; text-decoration: none; color: inherit;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-tile); padding: 18px 20px;
  box-shadow: var(--shadow-card); transition: border-color .15s, box-shadow .15s;
}
.tilecard:hover { color: inherit; border-color: var(--line-5); box-shadow: 0 6px 18px rgba(16,23,32,.06); }
.tilecard .t { font-size: 15px; font-weight: 700; letter-spacing: -.2px; }
.tilecard p { margin: 6px 0 0; font-size: 13px; color: var(--muted); line-height: 1.6; }

/* ---------- dark hero panel ---------- */
.hero {
  position: relative; overflow: hidden;
  background: var(--ink-deep); border-radius: var(--r-hero);
  box-shadow: var(--shadow-hero); margin-bottom: var(--gutter);
  display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: 1px;
}
.hero::before {
  content: ""; position: absolute; top: -160px; left: -80px;
  width: 520px; height: 420px; pointer-events: none;
  background: radial-gradient(circle, rgba(225,56,67,.34), transparent 66%);
}
.hero .lead { position: relative; padding: 30px 32px 28px; display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.hero .lead .cap {
  font-size: 10px; font-weight: 700; color: rgba(255,255,255,.46);
  letter-spacing: .18em; text-transform: uppercase;
}
.hero .lead .fig {
  font-family: var(--ob-mono, monospace);
  font-size: clamp(30px, 4.4vw, 52px); font-weight: 600;
  letter-spacing: -2px; line-height: 1; color: #fff; font-feature-settings: "tnum";
}
.hero .lead .fig .cur { font-size: .42em; letter-spacing: -.02em; color: rgba(255,255,255,.5); margin-right: .28em; }
.hero .lead .note { font-size: 13px; font-weight: 600; color: rgba(255,255,255,.62); text-wrap: pretty; }
.hero .kpis { position: relative; display: flex; flex-direction: column; background: rgba(255,255,255,.04); }
.hero .kpi {
  flex: 1; padding: 20px 28px; display: flex; align-items: center;
  justify-content: space-between; gap: 14px; border-bottom: 1px solid rgba(255,255,255,.07);
}
.hero .kpi:last-child { border-bottom: 0; }
.hero .kpi .t { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.hero .kpi .lbl {
  font-size: 10px; font-weight: 700; color: rgba(255,255,255,.42);
  letter-spacing: .16em; text-transform: uppercase;
}
.hero .kpi .note { font-size: 12px; font-weight: 600; color: rgba(255,255,255,.58); text-wrap: pretty; }
.hero .kpi .v {
  font-family: var(--ob-mono, monospace); font-size: 23px; font-weight: 600;
  letter-spacing: -1px; color: #fff; font-feature-settings: "tnum";
}
.hero .kpi .v.good { color: var(--success-bright); }
.hero .kpi .v.warn { color: #F0B354; }
.hero .kpi .v.bad  { color: #FF8F7C; }
.hero .kpi .v.dim  { color: rgba(255,255,255,.42); }
@media (max-width: 900px) { .hero { grid-template-columns: minmax(0, 1fr); } }

/* ---------- empty state ---------- */
.emptystate {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 80px 24px; display: flex; flex-direction: column; align-items: center; gap: 13px;
  box-shadow: var(--shadow-card); text-align: center;
}
.emptystate .ic {
  width: 52px; height: 52px; border-radius: var(--r-tile); background: var(--surface-3);
  display: flex; align-items: center; justify-content: center; color: var(--line-5); font-size: 18px;
}
.emptystate h2 { font-size: 19px; font-weight: 800; letter-spacing: -.5px; margin: 0; }
.emptystate p { font-size: 13px; color: var(--muted); font-weight: 500; max-width: 430px; margin: 0; text-wrap: pretty; }

/* ---------- 30px initials tile (design's customer-cell mark) ---------- */
/* Helper for hand-rolled cells. The DataGrid's own .who/.av avatar is drawn by
   datagrid.js with an inline colour and is left to the control. */
.tile30 {
  width: 30px; height: 30px; flex: 0 0 30px; border-radius: 10px;
  background: var(--surface-3); color: var(--ink-2);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800;
}
.tile30.dark { background: linear-gradient(150deg, var(--ink-deep-2), var(--ink-deep)); color: #fff; }

/* ---------- plain table (small Setup lists; big grids use the DataGrid) ---- */
.tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.tbl th {
  text-align: left; font-size: 9.5px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted);
  padding: 11px 12px; border-bottom: 1px solid var(--line-2); white-space: nowrap;
}
.tbl td { padding: 13px 12px; border-bottom: 1px solid var(--line-2); vertical-align: middle; }
.tbl tr:hover td { background: var(--surface-2); }
.tbl td.num, .tbl th.num {
  text-align: right; font-family: var(--ob-mono, monospace); font-feature-settings: "tnum";
}
.tbl tfoot td, .tbl tr.total td { background: var(--surface-2); font-weight: 800; border-bottom: 0; }
.tbl .rowact { display: flex; gap: 6px; justify-content: flex-end; }
.tbl .rowact .btn { height: 30px; padding: 0 12px; font-size: 11.5px; }

/* ---------- forms (layout helpers only; fields are ob-ui.css) ------------- */
.formgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px 18px; }
.formgrid .full { grid-column: 1 / -1; }
.formfoot { display: flex; gap: 10px; margin-top: 20px; align-items: center; flex-wrap: wrap; }

/* ============================ DataGrid host CSS (additive, never a fork) === */
/* Everything below ADDS to datagrid.css to reach the design's table look. The
   control's DOM, JS and stylesheet are untouched. */

/* Column headers: 9.5px uppercase muted with .14em tracking, on white. */
.dg thead th {
  background: var(--surface);
  font-size: 9.5px; font-weight: 700; color: var(--muted);
  letter-spacing: .14em; text-transform: uppercase;
  padding: 11px 12px; border-bottom: 1px solid var(--line-2);
  /* `top` is deliberately left at datagrid.css's 0. The sticky header resolves
     against .tscroll (overflow-x:auto makes it a scroll container), NOT the
     viewport — any offset here floats the header down over the first rows. */
}
.dg thead th.sortable:hover { color: var(--ink-2); }

/* Body rows: 12.5px on 1px #F2F3F7 rules, #FAFAFC hover. */
.dg tbody td { padding: 12px; border-bottom: 1px solid var(--line-2); font-size: 12.5px; }
.dg.compact tbody td { padding: 8px 12px; }
.dg tbody tr:hover { background: var(--surface-2); }
/* The design's generous card inset, without inflating every interior column. */
.dg thead th:first-child, .dg tbody td:first-child { padding-left: 22px; }
.dg thead th:last-child,  .dg tbody td:last-child  { padding-right: 22px; }
.dg .cbcol { padding-left: 22px !important; }

/* Identifiers: mono, crimson. Money: mono, right-aligned, 600 when it is the figure. */
.dg .idcell .no { font-family: var(--ob-mono, monospace); font-size: 12px; font-weight: 600; color: var(--acc); }
.dg td.num, .dg td.amt { font-family: var(--ob-mono, monospace); font-feature-settings: "tnum"; }
.dg td.amt { font-weight: 600; font-size: 12.5px; }
.dg td.rowno, .dg .date { font-family: var(--ob-mono, monospace); font-size: 11.5px; }
.dg .who .nm { font-weight: 700; font-size: 12.5px; }
.dg .who .em { font-family: var(--ob-mono, monospace); font-size: 10.5px; color: var(--muted); }
.dg .av { width: 30px; height: 30px; border-radius: 10px; font-size: 11px; font-weight: 800; }

/* Status pills: 11px/700, padding 5/11, fully round. */
.dg .pill { padding: 5px 11px; border-radius: var(--r-pill); font-size: 11px; font-weight: 700; }

/* Card + toolbar + footer strip. */
.dg .head h1 { font-size: 17px; font-weight: 800; letter-spacing: -.3px; }
.dg .head .sub { color: var(--muted); font-size: 12.5px; }
.dg .card { box-shadow: var(--shadow-card); }
.dg .toolbar { padding: 14px 22px; border-bottom-color: var(--line-2); }
.dg .foot { padding: 14px 22px; background: var(--surface-2); border-top-color: var(--line-3); }
.dg .foot .cnt { font-family: var(--ob-mono, monospace); font-size: 11.5px; }
.dg .filterbar { padding: 14px 16px; }
.dg .empty h3 { font-size: 17px; font-weight: 800; letter-spacing: -.4px; }
.dg .empty p { color: var(--muted); font-size: 13px; }

/* Controls inside the grid pick up pill geometry + the crimson "on" border that
   datagrid.css hardcodes as emerald (#B6E2D2 is a literal there, not a token). */
.dg .ctrl, .dg .fbtn2, .dg .tbtn, .dg .pg { border-radius: var(--r-control); }
.dg .ctrl.on, .dg .fbtn2.on, .dg .tbtn.prim { border-color: var(--acc-line); }
.dg .selpill { border-color: var(--acc-line); border-radius: var(--r-control); }
.dg .day.today:not(.edge) { box-shadow: inset 0 0 0 1.5px var(--acc-line); }
.dg .split .main, .dg .split .caret { font-weight: 700; }

/* The grid's own scrollbars are emerald literals in the control — retint. */
.dg * { scrollbar-color: var(--line-5) transparent; }
.dg ::-webkit-scrollbar-thumb { background: var(--line-5); }
.dg ::-webkit-scrollbar-thumb:hover { background: #BFC5CF; }

/* Status-pill vocabularies the control does not ship.
   datagrid.css carries Title-case business statuses only (Paid/Open/…), so CMHP's
   ALL-CAPS codes would otherwise render an uncoloured pill. Additive host CSS. */
/* ops queues */
.dg .pill.RECEIVED, .dg .pill.QUEUED { background: var(--info-soft); color: var(--info); }
.dg .pill.PROCESSING, .dg .pill.POSTING { background: var(--warning-soft); color: var(--warning); }
.dg .pill.PROCESSED, .dg .pill.POSTED { background: var(--success-soft); color: var(--success); }
.dg .pill.FAILED { background: var(--danger-soft); color: var(--danger); }
.dg .pill.DEAD { background: var(--ink-2); color: #fff; }
/* agreement standing — live book */
.dg .pill.ACTIVE { background: var(--success-soft); color: var(--success); }
.dg .pill.SETTLED { background: var(--success-soft); color: var(--success); }
/* recovery closures: REPOSSESSED reads amber-red (live trouble, not yet closed);
   WRITTEN_OFF is slate (gone from the book); the disposals and the voluntary
   termination are neutral history; VOID never counted. */
.dg .pill.REPOSSESSED { background: #FAE7DD; color: #B3491C; }
.dg .pill.WRITTEN_OFF { background: #E7EAEF; color: var(--ink-2); }
.dg .pill.CLOSED_SHORTFALL, .dg .pill.CLOSED_SURPLUS { background: var(--neutral-soft); color: var(--neutral); }
.dg .pill.VT_TERMINATED { background: var(--neutral-soft); color: var(--neutral); }
.dg .pill.VOID, .dg .pill.CANCELLED { background: var(--neutral-soft); color: var(--neutral); }
/* collections cases */
.dg .pill.OPEN, .dg .pill.IN_PROGRESS { background: var(--info-soft); color: var(--info); }
.dg .pill.PROMISED { background: var(--warning-soft); color: var(--warning); }
.dg .pill.BROKEN, .dg .pill.ESCALATED { background: var(--danger-soft); color: var(--danger); }
.dg .pill.RESOLVED, .dg .pill.CLOSED { background: var(--success-soft); color: var(--success); }
/* post-dated cheques */
.dg .pill.HELD { background: var(--neutral-soft); color: var(--neutral); }
.dg .pill.BANKED { background: var(--warning-soft); color: var(--warning); }
.dg .pill.CLEARED { background: var(--success-soft); color: var(--success); }
.dg .pill.BOUNCED { background: var(--danger-soft); color: var(--danger); }
/* settlement quotations */
.dg .pill.ISSUED { background: var(--info-soft); color: var(--info); }
.dg .pill.TAKEN, .dg .pill.COMPLETED { background: var(--success-soft); color: var(--success); }
.dg .pill.EXPIRED { background: var(--warning-soft); color: var(--warning); }

/* ================================================== print + motion ======== */
/* The five print pages (statement, payment history, settlement quote, statutory
   notice, receipt) use `body * {visibility:hidden}` + `#printArea{position:absolute}`.
   That resolves against the initial containing block ONLY while no ancestor is a
   containing block — and `rise` briefly applies a transform to .content while
   those pages call window.print() on load. Killing animation in print media
   guarantees the printed rendering has no transform anywhere in the chain. */
@media print {
  .sidebar, .apphead { display: none !important; }
  .app, .shell, .maincol, .content {
    display: block !important;
    position: static !important;
    transform: none !important;
    animation: none !important;
    overflow: visible !important;
    padding: 0 !important; margin: 0 !important; gap: 0 !important;
    min-height: 0 !important; height: auto !important;
  }
  body { background: #fff; }
}
@media (prefers-reduced-motion: reduce) {
  .content { animation: none; }
  .navItem, .btn, .chiprail button, .chiprail a { transition: none; }
}

/* ============================================ the menu button + backdrop === */
/* One control, two jobs — see cmhp-shell.js. Desktop: hide/show the pinned rail.
   Phone: open/close the rail as a drawer. */
.navtoggle {
  flex: 0 0 auto; width: 38px; height: 38px; margin-right: 2px;
  display: inline-flex; align-items: center; justify-content: center;
  background: #fff; border: 1px solid var(--line); border-radius: 11px;
  color: var(--ink); cursor: pointer; padding: 0;
  transition: background .15s ease, border-color .15s ease;
}
.navtoggle:hover { background: var(--acc-soft); border-color: var(--acc-line); }
/* .titles is flex:1 1 100% by design (the v4 header gives the title its own row), so
   without this the button would take a line of its own above it. Scoped to the
   adjacency, so a header rendered without a toggle keeps the original behaviour. */
.apphead .navtoggle + .titles { flex: 1 1 calc(100% - 56px); }
.navtoggle:focus-visible { outline: 2px solid var(--acc-bright); outline-offset: 2px; }
.navtoggle .bars { display: flex; flex-direction: column; gap: 3.5px; width: 16px; }
.navtoggle .bars i { display: block; height: 2px; border-radius: 2px; background: currentColor; }
/* the middle bar shortens when the rail is away — a hint of state, no icon swap */
.navtoggle .bars i:nth-child(2) { width: 11px; transition: width .18s ease; }
.navhidden .navtoggle .bars i:nth-child(2) { width: 16px; }

.navscrim {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(16, 18, 27, .5);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.navscrim[hidden] { display: none; }

/* desktop: the rail folds away and the content takes the full width */
.navhidden .sidebar { display: none; }

/* ===================================================== responsive ========= */
/* Desktop-first (counter PCs). At 1000px and below the rail stops being part of
   the layout and becomes an OFF-CANVAS DRAWER: the old behaviour dropped ~35 nav
   items on top of every page, so a phone had to scroll past the whole menu to
   reach the content. Collapsing to an icon strip is not an option either — the v4
   nav item is a dot + label, and an icon-only rail would carry no information. */
@media (max-width: 1000px) {
  .shell { flex-direction: column; padding: 12px; gap: 12px; }

  .sidebar {
    position: fixed; z-index: 61; top: 0; left: 0;
    width: min(86vw, 300px); flex: none;
    height: 100dvh; max-height: none;
    border-radius: 0 var(--r-rail) var(--r-rail) 0;
    transform: translateX(-100%);
    transition: transform .22s cubic-bezier(.4, 0, .2, 1);
    /* the drawer is the ONE thing allowed to sit above the page */
    box-shadow: 0 24px 60px rgba(16, 18, 27, .45);
  }
  body.navopen .sidebar { transform: translateX(0); }
  /* the desktop hide has no meaning here — the drawer owns visibility */
  .navhidden .sidebar { display: flex; }

  .maincol { width: 100%; min-width: 0; }
  .dg thead th { top: 0; }
}

@media (max-width: 640px) {
  .shell { padding: 10px; gap: 10px; }
  /* Two rows, not four: [menu · title · avatar] then [search · pay].
     The desktop pairing rule gives .titles a calc(100% - 56px) basis, which would
     wrap the avatar onto a line of its own — override it back to auto here. */
  .apphead { padding: 10px 12px; gap: 8px; flex-wrap: wrap; }
  /* Row one is [menu · title · avatar], row two is [search · pay].
     basis 0 rather than auto, so a long title ("Restructure — 1010200072350770")
     wraps inside the block instead of sizing to its content and shoving the avatar
     down; min-width keeps it from collapsing so far that the search pill slides up
     beside it and leaves the CTA stranded alone on row three. */
  .apphead .navtoggle + .titles { flex: 1 1 0; min-width: 55%; }
  .apphead .titles { min-width: 0; }
  .apphead .titles .ttl { font-size: 18px; line-height: 1.25; }
  .apphead .who { order: 2; margin-left: auto; padding-left: 0; border-left: 0; }
  /* the name beside the avatar is the first thing to go — the avatar still says who is signed in */
  .apphead .who .nm { display: none; }
  /* search and the CTA share the second row rather than taking one each */
  .apphead .searchpill { order: 3; flex: 1 1 55%; min-width: 0; }
  .apphead .cta { order: 4; flex: 0 0 auto; white-space: nowrap; }

  .card { padding: 16px 14px; }
  .card > .cardhead { margin: -16px -14px 14px; padding: 14px; }

  /* page headers stack instead of squeezing the action row off the edge */
  .pageHead { flex-direction: column; align-items: flex-start; gap: 10px; }
  .pageHead .actions { flex-wrap: wrap; width: 100%; }

  /* money tiles: two up on a phone. The base rule is auto-fit minmax(200px, 1fr),
     which at 375px resolves to ONE column and turns six tiles into a long scroll. */
  .statgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .stat .val { font-size: 19px; }

  /* forms go single-column — a two-column grid at 375px gives 150px fields */
  .formgrid { grid-template-columns: minmax(0, 1fr); }

  .tblwrap, .scrollx { overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/* ---------- wide content scrolls inside its own box, never off the page ----------
   Deliberately NOT `html, body { overflow-x: hidden }`: that stops the page scrolling
   sideways but makes the clipped columns UNREACHABLE, and it turns body into a scroll
   container, which is where `position: sticky` headers go wrong. Fix the containers
   instead, and the page has nothing to scroll. */
@media (max-width: 1000px) {
  /* The tab strip: ~9 tabs on the agreement page run to ~880px at 375px wide, so the
     last few (Guarantors, Documents, History) could not be reached at all. Scoped host
     CSS — ob-tabs.js/css are copied controls and are never edited. */
  .obtabs > nav {
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    flex-wrap: nowrap;
  }
  .obtabs > nav::-webkit-scrollbar { height: 0; }
  .obtabs > nav > * { flex: 0 0 auto; }

  /* Data tables: a block box scrolls at its natural width rather than being clipped.
     ~30 `.tbl` tables across 12 pages carry no wrapper element, so this has to work
     from the table itself. */
  .card > .tbl, .card > table.tbl, section > .tbl {
    display: block; overflow-x: auto; -webkit-overflow-scrolling: touch;
    max-width: 100%;
  }
}

/* ============================================================
   Loan record — the money band
   The four figures an operator opens this page for. Deliberately
   heavier than the contract strip beneath it: the page used to
   give equal weight to what the machine cost in 2023 and to how
   far behind the customer is today.
   ============================================================ */
.moneyband {
  display: grid; gap: 14px; margin: 0 0 14px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.moneyband .mb-item {
  background: var(--surface); border: 1px solid var(--line); border-radius: 16px;
  padding: 18px 20px; min-width: 0;
}
.moneyband .lbl {
  font-size: 11px; font-weight: 700; letter-spacing: .7px; text-transform: uppercase;
  color: var(--muted); margin-bottom: 8px;
}
.moneyband .val { font-size: 28px; font-weight: 800; letter-spacing: -1px; line-height: 1.1; }
.moneyband .note { margin-top: 7px; font-size: 12px; color: var(--muted); line-height: 1.45; }
/* arrears carries the only colour on the band — one red number, so it means something */
.moneyband .is-bad { border-color: #F0D3D0; background: #FDF7F6; }
.moneyband .is-bad .val { color: var(--acc, #B91F27); }
.moneyband .is-ok .val { color: #1B7F5A; }

.moneyband .mb-bar {
  margin-top: 12px; height: 7px; border-radius: 99px; background: var(--surface-3);
  overflow: hidden;
}
.moneyband .mb-bar > span { display: block; height: 100%; border-radius: 99px; background: #1B7F5A; }

/* the contract as written — facts, so they read as a strip and not as headlines */
.card.termstrip {
  display: flex; flex-wrap: wrap; gap: 10px 30px; align-items: baseline;
  padding: 16px 20px; margin-bottom: 14px;
}
.card.termstrip .ts-item { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.card.termstrip .lbl {
  font-size: 11px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--muted);
}
.card.termstrip .v { font-size: 14px; font-weight: 700; }

/* the plan's one-line answer, above the wall of rows */
.plansum {
  margin: 0 0 14px; font-size: 13.5px; color: var(--muted); line-height: 1.6;
}
.plansum strong { color: var(--ink-2); font-weight: 700; }

@media (max-width: 640px) {
  .moneyband .val { font-size: 24px; }
  .card.termstrip { gap: 10px 18px; }
}

/* ============================================================
   CRM record patterns (CMHP-owned, 2026-09-06)
   Added because the app read as a competent admin theme rather
   than a record system: read and edit were different pages,
   Save sat below thirty fields, every card carried identical
   weight, and nothing was ever collapsed. The OneBloc kit is
   untouched throughout - these are new patterns beside it, not
   a fork of it.
   ============================================================ */

/* ---------- 1. the save bar follows you ----------
   Scoped to `form` on purpose: .formfoot is also the action row on DETAIL pages
   (Customers/Detail, Loans/Detail), where pinning a row of links to the viewport
   would be wrong. A save bar belongs to a form; those do not. */
form .formfoot {
  position: sticky; bottom: 0; z-index: 20;
  margin: 20px calc(var(--gutter) * -1) 0;
  padding: 14px var(--gutter);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--line);
  justify-content: flex-end;
}
/* a hint of lift only once there is something scrolled under it */
form .formfoot::before {
  content: ""; position: absolute; left: 0; right: 0; top: -18px; height: 18px;
  background: linear-gradient(to top, color-mix(in srgb, var(--ink) 5%, transparent), transparent);
  pointer-events: none;
}
form .formfoot .spacer { margin-right: auto; }

/* ---------- 2. cards stop shouting in unison ----------
   Everything was one white box with one border and one radius, so nothing on a
   page was ever the point. */
.card.is-primary {
  border-color: var(--line-4);
  box-shadow: 0 1px 2px rgba(16, 23, 32, .04), 0 12px 28px -14px rgba(16, 23, 32, .18);
}
.card.is-quiet {
  background: var(--surface-2); box-shadow: none; border-color: var(--line-2);
}
.card.is-quiet h2 { color: var(--ink-2); }

/* ---------- 3. sections that fold ----------
   Native <details>, so it keeps keyboard and screen-reader behaviour for free and
   needs no JavaScript. A closed section still answers what is inside it. */
details.card { padding: 0; }
details.card > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; gap: 12px;
  padding: 18px 24px; border-radius: var(--r-card);
}
details.card > summary::-webkit-details-marker { display: none; }
details.card > summary:hover { background: var(--surface-2); }
details.card > summary h2 { margin: 0; flex: 0 0 auto; }
details.card > summary .sumnote {
  font-size: 12.5px; color: var(--muted); font-weight: 500; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
details.card > summary .caret {
  margin-left: auto; flex: 0 0 auto; color: var(--muted);
  transition: transform .16s ease;
}
details.card[open] > summary { border-bottom: 1px solid var(--line-2); border-radius: var(--r-card) var(--r-card) 0 0; }
details.card[open] > summary .caret { transform: rotate(90deg); }
details.card[open] > summary .sumnote { display: none; }
details.card > .dbody { padding: 20px 24px 22px; }

/* ---------- 4. the record and its related rail ----------
   A record page is the record plus what hangs off it. Stacking everything
   vertically behind tabs buries the second half. */
.recordgrid { display: grid; gap: var(--gutter); align-items: start; }
@media (min-width: 1100px) {
  .recordgrid { grid-template-columns: minmax(0, 1fr) 320px; }
  .recordgrid > .rail { position: sticky; top: 16px; }
}
.rail .card { margin-bottom: 12px; }
.rail .card h2 { font-size: 13px; }
.railrow {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  padding: 8px 0; border-bottom: 1px solid var(--line-2); font-size: 13px;
}
.railrow:last-child { border-bottom: 0; }
.railrow .k { color: var(--muted); }
.railrow .v { font-weight: 700; text-align: right; min-width: 0; }

/* ============================================================
   LIGHT SHELL (2026-09-06) — the Pivora-reference look.
   Appended as a LAYER, not a rewrite: every selector below
   matches one above at the same specificity, so source order
   does the work and deleting this block restores the dark rail
   exactly. The accent stays e-ONE crimson throughout - the
   reference's purple is its brand, not ours.
   ============================================================ */
:root {
  --page: #F6F7F9;          /* a touch lighter than the dark shell wanted */
  --rail: #FFFFFF;
  --rail-line: #ECEDF2;
  --rail-ink: #4A5261;      /* resting nav label */
  --rail-ink-on: #101720;   /* active / hover */
  --rail-cap: #A8AEBA;      /* section captions */
  --shadow-float: 0 1px 2px rgba(16,23,32,.04), 0 18px 40px -24px rgba(16,23,32,.22);
  --shadow-card: 0 1px 2px rgba(16,23,32,.035), 0 10px 24px -18px rgba(16,23,32,.16);
}

/* ---------- the rail turns white ---------- */
.sidebar { background: var(--rail); border: 1px solid var(--rail-line); }
.sidebar .brand .nm b { color: var(--rail-ink-on); }
.sidebar .brand .nm small { color: var(--rail-cap); }
.sidebar nav::-webkit-scrollbar-thumb { background: #E3E5EB; }
.navsec { color: var(--rail-cap); }

.navItem { color: var(--rail-ink); }
.navItem .dot { background: #D7DAE2; }
.navItem:hover { background: var(--surface-3); color: var(--rail-ink-on); }
.navItem:hover .dot { background: #B8BDC8; }
/* the active row is the one place the brand shows in the rail */
.navItem.active { background: var(--acc-soft, #F9E9EA); color: var(--acc-deep, #791821); font-weight: 700; }
.navItem.active .dot { background: var(--acc); box-shadow: 0 0 0 4px rgba(185,31,39,.14); }

.sidebar .foot {
  background: var(--surface-2); border: 1px solid var(--rail-line);
}
.sidebar .foot .cap { color: var(--rail-cap); }
.sidebar .foot .nm { color: var(--rail-ink-on); }
.sidebar .foot .sub, .sidebar .foot small { color: var(--muted); }
/* the sign-out control carries its OWN class, not .btn - it was white on white
   until a contrast sweep of the rail turned it up */
.sidebar .foot .btn,
.sidebar .foot .btn-signout {
  background: var(--surface); border: 1px solid var(--line-4); color: var(--ink-2);
}
.sidebar .foot .btn:hover,
.sidebar .foot .btn-signout:hover { background: var(--surface-3); color: var(--ink); }

/* ---------- primary actions take the brand, as the reference does ---------- */
.btn.primary { background: var(--acc); border-color: var(--acc); }
.btn.primary:hover { background: var(--acc-deep); border-color: var(--acc-deep); }
.apphead .cta { background: var(--acc); }
.apphead .cta:hover { background: var(--acc-deep); }

/* ---------- 5. the KPI card ----------
   Icon square, label, the number, a delta pill and what it is measured against -
   the reference's most useful idea. A figure with no comparison tells you nothing
   about whether to act. */
.kpirow {
  display: grid; gap: var(--gutter); margin-bottom: var(--gutter);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
/* SCOPED to .kpirow, and that is not fussiness: `.kpi` ALREADY EXISTS as the hero's
   stat rows on the Overview. A bare `.kpi` rule here painted them white with a border
   and a radius on a black card - three white pills with invisible labels, which is
   exactly how the landing page looked until Darren sent a screenshot of it. */
.kpirow > .kpi {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 18px 20px; box-shadow: var(--shadow-card); min-width: 0;
}
.kpirow .kpi .top { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.kpirow .kpi .ico {
  width: 32px; height: 32px; flex: 0 0 32px; border-radius: 10px;
  background: var(--surface-3); color: var(--ink-2);
  display: flex; align-items: center; justify-content: center;
}
.kpirow .kpi .ico svg { width: 17px; height: 17px; }
.kpirow .kpi .k { font-size: 13px; font-weight: 700; color: var(--ink-2); min-width: 0; }
.kpirow .kpi .figure { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.kpirow .kpi .v { font-size: 27px; font-weight: 800; letter-spacing: -1.1px; line-height: 1.05; }
.kpirow .kpi .vs { margin-left: auto; font-size: 11.5px; color: var(--muted); white-space: nowrap; }

/* the delta pill — green up, red down, grey flat. The ARROW carries the direction
   so it still reads without colour. */
.delta {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 3px 8px; border-radius: 99px;
  font-size: 11.5px; font-weight: 700; line-height: 1;
}
.delta.up   { background: var(--success-soft); color: var(--success); }
.delta.down { background: var(--danger-soft);  color: var(--danger); }
.delta.flat { background: var(--neutral-soft); color: var(--neutral); }

/* ---------- 6. the segmented period control ---------- */
.seg {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--surface-3); border-radius: 99px;
}
.seg > a, .seg > button {
  border: 0; background: none; cursor: pointer;
  padding: 6px 13px; border-radius: 99px;
  font-size: 12px; font-weight: 700; color: var(--muted);
  text-decoration: none; transition: background .14s, color .14s;
}
.seg > a:hover, .seg > button:hover { color: var(--ink-2); }
.seg > .on, .seg > [aria-current="true"] {
  background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(16,23,32,.07);
}

/* ---------- freshness, which end-of-day data badly needs ---------- */
.freshness {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12.5px; font-weight: 600; color: var(--success);
}
.freshness.stale { color: var(--warning); }

/* ============================================================
   Record layout — identity rail LEFT, work area right
   (Darren's second reference: a loan record from a lending CRM)
   The reference has TOP navigation, so its identity panel can sit
   on the left. We have a left nav rail already — but the shell's
   hamburger collapses it on desktop and remembers the choice, so
   this column costs no room to anyone who wants it back.
   ============================================================ */
@media (min-width: 1100px) {
  .recordgrid { grid-template-columns: 300px minmax(0, 1fr); }
  .recordgrid > .rail { position: sticky; top: 16px; order: -1; }
}
.recordgrid > .rmain { min-width: 0; }

/* the identity card — who this is, and how to reach them */
.idcard { text-align: left; }
.idname { font-size: 17px; font-weight: 800; letter-spacing: -.4px; line-height: 1.25; }
.idmeta { margin-top: 3px; font-size: 12px; color: var(--muted); }
.idacts { display: flex; gap: 8px; margin-top: 14px; }
.idact {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 10px 6px; border-radius: 12px;
  background: var(--surface-3); border: 1px solid transparent;
  font-size: 11px; font-weight: 700; color: var(--ink-2); text-decoration: none;
  transition: background .14s, border-color .14s;
}
.idact:hover { background: var(--surface); border-color: var(--line-4); }
.idact .g { font-size: 15px; line-height: 1; }
/* the one action a collections desk uses most carries the brand */
.idact.is-call { background: var(--acc-soft, #F9E9EA); color: var(--acc-deep, #791821); }
.idact.is-call:hover { background: var(--surface); border-color: var(--acc-line, #F0D0D2); }
.idphone { margin-top: 10px; font-size: 12.5px; color: var(--muted); text-align: center; }

/* The money band becomes ONE bordered card with dividers, as the reference groups
   its Docs Owed / Pending / Accepted tiles. Same four figures, far less furniture
   than four separately-bordered floating cards. Restyled in place rather than
   renamed, so the earlier .moneyband rules for .lbl / .val / .note still apply. */
.moneyband {
  display: grid; gap: 0;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); box-shadow: var(--shadow-card); overflow: hidden;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.moneyband > .mb-item {
  background: none; border: 0; border-radius: 0;
  border-right: 1px solid var(--line-2);
  padding: 18px 20px;
}
.moneyband > .mb-item:last-child { border-right: 0; }
.moneyband > .mb-item.is-bad { background: #FDF7F6; }
.moneyband > .mb-item.is-bad .val { color: var(--acc, #B91F27); }

/* the activity timeline — the same audit rows, read in half the time */
.timeline { list-style: none; margin: 0; padding: 0 0 0 18px; position: relative; }
.timeline::before {
  content: ""; position: absolute; left: 4px; top: 6px; bottom: 6px;
  width: 2px; background: var(--line-2); border-radius: 2px;
}
.timeline > li { position: relative; padding: 0 0 16px; }
.timeline > li:last-child { padding-bottom: 0; }
.timeline > li::before {
  content: ""; position: absolute; left: -18px; top: 5px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--line-5);
}
.timeline > li:first-child::before { border-color: var(--acc); }
.tl-when { font-size: 11px; color: var(--muted); }
.tl-what { font-size: 13px; margin-top: 2px; line-height: 1.45; }
.tl-what strong { font-weight: 700; }
.tl-detail { font-size: 12px; color: var(--muted); margin-top: 3px; line-height: 1.45; }

/* tab count badges — nine tabs and no way to tell which hold anything */
.tabcount {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px; margin-left: 6px;
  border-radius: 99px; background: var(--surface-3); color: var(--ink-2);
  font-size: 10.5px; font-weight: 800; line-height: 1;
}

/* ============================================================
   Sidebar — icons, and an active row you can find at a glance
   The rail used to mark every destination with the SAME 6px dot,
   so thirty-six items were thirty-six identical rows and you read
   the label every time. Icons are what make the reference's menu
   scan; the dot was the reason ours did not.
   ============================================================ */
.navItem .ni {
  width: 18px; height: 18px; flex: 0 0 18px;
  color: var(--muted); transition: color .14s;
}
.navItem { position: relative; gap: 10px; padding-left: 14px; }
.navItem:hover .ni { color: var(--ink-2); }

/* the active row: brand tint, brand icon, and a bar on the leading edge -
   the reference's own device, and the fastest thing in a list to find */
.navItem.active .ni { color: var(--acc); }
.navItem.active::before {
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 3px; height: 18px; border-radius: 0 3px 3px 0; background: var(--acc);
}

/* section captions sit back rather than shout */
.navsec {
  font-size: 10px; letter-spacing: .12em; color: #B4B9C4;
  padding: 18px 14px 6px; font-weight: 700;
}

/* a count on the right, for the two lists whose size is the news */
.navItem .cnt {
  margin-left: auto; flex: 0 0 auto;
  font-size: 11px; font-weight: 700; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.navItem.active .cnt { color: var(--acc-deep, #791821); }

/* the brand block gets the reference's breathing room */
.sidebar .brand { padding: 20px 18px 14px; border-bottom: 1px solid var(--rail-line); margin-bottom: 6px; }

/* ============================================================
   Sidebar + header, matched to the reference close-ups
   ============================================================ */

/* ---- brand row, with the fold control on the rail ---- */
.sidebar .brandrow {
  display: flex; align-items: center; gap: 8px;
  padding: 16px 14px 14px; border-bottom: 1px solid var(--rail-line); margin-bottom: 10px;
}
.sidebar .brandrow .brand { flex: 1 1 auto; min-width: 0; padding: 0; border: 0; margin: 0; }
.railfold {
  flex: 0 0 auto; width: 28px; height: 28px; border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 0; cursor: pointer; color: var(--muted);
  transition: background .14s, color .14s;
}
.railfold svg { width: 16px; height: 16px; }
.railfold:hover { background: var(--surface-3); color: var(--ink-2); }

/* ---- the account card, at the FOOT of the rail ----
   It sat at the top for one build, where the reference puts it. The reference has
   eight nav rows; this has thirty-six, so at the top it shoved the whole menu down
   and took the first thing the eye lands on for a name the operator already knows.
   It is back at the bottom, where it was before and where everyone here looks for
   it — and the disclosure is gone with it, because the menu behind it held exactly
   one item and a fold that hides one button is only a click in the way. */
.usercard { margin: 0; padding-top: 10px; border-top: 1px solid var(--rail-line); }
.usercard .uctop { display: flex; align-items: center; gap: 10px; padding: 2px 2px 9px; }
.usercard .av {
  width: 30px; height: 30px; flex: 0 0 30px; border-radius: 50%;
  background: linear-gradient(150deg, var(--acc-bright, #E13843), var(--acc-deep, #791821));
  color: #fff; font-size: 11px; font-weight: 800;
  display: flex; align-items: center; justify-content: center;
}
.usercard .who { min-width: 0; display: flex; flex-direction: column; }
.usercard .who b { font-size: 12.5px; font-weight: 700; color: var(--rail-ink-on); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.usercard .who small { font-size: 10.5px; color: var(--muted); }
/* the sign-out control carries its OWN class, not .btn — it was white on white until
   a contrast sweep of the rail turned it up, and the .sidebar .foot selector that used
   to reach it died with the block it named */
.usercard .btn-signout {
  width: 100%; margin: 0; display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  background: var(--surface); border: 1px solid var(--line-4); color: var(--ink-2);
  border-radius: var(--r-control, 10px); padding: 9px 0;
  font-size: 12px; font-weight: 700; cursor: pointer;
  transition: background .14s, color .14s, border-color .14s;
}
.usercard .btn-signout:hover { background: var(--surface-3); color: var(--ink); }
.usercard .btn-signout svg { width: 14px; height: 14px; }

/* ---- the active bar sits on the RAIL'S edge, as the reference has it ---- */
.sidebar nav { padding-left: 0; }
.navItem { margin-left: 12px; margin-right: 12px; padding-left: 12px; }
.navItem.active::before { left: -12px; height: 22px; width: 3px; border-radius: 0 3px 3px 0; }

/* ---- pinned rail footer: Settings / End of day ---- */
.railfoot { margin-top: auto; padding: 10px 12px 14px; border-top: 1px solid var(--rail-line); }
.raillink {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px; border-radius: var(--r-control, 10px);
  font-size: 13px; font-weight: 600; color: var(--rail-ink); text-decoration: none;
  transition: background .14s, color .14s;
}
.raillink:hover { background: var(--surface-3); color: var(--rail-ink-on); }
.raillink .ni { width: 18px; height: 18px; flex: 0 0 18px; color: var(--muted); }
.raillink .lb { flex: 1; min-width: 0; }
.raillink .ch { width: 14px; height: 14px; flex: 0 0 14px; color: var(--muted); }

/* ---- header: divider + the icon-button cluster ---- */
.headdiv { width: 1px; height: 24px; background: var(--line); flex: 0 0 1px; margin: 0 2px; }
.headacts { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.hbtn {
  width: 38px; height: 38px; border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  transition: background .14s, border-color .14s;
}
.hbtn svg { width: 18px; height: 18px; }
.hbtn:hover { background: var(--surface-3); border-color: var(--line-4); }

/* ============================================================
   ONE CONTAINER, not three floating cards
   The reference is a single rounded panel on a grey ground: rail
   flush left, a hairline, then the work area. Ours was a floating
   rounded rail, a gap, and a separately floating header card -
   which is why it never read the same however the insides were
   styled. The card is now the SHELL; everything sits inside it
   and nothing inside it floats.
   DESKTOP ONLY: below 1000px the rail is an off-canvas drawer and
   keeps its own shape.
   ============================================================ */
@media (min-width: 1001px) {
  .shell {
    display: flex; gap: 0; padding: 0;
    margin: var(--gutter);
    align-items: stretch;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-hero);
    box-shadow: var(--shadow-float);
    overflow: hidden;
    min-height: calc(100vh - (var(--gutter) * 2));
  }

  /* the rail stops being a card and becomes the left of the panel */
  .sidebar {
    border: 0; border-right: 1px solid var(--rail-line);
    border-radius: 0; box-shadow: none;
    position: sticky; top: 0;
    height: calc(100vh - (var(--gutter) * 2));
    flex: 0 0 264px; width: 264px;
  }

  /* the work area carries the ground colour, so the rail reads as white against it */
  .maincol { gap: 0; background: var(--page); min-width: 0; }

  /* the header stops floating: flush to the top of the work area, one hairline under */
  .apphead {
    position: sticky; top: 0;
    border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
    /* a hairline and nothing else - the reference's header does not float, and a
       shadow under it re-introduces exactly the layered look this block removed */
    box-shadow: none;
    background: color-mix(in srgb, var(--surface) 88%, transparent);
    padding: 14px 22px;
  }

  .content { padding: var(--gutter) var(--gutter) 26px; }
}

@media (min-width: 1001px) {
  html.navhidden .sidebar { display: none; }
  html.navhidden .maincol { border-radius: var(--r-hero); }
}

/* ============================================================
   FULL-BLEED SHELL — the rail is square and floor-to-ceiling
   The outer panel is gone: the rail runs the full height of the
   window, flush to its left edge, with one hairline separating it
   from the work area. Nothing about the app is a card any more -
   the cards are the CONTENT, which is what makes them read as
   content.
   DESKTOP ONLY: below 1000px the rail is still an off-canvas
   drawer and keeps its own shape.
   ============================================================ */
@media (min-width: 1001px) {
  body { background: var(--surface); }

  .shell {
    margin: 0; padding: 0; gap: 0;
    background: none; border: 0; border-radius: 0; box-shadow: none;
    min-height: 100vh; align-items: stretch;
    /* THE RAIL AND THE HEADER STICK BECAUSE OF THIS LINE. The block above clipped
       `.shell` to hide the rounded panel's corners - correct then, fatal now: an
       ancestor with a non-visible overflow becomes the scroll container a sticky
       descendant sticks INSIDE, and `.shell` never scrolls, so `top: 0` had nothing
       to hold on to. The rail and the header simply scrolled away with the page,
       leaving the empty column below them. The panel it was clipping does not exist
       any more - there is no radius left to hide. */
    overflow: visible;
  }

  .sidebar {
    border-radius: 0; box-shadow: none;
    border: 0; border-right: 1px solid var(--rail-line);
    position: sticky; top: 0;
    height: 100vh;
    flex: 0 0 264px; width: 264px;
  }

  /* the work area is the page now, so it carries the ground */
  .maincol { background: var(--page); min-height: 100vh; }

  .apphead {
    position: sticky; top: 0;
    border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
    box-shadow: none;
    background: color-mix(in srgb, var(--surface) 90%, transparent);
    padding: 14px 24px;
  }

  .content { padding: 18px 24px 30px; }

  /* folding the rail leaves nothing behind to round off */
  html.navhidden .maincol { border-radius: 0; }
}

/* ============================================================
   COLLAPSIBLE NAV SECTIONS
   Thirty-six rows, every one of them permanently on screen, is
   not a menu — it is an index, and it made the four screens
   people actually open as hard to find as the thirty they never
   touch. The section captions become the controls: Hire purchase
   and Collections open, the rest folded until asked for.

   The caption keeps the .navsec class it always had, so nothing
   about its type or colour is restated here — only the parts
   that are new: it is a control now, and it has a chevron.
   ============================================================ */
.navgrp { display: block; }
.navgrp > summary.navsec {
  display: flex; align-items: center; gap: 8px;
  list-style: none; cursor: pointer; user-select: none;
  transition: color .14s;
}
.navgrp > summary.navsec::-webkit-details-marker { display: none; }
.navgrp > summary.navsec:hover { color: var(--rail-ink-on, #101720); }
.navgrp > summary.navsec:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; border-radius: 6px; }
.navgrp > summary .cap { flex: 1; min-width: 0; }
/* A hint, not a control competing with the label: small, and close enough to the
   rail's own hairline colour to sit back into the background until looked for. */
.navgrp > summary .chev {
  width: 10px; height: 10px; flex: 0 0 10px; color: #D6DAE2;
  transition: transform .16s ease, color .14s;
}
.navgrp[open] > summary .chev { transform: rotate(180deg); }
.navgrp > summary.navsec:hover .chev { color: var(--rail-ink, #4A5261); }
.navgrpbody { display: flex; flex-direction: column; padding-bottom: 2px; }

/* `.navsec:first-child` was written when exactly ONE caption was the rail's first
   child. Every caption is now the first child of its own <details>, so that rule
   would flatten the top gap on all seven and run the sections together. */
.navgrp > summary.navsec { padding: 11px 14px 4px; font-size: 9.5px; }
.navgrp:first-of-type > summary.navsec { padding-top: 7px; }
.navgrpbody { padding-bottom: 0; }

/* ---- the rail's own scale, and the scrollbar under a menu that fits ----
   THE HORIZONTAL BAR. `.navItem` has carried `width: 100%` since the first shell,
   which was correct while the rows sat inside the nav's own 12px padding. The
   rail-edge rebuild moved that padding onto the rows as a MARGIN and set the nav's
   left padding to 0 — so every row measured 100% of the track and then started
   12px into it, running 12px off the end. Nothing looked broken because what
   overflowed was empty space; the only symptom was a scrollbar along the bottom of
   a menu with nothing to scroll. `width: auto` hands the sizing back to the column,
   which is what a flex child does when left alone.

   The rest is scale: smaller type, rows closer together. Twelve rows and seven
   captions now clear a 900px laptop with no vertical bar either. */
.sidebar .navItem {
  width: auto;
  padding-top: 7px; padding-bottom: 7px;
  font-size: 12.5px; gap: 9px;
}
.sidebar .navItem .ni { width: 17px; height: 17px; flex: 0 0 17px; }

/* That scale is for a mouse. Below 1000px the rail is a DRAWER on a phone, where a
   31px row is a miss waiting to happen — the tighter rhythm goes back out and the
   rows return to a thumb-sized target. */
@media (max-width: 1000px) {
  .sidebar .navItem { padding-top: 11px; padding-bottom: 11px; font-size: 13.5px; gap: 11px; }
  .sidebar .navItem .ni { width: 19px; height: 19px; flex: 0 0 19px; }
  .navgrp > summary.navsec { padding: 15px 14px 7px; font-size: 10px; }
  .navgrp:first-of-type > summary.navsec { padding-top: 10px; }
  .navgrp > summary .chev { width: 13px; height: 13px; flex: 0 0 13px; }
}

/* Fold the section you are standing in — you can, the shell remembers it — and the
   caption keeps a brand dot, so a collapsed section can never quietly swallow the
   page you are looking at. */
.navgrp.hasactive:not([open]) > summary .cap::after {
  content: ""; display: inline-block; vertical-align: middle;
  width: 5px; height: 5px; margin-left: 7px; border-radius: 50%;
  background: var(--acc);
}

/* ============================================================
   THE OVERVIEW
   The black hero is gone. It was the one thing on the app that
   contradicted the brief - clean and white - and it was carrying
   a single figure on a whole screen's width. Four white tiles
   say more in the same room, and the money that actually decides
   the day (what is overdue, and how old) gets the space instead.
   ============================================================ */

/* the KPI tile gains a currency mark, a footnote and coloured icon wells.
   .kpirow-SCOPED, always: `.kpi` is also the hero's stat row elsewhere. */
.kpirow .kpi .v .cur {
  font-size: .5em; font-weight: 700; letter-spacing: 0;
  color: var(--muted); margin-right: .3em;
}
.kpirow .kpi .v.bad { color: var(--danger); }
.kpirow .kpi .foot {
  margin-top: 10px; font-size: 11.5px; font-weight: 600; color: var(--muted);
  line-height: 1.45; text-wrap: pretty;
}
.kpirow .kpi .foot a { color: var(--ink-2); text-decoration: none; border-bottom: 1px solid var(--line-4); }
.kpirow .kpi .foot a:hover { color: var(--acc); border-color: var(--acc); }
.kpirow .kpi .ico.ok   { background: var(--success-soft); color: var(--success); }
.kpirow .kpi .ico.warn { background: var(--warning-soft); color: var(--warning); }
.kpirow .kpi .ico.bad  { background: var(--danger-soft);  color: var(--danger); }

/* ---- the two-panel row: arrears age beside the collections position ---- */
.dashgrid { display: grid; gap: var(--gutter); margin-bottom: var(--gutter); grid-template-columns: 1fr; }
@media (min-width: 1080px) {
  /* the bars need the room; the list is a column of five numbers */
  .dashgrid { grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr); }
}
.dashgrid > .card { margin-bottom: 0; }
.mutelink { font-size: 12px; font-weight: 700; color: var(--muted); text-decoration: none; white-space: nowrap; }
.mutelink:hover { color: var(--acc); }

/* ---- horizontal money bars ----
   Scaled against the BIGGEST bucket rather than the total, because the shape of the
   arrears is the point: against the total, four of the five bars would be slivers. */
.bars { display: flex; flex-direction: column; gap: 11px; }
.barrow {
  display: grid; align-items: center; gap: 12px;
  grid-template-columns: 108px minmax(0, 1fr) auto 46px;
}
.barrow .bl { font-size: 12.5px; font-weight: 600; color: var(--ink-2); white-space: nowrap; }
.barrow .bt { height: 10px; border-radius: 99px; background: var(--surface-3); overflow: hidden; }
.barrow .bf {
  display: block; height: 100%; border-radius: 99px;
  background: linear-gradient(90deg, var(--acc-bright, #E13843), var(--acc-deep, #791821));
  min-width: 2px;
}
/* the older the debt, the darker the bar - the last two are the ones that hurt */
.barrow:nth-child(1) .bf { background: #F0B354; }
.barrow:nth-child(2) .bf { background: #E8894A; }
.barrow:nth-child(3) .bf { background: var(--acc-bright, #E13843); }
.barrow:nth-child(4) .bf { background: var(--acc, #B91F27); }
.barrow:nth-child(5) .bf { background: var(--acc-deep, #791821); }
.barrow .bv { font-size: 12.5px; font-weight: 600; color: var(--ink); text-align: right; white-space: nowrap; }
.barrow .bp { font-size: 11.5px; font-weight: 700; color: var(--muted); text-align: right; }
.bartot {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line);
  font-size: 12.5px; font-weight: 700; color: var(--ink-2);
}
@media (max-width: 560px) {
  .barrow { grid-template-columns: 1fr auto; }
  .barrow .bt { grid-column: 1 / -1; order: 3; }
  .barrow .bp { order: 2; }
}

/* ---- a stacked label/value list, for a panel of counts ---- */
.stacklist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.stacklist li {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 0; border-bottom: 1px solid var(--line);
}
.stacklist li:last-child { border-bottom: 0; padding-bottom: 0; }
.stacklist li:first-child { padding-top: 0; }
.stacklist .sl-k { flex: 1; min-width: 0; font-size: 12.5px; font-weight: 600; color: var(--ink-2); text-wrap: pretty; }
.stacklist .sl-v { font-size: 16px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.stacklist .sl-v.warnv { color: var(--warning); }
.stacklist .sl-v.badv { color: var(--danger); }

/* ---- money in ---- */
.rxhead { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.rxtot { font-size: 26px; font-weight: 800; letter-spacing: -1px; color: var(--ink); }
.rxtot .cur { font-size: .5em; font-weight: 700; letter-spacing: 0; color: var(--muted); margin-right: .3em; }
.rxsub { font-size: 12px; font-weight: 600; color: var(--muted); }
.rxchart {
  display: flex; align-items: flex-end; justify-content: flex-start; gap: 3px;
  height: 132px; padding-top: 4px;
  border-bottom: 1px solid var(--line);
}
/* The cap is the point. A ninety-day series divides the panel into ninety slivers,
   but three days of receipts divide it into THREE - and a bar a third of the panel
   wide reads as a huge number rather than as three days that happened to have money
   in them. Capped and left-packed, a sparse series looks sparse, which is the truth
   about it; the count beside the total says how many days are actually drawn. */
.rxbar {
  flex: 1 1 0; min-width: 2px; max-width: 26px; border-radius: 3px 3px 0 0;
  background: var(--acc-soft, #F9E9EA);
  border-top: 2px solid var(--acc, #B91F27);
  transition: background .12s;
}
.rxbar:hover { background: var(--acc, #B91F27); }

/* ---- an empty state that says WHY, and offers the way out ----
   datagrid.js owns its own no-rows line and is locked; this is for the panels that
   are not grids, where "nothing here" without a reason is just a dead end. */
.blankstate {
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
  padding: 22px; border: 1px dashed var(--line-4); border-radius: var(--r-card);
  background: var(--surface-2);
}
.blankstate b { font-size: 13.5px; font-weight: 700; color: var(--ink); }
.blankstate span { font-size: 12.5px; font-weight: 500; color: var(--ink-2); line-height: 1.6; max-width: 74ch; text-wrap: pretty; }
.blankstate .btn { margin-top: 4px; }

/* the freshness line gained a dot, so it reads as a status and not as a sentence */
.freshness .d { width: 7px; height: 7px; flex: 0 0 7px; border-radius: 50%; background: currentColor; }

/* ============================================================
   FIELD UNITS — the % lives OUTSIDE the box
   A percent field holds 8.00, not "8.00%". The sign sits next to
   the input where it labels the number without becoming part of
   it, the way the old MERP screen does it. Typing a value should
   never mean typing its unit, and a stored "8.00%" is a string
   where a number belongs.
   ============================================================ */
.unitfield { display: flex; align-items: center; gap: 8px; }
.unitfield > .ob-input { flex: 1 1 auto; min-width: 0; }
.unitfield > .unit {
  flex: 0 0 auto; font-size: 12.5px; font-weight: 700; color: var(--muted);
  font-variant-numeric: tabular-nums; user-select: none;
}

/* ============================================================
   WHICH BOOKS — the company chip in the header
   Deliberately a LABELLED chip and not another icon square. The
   two buttons beside it are shortcuts; this one is the statement
   of what every number on the screen is about, and a number with
   the wrong entity behind it is worse than no number.
   ============================================================ */
.cochip {
  display: inline-flex; align-items: center; gap: 8px; flex: 0 1 auto; min-width: 0;
  height: 38px; padding: 0 12px; border-radius: 11px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  font-size: 12.5px; font-weight: 700; text-decoration: none;
  transition: background .14s, border-color .14s, color .14s;
}
.cochip:hover { background: var(--surface-3); border-color: var(--line-4); color: var(--ink); }
.cochip > svg:first-child { width: 16px; height: 16px; flex: 0 0 16px; color: var(--acc); }
.cochip .nm { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 22ch; }
.cochip .ch { width: 13px; height: 13px; flex: 0 0 13px; color: var(--muted); }

@media (max-width: 900px) {
  /* the label is the point, so on a narrow header the chip keeps its name and the
     shortcut buttons go instead */
  .cochip .nm { max-width: 12ch; }
}

/* ============================================================
   THE GUIDED SETUP CHECKLIST
   A row is: mark, then title + WHY + the evidence, then the way
   to fix it. The WHY is the whole point - it is what separates
   this from a to-do list, so it gets real line length rather
   than being squeezed into a caption.
   ============================================================ */
.setuplist > .setupitem {
  display: grid; grid-template-columns: 26px minmax(0, 1fr) auto;
  align-items: start; gap: 14px;
  padding: 18px 0; border-bottom: 1px solid var(--line);
}
.setuplist > .setupitem:last-child { border-bottom: 0; }

.setupitem .si-mark { width: 22px; height: 22px; margin-top: 1px; }
.setupitem .si-mark svg { width: 22px; height: 22px; }
.setupitem.done .si-mark { color: var(--success); }
.setupitem.todo .si-mark { color: var(--muted); }
.setupitem.blocking .si-mark { color: var(--danger); }

.setupitem .si-body { min-width: 0; }
.setupitem .si-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
.setupitem .si-title { font-size: 14px; font-weight: 700; color: var(--ink); }
.setupitem .si-why {
  margin: 0; font-size: 13px; line-height: 1.62; color: var(--ink-2);
  max-width: 78ch; text-wrap: pretty;
}

/* The evidence box: what the data says RIGHT NOW, in the app's own voice. Bordered on one
   side only, which is why it carries no radius. */
.setupitem .si-evidence {
  margin-top: 10px; padding: 9px 12px;
  background: var(--surface-2); border-left: 3px solid var(--line-4); border-radius: 0;
  font-size: 12.5px; line-height: 1.55; color: var(--ink-2);
}
.setupitem.blocking .si-evidence {
  background: var(--danger-soft); border-left-color: var(--danger); color: var(--danger);
  font-weight: 600;
}
.setupitem.done .si-evidence { border-left-color: var(--success); }

.setupitem .si-act { flex: 0 0 auto; }
.setupitem .si-act .btn { white-space: nowrap; }

@media (max-width: 720px) {
  /* the action drops under the text rather than squeezing the WHY into a column */
  .setuplist > .setupitem { grid-template-columns: 26px minmax(0, 1fr); }
  .setupitem .si-act { grid-column: 2; margin-top: 10px; }
}

/* =====================================================================
   THE MODULE ACCENT  (SPEC-APP-SHELL-DESIGN 3, decision 2)
   =====================================================================
   --ob-module is set on .shell by _Layout from the module registry. These
   two rules are the RAIL half - the row you are on and the bar on its
   leading edge. The rest of the shell follows the same variable, through
   the ramp at the bottom of this file [Darren 2026-09-09: "i want the same
   as erp"]. Both halves fall back to --acc, so a page belonging to no
   module - the Overview, sign-in, switch company - stays e-ONE crimson.

   The one thing that never moves is the mark: .sidebar .brand .mark.logo
   sets background:none, so no accent reaches the logo whatever the ramp
   resolves to.
*/
.navItem.active .ni { color: var(--ob-module, var(--acc)); }
.navItem.active::before { background: var(--ob-module, var(--acc)); }

/* The dot a FOLDED section keeps, so a collapsed section still says which
   area you are in - same selector as the rule that draws it above. */
.navgrp.hasactive:not([open]) > summary .cap::after { background: var(--ob-module, var(--acc)); }

/* =====================================================================
   THE MODULE BOUNDARY  (SPEC-APP-SHELL-DESIGN 2b)
   =====================================================================
   "The sidebar shows ONE module s pages, never the whole app." So the
   foot of the rail carries the two ways back out: an icon strip of every
   area, and a collapsed list of the same by name. */

/* Pushes everything below it to the bottom, wherever the link list ends -
   a five-row area and a twelve-row one both put the rail in one place. */
.navsp { flex: 1 1 auto; min-height: 18px; }

/* THE MODULE RAIL. Every area at once, as icons - the only place the whole
   system is still visible now the nav shows one part of it. */
.modrail {
  display: grid; gap: 6px;
  margin: 6px 10px 8px; padding: 8px 6px;
  border: 1px solid var(--line, #E6E9EE); border-radius: 12px;
  background: #FBFCFD;
}
.modrail a {
  display: flex; align-items: center; justify-content: center;
  height: 32px; border-radius: 9px; color: var(--muted, #6A7482);
  transition: background .14s, color .14s;
}
.modrail a:hover { background: #fff; color: var(--ink-2, #3A4453); }
.modrail a .ni { width: 17px; height: 17px; flex: 0 0 17px; }
/* Each tile carries its area's NAME under the icon (Darren 2026-11-11), so the
   strip reads without hovering. Taller tile, icon over words; a two-word name
   ("Hire purchase") may wrap onto a second line rather than being cut. */
.modrail a {
  flex-direction: column; gap: 4px;
  height: auto; min-height: 50px; padding: 7px 3px 6px;
  text-decoration: none;
}
.modrail a .ml {
  font-size: 10.5px; line-height: 1.15; font-weight: 600;
  text-align: center; letter-spacing: .01em;
}
/* Seven areas, three to a row: the last one sits alone - centre it rather
   than leave it hanging at the left. */
.modrail a:last-child:nth-child(3n+1) { grid-column: 2; }
/* The area you are in wears its OWN colour, so the strip answers "where am
   I" without a tooltip - each module carries its accent in --mod. */
.modrail a.on { background: #fff; color: var(--mod, var(--acc)); box-shadow: 0 1px 2px rgba(16,23,32,.10); }

/* (The collapsed "Switch area" list that sat here is gone - the tiles above
   now carry the names, 2026-11-11.) */

/* The company chip's TYPE badge (SPEC-COMPANY-SWITCHER 6a: short name AND type).
   Quiet enough not to compete with the name, loud enough that a dealer figure is
   never mistaken for a credit one - which is the whole reason the chip exists.
   No new colours: existing tokens only, as the spec requires. */
.cochip .ty {
  flex: 0 0 auto; font-size: 9.5px; font-weight: 800; letter-spacing: .07em;
  padding: 2px 6px; border-radius: 999px;
  background: var(--surface-3, #F1F3F6); color: var(--muted, #6A7482);
  border: 1px solid var(--line-4, #E6E9EE);
}

/* =====================================================================
   THE WHOLE SHELL TAKES THE MODULE COLOUR  (SPEC-APP-SHELL-DESIGN 3.2)
   =====================================================================
   "The accent becomes --ob-accent for the entire shell. One variable, set
   per module, and every button, active nav item and focus ring follows
   it. Nothing hard-codes a hue."

   CMHP keeps a hand-tuned ramp rather than one colour - deep, soft,
   bright, ink and line, read across forty-odd pages. So the ramp is
   DERIVED from the module accent with color-mix, which is what keeps the
   promise: change the module colour and everything downstream follows,
   with no second list of hexes to maintain.

   Only inside a module. No data-module attribute means the brand ramp
   above stands exactly as tuned - the Overview, sign-in and switch-company
   are e-ONE crimson, not the last area you happened to visit.

   --ob-hp exists because Hire purchase IS the brand colour, and pointing
   --acc at a variable that resolves to --acc would be a circular
   reference: CSS treats that as invalid and the ramp would silently
   collapse to nothing. */
:root { --ob-hp: #B91F27; }

.shell[data-module] {
  --acc:        var(--ob-module);
  --acc-bright: color-mix(in srgb, var(--ob-module) 86%, #fff);
  --acc-deep:   color-mix(in srgb, var(--ob-module) 80%, #000);
  --acc-ink:    color-mix(in srgb, var(--ob-module) 64%, #000);
  --acc-soft:   color-mix(in srgb, var(--ob-module)  9%, #fff);
  --acc-soft2:  color-mix(in srgb, var(--ob-module)  4%, #fff);
  --acc-line:   color-mix(in srgb, var(--ob-module) 24%, #fff);
  --ob-accent:  var(--ob-module);
  --accent:     var(--ob-module);
  --accent2:    var(--acc-deep);
  --accent-ink: var(--acc-deep);
  --accent-weak: var(--acc-soft);
  --accent-weak2: var(--acc-soft2);
}


/* =====================================================================
   THE ERP SHELL - AMENDING "FULL-BLEED SHELL" ABOVE
   =====================================================================
   [Darren 2026-09-09: "the nav and the header also need to same as erp
   design ... also the setup master page design also that is really good"]

   The flush chrome was ALREADY here - see FULL-BLEED SHELL further up,
   which took the rail square and floor-to-ceiling and put a hairline
   under the header. This block does not redo that work; it changes the
   four things that still differed from
   D:\OneBloc\erp\src\OneBlocErp.Api\Pages\Shared\_AppStyles.cshtml:

     1. the rail is 256px, not 264
     2. the header is a fixed 60px bar with a SOLID ground, not an
        auto-height padded strip behind a blur
     3. the page sits in a 1160px measure with 26/32/60 padding
     4. the shell is a two-column grid, so the rail column and the work
        column are one declaration rather than a flex basis on the child

   Everything else those rules already say - sticky at 0, 100vh, radius 0,
   no shadow, the right-hand hairline - is deliberately NOT restated here.
   Two blocks describing one layout is how a stylesheet starts to lie.

   Fenced to >= 1001px for the same reason that block is: below it the
   rail is an off-canvas drawer and must stay one.
   ===================================================================== */

@media (min-width: 1001px) {

  /* (4) and (1). The track carries the width now, so the flex basis and
     the explicit width on .sidebar have to stand down or they would win
     against the 256px column. */
  .shell {
    display: grid; grid-template-columns: 256px minmax(0, 1fr);
    align-items: stretch;
  }
  /* folding the rail must leave ONE column, not a 256px hole */
  .navhidden .shell { grid-template-columns: minmax(0, 1fr); }
  .sidebar { width: auto; flex: none; }

  /* (2) The ERP's .topbar: a fixed 60px, flush, one row, and opaque. The
     blur goes with the transparency - a solid bar has nothing to see
     through, and dropping it also un-does the containing block it created
     (a simplification, not a risk: nothing inside it is absolutely
     positioned). */
  .maincol { gap: 0; }
  .apphead {
    height: 60px; min-height: 60px;
    padding: 0 26px; gap: 14px; flex-wrap: nowrap;
    background: var(--surface, #fff);
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }

  /* (3) The ERP's .main: a comfortable measure rather than the full width
     of whatever monitor the counter has. Grids are unaffected -
     datagrid.js scrolls inside its own box, as the ERP's listings do. */
  .content { padding: 26px 32px 60px; max-width: 1160px; }
}

/* ---------- the top bar's own contents ----------------------------------
   One row, as the ERP has it: [menu] [title] .... [search] [actions].
   The crumb is dropped HERE because it moves INTO the brand lockup below -
   the ERP puts the module name beside the wordmark, not over the page
   title, and printing it in both places is how a shell starts to feel
   busy. The title drops from 19px/800 to the ERP's 15px/600 because the
   page now carries its own heading again (see .pageHead below); two 19px
   headings stacked was why the h1 had to be hidden in the first place. */
.apphead .titles,
.apphead .navtoggle + .titles { flex: 0 1 auto; max-width: 40ch; gap: 0; }
.apphead .crumb { display: none; }
.apphead .ttl {
  font-size: 15px; font-weight: 600; letter-spacing: -.015em; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* The company chip: the ERP's .co geometry (36px, radius 9). It stays in
   the TOP BAR and not in the rail - SPEC-APP-SHELL-DESIGN 4 is explicit
   that the ERP shows the company twice because it has the furniture for
   it and CMHP should pick one, and the top bar is where your eye goes
   when you are reading a number. */
.cochip { height: 36px; border-radius: 9px; }

/* ---------- the brand lockup, horizontal --------------------------------
   [mark] e-ONE Credit | Hire purchase - the ERP's .brand: the wordmark,
   a hairline rule, then the area you are in, all on one line. It was
   stacked, with the area in 9.5px uppercase underneath, which read as a
   caption rather than as half of a lockup. */
.sidebar .brand { padding: 18px 14px 12px; gap: 9px; align-items: center; }
.sidebar .brand .nm { flex-direction: row; align-items: center; gap: 10px; }
/* The wordmark never wraps - "e-ONE Credit" is twice the length of
   "OneBloc" and broke across two lines in a 256px rail. It holds one line
   and the AREA beside it takes what is left, wrapping when it needs to,
   which is what the ERP's own .b-modname does. */
/* The wordmark never wraps - "e-ONE Credit" is twice the length of
   "OneBloc" and broke across two lines in a 256px rail. It holds one line
   and the AREA beside it takes what is left. Sized DOWN from the ERP's
   16.5/14 because this rail also carries a collapse control the ERP's
   does not, and the ERP's own lockup is measured against a seven-letter
   wordmark. */
.sidebar .brand .nm b { font-size: 15px; font-weight: 800; letter-spacing: -.02em; line-height: 1.1; white-space: nowrap; flex: 0 0 auto; }
.sidebar .brand .nm small {
  font-size: 12.5px; font-weight: 600; letter-spacing: -.01em;
  text-transform: none; line-height: 1.2;
  border-left: 1px solid var(--line); padding-left: 9px;
  /* wraps between WORDS, never inside one: "Hire purchase" over two lines
     is the ERP's .b-modname behaviour, "Hir / e pur / ch / as / e" is what
     overflow-wrap:break-word did to it in a rail this narrow */
  white-space: normal; overflow-wrap: normal; word-break: normal; min-width: 0;
}

/* ---------- the active nav row -----------------------------------------
   THE most recognisable thing about the ERP's rail: the row you are on is
   a SOLID pill in the module colour with white text, not a tinted
   background with a coloured bar down its edge. _AppLayout sets
   --nav-active to the module accent for exactly this.

   The leading bar and the accent-tinted icon from the rules above are
   switched off rather than deleted, because on a page belonging to no
   module --ob-module is unset and the fallback still has to work. */
.navItem.active {
  background: var(--ob-module, var(--acc));
  color: #fff; font-weight: 600;
}
.navItem.active .ni,
.navItem.active .lb { color: #fff; }
.navItem.active::before { display: none; }
.navItem.active .dot { background: #fff; box-shadow: none; }
.navItem.active:hover { background: var(--ob-module, var(--acc)); color: #fff; }
.navItem.active:hover .ni { color: #fff; }

/* The module rail's current tile follows the same treatment - it is the
   same statement ("you are here") in a smaller control. */
.modrail a.on { background: var(--ob-module, var(--acc)); border-color: var(--ob-module, var(--acc)); color: #fff; }
.modrail a.on .ni { color: #fff; }

/* ---------- the page heading comes back --------------------------------
   The ERP shows the title TWICE on purpose: 15px in the bar, and again as
   a big light h1 on the page. That second one is what makes its screens
   feel airy - big-and-light always reads calmer than small-and-bold - and
   CMHP had thrown it away, visually hiding the h1 because it duplicated a
   19px/800 title in the header. With the header title down to 15px/600
   there is no duplication left to hide.

   .pageHead h1 above is position:absolute + clip-path (screen-reader
   only). Every property of that has to be undone, not just the clip. */
.pageHead h1 {
  position: static; width: auto; height: auto; margin: 0 0 5px; padding: 0;
  overflow: visible; clip-path: none; white-space: normal; border: 0;
  font-size: 29px; font-weight: 600; letter-spacing: -.025em; line-height: 1.15;
  color: var(--ink); text-wrap: balance;
}
.pageHead { margin-bottom: 24px; }
.pageHead .sub { font-size: 13.5px; max-width: 74ch; }
/* That rule existed only because a pageHead holding nothing but an
   invisible h1 left a gap. The h1 is visible now, so it always has one. */
.pageHead:not(:has(.sub)):not(:has(.actions)) { margin-bottom: 24px; }

/* The DataGrid writes the SAME h1 + .sub shape into its own header, so a
   grid screen and a form screen open with the same typography instead of
   17px/800 on one and 29px/600 on the other. Theming, not a kit edit. */
.dg .head h1 { font-size: 29px; font-weight: 600; letter-spacing: -.025em; line-height: 1.15; }
.dg .head .sub { font-size: 13.5px; max-width: 74ch; }

/* ---------- cards, the ERP's proportions --------------------------------
   radius 18, padding 22, and the two-layer shadow that is almost a hairline
   up close and a soft lift from a step back. */
.card { border-radius: 18px; }

/* ---------- the setup screen, the ERP's own shape ----------------------
   [Darren 2026-09-09: "the setup master page design also that is really
   good"]. The checklist was already a port of the ERP's ul.steps. These
   are the two things it did not have: BLOCKERS AS THEIR OWN CARD, before
   everything, and the big fraction that is the progress readout.
   (D:\OneBloc\erp\src\OneBlocErp.Api\Pages\App\Setup.cshtml) */
.card.blocker { border-color: #F3C2C2; background: #FEF7F7; }
.card.blocker .bl-h {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 800; letter-spacing: .09em;
  text-transform: uppercase; color: #C0392B;
}
.card.blocker .bl-h svg { width: 15px; height: 15px; flex: 0 0 15px; }
.card.blocker .bl-t { font-size: 15.5px; font-weight: 750; margin: 9px 0 5px; letter-spacing: -.01em; color: var(--ink); }
.card.blocker .bl-w { font-size: 13px; color: var(--ink-2); margin: 0; line-height: 1.55; }
.card.blocker .bl-d {
  font-size: 12.5px; color: #8E3B31; background: #FBEAEA;
  border-radius: 9px; padding: 10px 12px; margin: 12px 0 0; line-height: 1.5;
}

/* The progress head: heading and hint on the left, the count on the right.
   The number carries the state, so the bar below needs no label - which is
   why the old trailing "38%" went with it. */
.progh { display: flex; align-items: flex-start; gap: 16px; }
.progh .hint { font-size: 12.5px; color: var(--muted); line-height: 1.55; }
.progn {
  margin-left: auto; flex: none;
  font-family: var(--ob-mono, monospace); font-variant-numeric: tabular-nums;
  font-size: 26px; font-weight: 800; letter-spacing: -.03em; line-height: 1;
  color: var(--success);
}
.progn span { font-size: 15px; font-weight: 700; color: var(--muted); }
/* While anything is affecting money the readout is red, like the bar. */
.progn.bad { color: var(--danger); }

/* =====================================================================
   FULL-SCREEN LAYOUT, LIKE THE PMS  [Darren 2026-11-11]
   "u think we can do like PMS its align center content and the nav top
   full ... it will be a full screen design so its nicer" - and the two
   squeezed sections on the agreement page (the identity card's action
   buttons, the tab strip) plus the brand row "also not nice".

   Kept as ONE block at the end so it wins the cascade without rewriting
   the layers above; delete this block and the old shape comes back.
   ===================================================================== */

/* (1) THE PAGE USES THE SCREEN. The ERP-era measure (1160px, pinned left)
   left a third of a wide monitor empty and squeezed everything inside it.
   The work area now takes the full width, and only on a very wide screen
   does it stop and sit CENTRED rather than hug the left edge. */
@media (min-width: 1001px) {
  .content { max-width: 1680px; width: 100%; margin-left: auto; margin-right: auto; box-sizing: border-box; }
}

/* (2) THE TOP BAR RUNS THE FULL WIDTH. Title on the left, the agreement
   search in the middle, the actions on the right edge - it used to stop
   two thirds of the way across with everything bunched after the title.
   Two auto margins share the free space: the search sits between them,
   and when a person cannot search the title's margin alone pushes the
   actions to the edge. Desktop only: on a phone the bar wraps onto
   several rows and keeps the order it already had. */
@media (min-width: 1001px) {
  .apphead .titles,
  .apphead .navtoggle + .titles { margin-right: auto; }
  .apphead .searchpill { flex: 1 1 260px; max-width: 460px; margin-right: auto; }
}

/* (3) THE BRAND ROW. "e-ONE Credit | Hire purchase" on one line left the
   area name 70px to wrap in, and it ran into the fold button. The area
   now sits on its OWN line under the wordmark - one line each, never
   wrapped, cut with an ellipsis if a future area name is ever too long. */
.sidebar .brand .nm { flex-direction: column; align-items: flex-start; gap: 2px; min-width: 0; }
.sidebar .brand .nm b { font-size: 15px; }
.sidebar .brand .nm small {
  border-left: 0; padding-left: 0;
  font-size: 11.5px; font-weight: 600; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}

/* (4) THE AGREEMENT PAGE'S TWO SQUEEZED SECTIONS.
   (a) The identity card's actions were seven buttons in ONE row of a 252px
       card - 29px each, so "Statement", "Ledger" and "Interest" printed on
       top of one another. Now a grid, four across, each name on one line.
   (b) The record column grows to 320px to give that grid room. */
@media (min-width: 1100px) {
  .recordgrid { grid-template-columns: 320px minmax(0, 1fr); }
}
.idcard { padding: 20px 18px; }
.idacts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.idact { padding: 9px 2px 8px; font-size: 10.5px; white-space: nowrap; }
.idact .g { font-size: 16px; }

/*  (c) The tab strip wrapped every long name onto two lines ("Installment /
       plan", "Approval / trail"). Every tab is one line now; if they do not
       all fit, the strip scrolls sideways - what it already did on a phone. */
.obtabs > nav {
  flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden;
  scrollbar-width: thin;
}
.obtabs > nav > * { flex: 0 0 auto; white-space: nowrap; }

/* SUB-HEADINGS INSIDE AN AREA (Setup's six groups, 2026-11-11). Quieter
   than the area caption above them - a label, not a second title - with a
   little air before each so the groups read as blocks. The first one sits
   right under the area caption, so it gets no extra air. */
.sidebar .navsub {
  padding: 12px 12px 4px;
  font-size: 11px; font-weight: 700; letter-spacing: .02em;
  color: var(--muted, #6A7482);
}
.sidebar .navsec + .navsub { padding-top: 2px; }

/* The Help Desk icon ships [hidden] until onebloc-report.js wires it; .hbtn sets a display,
   which would otherwise beat the hidden attribute and show a button with nothing behind it. */
.hbtn[hidden] { display: none; }
