/* =========================================================================
   Normandy WC Portal — central theme (design tokens + component vocabulary)
   =========================================================================
   Single source of truth for every screen AND the Phase 5 proposal PDF.
   No screen hardcodes a color: everything reads these custom properties.

   TOKEN PROVENANCE
   ----------------
   [brand]   = hex taken verbatim from brand/brand colors.pdf
   [derived] = proposed derivation for states the brand guide doesn't cover
               (hover, disabled, focus, tint/ink pairs for contrast).
               Listed for owner approval in portal/README.md — change the
               token here and every screen follows.

   COLOR DISCIPLINE (non-negotiable, from the design brief)
   --------------------------------------------------------
   - Navy owns the hero and primary actions.
   - Green means money saved or Quoted. Amber means Referred / Indicative.
     Red means Declined. Nothing else is colored.
   - The interactive accent (brand blue) marks selection/focus/links only.
   ========================================================================= */

/* ---------- THE ONE FONT, SERVED BY THE APP (one font everywhere, owner
   ruling 2026-10-09, option B). Inter 4.1, the variable face: one file
   covers every weight the screens ask for (400 to 800, 650 and 750
   included). SIL Open Font License 1.1, unmodified, licence beside it in
   portal/fonts/. Until this rule the stack named Segoe UI first, which the
   app cannot serve (Microsoft forbids self-hosting Windows fonts), so each
   machine drew its own: Segoe UI on Windows, DejaVu Sans on the cloud's
   Linux, 13% wider. Served from here, every machine draws the same
   letters. The two screens that do not import this file (the workbench
   and the placement page) carry this same rule; the stack guard pins all
   three identical. ---------- */
@font-face {
  font-family: "Inter";
  src: url("/portal/fonts/InterVariable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* ---------- brand primaries ---------- */
  --navy:        #213e7c;  /* [brand] Primary Blue — hero, primary buttons   */
  --gray:        #8a898d;  /* [brand] Primary Gray — secondary text          */
  --gray-mid:    #bbbbbb;  /* [brand] medium gray — disabled fg, hairlines   */
  --gray-light:  #eeeeee;  /* [brand] light gray — disabled bg               */
  --blue-pale:   #8cc9e7;  /* [brand] very light blue — pills on navy        */
  --tint-blue:   #cfe9f7;  /* [brand] transparent blue — info/cross-sell bg  */
  --tint-green:  #e0f0df;  /* [brand] transparent green — success badge bg   */

  /* ---------- brand secondaries in service roles ---------- */
  --blue:        #068fc9;  /* [brand] button color 2 — interactive accent    */
  --green:       #009347;  /* [brand] button color 1 — savings / Quoted      */
  --amber:       #f7b623;  /* [brand] — Referred / Indicative                */
  --red:         #e12925;  /* [brand] — Declined                             */

  /* ---------- derived neutrals (proposed) ---------- */
  --ink:         #141c30;  /* [derived] near-black biased toward the navy    */
  --ink-soft:    #4a5265;  /* [derived] long-form secondary text             */
  --page:        #f6f7f9;  /* [derived] page ground, cool-biased             */
  --card:        #ffffff;
  --border:      #e4e7ee;  /* [derived] card + table hairlines               */
  --border-strong:#c9cedb; /* [derived] input borders                        */

  /* ---------- derived interaction states (proposed) ---------- */
  --navy-hover:  #1a3266;  /* [derived] navy darkened ~12%                   */
  --navy-deep:   #18306a;  /* [derived] hero gradient end                    */
  --blue-hover:  #0577a7;  /* [derived] */
  --green-hover: #007a3b;  /* [derived] */
  --focus-ring:  rgba(6, 143, 201, .40);   /* [derived] from --blue          */
  --disabled-fg: var(--gray-mid);
  --disabled-bg: var(--gray-light);

  /* ---------- derived semantic tint/ink pairs (proposed) ----------
     Badge text on a pale tint needs more contrast than the raw brand hue;
     each semantic color gets a darkened "ink" for text and its tint for bg. */
  --green-ink:   #00682f;  /* [derived] on --tint-green                      */
  --bound-green: #0b6634;  /* [derived] deep --green, the bound hero (2026-09-23) */
  --bound-green-deep: #06492a;  /* [derived] its gradient end               */
  --amber-tint:  #fdf3d8;  /* [derived] from --amber                         */
  --amber-ink:   #805c00;  /* [derived] on --amber-tint                      */
  --red-tint:    #fcebea;  /* [derived] from --red                           */
  --red-ink:     #b21611;  /* [derived] on --red-tint                        */
  --neutral-tint:#eef0f4;  /* [derived] Draft / Imported / neutral chips     */
  --purple:      #6a4bb0;  /* [derived] Pending UW (WC authority, 2026-09-23) */
  --purple-tint: #eee9f8;  /* [derived] from --purple                        */
  --purple-ink:  #4a2d8a;  /* [derived] on --purple-tint                     */
  --neutral-ink: #4a5265;

  /* ---------- on-navy (hero) ---------- */
  --on-navy:        #ffffff;
  --on-color:       #ffffff;  /* [derived] text on any filled brand colour (2026-09-23) */
  --sky-onnavy:     #8cc9e7;  /* [approved] plancards mockup v4 tagline on navy */
  --on-navy-soft:   rgba(255,255,255,.78);  /* [derived] hero secondary text */
  --on-navy-pill:   rgba(255,255,255,.14);  /* [derived] pill bg on navy     */
  --on-navy-border: rgba(255,255,255,.26);  /* [derived] pill border on navy */

  /* ---------- reward-points gold (agent status pages, 2026-08-20) --------
     The points figure is BARE GLOWING TEXT on the navy hero, not a chip in
     a container, so it needs gradient stops rather than one fill. Derived
     from the brand --amber (#f7b623) by lightening and darkening it; the
     brand guide covers a single amber, and a two-stop gradient cannot be
     expressed with one token. Used ONLY by the points block. */
  --gold-hi:    #ffd977;  /* [derived] --amber lightened, gradient start   */
  --gold-lo:    #f0a63a;  /* [derived] --amber warmed, gradient end        */
  --gold-label: #e8c98a;  /* [derived] the caption under the figure        */
  --gold-spark: #ffe9b8;  /* [derived] the twinkles                        */
  --gold-glow:  rgba(240,166,58,.35);  /* [derived] text-shadow bloom      */

  /* ---------- the workbench's gold and the avatar palette (workbench v3,
     items 1 and 10, 2026-10-31) -------- `--av-*` are the five colours a
     person's avatar is picked from; each carries white initials at AA. */
  --gold:       #f2c14e;  /* [approved] workbench v3 mockup */
  --gold-hover: #ffd56e;  /* [derived] --gold lightened     */
  --gold-tint:  #fffaf0;  /* [derived] from --gold          */
  --gold-border:#f3e3b8;  /* [derived] from --gold          */
  --av-navy:    #16305c;
  --av-royal:   #2d4fb5;
  --av-teal:    #0d6f6e;
  --av-green:   #0b6634;
  --av-violet:  #6a4bb0;

  /* ---------- typography ---------- */
  --font-ui: "Inter", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --fs-hero: 52px;   --lh-hero: 1.0;    /* the premium — largest thing on page */
  /* THE ONE STEP BETWEEN A HEADING AND THE PREMIUM (bind-clarity item 1,
     owner walkthrough 2026-08-28). It exists because the scale had a hole
     exactly where a confirmation headline needs to sit: every step from 11
     to 22 is a 1.1-1.3 ratio and then it JUMPS 2.36x to the premium, so a
     headline that must out-shout a 24px number had nowhere to go but the
     premium's own token - which is spoken for and says so on the line
     above. 34px is the geometric mean of 22 and 52 (33.8), which is the
     step the scale would have had if it had one. */
  --fs-h1-hero: 34px; --lh-h1-hero: 1.12;
  --fs-h1:   22px;   --lh-h1:   1.25;
  --fs-h2:   17px;   --lh-h2:   1.3;
  --fs-body: 14px;   --lh-body: 1.55;
  --fs-small:12.5px; --lh-small:1.45;
  --fs-label:11px;                       /* uppercase eyebrows / column heads */
  --ls-label:.08em;
  --fw-hero: 750;
  --fw-semibold: 600;
  --fw-medium: 500;

  /* ---------- geometry ---------- */
  --r-card:  16px;        /* card radius (brief)                             */
  --r-ctl:   10px;        /* inputs, small controls                          */
  --r-pill:  999px;       /* badges, toggles, switchers — pill-shaped        */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 24px; --sp-6: 32px; --sp-7: 40px; --sp-8: 64px;
  --content-max: 1100px;
  --shadow-card: 0 1px 2px rgba(20,28,48,.05), 0 4px 16px rgba(20,28,48,.06);
  --shadow-hero: 0 8px 28px rgba(24,48,106,.28);
  --shadow-pop:  0 2px 6px rgba(20,28,48,.08), 0 12px 32px rgba(20,28,48,.14);
}

/* =========================================================================
   Base
   ========================================================================= */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}
/* EVERY GLYPH IN THE SERVED FACE (land.py list 5, item 4, 2026-10-15):
   form controls and code do not inherit the page font by default, so
   buttons drew in Arial and code in Consolas on Windows (other faces
   elsewhere). They take the page's font like everything else. */
button, input, select, textarea, code, kbd, samp, pre,
input::file-selector-button { font-family: inherit; }
h1, h2, h3 { margin: 0; text-wrap: balance; }
a { color: var(--blue); text-decoration: none; }
a:hover { color: var(--blue-hover); text-decoration: underline; }
:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; border-radius: 4px; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

.money, .num { font-variant-numeric: tabular-nums; }

/* uppercase micro-label (eyebrows, column heads, pill labels) */
.label {
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--gray);
}

/* =========================================================================
   App chrome — white header (the logo is navy-on-white; it never sits on navy)
   ========================================================================= */
.chrome {
  background: var(--card);
  border-bottom: 1px solid var(--border);
}
/* THE CHROME ROW WRAPS AT EVERY WIDTH (2026-08-16).

   IT USED TO WRAP ONLY BELOW 900px AND THAT IS WHY IT CLIPPED. `flex-wrap:
   wrap` lived solely inside `@media (max-width: 900px)`, so above that the
   base rule applied and the row was `nowrap`. `.chrome-inner` is capped at
   1100px; the admin row wants 1369px; the excess spilled right. At a
   1280px viewport the signed-in identity landed at 1285 and the SIGN-OUT
   BUTTON at 1375 - both entirely past the viewport edge. **Sessions are
   revocable and the control that revokes them was off-screen.**

   Wrapping at every width costs nothing when the row fits: a wrap
   container lays a fitting row out exactly as a nowrap one does. It
   engages only when the alternative was clipping.

   THE BAND IS STATIC FLOW, so a wrapped row makes the header taller and
   pushes the page down. It cannot overlap content, and that is asserted
   rather than assumed. */
.chrome-inner {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 14px var(--sp-5);
  display: flex; align-items: center; gap: var(--sp-5);
  flex-wrap: wrap; row-gap: var(--sp-3);
}
.chrome .logo img { height: 30px; display: block; }
.chrome-nav { display: flex; flex-wrap: wrap; gap: var(--sp-2);
  margin-left: var(--sp-4); }
/* chrome nav links are pill-links (blue outline, empty fill); the current
   page keeps the outline treatment — no filled state (owner ruling). */
/* `min-width: 0` and `overflow-wrap: anywhere` are what make "any name
   length" true rather than "any name we happened to try". A flex item's
   default `min-width: auto` refuses to shrink below its content, so a long
   unbroken token would push the row wide again; these let the name break
   instead of the layout. */
.chrome-user { margin-left: auto; text-align: right; font-size: var(--fs-small);
  color: var(--gray); min-width: 0; overflow-wrap: anywhere; }
/* flexible middle zone (e.g. draft-save status) — grows to fill the space
   between the nav and the right-side actions, centering its content there
   rather than crowding either side. */
.chrome-center { flex: 1 1 auto; min-width: 0; display: flex; justify-content: center; }
.chrome-user b { display: block; color: var(--ink); font-weight: var(--fw-semibold); }

/* Chrome pill links — blue outline, empty fill (Dashboard, Rewards,
   Quote Other Lines). Blue = interactive, consistent with the accent rule. */
.pill-link {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--fs-small); font-weight: var(--fw-semibold);
  color: var(--blue); background: transparent;
  border: 1.5px solid var(--blue); border-radius: var(--r-pill);
  padding: 6px 16px; white-space: nowrap;
}
.pill-link:hover { background: var(--tint-blue); color: var(--blue-hover);
  border-color: var(--blue-hover); text-decoration: none; }
/* filled variant — external destinations (Rewards, Quote Other Lines) */
.pill-link-filled { background: var(--blue); color: #fff; border-color: var(--blue); }
.pill-link-filled:hover { background: var(--blue-hover); border-color: var(--blue-hover);
  color: #fff; }
.chrome-actions { margin-left: auto; display: flex; flex-wrap: wrap;
  gap: var(--sp-2); align-items: center; min-width: 0; }
/* ITEM 2 (owner walkthrough 2026-08-27): on the AGENT chrome the mount
   moves `.chrome-nav` INSIDE this row so the header is one line rather
   than two (the measurement and the reasoning are in session.js). The
   nav's 16px left inset is what separated it from the logo when it was a
   sibling; inside the action row the row's own gap does that job, and the
   inset would read as a stray space before the first pill. Everything
   else about the nav is untouched, deliberately - including the phones
   rule below, which still finds it. */
.chrome-actions .chrome-nav { margin-left: 0; }

/* THE CHROME WRAPS BEFORE IT PUSHES THE PAGE SIDEWAYS (spec 1.6;
   front-door entry item 5, 2026-08-15).

   FOUND BY MEASURING, NOT BY READING, and the measurement is worth
   recording because the answer was not what it looked like. The agent
   board at 768px was already scrolling sideways by 79px BEFORE this
   entry - two promotion pills, an identity chip and a logo on one
   nowrap row - and adding the sign-out control took it to 183px. So this
   is a pre-existing 1.6 defect that item 5 widened rather than one item 5
   introduced, and both halves are closed here.

   The pills carry `white-space: nowrap` deliberately (a wrapped "Quote
   Other Lines" reads as two links), so the row cannot shrink and must
   WRAP instead. 900px rather than 768px: the overflow starts well above
   the tablet breakpoint, and a rule that only fixes the width somebody
   measured is a rule that leaves the widths nobody did. */
/* WRAPPING MOVED TO THE BASE RULES ABOVE ON 2026-08-16, so what is left
   here is only what is genuinely about NARROW widths: a tighter gap, the
   nav losing its left inset, the identity reading left rather than right.
   The `flex-wrap: wrap` declarations that used to live here are gone
   rather than duplicated - a property set in two places is a property
   somebody will change in one of them. */
@media (max-width: 900px) {
  .chrome-inner { gap: var(--sp-3); }
  .chrome-nav { margin-left: 0; }
  .chrome-actions { row-gap: var(--sp-2); }
  .chrome-user { text-align: left; }
}

.content { max-width: var(--content-max); margin: 0 auto; padding: var(--sp-6) var(--sp-5) var(--sp-8); }

/* =========================================================================
   Buttons
   ========================================================================= */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: inherit; font-weight: var(--fw-semibold); font-size: 15px;
  border-radius: var(--r-ctl); padding: 12px 22px;
  border: 1px solid transparent; cursor: pointer;
  transition: background .12s ease, border-color .12s ease, box-shadow .12s ease;
  white-space: nowrap;
}
.btn-primary { background: var(--green); color: #fff; }
.btn-primary:hover { background: var(--green-hover); }
.btn-secondary-onnavy {
  background: transparent; color: var(--on-navy);
  border-color: var(--on-navy-border);
}
.btn-secondary-onnavy:hover { background: var(--on-navy-pill); }
.btn-secondary { background: var(--card); color: var(--navy); border-color: var(--border-strong); }
.btn-secondary:hover { border-color: var(--navy); }
/* item 6b (2026-08-26): the SMALL step of the button scale, named. The
   dashboard's New quote pill has worn exactly this size inline since C2
   (9px 18px, 14px) - this is that de-facto small tier as a class, so a
   green action can rank below the page's primary without leaving the
   scale. */
.btn-sm { padding: 9px 18px; font-size: 14px; }
.btn[disabled], .btn.is-disabled {
  background: var(--disabled-bg); color: var(--disabled-fg);
  border-color: transparent; cursor: not-allowed; box-shadow: none;
}

/* =========================================================================
   Status badges — pill + icon; the only colored elements outside the hero
   ========================================================================= */
.badge {
  display: inline-flex; align-items: center; gap: 7px;
  border-radius: var(--r-pill); padding: 5px 13px;
  font-size: var(--fs-small); font-weight: var(--fw-semibold);
  white-space: nowrap;
}
.badge .dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: none; }
.badge-quoted     { background: var(--tint-green); color: var(--green-ink); }
.badge-indicative { background: var(--amber-tint); color: var(--amber-ink); }
.badge-referred   { background: var(--amber-tint); color: var(--amber-ink); }
.badge-declined   { background: var(--red-tint);   color: var(--red-ink); }
.badge-bound      { background: var(--tint-green); color: var(--green-ink); }
.badge-bindreq    { background: var(--tint-blue);  color: var(--navy); }
.badge-draft      { background: var(--neutral-tint); color: var(--neutral-ink); }
.badge-imported   { background: var(--neutral-tint); color: var(--neutral-ink); }
/* on-navy variants (inside the hero) */
.badge-onnavy-quoted     { background: rgba(224,240,223,.95); color: var(--green-ink); }
.badge-onnavy-indicative { background: rgba(253,243,216,.95); color: var(--amber-ink); }
.badge-onnavy-referred   { background: rgba(253,243,216,.95); color: var(--amber-ink); }

/* =========================================================================
   Hero band (quote result) — navy owns this
   ========================================================================= */
.hero {
  background: linear-gradient(135deg, var(--navy) 0%, var(--navy-deep) 100%);
  color: var(--on-navy);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-hero);
  padding: var(--sp-6);
}
.hero-top { display: flex; align-items: flex-start; gap: var(--sp-4); }
.hero-eyebrow { color: var(--on-navy-soft); }
.hero-meta { margin-left: auto; display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; justify-content: flex-end; }
.hero-expiry { color: var(--on-navy-soft); font-size: var(--fs-small); white-space: nowrap; }
/* on a phone the expiry line may take two lines (standing rule 366: it ran
   to 350 at 320 on the cloud's widest letters) */
@media (max-width: 480px) { .hero-expiry { white-space: normal; } }
.hero-expiry b { color: var(--on-navy); font-weight: var(--fw-semibold); }

.hero-premium {
  font-size: var(--fs-hero); line-height: var(--lh-hero);
  font-weight: var(--fw-hero); letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
  margin-top: var(--sp-3);
}
.hero-premium .cents { font-size: .45em; font-weight: var(--fw-semibold); color: var(--on-navy-soft); }
.hero-sub { color: var(--on-navy-soft); font-size: var(--fs-small); margin-top: var(--sp-1); }

.hero-pills { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-4); }
.pill {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--on-navy-pill); border: 1px solid var(--on-navy-border);
  color: var(--on-navy); border-radius: var(--r-pill);
  padding: 5px 13px; font-size: var(--fs-small);
}
.pill .k { color: var(--blue-pale); font-weight: var(--fw-semibold); }
/* THE DIVIDEND CHIP'S CHECK (owner ruling 2026-09-23, item 4). Green is
   the money colour on this platform and a dividend is money back, so the
   mark is green - `--tint-green`, not `--green`, because the chip sits on
   the navy hero and the solid green does not carry there. The MEANING is
   in the words beside it ("Dividend included"): the mark is decorative,
   carries `aria-hidden`, and nothing about this chip is colour alone. */
.pill .k.pill-ok { color: var(--tint-green); }
.pill .k.pill-ok .pill-ok-svg { display: inline-block; vertical-align: -1px; }

.hero-actions {
  display: flex; gap: var(--sp-3); margin-top: var(--sp-5);
  padding-top: var(--sp-5); border-top: 1px solid var(--on-navy-border);
  align-items: center; flex-wrap: wrap;
}
.hero-actions .hint { color: var(--on-navy-soft); font-size: var(--fs-small); margin-left: auto; }

/* ---- quoted-hero landing layout (owner rulings 2-4, 2026-08-03) ----
   "Get my quote" now lands directly here (the in-flow result box is
   retired), so the quoted hero is the accomplishment moment: left column =
   premium with the bind action directly under it (the ruled first-time-user
   failure: the action must be unmistakable on arrival); right column = the
   rewards/commission panel, grown from the retired box's presentation.
   Only renderQuoted uses .hero-cols — other status heroes keep the plain
   stacked hero and its bordered .hero-actions row. */
.hero-cols { display: flex; gap: var(--sp-6); align-items: stretch; }
.hero-main { flex: 1 1 auto; min-width: 0; }
.hero-cols .hero-actions { border-top: 0; padding-top: 0; margin-top: var(--sp-5); }
.btn-bind-hero { font-size: 16.5px; padding: 14px 30px; }
.hero-bind-hint { color: var(--on-navy-soft); font-size: var(--fs-small); margin-top: var(--sp-2); }
.hero-cols + .hero-pills { margin-top: var(--sp-5); padding-top: var(--sp-5);
  border-top: 1px solid var(--on-navy-border); }

/* rewards — the exciting one, right side of the hero; commission sits
   quietly beneath it (deliberately separated presentations, owner
   direction carried over from the retired box) */
.hero-incentive { flex: 0 0 auto; display: flex; flex-direction: column;
  justify-content: center; gap: var(--sp-3); max-width: 300px;
  border-left: 1px solid var(--on-navy-border); padding-left: var(--sp-6); }
.hero-incentive .reward { display: flex; gap: 14px; align-items: flex-start; }
.reward-star { font-size: 28px; line-height: 1.1; color: var(--amber);
  animation: reward-pop .5s ease; }
@keyframes reward-pop { 0% { transform: scale(.4) rotate(-20deg); opacity: 0; }
  70% { transform: scale(1.15) rotate(4deg); } 100% { transform: none; opacity: 1; } }
.reward-lines { display: grid; gap: 1px; }
.reward-lead { color: var(--on-navy-soft); font-size: var(--fs-small); }
.reward-points { font-size: 30px; font-weight: 750; letter-spacing: -0.01em;
  color: #fff; line-height: 1.1; }
.reward-what { font-size: var(--fs-small); font-weight: var(--fw-semibold);
  color: var(--blue-pale); text-transform: uppercase; letter-spacing: .06em; }
.reward-note { color: var(--on-navy-soft); font-size: var(--fs-small); }
.hero-commission { font-size: var(--fs-small); color: var(--on-navy-soft); }
.hero-commission b { color: #fff; font-weight: var(--fw-semibold); }
.hero-incentive-note { color: var(--on-navy-soft); font-size: var(--fs-label);
  text-transform: uppercase; letter-spacing: .05em; opacity: .8; }
@media (max-width: 760px) {
  .hero-cols { flex-direction: column; gap: var(--sp-4); }
  .hero-incentive { border-left: 0; padding-left: 0; max-width: none;
    border-top: 1px solid var(--on-navy-border); padding-top: var(--sp-4); }
}
/* inline message (right above the plan cards) when Request bind / Download
   proposal is clicked before a payment plan is chosen — solid amber so it's
   impossible to miss. .is-info is the calmer navy-on-tint-blue note. */
.action-msg {
  margin: 0 0 var(--sp-4); padding: 13px 18px; border-radius: var(--r-card);
  font-weight: var(--fw-semibold); font-size: 15px;
  color: var(--ink); background: var(--amber);
  box-shadow: var(--shadow-card);
}
.action-msg:not(.is-info)::before { content: "\26A0"; margin-right: 9px; }
.action-msg.is-info {
  color: var(--navy); background: var(--tint-blue);
  border-left: 4px solid var(--blue); font-size: var(--fs-body);
}

/* RULING 15b (2026-08-06): the bind-requested COMPLETION experience — a
   state that reads "done and in good hands" at a glance, clearly different
   from the quote page: green check disc, completion statement, the
   three-step journey strip, condensed facts, and the rewards energy band.
   Tokens only; green = success per the color discipline. */
.hero--done { display: flex; gap: var(--sp-5); align-items: flex-start; }
.done-check { flex: none; width: 64px; height: 64px; border-radius: 50%;
  background: var(--green); color: #fff; font-size: 34px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow-card); }
.done-body { flex: 1; min-width: 0; }
.done-title { font-size: var(--fs-h1); font-weight: var(--fw-semibold);
  margin-top: 4px; }
.done-sub { color: var(--on-navy-soft); margin-top: 8px; max-width: 62ch; }
.done-sub b { color: var(--on-navy, #fff); }
.done-steps { display: flex; gap: 0; list-style: none; padding: 0;
  margin: 18px 0 0; flex-wrap: wrap; }
.done-steps li { display: flex; align-items: center; gap: 8px;
  font-size: var(--fs-small); font-weight: var(--fw-semibold);
  color: var(--on-navy-soft); padding: 7px 14px;
  border: 1px solid var(--on-navy-border); background: var(--on-navy-pill); }
.done-steps li:first-child { border-radius: var(--r-pill) 0 0 var(--r-pill); }
.done-steps li:last-child { border-radius: 0 var(--r-pill) var(--r-pill) 0; }
.done-steps li + li { border-left: 0; }
.done-steps .ic { width: 16px; height: 16px; border-radius: 50%; flex: none;
  border: 2px solid var(--on-navy-border); font-size: 10px; line-height: 12px;
  text-align: center; }
.done-steps .is-done { color: var(--on-navy, #fff); }
.done-steps .is-done .ic { background: var(--green); border-color: var(--green);
  color: #fff; }
.done-steps .is-now { color: var(--on-navy, #fff); }
.done-steps .is-now .ic { border-color: var(--amber); background: var(--amber); }
.done-facts { display: flex; gap: var(--sp-4); flex-wrap: wrap; margin-top: 18px; }
.done-fact .k { display: block; font-size: var(--fs-label); color: var(--on-navy-soft);
  text-transform: uppercase; letter-spacing: .08em; font-weight: var(--fw-semibold); }
.done-fact .v { display: block; font-size: 19px; font-weight: var(--fw-semibold);
  margin-top: 2px; font-variant-numeric: tabular-nums; }
.done-yr { font-size: .6em; color: var(--on-navy-soft); }
.done-reward { display: flex; gap: 14px; align-items: center; margin-top: 18px;
  background: var(--on-navy-pill); border: 1px solid var(--on-navy-border);
  border-radius: var(--r-card); padding: 14px 18px; max-width: 560px; }
.done-reward-star { flex: none; width: 40px; height: 40px; border-radius: 50%;
  background: var(--amber); color: var(--amber-ink); font-size: 20px;
  display: flex; align-items: center; justify-content: center; }
.done-reward-lead { font-size: 17px; font-weight: var(--fw-semibold); }
.done-reward-note { color: var(--on-navy-soft); font-size: var(--fs-small);
  margin-top: 2px; }
@media (max-width: 640px) {
  .hero--done { flex-direction: column; gap: var(--sp-3); }
  .done-steps li { flex: 1 1 auto; justify-content: center; }
}

/* Rulings 15c + A2 (2026-08-06): the shared other-lines promotion — the
   obvious next step, one component, three registers
   (celebrate | pivot | review) so the surfaces that carry it never drift.
   D4 (owner defect 2026-08-06) added "review" for the referred screen:
   navy, the informational family — under review is neither a win nor a
   dead end, so it borrows neither the green nor the pivot blue. */
.olp { display: flex; align-items: center; gap: var(--sp-5);
  background: var(--card); border: 1px solid var(--border);
  border-left: 5px solid var(--green); border-radius: var(--r-card);
  box-shadow: var(--shadow-card); padding: var(--sp-5) var(--sp-6);
  flex-wrap: wrap; }
.olp--celebrate { border-left-color: var(--green); }
.olp--pivot { border-left-color: var(--blue); }
.olp--review { border-left-color: var(--navy); }
.olp-body { flex: 1; min-width: 260px; }
.olp-eyebrow { font-size: var(--fs-label); text-transform: uppercase;
  letter-spacing: .12em; font-weight: var(--fw-semibold); color: var(--green-ink); }
.olp--pivot .olp-eyebrow { color: var(--blue); }
.olp--review .olp-eyebrow { color: var(--navy); }
.olp h2 { font-size: var(--fs-h2); font-weight: var(--fw-semibold); margin-top: 4px; }
.olp-lead { color: var(--ink-soft); margin-top: 6px; }
.olp-lines { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin-top: 12px; }
.olp-line { display: inline-flex; align-items: baseline; gap: 7px;
  background: var(--tint-blue); color: var(--navy); border-radius: var(--r-pill);
  padding: 6px 14px; font-weight: 700; font-size: 15px; }
.olp-line span { font-weight: var(--fw-regular, 400); font-size: var(--fs-small);
  color: var(--ink-soft); }
.olp-acord { margin-top: 12px; font-size: var(--fs-small); color: var(--ink-soft); }
.olp-acord::before { content: "\2913"; margin-right: 7px; color: var(--blue);
  font-weight: 700; }
.olp-cta { flex: none; }
@media (max-width: 640px) { .olp-cta { width: 100%; text-align: center; } }

/* THE BROKERAGE TRIGGER AND ECHO on the declined page (brokerage entry
   1a, 2026-09-05). The pivot register's visual language - the eyebrow,
   the h2, the soft lead, the blue rule - in its own class family so the
   pivot's own rules are not touched and a switched-off page renders
   exactly as before. `.brk-actions .btn` takes the row on a phone, the
   `.olp-cta` rule's own breakpoint. */
.brk-card { padding: 20px 24px; border-left: 4px solid var(--blue); }
.brk-eyebrow { font-size: var(--fs-label); text-transform: uppercase;
  letter-spacing: .06em; color: var(--blue); }
.brk-card h2 { font-size: var(--fs-h2); font-weight: var(--fw-semibold); margin-top: 4px; }
.brk-lead { color: var(--ink-soft); margin-top: 6px; }
.brk-actions { margin-top: 16px; display: flex; gap: 10px; flex-wrap: wrap;
  align-items: center; }
.brk-status { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 8px; }
.brk-facts { color: var(--ink-soft); margin-top: 8px; }
.brk-facts b { color: var(--ink); }
@media (max-width: 640px) { .brk-actions .btn { width: 100%; text-align: center; } }
/* THE ONE CARD (brokerage entry 1b, item 1, 2026-09-06): the decline in
   one line at the top of the card (and, after a send, on its own beneath
   the echo), and the second look as a QUIET tertiary - a text button in
   the link colour, no box, so it cannot outrank the two buttons above
   it. The field it opens is master's own .sl-row. */
.brk-decline { font-size: var(--fs-small); color: var(--ink-soft); margin: 0 0 12px; }
.brk-decline-lead { color: var(--red-ink); font-weight: var(--fw-semibold); }
.brk-decline-section { margin-top: 12px; }
.brk-decline-section .brk-decline { margin: 0; padding: 0 4px; }
.brk-tertiary { margin-top: 14px; }
.brk-quiet { background: none; border: 0; padding: 0; font: inherit;
  font-size: var(--fs-small); color: var(--blue); cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px; }
.brk-quiet:hover, .brk-quiet:focus-visible { color: var(--navy); }
/* THE NO-MARKET TWIN'S INLINE LINK (item 8): brk-quiet's look, but it flows
   inside a sentence, so it keeps the paragraph's own size. */
.brk-linkbtn { background: none; border: 0; padding: 0; font: inherit;
  color: var(--blue); cursor: pointer; text-decoration: underline;
  text-underline-offset: 3px; }
.brk-linkbtn:hover, .brk-linkbtn:focus-visible { color: var(--navy); }
.brk-sl-form { margin-top: 10px; }
/* THE ECHO'S FOUR BEATS (entry 1b, item 3): one row per line - code,
   chip, the sentence for now, the facts - each its own element with
   whitespace between (the spacing defect of 1a was two adjacent inline
   spans); then the two labelled beats. At 640 the row stacks. */
.brk-lines { list-style: none; margin: 10px 0 0; padding: 0; }
.brk-line-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px;
  padding: 8px 0; border-top: 1px solid var(--line, #e6e8ec); }
.brk-line-row:first-child { border-top: 0; padding-top: 4px; }
.brk-line-code { font-size: var(--fs-label); font-weight: var(--fw-semibold);
  letter-spacing: .06em; color: var(--navy); min-width: 2.2em; }
.brk-line-now { color: var(--ink); flex: 1 1 260px; }
.brk-line-row .brk-facts { margin-top: 0; flex-basis: 100%; font-size: var(--fs-small); }
.brk-beat { margin-top: 14px; }
.brk-beat-label { font-size: var(--fs-label); text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-soft); }
.brk-beat-text { margin: 4px 0 0; color: var(--ink); }
/* ADD A LINE AT SEND (entry 1b, item 4): the ticks in a row, each ticked
   line's panel beneath with the blue rule the card family uses, the
   questions two-up on a desk and one-up on a phone, the money field with
   its dollar sign, the excess underlying rows with their status word. */
.brk-add { margin-top: 16px; }
.brk-ticks { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: 6px; }
.brk-tick { display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  color: var(--ink); }
.brk-tick input { width: 18px; height: 18px; margin: 0; }
.brk-panel { margin-top: 12px; padding: 12px 0 4px 14px;
  border-left: 3px solid var(--tint-blue); }
.brk-qs { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 18px; }
.brk-q label { display: block; margin-bottom: 4px; }
.brk-q .brk-sub { margin-top: 6px; }
/* THE MONEY AND THE ASK ON A LINE ROW (brokerage entry 1c, 2026-09-07):
   the indication's softer variant, the firm-up action item, and the
   firm quote's total-cost block - each a block of its own below the
   line's facts, full width on the row. */
.brk-indication { flex-basis: 100%; margin-top: 4px; padding: 8px 12px; border-radius: 8px;
  background: var(--amber-tint, #fff6e5); color: var(--ink-soft); font-size: var(--fs-small); }
.brk-indication b { color: var(--ink); }
.brk-ask { flex-basis: 100%; margin-top: 8px; padding: 10px 14px; border-radius: 8px;
  border: 1px solid var(--tint-blue, #dbe7f6); background: var(--tint-blue, #eef4fb); }
.brk-ask-list { margin: 6px 0 0; padding-left: 20px; }
.brk-ask-list li { margin: 2px 0; }
.brk-ask-text { margin: 6px 0 0; color: var(--ink); }
.brk-ask-how { color: var(--ink-soft); font-size: var(--fs-small); }
.brk-quote { flex-basis: 100%; margin-top: 8px; padding: 12px 14px; border-radius: 8px;
  background: var(--tint-green, #e9f5ee); }
.brk-quote-total { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.brk-quote-total b { font-size: var(--fs-h2); }
.brk-quote-per { color: var(--ink-soft); font-size: var(--fs-small); }
.brk-quote-lines { list-style: none; margin: 8px 0 0; padding: 0; }
.brk-quote-lines li { display: flex; justify-content: space-between; gap: 12px;
  padding: 3px 0; border-top: 1px solid rgba(0,0,0,.06); font-size: var(--fs-small); }
.brk-quote-meta { margin-top: 8px; color: var(--ink-soft); font-size: var(--fs-small); }
.brk-subj li.is-done { text-decoration: line-through; color: var(--ink-soft); }
/* THE PROPOSAL CARD (proposal engine v1, item 4, 2026-09-16): the link
   the agent hands their insured, on the quote block's own footing. */
.brk-proposal { flex-basis: 100%; margin-top: 10px; padding: 12px 14px; border-radius: 8px;
  background: var(--tint-blue, #cfe9f7); }
.brk-proposal-url { display: block; width: 100%; margin-top: 8px; font: inherit; font-size: var(--fs-small);
  padding: 7px 9px; border: 1px solid var(--border); border-radius: 6px; background: #fff; color: var(--ink); }
.brk-proposal-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.brk-money { display: flex; align-items: center; gap: 6px; }
.brk-money span { color: var(--ink-soft); }
.brk-money input { flex: 1 1 auto; }
.brk-field-label { display: block; font-weight: var(--fw-semibold); margin-bottom: 6px; }
.brk-limits { margin-top: 12px; }
.brk-limits .brk-tick { margin-right: 18px; }
.brk-limits .hint { display: block; margin-top: 6px; }
.brk-under-list { margin-top: 12px; }
.brk-under { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px;
  padding: 6px 0; }
.brk-under-status { font-size: var(--fs-small); color: var(--ink-soft); }
.brk-under-status[data-status="held"] { color: var(--green-ink); }
.brk-under-status[data-status="pending"] { color: var(--navy); }
@media (max-width: 640px) {
  .brk-qs { grid-template-columns: 1fr; }
  .brk-ticks { flex-direction: column; gap: 10px; }
}
/* ATTACHMENTS AT SEND (entry 1b, item 5): the picker row and the list of
   what is waiting to go with the click; an underlying line's own picker
   sits in its row when that line is placed elsewhere. */
.brk-attach { margin-top: 16px; }
.brk-attach-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.brk-attach-row select { flex: 0 1 220px; }
.brk-attach-list { list-style: none; margin: 8px 0 0; padding: 0; }
.brk-attach-list li { padding: 4px 0; }
.brk-attach-kind { display: inline-block; padding: 1px 8px; border-radius: 999px;
  background: var(--neutral-tint); color: var(--neutral-ink);
  font-size: var(--fs-small); margin-right: 6px; }
.brk-under-file { flex-basis: 100%; }
/* THE ROW'S CHIPS (entry 1b, item 2; RE-CUT by the agent-side polish,
   items 6 and 9, rulings 137 and 140, 2026-09-22): one chip per line sent,
   EVERY chip prefixed with its line code (the WC's too), stacked vertically
   in a column - one line per chip, left-aligned - never wrapping side by
   side. */
.brk-row-stack { display: inline-flex; flex-direction: column; align-items: flex-start;
  gap: 4px; vertical-align: top; }
.brk-row-chip { margin-top: 0; white-space: nowrap; }
/* ONE LINE'S CHIP IS ITS WORDS (ruling 174, 2026-09-23): "WC · quoted ·
   Normandy" in the chip, and a firm quote past its date says so BESIDE it
   rather than inside, so the chip's words stay the inbox pill's */
.brk-row-line-wrap { display: inline-flex; align-items: center; gap: 6px; }
.brk-row-expired { font-size: var(--fs-small); color: var(--ink-soft); white-space: nowrap; }
/* THE SHOPPING STORY (agent-side brokerage polish, item 4, ruling 135,
   2026-09-22). The echo read flat: one bordered card, a list of rows. It
   is the home of the story now - a head that names what is being shopped,
   ONE CARD PER LINE (the line's code as a navy pill, its name, the status
   chip; the sentence for now; the facts; then the money, the package, the
   underwriter's ask and the proposal as blocks of the card), the lead that
   says whether anything is wanted, and the two beats side by side. The
   ruled vocabulary is untouched - this is presentation. Three widths: the
   beats and the card head reflow at 640, buttons take the row on a phone.
   The card keeps `display:flex; flex-wrap:wrap` (the 1a spacing-defect
   pin) - a wrapping flex column is a card. */
.brk-story-card { border-left: 0; padding: 22px 24px 20px;
  background: linear-gradient(180deg, var(--card) 0, var(--card) 72px, var(--page, #f6f7f9) 72px, var(--page, #f6f7f9) 100%); }
.brk-story-head { padding-bottom: 14px; }
.brk-story-head h2 { margin-top: 4px; }
.brk-story-sub { margin: 4px 0 0; color: var(--ink-soft); font-size: var(--fs-small); }
/* one column that may shrink (standing rule 366: a line card came to 359px
   in a 309px list at 375 on the cloud's fonts, gate 37136165972) */
.brk-story .brk-lines { display: grid; gap: 12px; margin-top: 6px;
  grid-template-columns: minmax(0, 1fr); }
.brk-line-card { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px 12px;
  padding: 14px 16px 14px; border: 1px solid var(--border); border-left: 4px solid var(--blue);
  border-radius: 12px; background: var(--card); box-shadow: var(--shadow-card); }
.brk-line-card:first-child { border-top: 1px solid var(--border); padding-top: 14px; }
.brk-line-card[data-status="firm_quote"], .brk-line-card[data-status="bind_requested"],
.brk-line-card[data-status="bound"] { border-left-color: var(--green-ink); }
.brk-line-card[data-status="indication"] { border-left-color: var(--amber-ink); }
.brk-line-card[data-status="lost"], .brk-line-card[data-status="declined_by_markets"] {
  border-left-color: var(--border-strong, #c9ced6); }
.brk-line-head { flex-basis: 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
.brk-line-card .brk-line-code { display: inline-block; padding: 2px 8px; border-radius: 6px;
  background: var(--navy); color: #fff; min-width: 0; line-height: 1.4; }
.brk-line-name { font-weight: var(--fw-semibold); color: var(--ink); }
/* the card's chips STACK (ruling 140): the status chip, then the
   items-needed overlay beneath it, right-aligned on a desk */
.brk-line-chips { margin-left: auto; display: flex; flex-direction: column;
  align-items: flex-end; gap: 4px; }
.brk-items-needed { font-size: 11px; }
/* the head's line pills (ruling 138): a grouping device, no status */
.brk-head-lines { display: inline-flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.brk-head-lines .brk-line-code { display: inline-block; padding: 2px 8px; border-radius: 6px;
  background: var(--navy); color: #fff; min-width: 0; line-height: 1.4; }
.brk-line-card .brk-line-now { flex-basis: 100%; margin: 2px 0 0; }
.brk-line-card .brk-facts { margin-top: 0; }
.brk-line-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.brk-line-card .brk-quote, .brk-line-card .brk-ask, .brk-line-card .brk-indication,
.brk-line-card .brk-proposal { margin-top: 10px; }
.brk-line-card .brk-quote { background: var(--tint-green, #e9f5ee); border: 1px solid rgba(0,0,0,.05); }
.brk-line-card .brk-quote-total b { font-size: 28px; line-height: 1.1; }
.brk-package { flex-basis: 100%; margin-top: 10px; padding: 12px 14px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--card); }
/* the ACORD 125/126 downloads (ruling 232): a label wraps rather than widen the card at 375 */
.brk-acord .btn { white-space: normal; text-align: left; max-width: 100%; }
.brk-lead--ask { color: var(--amber-ink, #a15c00); font-weight: var(--fw-semibold); }
/* SEND A DOCUMENT (item 5, ruling 136): the zone on the story's soft
   ground, the ask beneath it, the sent list as line pill + kind + name. */
.brk-upload { margin-top: 14px; padding: 14px 16px; border-radius: 12px;
  border: 1px dashed var(--border-strong, #c9cedb); background: var(--card); }
.brk-upload-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.brk-upload-caption { margin: 2px 0 10px; color: var(--ink); font-weight: var(--fw-semibold); }
.brk-upload .dz-ask { margin-top: 10px; }
.brk-sent-list { list-style: none; margin: 6px 0 0; padding: 0; }
.brk-sent-list li { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
  padding: 6px 0; border-top: 1px solid var(--border); font-size: var(--fs-small); }
.brk-sent-list .brk-line-code { display: inline-block; padding: 1px 7px; border-radius: 6px;
  background: var(--navy); color: #fff; min-width: 0; }
.brk-sent-name { color: var(--ink); }
.brk-sent-date { color: var(--ink-soft); margin-left: auto; }
.brk-beats { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 24px; margin-top: 4px; }
.brk-beats .brk-beat { margin-top: 14px; padding: 12px 14px; border-radius: 8px;
  background: var(--card); border: 1px solid var(--border); }
@media (max-width: 640px) {
  .brk-beats { grid-template-columns: 1fr; gap: 0; }
  .brk-line-chips { margin-left: 0; align-items: flex-start; flex-basis: 100%; }
  .brk-line-acts .btn { width: 100%; text-align: center; }
  .brk-quote-acts .btn { width: 100%; text-align: center; }
  .brk-story-card { padding: 18px 16px 16px; }
}

/* RULING 7 (owner, 2026-08-06): the celebrate register — the bind
   confirmation's "Keep going" — is rebuilt as the NEXT STEP rather than a
   footer ad: take the completed application, drop it in, go. Two numbered
   steps in quiet navy discs (no colour blocks, no second CTA competing
   with the portal link, no exclamation marks: cool, not loud), and the
   ACORD 130 slot inside step one.
   The slot degrades GRACEFULLY until 4C ships the generator — the
   coming-soon state is not an <a> at all, so there is no link to break;
   it reads as a shelf with the file's name already on it. Token-only. */
.olp--next .olp-steps { list-style: none; padding: 0; margin: var(--sp-4) 0 0;
  display: grid; gap: var(--sp-3); }
.olp--next .olp-steps li { display: flex; gap: 12px; align-items: flex-start;
  color: var(--ink); }
.olp-step-n { flex: none; width: 24px; height: 24px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--navy); color: var(--on-navy, #fff);
  font-size: var(--fs-label); font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums; }
.olp-acord-slot { display: flex; align-items: center; gap: 12px;
  margin-top: 10px; padding: 11px 14px; background: var(--page);
  border: 1px solid var(--border); border-radius: var(--r-ctl);
  flex-wrap: wrap; }
.olp-acord-icon { flex: none; width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--tint-blue); color: var(--blue); font-weight: 700; }
.olp-acord-text { flex: 1; min-width: 12rem; display: grid; }
.olp-acord-text b { font-weight: var(--fw-semibold); color: var(--ink); }
.olp-acord-text span { font-size: var(--fs-small); color: var(--ink-soft); }
/* .olp-soon / .olp-acord-slot.is-soon REMOVED 2026-08-07 (batch 4C Part
   3): they styled the ACORD slot's coming-soon pill and greyed icon. The
   download is live and that branch is gone from quote_result.html, so the
   rules had no selector left to match. */

/* Amendment A3 (2026-08-06): the referred hero's review band — the state
   reads in the hero itself: amber presence on navy, icon-dot + text (never
   color alone), the one-business-day expectation up front */
.hero-review-band { display: inline-flex; align-items: center; gap: 10px;
  margin-top: 12px; padding: 9px 16px; border-radius: var(--r-pill);
  background: var(--on-navy-pill); border: 1px solid var(--amber);
  color: var(--on-navy, #fff); font-size: var(--fs-small);
  font-weight: var(--fw-semibold); }
.hero-review-band .dot { width: 9px; height: 9px; border-radius: 50%;
  background: var(--amber); flex: none; }

/* =========================================================================
   Referred: helping the underwriter (owner rulings 1/2/3/5, 2026-08-06)
   -------------------------------------------------------------------------
   Ruling 2 — the note is SUBSTANTIALLY bigger. A single-line input said
   "a few words"; what actually moves a referral is a paragraph, so the
   control now looks like one and can be dragged taller.
   Ruling 5 — "Send to underwriter" is the primary action of its card, not
   a white secondary indistinguishable from "Back to dashboard".
   Ruling 3 — the loss-runs encouragement leaves .callout-note, which is
   this app's "this is optional / doesn't affect the premium" pill and is
   therefore exactly what an agent has learned to skim. It becomes a warm
   amber field in the REFERRAL family (not the informational blue), badge-
   anchored, headline-first, with the upload control inside it so the
   encouragement and the doing are one object.
   Token-only; no new colour.
   ========================================================================= */
.rn-note { width: 100%; min-height: 7.5rem; resize: vertical; font: inherit;
  color: var(--ink); background: var(--card);
  border: 1px solid var(--border-strong); border-radius: var(--r-ctl);
  padding: 11px 13px; line-height: var(--lh-body); }
.rn-note:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px;
  border-color: var(--blue); }
.rn-actions { display: flex; align-items: flex-end; gap: var(--sp-4);
  flex-wrap: wrap; margin-top: var(--sp-3); }
.rn-target { max-width: 12rem; }
/* .btn-lg retired with the 2026-08-07 re-flow (owner ruling 2): "Send to
   underwriter" stepped back to the regular green primary, and nothing
   else used the size. */
@media (max-width: 640px) {
  .rn-actions { display: grid; }
  .rn-target { max-width: none; }
  .rn-actions .btn { width: 100%; }
}

/* THE LOSS-RUNS PANEL FAMILY IS RETIRED (owner ruling 5, 2026-08-20).
   `.speedup` styled the loss-runs encouragement and its own upload door on
   the referred page. That page now carries ONE combined upload zone,
   shared with the bind page and living inside the forms panel, so this
   family had no users left.

   IT IS DELETED RATHER THAN LEFT, which is the opposite of what was done
   with the retired otherLinesPromo registers - deliberately. Those
   registers are still PINNED BY TESTS for their copy, so leaving them
   byte-identical keeps a live subject readable. Nothing pins these rules,
   so leaving them would only tell the next editor that a `.speedup` panel
   still renders somewhere.

   What ruling 3 protected is unchanged and is pinned in
   test_referred_experience_r1_r2_r3_r5: the encouragement is not a
   callout-note an agent has learned to skim, and the door sits where the
   agent is being asked for things. */

/* referral panel inside the amber-status hero geometry */
.refer-panel {
  background: var(--card); border: 1px solid var(--border);
  border-left: 4px solid var(--amber);
  border-radius: var(--r-card); box-shadow: var(--shadow-card);
  padding: var(--sp-5) var(--sp-6);
}
.refer-panel h2 { font-size: var(--fs-h2); }
/* ruling 9 (batch three, 2026-08-05): the referred state reads immediately —
   prominent but sleek: the lead panel warms to the amber tint and the ruled
   sentence renders at full body ink, not the soft grey */
.refer-panel--lead {
  background: linear-gradient(180deg, var(--amber-tint), var(--card) 55%);
  border-left-width: 5px;
}
.refer-panel--lead h2 { display: flex; align-items: center; gap: 8px; }
.refer-lead-body { color: var(--ink); margin: 6px 0 0;
  font-size: var(--fs-body); line-height: var(--lh-body); max-width: 72ch; }
/* rulings 4/5 (2026-08-05): the commission % line sits under the
   binding-review sentence in the hero */
.hero-main .hero-commission { margin-top: 4px; }

/* Batch-three ruling 14 (2026-08-05): dashboard return recognition — the
   row the agent just worked greets them back: a soft navy-tint highlight
   fading over ~2s plus a "just now" chip. CSS-driven (one animation, no
   polling); the chip carries the signal for reduced-motion users — never
   color alone.
   D5 (owner ruling 2026-08-06): the signal FADES AND VANISHES. The chip
   used to stay wedged between the insured name and the id until the next
   reload, breaking the column's alignment down the list; it now fades out
   and is removed, leaving the row exactly as it was. The signal is
   decoration only — it never changes the board's sort order. */
@keyframes rowReturn { from { background: var(--tint-blue); }
                       to   { background: transparent; } }
.row-return td { animation: rowReturn 2s ease-out 1; }
.chip-justnow { display: inline-block; margin-left: 8px;
  font-size: var(--fs-label); font-weight: var(--fw-semibold);
  color: var(--navy); background: var(--tint-blue);
  border-radius: var(--r-pill); padding: 2px 9px; white-space: nowrap; }
@keyframes chipGoing { from { opacity: 1; } to { opacity: 0; } }
.chip-justnow.is-going { animation: chipGoing .4s ease-out forwards; }
@media (prefers-reduced-motion: reduce) {
  .row-return td { animation: none; }
  /* no fade to watch — the script's fallback timer removes the chip */
  .chip-justnow.is-going { animation: none; opacity: 0; }
}
/* item 4 (2026-08-26): the agent board's mail icon - beside an account
   name whose thread holds a message the agent has not read. Renders
   from the same GET /messages/unread the nav badge reads.

   MADE NOTICEABLE (owner walkthrough 2026-08-27), AND THE ESTABLISH
   FOUND A SECOND DEFECT UNDERNEATH THE FIRST. The rule below used to say
   `color: var(--navy)` and the icon RENDERED GREY - measured in the pane
   at rgb(138,137,141). `.board .insured > span` (0,2,1) out-specifies a
   bare `.row-mail` (0,1,0) and was setting both the colour and a 12.5px
   size, so the navy this rule declared never reached the screen. The
   icon was the same grey as the submission number under it, which is why
   it read as decoration rather than as mail.

   Scoping the rule inside the cell (0,3,0) is what makes it win, and it
   would win even if the icon moved back outside the <b>.

   THE COLOUR IS `--amber-ink`, AND THE OWNER HAS CONFIRMED IT
   (2026-08-30). The theme's colour discipline reserves red for Declined,
   green for money and Quoted, blue for selection and links - so attention
   without danger is the amber family. Raw `--amber` (#f7b623) is 1.9:1 on
   white and fails the 3:1 floor for a graphic that carries meaning, which
   this one does: it has a title and an aria-label. `--amber-ink`
   (#805c00) is 7.4:1 and is the same token the Referred badge already
   speaks in.

   THE CONFIRMATION WAS TAKEN FROM PAINTED PIXELS RATHER THAN FROM THIS
   RULE, and that matters for the next person who wants to change the
   token. `&#9993;` is a codepoint, and a host that renders it in EMOJI
   PRESENTATION paints a colour picture while ignoring `color` entirely -
   so a declaration is not evidence of what an agent sees. The glyph was
   screenshotted at 4x and sampled: ink rgb(128,92,0) on white, a solid
   two-tone envelope, at 1280, 768 and 375. At READ there is no glyph at
   all - absent, not dimmed, which is this board's vocabulary and not the
   Desk's (that one has a quiet state). The harness is
   `phase2/measure_polish4_20260830.py --board --shots`.

   `display: inline-block` is not decoration: the row's hover underlines
   the name, and an inline-block child does not take an ancestor's
   text-decoration line - so the glyph stays clean while the name
   underlines. */
.board .insured .row-mail { color: var(--amber-ink); margin-left: 7px;
  font-size: 17px; line-height: 1; display: inline-block;
  vertical-align: -1px; text-decoration: none; }
/* item 4B (2026-08-26): the unread-messages summary pill above the
   board. Since the agent inbox entry (2026-09-23) it OPENS THE INBOX
   rather than toggling the unread filter, so its pressed state retired
   with the toggle. */
.msg-summary { display: inline-flex; align-items: center; gap: 8px;
  font: inherit; font-size: var(--fs-small); font-weight: var(--fw-semibold);
  color: var(--navy); background: var(--tint-blue);
  border: 1px solid var(--blue); border-radius: var(--r-pill);
  padding: 7px 16px; cursor: pointer; margin-bottom: var(--sp-3); }
.msg-summary:hover { border-color: var(--navy); }
.refer-reasons { margin: var(--sp-3) 0 0; padding: 0; list-style: none; display: grid; gap: var(--sp-2); }
.refer-reasons li { display: flex; gap: 10px; align-items: baseline; color: var(--ink-soft); }
.refer-reasons .rule { flex: none; font-size: var(--fs-label); letter-spacing: var(--ls-label);
  font-weight: var(--fw-semibold); color: var(--amber-ink); background: var(--amber-tint);
  border-radius: var(--r-pill); padding: 3px 10px; text-transform: uppercase; }

/* THE CONTACT-CONFIRMATION CARD'S THREE FIELDS (item 6, owner walkthrough
   2026-08-30, from his screenshot) — "Does everything look correct?".

   WHAT WAS WRONG, AND IT IS A CONSEQUENCE OF WHERE THE STYLES LIVED. All
   three fields were written INLINE in the renderer, and only two of them
   shared a spelling: the name and the phone were 11.5px uppercase labels
   over 600-weight text, and the email was the same label over a
   browser-default input in a fainter box than the platform's own field
   treatment — `--border` rather than `--border-strong`, an 8px radius
   nothing else on the screen uses, and no weight or colour of its own.
   Standing beside its two siblings it read as a different species.

   SO THE THREE SHARE ONE STYLE AND THE STYLE MOVED OUT OF THE MARKUP —
   which is the only version of "make them match" that stays matched: one
   label rule, one value rule, and the email taking the value rule INSIDE
   its box.

   THE BASELINES ARE MATCHED ON PURPOSE. `align-items: flex-end` lines the
   three boxes up at the bottom, and an input with 10px of padding and a
   1px border sits its text 11px above that edge while bare text sits on
   it. The two static values take the same 11px, so the three read as one
   line rather than as two things and a control.

   IT STAYS AN INPUT (ruled): the whole point of the field is that an
   agent can add the address here without leaving the page. */
.bc-fields { display: flex; flex-wrap: wrap; gap: 14px 28px;
  align-items: flex-end; }
.bc-f-lab { display: block; font-size: var(--fs-label);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--gray); }
.bc-f-val { font-size: var(--fs-body); font-weight: var(--fw-semibold);
  color: var(--ink); padding: 11px 0; }
.bc-f-email { flex: 1; min-width: 220px; }
/* AND `font: inherit` IS NOT ENOUGH, WHICH THE BROWSER WALK CAUGHT AND
   READING DID NOT. The shorthand resets every font longhand, and
   `input.bc-f-input` (0,1,1) out-ranks `.bc-f-val` (0,1,0) - so the
   value rule's weight never reached the box and the email rendered at
   400 beside two siblings at 600. Measured on the served page:

       value 'Dana Reyes'    14px/600      value '' (the input)  14px/400

   which is the EXACT defect this item is about, still there after the
   fix that was supposed to close it. The three text properties are
   restated on the winning rule rather than left to a shorthand. */
input.bc-f-input { width: 100%; font-family: inherit;
  font-size: var(--fs-body); font-weight: var(--fw-semibold);
  color: var(--ink); padding: 10px 14px;
  background: var(--card); border: 1px solid var(--border-strong);
  border-radius: var(--r-ctl); }
input.bc-f-input:focus { outline: 3px solid var(--focus-ring);
  outline-offset: 0; border-color: var(--blue); }
/* THE MISSING-EMAIL NOTICE (item 6b). It was `--gray` at 13px — the
   quietest thing on the card, for the one fact on it that asks for
   something. The owner named the treatment: the amber "!" the forms rows
   use for "somebody is waiting on this".

   IT IS THE SAME COMPONENT, NOT A SECOND AMBER. The glyph is
   `.ap-doc-ico.is-need`, unchanged, so the two surfaces cannot drift into
   two attention colours — and a scale override lives here rather than in
   that rule, because the forms rows' 34px ring beside one line of text
   would be a badge rather than a marker.

   THE COPY STAYS IN ITS CURRENT HELPFUL REGISTER (ruled): the request can
   still go, binding will need the address, adding it now saves a step. A
   marker makes it findable; it does not make it a refusal — so the block
   takes the amber TINT and keeps the platform's reading ink rather than
   turning the sentence amber too. */
.bc-notice { display: flex; align-items: flex-start; gap: 10px;
  margin-top: var(--sp-3); padding: 10px 14px;
  font-size: var(--fs-small); line-height: var(--lh-body); color: var(--ink);
  background: var(--amber-tint); border: 1px solid var(--amber);
  border-radius: var(--r-ctl); }
/* THE DISC HAS TO OUT-RANK `.is-need`, AND THE FIRST CUT DID NOT - also
   found by the walk rather than by reading. `.bc-notice .ap-doc-ico`
   (0,2,0) ties `.ap-doc-ico.is-need` (0,2,0) and loses on order, because
   this rule sits earlier in the file, so the amber disc stayed amber on
   an amber block: measured `glyphBg rgb(253,243,216)` against a block
   background of the same value. The SIZE won (the base rule is only
   (0,1,0)), which is what made it look deliberate. Three classes state
   the intent where it can actually take effect.
   THE COLOUR STILL BELONGS TO THE SHARED RULE: this changes the disc the
   glyph sits on, not the amber it is drawn in. */
.bc-notice .ap-doc-ico { width: 22px; height: 22px; font-size: 13px; }
.bc-notice .ap-doc-ico.is-need { background: var(--card); }

/* THE FOLDED THREAD'S SUMMARY ROW (item 2, owner design 2026-08-30) —
   the one line that stands where the message block stood on the quoted
   page, so the payment plans are not pushed down by an exchange the
   agent has already had.

   TWO STATES, AND NEITHER IS COLOUR ALONE. Unread wears the amber
   attention family — the same `--amber-ink` on `--amber-tint` the board's
   mail icon and the forms rows' "somebody is waiting for this" glyph
   already speak in — and the row's own words say "unread". Read is
   quiet: the platform's neutral tint and soft ink, a row that reports a
   fact rather than asking for anything. A reader who sees no colour
   reads the same two sentences.

   IT IS A BUTTON, so the keyboard reaches it and `aria-expanded` says
   what it does, and it is full width because the thing it replaced was.
   `text-align: left` and the inherited font are there because a bare
   `<button>` is centred 13.33px system text in every engine, which is
   the one thing this row must not look like. */
.thread-fold { display: flex; align-items: center; gap: 10px; width: 100%;
  font: inherit; font-size: var(--fs-small); font-weight: var(--fw-semibold);
  text-align: left; cursor: pointer;
  color: var(--ink-soft); background: var(--neutral-tint);
  border: 1px solid var(--border); border-radius: var(--r-card);
  padding: 12px 16px; }
.thread-fold:hover { border-color: var(--border-strong); }
.thread-fold:focus-visible { outline: 3px solid var(--focus-ring);
  outline-offset: 0; }
.thread-fold-ico { font-size: 17px; line-height: 1; flex: none; }
.thread-fold-txt { flex: 1 1 auto; min-width: 0; }
.thread-fold-act { flex: none; color: var(--blue); text-decoration: underline;
  text-underline-offset: 3px; }
.thread-fold.is-unread { color: var(--amber-ink); background: var(--amber-tint);
  border-color: var(--amber-ink); }
/* the body opens directly under the row rather than replacing it, so the
   agent can fold it away again without hunting for a second control */
#thread-body > .card { margin-top: var(--sp-3); }

/* correspondence thread (Pending Info loop, spec §5) — UW requests lean
   left in tint-blue, the agent's replies right in neutral, so direction
   reads without color-as-verdict. Reuses existing semantic tokens. */
.corr-thread { display: grid; gap: var(--sp-3); margin-top: var(--sp-4); }
.corr-row { max-width: 84%; display: grid; gap: 4px;
  border-radius: var(--r-card); padding: 10px 14px; }
.corr-uw { justify-self: start; background: var(--tint-blue); }
.corr-agent { justify-self: end; background: var(--neutral-tint); }
.corr-meta { font-size: var(--fs-label); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--gray); display: flex; gap: 8px; align-items: baseline; }
.corr-meta b { color: var(--ink); font-weight: var(--fw-semibold);
  text-transform: none; letter-spacing: 0; }
.corr-msg { color: var(--ink); font-size: var(--fs-small); white-space: pre-wrap; }
/* the documents an information request NAMED (owner ruling, 2026-08-18):
   a checklist the agent can work down, not a sentence to re-read */
.corr-forms { margin: 8px 0 0; padding-left: 20px; color: var(--ink);
  font-size: var(--fs-small); }
.corr-forms li { margin: 3px 0; font-weight: var(--fw-semibold); }
.corr-reply { margin-top: var(--sp-4); padding-top: var(--sp-4);
  border-top: 1px solid var(--border); }
.corr-reply textarea { width: 100%; font: inherit; color: var(--ink);
  background: var(--card); border: 1px solid var(--border-strong);
  border-radius: var(--r-ctl); padding: 10px 12px; }
.corr-err { color: var(--amber-ink); font-size: var(--fs-small); margin-top: 8px; }
/* the target premium relocated into the thread reply (referred reply
   path, 2026-08-26) - same flex-to-grid collapse the rn-actions row it
   came from uses, so both write doors keep one mobile behavior */
.corr-target-row { display: flex; align-items: flex-end; gap: var(--sp-4);
  flex-wrap: wrap; margin-top: var(--sp-4); padding-top: var(--sp-4);
  border-top: 1px solid var(--border); }
@media (max-width: 640px) {
  .corr-target-row { display: grid; }
  .corr-target-row .btn { width: 100%; }
}
/* inline field-level advisory (amber = attention, never a block) — e.g. the
   cross-agency FEIN clearance warning (owner item 10, 2026-07-14) */
.field-msg { display: block; margin-top: 6px; padding: 8px 12px;
  font-size: var(--fs-small); font-weight: var(--fw-semibold);
  color: var(--amber-ink); background: var(--amber-tint);
  border-radius: var(--r-ctl); }
/* display:block above would defeat the `hidden` attribute — without this
   the empty amber pill always rendered under the FEIN field, and (because
   .field is a grid) the extra row re-spaced the whole row's cells */
.field-msg[hidden] { display: none; }

/* decline panel — same geometry as refer-panel, red edge (reuses existing
   semantic red tokens; not a new color) */
.decline-panel {
  background: var(--card); border: 1px solid var(--border);
  border-left: 4px solid var(--red);
  border-radius: var(--r-card); box-shadow: var(--shadow-card);
  padding: var(--sp-5) var(--sp-6);
}
.decline-panel h2 { font-size: var(--fs-h2); }
/* the underwriter's decline message under the apology line (batch E item
   4c, 2026-08-22): the note the decline door requires, in the
   underwriter's own words. Token-only. */
.decline-uw-note { margin-top: var(--sp-3); padding: var(--sp-3) var(--sp-4);
  background: var(--page); border: 1px solid var(--border);
  border-radius: var(--r-ctl); }
.decline-uw-note p { margin: 4px 0 0; color: var(--ink); }

/* RULING 8 (owner, 2026-08-06): a rejected bind request reads plainly on
   the agent's quote — the underwriter's REQUIRED reason in their own
   words, and the state stated outright as no longer pending (a bind
   request is the one state where the agent is waiting on someone else,
   so "the wait is over" is said, not implied). Red-tint field in the
   declined family, the reason set off in a white inset so it reads as a
   quotation rather than as our summary of it. Token-only. */
.bind-declined { background: var(--red-tint); border-radius: var(--r-card);
  padding: var(--sp-5) var(--sp-6); }
.bind-declined-head { display: flex; gap: 14px; align-items: flex-start; }
.bind-declined-mark { flex: none; width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--red); color: #fff; font-weight: 700; }
.bind-declined h2 { font-size: var(--fs-h2); font-weight: var(--fw-semibold);
  color: var(--red-ink); }
.bind-declined-state { color: var(--ink); margin-top: 4px;
  font-weight: var(--fw-semibold); }
.bind-declined-reason { margin-top: var(--sp-4); background: var(--card);
  border-radius: var(--r-ctl); padding: 13px 16px; }
.bind-declined-reason .label { color: var(--gray); }
.bind-declined-reason p { color: var(--ink); margin-top: 5px;
  line-height: var(--lh-body); white-space: pre-wrap; max-width: 72ch; }
.bind-declined-meta { margin-top: 10px; font-size: var(--fs-small);
  color: var(--ink-soft); }

/* =========================================================================
   Cards & sections
   ========================================================================= */
.section { margin-top: var(--sp-7); }
.section-head { display: flex; align-items: baseline; gap: var(--sp-3); margin-bottom: var(--sp-4); }
.section-head h2 { font-size: var(--fs-h2); font-weight: var(--fw-semibold); }
.section-head .sub { color: var(--gray); font-size: var(--fs-small); }
/* ruling 15a (2026-08-05): section heads carry the navy accent bar — the
   quote page's sections read as one premium family with the hero/cards */
.section-head h2 { display: flex; align-items: center; gap: 10px; }
.section-head h2::before { content: ""; width: 4px; height: 1.05em;
  border-radius: 2px; background: var(--navy); }

.card {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--r-card); box-shadow: var(--shadow-card);
}

/* ---------- payment plan cards ---------- */
.plans { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: var(--sp-4); }
.plan {
  position: relative;
  background: var(--card); border: 1.5px solid var(--border);
  border-radius: var(--r-card); box-shadow: var(--shadow-card);
  padding: var(--sp-4) var(--sp-4) var(--sp-4);
  display: flex; flex-direction: column; gap: var(--sp-3);
  cursor: pointer;
  transition: border-color .12s ease, box-shadow .12s ease, transform .12s ease;
}
.plan:hover { border-color: var(--blue); box-shadow: var(--shadow-pop); transform: translateY(-1px); }
.plan.is-selected { border-color: var(--blue); box-shadow: 0 0 0 3px var(--focus-ring), var(--shadow-card); }
.plan-selected-badge {
  position: absolute; top: -10px; right: 14px;
  background: var(--blue); color: #fff;
  border-radius: var(--r-pill); padding: 3px 12px;
  font-size: var(--fs-label); font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-label); text-transform: uppercase;
}
.plan-name { font-weight: var(--fw-semibold); font-size: 15px; padding-right: 60px; }
.plan-due { margin-top: auto; }
.plan-due .amt { font-size: 26px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.plan-rows { display: grid; gap: 6px; font-size: var(--fs-small); color: var(--ink-soft); }
.plan-rows .r { display: flex; justify-content: space-between; gap: var(--sp-3); }
.plan-rows .r b { color: var(--ink); font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; }
.plan-note { font-size: var(--fs-small); color: var(--gray); }

/* ---------- payment plan CARDS (lineup ruling 4, 2026-08-05; mockup
   docs/design/plancards_mockup_FINAL.html, owner-approved v4) ----------
   Four vertical cards inline: navy header (white name, light-blue
   tagline), ONE hero figure (initial payment / deposit) large in navy,
   every other body line soft grey regular weight, description from
   bill_plans data. Two actions: "Select for binding" (single-select
   radio semantics, persisted+audited) and "On proposal" (the standing
   multi-select). Cards stack at narrow widths. */
.pcards { display: flex; gap: var(--sp-3); align-items: stretch; flex-wrap: wrap; }
.pcard { flex: 1 1 220px; min-width: 220px; background: var(--card);
  border: 1.5px solid var(--border); border-radius: var(--r-card);
  box-shadow: var(--shadow-card); display: flex; flex-direction: column;
  overflow: hidden; position: relative; }
.pcard.for-bind { border: 2px solid var(--navy);
  box-shadow: 0 0 0 3px var(--focus-ring), var(--shadow-card); }
.pcard .bindstrip { background: var(--amber); color: var(--amber-ink);
  font-size: 9px; font-weight: var(--fw-bold, 700); letter-spacing: .12em;
  text-transform: uppercase; text-align: center; padding: 3px 0; }
.pcard .phead { padding: 12px 16px 10px; background: var(--navy); color: var(--on-navy, #fff); }
.pcard .phead .nm { font-size: 14px; font-weight: var(--fw-semibold); line-height: 1.25; }
.pcard .phead .ptag { font-size: 10px; color: var(--sky-onnavy); margin-top: 3px; }
.pcard .pfacts { padding: 10px 16px 4px; flex: 1; }
.pcard .pfact { padding: 8px 0 6px; border-bottom: 1px solid var(--border); }
.pcard .pfact:last-child { border-bottom: none; }
.pcard .pfact .k { font-size: 9px; color: var(--gray); text-transform: uppercase; letter-spacing: .14em; }
.pcard .pfact .v { font-size: 20px; font-weight: var(--fw-semibold); color: var(--navy);
  font-variant-numeric: tabular-nums; margin-top: 2px; }
.pcard .pfact.mini .v { font-size: 12px; color: var(--ink-soft); font-weight: var(--fw-regular, 400); }
.pcard .pnote { font-size: 10px; background: var(--tint-green); color: var(--green-ink);
  margin: 0 16px 8px; padding: 4px 8px; border-radius: 3px; }
.pcard .pdesc { font-size: 11px; color: var(--ink-soft); padding: 0 16px 10px; line-height: 1.5; }
.pcard .pbtns { padding: 0 14px 14px; display: flex; flex-direction: column; gap: 8px; }
.pbtn { font: inherit; font-size: var(--fs-label); font-weight: var(--fw-semibold);
  display: flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 10px; min-height: 40px; border-radius: var(--r-ctl);
  cursor: pointer; border: 1.5px solid; background: var(--card); }
.pbtn .ring { width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid currentColor; flex: none; }
.pbtn .sq { width: 12px; height: 12px; border-radius: 3px;
  border: 2px solid currentColor; flex: none; display: grid; place-items: center;
  font-size: 9px; line-height: 1; }
.pbtn-bind { border-color: var(--navy); color: var(--navy); }
.pbtn-bind:hover { background: var(--tint-blue); }
.pcard.for-bind .pbtn-bind { background: var(--navy); color: var(--on-navy, #fff); }
.pcard.for-bind .pbtn-bind .ring { border-color: currentColor;
  background: radial-gradient(circle at center, currentColor 40%, transparent 45%); }
.pbtn-prop { border-color: var(--border-strong); color: var(--ink-soft); }
.pbtn-prop:hover { background: var(--neutral-tint); }
.pbtn-prop.on { background: var(--green); border-color: var(--green); color: #fff; }
.pbtn-prop.on .sq::before { content: "\2713"; }
/* the proposal download-gate mark (rulings 2 + 11, 2026-08-03) re-anchored
   to the card buttons */
.pcards.is-missing .pbtn-prop { border-color: var(--amber); }

/* THE BETTER-QUOTE STRIP (owner ruling 8, 2026-08-20). One short line
   directly above the pay plans, where a card with two open inputs used to
   sit below them. It is a LINE, not a panel: no card background, no border,
   no shadow — the visual weight belongs to the plan cards underneath it,
   which is the whole point of the move. The disclosed form is the retired
   card's own markup, so it inherits .field-row/.field styling unchanged. */
.bq-strip { margin-bottom: var(--sp-2); font-size: var(--fs-body);
  color: var(--ink-soft); }
.bq-strip .bq-lede { font-weight: var(--fw-semibold); color: var(--navy); }
.bq-strip a { color: var(--blue); text-decoration: underline; }
.bq-strip a:hover { color: var(--blue-hover); }
.bq-form { margin-top: var(--sp-2); }

/* the bind bar (lineup ruling 6 — mockup states A/B/C) */
.bindbar { margin-top: var(--sp-3); background: var(--card);
  border: 1.5px solid var(--border); border-radius: var(--r-card);
  padding: 14px 18px; display: flex; justify-content: space-between;
  align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.bindbar .msg { font-size: var(--fs-small); color: var(--ink-soft); }
/* THE BAR'S TWO ACTIONS, GROUPED (bind-clarity item 5, 2026-08-28). The
   bar is `space-between` over two children - the message and the action.
   A second button added as a third child would have spread all three
   across the bar and put "Download quote" in the middle of the sentence
   it follows. Wrapping the pair keeps the bar at two children, so the
   message stays left and both buttons stay right, and it wraps as a unit
   at narrow widths instead of the two splitting across lines. */
.bindbar-acts { display: flex; align-items: center; gap: var(--sp-2);
  flex-wrap: wrap; }
.bindbar .msg b { color: var(--navy); }
/* THE READY STATE (owner ruling 1, 2026-08-20): once a binding plan is
   chosen the bar reads back the choice in one green line. Tokens only -
   the same success green the Quoted badge and the on-quote toggle already
   wear, so "green means this is settled" keeps meaning one thing. It is
   never set while a plan is unchosen, so it cannot collide with the amber
   attempt state below. */
.bindbar.is-ready { background: var(--tint-green);
  border-color: var(--green); }
.bindbar.is-ready .msg { color: var(--green-ink);
  font-size: var(--fs-body); font-weight: var(--fw-semibold); }
.bindbar.err { border: 2px solid var(--amber); }
/* [retired 2026-08-06, amendment A1] .errline + its "!" icon — the gate
   guidance is the full-width banner below; the bindbar keeps its amber
   err border as the second (non-color-alone) attempt cue */
/* Amendment A1 (2026-08-06): the bind-gate guidance is a full-width
   amber BANNER above the plan cards — larger text, no icon prefix,
   unmissable at a glance; still attempt-only (the [hidden] toggle is
   the unchanged applyBindGate mechanic) */
.bind-gate-banner { display: block; background: var(--amber-tint);
  color: var(--amber-ink); border: 1.5px solid var(--amber);
  border-left-width: 5px; border-radius: var(--r-card);
  padding: 14px 20px; margin-bottom: var(--sp-3);
  font-size: 16px; font-weight: var(--fw-semibold); }
.bind-gate-banner[hidden] { display: none; }

/* ---------- payment plan ROWS — RETIRED 2026-08-05 (lineup ruling 4:
   the card UI above replaces the 2026-08-03 collapsed rows; regenerated
   mocks carry cards; tombstone kept per the .seg precedent) ---------- */
.plan-list { display: grid; gap: var(--sp-2); }
.plan-row { background: var(--card); border: 1.5px solid var(--border);
  border-radius: var(--r-card); box-shadow: var(--shadow-card); }
.plan-row.is-selected { border-color: var(--blue);
  box-shadow: 0 0 0 3px var(--focus-ring), var(--shadow-card); }
.plan-row-head { display: flex; align-items: center; gap: var(--sp-4);
  padding: 12px 16px; cursor: pointer; flex-wrap: wrap; }
.plan-row-name { font-weight: var(--fw-semibold); font-size: 15px; flex: 1 1 170px; }
.plan-row-fact { flex: 0 1 auto; min-width: 130px; }
.plan-row-fact .label { display: block; }
.plan-row-fact b { font-variant-numeric: tabular-nums; font-size: 15px; }
.plan-row-caret { flex: none; color: var(--gray); transition: transform .12s ease;
  font-size: 12px; }
.plan-row.is-open .plan-row-caret { transform: rotate(90deg); }
.plan-row-detail { display: none; padding: 12px 16px 14px;
  border-top: 1px solid var(--border); font-size: var(--fs-small);
  color: var(--ink-soft); }
.plan-row.is-open .plan-row-detail { display: grid; gap: 8px; }
.plan-row-detail .why { margin: 0; }

/* ---------- proposal plan multi-select (owner rulings 1-4, 2026-08-03 —
   multi-plan proposal selection) ----------
   A MULTI-select, deliberately distinct from the single-select .choice
   pattern (round radio ring, navy fill = the ONE bind plan): SQUARE
   checkbox shape, tint fill when on, label "On proposal" — shape and
   wording carry the difference so the two picks are never mistaken for
   each other, while the tokens keep it in the same design system. State
   rides the check SHAPE, never colour alone (the ruling-1 principle).
   Inclusion reads at a glance on the collapsed row without expanding. */
.pick {
  font: inherit; font-size: var(--fs-label); font-weight: var(--fw-semibold);
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--ink-soft); background: var(--card);
  border: 1.5px solid var(--border-strong); border-radius: var(--r-ctl);
  padding: 6px 12px 6px 9px; min-height: 40px; cursor: pointer;
  transition: border-color .12s ease, box-shadow .12s ease;
}
.pick::before {
  content: ""; box-sizing: border-box; flex: none;
  width: 16px; height: 16px; border-radius: 4px;
  border: 2px solid var(--gray-mid); background: var(--card);
  display: grid; place-items: center;
  font-size: 11px; font-weight: 700; line-height: 1;
}
.pick:hover { border-color: var(--blue); box-shadow: var(--shadow-card); }
.pick[aria-pressed="true"] {
  background: var(--tint-blue); border-color: var(--navy); color: var(--navy);
}
.pick[aria-pressed="true"]::before {
  content: "\2713"; border-color: var(--navy); background: var(--navy);
  color: var(--on-navy);
}
/* the download-gate guidance mark (rulings 2 + 11): the ruling-11 amber
   outline applied to the pick controls when a download was attempted with
   nothing selected — cleared the moment a plan is added */
.plan-list.is-missing .pick { border-color: var(--amber); }

/* ---------- waterfall / premium detail ---------- */
.switcher { display: inline-flex; background: var(--neutral-tint); border-radius: var(--r-pill); padding: 3px; gap: 2px; }
.switcher button {
  font: inherit; font-size: var(--fs-small); font-weight: var(--fw-semibold);
  color: var(--ink-soft); background: transparent; border: 0;
  border-radius: var(--r-pill); padding: 6px 16px; cursor: pointer;
}
.switcher button:hover { color: var(--ink); }
.switcher button[aria-selected="true"] { background: var(--navy); color: var(--on-navy); }

.wf { width: 100%; border-collapse: collapse; font-size: var(--fs-body); }
.wf th {
  text-align: left; font-size: var(--fs-label); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--gray); font-weight: var(--fw-semibold);
  padding: 12px 20px 10px; border-bottom: 1px solid var(--border);
}
.wf th.amt, .wf td.amt { text-align: right; font-variant-numeric: tabular-nums; }
.wf td { padding: 9px 20px; border-bottom: 1px solid var(--border); color: var(--ink-soft); }
.wf tr:last-child td { border-bottom: 0; }
.wf .indent td:first-child { padding-left: 36px; }
.wf .subtotal td { color: var(--ink); font-weight: var(--fw-semibold); background: var(--page); }
/* ruling 15a (2026-08-05): the total line lands with the hero's weight —
   navy tint band instead of a bare rule */
.wf .total td { color: var(--navy); font-weight: 700; font-size: 15px;
  border-top: 2px solid var(--navy); background: var(--tint-blue); }
.wf tbody tr:hover td { background: var(--page); }
.wf tbody tr.total:hover td { background: var(--tint-blue); }
.wf td.credit { color: var(--green); font-weight: var(--fw-semibold); }  /* money saved = green */
.wf .factor { color: var(--gray); font-size: var(--fs-small); }
/* The factor a line PRINTS, beside its label - the experience mod
   today (2026-09-01). Subdued and tabular so the column of labels
   still reads as a column, and inside the label cell so the four-
   column geometry does not move at any width. */
.wf .wf-factor { color: var(--gray); font-size: var(--fs-small);
  font-variant-numeric: tabular-nums; margin-left: 8px; }
/* A step of the filed order that did nothing (workbench walkthrough item
   1, 2026-10-03): listed with its reason and quiet, so the lines that
   moved the premium stand out. */
.wf tr.wf-idle td { color: var(--gray); font-size: var(--fs-small); }
.wf .wf-reason { margin-left: 8px; font-style: italic; }

/* ---------- cross-sell strip ---------- */
/* THE `.cross-sell` FAMILY IS RETIRED WITH ITS ONLY USER (owner
   walkthrough item 7, 2026-08-27). The blue strip with a pill on its
   right was the platform's THIRD cross-sell look; `crossSellStrip` now
   renders the ruled component - the same `apWhileYouWait` shell and
   `apTwoDoors` row every other surface uses - so nothing draws these
   three rules any more. SWEPT BEFORE DELETING: the only other
   `.cross-sell` in the repo is inside
   `docs/design/policy_forms_exemplar_20260809.html`, a committed design
   reference carrying its own stylesheet, which does not link this file.
   A CSS family whose only user is gone is dead weight the next editor
   reads as live - the same reasoning that retired `.ap-wait-acord`
   further down this section. */

/* payroll-company question styles REMOVED (owner ruling 5, 2026-08-03):
   the question is retired — paygo plans list on the same terms as any other
   plan of their kind; the payroll-reporting requirement reads as a callout
   in the Pay-as-you-go row's expanded detail (ruling 4). Historical answers
   stay on their snapshots (UW workspace still shows them). */

/* =========================================================================
   Status board — no hero; a fast scannable list
   ========================================================================= */

/* ---------- metrics summary (board only) — clickable filter tiles ---------- */
.metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--sp-3); margin-bottom: var(--sp-5); }
.metric {
  font: inherit; text-align: left; cursor: pointer;
  background: var(--card); border: 1.5px solid var(--border);
  border-radius: var(--r-card); box-shadow: var(--shadow-card);
  padding: var(--sp-4);
  display: grid; gap: 4px;
  transition: border-color .12s ease, box-shadow .12s ease, transform .12s ease;
}
.metric:hover { border-color: var(--blue); box-shadow: var(--shadow-pop); transform: translateY(-1px); }
.metric[aria-pressed="true"] { border-color: var(--blue); box-shadow: 0 0 0 3px var(--focus-ring), var(--shadow-card); }
.metric .m-count { font-size: 28px; font-weight: 700; line-height: 1;
  font-variant-numeric: tabular-nums; color: var(--ink); }
.metric .m-sub { font-size: var(--fs-small); color: var(--gray); font-variant-numeric: tabular-nums; }
.metric .m-sub b { font-weight: var(--fw-semibold); }
/* status-colored count accents — legitimate: these ARE statuses */
.metric-quoted .m-count { color: var(--green-ink); }
.metric-bound .m-count { color: var(--green-ink); }
.metric-pending .m-count { color: var(--amber-ink); }
.metric-declined .m-count { color: var(--red-ink); }
/* the Messages box (agent-side polish item 8, ruling 141): the unread ink */
.metric-messages .m-count { color: var(--blue); }
.metric .m-sub .up { color: var(--green-ink); }
.board-head { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-4); flex-wrap: wrap; }
.board-head h1 { font-size: var(--fs-h1); font-weight: var(--fw-semibold); }
.board-head .count { color: var(--gray); font-size: var(--fs-small); }
.board-tools { margin-left: auto; display: flex; gap: var(--sp-3); align-items: center; flex-wrap: wrap; }
.search {
  display: flex; align-items: center; gap: 8px;
  background: var(--card); border: 1px solid var(--border-strong);
  border-radius: var(--r-ctl); padding: 8px 14px; min-width: 240px;
  color: var(--gray); font-size: var(--fs-small);
}

.board { overflow-x: auto; }
.board table { width: 100%; border-collapse: collapse; font-size: var(--fs-body); min-width: 860px; }
.board th {
  text-align: left; font-size: var(--fs-label); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--gray); font-weight: var(--fw-semibold);
  padding: 12px 16px 10px; border-bottom: 1px solid var(--border);
  position: sticky; top: 0; background: var(--card);
}
.board td { padding: 13px 16px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.board td.date, .board th.date { white-space: nowrap; }

/* sortable date columns (Effective, Quote Expires) */
.board th.sortable button {
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
  background: none; border: 0; padding: 0; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
}
.board th.sortable button:hover { color: var(--ink); }
.sort-arrow { font-size: 9px; line-height: 1; color: var(--gray-mid); }
.board th[aria-sort="ascending"] .sort-arrow::after  { content: "\25B2"; color: var(--blue); }
.board th[aria-sort="descending"] .sort-arrow::after { content: "\25BC"; color: var(--blue); }
.board th[aria-sort="none"] .sort-arrow::after       { content: "\2195"; }
.board tr:last-child td { border-bottom: 0; }
.board tbody tr { cursor: pointer; }
.board tbody tr:hover td { background: var(--page); }
/* THE INSURED HEADER (follow-ups entry, item 2, ruling 148, 2026-09-23): a
   grouping device only - the insured's name and its line pills on a quiet
   band, no status, no link, no hover, no pointer - and the rows under it
   carry a navy rule at their left edge so the group reads as one block. On a
   phone the board scrolls sideways (its standing shape); the header's
   content is sticky at the left so the name stays in view while it does. */
.board tbody tr.acct-group-head { cursor: default; }
.board tbody tr.acct-group-head td,
.board tbody tr.acct-group-head:hover td { background: var(--page); padding: 10px 16px 8px; }
.acct-group-inner { position: sticky; left: 16px; display: inline-flex; align-items: center;
  flex-wrap: wrap; gap: 6px 12px; }
.acct-group-name { font-weight: var(--fw-semibold); color: var(--ink); }
.board tbody tr.acct-group-member td:first-child { box-shadow: inset 3px 0 0 var(--navy);
  padding-left: 24px; }
/* Account names read as links (owner ruling 6, 2026-08-06): the whole row
   already navigates to the submission, so the name takes the platform's
   standard link treatment — brand blue, underline on hover — exactly as
   `a` does (theme.css:113). Scoped to the name; the rest of the dashboard
   is deliberately untouched by this ruling. */
.board .insured b { display: block; color: var(--blue); font-weight: var(--fw-semibold); }
.board tbody tr:hover .insured b { color: var(--blue-hover); text-decoration: underline; }
.board .insured > span { color: var(--gray); font-size: var(--fs-small); display: inline-flex;
  align-items: baseline; gap: 6px; flex-wrap: wrap; }
/* states folded under the name — subtle, muted, not the filled chips */
.board .insured .st { font-size: var(--fs-label); font-weight: var(--fw-semibold);
  letter-spacing: .05em; color: var(--gray-mid); }
.board .insured .st-sep { color: var(--gray-mid); }
.board tbody tr:hover .insured .st { color: var(--gray); }
.board td.amt { text-align: right; font-variant-numeric: tabular-nums; font-weight: var(--fw-semibold); color: var(--ink); }
.board th.amt { text-align: right; }
.board .muted { color: var(--gray); }
.board .statechips { display: flex; gap: 4px; flex-wrap: wrap; }
.statechip {
  background: var(--neutral-tint); color: var(--neutral-ink);
  border-radius: var(--r-pill); padding: 2px 9px;
  font-size: var(--fs-label); font-weight: var(--fw-semibold); letter-spacing: .04em;
}
.continue-link { font-size: var(--fs-small); font-weight: var(--fw-semibold); margin-left: 8px; white-space: nowrap; }

.empty {
  text-align: center; padding: var(--sp-8) var(--sp-5); color: var(--gray);
}
.empty b { display: block; color: var(--ink); font-size: var(--fs-h2); font-weight: var(--fw-semibold); margin-bottom: var(--sp-2); }

/* =========================================================================
   Quote flow — guided journey (stepper, forms, review)
   ========================================================================= */
.flow { display: grid; grid-template-columns: 240px 1fr; gap: var(--sp-6); align-items: start; }

/* ---------- progress rail ---------- */
.rail { position: sticky; top: var(--sp-5); display: grid; gap: 2px; }
.rail-progress { margin-bottom: var(--sp-3); }
.rail-progress .bar { height: 6px; background: var(--neutral-tint); border-radius: var(--r-pill); overflow: hidden; }
.rail-progress .fill { height: 100%; background: var(--green); border-radius: var(--r-pill);
  transition: width .3s ease; }
.rail-progress .pct { font-size: var(--fs-small); color: var(--gray); margin-top: 6px;
  font-variant-numeric: tabular-nums; }
.rail-step {
  font: inherit; text-align: left; cursor: pointer;
  display: flex; align-items: center; gap: 10px;
  background: none; border: 0; border-radius: var(--r-ctl);
  padding: 10px 12px; color: var(--ink-soft); font-size: var(--fs-body);
}
.rail-step:hover { background: var(--neutral-tint); }
.rail-step[aria-current="step"] { background: var(--navy); color: var(--on-navy); font-weight: var(--fw-semibold); }
.rail-step .n {
  flex: none; width: 22px; height: 22px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--fs-label); font-weight: var(--fw-semibold);
  background: var(--neutral-tint); color: var(--ink-soft);
}
.rail-step[aria-current="step"] .n { background: var(--on-navy-pill); color: var(--on-navy); }
.rail-step.is-done .n { background: var(--tint-green); color: var(--green-ink); }
.rail-step.is-partial .n { background: var(--amber-tint); color: var(--amber-ink); }

/* ---------- step panel ---------- */
.step-panel { min-width: 0; }
.step-card { background: var(--card); border: 1px solid var(--border);
  border-radius: var(--r-card); box-shadow: var(--shadow-card); padding: var(--sp-6); }
.step-eyebrow { margin-bottom: 4px; }
.step-card h1 { font-size: var(--fs-h1); font-weight: var(--fw-semibold); }
.step-help { color: var(--gray); font-size: var(--fs-small); margin: 6px 0 0; }
.step-body { margin-top: var(--sp-5); display: grid; gap: var(--sp-4); }
/* SPECIES D's SECOND INSTANCE, AND THE SAME ONE-WORD MECHANISM (owner
   mobile walkthrough 2026-08-31). A grid item's default `min-width:
   auto` refuses to shrink below its own min-content, and a grid TRACK
   sized `1fr` or `minmax(180px, 1fr)` is then forced WIDER THAN ITS
   OWN CONTAINER to hold it.

   MEASURED at 320 on the coverage-history step: `#step-body` is 222px
   wide and its single column computed to 289.297px, because a number
   input three levels down would not go below its intrinsic width. The
   289 propagated up every grid in the chain - the row, the `.rep`
   group, the step body - and 18px of it left the viewport.

   THE 180px FLOOR IS NOT WEAKENED BY THIS. The track keeps its
   `minmax(180px, 1fr)` minimum; what changes is only that an ITEM can
   no longer inflate the track past the container. */
.step-body > *, .rep > *, .rep-row > *, .field > * { min-width: 0; }
.step-footer { display: flex; align-items: center; gap: var(--sp-3);
  margin-top: var(--sp-6); padding-top: var(--sp-5); border-top: 1px solid var(--border); }
.step-footer .spacer { flex: 1; }
/* Back and Continue side by side on the narrowest phone (standing rule 366,
   measured 2026-10-03): with every letter 3px wider the pair came to 21px
   past a 320 screen; 14px sides instead of 22 keeps both on one line and
   every tap height as it was */
@media (max-width: 400px) {
  .step-footer .btn { padding-left: 14px; padding-right: 14px; }
  /* and on the cloud's wider fonts (gate 37136165972) the pair may take
     two lines - Continue keeps the right edge */
  .step-footer { flex-wrap: wrap; }
  .step-footer #nav-next, .step-footer #get-quote { margin-left: auto; }
}
@keyframes step-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.step-card.entering { animation: step-in .18s ease; }

/* ---------- form controls ---------- */
.field { display: grid; gap: 6px; align-content: start; }
/* ---- address autocomplete (item 6, owner design 2026-08-27) -------------
   THE PANEL OVERLAYS, IT DOES NOT PUSH. A list that took layout space
   would shove the city/state/ZIP row down on every keystroke and back up
   on every pause, which is the jumpiest thing a form can do while
   somebody is typing - so the field it sits in is the positioning
   context and the panel is absolute inside it.

   `z-index` above the row and nothing else: this panel only ever has to
   win against the fields beside it, never against the chrome. Its
   max-height is eight rows' worth, and it scrolls rather than growing
   past the fold on a phone. The rows wear the same tint the board's
   selected state does, so "this one is highlighted" reads the same way
   here as everywhere else on the platform. */
.addr-field { position: relative; }
.addr-ac { position: absolute; z-index: 20; top: 100%; left: 0; right: 0;
  margin-top: 4px; background: var(--card);
  border: 1px solid var(--border-strong); border-radius: var(--r-ctl);
  box-shadow: var(--shadow-card); max-height: 232px; overflow-y: auto; }
.addr-ac[hidden] { display: none; }
.addr-opt { padding: 9px 12px; font-size: var(--fs-small); color: var(--ink);
  cursor: pointer; }
.addr-opt + .addr-opt { border-top: 1px solid var(--border); }
.addr-opt:hover, .addr-opt[aria-selected="true"] { background: var(--tint-blue); }
/* the pause line (owner ruling R3, 2026-10-18): plain words, never a pick */
.addr-note { padding: 9px 12px; font-size: var(--fs-small); color: var(--gray); }
/* align-content: start — a cell with an extra element (warning, hint) must
   never redistribute its height into siblings' label rows; controls in one
   field-row stay level regardless of what any one cell carries */
.field label { font-size: var(--fs-small); font-weight: var(--fw-semibold); color: var(--ink); }
.field .hint { font-size: var(--fs-small); color: var(--gray); font-weight: 400; }
/* `password` and `email` added 2026-08-14 with the sign-in surface: the
   selector list was written before any screen had a credential field, so a
   password input rendered as an unstyled browser default beside styled
   siblings. Found by measuring the real page at 375px, not by reading. */
.field input[type="text"], .field input[type="date"], .field input[type="number"],
.field input[type="password"], .field input[type="email"],
.field select, .field textarea {
  font: inherit; color: var(--ink); background: var(--card);
  border: 1px solid var(--border-strong); border-radius: var(--r-ctl);
  padding: 10px 14px; width: 100%;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: 3px solid var(--focus-ring); outline-offset: 0; border-color: var(--blue);
}
.field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--sp-4); }
/* THREE ACROSS AT A TABLET WIDTH IS TOO NARROW FOR A REAL VALUE (UW workbench
   batch 3, cloud rider, 2026-09-11). `minmax(180px, 1fr)` lays three fields
   across at 768, each box about 205px, and on the cloud's Linux fonts the
   flow's policyholder email ('dana@walkthrough.example') needed 229px - a
   VALUE finding this desk's narrower fonts never showed, found the first
   time 768 was a pinned width. Below 900 the row's track starts at 240px,
   so 768 lays a three-field row out two across and every field in it gains
   the width, not one field. `min(240px, 100%)` keeps a container narrower
   than the track from overflowing; 320 and 375 were one across already. */
@media (max-width: 900px) {
  .field-row { grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
}
.field .error { color: var(--red-ink); font-size: var(--fs-small); }
/* item 6c (2026-08-26): the second-look row - the input takes the width
   the button gives up, and stretch makes the two EQUAL IN HEIGHT (the
   button used to stand taller than the box beside it). Wraps at narrow
   widths with the button full-width, per the mobile mandate. */
.sl-row { display: flex; align-items: stretch; gap: var(--sp-3); flex-wrap: wrap; }
.sl-row input[type="text"] { flex: 1 1 240px; width: auto; }
.sl-row .btn { flex: 0 0 auto; }
@media (max-width: 560px) {
  .sl-row .btn { flex: 1 1 100%; }
}

/* [removed 2026-08-03, owner ruling 6] .seg — the grey segmented control is
   fully superseded by .choice below (rollout across the flow-map §1f list:
   questions yes/no, officer coverage, dashboard scope; prior coverage was
   the exemplar; the payroll-company seg was retired by ruling 5). No screen
   renders class="seg" anymore. */

/* ---------- choice buttons (the shared selection control) ----------
   Owner ruling 1 (2026-08-03, batch-two round 2): unselected options must
   read as CHOOSABLE — never as disabled grey (the .seg defect: transparent
   grey text on a grey bar). ONE pattern for every mutually-exclusive pick,
   two-option (yes/no) or multi-option (prior coverage):
   - unselected = white bordered button with an empty radio ring — obviously
     clickable, obviously not yet picked;
   - selected  = navy fill, and the ring becomes a checked dot — the check
     SHAPE carries the state, never colour alone;
   - :disabled = the platform disabled tokens, visually distinct from
     merely-unselected (some officer elections are genuinely locked).
   The "Choose one to continue" text cue is REMOVED platform-wide (owner
   ruling 10, 2026-08-03) — the button styling alone carries the
   affordance; a required-but-unmade pick surfaces via the advance-attempt
   missing-item guidance (ruling 11), not a standing line. Rolled out
   across the flow-map §1f target list (ruling 6, 2026-08-03). */
.choice { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.choice button {
  font: inherit; font-size: var(--fs-small); font-weight: var(--fw-semibold);
  display: inline-flex; align-items: center; gap: 9px;
  color: var(--ink); background: var(--card);
  border: 1.5px solid var(--border-strong); border-radius: var(--r-pill);
  padding: 8px 18px 8px 12px; min-height: 40px; cursor: pointer;
  transition: border-color .12s ease, box-shadow .12s ease;
}
.choice button::before {
  content: ""; box-sizing: border-box; flex: none;
  width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--gray-mid); background: var(--card);
  display: grid; place-items: center;
  font-size: 11px; font-weight: 700; line-height: 1;
}
.choice button:hover { border-color: var(--blue); box-shadow: var(--shadow-card); }
.choice button[aria-checked="true"] {
  background: var(--navy); border-color: var(--navy); color: var(--on-navy);
}
.choice button[aria-checked="true"]::before {
  content: "\2713"; border-color: var(--on-navy); background: var(--on-navy);
  color: var(--navy);
}
.choice button:disabled { background: var(--disabled-bg); border-color: var(--border);
  color: var(--disabled-fg); cursor: default; box-shadow: none; }
.choice button:disabled::before { border-color: var(--gray-mid); background: var(--disabled-bg); }
/* a LOCKED election's applied status stays legible (officer coverage,
   §14: the state default may be immovable) — grey checked dot, distinct
   from both the active navy selection and a merely-unselected option */
.choice button:disabled[aria-checked="true"] { color: var(--ink); }
.choice button:disabled[aria-checked="true"]::before {
  content: "\2713"; border-color: var(--gray-mid); background: var(--gray-mid);
  color: #fff; }
/* [removed 2026-08-03, owner ruling 10] .choice-cue — no section retains
   the "choose one" text cue; missing-required guidance (ruling 11) is the
   replacement. */

/* ---- advance-attempt missing-item guidance (owner ruling 11, 2026-08-03).
   Appears ONLY after Continue is pressed with required items unanswered;
   the chip's icon+text carries the message (never colour alone), the
   outline makes the control findable at a glance. */
.is-missing input, .is-missing select, .is-missing textarea,
.choice.is-missing button {
  border-color: var(--amber); }
.field.is-missing > label { color: var(--amber-ink); }
.miss-chip { display: inline-flex; align-items: center; gap: 6px;
  width: fit-content; font-size: var(--fs-label); font-weight: var(--fw-semibold);
  color: var(--amber-ink); background: var(--amber-tint);
  border-radius: var(--r-pill); padding: 3px 10px;
  text-transform: uppercase; letter-spacing: .04em; }

/* repeating rows (classes, officers, history) */
.rep { display: grid; gap: var(--sp-2); }
.rep-row { display: grid; gap: var(--sp-3); align-items: end;
  background: var(--page); border: 1px solid var(--border); border-radius: var(--r-ctl);
  padding: var(--sp-3) var(--sp-4); }
.rep-row .del { justify-self: end; background: none; border: 0; cursor: pointer;
  color: var(--gray); font-size: var(--fs-small); padding: 6px; }
.rep-row .del:hover { color: var(--red-ink); }

/* class-code search combobox (owner feedback 2026-07-11: search by
   description/business type, not bare code) */
.cc-field { position: relative; }
.cc-dropdown { position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 20;
  background: var(--card); border: 1px solid var(--border-strong); border-radius: var(--r-ctl);
  box-shadow: var(--shadow-pop); max-height: 260px; overflow-y: auto; }
.cc-opt { display: flex; align-items: baseline; gap: 10px; padding: 8px 12px; cursor: pointer; }
.cc-opt:hover, .cc-opt.is-active { background: var(--tint-blue); }
.cc-opt-code { font-variant-numeric: tabular-nums; font-weight: var(--fw-semibold);
  color: var(--navy); flex: none; }
.cc-opt-text { display: flex; flex-direction: column; min-width: 0; }
.cc-opt-desc { color: var(--ink-soft); font-size: var(--fs-small);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* disambiguation note on ambiguous business-type matches ("table service ->
   9082; counter/quick service -> 9083") — quiet guidance under the official
   description; wraps freely so it stays readable at phone widths */
.cc-opt-note { color: var(--blue); font-size: var(--fs-label);
  line-height: var(--lh-small); white-space: normal; padding-top: 1px; }
.cc-desc { grid-column: 1 / -1; font-size: var(--fs-small); color: var(--ink-soft);
  padding-top: 2px; }
.cc-desc b { color: var(--navy); font-weight: var(--fw-semibold); }
/* unfinished/unknown class-code nudge — form-validation red, same as .error */
.cc-warn { color: var(--red-ink); font-weight: var(--fw-semibold); }

/* ruling 7 (batch three, 2026-08-05): strict MM/DD/YYYY effective-date
   entry — the BLUE calendar affordance sits LEFT of the field; the native
   picker input is visually retired but drives the calendar popup */
/* THE ERROR MESSAGE MUST NEVER STEAL THE FIELD'S WIDTH (item 1c, owner
   walkthrough 2026-08-30 - the third of the three failures he hit on a
   phone, and the one that made the other two unrecoverable).

   WHAT WAS ACTUALLY WRONG, MEASURED ON THE BASE TREE rather than read:
   `attachBlurValidation` inserts its message with `inputEl.after(err)`,
   which on every other field lands in a BLOCK container and renders on
   its own line - and here lands inside this FLEX row as a third item.
   The text box is `flex: 1; min-width: 0`, so it gave the whole line up
   to a 209px message and was left 30px wide:

       375px   field 239 -> 30      error box 209, same line as the field
       768px   field 281 -> 30      error box 251, same line as the field

   Thirty pixels is not a field an agent can correct a date in, so the
   message that says the date is wrong is what stops them fixing it.

   THE FIX IS ON THE ROW, NOT ON `attachBlurValidation`. That function
   serves nine fields across this flow and behaves correctly in all of
   them; the one that is different is this one, because it is the only
   one whose input has a flex sibling. So the ROW says how a message
   joins it - full basis, its own line - and every other field is
   untouched. */
.date-wrap { display: flex; align-items: stretch; flex-wrap: wrap;
  column-gap: 0; row-gap: 4px; position: relative; }
.date-wrap input[type="text"] { flex: 1; min-width: 0;
  border-top-left-radius: 0; border-bottom-left-radius: 0; }
.date-wrap .error { flex: 1 0 100%; }
.cal-btn { display: inline-flex; align-items: center; justify-content: center;
  width: 38px; flex: none; cursor: pointer;
  color: var(--blue); background: var(--tint-blue);
  border: 1px solid var(--border-strong); border-right: 0;
  border-radius: var(--r-ctl) 0 0 var(--r-ctl); }
.cal-btn:hover { color: var(--blue-hover); border-color: var(--blue); }
.cal-btn:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
/* THE CALENDAR SLOT (item 1b, 2026-08-30): the button and the native
   date control occupy ONE cell of the row, the control laid over the
   button at its full size. `.cal-slot` is what gives the overlay
   something to be absolute against - against `.date-wrap` it would have
   covered the wrapped error line too, once the rule above let the row
   wrap. */
.cal-slot { position: relative; flex: none; display: flex; }
/* SPECIFICITY IS DELIBERATE AND WAS NOT BEFORE. `.field input[type="date"]`
   is (0,2,1) and out-ranked the old `.date-picker-hidden` (0,1,0), so the
   1px width that rule declared never applied and the ghost input was
   actually full-width with the field's own border and padding - invisible
   only because of `opacity: 0`. Three classes beat it honestly. */
.field .cal-slot .date-picker-overlay { position: absolute; inset: 0;
  width: 100%; height: 100%; min-width: 0; margin: 0; padding: 0;
  border: 0; border-radius: var(--r-ctl) 0 0 var(--r-ctl);
  background: transparent; opacity: 0; cursor: pointer;
  -webkit-appearance: none; appearance: none; }
/* A FINGER-SIZED TARGET WHERE FINGERS ARE USED. 38px is comfortable for
   a mouse and under the 44px touch floor; the slot widens on the narrow
   widths the mobile mandate names, and the overlay follows it because it
   is sized from the slot rather than in pixels of its own. */
@media (max-width: 560px) {
  .cal-btn { width: 46px; }
}

/* Part B ruling 1 (2026-08-05): submission-document upload rows — the
   agent's attached loss runs / applications, superseded rows dimmed but
   retained (permanent file) */
.doc-row { display: flex; align-items: baseline; gap: 10px;
  padding: 7px 0; border-bottom: 1px solid var(--border);
  font-size: var(--fs-small); }
.doc-row:last-child { border-bottom: none; }
.doc-row.is-superseded { opacity: .55; text-decoration: line-through; }
.doc-kind-chip { flex: none; font-size: var(--fs-label); text-transform: uppercase;
  letter-spacing: .07em; font-weight: var(--fw-semibold); color: var(--navy);
  background: var(--tint-blue); border-radius: var(--r-pill); padding: 2px 9px;
  text-decoration: none; }
/* Ruling 4 (owner, 2026-08-06): the type picker sits beside the attach
   control at every entry point. Deliberately a labelled select, not a
   guess: the type is stored on the record and becomes the workbench chip,
   so the agent states it rather than the system inferring it. Stacks on
   phones so neither control is squeezed. */
.doc-pick { display: flex; align-items: flex-end; gap: var(--sp-3);
  flex-wrap: wrap; }
.doc-type { display: grid; gap: 4px; }
.doc-type-label { font-size: var(--fs-label); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--gray); }
.doc-type select { font: inherit; font-size: var(--fs-small); color: var(--ink);
  background: var(--card); border: 1px solid var(--border-strong);
  border-radius: var(--r-ctl); padding: 8px 12px; min-width: 15rem; }
@media (max-width: 640px) {
  .doc-pick { display: grid; }
  .doc-type select { width: 100%; }
}
/* THE NAME BREAKS AT A WORD BOUNDARY (walkthrough follow-on item 15, owner
   walkthrough 2026-09-25). `overflow-wrap: anywhere` lowered the name's
   min-content width to one character, so in a row that does not wrap the
   chip, the size and the buttons squeezed it and it broke mid-word at
   1280. The name now takes the row's free space first, its break
   opportunities are the separators doclist.js marks, and a single run
   breaks only when it alone is wider than the line (break-word). */
.doc-name { font-weight: var(--fw-semibold); color: var(--ink);
  flex: 1 1 14rem; min-width: min(14rem, 100%); overflow-wrap: break-word; }
.doc-row > .hint { flex: none; }
/* AND THE ROW WRAPS RATHER THAN SQUEEZE IT (cloud gate 36359427159: a
   narrower column on the Linux runner's wider face at 768 squeezed the
   name below one word): the name keeps its 14rem floor and the size and
   the buttons move to the next line when the row cannot hold all four -
   the 560px rule below, now at every width. On a row that fits, nothing
   moves. */
.doc-row { flex-wrap: wrap; }

/* Drag-and-drop upload zone (owner ruling 3, 2026-08-07) — ONE shared
   component (portal/dropzone.js) at all four upload doors. A quiet
   dashed field that comes alive on hover/drag, never a billboard; the
   browse control stays a real focusable input (visually hidden, focus
   ring on the label) so keyboard and mobile users lose nothing. The
   drag-over state uses the interactive accent (blue marks interaction,
   per the color discipline); progress and success are carried by words
   plus the bar, never color alone. Token-only. */
.dz { border: 1.5px dashed var(--border-strong); border-radius: var(--r-ctl);
  background: var(--card); padding: var(--sp-4);
  transition: border-color .15s ease, background-color .15s ease;
  cursor: pointer; }
.doc-pick + .dz { margin-top: var(--sp-3); }
.dz:hover { border-color: var(--blue); }
.dz.is-over { border-color: var(--blue); background: var(--tint-blue); }
/* ITEM 2 (2026-08-17): the document list is its own surface now, placed
   independently of any upload door, so it carries its own heading and
   frame rather than inheriting a zone's. `.doc-row` keeps the
   presentation it had inside the door, so nothing an agent already
   recognises moves. */
.doc-surface { margin-top: var(--sp-4); }
.doc-surface-head { font-weight: var(--fw-semibold); color: var(--ink);
  margin-bottom: var(--sp-2); }
.doc-surface-head .hint { font-weight: var(--fw-regular); }
/* THE LIST ALWAYS SAYS SOMETHING. A surface that renders nothing cannot be
   told apart from a surface that is missing, which is the defect this
   whole item exists to stop repeating. */
.doc-empty { color: var(--gray); font-size: var(--fs-small);
  padding: var(--sp-3) 0; }
/* ITEM 3 (2026-08-17): every row opens. A button rather than a link,
   because this is an action and not a destination, styled as the quiet
   inline control it is. */
.doc-open { margin-left: auto; flex: none; background: none; border: 0;
  padding: 0; font: inherit; font-size: var(--fs-small);
  font-weight: var(--fw-semibold); color: var(--blue); cursor: pointer;
  text-decoration: underline; }
.doc-open:hover { color: var(--navy); }
.doc-open:focus-visible { outline: 3px solid var(--focus-ring);
  outline-offset: 2px; border-radius: 3px; }
.doc-open[disabled] { color: var(--gray); cursor: default;
  text-decoration: none; }
/* a superseded row keeps its mark AND its control: the file is still on
   the permanent file, and showing it while refusing to produce it is the
   same defect in a smaller box */
.doc-row.is-superseded .doc-open { color: var(--gray); }
/* the agent's Remove control (standing ruling, 2026-08-20). The same quiet
   link treatment as Download - it is not a destructive-looking button,
   because nothing is destroyed - and it turns amber only while ARMED, which
   is the one moment the next click actually does something. `margin-left`
   is not `auto` here: Download already claimed the gap, and this sits
   beside it. */
.doc-remove { flex: none; background: none; border: 0; padding: 0 0 0 14px;
  font: inherit; font-size: var(--fs-small);
  font-weight: var(--fw-semibold); color: var(--ink-soft); cursor: pointer;
  text-decoration: underline; }
.doc-remove:hover { color: var(--navy); }
.doc-remove:focus-visible { outline: 3px solid var(--focus-ring);
  outline-offset: 2px; border-radius: 3px; }
.doc-remove.is-armed { color: var(--amber-ink); }
.doc-remove[disabled] { color: var(--gray); cursor: default;
  text-decoration: none; }
.doc-row-msg { flex-basis: 100%; font-size: var(--fs-small); }
/* WALKTHROUGH (2026-08-21, fifty-ninth entry): at phone width a document
   row's fixed-width pieces (kind chip, meta, Download, Remove) outgrow the
   row and the Remove control pushed the PAGE 8px wide - measured at 375 on
   the bind page, reproduced through the pre-existing row door, so it
   predates this entry's door. The row wraps instead: `.doc-row-msg` has
   carried `flex-basis: 100%` since removal landed, which only ever did
   anything on a row that CAN wrap. */
@media (max-width: 560px) {
  .doc-row { flex-wrap: wrap; }
}

/* ITEM 1 (2026-08-17): a door whose type catalog did not load stops
   accepting files. The refusal lives in dropzone.js; this is the part the
   agent can see, so the zone does not look ready while it is paused. The
   hover and drag-over affordances are suppressed for the same reason. */
.doc-upload[data-uploads="paused"] .dz { opacity: .55; cursor: not-allowed; }
.doc-upload[data-uploads="paused"] .dz:hover,
.doc-upload[data-uploads="paused"] .dz.is-over {
  border-color: var(--border-strong); background: var(--card); }
.doc-upload[data-uploads="paused"] .dz-browse { pointer-events: none;
  opacity: .6; }
.dz-inner { display: flex; align-items: center; gap: var(--sp-3);
  flex-wrap: wrap; }
.dz-copy { margin: 0; color: var(--ink-soft); flex: 1; min-width: 0; }
.dz-copy b { color: var(--ink); font-weight: var(--fw-semibold); }
.dz-browse { position: relative; cursor: pointer; flex: none; }
.dz-browse:focus-within { outline: 3px solid var(--focus-ring);
  outline-offset: 2px; }
.dz-input { position: absolute; width: 1px; height: 1px; opacity: 0;
  overflow: hidden; clip: rect(0 0 0 0); }
.dz-hint { flex-basis: 100%; font-size: var(--fs-small); color: var(--gray); }
.dz-file { margin-top: var(--sp-3); cursor: default; }
.dz-file-line { display: flex; justify-content: space-between;
  align-items: baseline; gap: var(--sp-3); }
.dz-file-name { font-weight: var(--fw-medium); font-size: var(--fs-small);
  color: var(--ink); overflow-wrap: anywhere; }
.dz-file-state { flex: none; font-size: var(--fs-small);
  color: var(--ink-soft); }
.dz-file.is-done .dz-file-state { color: var(--green-ink);
  font-weight: var(--fw-semibold); }
.dz-file.is-error .dz-file-state { flex: 1; color: var(--red-ink); }
.dz-file.is-error .dz-file-line { flex-wrap: wrap; }
.dz-bar { height: 6px; margin-top: 6px; border-radius: var(--r-pill);
  background: var(--gray-light); overflow: hidden; }
.dz-bar-fill { height: 100%; width: 0; background: var(--blue);
  border-radius: var(--r-pill); transition: width .15s ease; }
.dz-file.is-done .dz-bar-fill { background: var(--green); }
.dz-file.is-error .dz-bar { display: none; }
/* THE SPLIT FAMILY IS RETIRED WITH ITS SHAPE (upload v3, batch E item 1,
   2026-08-22). Item 13's two flex-1 columns stacked only under 640px, so
   at every width between 641 and the desktop breakpoints each column got
   roughly 300px for a dropdown, a button, a hint and a drop target - the
   squished which-form ask the owner photographed. The v3 zone is the
   component's stacked default shape plus the drop-flow ask below it. */
.dz-ask { margin-top: var(--sp-2); padding: var(--sp-3);
  border: 1px solid var(--border); border-radius: var(--r-ctl);
  background: var(--card); }
.dz-ask .ap-formpick { margin-top: 0; }
.dz-ask-files { font-size: var(--fs-small); color: var(--ink-soft);
  margin-bottom: var(--sp-2); overflow-wrap: anywhere; }
.dz-ask-files:empty { display: none; margin: 0; }
.dz-ask-actions { display: flex; gap: var(--sp-2); margin-top: var(--sp-2);
  flex-wrap: wrap; }
@media (max-width: 640px) {
  /* `minmax(0, 1fr)` RATHER THAN THE IMPLICIT `auto` TRACK, and it is
     the third instance of one mechanism (owner mobile walkthrough
     2026-08-31). An implicit grid track is sized `auto`, whose BASE is
     the largest min-content contribution of its items - and that base is
     not clamped by the container. At 320 this stacked column measured
     255.297px inside a 188px zone and put 1.3px past the viewport.
     Capping the track at the container is what `minmax(0, 1fr)` says. */
  .dz-inner { display: grid; grid-template-columns: minmax(0, 1fr); }
  /* its words may wrap rather than spill out of the button (standing rule
     366: "Attach loss runs (PDF or Word)" spilled 265px of text from a
     188px button at 320 on the cloud's widest letters) */
  .dz-browse { text-align: center; white-space: normal; max-width: 100%; }
  .dz-file-state { flex: none; }
}

/* ruling 6c (batch three, 2026-08-05): a class row created from the officer
   section is visibly marked on the payroll screen */
.off-origin-chip { display: inline-block; font-size: var(--fs-label);
  color: var(--navy); background: var(--tint-blue);
  border-radius: var(--r-pill); padding: 3px 10px; margin-top: 2px; }
.off-addclass { display: block; background: none; border: none; cursor: pointer;
  color: var(--blue); font-size: var(--fs-small); padding: 0; margin-top: 5px;
  text-align: left; }
.off-addclass:hover { color: var(--blue-hover); text-decoration: underline; }
.off-addclass-form { position: relative; margin-top: 5px; }

/* officer rows: fields wrap onto as many lines as they need — nothing gets
   squeezed; the remove button sits in the corner instead of eating a column */
/* 216px, not 180 (owner walkthrough 2026-09-25, cleanup item 5): the
   narrowest officer cell must hold the Included / Excluded pair side by
   side with neither label shrunk past its pill - measured element-level
   at 1280/768/375 by tests/test_browser_officer_coverage_fit_20260925.py */
.rep-row.officer { position: relative;
  grid-template-columns: repeat(auto-fit, minmax(216px, 1fr));
  padding-right: 44px;
  /* D3 fix (owner defect 2026-08-06): the shared .rep-row rule bottom-aligns
     its cells, which works only while every cell is label-over-control. The
     Class cell carries the "+Add a class code" link BELOW its select
     (ruling 6c, 2026-08-05), so bottom-alignment lifted that select 25px
     clear of every other control on the same line — the misalignment the
     owner reported. Officer-row labels are a single line at every width
     from 375px up, so TOP-aligning the cells puts every control on one
     line and lets the add-class link hang under its own field where it
     belongs. Pinned by tests/test_officer_class_alignment_d3.py. */
  align-items: start; }
/* ruling 2 (batch three, 2026-08-05): Included and Excluded sit ADJACENT —
   the pair never wraps into a stack; narrower padding so both fit the cell */
.rep-row.officer .off-cov .choice { flex-wrap: nowrap; gap: 6px; }
/* a button never shrinks below its own label: `flex: 1 1 0; min-width: 0`
   let "Excluded" run out of its pill in a narrow cell (cleanup item 5).
   The chrome is tighter than the shared pill (6px sides, 6px dot gap, 6px
   between the pair): the cloud's Linux face is wider than the desk's, and
   at 375 the pair needed 222px of the 216px cell (cloud gate 36167123614) */
.rep-row.officer .choice button { flex: 1 0 auto; gap: 6px;
  padding-left: 6px; padding-right: 6px; white-space: nowrap; }
/* ON A PHONE THE CORNER'S ROOM IS THE FIRST LINE'S ONLY (standing rule 366,
   measured 2026-10-03): with every letter 3px wider the pair needed about
   230px of a 216px cell at 375, because the row reserved 44px for the
   delete corner down its whole height. Cells stack one per line here, and
   the corner sits beside the first (Name) alone - so that field keeps the
   44px and every line under it, the coverage pair's too, gets the row's
   full width. The pair still never stacks (ruling 2, 2026-08-05). */
@media (max-width: 600px) {
  /* and on the cloud's wider fonts (gate 37136165972: the pair needed 254px
     of a 243px cell) the row's sides are 10px and each button's 4px */
  .rep-row.officer { padding-left: 10px; padding-right: 10px; }
  .rep-row.officer > .field:first-child { margin-right: 34px; }
  .rep-row.officer .choice button { padding-left: 4px; padding-right: 4px; }
}
.del-corner { position: absolute; top: 10px; right: 10px; }
/* multi-entity ruling 1 (2026-08-05): entity rows use the officer-row
   wrap pattern — fields flow onto as many lines as they need at phone
   widths, nothing squeezed; remove button in the corner */
.rep-row.entity { position: relative;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  padding-right: 44px; }
/* THE FIVE ROWS THAT USED TO CARRY AN INLINE `grid-template-columns`
   (species A, owner mobile walkthrough 2026-08-31).

   THE OWNER'S REPORT WAS "crushed and can't be used", and the measured
   version of it at 375 was a class-code box holding 28px for a value
   needing 288, a payroll box holding 61 for 73, and a street-address box
   holding 31 for 152. The cause was one pattern in five places: these
   rows declared a FIXED column template inline, so it applied at every
   width and there was no rule a stylesheet could write to override it.
   Their siblings `.officer` and `.entity` — THE SECTION THE OWNER NAMED
   AS THE REFERENCE — wrap instead, and have since the 2026-08-05/06
   rulings that put them there.

   SO THE TEMPLATES MOVED HERE AND THE MOBILE BEHAVIOUR IS ONE RULE. The
   desktop layouts below are the same numbers that were inline, moved
   rather than redesigned; the media query underneath converges every one
   of them on the reference pattern.

   THE BREAKPOINT IS 900, WHICH IS NOT A NEW NUMBER. It is where `.flow`
   already stops being two columns and the rail becomes a strip — the
   width at which this page has always agreed it is narrow. Below it the
   rows wrap; at and above it they keep the columns they had. */
.rep-row.classes         { grid-template-columns: 100px 2.2fr 1fr auto; }
.rep-row.location        { grid-template-columns: 2fr 1.2fr 90px 110px auto; }
.rep-row.entity-address  { grid-template-columns: 2fr 1.2fr 90px 110px; }
/* A WAIVER ROW IS STATE / HOLDER / (CLASS) / REMOVE (2026-09-05).
   The Charge box is gone: what a waiver costs is a SENTENCE served
   per state and printed once above the rows, because a state can now
   price a percentage and "the greater of $250 or 2%" does not fit in
   a 90px box at 375. The class column appears only where the state
   prices off the holder's class, which is North Carolina today. */
.rep-row.waiver          { grid-template-columns: 110px 1fr auto; }
.rep-row.waiver.with-class { grid-template-columns: 110px 1fr 150px auto; }
/* a prior policy year: its label, then carrier, premium, incurred losses
   and the number of claims (walkthrough item 4, 2026-10-03) */
.rep-row.year            { grid-template-columns: 130px minmax(0, 2fr) repeat(3, minmax(0, 1fr)); }
/* THE CARRIER NAME NEEDS ROOM (workbench walkthrough gate fix, 2026-10-03):
   cloud gate 37170687706 measured it at 768 with letters 3px wider - a
   representative name needs 232px and the five-across wrap gave the box
   197px. Below the 900px breakpoint a year's fields wrap at 240px each,
   and the carrier takes a full line where the row is one field wide. */
@media (max-width: 900px) {
  /* `.rep` in front: the shared wrap rule just below names this row too */
  .rep .rep-row.year { grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
}

@media (max-width: 900px) {
  .rep-row.classes, .rep-row.location, .rep-row.entity-address,
  .rep-row.waiver, .rep-row.waiver.with-class, .rep-row.year {
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    align-items: start;
  }
  /* THE CLASS-CODE FIELD TAKES THE WHOLE ROW, and it is the one field
     on this platform that needs its own line in this rule. Unfocused it
     displays "CODE - DESCRIPTION", the longest single-line value any
     agent-facing input holds - 288px for `8810 - CLERICAL OFFICE
     EMPLOYEES NOC` - where the reference pattern's own cell is 180.

     `1 / -1` RATHER THAN `span 2`, AND THE DIFFERENCE WAS MEASURED. A
     span of two FORCES a second track into an `auto-fit` grid that had
     room for one: at 375 the row resolved to `180px 51px` and the
     class code took 243 of the 245 available, leaving a 51px sliver
     nothing else could use. Spanning to the end asks for the row rather
     than for a track count, so the narrow case stays one column and the
     wide case gives the field the full width instead of two thirds. */
  .rep-row.classes .cc-field { grid-column: 1 / -1; }
  /* A STREET ADDRESS TAKES THE WHOLE ROW TOO (standing rule 366, measured
     2026-10-03): with every letter 3px wider '220 Peachtree St NE' needs
     209px and the location row's auto-fit cell held 187 at 768 - the
     sweep's VALUE floor. Same rule, same reason as the class code above:
     the longest single-line value in the row gets the row. */
  .rep-row.location .addr-field { grid-column: 1 / -1; }
  /* REMOVE GOES IN THE CORNER, AS IT DOES IN THE REFERENCE (UW workbench
     batch 3 rider A, 2026-09-10).

     `repeat(auto-fit, minmax(180px, 1fr))` hands EVERY grid child of a row
     a track - the Remove button included - so at 768 the waiver row's
     state, holder and Remove each took a third of the box, and the holder
     showed 185px of "Peachtree Property Partners LLC" (224px; the
     2026-09-10 sweep's one VALUE finding, 768 only).

     THE REFERENCE THIS RULE CONVERGES ON ALREADY SAID WHAT TO DO. The
     officer and entity rows put Remove "in the corner instead of eating a
     column" (`.del-corner`, above), and the five rows that converged on
     their track template did not take that half. So the rows here whose
     Remove is the reference's own small cross - location and waiver -
     take it now. Out of the grid, Remove leaves the last track empty, and
     `auto-fit` collapses an empty track, so the fields share the row.

     A FIRST CUT GAVE REMOVE ITS OWN LINE (`grid-column: 1 / -1`) AND WAS
     MEASURED DOING NOTHING: a spanning item occupies every track on its
     line, so no track was empty and the holder kept its third. The classes
     row keeps its labelled "Remove" in a track - it is not the reference's
     cross, and that row carries no finding.

     ONLY WHERE A ROW HAS MORE THAN ONE TRACK, which is the block below.
     Below 768 these rows are a single column and Remove on its own line
     costs a field nothing; the corner's 44px of padding did - measured, the
     holder's box at 375 went from 207px to 179px on the unscoped cut. 768
     is not a new number: it is the flow's own phone breakpoint (`max-width:
     767px`) and the width the 44px ruling names beside 375. */
}

@media (min-width: 768px) and (max-width: 900px) {
  .rep-row.location, .rep-row.waiver {
    position: relative; padding-right: 44px; }
  .rep-row.location > .del, .rep-row.waiver > .del {
    position: absolute; top: 10px; right: 10px; }
}

.rep-add { justify-self: start; }
.rep-group-head { font-size: var(--fs-label); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--gray); font-weight: var(--fw-semibold);
  margin-top: var(--sp-2); }

/* Per-entity roster grouping (owner ruling 2, 2026-08-06): a multi-entity
   quote groups the people under their entity; single-entity quotes never
   render these. Informational navy family, not a status color. */
.off-entgroup { margin-top: var(--sp-2); }
.off-enthead { font-size: var(--fs-label); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--navy); font-weight: var(--fw-semibold);
  border-bottom: 1px solid var(--border-strong); padding-bottom: 4px;
  margin-bottom: 8px; }

/* Owners & Officers coverage messages (spec §14): the inline chips that
   explain every payroll adjustment, election rule, and form requirement AT
   ENTRY TIME — informational voice (navy on tint-blue, same family as
   .callout-note), never a status color. All amounts shown are annual. */
.off-chips { grid-column: 1 / -1; display: grid; gap: 5px; }
.off-chip { display: block; font-size: var(--fs-small); line-height: var(--lh-small);
  color: var(--navy); background: var(--tint-blue); border-radius: var(--r-ctl);
  padding: 6px 11px; max-width: 72ch; }
.off-chip-info { background: var(--neutral-tint); color: var(--ink-soft); }
.off-covnote { display: block; margin-top: 5px; font-size: var(--fs-label);
  line-height: var(--lh-small); color: var(--ink-soft); max-width: 32ch; }
.off-fixed { display: inline-block; font-size: var(--fs-small);
  font-weight: var(--fw-semibold); color: var(--navy);
  background: var(--neutral-tint); border-radius: var(--r-pill);
  padding: 7px 14px; }
/* compact entered-vs-applied block on the quote result (spec §14 step 4) */
.off-summary { background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: var(--sp-4) var(--sp-5); }
.off-summary-head { font-weight: var(--fw-semibold); color: var(--navy);
  margin-bottom: var(--sp-2); }
.off-sum-row { display: flex; justify-content: space-between; gap: var(--sp-3);
  font-size: var(--fs-small); padding: 4px 0; flex-wrap: wrap; }
.off-sum-name { font-weight: var(--fw-semibold); }
.off-summary .off-chip { margin: 2px 0 6px; }

/* noticeable inline callout — for guidance an agent could easily skim past
   as plain gray text ("this is optional", "doesn't affect the premium",
   "entered elsewhere"). Same visual language as .why. Reserved for real
   heads-up notes, not tiny inline format hints like "(9 digits)". */
.callout-note { display: block; text-transform: none; letter-spacing: normal;
  font-size: var(--fs-small); font-weight: 400; color: var(--navy);
  background: var(--tint-blue); border-radius: var(--r-ctl);
  padding: 7px 12px; margin-top: 6px; max-width: 62ch; }
.rep-group-head .callout-note { margin-top: 8px; }

/* THE DIVIDEND CALLOUT (owner rulings 2026-10-19, D1: option A, the green
   band). A plan on the quote is GOOD NEWS, so it is not the blue
   information note (navy on --tint-blue), the amber warning or the red
   error: --tint-green with a solid --green rule and a green medallion, the
   brand's money colour and the hero chip's. Every pair is the theme's own
   tokens and clears WCAG AA: green-ink on tint-green 5.86, ink on
   tint-green 14.3, the white coin on --green 3.99 and the --green rule on
   its tint 3.36 (3:1, non-text). It carries no button (owner, at sign-off,
   2026-10-19). */
.dv-callout { display: flex; gap: 14px; align-items: flex-start;
  margin: 12px 0 14px; padding: 16px 18px;
  background: var(--tint-green); color: var(--ink);
  border-left: 5px solid var(--green); border-radius: var(--r-card);
  font-family: var(--font-ui); }
.dv-callout .dv-medal { flex: 0 0 auto; width: 44px; height: 44px;
  border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: var(--green); color: var(--on-color); }
.dv-callout .dv-body { min-width: 0; flex: 1 1 auto; }
.dv-callout .dv-eyebrow { font-size: var(--fs-label); letter-spacing: var(--ls-label);
  text-transform: uppercase; font-weight: var(--fw-semibold); color: var(--green-ink); }
.dv-callout .dv-head { font-size: var(--fs-h2); line-height: var(--lh-h2);
  font-weight: var(--fw-semibold); color: var(--green-ink); margin: 2px 0 4px; }
.dv-callout .dv-text { font-size: var(--fs-body); line-height: var(--lh-body);
  margin: 0; color: var(--ink); }

/* REQUEST A DIVIDEND PLAN (owner rulings 2026-09-17/18): the quoted page's
   request control rides the dividend line's own callout, so it reads as
   the same subject. The note box is the referral note's control at a
   shorter height, and the button and the box are 44px touch targets. */
/* full width of its band: the callout's 62ch reading cap left it 302px
   off centre at 768, which the centring floor caught in the gate */
.div-request { margin-top: 10px; padding: 12px 14px; max-width: none; }
.div-request .dr-label { display: block; margin-top: 10px; font-size: var(--fs-small);
  color: var(--navy); }
.div-request .dr-note { width: 100%; min-height: 44px; margin-top: 4px; resize: vertical;
  font: inherit; color: var(--ink); padding: 8px 10px; border: 1px solid var(--border-strong);
  border-radius: var(--r-ctl); background: var(--card); box-sizing: border-box; }
.div-request .dr-note:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
.div-request .dr-acts { margin-top: 10px; }
.div-request .dr-acts .btn { min-height: 44px; max-width: 100%;
  white-space: normal; text-align: center; }  /* standing rule 366 */

/* review-step "needs attention" summary — informational (navy on tint-blue,
   same family as .callout-note / .why), NOT a status color. Lists every
   incomplete/invalid item with a jump link before the agent can quote. */
.needs-attention { background: var(--tint-blue); color: var(--navy);
  border-radius: var(--r-card); padding: var(--sp-4) var(--sp-5); margin-bottom: var(--sp-5); }
.needs-attention > b { display: block; margin-bottom: var(--sp-2); font-weight: var(--fw-semibold); }
.needs-attention ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 7px; }
.needs-attention li { display: flex; align-items: baseline; gap: var(--sp-3);
  justify-content: space-between; font-size: var(--fs-small); }
.needs-attention li b { font-weight: var(--fw-semibold); }
.needs-attention li a { color: var(--navy); font-weight: var(--fw-semibold);
  text-decoration: underline; white-space: nowrap; }

/* rating-variables: deductible + credit boxes, aligned per-state rows */
.rv-box { border: 1px solid var(--border); border-radius: var(--r-card);
  background: var(--page); padding: var(--sp-4); display: grid; gap: var(--sp-3); }
.rv-row { display: grid; grid-template-columns: 48px minmax(0, 1fr);
  gap: var(--sp-4); align-items: start; }
.rv-row + .rv-row { border-top: 1px solid var(--border); padding-top: var(--sp-3); }
.rv-state { font-weight: var(--fw-semibold); color: var(--ink);
  font-size: var(--fs-small); padding-top: 9px; }
.rv-box .field { max-width: 360px; }

.credit-list { display: grid; gap: 8px; padding-top: 2px; }
.credit-opt { display: flex; align-items: center; gap: 10px;
  font-size: var(--fs-body); color: var(--ink); cursor: pointer; }
.credit-opt input { width: 16px; height: 16px; accent-color: var(--blue); cursor: pointer; flex: none; }
/* the label wraps and never sets the row's floor - `.check-opt`'s rule
   below (standing rule 366, measured 2026-10-03: with every letter 3px
   wider a credit's name ran 1px past a 320 screen) */
.credit-opt span { flex: 1; min-width: 0; overflow-wrap: anywhere; }
/* A LABELLED CHECKBOX ON ITS OWN ROW - "Mailing address only" under the
   Primary/Mailing Address on the flow and the workbench (owner ruling
   2026-09-27). The text wraps; the box keeps its size. */
.check-opt { display: flex; align-items: center; gap: 10px;
  min-height: var(--tap-aa, 24px); margin: 4px 0 8px;
  font-size: var(--fs-body); color: var(--ink); cursor: pointer; }
.check-opt input { width: 24px; height: 24px; margin: 0;
  accent-color: var(--blue); cursor: pointer; flex: none; }
.check-opt span { flex: 1; min-width: 0; }
.credit-opt b { color: var(--green); font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums; }  /* credit % = money saved = green */
.credit-box .why { margin-top: var(--sp-1); }

/* conditional question why-note */
.why { display: flex; gap: 8px; align-items: baseline; font-size: var(--fs-small);
  color: var(--navy); background: var(--tint-blue); border-radius: var(--r-ctl);
  padding: 6px 12px; }

/* question rows */
.q-row { display: flex; align-items: center; gap: var(--sp-4); padding: 12px 0;
  border-bottom: 1px solid var(--border); }
.q-row:last-child { border-bottom: 0; }
.q-row .q-text { flex: 1; }
.q-row .q-text .why { margin-top: 6px; }

/* autosave chip */
.autosave { display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--fs-small); color: var(--gray); font-variant-numeric: tabular-nums; }
.autosave .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--gray-mid); }
.autosave.is-saved .dot { background: var(--green); }
.autosave.is-saving .dot { background: var(--amber); }
.autosave.is-error .dot { background: var(--red); }

/* welcome-back banner (resume) */
/* SPECIES G (owner mobile walkthrough 2026-08-31, and FOUND BY THE CLOUD
   GATE RATHER THAN BY THIS DESK). A flex row with no `flex-wrap` cannot
   get narrower than its widest rigid item, and this row has one: the
   "start a new quote" link is `white-space: nowrap`. On this desk's font
   metrics the row fitted 375 exactly and every local measurement read
   zero overflow; on the runner's metrics it was 48px too wide and took
   the whole page with it, on EVERY step of the flow. 320 reproduces it
   here - 49px - which is why the sweep now runs that width too. */
.resume-banner { display: flex; align-items: center; gap: var(--sp-3);
  flex-wrap: wrap;
  background: var(--tint-blue); color: var(--navy); border-radius: var(--r-card);
  padding: var(--sp-3) var(--sp-5); margin-bottom: var(--sp-4); }
.resume-banner b { font-weight: var(--fw-semibold); }
.resume-banner a { color: var(--navy); font-weight: var(--fw-semibold);
  text-decoration: underline; white-space: nowrap; }
.resume-banner .close { margin-left: auto; background: none; border: 0; cursor: pointer;
  color: var(--navy); font-size: 16px; }

/* review step — REDESIGNED to the plan-card standard (batch-three ruling
   15a, 2026-08-05, exemplar for the owner checkpoint): navy section heads
   with the sky step eyebrow (the .pcard .phead vocabulary), a card deck
   that reads as a set, and a premium ready-to-quote band. Every fact and
   behavior (kv rows, Edit links, needs-attention flags, the Get-my-quote
   mechanics) is unchanged — this is presentation only. */
.review-deck { display: grid; grid-template-columns: 1fr 1fr;
  gap: var(--sp-3); align-items: start; }
.review-section { border: 1px solid var(--border); border-radius: var(--r-card);
  overflow: hidden; background: var(--card); box-shadow: var(--shadow-card);
  display: flex; flex-direction: column; }
/* SPECIES G's SECOND INSTANCE, and the same shape: this row's `h3` is a
   flex item, a flex item's default `min-width: auto` refuses to shrink
   below its content, and `.edit` carries `margin-left: auto` - so a
   heading one font wider than this desk's pushes the Edit chip out
   through `.review-section`'s own `overflow: hidden`. MEASURED on the
   runner: right edge 343 against a clipping ancestor at 326. Letting the
   heading shrink and the row wrap keeps the chip inside at every width;
   nothing about the treatment moves. */
.review-head { display: flex; align-items: center; gap: var(--sp-3);
  flex-wrap: wrap;
  padding: 11px 18px 10px; background: var(--navy); }
.review-head h3 { font-size: 14px; font-weight: var(--fw-semibold);
  min-width: 0; overflow-wrap: anywhere;
  color: var(--on-navy, #fff); line-height: 1.25; }
.review-head .rv-eyebrow { font-size: 10px; color: var(--sky-onnavy);
  text-transform: uppercase; letter-spacing: .14em; font-weight: var(--fw-semibold);
  margin-right: 2px; }
.review-head .edit { margin-left: auto; font-size: var(--fs-label);
  font-weight: var(--fw-semibold); color: var(--on-navy, #fff);
  background: var(--on-navy-pill); border: 1px solid var(--on-navy-border);
  border-radius: var(--r-pill); padding: 3px 12px; text-decoration: none; }
.review-head .edit:hover { background: var(--on-navy-border); }
.review-body { padding: var(--sp-4) 18px; display: grid; gap: 8px;
  font-size: var(--fs-body); flex: 1; }
.review-body .kv { display: flex; gap: var(--sp-3);
  padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.review-body .kv:last-child { border-bottom: none; padding-bottom: 0; }
.review-body .kv .k { flex: none; width: 150px; color: var(--gray);
  font-size: var(--fs-label); text-transform: uppercase;
  letter-spacing: .07em; font-weight: var(--fw-semibold); padding-top: 2px; }
.review-body .kv .v { color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
.review-missing { color: var(--amber-ink); background: var(--amber-tint);
  border-radius: var(--r-pill); padding: 2px 10px; font-size: var(--fs-label);
  font-weight: var(--fw-semibold); letter-spacing: .04em; text-transform: uppercase; }
/* the ready band — the moment everything checks out (navy statement,
   matching the hero language) */
.rv-ready { display: flex; align-items: center; gap: var(--sp-4);
  background: linear-gradient(120deg, var(--navy-hover), var(--navy));
  color: var(--on-navy, #fff); border-radius: var(--r-card);
  box-shadow: var(--shadow-card); padding: var(--sp-4) var(--sp-5);
  margin-bottom: var(--sp-4); flex-wrap: wrap; }
.rv-ready .rv-ready-title { font-size: var(--fs-h2); font-weight: var(--fw-semibold); }
.rv-ready .rv-ready-sub { color: var(--on-navy-soft); font-size: var(--fs-small);
  margin-top: 2px; }
.rv-ready .btn { margin-left: auto; }
@media (max-width: 900px) {
  .review-deck { grid-template-columns: 1fr; }
  .rv-ready .btn { margin-left: 0; width: 100%; }
  .review-body .kv { flex-direction: column; gap: 2px; }
  .review-body .kv .k { width: auto; }
}

/* [removed 2026-08-03, owner ruling 2] .flow-result / .flow-commission /
   .flow-incentive — the in-flow post-quote result box is retired; "Get my
   quote" lands directly on the full quote. The rewards presentation
   (.reward-* family) moved into the hero-band section above (ruling 3). */

@media (max-width: 900px) {
  .flow { grid-template-columns: 1fr; }
  /* `min-width: 0` IS THE FIX FOR SPECIES D (owner mobile walkthrough
     2026-08-31), and it is one word for a 42px page overflow.

     MEASURED: `quote_flow.html` at 375 scrolled 42px wider than the
     viewport, and the widest element was `button.rail-step` with its
     right edge at 1082.9 of 375. The rail already declares
     `overflow-x: auto`, so its content is supposed to scroll INSIDE it -
     but it is a GRID ITEM, and a grid item's default `min-width: auto`
     lets it grow to fit its content rather than clip. So the strip that
     was meant to scroll instead took the page with it. */
  .flow > * { min-width: 0; }
  .rail { position: static; display: flex; overflow-x: auto; padding-bottom: 4px;
          min-width: 0; }
  .rail-progress { display: none; }
  .rail-step { flex: none; }
}

/* =========================================================================
   Pager — twenty submissions to a page, Next/Prev (C2, carried 4A ruling 8)
   -------------------------------------------------------------------------
   ONE definition serving BOTH paged surfaces: the agent board here and the
   console's All Submissions archive, which @imports this file. Token-only:
   the buttons are the white-secondary treatment the board already uses,
   the count is the same tabular-num figure style. Disabled ends use the
   shared --disabled-* pair rather than vanishing, so the control never
   moves under the cursor at the ends of the book.
   ========================================================================= */
.pager { display: flex; align-items: center; justify-content: center;
  gap: var(--sp-4); margin-top: var(--sp-4); flex-wrap: wrap; }
.pager button { font: inherit; font-size: var(--fs-small);
  font-weight: var(--fw-semibold); color: var(--navy); background: var(--card);
  border: 1px solid var(--border-strong); border-radius: var(--r-pill);
  padding: 8px 18px; cursor: pointer; }
.pager button:hover:not(:disabled) { border-color: var(--navy); }
.pager button:disabled { color: var(--disabled-fg); background: var(--disabled-bg);
  border-color: var(--border); cursor: default; }
.pager-count { font-size: var(--fs-small); color: var(--ink-soft);
  font-variant-numeric: tabular-nums; }

/* =========================================================================
   SPECIES E — THE CONTROLS BELOW WCAG 2.5.8 LEVEL AA
   (owner mobile walkthrough 2026-08-31; the measured table is
   docs/mobile_sweep_unread_scope_establish_20260831.md)
   -------------------------------------------------------------------------
   ONE BLOCK RATHER THAN NINE EDITS SCATTERED THROUGH THIS FILE, because
   these are one finding stated nine times: a control a finger cannot
   reliably land on. The sweep measured every interactive control on
   every agent-reachable surface and these nine came back under **24 CSS
   px** in at least one dimension - the Level AA floor (WCAG 2.5.8 Target
   Size (Minimum)), which is the level this platform would actually be
   held to. Each is listed with the number the sweep read.

   WHY 24 AND NOT 44. 44 is Level AAA (WCAG 2.5.5), and on this platform
   the 24-44 band is not a set of oversights - it is the control metrics,
   on surfaces the owner has walked and approved. That band is TABLED and
   PUT TO THE OWNER in the establish document rather than changed here.
   These nine are below the floor nobody has to argue about.

   THE FIX IS THE HIT BOX, NOT THE TYPE. Every rule below sets a minimum
   and centres the existing content inside it; no font size, colour,
   weight or copy moves. `inline-flex` is what makes `min-height` apply
   to an anchor at all.

   AND `input.dz-input` AT 1x1 IS DELIBERATELY NOT HERE. The drop zone's
   visible surface is the target and that input is the accessible
   mechanism hidden behind it; raising it would put a file picker on top
   of the zone the agent is meant to tap. It is RULED in the establish
   document rather than exempted in the instrument, so the next 1x1
   control is still reported.
   ========================================================================= */
:root { --tap-aa: 24px; }

/* height 21.7 - "start a new quote". It reads as a link in a sentence,
   which WCAG's inline exception would forgive, but `.resume-banner` is a
   flex row and a flex container BLOCKIFIES its children - so this is a
   21.7px block that merely looks inline, and the exception does not
   apply to it. */
.resume-banner a { display: inline-flex; align-items: center;
  min-height: var(--tap-aa); }
/* height 23, and width 25.1 which is the AAA band - the banner dismiss */
.resume-banner .close { display: inline-flex; align-items: center;
  justify-content: center; min-height: var(--tap-aa);
  min-width: var(--tap-aa); }
/* height 16 - "Send your underwriter a message", on the quote hero */
.ap-hero-msg a { display: inline-flex; align-items: center;
  min-height: var(--tap-aa); }
/* height 17 - the board's sortable column headers. They are the whole
   sort control, and there are seven of them in one row. */
.board th.sortable button { min-height: var(--tap-aa); }
/* height 16 - "Continue ->" on a draft row of the dashboard */
.continue-link { display: inline-flex; align-items: center;
  min-height: var(--tap-aa); }
/* width 22.2 - the corner remove on an entity or location row. Its
   HEIGHT was already 28; only the narrow axis was under. */
.rep-row .del { min-width: var(--tap-aa); min-height: var(--tap-aa); }
/* 16 x 16 - the credit checkboxes on the rating step. The visual box
   stays 16px (`accent-color` draws it); the LABEL row is what grows, so
   the tap lands on the same control it always did. */
.credit-opt { min-height: var(--tap-aa); }
.credit-opt input { min-width: var(--tap-aa); min-height: var(--tap-aa);
  margin: 0; }
/* height 17 - "Edit" / "Change" on a review section head */
.review-head .edit, .qacc-q.rcpt .edit { display: inline-flex;
  align-items: center; min-height: var(--tap-aa); }
/* height 19.4 - "Fix ->" in the needs-attention panel */
.needs-attention li a { display: inline-flex; align-items: center;
  min-height: var(--tap-aa); }
/* height 19.4 - a document row's Download and Remove, on the bound page
   and every documents list (WC authority entry, 2026-09-24). Found when
   the sweep's bound account first carried an uploaded document - its
   loss runs, verified before the bind - so the rows had never been swept */
.doc-open, .doc-remove { min-height: var(--tap-aa); }

/* =========================================================================
   Loading skeletons
   ========================================================================= */
@keyframes shimmer { 0% { opacity: .55; } 50% { opacity: 1; } 100% { opacity: .55; } }
.skel { background: var(--neutral-tint); border-radius: 8px; animation: shimmer 1.4s ease-in-out infinite; }
.skel-onnavy { background: var(--on-navy-pill); border-radius: 8px; animation: shimmer 1.4s ease-in-out infinite; }

/* =========================================================================
   Responsive
   ========================================================================= */
@media (max-width: 760px) {
  :root { --fs-hero: 40px; }
  .content { padding: var(--sp-4) var(--sp-4) var(--sp-7); }
  /* THE HEADER TAKES THE PAGE'S OWN INSET (species C, owner mobile
     walkthrough 2026-08-31): "several screens sit slightly right of
     center at mobile width - small but consistent misalignment".

     ONE CAUSE EXPLAINED ALL SEVENTEEN, and it is this line. `.content`
     drops to `--sp-4` (16px) here and `.chrome-inner` kept its base
     `--sp-5` (24px), so at 375 the header's content ran 24..351 while
     the page's ran 16..359 - measured identically on every
     chrome-bearing surface, both boxes perfectly centred and centred on
     DIFFERENT WIDTHS, which is why a plain centring check finds nothing
     and the eye finds it immediately. The wordmark and the nav sat 8px
     inboard of every card beneath them.

     THE PAGE'S VALUE WINS RATHER THAN THE HEADER'S, because 16px is the
     one chosen FOR this width - it is what the same media query already
     gives the cards - and matching upward to 24 would take 16px of room
     away from every card on a phone to fix an alignment. */
  .chrome-inner { padding-left: var(--sp-4); padding-right: var(--sp-4); }
  .hero { padding: var(--sp-5); }
  .hero-top { flex-wrap: wrap; }
  .hero-meta { margin-left: 0; justify-content: flex-start; }
  .hero-actions .btn { flex: 1 1 auto; }
  /* A LONG HERO LABEL MAY TAKE A SECOND LINE ON A PHONE (standing rule 366,
     measured 2026-10-03): with every letter 3px wider "Download quote
     package" and "Get an updated quote" outgrew a 320 screen by 6-7px as
     one no-wrap line; the button is already full width here */
  .hero-actions .btn { white-space: normal; text-align: center; }
  .chrome-nav { display: none; }
  /* header: logo keeps row 1; the action pills wrap onto their own row
     instead of overflowing the viewport (mobile fix). The "logged in as"
     identity is dropped on phones (non-essential, conventional) to keep the
     header to two tidy rows. */
  .chrome-inner { flex-wrap: wrap; gap: var(--sp-3); }
  .chrome-center { flex-basis: 100%; order: 3; justify-content: flex-start; }
  .chrome-actions { margin-left: auto; flex-wrap: wrap; row-gap: var(--sp-2); }
  .chrome-user { display: none; }
  /* section head (e.g. Premium detail): let the per-state switcher drop below
     the heading rather than overflow on narrow screens */
  .section-head { flex-wrap: wrap; }
  .section-head > div[style*="margin-left"] { margin-left: 0 !important; }
}

/* =========================================================================
   POLICY FORMS - the shared status row (owner rulings R-C / R-D, 2026-08-08)
   =========================================================================
   Built to the committed design reference
   `docs/design/forms_workbench_mockup_v2_20260808_1.html` (sha256 915bc163).

   THIS LIVES IN THE SHARED LAYER ON PURPOSE. The reference draws the
   underwriter's `On file` ledger and the agent's `Policy forms` panel with
   the SAME row, and `admin/admin.css` imports this file - so one definition
   serves both surfaces and they cannot drift into two rows that merely look
   alike. What is NOT here is anything only one audience has: the review
   queue, the ribbon and the two cleared states are workbench-only and stay
   in admin.css.

   THE STATE MODIFIERS ARE PRESENTATION, NOT STATUS. `.fw-confirmed` is worn
   by an underwriter's `confirmed` AND by an agent's `received`, because
   ruling R-D collapses them at the boundary - and the class name is
   deliberately not the status name, so nobody can read a status back out of
   the DOM that the server declined to send.                              */

.fw-ledger { padding-top: 2px; }
.fw-row { display: flex; align-items: center; gap: 12px; padding: 12px 2px;
  border-bottom: 1px solid var(--border); }
.fw-row:last-child { border-bottom: 0; }
.fw-mark { width: 18px; height: 18px; border-radius: 50%; flex: none;
  display: grid; place-items: center; }
.fw-confirmed .fw-mark { background: var(--green); }
.fw-confirmed .fw-mark:after { content: ""; width: 5px; height: 9px;
  border: solid var(--card); border-width: 0 2px 2px 0;
  transform: rotate(43deg) translateY(-1px); }
.fw-waiting .fw-mark { border: 1.5px dashed var(--border-strong); }
/* OPTIONAL: THE QUIET TREATMENT (owner ruling 2026-08-28). A form nobody
   is waiting on wears the neutral chip this platform already uses for
   states that ask nothing of the reader - the same pair the Draft and
   Imported badges wear - and its mark is a SOLID hairline ring rather
   than the waiting row's dashed one, because a dashed ring reads as an
   empty box somebody has to fill. Never colour alone: the tag says
   "Optional" and the sub-line leads with the word. */
.fw-optional .fw-mark { border: 1.5px solid var(--border-strong); }
.fw-optional .fw-name { font-weight: var(--fw-medium); }
.fw-optional .fw-tag { color: var(--neutral-ink);
  background: var(--neutral-tint); }
.fw-na .fw-mark { background: var(--gray-light); }
.fw-main { flex: 1; min-width: 0; }
.fw-name { font-weight: var(--fw-semibold); font-size: 13.5px; }
.fw-na .fw-name { color: var(--gray); font-weight: 400; }
.fw-sub { font-size: var(--fs-label); color: var(--gray); margin-top: 1px; }
.fw-sub a { color: var(--navy); }
.fw-tag { font-size: 11px; font-weight: var(--fw-semibold);
  padding: 2px 9px; border-radius: 5px; white-space: nowrap; }
.fw-confirmed .fw-tag { color: var(--green-ink); background: var(--tint-green); }
.fw-waiting .fw-tag { color: var(--neutral-ink); background: var(--neutral-tint); }
.fw-na .fw-tag { color: var(--gray); background: var(--neutral-tint); }
.fw-act { flex: none; }

@media (max-width: 560px) {
  .fw-row { flex-wrap: wrap; }
  .fw-act { width: 100%; }
  .fw-act .btn { width: 100%; }
}

/* =========================================================================
   AGENT STATUS PAGES - bind_requested and referred (2026-08-20)
   =========================================================================
   ONE SKIN, TWO TRUTHS. The two references (bind_page_mockup_v12,
   referred_page_mockup_v6) are SIBLINGS: the same skeleton - hero, status
   waterfall, while-you-wait cross-sell, forms checklist, what-happens-next,
   locations - carrying different facts. So the vocabulary below is defined
   ONCE and both statuses wear it; a rule that applied to only one of them
   would be the seam where the two pages start drifting apart.

   TOKEN-ONLY, like every other block in this file (spec §6, and
   test_dashboard_account_names_r6 / test_dropzone_r3 pin the discipline).
   The references were drawn in their own palette - a different navy, a
   hand-picked gold - and NONE of those hexes are copied here. The
   references are the authority on LAYOUT AND BEHAVIOUR; this file stays the
   authority on colour, so the pages land in Normandy's brand rather than
   the mockup's. Four gold tokens are added at :root for the points block,
   because a gradient needs stops and the brand guide covers one amber.     */

/* ---- status waterfall: THE WHOLE FAMILY IS RETIRED ----------------------
   ITEM 1 (owner walkthrough 2026-08-27). `.wf-flow`, `.wf-steps`,
   `.wf-step` (with its is-now / is-todo states), `.wf-dot`, `.wf-lab`,
   `.wf-line`, `.wf-note`, `.wf-ico` and the `wf-pulse` keyframes dressed
   ONE component - the agent status pages' progress bar - and that
   component's last call site went with the bind page's bar. Established
   before deleting: exactly one file in the repo carried any of these
   class names (portal/screens/quote_result.html, in `apWaterfall()`
   alone), swept across every screen that links this stylesheet and both
   portal scripts. The admin console's `.wf-step`/`.wf-note` are a
   DIFFERENT vocabulary in `admin/admin.css` and that screen's own inline
   style block; those screens do not link this file.

   `.wf-why` below is NOT part of that family. It dresses the referred
   page's reasons list and only borrows the prefix - its own comment in
   quote_result.html says the name is slightly wrong and why copying the
   rules to a better-named class would be the drift this file spends its
   comments preventing. The premium table's `.wf` / `.wf-panel` above are
   a third, unrelated user of the two letters.                            */
/* the why-referred reasons, folded under the note as a compact line
   (owner ruling 5, 2026-08-20 - the panel is retired, the reasons are not;
   the note itself retired with the bar on 2026-08-27) */
.wf-why { margin: var(--sp-3) 0 0; padding: 0; list-style: none;
  font-size: var(--fs-small); color: var(--ink-soft); }
.wf-why li { padding: 3px 0 3px var(--sp-4); position: relative; }
.wf-why li:before { content: ""; position: absolute; left: 4px; top: 11px;
  width: 4px; height: 4px; border-radius: 50%; background: var(--amber); }
/* the .wf-rule chip is RETIRED (batch E item 2, 2026-08-22): entries no
   longer print the rule id - it was an internal identifier on an agent
   page, and the ruled entry format carries the question text alone. */

/* ---- section cards ---- */
/* THE CARD RHYTHM IS TWO-SIDED (owner walkthrough items 2 and 6,
   2026-08-30), AND UNTIL NOW IT WAS ONE.

   `.ap-sec` carried `margin-bottom` and nothing above it. Between two
   cards that is enough; against anything whose own bottom margin is ZERO
   it is nothing at all - and the owner found the hole from two different
   pages on the same afternoon. Measured at 1280px before the fix, there
   were THREE of them, not the two reported:

     referred   hero            -> Underwriting updates      0px
     referred   .msg-thread-sec -> Why it was referred        0px   (item 2)
     bind       hero            -> Send this form             0px   (item 6)

   The message/target-premium card wears `.section`, whose vocabulary is
   `margin-top: var(--sp-7)` and NO bottom margin; the hero has padding
   and no margin at all. Neither is wrong - they simply cannot supply a
   gap the card below them is not asking for.

   ONE CORRECTION COVERS BOTH PAGES, which is the question item 6 asked.
   They are one file and one card vocabulary, so a per-page gap would be
   two places to get this wrong rather than one.

   THE RHYTHM IS PRESERVED RATHER THAN REPLACED, because `.content` is
   ordinary block flow and adjacent sibling margins COLLAPSE:
   max(16,16)=16 between two cards - unchanged - max(0,16)=16 under the
   hero and under a `.section`, and max(16,40)=40 wherever the legacy
   `.section` rhythm still governs. Nothing that was already spaced moves. */
.ap-sec { background: var(--card); border-radius: var(--r-card);
  box-shadow: var(--shadow-card);
  margin-top: var(--sp-4); margin-bottom: var(--sp-4); overflow: hidden; }
.ap-sec-head { display: flex; align-items: center; gap: 11px;
  padding: var(--sp-3) var(--sp-5); border-bottom: 1px solid var(--border);
  flex-wrap: wrap; }
.ap-sec-ico { width: 32px; height: 32px; border-radius: var(--r-ctl);
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; flex: 0 0 auto; font-weight: var(--fw-hero);
  color: var(--on-navy); background: var(--navy); }
.ap-sec-ico.is-amber { background: var(--amber); color: var(--amber-ink); }
.ap-sec-ico.is-teal  { background: var(--blue); }
.ap-sec-head h2 { margin: 0; font-size: var(--fs-h2); font-weight: var(--fw-semibold); }
.ap-sec-head .ap-sub { font-size: var(--fs-small); color: var(--gray); margin-left: auto; }
.ap-sec-body { padding: var(--sp-3) var(--sp-5) var(--sp-4); }
/* a section's own button never outgrows the section (standing rule 366:
   "+ Add another location" ran to 336 in a 304 section at 320 on the
   cloud's fonts, gate 37136165972) - its words may take a second line */
.ap-sec-body .btn { max-width: 100%; white-space: normal; text-align: center; }

/* ---- underwriting updates (the notification surface, 2026-08-21) ----
   One row per durable notification on this submission, newest first. The
   date column collapses under its message on a narrow screen rather than
   squeezing the sentence into a gutter. */
.ap-upd { display: grid; gap: var(--sp-2); }
.ap-upd-row { display: flex; gap: var(--sp-3); align-items: baseline;
  font-size: 13.5px; }
.ap-upd-when { color: var(--gray); font-size: var(--fs-small);
  flex: 0 0 auto; min-width: 82px; }
.ap-upd-msg { color: var(--ink); }
.ap-upd-row:first-child .ap-upd-msg { font-weight: var(--fw-semibold); }
/* A VERDICT THAT NO LONGER APPLIES (owner walkthrough item 1, 2026-08-30).
   History stays visible and stops reading as the current word: the
   sentence dims and strikes, and the marker under it says what lifted it
   and when.

   THREE SIGNALS, NEVER COLOUR ALONE - the platform's standing rule. The
   strike carries it for a reader who cannot see the dim, and the marker
   is a WORD, which carries it for a reader who cannot see either.

   THE MARKER IS NOT STRUCK. It is the only live sentence in the row, and
   the strike is scoped to `.ap-upd-said` rather than the whole message
   cell for exactly that reason. The first row can never be superseded (a
   reopener would have to be newer than the newest entry), so this never
   argues with the bold rule above it. */
.ap-upd-row.is-superseded .ap-upd-said { color: var(--gray);
  text-decoration: line-through; }
.ap-upd-sup { display: block; margin-top: 2px; font-size: var(--fs-small);
  font-weight: var(--fw-semibold); color: var(--ink-soft); }
@media (max-width: 560px) {
  .ap-upd-row { flex-direction: column; gap: 1px; }
  .ap-upd-when { min-width: 0; }
}

/* ---- what happens next ---- */
.ap-next { display: grid; gap: var(--sp-3); }
.ap-next-row { display: flex; gap: var(--sp-3); align-items: flex-start; font-size: 13.5px; }
.ap-next-n { width: 22px; height: 22px; border-radius: 7px;
  background: var(--tint-blue); color: var(--navy); font-size: 12px;
  font-weight: var(--fw-hero); display: flex; align-items: center;
  justify-content: center; flex: 0 0 auto; margin-top: 1px; }
.ap-next-row b { font-weight: var(--fw-semibold); }
.ap-next-row .ap-m { color: var(--ink-soft); }

/* ---- locations ---------------------------------------------------------
   ADD-ANOTHER IS NOT ALWAYS THERE, and that is a ruling rather than a
   layout choice (owner ruling 4, 2026-08-20): edits are legal at referred
   and are not at bind_requested, so the button renders only where the API
   would accept it. A control that 403s is worse than no control.          */
.ap-loc { display: flex; align-items: center; gap: var(--sp-3);
  padding: 9px 0; font-size: 13.5px; }
.ap-loc + .ap-loc { border-top: 1px solid var(--border); }
.ap-loc-n { width: 22px; height: 22px; border-radius: 7px;
  background: var(--page); color: var(--ink-soft); font-size: 12px;
  font-weight: var(--fw-hero); display: flex; align-items: center;
  justify-content: center; flex: 0 0 auto; }
/* the add-location trigger wears the standard .btn btn-secondary since
   2026-08-26 (item 10) - its bespoke dashed full-width dress retired
   with the markup that wore it */
.ap-loc-hint { font-size: var(--fs-small); color: var(--gray); margin-top: var(--sp-2); }
.ap-loc-empty { font-size: 13.5px; color: var(--ink-soft); padding: 9px 0; }
/* the inline add-location form, revealed by the button above it. Its
   fields reuse the platform's .field vocabulary rather than restyling
   inputs, so a change to input styling reaches here too. */
.ap-loc-form { margin-top: var(--sp-3); padding: var(--sp-4);
  background: var(--page); border: 1px solid var(--border);
  border-radius: var(--r-ctl); }
.ap-loc-grid { display: grid; gap: var(--sp-3);
  grid-template-columns: 2fr 1fr 1fr; }
.ap-loc-actions { display: flex; gap: var(--sp-2); margin-top: var(--sp-3);
  flex-wrap: wrap; }
@media (max-width: 560px) {
  .ap-loc-grid { grid-template-columns: 1fr; }
  .ap-loc-actions .btn { flex: 1 1 auto; }
}

@media (max-width: 640px) {
  .ap-sec-head { padding: var(--sp-3) var(--sp-4); }
  .ap-sec-head .ap-sub { margin-left: 0; flex-basis: 100%; }
  .ap-sec-body { padding: var(--sp-3) var(--sp-4) var(--sp-4); }
}

/* ---- the hero, on both status pages ------------------------------------
   HONEST HEROES. Bind celebrates the REQUEST and says the points come WHEN
   BOUND; referred reassures and shows NO premium and NO points at all. The
   difference is entirely in what the caller passes - there is no
   `.ap-hero--bind` that quietly turns a fact on, because a modifier that
   reveals money is a modifier somebody puts on the wrong page.            */
.ap-hero-head { display: flex; flex-wrap: wrap; gap: var(--sp-4);
  align-items: flex-end; }
.ap-hero-head h1 { margin: 0; font-size: var(--fs-h1);
  font-weight: var(--fw-hero); letter-spacing: -.02em; }
/* THE CONFIRMATION HEADLINE, AND WHY IT NEEDED A MODIFIER AT ALL
   (bind-clarity item 1, owner walkthrough 2026-08-28).

   MEASURED BEFORE IT WAS CHANGED: on the bind-requested hero the headline
   was NOT the loudest thing in its own hero, and was not even the largest
   text in it. `.ap-hero-head h1` is 22px/750; `.ap-points .ap-p-num` is
   24px/800 in glowing gold. So an agent arriving on this page was drawn to
   a reward-points figure while the sentence telling them their request
   landed sat smaller and quieter beside it. A tester read the page and
   asked "is that it? did it go through?" - and the type scale is half the
   answer to why.

   IT IS A MODIFIER ON THIS ONE CALL, NOT A NEW DEFAULT for `.ap-hero-head`,
   for the reason `.is-stacked` records one rule up: the referred hero is
   the same skeleton carrying a different truth. "We are taking a closer
   look." is a reassurance and must not shout; this is a confirmation and
   must. A shared skeleton earns its keep by having the caller say which. */
.ap-hero-head h1.is-confirm { font-size: var(--fs-h1-hero);
  line-height: var(--lh-h1-hero); }
/* THE ARRIVAL (bind-clarity item 7, owner walkthrough 2026-08-28). One
   keyframe and one class, which is the budget the owner set for it.

   The headline rises a few pixels and fades in ONCE, when the agent lands
   on this page from the bind request - `landOnTheConfirmation` adds the
   class after the scroll, so nothing re-plays on the redraws this page
   does for other reasons. `both` holds the end state, so the headline does
   not snap back to a starting position after the animation finishes.

   NOT A CELEBRATION. The bind has been REQUESTED, not approved, and an
   animation that reads as confetti would be celebrating an event that has
   not happened. This draws the eye; it does not throw a party. */
@keyframes ap-confirm-in {
  from { opacity: 0; transform: translateY(9px); }
  to   { opacity: 1; transform: none; }
}
.ap-hero-head h1.is-confirm.is-arriving {
  animation: ap-confirm-in .42s cubic-bezier(.2, .7, .3, 1) both; }
/* REDUCED MOTION: the decoration goes, the headline stays. Beside the rule
   it disables rather than in the screen, for the reason the twinkles rule
   below is written the same way - a motion preference is a stylesheet
   concern, and honouring it in script means honouring it in every script. */
@media (prefers-reduced-motion: reduce) {
  .ap-hero-head h1.is-confirm.is-arriving { animation: none; }
}
.ap-hero-head .ap-hero-sub { font-size: var(--fs-small);
  color: var(--on-navy-soft); margin-top: 5px; }
/* the eyebrow and the status chip on one line (item 2e, 2026-08-21). The
   chip is the platform's own `.badge` in its on-navy variant, so nothing
   about its colour or shape is decided here - this rule only says the two
   sit beside each other and wrap rather than collide on a narrow screen. */
.ap-hero-eyebrow-row { display: flex; align-items: center; gap: var(--sp-3);
  flex-wrap: wrap; }
/* THE TWO COLUMNS NOW SAY HOW THEY SHARE THE WIDTH (item 4, owner
   walkthrough 2026-08-30), AND UNTIL NOW NEITHER DID.

   Both were `flex: 0 1 auto`, so each got a basis of its own max-content
   and shrank in PROPORTION to it. The title column's max-content is a
   34px headline and a long identification line, so it won - and the fact
   row on the other side wrapped to whatever was left. That cost nothing
   while the right column held three tiles; the moment item 4 moved two
   more into it the row wrapped FOUR deep and the hero got 103px TALLER,
   measured, which is the opposite of what the item asked for.

   SO THE BASES ARE DECLARED. The fact row is given enough to lay out in
   two lines and the title column gets the rest; both still grow and both
   still wrap onto their own lines on a narrow screen, exactly as before.
   `min-width: 0` is what lets the title column actually shrink to its
   share rather than being held open by its longest unbreakable line.

   IT IS ON THE SHARED SKELETON, DELIBERATELY. The referred hero divides
   the same way for the same reason, and a rule that applied to one page
   would be a second thing to keep in step. Referred's right column is two
   tiles and asks for less than its basis, so it simply hugs the right as
   it always has - measured, not assumed.

   AND THE RIGHT COLUMN'S BASIS RETIRES WITH THE ARRANGEMENT IT WAS
   DECLARED FOR (item 5b, owner walkthrough 2026-08-30, superseding the
   above by twelve hours). `flex: 0 1 440px` existed BECAUSE the fact row
   had moved into that column and was wrapping four deep inside it. The
   owner has now ruled the facts along the BOTTOM of the hero in one
   full-width row, so the column holds the points block alone - and a
   440px basis reserved for a block that asks for 180 would hold the
   title column open for nothing. It goes back to hugging its content.
   THE TITLE COLUMN'S DECLARATION STAYS: `flex: 1 1 380px; min-width: 0`
   is what lets it shrink to its share rather than being held open by its
   longest unbreakable line, and that is true of both heroes whatever the
   right column is carrying. */
.ap-hero-title { flex: 1 1 380px; min-width: 0; }
.ap-hero-right { margin-left: auto; display: flex; gap: var(--sp-3);
  align-items: flex-end; flex-wrap: wrap; flex: 0 1 auto; }
/* THE BIND HERO'S RIGHT COLUMN IS A STACK (item 3a, owner's marked
   screenshot, 2026-08-21): the rewards display in the open space right of
   the title row, the fact tiles beneath it. `stretch` plus
   `space-between` is what puts the two ends opposite the two ends of the
   title block, so the points sit level with the eyebrow and the tiles with
   the facts line - rather than both hanging off the bottom, which is where
   a bottom-aligned row left them.
   IT IS A MODIFIER ON THE BIND PAGE'S CALL, NOT A NEW DEFAULT. The referred
   hero keeps the plain row, because it has no points block to lift and two
   tiles that belong beside the headline. */
.ap-hero-right.is-stacked { flex-direction: column; align-items: flex-end;
  align-self: stretch; justify-content: space-between; flex-wrap: nowrap; }
/* THE FACT ROW RUNS ALONG THE BOTTOM OF THE HERO (item 5b, owner
   walkthrough 2026-08-30). It is a direct child of the hero now rather
   than of the right column, so it gets the hero's full width and reads
   left to right under the head - which is what pushed it out of
   `justify-content: flex-end`, a rule that only made sense while it was
   hanging off a right-hand column.
   IT HAS EXACTLY ONE USER, WHICH IS WHY THIS IS AN EDIT RATHER THAN A
   MODIFIER. The referred hero draws `apHeroChips` straight into
   `.ap-hero-right` and has never worn this class. A modifier for a
   difference that does not exist is a modifier somebody puts on the
   wrong page later.

   THE HEIGHT THIS ARRANGEMENT COSTS IS RULED, NOT AN OVERSIGHT (owner
   ruling 2026-08-30), AND IT IS WRITTEN HERE BECAUSE THIS IS THE RULE
   SOMEBODY WOULD EDIT TO "FIX" IT. Measured at 1280: the hero went
   441.5px -> 439.8px while its head went 279.2px -> 156.6px, because
   the chip row's 122.6px is spent on this row's own band (+91.3) and on
   the message link the same walkthrough asked for (+29.7).

     > "The goal was less busy, not fewer pixels; the measurement stands
     >  as the honest record."

   So a later entry that shortens the hero is answering a question
   nobody asked, and one that reads 1.7px as a failed optimisation is
   reading the wrong number.

   AND AT 375 THE FIVE TILES WRAP TO THREE LINES, costing 225.8px. That
   is BOOKED as a candidate for a future mobile pass and is not a defect
   (same ruling): there is no overflow, every tile is legible, and the
   ruled order survives the wrap. Five tiles at 20px figures cannot
   occupy one line at that width, so the choice a future pass makes -
   fewer tiles there, smaller tiles there, or three lines - is a ruling
   about what an agent needs on a phone rather than a CSS tidy-up. */
.ap-hf-row { display: flex; gap: var(--sp-3); flex-wrap: wrap;
  justify-content: flex-start; margin-top: var(--sp-5); }
.ap-hero-right.is-stacked .ap-points { align-self: flex-end; }
.ap-hf { background: var(--on-navy-pill); border: 1px solid var(--on-navy-border);
  border-radius: 12px; padding: var(--sp-2) var(--sp-4); text-align: right; }
.ap-hf-num { font-size: 20px; font-weight: var(--fw-hero); letter-spacing: -.02em; }
.ap-hf-num.is-money { color: var(--tint-green); }
.ap-hf-lab { font-size: 10.5px; color: var(--on-navy-soft);
  letter-spacing: .06em; text-transform: uppercase; margin-top: 2px; }
/* THE ONE-SENTENCE ANSWER UNDER THE CONFIRMATION HEADLINE (bind-clarity
   item 2, owner walkthrough 2026-08-28). Body size rather than the sub's
   small: it is the second thing an agent reads on this page and the first
   thing that tells them what happens next, so it must not sit at the size
   the platform uses for identification metadata. Full-strength on-navy for
   the same reason - `--on-navy-soft` is the colour of context, and this is
   the answer. Capped so a long line does not run the full hero width and
   turn a sentence into a paragraph. */
.ap-hero-say { margin-top: var(--sp-3); font-size: var(--fs-body);
  line-height: var(--lh-body); color: var(--on-navy); max-width: 52ch; }
/* `.ap-hf-row.ap-hero-status` IS RETIRED WITH ITS ONLY USER (item 4, owner
   walkthrough 2026-08-30). It existed to left-align the bind hero's two
   status chips in the LEFT column, because `.ap-hf-row` is written for the
   right column and pushes to flex-end. The chips have moved into that
   right-hand row, so the left alignment has nothing left to align and the
   rule goes with the markup that wore it - the same discipline that
   retired the waterfall family and `.ap-wait-acord`. Both heroes now draw
   ONE `.ap-hf-row` each and it needs no modifier. */
/* the hero pills, kept as a compact facts line (owner ruling 5) */
.ap-facts { display: flex; flex-wrap: wrap; gap: var(--sp-2);
  margin-top: var(--sp-3); }
/* item 3 (2026-08-26): the small send-a-message link under the referred
   hero's actions - a pointer at the Help-the-underwriter section, on
   navy, deliberately quieter than the buttons above it */
.ap-hero-msg { margin-top: var(--sp-2); }
.ap-hero-msg a { color: var(--on-navy-soft); font-size: var(--fs-small);
  text-decoration: underline; text-underline-offset: 3px; }
.ap-hero-msg a:hover { color: var(--on-navy); }

/* points: BARE GLOWING TEXT WITH TWINKLES, NO CONTAINER (ruled). It is
   deliberately not an `.ap-hf` tile - the tiles are facts about the policy,
   and the points are a promise about what happens on bind. */
.ap-points { position: relative; align-self: center; text-align: right;
  padding: 6px var(--sp-2); }
.ap-points .ap-p-num { font-size: 24px; font-weight: 800; letter-spacing: -.02em;
  background: linear-gradient(120deg, var(--gold-hi), var(--gold-lo));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  text-shadow: 0 0 22px var(--gold-glow); }
/* THE LABEL WRAPS TO TWO LINES (owner walkthrough item 3, 2026-08-30),
   AND THAT IS THE WHOLE OF THE MOVE HE ASKED FOR.

   MEASURED BEFORE IT WAS CHANGED, which is what turned the item from a
   placement into a wrap: the points block was ALREADY 32px in from the
   hero's top and 32px in from its right - exactly the hero's own
   `padding: var(--sp-6)`, so it was already in the corner. What stopped
   it reading as one was this label, 180px of unbroken sentence holding
   the whole right column open. A figure with a caption as wide as a
   headline is not a corner; it is a column.

   THE CAP IS ON THE LABEL, NOT ON THE BLOCK. `.ap-points` is a shrink-to-
   fit flex item, so capping the caption is what narrows the block, and
   the number is never at risk of being wrapped by a rule aimed at the
   words under it. The break lands after "earned", which keeps the noun
   phrase the owner ruled ("reward points earned") on one line and the
   condition on the other - the half of the label the 2026-08-21 ruling
   says must not drift.

   THE SPARKLES SURVIVE THE MOVE. They are absolutely positioned against
   `.ap-points`, so a narrower block carries them with it; nothing about
   the treatment is decided here. */
.ap-points .ap-p-lab { font-size: 12px; font-weight: var(--fw-semibold);
  color: var(--gold-label); display: block; margin-top: 1px;
  max-width: 20ch; }
.ap-points .ap-spark { position: absolute; color: var(--gold-spark);
  font-size: 12px; animation: ap-tw 2.6s ease-in-out infinite; }
.ap-points .ap-s1 { top: -4px; right: 2px; }
.ap-points .ap-s2 { bottom: 2px; left: -6px; animation-delay: 1.1s; }
.ap-points .ap-s3 { top: 6px; left: 26px; animation-delay: 1.8s; font-size: 9px; }
@keyframes ap-tw {
  0%, 100% { opacity: .3; transform: scale(.8); }
  50%      { opacity: 1;  transform: scale(1.2); }
}
/* REDUCED MOTION IS HONOURED. The twinkles are decorative and the reader
   loses nothing when they stop. (The waterfall pulse was the other half of
   this rule until 2026-08-27; it went with the bar it animated.) */
@media (prefers-reduced-motion: reduce) {
  .ap-points .ap-spark { animation: none; opacity: .75; }
}

/* ---- while you wait: the cross-sell, TWO DOORS AND ONLY TWO -------------
   Lines that quote online right now as buttons; everything else as one
   email sentence. No picker and no middle path - the reference is emphatic
   that a third option is what turns this from a next step into a menu.
   The card is deliberately COMPACT so the forms panel stays reachable
   without scrolling past a promotion.                                     */
.ap-wait { background: var(--card); border: 1px solid var(--border);
  border-left: 3px solid var(--blue); border-radius: var(--r-card);
  box-shadow: var(--shadow-card); margin-bottom: var(--sp-4);
  padding: 13px var(--sp-4); }
.ap-wait-head { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; }
.ap-wait-ico { width: 32px; height: 32px; border-radius: var(--r-ctl);
  background: var(--navy); display: flex; align-items: center;
  justify-content: center; flex: 0 0 auto; }
.ap-wait-head h2 { margin: 0; font-size: var(--fs-h2); font-weight: var(--fw-semibold); }
/* the one sentence that names the first door (item 3c, 2026-08-21) */
.ap-lines-lede { margin-top: var(--sp-2); font-size: var(--fs-small);
  color: var(--ink-soft); }
.ap-lines-lede b { color: var(--ink); }
.ap-lines { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-2); }
/* GREEN, BECAUSE ON THIS PLATFORM GREEN IS WHAT "YOU CAN DO THIS NOW"
   LOOKS LIKE (item 3c's own words, moved from the retired tag to the
   whole control - owner walkthrough 2026-08-26, item 2). The pairing is
   chosen by MEASUREMENT, not by matching .btn-primary: white on --green
   is 3.99:1, under AA's 4.5 for 13px text, while --green-ink on
   --tint-green is 5.86:1 and the hover's white on --green-hover is
   5.46:1 - every value an existing palette token, no new color. */
.ap-line-btn { border: 1.5px solid var(--green); background: var(--tint-green);
  border-radius: var(--r-pill); padding: var(--sp-2) 17px; font: inherit;
  font-size: 13px; font-weight: var(--fw-semibold); color: var(--green-ink);
  cursor: pointer; text-decoration: none; display: inline-block; }
.ap-line-btn:hover { background: var(--green-hover);
  border-color: var(--green-hover); color: var(--on-navy); }
/* NAMED FOR WHAT IT IS, AND RENAMED FOR A REASON (2026-08-20). The
   reference calls this "tier 2" - the second of the two doors. That name
   shipped as `.ap-tier2` and the TIER NON-DISCLOSURE SWEEP caught it
   immediately: it greps agent-facing screens for "tier", and it is
   deliberately blunt about it, because a sweep with an exception for
   "well, that tier means something else" is a sweep somebody talks their
   way past. The class is renamed rather than the sweep weakened. */
.ap-emaildoor { margin-top: var(--sp-2); font-size: var(--fs-small); color: var(--ink-soft); }
.ap-emaildoor b { color: var(--ink); }
.ap-emaildoor a { color: var(--navy); font-weight: var(--fw-semibold);
  text-decoration: none;
  /* an address breaks rather than push the page (standing rule 366: the
     brokerage address ran to 337 at 320 on the cloud's widest letters) */
  overflow-wrap: anywhere; }
/* THE `.ap-wait-acord` RULE IS RETIRED WITH ITS ONLY USER (owner
   walkthrough item 2a, 2026-08-21): the cross-sell card no longer carries
   the ACORD slot, because the hero on both status pages serves the same
   download one screenful above it. A CSS family whose only user is gone is
   dead weight the next editor reads as live. */

/* ---- the forms panel, status-first --------------------------------------
   GREEN CHECK RECEIVED, AMBER EXCLAMATION NEEDED, and the ring is the first
   thing in the row because "what do I still owe you" is the only question
   this panel is asked. The two ring states are the ONLY two: the server has
   already collapsed the internal review status (ruling R-D, 2026-08-08), so
   there is no third ring to render and no way to leak one.                */
.ap-doc { display: flex; align-items: center; gap: 13px; padding: 11px 0; }
.ap-doc + .ap-doc { border-top: 1px solid var(--border); }
.ap-doc-ico { width: 34px; height: 34px; border-radius: 50%; display: flex;
  align-items: center; justify-content: center; font-size: 14px;
  font-weight: var(--fw-hero); flex: 0 0 auto; }
.ap-doc-ico.is-got  { background: var(--tint-green); color: var(--green-ink);
  border: 1.5px solid var(--green); }
.ap-doc-ico.is-need { background: var(--amber-tint); color: var(--amber-ink);
  border: 1.5px solid var(--amber); }
.ap-doc-main { flex: 1 1 auto; min-width: 0; font-weight: var(--fw-medium); }
.ap-doc-meta { font-size: 12px; color: var(--gray); font-weight: 400; }
/* THE REPLACE SENTENCE (item 2, 2026-08-31). Quieter than the meta
   line above it and wrapping freely, because it is a full sentence
   under a row that is otherwise three words wide - and at 375 it has
   to wrap to three lines without pushing the door off the row, which
   the `.ap-doc { flex-wrap: wrap }` rule below already arranges. */
.ap-doc-note { font-size: 12px; color: var(--gray); font-weight: 400;
  margin-top: 3px; line-height: 1.45; max-width: 54ch; }
.ap-doc-act { display: flex; gap: var(--sp-2); align-items: center; flex: 0 0 auto; }
.ap-mini { border: 1px solid var(--border); background: var(--card);
  border-radius: var(--r-pill); font: inherit; font-size: 12px;
  font-weight: var(--fw-semibold); color: var(--ink-soft);
  padding: 6px var(--sp-3); cursor: pointer; }
.ap-mini:hover { border-color: var(--blue); color: var(--blue); }
.ap-mini.is-primary { border-color: var(--navy); color: var(--navy); }
/* THE ROW'S OWN UPLOAD DOOR (walkthrough defect 1, 2026-08-21). The shared
   combined zone and its which-form ask are gone from both status pages; this
   is what stands where they stood. It is `DropZone`'s row-button shape, so
   the control the agent clicks is a LABEL rather than a button - a file
   input needs one - and it wears `.ap-mini.is-primary` so it reads exactly
   as the button it replaces.
   THE FEEDBACK STACKS UNDER IT rather than beside it: a progress row and an
   error line are short-lived, and an action cell that reserves room for them
   would be a cell with a permanent gap in it. `:empty` keeps the gap out of
   the row until there is something to say. */
.doc-upload-row { display: inline-flex; flex-direction: column;
  align-items: stretch; gap: 5px; min-width: 0; max-width: 260px; }
.doc-upload-row .dz-browse { display: inline-block; text-align: center; }
.doc-upload-row .dz-files:empty, .doc-upload-row .doc-msg:empty {
  display: none; }
.doc-upload-row .dz-file { margin-top: 0; }
.doc-upload-row .doc-msg { font-size: 12px; }
/* `.ap-forms-foot`, `.ap-allin` and `.ap-doc-ico.is-optional` RETIRED with
   the status-first panel (agent bind page polish item 1, 2026-09-24): the
   forms card draws its own count, bar, rows and one green line. */

@media (max-width: 640px) {
  /* The confirmation headline steps back to 28px at phone widths - still
     comfortably the loudest thing on the page (the points figure is 24px
     and does not scale), and 34px on a 375 viewport spends three lines
     saying four words. */
  .ap-hero-head h1.is-confirm { font-size: 28px; }
  .ap-hero-right { margin-left: 0; width: 100%; }
  /* the stack unwinds to the left edge with everything else (item 3a): at
     this width there is no "open space right of the title row" to move
     into, so the points lead the block rather than float off it */
  .ap-hero-right.is-stacked { align-items: flex-start; align-self: auto;
    flex-wrap: wrap; }
  .ap-hero-right.is-stacked .ap-points { align-self: flex-start; }
  /* `.ap-hf-row { justify-content: flex-start }` RETIRED FROM HERE (item
     5b, 2026-08-30): the row is the hero's own full-width band now and
     starts at the left at EVERY width, so an override that only unwound
     the right column's push at 640 has nothing left to unwind. The rule
     it duplicated is the base rule. */
  .ap-points { align-self: flex-start; text-align: left; }
  .ap-doc { flex-wrap: wrap; }
  .ap-doc-act { width: 100%; }
  .ap-doc-act .ap-mini { flex: 1 1 auto; }
  /* the row door stretches with its siblings (defect 1, 2026-08-21) */
  .ap-doc-act .doc-upload-row { flex: 1 1 auto; max-width: none; }
  .ap-line-btn { flex: 1 1 auto; text-align: center; }
}

/* the mis-filing picker: the one place a shared-zone upload says which
   form it answers (2026-08-20). It sits between the rows and the zone
   because that is the order the question is asked in - here is what is
   outstanding, which of them is this, now send it. */
.ap-formpick { display: flex; align-items: center; gap: var(--sp-3);
  margin-top: var(--sp-3); flex-wrap: wrap; }
.ap-formpick-lab { font-size: var(--fs-small); font-weight: var(--fw-semibold);
  color: var(--ink); }
.ap-formpick select { font: inherit; font-size: 13px; padding: 7px var(--sp-3);
  border: 1px solid var(--border-strong); border-radius: var(--r-ctl);
  background: var(--card); color: var(--ink); max-width: 100%; flex: 1 1 260px; }
.ap-formpick select:focus { outline: 2px solid var(--focus-ring);
  border-color: var(--blue); }
@media (max-width: 560px) {
  .ap-formpick { flex-direction: column; align-items: stretch; gap: var(--sp-2); }
}
/* the send-a-document family (.ap-senddoc / .sd-panel / .sd-door) is
   RETIRED (upload v3, batch E item 1, 2026-08-22): the owner reversed
   the fifty-ninth entry's button-and-reveal, and the drop-flow ask
   (.dz-ask, beside the zone family above) is its successor. */

/* ==========================================================================
   COMBINED UPLOAD, AUTO-SPLIT (owner design, 2026-08-28) - the zone above
   the form rows and the split preview it opens.

   THE SHAPE IS STACKED AND IT IS STACKED ON PURPOSE. The one layout defect
   the owner has photographed twice on this panel was the split zone's two
   flex columns, which stacked only under 640px and left each column about
   300px for a dropdown, a button, a hint and a drop target at 768. Nothing
   here is ever a column pair: the head, the zone and the preview stack at
   every width, and each preview row is a page label over its select.

   EVERY PART OF IT WRAPS RATHER THAN SCROLLS. A file name is somebody's
   scanner output and can be 200 characters (`overflow-wrap: anywhere`); a
   form label is served from config and is not length-bounded; a select's
   `max-width: 100%` is what keeps a long option from widening the page.
   The panel must not produce horizontal overflow at 375, which is what
   the responsive proof measures.
   ========================================================================== */
/* THE SEPARATOR FOLLOWED THE ZONE (item 5, owner walkthrough 2026-08-30).
   The rule was on the BOTTOM because the zone was a header block sitting
   over the checklist. The owner has ruled the rows first and the zone
   after them, so the same one rule moves to the TOP - it is the line
   between the checklist and the shortcut either way, and leaving it below
   would have put the zone flush against the last form row with a stray
   line under it.

   AND THE SEPARATOR IS ALL IT WAS (item 4, owner ruling 2026-08-30). A
   headline feature was rendering as a hairline rule and one semibold line
   of body text, sitting directly under form rows whose own labels are
   14px/500 - about half a step of contrast between the shortcut and the
   list it shortcuts. The owner's words are "subtle-but-found, not loud",
   so the change is a block treatment rather than a colour shout:

     * A LEFT ACCENT RULE IN `--blue`, which is the platform's
       interactive accent and the family `.msg-summary` and the
       `.off-chip-info` callout already speak in. Blue is the honest
       family here: this is an OFFER, and amber is reserved for "somebody
       is waiting on you" (the form rows' own need glyph, one line up) -
       an accent that borrowed amber would make the shortcut look like an
       outstanding item.
     * A TINT, NOT A FILL. `--page` is the platform's own ground rather
       than a new colour, so the block reads as a raised panel inside the
       card instead of a coloured banner. `--tint-blue` at block size was
       measured against this and is the "loud" the ruling excludes.
     * THE HEADING GOES UP ONE STEP AND NO MORE - `--fs-h2` at
       `--fw-hero`, against the rows' 14px/500. It is the largest text in
       the panel body, which is what "noticeable" means here, and it is
       still well under the section's own `<h2>` above it, so the panel
       still reads as one thing with a heading rather than two sections.

   THE ROWS ARE NOT TOUCHED. The ruling says "without competing with the
   forms rows above it", and the way to lose that competition is to leave
   the rows exactly as they are: every number that moved is on the zone. */
.ap-cu { margin: var(--sp-4) 0 0; padding: var(--sp-4);
  border-top: 1px solid var(--border);
  border-left: 3px solid var(--blue);
  border-radius: 0 var(--r-ctl) var(--r-ctl) 0;
  background: var(--page); }
.ap-cu-head { margin-bottom: var(--sp-3); }
.ap-cu-title { font-size: var(--fs-h2); line-height: var(--lh-h2);
  font-weight: var(--fw-hero); color: var(--ink); letter-spacing: -.01em; }
.ap-cu-sub { font-size: var(--fs-small); color: var(--ink-soft);
  margin-top: 3px; }

.ap-split { margin-top: var(--sp-3); padding: var(--sp-3);
  border: 1px solid var(--border); border-radius: var(--r-ctl);
  background: var(--card); }
.ap-split-head { font-weight: var(--fw-semibold); color: var(--ink); }
.ap-split-file { font-size: var(--fs-small); color: var(--ink-soft);
  margin-top: 2px; overflow-wrap: anywhere; }
.ap-split-file:empty { display: none; }
.ap-split-lede { font-size: var(--fs-small); color: var(--ink-soft);
  margin: var(--sp-2) 0 0; }
/* THE FLOOR NOTICES (owner ruling, 2026-08-28) - GUIDANCE, NOT AN ERROR.
   A scan that carries no text and a Word file that files whole are both
   perfectly ordinary things to send, so neither wears the red `.error`
   treatment a refusal uses. Same quiet card as the ask panel. */
.ap-split-note { margin-top: var(--sp-2); padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--border); border-radius: var(--r-ctl);
  background: var(--surface, var(--card)); font-size: var(--fs-small);
  color: var(--ink); }
.ap-split-note[hidden] { display: none; }
.ap-split-rows { margin-top: var(--sp-2); }
.ap-split-row { display: flex; align-items: center; gap: var(--sp-3);
  flex-wrap: wrap; padding: var(--sp-2) 0; }
.ap-split-row + .ap-split-row { border-top: 1px solid var(--border); }
.ap-split-pages { font-size: 13px; font-weight: var(--fw-semibold);
  color: var(--ink); flex: 0 0 auto; min-width: 108px;
  overflow-wrap: anywhere; }
/* the picker inherits .ap-formpick's control styling and drops its top
   margin: inside a row it is a cell, not a question under a panel */
.ap-split-pick { margin-top: 0; flex: 1 1 260px; min-width: 0; }
.ap-split-actions { display: flex; gap: var(--sp-2); margin-top: var(--sp-3);
  flex-wrap: wrap; }
@media (max-width: 560px) {
  /* the page label sits ABOVE its control rather than beside it - two
     columns at 375 is the squeeze this design refuses */
  .ap-split-row { flex-direction: column; align-items: stretch;
    gap: var(--sp-2); }
  .ap-split-pages { min-width: 0; }
  .ap-split-actions .btn { flex: 1 1 auto; text-align: center; }
}

/* ==========================================================================
   THE QUESTIONS ACCORDION (batch G item 1, 2026-08-23). Design authority:
   questions_layout_mockup_v8b (landing) / v8 (mid-flight), 2026-08-22,
   verified hashes 7c966342 / 528d447f; taxonomy owner-approved 2026-08-23.
   Geometry follows the reference; family colors ride the brand tokens
   (reference accent -> --blue, greens -> --green family, navy -> --navy).
   ========================================================================== */

/* progress is the unlabeled sliver only - it fills, it never counts */
.qacc-sliver { height: 4px; border-radius: 2px; background: var(--border);
  margin: 2px 0 20px; overflow: hidden; }
.qacc-sliver i { display: block; height: 100%; border-radius: 2px;
  background: linear-gradient(90deg, var(--blue),
    color-mix(in srgb, var(--blue), var(--card) 30%)); transition: width .25s ease; }

/* closed group bars: slim, NAMES ONLY - no question counts anywhere */
.qacc-bar { display: flex; align-items: center; gap: 10px;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 12px; padding: 12px 18px; margin-bottom: 8px;
  cursor: pointer; }
.qacc-bar:hover { border-color: var(--blue); }
.qacc-bar:focus-visible { outline: 2px solid var(--focus-ring); }
.qacc-bar.todo { border-style: dashed; }
.qacc-bar .nm { font-size: 13.5px; font-weight: 700; }
.qacc-bar .tick { width: 19px; height: 19px; border-radius: 50%;
  background: var(--tint-green); color: var(--green-ink); flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800; }
.qacc-bar .sum { font-size: 12px; color: var(--gray); }
.qacc-bar .hint-edit { margin-left: auto; font-size: 12px; color: var(--gray); }
.qacc-bar .next-chip { margin-left: auto; font-size: 11px; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase; color: var(--blue);
  background: var(--tint-blue); border-radius: 999px; padding: 4px 12px; }

/* the bare GREEN triangle (v8): 19px, its only motion a 2px downward
   nudge on hover; the open header carries the upward twin */
.qacc-bar .chev, .qacc-open .chev { margin-left: 0; color: var(--green);
  font-size: 19px; line-height: 1; flex: 0 0 auto;
  transition: transform .15s ease; }
.qacc-bar .next-chip + .chev, .qacc-bar .hint-edit + .chev { margin-left: 0; }
.qacc-bar .nm + .chev { margin-left: auto; }
.qacc-bar:hover .chev { transform: translateY(2px); }

/* the ONE open group */
.qacc-open { background: var(--card); border: 1.5px solid var(--blue);
  border-radius: 14px; box-shadow: var(--shadow-1, 0 1px 3px rgba(12,28,51,.07),
  0 8px 22px rgba(12,28,51,.07)); margin-bottom: 8px; overflow: hidden; }
.qacc-open .gh { display: flex; align-items: center; gap: 10px;
  padding: 13px 18px; border-bottom: 1px solid var(--border); }
.qacc-open .gh h2 { margin: 0; font-size: 14.5px; font-weight: 700; }
.qacc-open .gh .where { margin-left: auto; margin-right: 10px;
  font-size: 11px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--blue); font-weight: 700; }

/* live question rows */
.qacc-q { display: flex; align-items: center; gap: 16px; padding: 12px 18px;
  border-bottom: 1px solid var(--page); }
.qacc-q:last-child { border-bottom: 0; }
.qacc-q .q-txt { flex: 1; font-size: 13.5px; }
.qacc-q.nested .q-txt { margin-left: 26px; border-left: 3px solid var(--blue-pale);
  padding-left: 14px; }

/* the two sleek pills: hairline border, 1px hover lift, gradient selected
   state (Yes navy, No green), no check mark */
.qacc-seg { display: flex; gap: 10px; flex: 0 0 auto; }
.qacc-seg button { border: 1px solid var(--border); background: var(--card);
  font: inherit; font-size: 13px; font-weight: 600; letter-spacing: .01em;
  color: var(--ink-soft); border-radius: 999px; padding: 9px 26px;
  cursor: pointer; transition: all .15s ease;
  box-shadow: 0 1px 2px rgba(12,28,51,.04); }
.qacc-seg button:hover { color: var(--ink); border-color: var(--border-strong);
  transform: translateY(-1px); box-shadow: 0 3px 8px rgba(12,28,51,.10); }
.qacc-seg button.on { transform: none; }
.qacc-seg button.yes.on { background: linear-gradient(135deg, var(--navy),
    color-mix(in srgb, var(--navy), var(--card) 22%)); border-color: transparent;
  color: var(--card); box-shadow: 0 3px 10px rgba(33,62,124,.28); }
.qacc-seg button.no.on { background: linear-gradient(135deg, var(--green),
    color-mix(in srgb, var(--green), var(--card) 20%)); border-color: transparent;
  color: var(--card); box-shadow: 0 3px 10px rgba(0,147,71,.28); }

/* answered rows compress IN PLACE to thin receipts */
.qacc-q.rcpt { padding: 7px 18px;
  background: color-mix(in srgb, var(--card), var(--page) 55%); }
.qacc-q.rcpt .q-txt { font-size: 12px; color: var(--gray);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.qacc-q.rcpt .tick { width: 16px; height: 16px; border-radius: 50%;
  background: var(--tint-green); color: var(--green-ink); flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 9.5px; font-weight: 800; }
.qacc-q.rcpt .ans { font-size: 12px; font-weight: 700; flex: 0 0 auto; }
.qacc-q.rcpt .edit { font-size: 11px; color: var(--blue); font-weight: 650;
  text-decoration: none; flex: 0 0 auto; }

/* 375px: rows stack so the pills never squeeze the question text */
@media (max-width: 560px) {
  .qacc-q { flex-direction: column; align-items: stretch; gap: 10px; }
  .qacc-q.rcpt { flex-direction: row; align-items: center; }
  .qacc-seg { justify-content: flex-end; }
}


/* =========================================================================
   STAFF CHROME (moved here from admin/admin.css, owner ruling 2026-08-24)
   =========================================================================
   IT LIVES HERE BECAUSE IT IS PLATFORM CHROME RATHER THAN CONSOLE
   VOCABULARY. It sat in `admin.css` because the only screens that had ever
   worn it were console screens - but `admin.css` is the ADMIN component
   vocabulary, and an agent-floor screen opened by an underwriter is still a
   staff person looking at a nav bar. A screen cannot link `admin.css` to
   get a header without also taking the console's board, drawer and hero
   classes, which is why this had to move rather than be imported.

   `admin.css` still @imports this file, so every console screen sees these
   rules exactly as before - the move is invisible to them by construction.

   EVERY RULE IS SCOPED TO `.chrome-staff`, AND TWO OF THEM WERE NOT BEFORE.
   theme.css is shared with the agent portal, so an unscoped rule here is a
   rule on an agent surface. Asking of each one "does an agent screen's DOM
   contain anything this would newly match?" found exactly two that did:
   the current-page pill (session.js sets `aria-current` on an agent's nav
   too) and `button.pill-link` (the Sign out control is a button on every
   screen). Both are scoped below. The rest match nothing without the
   marker - `.nav-count`, `.nav-group*`, `.idwrap`, `.idchip` and `.idpop`
   are classes only the staff chrome ever creates - so they moved verbatim,
   which is also what keeps their names stable for the parity tests in
   `test_workbench_chrome_20260820.py`.
   ========================================================================= */
/* ---------- admin chrome nav - outline pills; current page = navy outline
   (still outline, not filled - consistent with the owner ruling) ---------- */
.chrome-staff .chrome-nav .pill-link[aria-current="page"] {
  color: var(--navy); border-color: var(--navy);
}
/* YOUR DESK IS THE GREEN PILL (owner, batch F item 5, 2026-08-22): the
   underwriter's landing page stands apart from the blue link family in
   the platform's own success green - the Bound/Quoted family's tokens,
   nothing new mixed. Keyed on the href because the href IS the link's
   identity: no new class to thread through session.js's hydration or
   every screen's placeholder markup, and the pre-hydration placeholder
   is covered by the same rule. Still an outline pill (the owner ruling
   above); current page darkens within the family, exactly as the blue
   pills darken to navy. */
.chrome-nav .pill-link[href$="uw_queue.html"] {
  color: var(--green); border-color: var(--green);
}
.chrome-nav .pill-link[href$="uw_queue.html"]:hover {
  background: var(--tint-green); color: var(--green-hover);
  border-color: var(--green-hover);
}
.chrome-nav .pill-link[href$="uw_queue.html"][aria-current="page"] {
  color: var(--green-ink); border-color: var(--green-ink);
}
.chrome-nav .pill-link[href$="uw_queue.html"] .nav-count {
  background: var(--green);
}
/* THE BROKERAGE UNDERWRITER'S DESK (brokerage desk polish entry, ledger ruling
   372, 2026-10-01): its "Your Desk" is the Placements page and its WC desk
   pill reads "Normandy WC". The green follows the DESK, not the href:
   `/navigation` marks the two swapped links and these rules, after the href
   rules above, recolour exactly those two. Nobody else's nav carries a mark. */
.chrome-nav .pill-link[data-desk-swap="desk"] {
  color: var(--green); border-color: var(--green);
}
.chrome-nav .pill-link[data-desk-swap="desk"]:hover {
  background: var(--tint-green); color: var(--green-hover);
  border-color: var(--green-hover);
}
.chrome-nav .pill-link[data-desk-swap="desk"][aria-current="page"] {
  color: var(--green-ink); border-color: var(--green-ink);
}
.chrome-nav .pill-link[data-desk-swap="wc"] {
  color: var(--blue); border-color: var(--blue);
}
.chrome-nav .pill-link[data-desk-swap="wc"]:hover {
  background: var(--tint-blue); color: var(--blue-hover);
  border-color: var(--blue-hover);
}
.chrome-nav .pill-link[data-desk-swap="wc"][aria-current="page"] {
  color: var(--navy); border-color: var(--navy);
}
.chrome-nav .pill-link[data-desk-swap="wc"] .nav-count {
  background: var(--navy);
}
.nav-count {
  background: var(--navy); color: var(--on-navy);
  border-radius: var(--r-pill); padding: 1px 8px;
  font-size: var(--fs-label); font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
}

/* =========================================================================
   Staff chrome (staff chrome entry, 2026-08-23; sketch 9aa448cc)
   =========================================================================
   Staff screens mark their header `chrome chrome-staff` and get: the logo
   on its own row with the nav row beneath (the whole content width for the
   pills, which is what lets the row fit ONE LINE at 1280), grouped nav
   entries as a dropdown, the identity as an initials chip, and Sign out
   inline as the muted gray pill - exit, not navigation. Agent screens
   carry no marker and are untouched. Every color is a theme token. */
.chrome-staff .logo { flex: 1 0 100%; }
.chrome-staff .chrome-inner { padding-top: 12px; padding-bottom: 12px;
  row-gap: var(--sp-3); }
.chrome-staff .chrome-nav { margin-left: 0; }

/* the grouped-nav dropdown: a pill trigger, a card menu */
.nav-group { position: relative; }
.chrome-staff button.pill-link { font-family: inherit; cursor: pointer; }
.nav-group-trigger .caret { font-size: 10px; line-height: 1; }
.nav-group.open > .nav-group-trigger,
.nav-group-trigger[data-current="true"] {
  color: var(--navy); border-color: var(--navy);
}
.nav-group-menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 60;
  min-width: 200px; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--r-ctl);
  box-shadow: var(--shadow-pop); padding: 6px; display: none;
}
.nav-group.open > .nav-group-menu { display: block; }
.nav-group-item {
  display: block; padding: 8px 12px; border-radius: 8px;
  color: var(--ink); font-size: var(--fs-small);
  font-weight: var(--fw-medium);
}
.nav-group-item:hover { background: var(--tint-blue); color: var(--navy);
  text-decoration: none; }
.nav-group-item[aria-current="page"] { background: var(--tint-blue);
  color: var(--navy); font-weight: var(--fw-semibold); }

/* the account avatar and its menu (workbench v3, item 1) */
.idwrap { position: relative; display: inline-flex; }
.idchip {
  width: 40px; height: 40px; border-radius: 50%; border: 0; padding: 0;
  background: var(--av-navy); color: var(--on-navy);
  display: inline-flex; align-items: center; justify-content: center;
  font-family: inherit; font-size: 14px; letter-spacing: .03em;
  font-weight: 700; cursor: pointer; flex: 0 0 auto;
  box-shadow: 0 0 0 2px var(--card), 0 0 0 4px var(--gold);
}
.av-c0 { background: var(--av-navy); }
.av-c1 { background: var(--av-royal); }
.av-c2 { background: var(--av-teal); }
.av-c3 { background: var(--av-green); }
.av-c4 { background: var(--av-violet); }
.av { display: grid; place-items: center; width: 38px; height: 38px;
  border-radius: 50%; color: var(--on-navy); font-size: 13px; font-weight: 700;
  letter-spacing: .03em; flex: none; }
.av-lg { width: 46px; height: 46px; font-size: 16px; }
.idpop {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 60;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 18px; box-shadow: var(--shadow-pop);
  padding: 8px; font-size: 13px; color: var(--ink-soft);
  width: min(280px, calc(100vw - 32px)); text-align: left;
  display: flex; flex-direction: column;
}
.idpop[hidden] { display: none; }
.idpop-who { display: flex; align-items: center; gap: 12px;
  padding: 10px 10px 14px; margin-bottom: 6px;
  border-bottom: 1px solid var(--border); }
.idpop-words { display: flex; flex-direction: column; min-width: 0;
  overflow-wrap: anywhere; }
.idpop b { display: block; color: var(--ink); font-size: 15px;
  font-weight: var(--fw-semibold); }
.idmi { display: flex; align-items: center; width: 100%; min-height: 44px;
  padding: 8px 12px; border: 0; border-radius: 10px; background: none;
  color: var(--ink); font-family: inherit; font-size: 14px; font-weight: 500;
  text-align: left; text-decoration: none; cursor: pointer; }
.idmi:hover { background: var(--neutral-tint); color: var(--ink);
  text-decoration: none; }
.idmi-out { color: var(--red-ink); }
.idmi-out:hover { background: var(--red-tint); color: var(--red-ink); }
.idfeed { display: flex; flex-direction: column; gap: 2px; padding: 4px 12px 8px;
  max-height: 240px; overflow-y: auto; font-size: 13px; }
.idfeed[hidden] { display: none; }
.idfeed-row { padding: 6px 0; color: var(--ink-soft); overflow-wrap: anywhere; }
@media (pointer: coarse) {
  .idpop { gap: 8px; }
}


/* ==========================================================================
   TOUCH TARGETS: THE RULED SET AT 44px (Species F, owner ruling 2026-09-08)

   BOOKED ON 2026-08-31 AS ITS OWN ENTRY, with the mobile sweep's Species F
   table as its establish - 398 findings across 30 controls in the 24-to-44px
   band, every one of them ABOVE Level AA (24px, WCAG 2.5.8) and below Level
   AAA (44px, WCAG 2.5.5). The booking's whole point was that this is a
   DESIGN DECISION, not a defect fix, and the owner took it with the table in
   front of him.

   THE RULING IS A SUBSET, AND THE SUBSET IS THE INTERESTING PART. The agent
   flow's PRIMARY touch controls go to 44: the rail steps, the header pills,
   the choice and plan buttons, and the bind/quote buttons. The wordmark,
   sign out, the banner dismiss and the filter widgets STAY AT THE AA FLOOR -
   they are not what a finger reaches for while filling in a quote, and
   growing the header on every page to make Sign out 44px tall would trade a
   real cost for a target nobody hunts.

   AT 375 AND 768, AND 1280 IS VISUALLY UNCHANGED, which is why this is a
   MEDIA BLOCK and not seven edits to seven rules. WCAG 2.5.5 is about
   TOUCH; the desktop layout has a pointer, and the ruling pins 1280 as it
   stands. 900px is the theme's existing layout breakpoint (the chrome
   already wraps there), so the floor rides a boundary the design already
   has rather than inventing an eighth one.

   WHAT IS DELIBERATELY NOT HERE:
     * the `.field` text-entry family, which lands at 43.7 and misses 44 by
       ROUNDING. The ruling skips rounding-invisible cases by name, and
       0.3px of growth on every input on the platform is churn with nothing
       to show for it.
     * `#sign-out`, below, which carries `.pill-link` and is named OUT.
     * `.btn` / `.btn-sm` (New quote, the second-look send, both 41.7),
       which this ruling named in neither list - RULED IN 2026-09-26
       (walkthrough follow-on item 11): their floor is the block at the
       END of this file, so it wins over the later per-component rules
       (`.fc-btn` above sets its own 36px).
   ========================================================================== */
@media (max-width: 900px) {
  /* the flow's seven steps (42 -> 44) */
  .rail-step { min-height: 44px; }

  /* the header pills: Dashboard, Rewards, Quote Other Lines, Manage
     Policies (33.4 -> 44). The filled variant is the same control with a
     different fill, so it takes the floor from the same rule. */
  .pill-link { min-height: 44px; }
  /* SIGN OUT IS NAMED OUT OF THE RULED SET and it is a `.pill-link`, which
     is the one collision the ruling contains. It keeps its own metric
     HERE rather than the rule being narrowed to `a.pill-link` - which
     would have silently dropped the `.pill-link-filled` BUTTONS that are
     in. It stays above the AA floor it already cleared. */
  #sign-out.pill-link { min-height: 0; }

  /* the segmented Yes/No pairs (40.1 -> 44) and the question accordion's
     own pair, which is the same control on a different screen */
  .choice button { min-height: 44px; }
  .qacc-seg button { min-height: 44px; }

  /* the state premium chips (31.4 -> 44) */
  .switcher button { min-height: 44px; }

  /* Select for binding / Add to quote (40 -> 44) */
  .pbtn { min-height: 44px; }
}

/* =========================================================================
   THE AGENT'S INBOX (agent inbox entry item 1, owner ruling 2026-09-23)
   =========================================================================
   The envelope in the agent's action row carries the unread count (moved
   off the Dashboard pill, which the phones rule hides) and opens a drawer
   from the right; at phone widths the drawer is a full-screen sheet. The
   slide is a transform TRANSITION, so the global reduced-motion rule at
   the top of this file removes it and the drawer is simply there. */
.inbox-btn { gap: 6px; padding: 6px 12px; cursor: pointer; font: inherit;
  font-size: var(--fs-small); font-weight: var(--fw-semibold); }
.inbox-btn .inbox-ico { display: block; flex: none; }
.inbox-btn.has-unread { background: var(--tint-blue); }
.inbox-btn .nav-count { background: var(--blue); color: var(--on-color); }
.inbox-scrim { position: fixed; inset: 0; z-index: 900;
  background: rgba(20, 28, 48, .32); opacity: 0; transition: opacity .2s ease; }
.inbox-scrim.is-open { opacity: 1; }
.inbox-drawer { position: fixed; top: 0; right: 0; bottom: 0; z-index: 910;
  width: min(420px, 100vw); display: flex; flex-direction: column;
  background: var(--card); box-shadow: var(--shadow-pop);
  transform: translateX(100%); transition: transform .22s ease; }
.inbox-drawer.is-open { transform: none; }
/* CLOSED IS GONE: the `display: flex` above outranks the `hidden`
   attribute's own rule, which left a closed drawer in the layout off to
   the right - out of sight and still in the tab order. */
.inbox-drawer[hidden], .inbox-scrim[hidden] { display: none; }
html.inbox-open, html.inbox-open body { overflow: hidden; }
.inbox-head { display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5); border-bottom: 1px solid var(--border); }
.inbox-head h2 { font-size: var(--fs-h3, 18px); font-weight: var(--fw-semibold);
  color: var(--ink); }
.inbox-close { margin-left: auto; min-width: 44px; min-height: 44px;
  border: 0; background: transparent; color: var(--ink-soft); cursor: pointer;
  font-size: 26px; line-height: 1; border-radius: var(--r-pill); }
.inbox-close:hover { background: var(--neutral-tint); color: var(--ink); }
.inbox-body { flex: 1 1 auto; overflow-y: auto; min-height: 0; }
.inbox-status { margin: 0; padding: var(--sp-5); color: var(--ink-soft);
  font-size: var(--fs-body); text-align: center; }
.inbox-list { list-style: none; margin: 0; padding: 0; }
.inbox-row { display: grid; grid-template-columns: 10px minmax(0, 1fr);
  gap: var(--sp-3); width: 100%; min-height: 44px; text-align: left;
  font: inherit; color: var(--ink); background: transparent; border: 0;
  border-bottom: 1px solid var(--border); padding: 14px var(--sp-5);
  cursor: pointer; }
.inbox-row:hover { background: var(--neutral-tint); }
.inbox-row:focus-visible { outline-offset: -3px; }
.inbox-dot { width: 10px; height: 10px; margin-top: 5px; border-radius: 50%; }
.inbox-row.is-unread .inbox-dot { background: var(--blue); }
.inbox-main { display: grid; gap: 3px; min-width: 0; }
.inbox-top { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.inbox-acct { font-weight: var(--fw-regular, 400); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.inbox-row.is-unread .inbox-acct { font-weight: var(--fw-semibold); }
.inbox-chip { flex: none; margin-left: auto; }
/* the entry's line pills (brokerage agent follow-ups, item 4, ruling 150;
   ruling 174's words): "WC · quoted · Normandy" - the result page's navy
   pills, small, on their own line under the name, wrapping pill by pill;
   each pill stays one piece. A row without pills (the brokerage off) is
   today's: the name, and the chip at the right. */
.inbox-top.has-pills { flex-wrap: wrap; row-gap: 3px; }
.inbox-lines { display: inline-flex; flex: none; gap: 4px; }
.inbox-top.has-pills .inbox-lines { flex: 1 1 100%; flex-wrap: wrap; min-width: 0; }
.inbox-lines .brk-line-code { display: inline-block; padding: 1px 6px; border-radius: 5px;
  background: var(--navy); color: var(--on-navy); min-width: 0; font-size: 10px; line-height: 1.4;
  white-space: nowrap; }
.inbox-meta { display: flex; gap: var(--sp-2); font-size: var(--fs-small);
  color: var(--ink-soft); min-width: 0; }
.inbox-who { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0; }
.inbox-when { margin-left: auto; flex: none; white-space: nowrap; }
.inbox-line { display: flex; align-items: center; gap: 6px; min-width: 0;
  font-size: var(--fs-small); color: var(--ink-soft); }
.inbox-row.is-unread .inbox-line { color: var(--ink); }
.inbox-att { flex: none; color: var(--ink-soft); }
.inbox-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0; }
.inbox-sr { position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; }
/* THE AGENT'S NOTICES IN THE DRAWER (agent surfaces entry, item 3, owner
   rulings 2026-10-10): above the conversations under "Updates". The
   sentence WRAPS - it is the whole notice, so it is never cut to one line
   like a conversation's preview - and the doors sit under it at the 44px
   tap floor, wrapping on a phone rather than pushing the drawer wide. */
.inbox-sec { margin: 0; padding: var(--sp-4) var(--sp-5) var(--sp-2);
  font-size: var(--fs-small); font-weight: var(--fw-semibold);
  color: var(--ink-soft); border-bottom: 1px solid var(--border); }
.inbox-note { display: grid; gap: 6px; min-width: 0;
  padding: 12px var(--sp-5); border-bottom: 1px solid var(--border); }
.inbox-note-top { display: flex; align-items: baseline; gap: var(--sp-2);
  min-width: 0; }
.inbox-note .inbox-acct { font-weight: var(--fw-semibold); }
.inbox-note .inbox-when { font-size: var(--fs-small); color: var(--ink-soft); }
.inbox-note-text { margin: 0; min-width: 0; font-size: var(--fs-small);
  color: var(--ink); overflow-wrap: anywhere; }
.inbox-note-acts { display: flex; flex-wrap: wrap; align-items: center;
  justify-content: flex-end; gap: var(--sp-2); min-width: 0; }
.inbox-note-ask { margin-right: auto; font-size: var(--fs-small);
  font-weight: var(--fw-semibold); color: var(--ink); }
.inbox-note-btn { min-height: 44px; padding: 8px 16px; }
@media (max-width: 760px) {
  .inbox-drawer { width: 100vw; }
  .inbox-btn .inbox-btn-label { display: none; }
}

/* THE ARRIVAL AT THE THREAD (item 1): the messages the agent had not read
   sit under a "New" divider, and on arrival from the inbox they carry a
   brief soft highlight. The highlight is an ANIMATION, so under reduced
   motion the global rule removes it: the divider says which are new, the
   end state, with no motion. */
.corr-new { display: flex; align-items: center; gap: var(--sp-3);
  color: var(--blue); font-size: var(--fs-label); font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-label); text-transform: uppercase; }
.corr-new::before, .corr-new::after { content: ""; flex: 1 1 auto;
  border-top: 1px solid var(--blue); opacity: .45; }
.corr-row.is-new-flash { animation: corr-arrive 1.6s ease-out 1; }
/* THE ARRIVAL AT ONE UPDATE (agent surfaces entry, item 3): the drawer's
   Open lands on the notice's own row in the quote page's history with the
   thread's soft highlight; reduced motion removes it, the focus stays. */
.ap-upd-row.is-new-flash { animation: corr-arrive 1.6s ease-out 1; }
@keyframes corr-arrive {
  0%, 35% { box-shadow: 0 0 0 3px var(--focus-ring); }
  100% { box-shadow: 0 0 0 3px transparent; }
}

/* THE DASHBOARD'S GREEN CHECK (agent inbox entry item 4, owner ruling
   2026-09-23): beside a bound row's chip for one business day. */
/* `position: relative` makes the check the containing block of its own
   screen-reader text: the board scrolls sideways inside `.card.board`,
   which is not positioned, so an absolute child escaped the board's clip
   and widened the whole page at 375 (the drive's measurement). */
.row-justbound { position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; margin-left: 6px; vertical-align: middle;
  border-radius: 50%; background: var(--green); color: var(--on-color);
  font-size: 12px; font-weight: var(--fw-semibold); line-height: 1; }
.row-justbound-sr { position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; }

/* =========================================================================
   THE GREEN BOUND STATE AND ITS ONE-TIME CELEBRATION (agent inbox entry
   item 4, owner rulings 2026-09-23)
   =========================================================================
   `.hero-bound` is PERMANENT for a bound account: deep green, the check,
   the ruled headline, the documents line and this bind's points.
   `.is-celebrating` is the one-time motion over it: the green fades up
   from the blue and the check draws itself in. Both are ANIMATIONS, so
   the global reduced-motion rule at the top of this file removes them
   and the end state is simply there. The confetti, the count-up and the
   flight are script, and the script checks the same preference. */
.hero.hero-bound {
  background: linear-gradient(135deg, var(--bound-green) 0%, var(--bound-green-deep) 100%);
}
.hero-bound.is-celebrating { animation: bound-arrive .9s ease-out 1 both; }
@keyframes bound-arrive {
  from { box-shadow: inset 0 0 0 999px var(--navy), var(--shadow-hero); }
  to   { box-shadow: inset 0 0 0 999px transparent, var(--shadow-hero); }
}
.bound-head { display: flex; align-items: center; gap: 12px; margin-top: 6px;
  font-size: var(--fs-h1); font-weight: var(--fw-semibold); color: var(--on-color); }
.bound-check { flex: none; color: var(--on-color); }
.bound-check-mark { stroke-dasharray: 26; stroke-dashoffset: 0; }
.hero-bound.is-celebrating .bound-check-mark {
  animation: bound-check-draw .6s .35s ease-out 1 both; }
@keyframes bound-check-draw { from { stroke-dashoffset: 26; } to { stroke-dashoffset: 0; } }
.bound-eff { color: var(--on-navy-soft); font-size: var(--fs-body); margin-top: 4px; }
.bound-docs { color: var(--on-navy); font-size: var(--fs-body); margin-top: var(--sp-2); }
.bound-points { margin-top: var(--sp-4); }
/* THE POINTS MOVE RIGHT (agent bind page polish item 3, owner walkthrough
   2026-09-24): the bound hero takes the quote hero's `.hero-cols`, and the
   points are its right-hand `.hero-incentive`, where the quote hero says
   "You'll earn N Normandy Reward Points". At 760px and below the columns
   stack and the points come FIRST, directly under the headline, with the
   rule that separates them moved beneath. */
.hero-cols .bound-points { margin-top: 0; }
@media (max-width: 760px) {
  .hero-bound .bound-points { order: -1; border-top: 0; padding-top: 0;
    border-bottom: 1px solid var(--on-navy-border);
    padding-bottom: var(--sp-4); }
}
.bound-points-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.bound-points-fig { font-size: 30px; font-weight: var(--fw-semibold); line-height: 1.1;
  background: linear-gradient(120deg, var(--gold-hi), var(--gold-lo));
  -webkit-background-clip: text; background-clip: text; color: transparent; }
.bound-points-label { font-weight: var(--fw-semibold); color: var(--on-navy); }
.bound-points-note { color: var(--on-navy-soft); font-size: var(--fs-small); margin-top: 4px; }
.bound-points-ghost { position: fixed; z-index: 960; margin: 0; pointer-events: none;
  font-size: 30px; font-weight: var(--fw-semibold); line-height: 1.1;
  color: var(--gold-lo); will-change: transform; }
.bind-confetti { position: fixed; inset: 0; z-index: 950; pointer-events: none; }
/* the pulse's length is the script's CELEBRATION_MS.landingPulse (item 4,
   2026-09-24), handed over as a custom property on the control */
.pill-link.is-landing { animation: rewards-pulse var(--landing-pulse-ms, .7s) ease-out 1; }
@keyframes rewards-pulse {
  0%   { transform: scale(1); box-shadow: 0 0 0 0 var(--gold-glow); }
  40%  { transform: scale(1.12); box-shadow: 0 0 0 8px var(--gold-glow); }
  100% { transform: scale(1); box-shadow: 0 0 0 0 transparent; }
}

/* =========================================================================
   THE LIVE PREMIUM TRACKER (agent inbox entry item 3, owner rulings
   2026-09-23; re-laid out 2026-10-04, the deferred-flag entry item 9)
   =========================================================================
   AT EVERY WIDTH a slim "Estimate" tab fixed to the right edge, carrying
   the figure, and a small panel it slides out OVER the form. Both are
   fixed to the viewport, so the form keeps its width and nothing reflows -
   the retired layout made the tracker a third grid column at 1180px and
   wider, which narrowed the form, and a slim bottom bar below that. The
   content box keeps the 1280px it took for the column, so the form is as
   wide as it was before the tracker appeared. */
.tracker[hidden], .tracker-card[hidden], .tracker-fine[hidden] { display: none; }
.tracker { position: fixed; right: 0; top: 38vh; z-index: 800;
  display: flex; align-items: flex-start; flex-direction: row-reverse;
  pointer-events: none; }
.tracker > * { pointer-events: auto; }
.tracker-tab { display: flex; flex-direction: column; align-items: center;
  gap: 8px; width: 36px; min-height: 44px; padding: 12px 0;
  border: 0; border-radius: var(--r-card) 0 0 var(--r-card); cursor: pointer;
  background: var(--navy); color: var(--on-navy); font: inherit;
  box-shadow: var(--shadow-pop); }
.tracker-tab-label, .tracker-pill { writing-mode: vertical-rl;
  transform: rotate(180deg); white-space: nowrap; }
.tracker-tab-label { font-size: var(--fs-label); font-weight: var(--fw-semibold);
  letter-spacing: .04em; text-transform: uppercase; }
.tracker-pill { font-size: var(--fs-small); font-weight: var(--fw-semibold); }
.tracker-card { width: min(280px, calc(100vw - 52px)); margin-right: 8px;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--r-card); box-shadow: var(--shadow-pop);
  padding: 14px 16px; min-width: 0;
  animation: tracker-in .18s ease-out; }
@keyframes tracker-in { from { transform: translateX(24px); opacity: 0; }
                        to { transform: none; opacity: 1; } }
.tracker-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.tracker-label { font-size: var(--fs-small); font-weight: var(--fw-semibold);
  color: var(--ink-soft); min-width: 0; }
.tracker-toggle { margin-left: auto; min-width: 44px; min-height: 44px;
  margin-right: -10px; border: 0; background: transparent; color: var(--ink-soft);
  border-radius: var(--r-pill); cursor: pointer; display: inline-flex;
  align-items: center; justify-content: center; }
.tracker-toggle:hover { background: var(--neutral-tint); color: var(--ink); }
.tracker-fig { font-size: 26px; line-height: 1.15; font-weight: var(--fw-semibold);
  color: var(--navy); margin-top: 2px; overflow-wrap: anywhere; }
.tracker-sub { font-size: var(--fs-small); color: var(--ink-soft); margin-top: 2px; }
/* the second, smaller line under the estimate (item 8, owner walkthrough
   2026-10-04) */
.tracker-fine { font-size: var(--fs-label, 11px); color: var(--ink-soft); margin-top: 2px; }
.tracker-change { min-height: 1.45em; margin-top: 6px; font-size: var(--fs-small);
  font-weight: var(--fw-semibold); }
.tracker-change[data-dir="down"] { color: var(--green-ink); }
.tracker-change[data-dir="up"] { color: var(--amber-ink); }
@media (min-width: 1180px) {
  .content.content-flow { max-width: 1280px; }
}
/* THE PAGE'S SCROLLBAR TAKES NO WIDTH FROM THE FORM EITHER: a class added
   at 1280 made the page tall enough to scroll, and the bar's 15px came out
   of the form (measured: 696 -> 681). The quote flow always carries its
   scrollbar, so the form's width does not change as it grows (a phone's
   overlay scrollbar takes no width either way). */
html:has(.content.content-flow) { overflow-y: scroll; }

/* ---- THE FORMS CARD (agent bind page polish item 1, owner walkthrough
   2026-09-24). Second below the thread on the quote, bind-requested and
   bound pages, while a required form is outstanding: a header with a
   count, a slim bar, one row per form with its pill and two real buttons,
   the general zone last. A soft amber left edge while anything is
   Missing; one green line when everything is in. Every row is a drop
   target (`is-over` while a file hovers it). */
.fc-card { background: var(--card); border-radius: var(--r-card);
  box-shadow: var(--shadow-card); margin: var(--sp-4) 0;
  padding: var(--sp-4) var(--sp-5); min-width: 0; }
.fc-card.is-missing { border-left: 4px solid var(--amber);
  border-radius: 0 var(--r-card) var(--r-card) 0; }
.fc-head { display: flex; align-items: baseline; gap: var(--sp-3);
  flex-wrap: wrap; }
.fc-title { font-size: var(--fs-h2); line-height: var(--lh-h2);
  font-weight: var(--fw-hero); color: var(--ink); margin: 0;
  flex: 1 1 260px; min-width: 0; }
.fc-count { font-size: var(--fs-small); font-weight: var(--fw-semibold);
  color: var(--amber-ink); white-space: nowrap; }
.fc-bar { height: 6px; border-radius: var(--r-pill);
  background: var(--amber-tint); margin: var(--sp-2) 0 var(--sp-3);
  overflow: hidden; }
.fc-bar-fill { height: 100%; background: var(--green);
  border-radius: var(--r-pill); }
.fc-rows { display: flex; flex-direction: column; gap: var(--sp-2); }
.fc-row { display: flex; align-items: center; gap: var(--sp-3);
  flex-wrap: wrap; padding: var(--sp-3); border: 1px dashed var(--border);
  border-radius: var(--r-ctl); background: var(--card); min-width: 0; }
.fc-row.is-missing { background: var(--amber-tint);
  border-color: var(--amber); }
.fc-row.is-over { border-style: solid; border-color: var(--blue);
  box-shadow: 0 0 0 3px var(--focus-ring); }
.fc-main { flex: 1 1 220px; min-width: 0; }
.fc-name { font-weight: var(--fw-semibold); color: var(--ink);
  overflow-wrap: anywhere; }
.fc-pill { display: inline-block; margin-top: 4px; padding: 2px 10px;
  border-radius: var(--r-pill); font-size: var(--fs-small);
  font-weight: var(--fw-semibold); }
.fc-pill.is-missing { background: var(--amber); color: var(--amber-ink); }
.fc-pill.is-received { background: var(--tint-green); color: var(--green-ink); }
.fc-note { font-size: var(--fs-small); color: var(--ink-soft);
  margin-top: 4px; }
.fc-acts { display: flex; gap: var(--sp-2); flex-wrap: wrap;
  align-items: center; }
.fc-acts .doc-upload-row { display: inline-flex; flex-wrap: wrap;
  align-items: center; gap: var(--sp-2); }
.fc-btn { padding: 8px 14px; font-size: var(--fs-small); min-height: 36px; }
.fc-other .ap-cu { border-radius: var(--r-ctl); }
.fc-done { display: flex; align-items: center; gap: var(--sp-2);
  color: var(--green-ink); font-weight: var(--fw-semibold); }
.fc-card.is-done { background: var(--tint-green); padding: var(--sp-3) var(--sp-5); }
/* The optional forms' one quiet line (item 8, 2026-09-24): small, soft,
   no pill, no amber; its Download link keeps WCAG 2.5.8's 24px target. */
.fc-optional { font-size: var(--fs-small); color: var(--ink-soft);
  margin-top: var(--sp-3); overflow-wrap: anywhere; }
.fc-optional a { display: inline-block; min-height: 24px; line-height: 24px; }
@media (max-width: 760px) {
  .fc-card { padding: var(--sp-3) var(--sp-4); }
  .fc-acts { width: 100%; }
  /* DIRECT CHILDREN ONLY: the upload wrapper is a COLUMN flex box, so a
     basis reaching the button inside it became the button's HEIGHT - a
     140px green block at 375 (found by the item 3 visual check) */
  .fc-acts > .fc-btn, .fc-acts > .doc-upload-row { flex: 1 1 140px; }
  .fc-acts > .doc-upload-row { max-width: none; }
  .fc-acts .doc-upload-row .fc-btn { flex: none; width: 100%;
    justify-content: center; }
}

/* The hero's chip: a quiet pill on the hero ground that says how many
   forms are still needed and points down at the card. */
.forms-chip-slot:empty { display: none; }
.forms-chip { display: inline-flex; align-items: center; gap: 6px;
  margin-top: var(--sp-2); padding: 5px 12px; border-radius: var(--r-pill);
  background: var(--amber); color: var(--amber-ink);
  font-size: var(--fs-small); font-weight: var(--fw-semibold);
  text-decoration: none; max-width: 100%; }
.forms-chip:hover, .forms-chip:focus-visible { background: var(--gold-hi); }
.forms-chip svg { flex: 0 0 auto; }

/* ---- TWO-WAY ATTACHMENTS (agent bind page polish item 5, owner
   walkthrough 2026-09-24): the files on a message, each a download, and
   the reply box's attach control with its waiting list. */
.corr-atts { list-style: none; margin: 8px 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 4px; }
.corr-att { display: flex; align-items: center; gap: 6px; min-width: 0;
  font-size: var(--fs-small); color: var(--ink-soft); }
.corr-att-ico { flex: 0 0 auto; color: var(--ink-soft); }
.corr-att-dl { border: 0; background: none; padding: 2px 0; cursor: pointer;
  font: inherit; color: var(--blue); text-decoration: underline;
  text-align: left; overflow-wrap: anywhere; min-width: 0; }
.corr-att-dl:hover { color: var(--blue-hover); }
.corr-att-name { overflow-wrap: anywhere; min-width: 0; }
.corr-att-gone { color: var(--gray); }
.corr-attach { display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--sp-2); margin-top: var(--sp-2); }
.corr-attach-btn { position: relative; overflow: hidden; cursor: pointer; }
/* THE INPUT COVERS THE BUTTON (gate rider, 2026-09-24): invisible, but the
   whole "Attach files" button's size, so the tap lands on the file input
   itself and the target is the button's - WCAG 2.5.8's 24px floor is met
   by construction. The first cut copied the drop zone's 1x1 input, which
   is the ONE ruled exception on the mobile control sweep and does not
   extend to a second control. */
.corr-attach-btn input[type=file] { position: absolute; inset: 0;
  width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.corr-attach-btn:focus-within { box-shadow: 0 0 0 3px var(--focus-ring); }
.corr-attach-hint { font-size: var(--fs-small); color: var(--ink-soft); }
.corr-attach-list { list-style: none; margin: 0; padding: 0; width: 100%;
  display: flex; flex-direction: column; gap: 4px; }
.corr-attach-list:empty { display: none; }
.corr-attach-file { display: flex; align-items: center; gap: 6px;
  font-size: var(--fs-small); min-width: 0; }
.corr-attach-state { color: var(--green-ink); font-weight: var(--fw-semibold); }
.corr-attach-x { border: 0; background: none; cursor: pointer;
  font-size: 18px; line-height: 1; color: var(--ink-soft);
  min-width: 32px; min-height: 32px; }

/* =========================================================================
   EVERY .btn AT 44px ON A PHONE (owner ruling 2026-09-26, walkthrough
   follow-on item 11; the gap the 2026-09-08 ruling named in neither list)
   =========================================================================
   New quote, the second-look send, the forms card's Download blank and
   every other control of the theme's button class - `.btn-sm` included -
   meet 44px at the theme's 900px layout breakpoint, the block the rest of
   the 44px set already rides. LAST IN THE FILE ON PURPOSE: a component
   rule written later with the same specificity (`.fc-btn`'s 36px) would
   otherwise win the cascade and quietly undo it. 1280 is untouched - the
   desktop layout has a pointer (`tests/test_tap_targets_1280_20260908.py`).
   Measured by the tap-target sweep (`RULED_44`, needle `.btn`). */
@media (max-width: 900px) {
  .btn, .btn.fc-btn { min-height: 44px; }
}

/* "MAILING ADDRESS ONLY" AT 44px ON A PHONE (owner ruling 2026-09-27,
   follow-on rulings item 1, at cloud gate 36431734810): the checkbox under
   the Primary/Mailing Address is 24px at desktop (the AA floor) and 44px at
   the 900px breakpoint. Last in the file for the reason above. Measured by
   the tap-target sweep (`RULED_44`, needle `.check-opt`'s input). */
@media (max-width: 900px) {
  .check-opt input { width: 44px; height: 44px; }
}

/* =========================================================================
   TOUCH TARGETS: EVERY CONTROL'S TAP AREA 44 x 44, 8px APART, ON A TOUCH
   DEVICE (touch targets entry, owner rulings 2026-10-19; establish
   docs/touch_dividend_establish_20261018.md, Part 1)
   =========================================================================
   THE STANDARD: on a touch device (`pointer: coarse`) every interactive
   element has a tap area of at least 44 x 44 CSS px and neighbouring tap
   areas are at least 8px apart. DESKTOP DENSITY IS UNCHANGED - nothing
   below applies to a mouse, at any width; the 1280 pin
   (tests/test_tap_targets_1280_20260908.py) still reads the desktop as it
   was. A tablet in landscape is covered, which a width rule would miss.

   ENLARGE THE TAP AREA, NEVER THE LOOK. The mechanism is said HERE, once:
   the control becomes a positioning box and an invisible `::after` square,
   centred on it, reaches at least 44 x 44 - a tap on the pseudo-element is
   a tap on the control. `:where()` keeps the position rule at zero
   specificity, so a control a screen positions absolutely or fixed keeps
   that. Applied ONLY to the controls listed (each measured without an
   `::after` of its own), never to every button, so a component that draws
   with `::after` is never overwritten.

   THE ONE VISIBLE CHANGE IS A TEXT FIELD OR SELECT: a replaced control
   cannot carry a pseudo-element, so it meets 44 by `min-height` - the
   `.field` family moves 43.7 -> 44 (rounding nobody sees), a select 41 ->
   44. The filter widgets the owner named meet it with no visual change
   (status_board_own.html's own block).

   Measured by tests/test_browser_touch_targets_{agent,staff,console}
   _20261019.py, which tap the four corners of the 44 square on every
   control of every screen at 390 x 844 and 820 x 1180. RULE R1 (owner,
   2026-10-19): the wordmark, Sign out and the banner dismiss - named OUT
   of 44 on 2026-09-08 - are IN on a touch device, by this hit area, with
   no change to how they look. */
@media (pointer: coarse) {
  :where(.chrome .logo, #sign-out, .chrome .pill-link, .idchip,
         .resume-banner a, .resume-banner .close, .tracker-tab,
         .review-head .edit, .qacc-q.rcpt .edit, .board th.sortable button,
         .rep-row .del, .needs-attention li a, .ap-hero-msg a, .forms-chip,
         .msg-summary, .continue-link, .doc-open, .doc-remove, .ap-line-btn,
         .wv-opt, .wv-addbtn, .wv-del, .credit-opt) {
    position: relative;
  }
  :where(.chrome .logo, #sign-out, .chrome .pill-link, .idchip,
         .resume-banner a, .resume-banner .close, .tracker-tab,
         .review-head .edit, .qacc-q.rcpt .edit, .board th.sortable button,
         .rep-row .del, .needs-attention li a, .ap-hero-msg a, .forms-chip,
         .msg-summary, .continue-link, .doc-open, .doc-remove, .ap-line-btn,
         .wv-opt, .wv-addbtn, .wv-del, .credit-opt)::after {
    content: ""; position: absolute;
    top: min(0px, calc((100% - 44px) / 2));
    bottom: min(0px, calc((100% - 44px) / 2));
    left: min(0px, calc((100% - 44px) / 2));
    right: min(0px, calc((100% - 44px) / 2));
  }

  /* the credit option is a LABEL carrying its checkbox's square: the
     checkbox stays on top (the label is its own stacking context, the
     square at z-index -1 inside it), so a tap on the box lands on the box */
  .credit-opt { z-index: 0; }
  .credit-opt::after { z-index: -1; }

  /* text entry and selects: a replaced control has no pseudo-element */
  .field input:not([type=checkbox]):not([type=radio]):not([type=file]),
  .field select, .field textarea { min-height: 44px; }

  /* the tracker's tab is flush with the screen's right edge: its area
     reaches left, never past the glass */
  .tracker-tab::after { left: -8px; right: 0; }
  /* the date field's calendar: the 2026-08-30 fix's 46px, which it gave
     only below 560px, on every touch device (the native date control laid
     over it is sized from the slot, so the tap area follows) */
  .cal-btn { width: 46px; }
  /* the waiver section's own controls (portal/waivers.js, which injects
     its stylesheet after this one - hence the doubled class) */
  .wv .wv-input { min-height: 44px; }

  /* SPACING: neighbours whose 44 areas would otherwise crowd each other.
     Only gaps move; no control changes size or colour. */
  .needs-attention ul { gap: 12px; }
  .needs-attention li { min-height: 44px; align-items: center; }
  .chrome-inner { row-gap: 16px; }
  .chrome-actions { row-gap: 16px; }
  .ap-lines { gap: 14px; }
  .rep-row { gap: 20px; }
  .wv.wv { --wv-gap: 16px; }
  .wv .wv-list, .wv .wv-add { gap: 14px; }
  .ap-hero-msg { margin-top: 20px; }
  .field > .sl-row { margin-top: 4px; }
  /* a pair of buttons that wraps on a phone: 8px between, on both axes */
  .btn-pair { display: flex; flex-wrap: wrap; gap: 8px; }
  .btn-pair > .btn { margin-left: 0 !important; }
}

/* the corner Remove of a location or waiver row, between the theme's 768
   and 900 breakpoints (above): on a touch device the row reserves enough
   corner for its 44 square and 8px to the field */
@media (pointer: coarse) and (min-width: 768px) and (max-width: 900px) {
  .rep-row.location, .rep-row.waiver { padding-right: 64px; }
}
