/* Harkham agent portal — layout and components that exist ONLY on this surface.
 *
 * ⚠️ EVERY TOKEN AND EVERY SHARED PRIMITIVE LIVES IN `/shared/tokens.css`, WHICH `index.html`
 * LOADS BEFORE THIS FILE. Until 4 September 2026 the first 146 lines of this file were a
 * byte-identical copy of the first 146 lines of `public/admin/app.css` — see the shared file's
 * header for what that copy had already cost on the console side, and for docs/60's own ruling
 * that the tokens, components, money rules and error wording "are shared and must stay shared".
 *
 * Six rules that used to live here have moved there because the console needed them too and did
 * not have them: `.pagehd`, `.card{overflow-x:auto}`, `td.n`/`td.nowrap`, `.fldmsg`/`.inp.bad`,
 * `.alert.ok`, `select.inp`, and the narrow-width touch-target block.
 *
 * ⚠️ AND THE TRAFFIC NOW RUNS BOTH WAYS, 4 September 2026 (Run F). `.shell`, `.side`, `.navgroup`,
 * `.glabel` and `.navitem` moved OUT OF the console's stylesheet and INTO the shared one when this
 * portal replaced its three-tab segmented strip with a rail of seven destinations — the alternative
 * was a second copy of `.navitem` here, which is the exact failure the paragraphs above record.
 * The bottom bar and the More sheet are there too, because a surface-specific component still gets
 * one definition.
 *
 * ⚠️ DO NOT DECLARE A CUSTOM PROPERTY OR A HEX COLOUR IN THIS FILE. `src/sharedDesignTokens.test.ts`
 * fails on either. What belongs here is what the console has no counterpart for: the carrier-of-
 * record disclosure, the address block, the KYC gate list, the path-to-BOOKED list, the worklist
 * sections, the phone-first field-width system docs/60 §14 specifies for this surface, and this
 * surface's own answer to what the navigation becomes below 768px.
 */

.copybtn{font-size:var(--t-small);padding:var(--s1) var(--s2)}

.reccodes{display:grid;grid-template-columns:1fr 1fr;gap:var(--s2);
  font-family:var(--font-mono);font-size:var(--t-body);letter-spacing:.04em;
  background:var(--navy);border-radius:var(--r);padding:var(--s3);margin:var(--s3) 0}

.kycflag{display:inline-flex;align-items:center;gap:var(--s1)}

/* ================================================================================================
   CARRIER OF RECORD — 46 CFR 515.4(c). Rendered at quote, at booking and at payment.
   ================================================================================================
   Deliberately quiet but NOT muted-grey-small-print. Harkham's OTI exemption holds only for cargo
   moving under MV DUDU EXPRESS LTD's own bill of lading, as that carrier's disclosed agent — so
   this is a disclosure that has to be READ, not a legal footer nobody looks at. It gets a left
   border and its own ground so it reads as a distinct statement rather than another muted line in
   a card, and the carrier's NAME is at body size while the explanatory sentence is smaller.

   ⚠️ Not gold and not red: it is neither a warning nor an action. It is a fact about who the
   counterparty is, and dressing it as an alert would train people to dismiss it.

   ⚠️ THE BOX AROUND IT IS GONE, 4 September 2026, AND THE LEFT RULE IS NOT. The full border plus
   the left rule plus the ground was three separation devices on one element; the ground and the
   rule are two and say the same thing the three did. */
.carrier{background:var(--navy2);border-left:3px solid var(--line2);
  border-radius:0 var(--r) var(--r) 0;padding:var(--s3) var(--s4)}
.carrier-hd{font-size:var(--t-micro);font-weight:500;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink3);margin-bottom:var(--s1)}
.carrier-name{font-size:var(--t-body);font-weight:600;color:var(--ink);margin-bottom:var(--s1)}
.carrier-note{font-size:var(--t-small);line-height:1.5;color:var(--ink2)}

/* ================================================================================================
   ONE ADDRESS BLOCK — billing, pickup or delivery.
   ================================================================================================
   Registration can carry up to three, each with its own country and therefore its own field set.
   Without a visible boundary, three stacked address forms read as one long form with repeated
   labels, and an agent on a phone loses track of which "City" they are filling in. The block is
   the unit of meaning, so it needs to be visibly one thing — but on dark that is a LIFT, not a
   border (see the shared sheet's header). */
.addrblock{border-radius:var(--r);padding:var(--s4);margin-bottom:var(--s3);background:var(--navy2)}
.addrblock h3{margin-top:0;margin-bottom:var(--s3)}
.addrblock .seg{margin-bottom:var(--s2)}

/* ================================================================================================
   THE THREE-LINE GATE — what an unconfirmed identity check permits and blocks.
   ================================================================================================
   Randy, verbatim: "no sail unpaid or no payment without KYC." Booking allowed and flagged,
   payment blocked, release blocked. Rendered as a list with the verdict FIRST on each line, because
   an agent scanning it under time pressure needs the allowed/blocked column to line up — a sentence
   ending in "is blocked" reads at the speed of prose, not at the speed of a glance. */
.gatelist{list-style:none;margin:0;padding:0}
.gatelist li{display:flex;align-items:baseline;gap:var(--s2);font-size:var(--t-body);color:var(--ink2);
  padding:var(--s2) 0;border-bottom:1px solid var(--line)}
.gatelist li:last-child{border-bottom:0}
.gatelist .pill{flex:0 0 auto;min-width:62px;justify-content:center}

/* ================================================================================================
   BEFORE THIS IS BOOKED — the outstanding preconditions, each with its owner.
   ================================================================================================
   The owner pill is first and fixed-width for the same reason the gate list's verdict is: the
   question an agent is answering while they scan this is "is this mine?", and a column that lines
   up answers it at a glance. A reason that started with prose would have to be read. */
.pathlist{list-style:none;margin:0;padding:0}
.pathlist li{display:flex;align-items:flex-start;gap:var(--s2);font-size:var(--t-body);color:var(--ink2);
  padding:var(--s2) 0;border-bottom:1px solid var(--line)}
.pathlist li:last-child{border-bottom:0}
.pathlist .pill{flex:0 0 auto;min-width:96px;justify-content:center;margin-top:1px}

/* ================================================================================================
   FORM LAYOUT — docs/60 §14. PHONE-FIRST, because this is the agent portal.
   ================================================================================================
   Randy: *"FIELD WIDTH SIGNALS EXPECTED INPUT LENGTH. A two-character state field rendered as wide
   as a street address tells the user nothing, and a column of identical boxes is slow to scan."*

   ⚠️ AND THE TENSION HE NAMED IS WHY THIS IS WRITTEN MOBILE-FIRST RATHER THAN WITH DESKTOP
   OVERRIDES: *"full-width stacked fields are CORRECT on a phone and wrong on a desktop."* The base
   rules below stack everything full width — which is the right answer at 390px and is what an agent
   in a yard actually gets — and the `min-width` block widens fields to their declared content size
   only once there is room. Written the other way round, the phone case becomes the exception and is
   the one nobody looks at.

   `w-tiny` ~ a US state · `w-short` ~ a ZIP, a licence number · `w-medium` ~ a city, an email
   · `w-full` ~ a street address, a person's name. A field declares what it EXPECTS TO HOLD; it
   never declares a column. */
.fldrow{display:flex;flex-direction:column;gap:0}
.fldrow > .fld{width:100%}
.fldhint{margin-top:var(--s1)}

/* ⚠️ 768px, matching every other breakpoint in the platform. This block was at 620px, the shared
   grid rules were at 760px and the console shell was at 900px — three numbers for one idea. */
@media (min-width: 768px) {
  .fldrow{flex-direction:row;gap:var(--s3);align-items:flex-start}
  /* `flex-grow:0` throughout: a row of three must not stretch a two-character state to a third of
     the width, which is the exact defect this replaces. The row is left-aligned and short fields
     stay short. */
  .fldrow > .fld{flex:0 0 auto}
  .fldrow > .fld.w-tiny{width:88px}
  .fldrow > .fld.w-short{width:150px}
  .fldrow > .fld.w-medium{width:240px}
  /* The one field allowed to take the remaining room, so a row never ends in dead space. */
  .fldrow > .fld.w-full{flex:1 1 auto;min-width:200px}

  /* Outside a row, a lone field is still sized to its content rather than to the modal. */
  .fld.w-tiny{max-width:88px}
  .fld.w-short{max-width:150px}
  .fld.w-medium{max-width:320px}
}

/* ⚠️ A HINT UNDER A NARROW FIELD MUST NOT SET THE FIELD'S WIDTH. Without this, a 150px ZIP field
   with a 60-character hint under it gets stretched by its own explanatory text — the layout bug
   that makes people delete the hint instead of fixing the CSS. */
.fldrow > .fld .fldhint{width:max-content;max-width:34ch}

/* "Same client as last time" — one tap, full width, comfortably tappable on a phone. */
.recentclient{display:flex;width:100%;justify-content:flex-start;margin-bottom:var(--s2);text-align:left}

/* What a duplicate deliberately did NOT carry over, inside the info banner. ⚠️ Styled to be READ,
   not skimmed past: an agent who does not notice "the VIN is not carried over" fills in a form they
   believe is complete. */
.withheldlist{margin:var(--s2) 0 0;padding-left:var(--s4)}
.withheldlist li{font-size:var(--t-small);line-height:1.5;color:var(--ink2);margin-top:var(--s1)}

/* ⚠️ THE 880px CAP IS GONE — 5 September 2026. It said, correctly for the time, that this surface
   is "phone-first and PROSE-HEAVY" and that 880px keeps a line of portal prose inside a comfortable
   measure. THE PROSE IS WHAT CHANGED: the permanent policy text moved behind the .infodot, and what
   is left in the column is data and controls, which have no comfortable measure — they have a
   screen to fill.

   ⚠️ MEASURED, BECAUSE THIS IS THE COMPLAINT: at 1440 under the old cap the content column ended at
   x=1076 and 364px of the screen was empty. The rail is 196px and the page pads 20px a side, so
   1120px is the width at which the column reaches the edge of the space it has at 1440 and stops
   growing on anything wider. It is also exactly what the console already uses, so the two surfaces
   now agree on one number instead of holding two. */
.main{max-width:1120px}

/* ================================================================================================
   THIS SURFACE'S NARROW-WIDTH NAVIGATION — Run F, 4 September 2026.
   ================================================================================================
   The shell, the rail and the bottom bar itself all live in `/shared/tokens.css`. What belongs
   HERE is the one decision that differs between the two surfaces: below 768px the console keeps
   its rail and scrolls it sideways, and this portal HIDES the rail outright because it has a
   bottom bar instead. Two rails on one narrow screen would be two navigations.

   ⚠️ 768px, and there is no fourth number. The breakpoint carried three different values for one
   idea until they were unified two runs ago (the form-row block here was at 620px, the shared grid
   rules at 760px, the console shell at 900px). */
@media (max-width: 767px) {
  .shell { grid-template-columns: minmax(0, 1fr) }
  .side { display: none }
}

/* The rail toggle in the top bar. A worded button, never a glyph — this product has no icon set
   and "an icon set is complete or absent". It is hidden below the breakpoint, where there is no
   rail for it to act on and the bottom bar is the navigation. */
@media (max-width: 767px) { .railtoggle { display: none } }

/* ================================================================================================
   THE WORKLIST — HOME. One question: what needs me today?
   ================================================================================================
   Each section is a card with a heading, a count, and the rows. The COUNT is in the heading rather
   than in a badge because a section whose count is zero must be able to say so in words in the same
   place — a badge reading "0" is the "zero that looks like an answer" this screen is forbidden to
   show anywhere.

   ⚠️ THE SECTION ORDER IS THE DESIGN AND IT IS FIXED IN THE MARKUP, NOT SORTED AT RUNTIME. Clients
   pending KYC first, because a client at PENDING cannot pay and so every pending client is a deal
   that cannot complete. Drafts, then bookings awaiting payment, then the next cutoff. A screen that
   reordered itself by count would move the most valuable section around under a person who had
   learned where it was. */
.wl { margin-bottom: var(--gap-block) }
/* ⚠️ A WORKLIST CARD IS A READOUT, NOT A DECISION. `--pad-decide` (24px) is docs/60 §16.2 density
   for "a card, a form, a modal body -- anywhere a person DECIDES something". These cards decide
   nothing: they answer "is anything waiting for me", and three of them answering "no" were spending
   24px above and below one sentence each. `--pad-decide-tight` is the token for exactly this and it
   already exists -- reaching for it is the subtractive move; inventing a third value would not be. */
.card.wl { padding: var(--pad-decide-tight) var(--pad-decide) }
.wl-hd { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); margin-bottom: var(--s2) }
/* ⚠️ A FLEX BOX, SO THE "i" CANNOT BE ORPHANED ONTO A LINE OF ITS OWN — OPS-70 phase A4, seen in
   the 390px capture of the home screen and not in any assertion. `.infodot` is an `inline-flex`
   sibling of a bare text node, and a browser is free to break between the two: "Clients who cannot
   pay yet" and "Waiting to be paid" both put the 16px mark alone on a second line, which reads as a
   stray dot rather than as a control attached to a heading. As two flex items the title wraps
   inside its own box and the mark stays beside it at the first baseline.

   `gap` replaces `.infodot`'s own `margin-left` here — it would otherwise be added to the gap and
   push the mark further out than every other "i" in the portal. */
.wl-hd h2 { margin: 0; display: flex; align-items: baseline; gap: var(--s2); min-width: 0 }
.wl-hd h2 > .infodot { margin-left: 0 }
/* The admission rule, in one sentence, under the heading of the section it governs. Written for a
   person, not a comment for a developer: a list with no stated rule for what is in it is the shape
   that produced an admin queue of 650 rows for four decisions. */
.wl-rule { font-size: var(--t-micro); color: var(--ink3); letter-spacing: .02em }
.wl-empty { font-size: var(--t-small); color: var(--ink2) }
/* One row of the worklist: what it is on the left, how long it has been waiting on the right. */
.wl-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3);
  padding: var(--s2) 0; border-bottom: 1px solid var(--line) }
.wl-row:last-child { border-bottom: 0 }
.wl-row .wl-what { min-width: 0 }
.wl-row .wl-when { flex: 0 0 auto; font-size: var(--t-small); color: var(--ink3);
  font-variant-numeric: tabular-nums; white-space: nowrap }

/* THE NEXT CUTOFF — time remaining, at a size that can be read across a yard. The figure is the
   server's own `closesInHours`; nothing here does date arithmetic (see app.js). */
.cutoffbig { font-size: var(--t-h1); font-weight: 650; letter-spacing: -.02em; color: var(--ink);
  font-variant-numeric: tabular-nums }
.cutoffbig.past { color: var(--red) }

/* ================================================================================================
   THE CLIENT-LIST FILTER ROW — a segmented control that must never lose a segment.
   ================================================================================================
   🔴 `.seg` SETS `overflow: hidden`, WHICH IS FINE FOR THE TWO- AND THREE-LABEL SEGMENTED CONTROLS
   IT WAS BUILT FOR AND IS NOT FINE HERE. Each of these chips carries a COUNT, so its width is
   data-dependent — and at 390px the third one was clipped away entirely rather than made
   scrollable. A filter that hides one of its own options hides part of the list.
   
   Scoped to this row rather than changed on `.seg` itself: that `overflow: hidden` is load-bearing
   elsewhere (it is what keeps a selected tab's fill inside the track's rounded corners), and the
   shared sheet's own note records that it once clipped the portal's focus ring into invisibility.
   Wrapping is the right answer for a control whose segment widths depend on the data; `visible`
   overflow is a bonus here, because it is the one place a clipped focus ring could come back.
   
   ⚠️ The 3px inset padding on `.seg` means each chip is already inside the track's corner radius, so
   nothing needs clipping to look right. */
#client-filters .seg { flex-wrap: wrap; overflow: visible; row-gap: 3px }

/* ================================================================================================
   `.seg.wrap` — a segmented control whose LABELS are too long to fit on a phone.
   ================================================================================================
   🔴 THE SAME `overflow: hidden` DEFECT AS THE ROW ABOVE, ARRIVED AT FROM THE OTHER DIRECTION, AND
   THIS ONE CLIPPED A LEGAL CHOICE. `#dl-broker-seg` offers "Use Harkham's broker" and "The customer
   has their own" — `.seg button` sets `white-space: nowrap`, so neither label can shrink — inside a
   track that carried an inline `max-width:420px` on a 390px viewport. The second option was cut off
   mid-word. It is the control whose own hint reads "This has legal consequences for the customer",
   and it decides who lodges the customs entry at Nassau.

   ⚠️ A CLASS, NOT A SECOND ID RULE. `#client-filters .seg` above was written for one row and this is
   the second instance of the same need in the same stylesheet — a third id rule would be the point
   at which three copies start to diverge (rule 22). Its reasoning transfers unchanged and is not
   restated here: read it above, including why `overflow: visible` is a bonus rather than a risk
   (`.seg`'s 3px inset padding already keeps each chip inside the track's corner radius) and why
   changing `.seg` itself is not the answer.

   ⚠️ THE INLINE `max-width` IS GONE FROM THE MARKUP TOO, AND WRAPPING ALONE WOULD NOT HAVE BEEN
   ENOUGH WITHOUT THAT. A track fixed at 420px inside a 390px viewport overflows whatever its
   children do; `.seg`'s own `max-width: 100%` is the correct bound and was being overridden. */
.seg.wrap { flex-wrap: wrap; overflow: visible; row-gap: 3px }

/* ================================================================================================
   THE TARIFF TABLE — a rate code is an identifier and never wraps mid-identifier.
   ================================================================================================ */
.tariffcode { font-family: var(--font-mono); font-size: var(--t-small); white-space: nowrap }
/* 🔴 AN IDENTIFIER MAY NOT RUN OFF THE EDGE OF THE CARD IT IS IN — OPS-69B, found by opening the
 * 390px Profile capture. A uuid is 36 monospaced characters; the Profile card's value column at
 * 390px is about 210px wide. `white-space: nowrap` above is right on a wide table, where it stops a
 * code breaking mid-token across two lines, and at phone width it means the agent id is simply
 * CUT OFF by the card — the last third of it cannot be read, selected or copied, on the one screen
 * whose entire job is to state what this system holds about you.
 * ⚠️ `anywhere`, NOT `break-all`: it lets the browser break at any point WHEN IT HAS TO, and leaves
 * the token whole when it fits — so the same rule that rescues 390px changes nothing at 1440px. */
@media (max-width: 767px) {
  .tariffcode { white-space: normal; overflow-wrap: anywhere }
}

/* ================================================================================================
   THE CARGO-CLASS PICKER — NINE OPTIONS, ONE DECISION.
   ================================================================================================
   🔴 MEASURED BEFORE THIS EXISTED, at 1440x900 against these same stylesheets, 16 September 2026:
   each option was a `.card` carrying `--pad-decide` (24px top AND bottom) around 21px of content —
   one line of text and a price pill — for a row height of 69px. Production publishes NINE sellable
   classes, so the picker ran 621px before the buttons beneath it. Seventy per cent of it was
   padding, on the step an agent uses most.

   🔒 THE UNIT OF DECISION IS THE PICKER, NOT THE ROW, and that is the whole argument. `tokens.css`
   defines `--pad-decide` as "a card, a form, a modal body -- anywhere a person DECIDES something";
   an agent decides ONCE here and the nine rows are the options they decide between. So the picker
   keeps a card, tightened, and the rows take the dense treatment this system already names:
   `--cell-y`, "a table row: DENSE, deliberately". No new density is invented.

   ⚠️ THE ROWS ARE `<button>`s IN A `radiogroup`. They were clickable `<div>`s — unreachable by
   keyboard, announcing nothing — so an agent tabbing through step 3 could not choose a cargo class
   at all. `:focus-visible` is therefore load-bearing here, not decoration. */
.classlist { padding: var(--s2) var(--pad-decide-tight) }
.classrow {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  width: 100%; padding: var(--cell-y) 0; background: transparent; border: 0;
  border-bottom: 1px solid var(--line); border-radius: 0;
  color: var(--ink); font: inherit; text-align: left; cursor: pointer;
}
.classrow:last-child { border-bottom: 0 }
.classrow-label { font-weight: 600; min-width: 0 }
.classrow:hover { background: var(--navy2) }
.classrow:focus-visible { outline: 2px solid var(--cy2); outline-offset: -2px }
/* The chosen option. A state CLASS rather than the inline outline this used to set, so
   `src/stateClassesAreStyled.test.ts`'s subject — a state the stylesheet has no rule for — cannot
   arise here. Marked on the LEFT edge as well as by ground, so the selection is not carried by a
   background colour alone. */
.classrow.on { background: var(--navy2); box-shadow: inset 3px 0 0 0 var(--cy2) }

/* ================================================================================================
   THE STEP BREADCRUMB — THREE STATES THAT NOW SAY WHICH THEY ARE.
   ================================================================================================
   `.stepcrumbs` had NO rule of its own at all: the three states were `<b>`, `.muted` and a bare
   `<a>`, which is three appearances a person has to infer the meaning of. The one that changes what
   an agent can DO — an earlier step is clickable and returns you to it with everything kept — was
   the least visible of the three, because an `<a>` with no href takes no link styling.

   ⚠️ NONE OF THE THREE IS CARRIED BY COLOUR ALONE: done is underlined, current is bold with its own
   ground, and not-yet is muted AND unemphasised. Each also carries a `.vh` word naming it, so the
   distinction survives being read aloud. */
.stepcrumbs { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) }
.crumb { font-size: var(--t-small); line-height: 1.6 }
.crumb-here {
  color: var(--ink); font-weight: 600; background: var(--navy2);
  padding: 0 var(--s2); border-radius: var(--r-sm);
}
.crumb-done { color: var(--cy); text-decoration: underline; cursor: pointer }
.crumb-done:hover { color: var(--ink) }
.crumb-done:focus-visible { outline: 2px solid var(--cy2); outline-offset: 2px; border-radius: var(--r-sm) }
.crumb-later { text-decoration: none }
.crumb-sep { font-size: var(--t-small) }
/* WHY you are on this step, when there is a reason beyond "you walked here" — a recovered draft, a
   repeat. It is a separate block rather than a clause appended to the crumb row, because appended
   after the last crumb it read as part of it: `5. review — pick a sailing`. */
.crumb-why { display: block; margin-top: var(--s1); font-size: var(--t-small); color: var(--ink2) }
/* Said once, and only while at least one step is actually clickable. */
.crumb-hint { display: block; margin-top: var(--s1); font-size: var(--t-micro); color: var(--ink3) }

/* ────────────────────────────────────────────────────────────────────────────────────────────────
   THE ONE-LINE VERSION, FOR A PHONE. OPS-70 phase A3.
   ────────────────────────────────────────────────────────────────────────────────────────────────
   Measured at 390px before this rule: the crumb row is 153px and seven lines, against 22px and one
   line at 1440px. Three of those lines are crumbs at their 44px phone touch targets and two more
   are the "underlined steps are done" hint — a breadcrumb consuming a fifth of the viewport of a
   modal whose job is to collect one answer.

   ⚠️ THE HINT GOES WITH THE CRUMBS AND THAT IS NOT TIDYING. It says "Underlined steps are done —
   click one to go back"; left behind after the crumbs are hidden it describes a control that is not
   on the screen, which is worse than saying nothing at all. Both are hidden by the same rule so the
   two cannot come apart.

   ⚠️ THE CRUMB MARKUP IS UNCHANGED AND STILL RENDERED — this hides it, it does not stop building
   it. So nothing about the step state, the bold crumb, the ARIA `aria-current="step"` or the
   click bindings differs between the two widths; only what is painted does. */
.stepnow { display: none }
@media (max-width: 767px) {
  .stepnow { display: block; font-size: var(--t-small); font-weight: 600; color: var(--ink) }
  .stepcrumbs, .crumb-hint { display: none }
}

/* ================================================================================================
   THE CARRIER OF RECORD, BRIEF — the same words, a quarter of the height.
   ================================================================================================
   🔴 NOTHING IS REMOVED AND NO SENTENCE IS SPLIT. Every word the server sent is still rendered, in
   the server's own order; what changes is that the uppercase tag and the carrier's name stop being
   two stacked blocks above the sentence and sit inside its flow. The name is not lost — it is in
   the disclosure sentence itself, which is where it legally matters.

   ⚠️ WHY A VARIANT AT ALL, AND WHY THE DEFAULT IS THE FULL ONE. Randy, 16 September 2026: one line
   while browsing, full text at the commitment step and on the documents, and *"do not remove it
   anywhere — it is a disclosed-agent notice and where it must appear is counsel's question, not
   ours."* So `carrierOfRecordDisclosure` renders FULL unless a caller asks for brief: a call site
   added later and not thought about gets the safe one, which is the direction a legal default has
   to fail in. */
   🛑 AND THE NAME IS INLINED, NEVER `display:none`. The first draft of this rule hid
   `.carrier-name` on the brief variant, on the reasoning that the legal name already appears inside
   the disclosure sentence. That is true of TODAY'S sentence, which is the server's and may change —
   and `display:none` removes an element from the accessibility tree as well as from the page, so
   the one thing it would have hidden is the carrier's identity, from exactly the reader who cannot
   skim for it. Every one of the three blocks is still rendered and still read; they sit on one flow
   instead of three. */
.carrier.brief { padding: var(--s2) var(--s3) }
.carrier.brief > summary {
  display: flex; align-items: baseline; gap: var(--s2); cursor: pointer; list-style: none;
  font-size: var(--t-small);
}
/* The disclosure triangle, drawn rather than inherited, so it reads as "there is more here" at the
   same weight in every browser. Safari renders the default marker outside the flex line. */
.carrier.brief > summary::-webkit-details-marker { display: none }
.carrier.brief > summary::after {
  content: '+'; margin-left: auto; color: var(--ink3); font-size: var(--t-small); line-height: 1;
}
.carrier.brief[open] > summary::after { content: '−' }
.carrier.brief > summary:focus-visible { outline: 2px solid var(--cy2); outline-offset: 2px; border-radius: var(--r-sm) }
.carrier.brief .carrier-hd { margin: 0; flex: 0 0 auto }
.carrier.brief .carrier-name { font-size: var(--t-small); margin: 0; min-width: 0 }
.carrier.brief .carrier-note { margin-top: var(--s2) }

/* ================================================================================================
   A FIELD NHTSA FILLED IN — marked on the field itself, cleared the moment the agent types.
   ================================================================================================
   The VIN decode has filled year, make and model since register item 910, and said so in a run of
   sentences under the VIN box. Those are read once. This is the mark that is still there when the
   agent scrolls back up and asks which of these boxes they typed.

   ⚠️ NOT A COLOUR ALONE — a left edge in the accent plus a `title`. And it is `--cy2`, the token
   `tokens.css` itself describes as "for a border or a focused edge", never the text accent.

   🔴 AND THERE IS NO SUCH MARK ON HEIGHT, LENGTH OR WIDTH, BECAUSE vPIC DOES NOT PUBLISH THEM.
   Asked of the live endpoint on 16 September 2026: `DecodeVINValuesBatch` returns 154 fields, of
   which NINE have dimension-shaped names — BedLengthIN, BusLength, TrackWidth, TrailerLength,
   WheelBaseLong, WheelBaseShort, WheelBaseType, WheelSizeFront, WheelSizeRear — and not one is
   overall height, length or width. All nine came back EMPTY for an ordinary sedan VIN. A wheelbase
   is not a length and an axle track is not a width; filling a shipping dimension from either would
   be inventing a measurement that reaches a lane-metre calculation and a bill of lading. */
.inp.from-decode { box-shadow: inset 3px 0 0 0 var(--cy2) }
