/* CJH interface — the visual system of spec 21.
 *
 * Two brand colours, read out of the logo, and nothing else as an accent. Four status
 * colours that always mean the same thing. One type scale, one spacing scale. The
 * emphasis of a control says whether its action is still outstanding; the wording of a
 * state lives in a chip, never in a button.
 *
 * Every colour pair below was measured, not estimated: each reaches at least 4.5:1
 * against its own background (values in the comments).
 */
:root {
  /* brand (spec 21.2) */
  --blue: #006CB4;            /* 5.52:1 on white, and white 5.52:1 on it */
  --grey: #606060;            /* 6.29:1 on white */

  /* neutrals */
  --line: #dfe3e6;
  --bg: #f6f7f9;
  --ink: #1d2124;
  --shade: #f1f2f4;

  /* status — meaning, never decoration (spec 21.2) */
  --done-bg: #e8f5e9;  --done-ink: #1b5e20;  --done-line: #a5d6a7;   /* 7.00:1 */
  --ready-bg: #fff8e1; --ready-ink: #6b4e00; --ready-line: #e6c64d;  /* 7.28:1 */
  --block-bg: #fff1e6; --block-ink: #8a3e00; --block-line: #e8b08a;  /* 6.85:1 */
  --err-bg: #fdecea;   --err-ink: #a3160b;   --err-line: #e5a9a2;    /* 6.86:1 */

  /* kept for older rules that still name them */
  --warn: var(--block-ink);
  --err: var(--err-ink);

  /* type scale — five steps that are actually different (spec 21.5) */
  --t-micro: .8125rem;
  --t-small: .875rem;
  --t-body: 1rem;
  --t-head: 1.25rem;
  --t-title: 1.75rem;

  /* spacing scale */
  --s1: .25rem; --s2: .5rem; --s3: .75rem; --s4: 1rem; --s5: 1.5rem; --s6: 2rem;

  --radius: 6px;
}
* { box-sizing: border-box; }
body {
  margin: 0;
  font-family: Carlito, Calibri, "Segoe UI", system-ui, sans-serif;
  font-size: var(--t-body);
  color: var(--ink);
  background: var(--bg);
}
a { color: var(--blue); }                 /* one blue, not two (spec 21.7) */

/* Visible focus is not decoration; its absence is what feels unfinished (21.6). */
:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; border-radius: 3px; }

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s4); padding: var(--s3) var(--s5); background: #fff;
  border-bottom: 1px solid var(--line);
}
.topbar-slot { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
.brand img { height: 38px; display: block; }

/* Page width is a decision, not one number for everything (spec 21.5): a working
   screen with a wide table may use the space, a reading screen keeps its measure. */
.page { max-width: 68rem; margin: var(--s5) auto var(--s6); padding: 0 var(--s5); }
.page.wide { max-width: min(100rem, calc(100% - 3rem)); }
.footer { padding: var(--s4) var(--s5) var(--s6); color: var(--grey);
          font-size: var(--t-small); text-align: center; }

h1 { font-size: var(--t-title); margin: 0 0 var(--s1); line-height: 1.2; }
h2 { font-size: var(--t-head); margin: var(--s6) 0 var(--s3); }
h3 { font-size: var(--t-body); margin: var(--s5) 0 var(--s2); }
.sub { color: var(--grey); margin: 0 0 var(--s5); }
.hint { color: var(--grey); font-size: var(--t-small); }
/* The English half is a reading aid, not a second heading (spec 21.5). */
.en { color: var(--grey); font-weight: 400; font-size: .92em; }
h1 .en, h2 .en, h3 .en { font-size: .78em; }

.card { background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
        padding: var(--s5); margin-bottom: var(--s5); }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--s4); }
/* `max-content` never wraps, so a long label pushed the whole list out of its grid
   cell and printed over the next column (found in the browser, round 8). `auto` lets
   the label column shrink and the text wrap instead. */
.kv { display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr);
      gap: var(--s1) var(--s4); font-size: var(--t-small); }
.kv dt { color: var(--grey); overflow-wrap: break-word; }
.kv dd { margin: 0; }
/* A label that is a whole sentence takes the row to itself and puts its value
   underneath. In the two-column grid it ate the entire width and squeezed the value
   to **zero pixels** - the date was in the DOM and invisible on the screen (found in
   the browser, order 16.0 H). The same trap as the `max-content` overflow of round 8:
   a grid does not warn, it just gives the other column nothing. */
.kv .span { grid-column: 1 / -1; }

label { display: block; font-size: var(--t-small); margin-bottom: var(--s1); color: var(--ink); }
input[type=text], input[type=date], input[type=number], input[type=email],
input[type=password], select, textarea {
  width: 100%; padding: .4rem .55rem; min-height: 2.15rem; border: 1px solid var(--line);
  border-radius: 5px; font: inherit; font-size: var(--t-small); background: #fff;
}
input:hover, select:hover, textarea:hover { border-color: #c3c9ce; }

table { width: 100%; border-collapse: collapse; font-size: var(--t-small); }
th, td { text-align: left; padding: var(--s2) var(--s2); border-bottom: 1px solid var(--line);
         vertical-align: top; }
th { color: var(--grey); font-weight: 600; font-size: var(--t-micro); }
tbody tr:hover > td { background: #fafbfc; }       /* hover feedback (spec 21.6) */
td input:not([type="checkbox"]):not([type="radio"]), td select { min-width: 4.5rem; }

/* Emphasis follows state (spec 21.3): filled = the expected next action · outline =
   available but already done once · quiet = a secondary action such as Preview ·
   withdraw = an action that takes something back. The label always names the action;
   the state is the chip's job. */
.btn {
  display: inline-block; padding: .45rem .85rem; border-radius: 5px;
  border: 1px solid var(--blue); background: var(--blue); color: #fff;
  font: inherit; font-size: var(--t-small); cursor: pointer; text-decoration: none;
  line-height: 1.35;
}
.btn:hover { filter: brightness(1.08); }
.btn.outline, .btn.secondary { background: #fff; color: var(--blue); }
.btn.outline:hover, .btn.secondary:hover { background: #eef6fc; filter: none; }
.btn.quiet { background: transparent; border-color: transparent; color: var(--blue); }
.btn.quiet:hover { background: #eef6fc; filter: none; }
.btn.withdraw { background: #fff; border-color: var(--err-line); color: var(--err-ink); }
.btn.withdraw:hover { background: var(--err-bg); filter: none; }
.btn.small { padding: .2rem .5rem; font-size: var(--t-micro); }
/* A disabled control is still meant to be read - it says what will be possible once
   the preview has been opened, so it goes neutral rather than transparent. */
.btn[disabled] { background: var(--shade); border-color: var(--line); color: var(--grey);
                 cursor: not-allowed; filter: none; }
.actions { display: flex; gap: var(--s2); align-items: center; margin-top: var(--s4);
           flex-wrap: wrap; }
.actions form { margin: 0; }

/* Feedback is a block at the top of the content, and the page returns to the top after
   saving, submitting and uploading - so the message is where the eye already is
   (spec 21.4). Only *generate* moves the view to the row it produced. */
.notice { border: 1px solid var(--line); border-left: 3px solid var(--blue);
          border-radius: var(--radius); background: #fff; padding: var(--s3) var(--s4);
          margin-bottom: var(--s5); }
.notice.error { border-left-color: var(--err-ink); background: var(--err-bg); }
/* Order 35.0 H.4: success takes the green already defined for *done* (spec 21.2) -
   no fifth colour, the same one a green chip uses. The tick is drawn in CSS rather
   than pulled from an icon set: one character, no dependency. */
.notice.success { border-left-color: var(--done-line); background: var(--done-bg); }

/* Order 35.0 H.3: the upload belongs to its own row of fields; the line separates it
   from the buttons that end the whole form. Two forms in one card need the seam drawn,
   or every button reads as one group. */
.upload-action { margin-top: var(--s2); }
.card-rule { border: 0; border-top: 1px solid var(--line); margin: var(--s5) 0 var(--s4); }
.notice.success .msg::before {
  content: "\2713"; display: inline-flex; align-items: center; justify-content: center;
  width: 1.15rem; height: 1.15rem; margin-right: .5rem; border-radius: 50%;
  background: var(--done-ink); color: #fff; font-size: .7rem; font-weight: 700;
  vertical-align: -.15rem;
}
/* A condition that stands in the way but can be overridden - the *blocked* colour of
 * the four, not a fifth one (spec 21.2). */
.notice.blocked { border-left-color: var(--block-ink); background: var(--block-bg); }

.messages { list-style: none; padding: 0; margin: 0; }
.msg { padding: var(--s1) 0; }
.msg.success { color: var(--ink); }
.msg.error { color: var(--err-ink); }
.msg.warning { color: var(--block-ink); }
/* The row an action has just produced, so the eye finds it without searching. */
.just-created > td, tr.just-created > td { background: var(--ready-bg); }

/* Chips carry state (spec 12.11) and only state. Four meanings, one look each. */
.chip { display: inline-block; padding: .1rem .5rem; border-radius: 999px;
  font-size: var(--t-micro); border: 1px solid var(--line); background: #fff;
  color: var(--grey); white-space: nowrap; }
.chip.done { border-color: var(--done-line); background: var(--done-bg); color: var(--done-ink); }
.chip.ready { border-color: var(--ready-line); background: var(--ready-bg); color: var(--ready-ink); }
.chip.blocked { border-color: var(--block-line); background: var(--block-bg); color: var(--block-ink); }
.chip.error { border-color: var(--err-line); background: var(--err-bg); color: var(--err-ink); }
/* An attribute is not a status, so it recedes (spec 21.5). */
.chip.attr { background: var(--shade); border-color: var(--shade); color: var(--grey); }

/* `.badge` is the older name; keep it working and looking the same. */
.badge { display: inline-block; padding: .1rem .5rem; border-radius: 999px;
  font-size: var(--t-micro); border: 1px solid var(--line); background: #fff; color: var(--grey); }
.badge.ok { border-color: var(--done-line); background: var(--done-bg); color: var(--done-ink); }
.badge.warn { border-color: var(--block-line); background: var(--block-bg); color: var(--block-ink); }
.badge.info { border-color: #b9cdea; background: #eef4fc; color: #1b4f8a; }

.todo { margin: 0; padding-left: 1.1rem; }
.readonly-note { border-left: 3px solid var(--blue); }

/* dashboard + workspace */
/* A choice is not a state (spec 21.3): the mode filters had the status pill's shape,
   so the active one read as a green "OK". They are a segmented control now. */
.filters { display: inline-flex; margin-bottom: var(--s4); flex-wrap: wrap;
           border: 1px solid var(--line); border-radius: 5px; overflow: hidden;
           background: #fff; }
.filters a { text-decoration: none; padding: .3rem .75rem; font-size: var(--t-small);
             color: var(--ink); border-right: 1px solid var(--line); }
.filters a:last-child { border-right: 0; }
.filters a:hover { background: var(--shade); }
.filters a.active { background: var(--blue); color: #fff; }
/* How many shipments a customer filter would show - a figure, not an emphasis. */
.filter-count { color: var(--grey); font-size: var(--t-micro); }
.filters a.active .filter-count { color: #dceaf5; }

/* Sortable column headers (spec 15.1). A header is a control, so it reads as one -
   but quietly: the table is the content, the sorting is a way of looking at it. */
th a.sort { color: inherit; text-decoration: none; }
th a.sort:hover { text-decoration: underline; }
th a.sort.active { color: var(--blue); }
.sort-arrow { margin-left: .2rem; font-size: var(--t-micro); }

/* A shortfall is a link, not a number (spec 15.2): it jumps to the first sub-shipment
   the step is missing on. It keeps the colour of the count it stands in - what it says
   is "still missing", and that must not turn blue and read as an ordinary link. */
a.shortfall { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
a.shortfall:hover { text-decoration-thickness: 2px; }
table.dashboard th { white-space: nowrap; }
table.dashboard td { white-space: nowrap; }
table.dashboard td.wrap, table.dashboard th.wrap { white-space: normal; }
/* Deferred, not broken (spec 21.7): the column says which phase owns it. */
table.dashboard td.phase { color: var(--grey); }
.phase-tag { display: inline-block; margin-left: .25rem; padding: 0 .3rem; border-radius: 3px;
             background: var(--shade); color: var(--grey); font-size: .7rem; font-weight: 600; }
/* `.sub-head` was the card head until order 31.0 D.1 replaced it with `.card-top`. */
.inline-form { display: flex; gap: var(--s2); align-items: flex-end; flex-wrap: wrap; }
/* A chip, its timestamp and the button that sets it, on one centre line
   (order 30.0 L). `.inline-form` aligns to flex-end for the forms that carry a
   labelled input; here the neighbours are a chip and a hint, so the shared row
   centres instead. */
.row-controls { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
.row-controls .inline-form { align-items: center; }
.inline-form label { margin-bottom: 0; }
.inline-form input[type=text] { width: 14rem; }
/* A group of controls that belong together, separated from the next group. */
.control-group { display: flex; gap: var(--s2); align-items: flex-end; padding-right: var(--s5);
                 border-right: 1px solid var(--line); margin-right: var(--s3); }
.control-group:last-child { border-right: 0; padding-right: 0; margin-right: 0; }

/* supplier portal */
.formblock { border: 1px solid var(--line); }
.req { color: #b3261e; font-weight: 700; }
/* Order 34.0 I: Django renders field errors as `<ul class="errorlist">`, and no rule
   ever matched it - so *Required to submit.* stood in body text next to a red asterisk
   saying the same thing. Same red as `.req`. */
.errorlist { color: #b3261e; font-weight: 600; list-style: none;
             padding: 0; margin: .25rem 0 0; }
.reminder-note { border-left: 3px solid var(--warn); }
/* A hint the user has to act on, not just read - e.g. a stored pickup date that has
   passed and must be entered again (spec 5.4). */
.warn-hint { color: var(--warn); font-weight: 600; }
.col-del { width: 2.5rem; text-align: center; }
/* N10 / order 13.0 D9: a checkbox column is read left to right like every other
   column. Centring it put the box and its label out of line with the heading above
   and with the rest of the row, which is what made the table look unsettled. The
   trash column above stays centred: it is an icon, not a labelled value. */
.col-check { text-align: left; }
/* delete = a trash icon, the checkbox behind it stays for accessibility */
.trash { display: inline-flex; align-items: center; cursor: pointer; font-size: 1.15rem;
         color: var(--grey); line-height: 1; }
.trash input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.trash:hover { color: #b3261e; }
.trash:has(input:checked) { color: #b3261e; }
.trash input:focus-visible + span { outline: 2px solid var(--blue); outline-offset: 2px; }
tr:has(.trash input:checked) td { text-decoration: line-through; opacity: .55; }
/* A locked field must look locked (spec 21.7): after submission the supplier's fields
   were almost indistinguishable from open ones. */
fieldset[disabled] input, fieldset[disabled] select, fieldset[disabled] textarea {
  background: var(--shade); color: var(--grey); border-style: dashed; cursor: not-allowed; }
fieldset[disabled] .col-del, fieldset[disabled] .trash { display: none; }

/* submit summary + final data confirmation */
.error-summary { border-left: 3px solid #b3261e; background: #fdf2f2; }
.confirmation { border: 1px solid var(--line); border-radius: 6px; padding: 1rem; margin-bottom: 1rem; }
.confirmation-texts { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
.confirmation-text { font-size: .9rem; line-height: 1.45; }
.confirmation-text ul { margin: .4rem 0; padding-left: 1.1rem; }
.confirmation-text.en-block { color: var(--grey); border-left: 1px solid var(--line); padding-left: 1.5rem; }
.confirmation-inputs { margin-top: 1rem; border-top: 1px solid var(--line); padding-top: 1rem; }
.confirmation-inputs .checkline { margin: .75rem 0 .5rem; }
.confirmation-inputs .checkline label { display: inline; }
.radio-row ul { list-style: none; display: flex; gap: 1.25rem; margin: 0; padding: 0; }
.radio-row label { display: inline-flex; align-items: center; gap: .35rem; }
@media (max-width: 780px) { .confirmation-texts { grid-template-columns: 1fr; }
  .confirmation-text.en-block { border-left: 0; padding-left: 0; } }

/* The Cost module is one card with three sections inside it (spec 10.9, order 19.0 D).
   The rule between sections is what keeps them read as parts of one thing rather than
   as three cards that happen to touch. */
.cost-module .cost-section + .cost-section { margin-top: var(--s5); padding-top: var(--s5);
                                             border-top: 1px solid var(--line); }
.cost-module .cost-section h3 { margin-top: 0; }
/* A row nobody has priced yet: present, and visibly not a figure (spec 10.10). */
.cost-module tr.placeholder td { color: var(--grey); }

/* The signature preview on the mail draft page (spec 13.3 / V3). The block itself
   carries inline styles, because a mail client applies no stylesheet - this only frames
   it so it reads as a preview of something rather than as part of the form. */
.signature-preview { border: 1px solid var(--line); border-radius: var(--radius);
                     background: #fff; padding: var(--s4); margin-bottom: var(--s4); }
/* The interface's own table rules - full width, a rule under every row - would draw
   the preview as a data table and show CJH a signature that looks nothing like the
   one that goes out. A mail client applies none of them. */
.signature-preview table { width: auto; font-size: inherit; }
.signature-preview td { border: 0; }

/* supplier-declared deviation (spec 5.3.1) */
.deviation-alert { border: 2px solid #b3261e; background: #fdf2f2; }
.deviation-alert h2 { margin-top: 0; color: #b3261e; }
.deviation-text { font-size: 1.05rem; white-space: pre-wrap; }

/* Action cells hold a preview link plus a small form; they must not stretch the row. */
.col-actions { white-space: nowrap; }
.col-actions .btn, .col-actions form { display: inline-block; vertical-align: middle;
                                       margin: 0 0.15rem 0.15rem 0; }

/* Pickup-location details in the supplier portal (spec 5.3). */
.pickup-details { margin-top: 0.6rem; padding: 0.6rem 0.8rem; border-left: 3px solid #1b4f8a;
                  background: #f4f7fb; font-size: 0.92rem; }
.pickup-details p { margin: 0 0 0.35rem; }
.pickup-details p:last-child { margin-bottom: 0; }

/* The sub-shipments an invoice or an ABD covers (spec 5.10 / 8.10.1): a checkbox and
   its ID belong together on one line, and several of them read as a row, not a stack.

   Order 14.1 C6 / spec 21.6: **the label sits directly at its box.** Django wraps each
   option in a `<div>` of its own; as a plain flex item that div stretched well past its
   content, leaving more empty space after a label than between the label and its own
   box - so the eye paired each caption with the *next* checkbox. `max-content` stops
   the stretch, and the row gap is wider than the box-to-label gap, which is what makes
   the grouping unambiguous. */
/* Order 36.0 K: **one per line.** Wrapping packed two or three sub-shipment IDs onto
   a line or spread them over two depending on the width, and a tick belonging to the
   ID beside it rather than above it is read wrong once and then always. */
.col-check > div { display: flex; flex-direction: column; gap: .15rem; }
.col-check > div > div { display: flex; width: max-content; }
.col-check label { display: inline-flex; align-items: center; gap: .35rem;
  white-space: nowrap; margin: 0; width: max-content; }
.col-check input[type=checkbox] { margin: 0; }

/* Status chips of spec 12.11 - meaning, never decoration. The tokens behind them
   arrive with the visual system of spec 21. */
.chip { display: inline-block; padding: .15rem .5rem; border-radius: 999px;
  font-size: .8rem; border: 1px solid var(--line); background: #fff; color: var(--grey); }
.chip.done { border-color: #b7d8b7; background: #f1f9f1; color: #2f6b31; }
.chip.ready { border-color: #e3d08a; background: #fdf8e7; color: #6b5a12; }
.chip.blocked { border-color: #e8c2a0; background: #fdf3ea; color: #8a4b12; }

/* Why an approval fell by itself (spec 5.8, order 14.2 A2). It explains the chip above
   it, so it recedes behind it - a note, not a second state. */
.reset-note { margin: .15rem 0 0; font-size: var(--t-micro); color: var(--block-ink); }

/* The sentence that says why a sub-shipment does not go on (spec 21.7). */
.blocking { margin: var(--s3) 0; color: var(--block-ink); font-size: var(--t-small); }
.blocking .chip { margin-right: var(--s2); }

/* The delivery address (spec 7.8) is read as a postal block, line by line, on the
   screens - the compact `city, country` form belongs on the exports (spec 8.1). */
.delivery-address { line-height: 1.5; margin: 0 0 var(--s3); }

/* The counted "still missing" list of the agent checkpoint (spec 8.10.1). Colour
   carries meaning here as everywhere else: done green, outstanding orange. */
.ok-count { color: var(--done-ink); }
.missing-count { color: var(--block-ink); font-weight: 600; }


/* Collapsible sections (order 30.0 I, order 31.0 C).
 *
 * The browser's own marker is a few pixels wide and easy to miss on a page this dense,
 * so it is replaced by one triangle at a readable size - the same one on every level,
 * because two sizes in one view read as two different mechanisms.
 *
 * The heading keeps its own element inside the summary: `<summary><h2>` is what makes
 * the section title still a title for a screen reader, and `display: inline` is what
 * keeps it on the summary's own line.
 */
summary { list-style: none; cursor: pointer; display: flex; align-items: center;
          gap: var(--s2); }
summary::-webkit-details-marker { display: none; }
/* Order 39.0 L / decision CA4: the **full** triangle (U+25B6) instead of the small one
   (U+25B8). The small glyph fills about a third of its em box, so raising its font size
   made the box taller and the triangle barely larger - measured, 28px still drew a
   10px mark. At 1rem the full triangle draws about 13px, which reads as the control
   at a glance next to a 20px h2 and stays smaller than the title it opens. One size on
   every level, h2 and h3 alike (the rule of 30.0 I); the flex centring keeps it on the
   heading's middle. */
summary::before { content: "\25B6"; font-size: 1rem; line-height: 1;
                  color: var(--grey); transition: transform .12s ease; }
details[open] > summary::before { transform: rotate(90deg); }
summary > h2, summary > h3 { display: inline; margin: 0; }
/* A closed section keeps the gap a card leaves (CA4) - two closed summaries stood 0px
   apart and read as one block. An open one gets that gap from the card inside it. */
.page > details:not([open]) { margin-bottom: var(--s5); }
.page > details > summary { margin-bottom: var(--s3); }

/* A sortable cost-lines heading (order 31.0 B): a button that looks like the heading
   it replaces, not like a control dropped into the row. */
th button.sort { background: none; border: 0; padding: 0; font: inherit; color: inherit;
                 cursor: pointer; display: inline-flex; align-items: center; gap: .3em; }
th button.sort [data-arrow] { color: var(--grey); font-size: .9em; }

/* The sub-shipment card (order 31.0 D), following the v2 reference design.
 *
 * The shape it enforces: identity and context left, the end-state badge right, then
 * what blocks, then two folds and one status line carrying the single highlighted next
 * step. Everything else lives behind *All details* — including what is still locked,
 * which stays visible because a card that hides the road ahead says nothing about it.
 */
.card-top { display: flex; flex-wrap: wrap; align-items: center;
            justify-content: space-between; gap: var(--s2) var(--s3); }
.card-top-left { display: flex; flex-wrap: wrap; align-items: center; gap: 7px 9px; }
.card-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.card-dot { color: var(--grey); }

/* The badge is the one green thing on a quiet card, so it is the one that carries
   weight. Only the three end states reach it (spec 12.11). */
.card-badge { flex-shrink: 0; border-radius: 999px; padding: 3px 11px;
              font-size: 11.5px; font-weight: 700; white-space: nowrap;
              border: 1px solid var(--done-line); color: var(--done-ink);
              background: var(--done-bg); }

.blocked-note { display: flex; align-items: center; gap: var(--s2); margin-top: var(--s3);
                font-size: 12.5px; }

.details-toggle { font: inherit; font-size: 12px; font-weight: 600; color: var(--grey);
                  background: none; border: 0; padding: 0; margin-top: var(--s3);
                  cursor: pointer; display: inline-flex; align-items: center; gap: 5px; }
/* The in-card fold "9 more fields" is a button inside a 12px line, not a section (CA4):
   the same full triangle as the sections, at the size of its own line (0.85em, about
   8px drawn), because a 13px mark would outgrow the words beside it. */
.details-toggle .chev { display: inline-block; font-size: .85em; line-height: 1;
                        transition: transform .12s ease; }
.details-toggle[aria-expanded="true"] .chev { transform: rotate(90deg); }
.context-grid { margin-top: var(--s2); padding: var(--s3) 0;
                border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }

/* `hidden` must beat every display rule. The context grid also carries `.grid`, whose
   `display: grid` outranks the browser's own `[hidden]` by source order - so the fold
   reported `aria-expanded="false"` and `hidden`, and showed its nine fields anyway.
   Attributes said closed, pixels said open; only the screenshot caught it. */
[hidden] { display: none !important; }

.actionrow { display: flex; align-items: center; gap: var(--s3); margin-top: var(--s3);
             flex-wrap: wrap; }
.actionrow .grow { flex: 1; }

/* ~26px circles, a tick when done and an empty ring when not - no captions, because a
   row of four labels would be longer than the card it summarises (order 31.0 D.2). */
.dots { display: flex; gap: 6px; align-items: center; flex-shrink: 0; }
.dots .dot { width: 26px; height: 26px; border-radius: 50%; display: flex;
             align-items: center; justify-content: center; flex-shrink: 0;
             border: 1.5px solid var(--line); background: #fff;
             font-size: 13px; line-height: 1; }
.dots .dot.done { background: var(--done-bg); border-color: var(--done-line);
                  color: var(--done-ink); }

.overflow-btn { font: inherit; font-size: 12px; font-weight: 600; color: var(--grey);
                background: #f5f6f8; border: 1px solid var(--line);
                border-radius: 7px;
                padding: 8px 11px; cursor: pointer; flex-shrink: 0; }
.overflow-panel { margin-top: var(--s3); padding-top: var(--s3);
                  border-top: 1px dashed var(--line); }
.overflow-label { font-size: 11px; color: var(--grey); font-weight: 600;
                  text-transform: uppercase; letter-spacing: .04em; margin-top: var(--s3); }
.locked-zone { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s2); }
/* Order 34.0 M: the container picker holds `C1 40'HC` and nothing longer, but it sat
   in a grid column and stretched to fill it, pushing the RFQ carrier block off its
   line. A field is as wide as its content (spec 21.6). */
.container-pick { max-width: 16rem; }

.locked-item { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px;
               color: #a3aab5; background: #eef0f3; border: 1px solid #dde1e7;
               border-radius: 7px; padding: 5px 10px; }
/* The reason is the point of the section: a lock without a why sends CJH looking. It
   stood in a `title` only, where nothing on a touch screen ever reads it. */
.locked-why { color: #8b929c; }
.locked-why::before { content: "\2014\00a0"; }

/* Visible to a screen reader, absent from the page - the dots carry their meaning in
   a title and in this, never in printed text (spec 21.6). */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
           overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
