/* GENERATED FILE. Do not hand-edit: run `scripts/build_css.py`.

 * Source: app/lib/design.py. See that module and this script's

 * own docstring for what governs each section below. */

:root {
  --tde-anchor: #1E3A8A;
  --tde-background: #F8FAFC;
  --tde-breach: #c62828;
  --tde-button-edge: #1E3A8A;
  --tde-button-fill: #1E3A8A;
  --tde-button-text: #FFFFFF;
  --tde-canvas: #F3F6FA;
  --tde-focus-inner: #0F172A;
  --tde-focus-ring: #F9A825;
  --tde-hairline: #E2E8F0;
  --tde-holds: #2e7d32;
  --tde-ink: #0F172A;
  --tde-input-edge: #475569;
  --tde-input-fill: #FFFFFF;
  --tde-judgement: #A76700;
  --tde-muted: #475569;
  --tde-on-anchor: #C7D6F5;
  --tde-on-ink: #8C96A6;
  --tde-panel-edge: #475569;
  --tde-signal: #F9A825;
  --tde-surface: #FFFFFF;
  --tde-tint-field: #FFFBF1;
  --tde-scheme-anchor-field-bg: #1E3A8A;
  --tde-scheme-anchor-field-fg: #FFFFFF;
  --tde-scheme-anchor-field-fg-secondary: #C7D6F5;
  --tde-scheme-canvas-field-bg: #F3F6FA;
  --tde-scheme-canvas-field-fg: #0F172A;
  --tde-scheme-canvas-field-fg-secondary: #475569;
  --tde-scheme-ink-field-bg: #0F172A;
  --tde-scheme-ink-field-fg: #FFFFFF;
  --tde-scheme-ink-field-fg-secondary: #8C96A6;
  --tde-scheme-signal-field-bg: #F9A825;
  --tde-scheme-signal-field-fg: #0F172A;
  --tde-scheme-signal-field-fg-secondary: #0F172A;
  color-scheme: light dark;
  --tde-anchor-hover: #15285F;
  --tde-pill-border-bad: #c6282833;
  --tde-pill-border-good: #2e7d3233;
  --tde-pill-border-info: #1E3A8A33;
  --tde-pill-border-neutral: #47556933;
  --tde-pill-border-watch: #A84B0033;
  --tde-pill-tint: #F1F5F9;
  --tde-scroll-shade: #47556959;
  --tde-watch-ink: #A84B00;
  --tde-space-1: 4px;
  --tde-space-2: 8px;
  --tde-space-3: 12px;
  --tde-space-4: 16px;
  --tde-space-5: 24px;
  --tde-space-6: 32px;
  --tde-space-7: 48px;
  --tde-space-8: 64px;
  --tde-space-9: 96px;
}

@media (prefers-color-scheme: dark) {

:root:not([data-tde-theme="light"]) {
  --tde-anchor: #4F73D9;
  --tde-background: #030507;
  --tde-breach: #D94141;
  --tde-button-edge: #4F73D9;
  --tde-button-fill: #4F73D9;
  --tde-button-text: #000000;
  --tde-canvas: #05080C;
  --tde-focus-inner: #D5DDF0;
  --tde-focus-ring: #F9A825;
  --tde-hairline: #0F151D;
  --tde-holds: #328836;
  --tde-ink: #D5DDF0;
  --tde-input-edge: #96A4B8;
  --tde-input-fill: #0F172A;
  --tde-judgement: #A76700;
  --tde-muted: #96A4B8;
  --tde-on-anchor: #C7D6F5;
  --tde-on-ink: #8C96A6;
  --tde-panel-edge: #96A4B8;
  --tde-signal: #F9A825;
  --tde-surface: #000000;
  --tde-tint-field: #FFFBF1;
  --tde-scheme-anchor-field-bg: #1E3A8A;
  --tde-scheme-anchor-field-fg: #FFFFFF;
  --tde-scheme-anchor-field-fg-secondary: #C7D6F5;
  --tde-scheme-canvas-field-bg: #05080C;
  --tde-scheme-canvas-field-fg: #D5DDF0;
  --tde-scheme-canvas-field-fg-secondary: #96A4B8;
  --tde-scheme-ink-field-bg: #0F172A;
  --tde-scheme-ink-field-fg: #FFFFFF;
  --tde-scheme-ink-field-fg-secondary: #8C96A6;
  --tde-scheme-signal-field-bg: #F9A825;
  --tde-scheme-signal-field-fg: #0F172A;
  --tde-scheme-signal-field-fg-secondary: #0F172A;
  --tde-anchor-hover: #A0B3EA;
  --tde-scroll-shade: #96A4B859;
}

}

:root[data-tde-theme="dark"] {
  color-scheme: dark;
  --tde-anchor: #4F73D9;
  --tde-background: #030507;
  --tde-breach: #D94141;
  --tde-button-edge: #4F73D9;
  --tde-button-fill: #4F73D9;
  --tde-button-text: #000000;
  --tde-canvas: #05080C;
  --tde-focus-inner: #D5DDF0;
  --tde-focus-ring: #F9A825;
  --tde-hairline: #0F151D;
  --tde-holds: #328836;
  --tde-ink: #D5DDF0;
  --tde-input-edge: #96A4B8;
  --tde-input-fill: #0F172A;
  --tde-judgement: #A76700;
  --tde-muted: #96A4B8;
  --tde-on-anchor: #C7D6F5;
  --tde-on-ink: #8C96A6;
  --tde-panel-edge: #96A4B8;
  --tde-signal: #F9A825;
  --tde-surface: #000000;
  --tde-tint-field: #FFFBF1;
  --tde-scheme-anchor-field-bg: #1E3A8A;
  --tde-scheme-anchor-field-fg: #FFFFFF;
  --tde-scheme-anchor-field-fg-secondary: #C7D6F5;
  --tde-scheme-canvas-field-bg: #05080C;
  --tde-scheme-canvas-field-fg: #D5DDF0;
  --tde-scheme-canvas-field-fg-secondary: #96A4B8;
  --tde-scheme-ink-field-bg: #0F172A;
  --tde-scheme-ink-field-fg: #FFFFFF;
  --tde-scheme-ink-field-fg-secondary: #8C96A6;
  --tde-scheme-signal-field-bg: #F9A825;
  --tde-scheme-signal-field-fg: #0F172A;
  --tde-scheme-signal-field-fg-secondary: #0F172A;
  --tde-anchor-hover: #A0B3EA;
  --tde-scroll-shade: #96A4B859;
}
:root[data-tde-theme="light"] { color-scheme: light; }

.tde-type-display_hero { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 700; font-size: 148px; letter-spacing: -0.05em; line-height: 1.0; overflow-wrap: anywhere; }
.tde-type-display_section_large { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 700; font-size: 92px; letter-spacing: -0.035em; line-height: 1.0; overflow-wrap: anywhere; }
.tde-type-display_section_small { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 700; font-size: 72px; letter-spacing: -0.035em; line-height: 1.0; overflow-wrap: anywhere; }
.tde-type-one_number_min { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 700; font-size: 168px; letter-spacing: -0.055em; line-height: 1.0; }
.tde-type-one_number_max { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 700; font-size: 300px; letter-spacing: -0.055em; line-height: 1.0; }
.tde-type-body_large { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 400; font-size: 27px; letter-spacing: 0; line-height: 1.55; }
.tde-type-body_small { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 400; font-size: 21px; letter-spacing: 0; line-height: 1.45; }
.tde-type-small { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 400; font-size: 19px; letter-spacing: 0; line-height: 1.45; }
.tde-type-app_floor { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 400; font-size: 17px; letter-spacing: 0; line-height: 1.45; }
.tde-type-stamp_large { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 700; font-size: 24px; letter-spacing: .11em; line-height: 1.0; text-transform: uppercase; }
.tde-type-stamp_small { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 700; font-size: 18px; letter-spacing: .11em; line-height: 1.0; text-transform: uppercase; }

.tde-one-number {
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    font-weight: 700;
    font-size: clamp(56px, calc(59.4px + 5.3vw), 300px);
    letter-spacing: -0.055em;
    line-height: 1.0;
    font-variant-numeric: tabular-nums;
    /* KEEL PHONE VERDICT: measured at 375px, the verdict sentence reported
       303px inside a 301px box. A long word at a display size has nowhere
       to break unless it is told it may. */
    overflow-wrap: anywhere;
}

.tde-field-anchor { background: var(--tde-scheme-anchor-field-bg); color: var(--tde-scheme-anchor-field-fg); --tde-ground: var(--tde-scheme-anchor-field-bg); }
.tde-field-anchor .tde-field-secondary { color: var(--tde-scheme-anchor-field-fg-secondary); }
.tde-field-anchor > * { --tde-panel-edge: var(--tde-scheme-anchor-field-fg-secondary); }
.tde-field-canvas { background: var(--tde-scheme-canvas-field-bg); color: var(--tde-scheme-canvas-field-fg); --tde-ground: var(--tde-scheme-canvas-field-bg); }
.tde-field-canvas .tde-field-secondary { color: var(--tde-scheme-canvas-field-fg-secondary); }
.tde-field-ink { background: var(--tde-scheme-ink-field-bg); color: var(--tde-scheme-ink-field-fg); --tde-ground: var(--tde-scheme-ink-field-bg); }
.tde-field-ink .tde-field-secondary { color: var(--tde-scheme-ink-field-fg-secondary); }
.tde-field-ink > * { --tde-panel-edge: var(--tde-scheme-ink-field-fg-secondary); }
.tde-field-signal { background: var(--tde-scheme-signal-field-bg); color: var(--tde-scheme-signal-field-fg); --tde-ground: var(--tde-scheme-signal-field-bg); }
.tde-field-signal .tde-field-secondary { color: var(--tde-scheme-signal-field-fg-secondary); }
.tde-field-signal > * { --tde-panel-edge: var(--tde-scheme-signal-field-fg-secondary); }

body { margin: 0; background: var(--tde-background); color: var(--tde-ink);
       --tde-ground: var(--tde-background);
       font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.55; }
main { max-width: 46rem; margin: 0 auto; padding: 1.25rem 1.25rem 4rem; }
header { display: flex; align-items: center; justify-content: flex-end;
         gap: 16px; margin-bottom: .75rem; }
.eyebrow { text-align: right; font-size: .75rem; letter-spacing: .04em;
           text-transform: uppercase; color: var(--tde-muted); }
.tde-mark {
    position: relative;
    display: inline-grid;
    place-items: center;
    width: 26px;
    height: 26px;
    border-radius: 6px;
    background: var(--tde-signal);
    flex: none;
}
.tde-mark::before {
    content: "";
    position: absolute;
    width: 12px;
    height: 12px;
    border: 1.6px solid var(--tde-ink);
    border-radius: 50%;
}
.tde-mark::after {
    content: "";
    position: absolute;
    width: 18.5px;
    height: 1.6px;
    background: var(--tde-ink);
}
/* KEEL PHONE VERDICT, 2026-09-20: the heading scales instead of stepping.
   48px on a 375px screen, starting 463px down, was the Commander's "the font
   is too large"; 88px on a desktop is unchanged. The derivation of the three
   numbers below, and why the tracking loosens at the phone end, is in
   `design.H1_CLAMP_*`'s own comment. */
h1 { font-size: clamp(34px,
       calc(11.6px + 5.97vw),
       88px);
     line-height: 1.05; font-weight: 700;
     margin: 0 0 .35rem; letter-spacing: -0.035em; overflow-wrap: anywhere; }
.muted { color: var(--tde-muted); font-size: .875rem; }
.card { border: 1px solid var(--tde-panel-edge); border-radius: .5rem;
        background: var(--tde-surface); color: var(--tde-ink);
        padding: 1rem 1.25rem; margin: 1rem 0; --tde-ground: var(--tde-surface); }
/* A fieldset (the currency choice on /settings and /start) is a boxed group like a
   card: the browser's own faint groove is under 3:1 against the page (B36 round 3). */
fieldset { border: 1px solid var(--tde-panel-edge); border-radius: .5rem; }
.card .value { font-size: 1.75rem; font-weight: 600; letter-spacing: -0.02em; }
.label { color: var(--tde-muted); font-size: .875rem; }
.tag { display: inline-block; font-size: .6875rem; letter-spacing: .04em;
       text-transform: uppercase; color: var(--tde-muted);
       border: 1px solid var(--tde-panel-edge); border-radius: .25rem;
       padding: .05rem .35rem; }
.tde-field-anchor a { color: var(--tde-scheme-anchor-field-fg); }
.tde-field-anchor .tag { color: var(--tde-scheme-anchor-field-fg-secondary); }
.holds { border-left: 4px solid var(--tde-holds); }
.bends { border-left: 4px solid var(--tde-breach); }
/* THE PRE-COMMITMENT SCORECARD (P44) AND ITS ONE LIGHT (P22), his rulings of 20
   and 21 September 2026: "each row lit green, amber or red, the single light
   above them". A round mark before the status WORD, in the palette's own three
   status colours (breach, holds, the one accent amber); the word always stays,
   so print, a screen reader and a colour-blind reader lose nothing. */
.tde-scorecard-light { margin: 0 0 6px 0; font-size: 1.15rem; }
.tde-scorecard-light strong::before, .tde-scorecard-row strong::before {
  content: ""; display: inline-block; border-radius: 50%; margin-right: 8px;
  vertical-align: middle; background: var(--tde-muted); }
.tde-scorecard-light strong::before { width: 18px; height: 18px; }
.tde-scorecard-row strong::before { width: 10px; height: 10px; }
.tde-scorecard-light-red strong::before, .tde-scorecard-red strong::before,
.tde-scorecard-hold strong::before { background: var(--tde-breach); }
.tde-scorecard-light-amber strong::before, .tde-scorecard-amber strong::before,
.tde-scorecard-review strong::before, .tde-scorecard-partial strong::before,
.tde-scorecard-unknown strong::before { background: var(--tde-signal); }
.tde-scorecard-light-green strong::before, .tde-scorecard-green strong::before,
.tde-scorecard-proceed strong::before, .tde-scorecard-calculated strong::before {
  background: var(--tde-holds); }
.tde-scorecard-rows td p { margin: 4px 0 0 0; }
.tde-scorecard-rows td p .tde-caption { font-size: inherit; }
/* P26: the "?" disclosure beside a figure's value. A small round mark; open, its
   sentence sits under the row at the type floor (17px, declared: an undeclared
   size inherited 16px, the auditor, 22 September 2026). */
/* The mark sits on the figure's own line: the disclosure follows the row in
   the markup (so the naming guard reads the row alone) and is pulled up into
   the row's bottom padding, right-aligned, with the sentence dropping below. */
.tde-figure-explain { display: inline-block; margin-left: 6px; vertical-align: middle; }
.tde-figure-explain[open] { display: block; margin-left: 0; }
.tde-figure-explain p { text-align: left; }
.tde-figure-explain summary { list-style: none; cursor: pointer; display: inline-block;
  width: 24px; height: 24px; line-height: 24px; text-align: center; border-radius: 50%;
  border: 1px solid var(--tde-panel-edge); color: var(--tde-muted); }
.tde-figure-explain summary::-webkit-details-marker { display: none; }
.tde-figure-explain[open] summary { background: var(--tde-tint-field); }
.tde-figure-explain summary { font-size: 17px; }
.tde-figure-explain p { margin: 4px 0 0 0; color: var(--tde-muted); font-size: 17px; }
/* 12 October 2026 (the auditor's HOLD on border-vat, item 7): an open explanation sits in a figure
   cell that does not wrap, so its sentence ran on to 1510px at a 1280 screen. The sentence wraps,
   and its line is capped in characters, which a table cell cannot stretch. */
.tde-figure-explain[open] p { white-space: normal; overflow-wrap: anywhere; max-width: 46ch; }
/* The cash floor's slider fills its cell, under its number box. */
table.tde td input[type=range] { width: 100%; margin-top: 6px; }
/* A range input draws no border of its own, and the inputs guard
   (`tests/test_shell_inputs_nav.py`) holds every input to a visible edge at
   3:1, which the Decision page's slider failed on Linux, 22 September 2026.
   The same edge every text box has, so the control reads as a control. */
input[type=range] { border: 1px solid var(--tde-input-edge); border-radius: 6px; padding: 6px 4px;
  background: var(--tde-input-fill); box-sizing: border-box; }
input[type=range]:focus-visible { outline: 3px solid var(--tde-focus-ring); outline-offset: 2px; }
ul { padding-left: 1.15rem; }
a { color: var(--tde-anchor); }
a:hover { color: var(--tde-anchor-hover); }
label { display: block; margin-bottom: .2rem; }
input[type=text] { width: 14rem; max-width: 100%; padding: .4rem .55rem; border: 2px solid var(--tde-input-edge); border-radius: .25rem; font-size: 1rem; font-family: inherit; color: var(--tde-ink); background: var(--tde-input-fill); }
/* KEEL LAID wave 3b, keel-shell-inputs-nav, 2026-09-15: the number, email and
   search boxes and every textarea carried no rule at all, so the browser drew
   its own thin grey edge (measured: sales_text's focus ring was the browser's
   own 1px). The same box as input[type=text], its type at the 17px floor. */
input[type=number], input[type=email], input[type=search], textarea {
  padding: .4rem .55rem; border: 2px solid var(--tde-input-edge); border-radius: .25rem; font-size: 17px; font-family: inherit; color: var(--tde-ink); background: var(--tde-input-fill); }
:is(input, select, textarea):focus,
:is(input, select, textarea)[tabindex]:focus { outline: 3px solid var(--tde-focus-ring); outline-offset: 0; box-shadow: inset 0 0 0 2px var(--tde-focus-inner); }
/* A checkbox or radio is drawn by the browser and has no fill for the inner
   ring to change, so its ring is the ink one, outside the box. */
:is(input[type=checkbox], input[type=radio]):focus {
  outline: 3px solid var(--tde-focus-inner); outline-offset: 2px; box-shadow: none; }
/* KEEL LAID wave 3b, keel-light-legibility, 2026-09-15, defect 3: a bare
   select carried no width rule, so the browser sized it to its longest
   option text - the Incoterm select on /costs, 482px, pushed the page to
   523px wide at a 390px viewport. Same fixed width, shrink floor and border
   as input[type=text] above, never a second typed copy of the box.
   Wave 3 close, 2026-09-15: the select's type is set at the 17px floor, not
   the shared field box's 1rem (16px), which would have added a fourth 1rem
   declaration under the floor (tests/test_type_floor.py). */
select { width: 14rem; max-width: 100%; padding: .4rem .55rem; border: 2px solid var(--tde-input-edge); border-radius: .25rem; font-size: 17px; font-family: inherit; color: var(--tde-ink); background: var(--tde-input-fill); }
table.tde td input[type=text] { width: 8rem; }
table.tde td.tde-usedby, table.tde th.tde-usedby { white-space: nowrap; }
table.tde.tde-figures td:first-child, table.tde.tde-figures th:first-child { min-width: 11rem; }
.products-desc-field { width: 14rem; max-width: 100%; padding: .4rem .55rem; border: 2px solid var(--tde-input-edge); border-radius: .25rem; font-size: 1rem; font-family: inherit; color: var(--tde-ink); background: var(--tde-input-fill);
  resize: vertical; }
button { font-family: inherit; font-size: 1rem; padding: .55rem 1.1rem;
         border-radius: .35rem; border: 1px solid var(--tde-button-edge);
         background: var(--tde-button-fill); color: var(--tde-button-text); cursor: pointer; }
button:hover { background: var(--tde-anchor-hover); border-color: var(--tde-anchor-hover); }
/* KEEL LAID keel-live-defects-0916, 2026-09-16, defect 1: a class written for a
   link (.tde-next-step sets the link colour and an underline) on a filled
   button drew the label in the fill, 1:1 ("Use this quote", /navigator/quotes).
   A button's label is always the button's own token. */
button.tde-next-step { color: var(--tde-button-text); text-decoration: none; }
.field { margin: 0 0 .85rem; }
details.tde-group > summary { border-bottom: 1px solid var(--tde-hairline);
  padding-bottom: .5rem; cursor: pointer; }
hr.tde-rule { border: none; border-top: 1px solid var(--tde-hairline); margin: 1rem 0; }
.tde-summary-count { color: var(--tde-muted); font-size: .8125rem; font-weight: 400;
  margin-left: .4rem; }
.choices { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
           gap: .75rem; margin: .75rem 0 1.5rem; }
.choices > .card { margin: 0; }
.choices > .card p { margin: .35rem 0; }
a.choice { display: block; border: 1px solid var(--tde-panel-edge); border-radius: .5rem;
           background: var(--tde-surface); padding: 1rem 1.25rem; text-decoration: none;
           --tde-ground: var(--tde-surface);
           color: var(--tde-ink); }
a.choice:hover, a.choice:focus-visible { border-color: var(--tde-anchor); }
a.choice strong { display: block; color: var(--tde-anchor); text-decoration: underline;
                   margin-bottom: .25rem; }
a.choice .muted { display: block; }
.choice-eyebrow { font-size: .75rem; letter-spacing: .04em; text-transform: uppercase;
                   color: var(--tde-muted); margin: 0 0 .25rem; }
footer { margin-top: 2.5rem; font-size: .8125rem; color: var(--tde-muted); }
.tde-saved { display: none; margin-left: .5rem; font-size: .8125rem;
             font-weight: 600; color: var(--tde-holds); }
.tde-saved-show { display: inline; }
/* KEEL LAID keel-table-boundaries, 2026-09-21, his order (section 6 of
   docs/keel_laid/orders/2026-09-21_his_repeals_and_the_feature_register.md):
   "for the love of god, use boundaries in tables." Every rule between rows
   AND columns, in both themes, at every width - a design.py/stylesheet job
   done once, not per page. Before this: a body row's rule was
   `--tde-hairline`, measured (`design.contrast_ratio`) at 1.23:1 against
   SURFACE, 1.14:1 against CANVAS, 1.18:1 against BACKGROUND in light and
   about 1.1:1 on every dark surface - the SAME figures `PANEL_EDGE`'s own
   comment above already recorded for a card's edge, because HAIRLINE is "the
   rule between two figures, nothing else" (the handoff's palette table), not
   a boundary a reader can see. `--tde-panel-edge` (MUTED) is the token that
   comment already chose for a visible edge: 7.24-7.58:1 in light and
   7.9-8.3:1 in dark against every surface a table sits on - no new hex, the
   same token the header row and every card/panel edge already draws with.
   `border-collapse: collapse` (already set) means giving every cell a full
   border does not widen the table: collapsed borders share the grid line
   instead of adding to it, so column rules cost no extra px.
   THE WIDTHS FOLLOW THE HANDOFF'S OWN GEOMETRY, not a number picked here:
   `docs/design_handoff/README.md`'s "Rules" line reads "1px hairline between
   figures; 3px between columns; 4-6px for a limit or a section boundary" -
   row rules stay 1px, column rules are 3px, both now in the visible token
   rather than the one the handoff itself only ever names for figures. */
table.tde { border-collapse: collapse; width: 100%; margin: .75rem 0 1rem;
            font-size: .9375rem; font-variant-numeric: tabular-nums;
            border: 1px solid var(--tde-panel-edge); }
table.tde th, table.tde td { padding: .45rem .6rem; text-align: left;
            border-top: 1px solid var(--tde-panel-edge);
            border-bottom: 1px solid var(--tde-panel-edge);
            border-left: 3px solid var(--tde-panel-edge);
            border-right: 3px solid var(--tde-panel-edge); vertical-align: top; }
table.tde th { color: var(--tde-muted); font-weight: 500; font-size: .8125rem;
            letter-spacing: .02em; text-transform: uppercase; }
table.tde td.num, table.tde th.num { text-align: right; }
/* `table.ledger` (the glossary): the same boundaries, from the ONE stylesheet
   (his ruling, 21 September: "a stylesheet job done once, not per page"). The
   page keeps only its own spacing and its term column; the rules are here. */
table.ledger { border-collapse: collapse; border: 1px solid var(--tde-panel-edge); }
table.ledger th, table.ledger td {
            border-top: 1px solid var(--tde-panel-edge);
            border-bottom: 1px solid var(--tde-panel-edge);
            border-left: 3px solid var(--tde-panel-edge);
            border-right: 3px solid var(--tde-panel-edge); }
table.tde tr.total td { border-top: 3px solid var(--tde-ink); font-weight: 700; }
table.tde td.neg { color: var(--tde-breach); }
table.tde td.pos { color: var(--tde-holds); }
/* KEEL LAID keel-live-defects-0916, 2026-09-16, defect 4: a wide table already
   scrolled inside its wrap, but behind an OVERLAY scrollbar, which is the
   macOS default in the Commander's own browser: it appears only while
   scrolling, so he saw "SUPPLIER COU" and "MINIMUM O" cut with nothing saying
   there was more. Measured here: a styled ::-webkit-scrollbar still took no
   room in Chromium (offsetHeight equalled clientHeight). So the affordance is
   drawn by the page itself and cannot depend on the platform: a shade at each
   edge that is there while content is hidden that way and gone when it is
   not (the two `local` gradients cover the shade when scrolled to that end).
   The styled scrollbar stays for platforms that draw a classic one. The
   table's own caption is laid out as wide as the table (1425px on
   /navigator/quotes inside a 702px wrap) and was cut at the edge; it is held
   to the wrap's own width. */
.table-wrap, .tde-table-wrap { overflow-x: auto; container-type: inline-size;
  background:
    linear-gradient(to right, var(--tde-ground, var(--tde-surface)) 40%, transparent)
      left center / 28px 100% no-repeat local,
    linear-gradient(to left, var(--tde-ground, var(--tde-surface)) 40%, transparent)
      right center / 28px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, var(--tde-scroll-shade), transparent)
      left center / 14px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, var(--tde-scroll-shade), transparent)
      right center / 14px 100% no-repeat scroll; }
.table-wrap::-webkit-scrollbar, .tde-table-wrap::-webkit-scrollbar { height: 12px; }
.table-wrap::-webkit-scrollbar-track, .tde-table-wrap::-webkit-scrollbar-track {
  background: var(--tde-ground, var(--tde-surface)); border-top: 1px solid var(--tde-hairline); }
.table-wrap::-webkit-scrollbar-thumb, .tde-table-wrap::-webkit-scrollbar-thumb {
  background: var(--tde-panel-edge); border-radius: 6px; }
.table-wrap caption, .tde-table-wrap caption { max-width: 100cqi; text-align: left; }
/* KEEL LAID wave 3b, keel-shell-inputs-nav, 2026-09-15: tables use the room.
   Measured in Chromium at 1280px, sidebar open (tests/test_shell_inputs_nav.
   py::TestTablesUseTheRoom): the 11-column ledger on /navigator squeezed
   "Landed cost per unit" to 79px, four lines; a prose column on /navigator/
   risks took 395 of 736px and left its neighbours one word per line; two
   option cards side by side left each comparison table 300px. Three rules,
   chosen by trying candidates on all 23 pages in both states (a header
   minimum on EVERY table squeezed /past-crises' row labels instead, so the
   minimum is scoped to header rows of eight cells or more, which already
   scroll inside their own wrap). No type size changes. No :has() either:
   tests/test_web_shell.py keeps the stylesheet free of it, so the header
   rule counts siblings (a header row whose first cell is eighth from the
   end) and the option cards, the only div.card children of a .choices grid
   (/start's are a.choice and form.card), span the whole row instead. */
table.tde td { max-width: 16rem; }
table.tde th:first-child:nth-last-child(n+8),
table.tde th:first-child:nth-last-child(n+8) ~ th { min-width: 6rem; }
.choices > div.card { grid-column: 1 / -1; }
/* THE STICKY FIRST COLUMN PAINTS WHAT ITS OWN ROW PAINTS, 2026-09-21.
   It used to paint `--tde-ground` while the row it sits in was painted by
   whatever rule owned that row, and on /decision at 390px those two drifted
   apart: the header row resolved to the surface token and its first cell
   to the ground token, three parts in 255 apart, invisible to the eye,
   and exactly the "odd header cell" shape
   tests/test_live_defects_buttons_tables.py::TestTablesAreWholeAndEven was
   written to catch after fifteen pages shipped a first column painting
   white across them. The guard caught it the night the card device landed
   and it was fixed here rather than in the guard.
   Two declarations, so the pair CANNOT drift again: the row inside a
   scrollable wrap gets a ground of its own, and the sticky cell inherits
   whatever its row ended up with. A row with a more specific rule of its
   own still wins, and the cell follows it, which is the whole point. */
.table-wrap table:first-child tr,
.tde-table-wrap table:first-child tr {
  background: var(--tde-ground, var(--tde-surface));
}
.table-wrap table:first-child td:first-child,
.table-wrap table:first-child th:first-child,
.tde-table-wrap table:first-child td:first-child,
.tde-table-wrap table:first-child th:first-child {
  position: sticky; left: 0; background: inherit;
}
/* THE FRESHNESS DISCLOSURE WRAPS, 2026-09-21. Its explanation ("IMF PortWatch
   daily chokepoint transits ... 8 days behind") sits inside a disclosure that
   the freshness line squeezes to about 57px at 375px, and one long word such
   as "chokepoint" cannot break inside that, so it ran 27px past its box on
   /navigator/risks and refused the push of 21 September. Let a word break
   rather than overflow, here only. */
.tde-as-of, .tde-as-of > span { overflow-wrap: anywhere; min-width: 0; }
/* The share page's link text (2026-09-23): a long link breaks anywhere rather than
   running off a phone, in place of two inline styles. */
.tde-share-link { overflow-wrap: anywhere; font-size: 17px; }
.shell { display: flex; align-items: stretch; gap: 0; min-height: 100vh; }
/* The sidebar is the fixed "ink" field scheme (always dark), not the semantic
   --tde-ink text colour, which inverts with the viewer's mode and washed the
   panel out pale-on-pale in dark mode (found 2026-09-08 from a screenshot). */
.side { flex: 0 0 300px; box-sizing: border-box; min-height: 100vh;
        background: var(--tde-scheme-ink-field-bg); padding: 1.5rem 1.5rem 1.75rem;
        display: flex; flex-direction: column; }
.side-home { display: flex; align-items: center; gap: 8px;
             text-decoration: none; width: fit-content; margin-bottom: 1.75rem; }
.side-wordmark { font-weight: 700; letter-spacing: 0.06em; font-size: 1.2rem;
                  color: var(--tde-scheme-ink-field-fg); }
.side-group { font-size: 12px; font-weight: 700; letter-spacing: .16em;
              text-transform: uppercase; color: var(--tde-on-anchor);
              margin: 1.5rem 0 .6rem; }
/* MANIFEST B6 (2026-09-16): each accounting's section is its own grouping
   element, so every label is the first of its type; only the first section's
   label sits flush, and each accounting's line tucks under its name. */
[data-account]:first-child > .side-group { margin-top: 0; }
.side-group + .side-small { margin: -.35rem 0 .6rem; }
a.side-link { display: flex; align-items: center; gap: .55rem;
              padding: .5rem .75rem; margin: 0 -.75rem .15rem;
              border-radius: .35rem; text-decoration: none; font-size: 15px;
              font-weight: 400; color: var(--tde-on-anchor); }
a.side-link:hover { background: rgba(255, 255, 255, .08); }
a.side-link[aria-current="page"] { background: var(--tde-signal);
              color: var(--tde-scheme-signal-field-fg); font-weight: 600; }
a.side-link[aria-current="page"]:hover { background: var(--tde-signal); }
/* MANIFEST B6, 2026-09-16, item 5: THE SIDEBAR'S FOCUS RING. The defect
   `keel-shell-inputs-nav` left as "found, not fixed": the sidebar's links took
   the default 2px anchor ring, which measures about 1.7:1 on the ink field
   (measured again here, light 1.72:1). The sidebar is the fixed ink scheme in
   both themes, so its ring is the signal amber the focused input already uses,
   3px, offset clear of the item's own block. Outranks the default ring in
   `_A11Y_RULES` on specificity, and applies to the wordmark, the nav links,
   the footer's account link, the theme switch and the phone menu alike. */
.side :is(a, button, summary):focus-visible { outline: 3px solid var(--tde-focus-ring);
              outline-offset: 2px; }
.tde-icon { flex: none; }
.side-footer { margin-top: auto; padding-top: 1.25rem;
               border-top: 1px solid var(--tde-muted); }
/* KEEL NAV DETAILS (2026-09-20): Settings' own foot-of-nav link, now the
   first child of `.side-footer` (see base.html) - the SAME spacing rhythm
   `.side-load-line` already uses, and its own sibling rule takes over the
   job `.side-footer-label:first-child` used to do for "The sea route" label
   directly below it. */
.side-foot { margin: 0 0 .85rem; }
.side-foot + .side-footer-label { margin-top: 0; }
.side-load-line { margin: 0 0 .85rem; }
.side-persona { color: var(--tde-scheme-ink-field-fg); font-size: .875rem; margin: 0 0 .6rem; }
.side-footer-label { display: block; font-size: 12px; font-weight: 700;
                      letter-spacing: .1em; text-transform: uppercase;
                      color: var(--tde-signal); margin: 1rem 0 .35rem; }
.side-footer-label:first-child { margin-top: 0; }
.side-small, .side-context { color: var(--tde-on-anchor); font-size: .8125rem;
              margin: .35rem 0; }
.side-edit { display: block; margin-top: .3rem; font-size: .8125rem;
             color: var(--tde-signal); }
.side-nav { display: flex; flex-direction: column; flex: 1 1 auto; }
.side-nav[hidden] { display: none; }
.side-menu { display: none; }
.content { flex: 1 1 auto; min-width: 0; }
/* KEEL LAID wave 3b, keel-shell-inputs-nav, 2026-09-15: the sidebar that
   hides (his order: "Make nav bar collapsable"). static/shell.js puts
   data-tde-menu="shown" or "hidden" on the root element before the body
   paints, from 721px up; with no script the attribute never appears, both
   toggles keep their hidden attribute, and nothing below applies. Hidden
   means fully hidden, not a rail: the whole 300px goes back to the page, and
   main's measure widens by exactly that 300px, so a table gets the room and
   a screenshot carries no chrome but the one "Show menu" button. */
.side-toggle { display: none; }
@media (min-width: 721px) {
  .side-toggle:not([hidden]) { display: inline-block; font-family: inherit; font-size: 17px;
               font-weight: 500; line-height: 1.3; padding: .45rem .9rem; border-radius: .35rem;
               cursor: pointer; background: transparent; }
  .side .side-toggle:not([hidden]) { align-self: flex-start; margin: 0 0 1.25rem;
               color: var(--tde-scheme-ink-field-fg); border: 1px solid var(--tde-on-anchor); }
  .side .side-toggle:not([hidden]):hover { background: rgba(255, 255, 255, .08);
               border-color: var(--tde-scheme-ink-field-fg); }
  .side .side-toggle:focus-visible { outline: 3px solid var(--tde-focus-ring); outline-offset: 3px; }
  header .side-toggle:not([hidden]) { margin-right: auto; color: var(--tde-anchor);
               border: 1px solid var(--tde-anchor); }
  header .side-toggle:not([hidden]):hover { background: var(--tde-canvas);
               color: var(--tde-anchor-hover); border-color: var(--tde-anchor-hover); }
  html[data-tde-menu="hidden"] .side { display: none; }
  html[data-tde-menu="hidden"] main { max-width: calc(46rem + 300px); }
}
/* MANIFEST B6, 2026-09-16: THE SHELL CONTRACT (design.block_attrs). The
   executive view hides every analyst block only when the shell has put
   data-tde-view="executive" on the root element; with no script that
   attribute never appears and every analyst block shows. A block of one
   accounting stops a little below the page edge when a link jumps to it. */
html[data-tde-view="executive"] :is(.tde-analyst, [data-view="analyst"]) { display: none !important; }
.tde-account-products, .tde-account-business, .tde-account-plan { scroll-margin-top: 1.25rem; }
/* MANIFEST B6, 2026-09-16: the two switches (static/shell.js), "Show the
   working" in the page header and the theme at the top of the sidebar. Both
   ship hidden and the script shows them; pressed is aria-pressed="true". In
   the always-dark sidebar a pressed choice is the signal block the current
   page already uses; in the header it is an anchor block. */
.tde-switch { font-family: inherit; font-size: 17px; font-weight: 500; line-height: 1.3;
              padding: .35rem .75rem; border-radius: .35rem; cursor: pointer;
              background: transparent; }
.side-theme:not([hidden]) { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0 0 1.25rem; }
.side .tde-switch { color: var(--tde-scheme-ink-field-fg); border: 1px solid var(--tde-on-anchor); }
.side .tde-switch:hover { background: rgba(255, 255, 255, .08); }
.side .tde-switch[aria-pressed="true"] { background: var(--tde-signal); border-color: var(--tde-signal);
              color: var(--tde-scheme-signal-field-fg); }
header { flex-wrap: wrap; }
header .tde-switch { color: var(--tde-anchor); border: 1px solid var(--tde-anchor); }
header .tde-switch:hover { background: var(--tde-canvas); }
header .tde-switch[aria-pressed="true"] { background: var(--tde-anchor); color: var(--tde-surface); }
/* KEEL LAID to 10 October, slice 18 (P25, P55), 2026-09-24: a stress check
   drawn as a scenario card (`/navigator/test`), its heading flush with the
   card's top, and its one toggle ("Every lead time at its worst") the same
   anchor switch the header draws, pressed when it is on, at least the 44px
   tap target tall (fix round 1: it measured 35.3px at 375px). */
.tde-scenario-card > h3:first-child { margin-top: 0; }
.tde-scenario-card .tde-switch { color: var(--tde-anchor); border: 1px solid var(--tde-anchor);
  min-height: 44px; }
.tde-scenario-card .tde-switch:hover { background: var(--tde-canvas); }
.tde-scenario-card .tde-switch[aria-pressed="true"] { background: var(--tde-anchor); color: var(--tde-surface); }
/* Fix round 2b: the card's own disclosure ("Show all 10") at the 44px tap
   target; it measured 33.8px. Every other disclosure is untouched. */
.tde-scenario-card details > summary { min-height: 44px; box-sizing: border-box;
  padding-top: .6rem; }
/* MANIFEST B6, 2026-09-16: the place for the mode switch (PLANKING D5), beside
   "Show the working". Nothing renders these until `/targets` and `/actuals`
   have routes (`web/layout.py::_modes`); the rule waits for them, the way
   every RESERVED class's rule does. */
.tde-modes { display: flex; flex-wrap: wrap; gap: .4rem; }
.tde-mode { font-size: 17px; font-weight: 500; line-height: 1.3; padding: .2rem .7rem;
             border-radius: .35rem; text-decoration: none; color: var(--tde-anchor);
             border: 1px solid var(--tde-anchor); }
.tde-mode-current { background: var(--tde-anchor); color: var(--tde-surface); }
.barometer-pill {
    display: inline-block;
    border-radius: 4px;
    border: 1px solid var(--tde-hairline);
    background-color: var(--tde-surface);
    padding: 4px 12px;
    font-weight: 700;
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--tde-ink);
}
.tde-databar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 0 0 14px 0;
    padding: 7px 12px;
    border-radius: 6px;
    background: var(--tde-background);
    border: 1px solid var(--tde-hairline);
    color: var(--tde-muted);
    font-size: 0.86rem;
}
.tde-databar strong { color: var(--tde-ink); font-weight: 600; }
.tde-databar { border-color: var(--tde-panel-edge); }
body.tde-skeptic [data-provenance]:not([data-provenance="read"]):not([data-provenance="measured"]),
body.tde-skeptic [data-provenance-figure]:not([data-provenance-figure="read"]):not([data-provenance-figure="measured"]) {
  opacity: .38;
}
body:not(.tde-skeptic) [data-provenance] { display: none !important; }

@media (max-width: 720px) {
  .shell { display: block; }
  .side { flex: none; width: auto; min-height: 0; flex-direction: row;
          flex-wrap: wrap; align-items: center; justify-content: space-between;
          padding: 1rem 1.25rem; }
  .side-home { margin-bottom: 0; }
  .side-nav { flex-basis: 100%; padding-top: 1rem; }
  .side-menu:not([hidden]) { display: inline-block; font: inherit; font-size: .9375rem;
               padding: .35rem .8rem; border-radius: .35rem; cursor: pointer;
               background: transparent; color: var(--tde-scheme-ink-field-fg);
               border: 1px solid var(--tde-on-anchor); }
  .side-menu[aria-expanded="true"] { background: var(--tde-signal); color: var(--tde-scheme-signal-field-fg);
               border-color: var(--tde-signal); }
  /* minmax(0, 1fr), not 1fr (keel-shell-inputs-nav): a bare 1fr lets a card
     grow to its widest table, which pushed /navigator/options to 481px on a
     390px phone. The table scrolls inside its own wrap instead. */
  .choices { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 430px) {
  /* The clamp above already holds the heading at 34px here; the tracking is
     the half that cannot be clamped, and it loosens as the size drops. */
  h1 { letter-spacing: -0.02em; }
  /* KEEL PHONE VERDICT: the chrome band above the answer. Measured at
     375px, the heading started 200px down and the first product's money
     landed 67px past the fold. Three small rules buy it back, and each one
     is spacing, never a figure: the page's own controls sit on one line
     with the corridor stamp, the sidebar bar loses half its padding, and a
     section heading keeps a half-step below it instead of a full one. */
  .side { padding: .5rem 1.25rem; }
  header { justify-content: space-between; gap: 8px; margin-bottom: .35rem; }
  .eyebrow { text-align: left; }
  /* T1 of "Trust first, wave 1", fix round 1 (I2), 2026-09-25: the corridor
     stamp takes the room beside "Show the working" and wraps inside it,
     rather than dropping to a line of its own. Tandem's "UK-India, UK-China
     (in part)" is 196px against the 162px left beside the switch at 375px:
     on a line of its own it pushed the first product's money 27px down and
     past the fold; wrapped beside the switch it adds 2px. The 8rem basis
     keeps it off the modes' row. */
  header .eyebrow { flex: 1 1 8rem; min-width: 0; text-align: right; }
  main { padding-top: .5rem; }
  main h2 { margin: .6rem 0 .4rem; }
  /* KEEL PHONE VERDICT: the verdict field. See `design.ONE_NUMBER_PHONE_PX`
     for what was measured and why the clamp itself is untouched. */
  .tde-one-number { font-size: 40px; }
  div[style*="letter-spacing:-0.03em"] { font-size: 3rem !important; }
  .products-desc-field { width: 100%; }
  /* A figure that is a phrase ("Month 2: buy 232 units, £105,052", 340px on
     /products) may wrap on a phone; a bare number has no space to break at. */
  .tde-figure-row .tde-figure-value { white-space: normal; flex: 0 1 auto; min-width: 0; }
  /* The "?" stays on the value's last line when the value wraps: the row's
     gap is dropped between the two and the mark's own margin carries it. */

  /* KEEL PHONE VERDICT, 2026-09-20: THE CARD TABLE. One table, laid out as a
     card per row. See `design.CARD_TABLE_CLASS`'s own comment for what was
     measured and why this is a stylesheet rule rather than a second block of
     markup. The wrapper stops scrolling and stops drawing its scroll shades,
     because there is nothing off to the side any more. */
  .tde-card-table { overflow-x: visible; background: none; }
  .tde-card-table table.tde,
  .tde-card-table table.tde tbody,
  .tde-card-table table.tde tr,
  .tde-card-table table.tde td { display: block; width: auto; max-width: none; }
  /* The header row goes. `display: block` on the cells above has already
     taken this table's row and column semantics away, so a visually hidden
     `<thead>` would announce six headings attached to nothing AND, measured
     here, still reported a 629px scrollWidth inside a 1px box, which is the
     defect this whole rule exists to remove. The label on each card comes
     from `data-label`, which carries the same string the `<th>` holds, and
     the `<th>` itself is untouched in the served HTML. */
  .tde-card-table table.tde thead { display: none; }
  /* The table's own outer edge (added above for the boundaries order) is the
     wrong shape here: the CARD is the box now, one per row, each with its
     own edge below. */
  .tde-card-table table.tde { margin: .35rem 0 1rem; border: 0; }
  .tde-card-table table.tde tr { border: 1px solid var(--tde-panel-edge);
     border-radius: .5rem; background: var(--tde-surface); padding: 10px 14px;
     margin: 0 0 14px; box-sizing: border-box; }
  /* Label and value on ONE line, the `tde-figure-row` idiom: label at the
     left, figure at the right, and the pair wraps to a second line only
     when the figure is a phrase rather than a number. Stacking them cost
     371 to 421px a card, measured, which put the first product's money off
     the first screen even after everything else had moved.
     KEEL LAID keel-table-boundaries, 2026-09-21: each label/value LINE now
     carries its own rule (`--tde-panel-edge`, the same visible token the
     desktop table uses) - a bottom rule between lines and a left rule
     standing for the column boundary a single-column card still has none of
     visually, so the mechanical "rule between rows and columns" holds even
     when there is only one column left to draw. `width:auto` (set above)
     means the border never changes the card's measured width, and
     `box-sizing: border-box` on the card itself keeps the fixed padding from
     doing so either. */
  .tde-card-table table.tde td { border: 0;
     border-bottom: 1px solid var(--tde-panel-edge);
     border-left: 3px solid var(--tde-panel-edge);
     box-sizing: border-box; padding: 4px 0 4px 10px;
     text-align: left; position: static; display: flex; flex-wrap: wrap;
     justify-content: space-between; align-items: baseline; gap: 0 16px; }
  .tde-card-table table.tde td.num { text-align: left; }
  /* The first cell is the card's name, so it is a heading, not a label and a
     value: `body_small` from the type scale, well above the 17px floor. */
  .tde-card-table table.tde td:first-child { display: block;
     font-weight: 700; font-size: 21px; line-height: 1.25; padding: 0 0 4px 10px; }
  .tde-card-table table.tde td[data-label]::before {
     content: attr(data-label); flex: 0 1 auto; color: var(--tde-muted);
     font-size: 17px; font-weight: 500; letter-spacing: .02em;
     text-transform: uppercase; }
  .tde-card-table table.tde tr.total td:first-child { border-top: 0; }
}

.tde-print-link { font-size: .8125rem; }
.tde-print-no-plan { display: none; }

@media print {
  .side { display: none !important; }
  .tde-print-link { display: none !important; }
  .tde-saved, .tde-saved-show { display: none !important; }
  input, textarea, select, button { display: none !important; }
  .tde-print-no-plan { display: block !important; }
  .shell { display: block; }
  .content, main { max-width: none; padding: 0; margin: 0; }
}

.tde-device-frame { border: 1px solid var(--tde-panel-edge); border-radius: .5rem; padding: 16px; }
.tde-caption { color: var(--tde-muted); font-size: 17px; }
.tde-next-step { color: var(--tde-anchor); font-weight: 600; text-decoration: underline; }
.tde-figure-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 16px;
  padding: 12px 10px; border-top: 1px solid var(--tde-hairline);
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.tde-as-of { display: inline-block; }
.tde-as-of > summary { cursor: pointer; color: var(--tde-ink); font-weight: 600;
  text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 2px; }
.tde-as-of > span { display: block; margin-top: 4px; font-size: 17px;
  font-weight: 400; color: var(--tde-muted); }
.tde-v1-marker {
  display: inline-flex; align-items: center; height: 24px; padding: 0 7px;
  margin-left: 8px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 700; font-size: 17px;
  letter-spacing: 0.1em; text-transform: uppercase; white-space: nowrap;
  color: var(--tde-judgement); border: 1px solid var(--tde-judgement);
  border-radius: 3px;
}
.tde-diagnostic-note {
  display: flex; align-items: center; gap: 8px; margin: 6px 0 20px 0;
  padding: 9px 14px; border-left: 3px solid var(--tde-anchor);
  background: var(--tde-background); color: var(--tde-ink);
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 17px; font-weight: 600;
}
.tde-stale-band {
  border: 2px solid var(--tde-breach); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; margin: 0 0 18px 0;
}
.tde-stale-stripes {
  height: 32px;
  background: repeating-linear-gradient(135deg, var(--tde-signal) 0 20px,
    var(--tde-ink) 20px 40px);
}
.tde-stale-admission {
  margin: 10px 0 0; padding: 0; color: var(--tde-ink); font-size: 17px; font-weight: 600;
}
/* THE STALE-DATA FOLD (F277, 2026-09-28). Measured at 375px: the stacked
   band (a 32px stripe, then the admission below it) cost 143px above the
   verdict card - the stripe's own height, the admission's 10px margin-top,
   its wrapped lines, the band's border and its 18px margin-bottom - which
   on the worst worked example (`malaysia_exporter`, fresh card bottom
   764px, so only 48px of the first screen is left to give) pushed the card
   to 907px, past the phone's first screen. GOV.UK's "Warning text"
   pattern (an icon beside one sentence, never stacked above it) is the
   shape this follows: the stripe becomes a 30px-WIDE vertical strip (the
   handoff's own 30-34px range, read as a cross dimension rather than a
   height) beside the admission (a flex row) rather than a 32px-TALL bar
   above it, so the stripe costs no height of its own, and the margins
   that used to separate the two stacked pieces are trimmed to what one
   row needs - including the band's own border, dropped on this
   breakpoint alone (nothing in the handoff requires one; the hazard
   stripe and the bold ink beside it already read as one unit without it,
   and the 2px it cost was the difference between clearing and missing
   `malaysia_exporter`'s 48px budget).
   Placed in ITS OWN media block, after the base rules above rather than
   inside the earlier "KEEL PHONE VERDICT" block: two rules of equal
   specificity at the same breakpoint resolve by source order, and a block
   written before `.tde-stale-band`'s own base rule (KEEL PHONE VERDICT's,
   above the fold at line ~800) lost every property the base rule also
   set - measured the hard way, margin-bottom stayed 18px until this block
   moved below it. Desktop is untouched (rule 6 of the brief: "not made
   worse") - this lives inside the phone breakpoint alone, so the band
   still reads as a band at the top of the content column at 1280px. */
@media (max-width: 430px) {
  .tde-stale-band { display: flex; align-items: stretch; gap: 4px; margin: 0;
     border-width: 0; }
  .tde-stale-stripes { flex: 0 0 30px; width: 30px; height: auto; }
  /* `line-height` alone, never `font-size` - the type floor
     (`tests/test_type_floor.py`) scans `font-size:` declarations only, and
     17px stays exactly on the floor. FIX ROUND 1 (2026-09-28), his ruling:
     accuracy over brevity moved the admission back to three sentences
     ("These figures are not current. Refreshed N days ago. Shipping to X,
     prices to Y, trade to Z."). CORRECTED (F277b item 3, 2026-09-28): this
     does not wrap to a flat "three lines" at 301px the way an earlier
     version of this comment said - measured directly, a lane with TWO
     dates (`malaysia_exporter`'s own ship+trade) wraps to three lines
     (54px), but a lane with all THREE (uk_india's ship+prices+trade, the
     longer clause) wraps to FOUR (71px) - so the line itself has to pack
     tighter than before (1.05, against the body's own 1.55) to hold the
     room malaysia_exporter's first screen has. Combined with the two
     margin rules below (this line-height alone was not enough on any
     reasonable setting - see their own comment). */
  .tde-stale-admission { margin: 0; line-height: 1.05; }
  /* THE VERTICAL MARGIN BETWEEN THE HEADING AND THE CARD, ONLY WHILE THE
     BAND SHOWS AND ONLY ON /decision's OWN CHAIN (fix round 1, his own
     suggestion; F277b item 1 CORRECTED this rule's shape, the qa-
     auditor's finding on the F277 push - see below). What stands between
     the heading and the card: `h1`'s own margin-bottom (`.35rem`, `h1 {
     margin: 0 0 .35rem }`) and `.tde-verdict-card`'s own margin-top
     (`.5rem`) collapse to the LARGER one (8px) under normal sibling
     margin collapsing - fix round 1 measured this directly for zeroing
     `h1`'s side alone (the 8px gap stayed exactly where it was, because
     the card's own 8px was still the larger margin setting it); the same
     collapsing rule means zeroing only the card's side the other way
     would just as surely leave `h1`'s own 5.6px as the new max - either
     side alone changes nothing, so the two have to net to nothing
     together.

     F277 FIX ROUND 1 zeroed `h1`'s margin-bottom via `.tde-stale-band +
     h1 { margin-bottom: 0 }` - but that selector has no way to see what
     comes AFTER the heading, so it matched on EVERY page whose body opens
     with an `<h1>` right after the band (`{{ outage }}{{ stale }}` sits
     right before `{% block body %}` in `base.html`), not only /decision's.
     On /compare and /navigator/options the heading is followed by a `<div
     class="tde-device-frame ...">` style note, never the verdict card, so
     zeroing that heading's own margin-bottom closed a gap this rule was
     never meant to touch - at 375px stale, the note's own box sat about
     2px above the heading's descenders (the handoff's "clear rules off
     the ink"). The qa-auditor's own suggested fix, scoping the first rule
     with `:has(+ .tde-verdict-card)`, is refused here: `tests/
     test_web_shell.py::TestTheSkepticFilter::
     test_the_css_rule_targets_both_data_attributes_design_stamps_carry`
     already bans the literal `:has(` anywhere in this stylesheet (measured
     - that test scans the WHOLE built file, not only the skeptic filter's
     own rule), and this file already routes around the same ban twice
     elsewhere (the `table.tde td` comment above, and the bank-pack
     `body.tde-bank-pack-page` comment below) rather than add a third,
     narrower exception.

     F277b's OWN FIX drops the first rule ENTIRELY - `h1`'s margin-bottom
     is never touched, on any page, stale or not - and instead makes the
     SECOND rule (`.tde-stale-band + h1 + .tde-verdict-card`, already
     exclusive to /decision's own chain with no lookahead needed: a
     forward-only selector on THREE elements in a row) do the whole job by
     margin ARITHMETIC rather than a lookahead selector. Per the CSS
     collapsing spec, when one adjoining margin is positive and another is
     negative, the collapsed result is the positive maximum PLUS the
     negative minimum, not a lookup - so setting this rule's margin-top to
     the exact negative of `h1`'s own margin-bottom (`-.35rem`): the only
     positive margin in the pair is `h1`'s own `.35rem`, the only negative
     one is this rule's `-.35rem`, and `.35rem + (-.35rem)` = 0 - the same
     net gap fix round 1 reached by zeroing both sides directly. `h1`'s own
     margin-bottom stays live everywhere, including on /decision itself -
     it is simply cancelled by this rule's own negative margin on THIS
     chain alone, which (unchanged from fix round 1) can only ever exist on
     /decision. `-.35rem` is coupled to `h1`'s own literal margin-bottom
     value above; if that literal ever changes, this value must change with
     it - there is no shared constant to enforce this both existing rules
     did not already share either. Measured together with line-height
     1.05: the collapsed gap goes to 0 (h1 bottom and card top land on the
     same pixel) and `malaysia_exporter` clears 812px with a few pixels to
     spare - the exact figures are in the F277b report. */
  .tde-stale-band + h1 + .tde-verdict-card { margin-top: -.35rem; }
}
.tde-month-row, .tde-limit-and-hang, .tde-coverage-row, .tde-refused-chart,
.tde-composition-bar, .tde-passage, .tde-lane-map, .tde-bar-chart, .tde-line-chart {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.tde-month-block { width: 28px; height: 28px; }
.tde-month-solid { background: var(--tde-ink); }
.tde-month-hollow { background: var(--tde-surface); border: 2px solid var(--tde-ink);
  box-sizing: border-box; }
.tde-month-row-blocks { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.tde-month-row-caption { display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin-top: 8px; }
.tde-limit-rule { height: 6px; background: var(--tde-ink); }
.tde-limit-and-hang-row { display: flex; flex-wrap: wrap; align-items: flex-start;
  gap: 14px; margin-top: 0; }
.tde-breach-col { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.tde-breach-mass { width: 44px; background: var(--tde-breach); }
.tde-breach-label { color: var(--tde-muted); font-size: 17px; font-weight: 700; }
.tde-breach-thin-note { color: var(--tde-muted); font-size: 17px; display: block;
  max-width: 64px; }
.tde-coverage-block { width: 20px; height: 20px; }
.tde-coverage-held { background: var(--tde-ink); }
.tde-coverage-gap { background: var(--tde-surface); border: 2px solid var(--tde-muted);
  box-sizing: border-box; }
.tde-coverage-row-blocks { display: flex; flex-wrap: wrap; gap: 5px; }
.tde-coverage-caption { margin-top: 8px; color: var(--tde-muted); font-size: 17px; }
.tde-coverage-caption-emphasis { color: var(--tde-ink); }
.tde-refused-chart { border: 2px solid var(--tde-muted); box-sizing: border-box;
  display: flex; align-items: center; justify-content: center; padding: 16px;
  max-width: 100%; }
.tde-refused-chart-text { color: var(--tde-muted); font-size: 17px; line-height: 1.4;
  text-align: center; }
.tde-chart-svg { max-width: 100%; height: auto; }
.tde-chart-stamp { margin-top: 4px; }
.tde-chart-caption { fill: var(--tde-ink); }
.tde-ytick { fill: var(--tde-muted); }
.tde-zero-line { stroke: var(--tde-hairline); }
.tde-bar-chart-bg { fill: var(--tde-surface); }
.tde-bar { fill: currentColor; }
.tde-composition-bar-wrap, .tde-bar-chart-wrap { display: block; }
.tde-composition-segment { fill: currentColor; }
.tde-segment-label { fill: var(--tde-surface); }
.tde-composition-legend-row { display: flex; flex-wrap: wrap; margin-top: 4px; }
.tde-composition-legend-item { display: inline-flex; align-items: center; gap: 4px;
  margin-right: 14px; }
.tde-composition-legend-swatch { display: inline-block; width: 10px; height: 10px;
  background: currentColor; }
.tde-composition-legend-text { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 17px;
  color: var(--tde-muted); }
.tde-icon { flex: none; }
.tde-load-line-under { color: var(--tde-breach); }
.tde-load-line-clear, .tde-load-line-at { color: var(--tde-ink); }
.tde-passage-wrap { display: flex; align-items: center; gap: 10px; }
.tde-passage-reading { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 700; color: var(--tde-ink);
  font-size: 17px; }
.tde-passage-label { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; color: var(--tde-muted); font-size: 17px; }
.tde-passage-frame { fill: var(--tde-surface); stroke: var(--tde-muted); }
.tde-lane-map-wrap { overflow-x: auto; }
.tde-lane-map-question { margin: 0 0 6px; color: var(--tde-ink); font-size: 17px;
  font-weight: 600; }
.tde-lane-sea { stroke: var(--tde-muted); }
.tde-lane-passage { stroke: currentColor; }
.tde-lane-node { fill: var(--tde-surface); stroke: var(--tde-ink); }
.tde-lane-spur { stroke: var(--tde-muted); }
.tde-lane-share, .tde-lane-suppliers { fill: var(--tde-ink); }
.tde-lane-state, .tde-lane-thin { fill: var(--tde-muted); }
.tde-lane-map-table { width: 100%; border-collapse: collapse; }
.tde-load-line { display: inline-block; }
.tde-load-line-disc { fill: var(--tde-canvas); stroke: var(--tde-ink); }
.tde-purser-tile { fill: var(--tde-scheme-anchor-field-bg); }
.tde-purser-face { fill: var(--tde-scheme-anchor-field-fg); }
.tde-purser-band { fill: var(--tde-signal); }
.tde-purser-smile { stroke: var(--tde-scheme-anchor-field-fg); }
/* KEEL LAID wave 3b, keel-light-legibility, 2026-09-15, defect 4: the label
   and figure were a fixed 15rem/5rem (flex-shrink 0), which left a 390px
   panel too little room for the track between them and pushed the figure
   past the panel's own border ("136 days" measured at 379px inside a 350px
   panel). clamp() holds each to its ORIGINAL fixed size at 1280 (28vw/13vw
   both exceed the clamp's max there, same derivation `design.
   ONE_NUMBER_CLAMP_*`'s own comment uses) and shrinks it at 390, leaving the
   track a real width instead of squeezing to nothing. */
.ladder-row { display: flex; align-items: center; gap: 10px; margin: .4rem 0; }
.ladder-label { flex: 0 0 clamp(6rem, 28vw, 15rem); font-size: 17px; color: var(--tde-ink); }
.ladder-track { position: relative; flex: 1 1 auto; height: 14px;
  background: var(--tde-background); border: 1px solid var(--tde-panel-edge); border-radius: 3px; }
.ladder-bar { position: absolute; top: 0; left: 0; height: 100%; border-radius: 2px; }
.ladder-bar.overdue { background: var(--tde-breach); }
.ladder-bar.late { background: var(--tde-ink); }
.ladder-bar.on_time { background: transparent; box-shadow: inset 0 0 0 2px var(--tde-ink); }
.ladder-mark { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--tde-muted); }
.ladder-figure { flex: 0 0 clamp(3rem, 13vw, 5rem); text-align: right; font-variant-numeric: tabular-nums;
  font-size: 17px; color: var(--tde-muted); }
.hp { position: absolute; left: -9999px; top: -9999px; }

.tde-provenance {
    display: inline-flex;
    align-items: center;
    height: 26px;
    padding: 0 8px;
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    font-weight: 700;
    font-size: 17px;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    white-space: nowrap;
}
.tde-provenance-computed { color: var(--tde-anchor); background: var(--tde-surface); box-shadow: inset 0 0 0 3px var(--tde-anchor); }
.tde-provenance-derived { color: var(--tde-ink); background: var(--tde-surface); box-shadow: inset 0 0 0 3px var(--tde-ink); }
.tde-provenance-estimated { color: var(--tde-ink); background: var(--tde-signal); outline: 2px dashed var(--tde-judgement); outline-offset: 4px; }
.tde-provenance-measured { color: var(--tde-surface); background: var(--tde-anchor); }
.tde-provenance-proxy { color: var(--tde-ink); background: var(--tde-surface); box-shadow: inset 0 0 0 3px var(--tde-ink); outline: 2px dashed var(--tde-muted); outline-offset: 4px; }
.tde-provenance-read { color: var(--tde-surface); background: var(--tde-ink); }

.tde-figure-row-tint { background: var(--tde-tint-field); }
.tde-figure-label { flex: 1 1 200px; min-width: 0; color: var(--tde-muted); font-size: 17px; }
.tde-figure-value { flex: 0 0 auto; white-space: nowrap; color: var(--tde-ink); font-size: 22px; font-weight: 700; }
.tde-figure-stamp { flex: 0 0 auto; }

.barometer-pill-bad { color: var(--tde-breach); background: var(--tde-pill-tint); border-color: var(--tde-pill-border-bad); }
.barometer-pill-good { color: var(--tde-holds); background: var(--tde-pill-tint); border-color: var(--tde-pill-border-good); }
.barometer-pill-info { color: var(--tde-anchor); background: var(--tde-pill-tint); border-color: var(--tde-pill-border-info); }
.barometer-pill-neutral { color: var(--tde-muted); background: var(--tde-pill-tint); border-color: var(--tde-pill-border-neutral); }
.barometer-pill-watch { color: var(--tde-watch-ink); background: var(--tde-pill-tint); border-color: var(--tde-pill-border-watch); }

.tde-icon-account { fill: currentColor; }
.tde-icon-add { fill: currentColor; }
.tde-icon-chart { fill: currentColor; }
.tde-icon-costs { fill: currentColor; }
.tde-icon-decision { fill: currentColor; }
.tde-icon-details { fill: currentColor; }
.tde-icon-export { fill: currentColor; }
.tde-icon-measured { fill: currentColor; }
.tde-icon-plan { fill: currentColor; }
.tde-icon-products { fill: currentColor; }
.tde-icon-route { fill: currentColor; }
.tde-icon-settings { fill: currentColor; }
.tde-icon-start { fill: currentColor; }
.tde-icon-table { fill: currentColor; }

.tde-paint-ink { color: var(--tde-ink); }
.tde-paint-anchor { color: var(--tde-anchor); }
.tde-paint-muted { color: var(--tde-muted); }
.tde-paint-hairline { color: var(--tde-hairline); }
.tde-paint-surface { color: var(--tde-surface); }
.tde-paint-canvas { color: var(--tde-canvas); }
.tde-paint-breach { color: var(--tde-breach); }
.tde-paint-judgement { color: var(--tde-judgement); }
.tde-paint-signal { color: var(--tde-signal); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
:is(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--tde-anchor); outline-offset: 2px;
}
/* THE SKIP LINK (base.html's FIRST focusable element, ahead of the
   sidebar; KEEL LAID to 10 October, slice 12, F111). Off-screen by
   default by `left`/`top`, never `display:none` or `visibility:hidden`:
   either of those would also take it out of the Tab order, and a keyboard
   is the one reader this control exists for. On focus it comes back at the
   top left, above everything (z-index 1000, the only z-index this
   stylesheet declares).
   ITS COLOURS ARE THE SIGNAL FIELD SCHEME, measured where it is drawn.
   At the top left it lands on the sidebar, which is the fixed ink field in
   BOTH themes (`.side` above), so the link is a fixed amber field too:
   ink on amber, 9.06:1 in light and dark alike (the product's 7:1 bar for
   text, `tests/test_theme_contrast.py`), and the amber box stands 9.06:1
   off the ink sidebar behind it. The theme-following button pair would
   have been 4.79:1 for its text in dark mode, and its fill 1.72:1 against
   the sidebar in light. Where the menu is hidden and the page is behind
   it instead, the default focus ring just above draws its edge (9.9:1 on
   the light page, 4.65:1 on the dark). Hover keeps the same ink:
   `a:hover`'s anchor-hover blue would fall to 1.05:1 on amber in dark
   mode.
   17px (the app's type floor, `TYPE["app_floor"]`) on the body's 1.55
   line height plus 14px of padding is a box about 54px tall: at or above
   the 44px tap target in both axes, checked on the rendered box by
   `tests/test_skip_link.py`'s browser proof. */
.tde-skip-link {
  position: absolute;
  left: -9999px;
  top: -9999px;
  z-index: 1000;
  padding: 14px 20px;
  background: var(--tde-scheme-signal-field-bg);
  font-size: 17px;
  font-weight: 600;
  text-decoration: none;
  border-radius: .35rem;
}
.tde-skip-link, .tde-skip-link:hover { color: var(--tde-scheme-signal-field-fg); }
.tde-skip-link:focus {
  left: 8px;
  top: 8px;
}

/* THE BANK PACK (T4, F249): the table, the phone cards and the printout. */
.tde-bank-pack td { overflow-wrap: break-word; }
/* A figure never wraps away from its sign (fix round 1, M6: at 375px the
   lowest-month sentence broke between "-" and "£761,389.15"). */
.tde-bank-pack .tde-bank-fig, .tde-bank-pack td.num { white-space: nowrap; }
/* SIX MONTHS FIT A LAPTOP (W1c, the audit of 25 September, HOLD 1), AT THE
   APP'S READABLE SIZE (his ruling of 27 September, orders item 41). The
   table keeps the shell's own type (lines 15px, headers 13px): the earlier
   fit set it to 13px with 12px figures, under the app's type floor, and
   tests/test_type_floor.py's ratchet refused it. Instead the figure cells
   carry no currency symbol (web/bank_pack.py's figure(), cut from the one
   money door) and each month's header names it once, "Month 1 (£)"; on a
   screen wider than a phone the table takes main's side padding (1.25rem
   each side) and the cells lose their side padding, keeping one pixel
   between a figure and the column rule on its right. Measured at 1024 (the
   300px menu leaves main 724px): indian_exporter's six months need 716px
   with no side padding and 738px with .1rem, so the padding is what the
   widest worked example leaves room for; the fit test covers all eight at
   1024, 1280 and 1920. The nowrap above stays, so a figure never leaves its
   sign; this rule is screen only, so the phone's cards and the printout
   keep their layout (both show the headers' "(£)"). */
@media screen and (min-width: 431px) {
  .tde-bank-pack .tde-bank-pack-table { margin-left: -1.25rem; margin-right: -1.25rem; }
  .tde-bank-pack table.tde th, .tde-bank-pack table.tde td { padding: .4rem 0; }
  .tde-bank-pack table.tde th.num, .tde-bank-pack table.tde td.num { padding-right: 1px; }
}
.tde-bank-pack tr.tde-bank-section th { text-align: left; font-weight: 700;
   background: var(--tde-canvas); }
.tde-bank-pack .tde-bank-lowest { background: var(--tde-canvas); }
.tde-bank-pack .tde-bank-absent { color: var(--tde-muted); }
.tde-bank-pack tr.tde-bank-beside td { font-style: italic; }
.tde-bank-pack .tde-bank-assumptions li { margin: 0 0 6px; }
.tde-bank-pack .tde-bank-seal { border-top: 1px solid var(--tde-panel-edge);
   margin-top: 24px; padding-top: 12px; }
@media (max-width: 430px) {
  .tde-bank-pack .tde-card-table table.tde tr.tde-bank-section { border: 0;
     background: none; padding: 12px 0 4px; margin: 0; }
  .tde-bank-pack .tde-card-table table.tde tr.tde-bank-section th {
     display: block; background: none; padding: 0; border: 0; }
  .tde-bank-pack .tde-card-table table.tde td.tde-bank-absent { display: block; }
}
@page tde-bank-pack { size: A4 landscape; margin: 12mm; }
@media print {
  /* On the BODY, not the pack's own box: a named page on an inner box
     forces a page break before it (measured: page one printed the menu
     alone), while the body's name is the first page's own. */
  body.tde-bank-pack-page { page: tde-bank-pack; }
  /* The shell's Plan / Targets / Actuals switch is for the screen, not the
     page a bank reads (fix round 1, M7); keyed on the class the pack's own page puts on <body> (never :has(), which
     tests/test_web_shell.py bans from tde.css),
     so no other page's printout moves. */
  body.tde-bank-pack-page .tde-modes { display: none !important; }
  .tde-bank-pack .tde-bank-pack-exports { display: none !important; }
  .tde-bank-pack .tde-bank-pack-table { overflow: visible !important; }
  .tde-bank-pack table.tde { width: 100%; border-collapse: collapse; }
  .tde-bank-pack tr, .tde-bank-pack .tde-bank-seal { break-inside: avoid; }
}

/* THE VERDICT CARD (T2, F241): one verdict first, the rest one tap below. */
.tde-verdict-card { border-left: 4px solid var(--tde-panel-edge); padding: .85rem 1rem; margin-top: .5rem; }
.tde-verdict-card.tde-verdict-holds { border-left-color: var(--tde-holds); }
.tde-verdict-card.tde-verdict-breaks { border-left-color: var(--tde-breach); }
.tde-verdict-card p { overflow-wrap: break-word; margin: 0 0 .5rem; line-height: 1.4; }
/* The headline's size is the design scale's own `tde-type-body_small` (21px),
   a class in the vocabulary, so this section adds no font-size of its own. */
.tde-verdict-card .tde-verdict-head { line-height: 1.2; }
/* Task 6a fix round 2: the stockout's one short line, under the headline inside its paragraph
   (one line, no paragraph gap), at the card's body size rather than the headline's. Gate-reds round
   (12 October 2026): the size is the design scale's own `tde-type-app_floor` (17px), a class on the
   span, so this rule adds no font-size of its own (it had added a 16px one, under the app floor). */
.tde-verdict-card .tde-verdict-head .tde-verdict-stockout { display: block; line-height: 1.2; }
.tde-verdict-card .tde-verdict-figure { font-weight: 600; }
/* Merge of duty-ask into trust-and-fixes (12 October 2026): the worst-month line's paragraph, which
   also carries ruling 124's duty sentence, is set a little tighter (it is the small muted size), so the
   card still ends inside a phone's first screen (indian_importer ran to 816 of 812 with the duty
   sentence as a paragraph of its own). */
.tde-verdict-card .tde-verdict-worst { line-height: 1.3; margin-bottom: .25rem; }
.tde-verdict-card .tde-verdict-seal { border-top: 1px solid var(--tde-hairline);
   margin-top: 8px; padding-top: 6px; }
.tde-verdict-card .tde-verdict-seal p { margin: 0 0 4px; }
.tde-verdict-card .tde-verdict-fp { white-space: nowrap; }
details.tde-verdict-more { margin: 0 0 1rem; }
details.tde-verdict-more > summary { cursor: pointer; font-weight: 600; padding: 10px 0;
   min-height: 44px; box-sizing: border-box; }
