/* ============================================================================
   CARGO PLANNER  ·  v3 (rework)
   Transport-planning pane on the dashboard: stat tiles, rolling business-day
   carousel, Calibri worklist with grouped header + severity rail, separator
   rows, dispatch modal (release-note trays) and the week calendar.

   THEMING — everything runs on a local palette layer (--cp-*) derived from the
   app tokens in css/themes.css. Dark is the default (:root), the Harbor marine
   light theme overrides under :root[data-theme="light"] .cp-root.

   SPECIFICITY NOTE — themes.css carries broad light-theme rules with
   !important on bare ELEMENT selectors ([data-theme="light"] button/span/b/i…).
   Every planner selector is therefore anchored on .cp-root (or one of the three
   body-level portals), which outranks them (0,2,0 > 0,1,1); paint properties on
   buttons and coloured spans additionally carry !important so the important
   comparison is won on specificity. That is why they are here — not decoration.
   ============================================================================ */

/* The palette layer. It is declared on EVERY planner host, not just the pane:
   the two modals, the tooltip, the separator popover and the row context menu
   are all rendered outside .cp-root (modal overlays live at the end of <body>),
   so without this list their var() lookups would resolve to nothing. */
.cp-root,
.modal-panel.cp-modal,
.cp-tip,
.cp-seppop,
.cp-ctx-menu {
    /* surfaces */
    --cp-bg:        var(--bg-primary);
    --cp-panel:     var(--bg-secondary);
    --cp-inset:     color-mix(in srgb, var(--bg-secondary) 78%, var(--bg-primary));
    --cp-tert:      var(--bg-tertiary);
    --cp-hover:     var(--bg-hover);
    --cp-field:     var(--input-bg);
    --cp-line:      var(--border-color);
    --cp-line-soft: color-mix(in srgb, var(--border-color) 58%, var(--bg-secondary));

    /* type */
    --cp-txt-1: var(--text-primary);
    --cp-txt-2: var(--text-secondary);
    --cp-txt-3: var(--text-muted);

    /* accents */
    --cp-acc:         var(--accent-orange);   /* selection / active affordance */
    --cp-link:        #38bdf8;                /* refs + counts (light overrides) */
    --cp-blue:        var(--accent-blue);
    --cp-blue-strong: #2563eb;
    --cp-ok:          var(--accent-green);
    --cp-warn:        var(--accent-yellow);
    --cp-bad:         var(--accent-red);

    /* rows */
    --cp-row-alt:   var(--bg-row-alt);
    --cp-row-hover: var(--bg-row-hover);
    --cp-row-sel:   #1d3a52;
    /* "release note already sent" row tint — a success wash, deliberately far
       enough from --cp-hover and --cp-row-sel to stay its own signal. Derived
       from --cp-ok so it follows whichever theme is mounted. */
    --cp-sent-row:   color-mix(in srgb, var(--cp-ok) 16%, var(--cp-panel));
    --cp-sent-row-h: color-mix(in srgb, var(--cp-ok) 28%, var(--cp-panel));
    /* "client-arranged transport" row tint — same success family, roughly half
       the strength, because nothing was ever actually sent for this line. */
    --cp-client-row:   color-mix(in srgb, var(--cp-ok) 7%, var(--cp-panel));
    --cp-client-row-h: color-mix(in srgb, var(--cp-ok) 16%, var(--cp-panel));

    /* table head */
    --cp-th-bg:   linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
    --cp-th-txt:  #ffffff;
    --cp-th-line: var(--border-color);
    --cp-th-grp:  linear-gradient(135deg, #141428 0%, #111a31 100%);

    /* signal dots — deliberately fixed hues in both themes: red / amber / green
       encode regulatory state, not brand */
    --cp-dot-ok: #16a34a;   --cp-dot-ok-l: #15803d;
    --cp-dot-warn: #d97706; --cp-dot-warn-l: #b45309;
    --cp-dot-bad: #dc2626;  --cp-dot-bad-l: #b91c1c;
    --cp-dot-off: #475569;  --cp-dot-off-l: #334155;
    /* THE FOURTH TONE — an open T1 transit document (owner ask 28.5). It is NOT
       a fourth severity: the row still ranks amber everywhere it is counted (see
       customsRank in js/cargo-planner.js). Blue because the traffic-light three
       are spoken for and because "in transit" is a state, not a verdict.

       WHY NOT ONE OF THE BLUES ALREADY IN THIS FILE. --cp-link (#38bdf8) is the
       file ref and the terminal chip, --cp-blue-strong (#2563eb) is the INTERNAL
       note dot two columns to the left, and a customs verdict that borrowed
       either would read as one of those. Indigo sits far enough off both to be
       told apart at 18px while still reading as blue.
       MEASURED, dark: fill #6366f1 vs its white glyph 4.47:1, vs the row
       (#1e293b) 3.27:1, vs the zebra row (#1a2336) 3.51:1 — the same band the
       existing dots occupy (ok 3.30 / 4.44, warn 3.19 / 4.59, bad 4.83 / 3.03).
       Light: #4f46e5 on white 6.29:1, on the zebra row (#f7f9fb) 5.96:1 — the
       dark row's constraint is gone, so the light theme takes the deeper indigo
       rather than the pale one white would wash out.
       DEUTERANOPIA (Viénot simulation): the transit blue lands at #6565f1 and
       ok-green at #8c8c4e — ΔE76 115 (dark) / 127 (light), i.e. nowhere near
       each other; the closest pair is the internal-note blue at ΔE76 9.3, which
       is why the transit dot ALSO carries a 'T' glyph and the note dot never
       does. Nothing on this sheet is left to hue alone. */
    --cp-dot-transit: #6366f1; --cp-dot-transit-l: #4338ca;

    --cp-today: #38bdf8;    /* today's marker on the day carousel */
    --cp-cal-meta: var(--text-muted);
    --cp-cal-strong: var(--text-secondary);

    --cp-tip-bg:   linear-gradient(180deg, #1e293b, #0f172a);
    --cp-tip-line: var(--border-color);

    --cp-shadow:    var(--shadow-lg);
    --cp-shadow-sm: var(--shadow-sm);
    --cp-focus:     #38bdf8;

    --cp-gut: 28px;   /* width of the separator rail beside the worklist */
    /* the worklist (and only the worklist) is set in Calibri — a local Windows
       face, so nothing is fetched; the stack falls back to the humanist sans
       that ships with every other platform */
    --cp-tblfont: Calibri, 'Segoe UI', Candara, 'Trebuchet MS', sans-serif;
}

.cp-root {
    display: block;
    padding: 0.5rem 2px 2.5rem;
    color: var(--cp-txt-1);
    font-size: 13px;
    line-height: 1.45;
    font-variant-numeric: tabular-nums;
}

:root[data-theme="light"] .cp-root,
:root[data-theme="light"] .modal-panel.cp-modal,
:root[data-theme="light"] .cp-tip,
:root[data-theme="light"] .cp-seppop,
:root[data-theme="light"] .cp-ctx-menu {
    --cp-inset:     #f2f7fb;
    --cp-line-soft: #e6eef4;
    --cp-acc:         var(--accent-blue);      /* marine #0a5989 */
    --cp-link:        var(--accent-blue);
    --cp-blue-strong: var(--accent-blue);
    --cp-row-sel:   #d4ecf5;
    --cp-sent-row:   color-mix(in srgb, var(--cp-ok) 15%, #ffffff);
    --cp-sent-row-h: color-mix(in srgb, var(--cp-ok) 26%, #ffffff);
    --cp-client-row:   color-mix(in srgb, var(--cp-ok) 7%, #ffffff);
    --cp-client-row-h: color-mix(in srgb, var(--cp-ok) 15%, #ffffff);
    --cp-th-bg:   var(--accent-blue);
    --cp-th-line: #084a73;
    --cp-th-grp:  #084a73;
    --cp-dot-off: #cbd5e1;  --cp-dot-off-l: #94a3b8;
    /* deeper on white — see the measurements beside the dark values above */
    --cp-dot-transit: #4f46e5; --cp-dot-transit-l: #3730a3;
    --cp-today:   #2c8c62;   /* light theme: today is GREEN, selection stays marine */
    --cp-cal-meta: var(--text-secondary);
    --cp-cal-strong: var(--text-primary);
    --cp-tip-bg:   #ffffff;
    --cp-focus:    var(--accent-blue);
}

.cp-root *, .cp-root *::before, .cp-root *::after { box-sizing: border-box; }
.cp-root [hidden] { display: none !important; }
.cp-root button { font-family: inherit; cursor: pointer; }
.cp-root input, .cp-root select, .cp-root textarea { font-family: inherit; }
.cp-root input:not([type=checkbox]),
.cp-root select,
.cp-root textarea {
    background: var(--cp-field);
    color: var(--cp-txt-1);
    border: 1px solid var(--cp-line);
    border-radius: 6px;
    font-size: 0.72rem;
    padding: 6px 8px;
    transition: border-color 0.14s;
}
.cp-root input:not([type=checkbox]):hover,
.cp-root select:hover,
.cp-root textarea:hover { border-color: var(--cp-txt-3); }
.cp-root input[type=checkbox] { accent-color: var(--cp-blue-strong); width: 14px; height: 14px; cursor: pointer; margin: 0; }
.cp-root :focus-visible { outline: 2px solid var(--cp-focus); outline-offset: 2px; border-radius: 4px; }
.cp-root .cp-grow { flex: 1 1 auto; }

/* The planner's modals live OUTSIDE .cp-root (they are body-level overlays), so
   they are named explicitly here — otherwise the release-note reading bar would
   keep scanning for a reader who asked for no motion. */
@media (prefers-reduced-motion: reduce) {
    .cp-root *, .cp-root *::before, .cp-root *::after,
    /* the panel ITSELF, not just its descendants: .modal-panel carries the
       app's 0.2s modalIn entry animation, which the descendant selector below
       never reached. */
    .modal-panel.cp-modal,
    .modal-panel.cp-modal *, .modal-panel.cp-modal *::before, .modal-panel.cp-modal *::after,
    .cp-tip, .cp-seppop, .cp-ctx-menu {
        transition: none !important;
        animation: none !important;
        scroll-behavior: auto !important;
    }
}

/* ==========================================================================
   VIEW BAR + SUB TABS
   ========================================================================== */
.cp-root .cp-viewbar { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 12px; }
.cp-root .cp-ptitle { font-size: 1rem; font-weight: 800; letter-spacing: 0.01em; display: flex; align-items: center; gap: 8px; color: var(--cp-txt-1) !important; margin: 0; }
.cp-root .cp-ptitle .cp-sub { font-size: 0.6rem; font-weight: 600; color: var(--cp-txt-3) !important; letter-spacing: 0.1em; text-transform: uppercase; }

.cp-root .cp-vtabs { display: flex; gap: 3px; padding: 3px; background: var(--cp-panel); border: 1px solid var(--cp-line); border-radius: 9px; }
.cp-root .cp-vtab {
    display: inline-flex; align-items: center; gap: 7px; padding: 6px 14px;
    border: 1px solid transparent !important; background: transparent !important;
    color: var(--cp-txt-3) !important; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
    border-radius: 7px; transition: background 0.14s, color 0.14s;
}
.cp-root .cp-vtab:hover { color: var(--cp-txt-1) !important; }
.cp-root .cp-vtab.active { background: var(--cp-acc) !important; color: #fff !important; border-color: var(--cp-acc) !important; }
.cp-root .cp-vtab .cp-cnt {
    font-size: 0.6rem; font-weight: 800; padding: 0 6px; border-radius: 999px;
    background: color-mix(in srgb, var(--cp-txt-3) 22%, transparent); color: inherit !important;
}
.cp-root .cp-vtab.active .cp-cnt { background: rgba(255, 255, 255, 0.24); }

.cp-root .cp-live { display: inline-flex; align-items: center; gap: 7px; font-size: 0.62rem; color: var(--cp-txt-3) !important; white-space: nowrap; }
.cp-root .cp-live-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--cp-ok); box-shadow: 0 0 0 3px color-mix(in srgb, var(--cp-ok) 22%, transparent); }

/* ==========================================================================
   BUTTONS / CHIPS (planner-local — the app chrome keeps its own .btn)
   ========================================================================== */
.cp-root .cp-btn {
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
    border: 1px solid var(--cp-line) !important; background: var(--cp-tert) !important; color: var(--cp-txt-1) !important;
    border-radius: 7px; padding: 7px 13px; font-size: 0.71rem; font-weight: 700;
    transition: background 0.14s, border-color 0.14s, color 0.14s, opacity 0.14s;
}
.cp-root .cp-btn:hover:not(:disabled) { background: var(--cp-hover) !important; border-color: var(--cp-txt-3) !important; }
.cp-root .cp-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.cp-root .cp-btn.primary { background: var(--cp-blue-strong) !important; border-color: var(--cp-blue-strong) !important; color: #fff !important; }
.cp-root .cp-btn.primary:hover:not(:disabled) { filter: brightness(1.1); }
.cp-root .cp-btn.ghost { background: transparent !important; }
.cp-root .cp-btn.ghost:hover:not(:disabled) { background: var(--cp-hover) !important; }
.cp-root .cp-btn.sm { padding: 5px 9px; font-size: 0.64rem; }

/* ---- EXCEL EXPORT — the one solid GREEN button on the command bar ----
   Owner request 2026-08-12: "make excel report button on cargo planner green
   and txt white". Styled BY ID, from this sheet, so index.html keeps the markup
   it already has (class="cp-btn ghost") and no version marker has to move for a
   colour change.
   That means the rule has to out-rank two things at once:
     · this sheet's own `.cp-root .cp-btn.ghost { background: transparent
       !important }` (0,3,0) five lines up, and
     · themes.css's `[data-theme="light"] button { background:#fff !important;
       color:#102033 !important; border:1px solid #b9cedb !important }` (0,1,1).
   `.cp-root #cpExportBtn` is (1,2,0), and one id outranks any number of classes,
   so the !important comparison is won on specificity in BOTH themes — which is
   why the paint properties below carry !important and nothing else does.
   THE HUE IS FIXED IN BOTH THEMES, deliberately, and it is NOT --cp-ok: the app
   token behind that (--accent-green) is #22c55e in dark and #2c8c62 in light,
   and white text on those measures 2.2:1 and 4.17:1 — both fail AA, which is
   exactly the trap "green button, white text" walks into. #15803d measures
   5.02:1 against #ffffff and the hover step #166534 measures 7.13:1, so the
   label holds in every state and the button reads as the same object whichever
   theme is mounted. #15803d is already in this file as the stepped-down
   --cp-dot-ok inside the amber scan zone, so no new hue enters the sheet. */
.cp-root #cpExportBtn {
    background-color: #15803d !important;
    border-color: #15803d !important;
    color: #ffffff !important;
}
/* The ⤓ glyph is bare text in the button today, so it already inherits the white
   above; this second selector is for the day someone wraps it in a <span> or an
   <i>, which themes.css light would re-ink on sight ([data-theme="light"] span
   / i, 0,1,1). At (1,2,0) the glyph stays white whatever it gets wrapped in. */
.cp-root #cpExportBtn > * { color: #ffffff !important; }

.cp-root #cpExportBtn:hover:not(:disabled) {
    background-color: #166534 !important;
    border-color: #166534 !important;
}
/* Focus ring: .cp-root's own 2px --cp-focus at 2px offset is drawn OUTSIDE the
   button, on the panel — never on the green — so there is nothing to re-tune
   here. The fill is restated only so a focused button can never fall back to
   the ghost transparent underneath it. */
.cp-root #cpExportBtn:focus-visible {
    background-color: #15803d !important;
    border-color: #15803d !important;
    color: #ffffff !important;
}
/* Disabled: `.cp-btn:disabled` drops the whole button to opacity .4, which on a
   SOLID fill takes white-on-green to roughly 2.9:1 — disabled controls are
   exempt from 1.4.3, but that is unreadable rather than merely muted. .55 still
   reads as "off" beside its live siblings and keeps the label a label. Nothing
   in the planner disables this button today; the rule is here so the state
   cannot arrive broken the first time something does. */
.cp-root #cpExportBtn:disabled { opacity: 0.55; }

.cp-root .cp-selchip {
    font-size: 0.66rem; font-weight: 800; letter-spacing: 0.03em; padding: 4px 11px; border-radius: 999px;
    color: var(--cp-link) !important; background: color-mix(in srgb, var(--cp-link) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--cp-link) 45%, transparent);
}
.cp-root .cp-filternote { font-size: 0.63rem; color: var(--cp-txt-3) !important; }
.cp-root .cp-filternote b { color: var(--cp-txt-1) !important; }
.cp-root .cp-cmd-div { width: 1px; align-self: stretch; background: var(--cp-line); margin: 0 2px; }

/* ==========================================================================
   STAT TILES
   ========================================================================== */
.cp-root .cp-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; }
.cp-root .cp-tile {
    position: relative; overflow: hidden; text-align: left; display: flex; flex-direction: column; gap: 1px;
    padding: 11px 13px 11px 16px; border: 1px solid var(--cp-line-soft) !important; border-radius: 11px;
    background: var(--cp-panel) !important; color: var(--cp-txt-1) !important;
    transition: border-color 0.14s, background 0.14s, transform 0.12s;
}
.cp-root .cp-tile::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--cp-tone, var(--cp-line)); }
.cp-root .cp-tile:hover { border-color: var(--cp-tone, var(--cp-txt-3)) !important; transform: translateY(-1px); }
.cp-root .cp-tile.on { border-color: var(--cp-tone) !important; background: color-mix(in srgb, var(--cp-tone) 11%, var(--cp-panel)) !important; }
.cp-root .cp-tile .k { font-size: 0.58rem; font-weight: 800; letter-spacing: 0.11em; text-transform: uppercase; color: var(--cp-txt-3) !important; }
.cp-root .cp-tile .v { font-size: 1.55rem; font-weight: 800; line-height: 1.15; color: var(--cp-txt-1) !important; }
.cp-root .cp-tile .s { font-size: 0.6rem; color: var(--cp-txt-3) !important; }
.cp-root .cp-tile.on .k { color: var(--cp-tone) !important; }
.cp-root .cp-tile .pin { position: absolute; top: 9px; right: 10px; font-size: 0.52rem; font-weight: 800; letter-spacing: 0.08em; color: var(--cp-tone) !important; opacity: 0; }
.cp-root .cp-tile.on .pin { opacity: 1; }

/* ==========================================================================
   COMMAND BAR
   ========================================================================== */
.cp-root .cp-cmdbar {
    display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-top: 12px;
    padding: 9px 11px; background: var(--cp-panel); border: 1px solid var(--cp-line); border-radius: 11px;
}
.cp-root .cp-srch {
    display: flex; align-items: center; gap: 7px; background: var(--cp-inset);
    border: 1px solid var(--cp-line); border-radius: 8px; padding: 0 9px; min-width: 236px; flex: 0 1 300px;
    color: var(--cp-txt-3) !important;
}
.cp-root .cp-srch span { color: var(--cp-txt-3) !important; font-size: 0.7rem; }
.cp-root .cp-srch input { border: none !important; background: transparent !important; padding: 7px 0 !important; flex: 1; min-width: 0; }
.cp-root .cp-srch input:focus { outline: none; }
.cp-root .cp-srch:focus-within { border-color: var(--cp-focus); }

/* ==========================================================================
   DAY CAROUSEL
   ========================================================================== */
.cp-root .cp-daystrip {
    display: flex; align-items: stretch; gap: 10px; padding: 10px; margin-top: 12px;
    background: var(--cp-panel); border: 1px solid var(--cp-line); border-radius: 11px;
}
.cp-root .cp-dfield { display: flex; flex-direction: column; gap: 4px; justify-content: center; min-width: 168px; flex: 0 0 auto; }
.cp-root .cp-dfield label { font-size: 0.56rem; font-weight: 800; letter-spacing: 0.11em; text-transform: uppercase; color: var(--cp-txt-3) !important; }
.cp-root .cp-dfield select { font-weight: 700; padding: 7px 8px; }
.cp-root .cp-dnav {
    align-self: center; width: 30px; min-height: 62px; border-radius: 8px;
    border: 1px solid var(--cp-line) !important; background: var(--cp-tert) !important; color: var(--cp-txt-2) !important;
    font-size: 1rem; font-weight: 800; flex: 0 0 auto;
}
.cp-root .cp-dnav:hover { background: var(--cp-hover) !important; color: var(--cp-txt-1) !important; }
/* the top padding leaves room for today's on-border TODAY legend, which rides
   half a line above the card edge — the strip is a scroller and would clip it */
.cp-root .cp-daycards { display: flex; gap: 8px; flex: 1 1 auto; min-width: 0; overflow-x: auto; padding: 11px 1px 1px; }
.cp-root .cp-daycard {
    flex: 1 1 0; min-width: 104px; text-align: left; position: relative;
    border: 1px solid var(--cp-line) !important; border-radius: 10px;
    --cp-card-bg: var(--cp-inset); background: var(--cp-card-bg) !important;
    padding: 8px 10px 9px; color: var(--cp-txt-2) !important;
    display: flex; flex-direction: column; gap: 2px;
    transition: border-color 0.14s, background 0.14s, box-shadow 0.14s;
}
.cp-root .cp-daycard:hover { border-color: var(--cp-txt-3) !important; }
.cp-root .cp-daycard .dtop { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.cp-root .cp-daycard .dow { font-size: 1.02rem; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase; color: var(--cp-txt-3) !important; line-height: 1.1; }
.cp-root .cp-daycard .dm { font-size: 1.02rem; font-weight: 800; color: var(--cp-txt-1) !important; line-height: 1.1; }
.cp-root .cp-daycard .n { font-size: 0.58rem; color: var(--cp-txt-3) !important; }
.cp-root .cp-daycard .n b { color: var(--cp-link) !important; font-weight: 800; }
.cp-root .cp-daycard .n .arr { color: var(--cp-ok) !important; font-weight: 800; }
.cp-root .cp-daycard .n .opn { color: var(--cp-bad) !important; font-weight: 800; }
.cp-root .cp-daycard .n .zero { color: var(--cp-txt-3) !important; }
.cp-root .cp-daycard.past { --cp-card-bg: color-mix(in srgb, var(--cp-inset) 82%, var(--cp-bg)); }
.cp-root .cp-daycard.past .dm { color: var(--cp-txt-2) !important; }
/* today = a highlighted card with its label sitting ON the top border (the
   fieldset-legend trick: the label paints the card's own background behind
   itself, so it interrupts the border line instead of floating over it). The
   2px border is paid for out of the padding, so the card keeps its size. */
.cp-root .cp-daycard.today {
    --cp-today-c: var(--cp-today);
    --cp-card-bg: color-mix(in srgb, var(--cp-today) 9%, var(--cp-inset));
    border: 2px solid var(--cp-today-c) !important;
    padding: 7px 9px 8px;
}
.cp-root .cp-daycard.today::before {
    content: 'TODAY'; position: absolute; top: 0; left: 50%; transform: translate(-50%, -50%);
    padding: 1px 7px; line-height: 1; border-radius: 5px; pointer-events: none;
    font-size: 0.72rem; font-weight: 800; letter-spacing: 0.11em;
    background: var(--cp-card-bg); color: var(--cp-today-c);
}
.cp-root .cp-daycard.today:hover { border-color: var(--cp-today-c) !important; }
.cp-root .cp-daycard.today .dm, .cp-root .cp-daycard.today .dow { color: var(--cp-today-c) !important; }
.cp-root .cp-daycard.on {
    border-color: var(--cp-acc) !important; --cp-card-bg: color-mix(in srgb, var(--cp-acc) 12%, var(--cp-inset));
    box-shadow: inset 0 0 0 1px var(--cp-acc);
}
.cp-root .cp-daycard.on .dow, .cp-root .cp-daycard.on .dm { color: var(--cp-acc) !important; }
.cp-root .cp-daycard.on .n b { color: var(--cp-acc) !important; }
/* today AND picked: selection owns the FILL and the inner ring, today keeps the
   border and turns its legend into a solid pill so the marker still carries */
.cp-root .cp-daycard.today.on {
    border-color: var(--cp-today-c) !important;
    box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--cp-acc) 55%, transparent);
}
.cp-root .cp-daycard.today.on::before { background: var(--cp-today-c); color: #fff; }
.cp-root .cp-sevbar { display: flex; height: 4px; gap: 2px; margin-top: 3px; }
.cp-root .cp-sevbar i { display: block; height: 100%; border-radius: 2px; }
.cp-root .cp-sevbar i.bad { background: var(--cp-dot-bad); }
.cp-root .cp-sevbar i.warn { background: var(--cp-dot-warn); }
.cp-root .cp-sevbar i.ok { background: var(--cp-dot-ok); }
.cp-root .cp-sevbar.empty { background: var(--cp-line-soft); border-radius: 2px; }
.cp-root .cp-daycard.add {
    flex: 0 0 54px; min-width: 54px; align-items: center; justify-content: center; gap: 1px;
    border-style: dashed !important; background: transparent !important; color: var(--cp-txt-3) !important;
    margin: 11px 0 1px;
}
.cp-root .cp-daycard.add:hover { color: var(--cp-txt-1) !important; border-color: var(--cp-txt-3) !important; }
.cp-root .cp-daycard.add .wsym { font-size: 1rem; font-weight: 800; line-height: 1.05; color: inherit !important; }
.cp-root .cp-daycard.add .wlbl { font-size: 0.5rem; font-weight: 800; letter-spacing: 0.09em; color: inherit !important; }
.cp-root .cp-daycard.add.on {
    border-style: solid !important; border-color: var(--cp-acc) !important; color: var(--cp-acc) !important;
    background: color-mix(in srgb, var(--cp-acc) 12%, transparent) !important;
}
.cp-root .cp-todaybtn {
    align-self: center; flex: 0 0 auto; white-space: nowrap; padding: 8px 12px; font-size: 0.64rem;
    font-weight: 800; letter-spacing: 0.05em; border-radius: 8px;
}
.cp-root .cp-todaybtn.centred { color: var(--cp-txt-3) !important; border-style: dashed !important; }
.cp-root .cp-todaybtn:not(.centred) { border-color: var(--cp-acc) !important; color: var(--cp-acc) !important; background: color-mix(in srgb, var(--cp-acc) 12%, transparent) !important; }

/* ==========================================================================
   WORKLIST TABLE
   outer shell: [separator gutter | scroller] — the gutter is NOT part of the
   horizontal scroller, so the "+" handles can never scroll away sideways
   ========================================================================== */
.cp-root .cp-tblshell { display: flex; align-items: stretch; min-width: 0; margin-top: 12px; }
.cp-root .cp-tblshell > .cp-tblwrap { flex: 1 1 auto; min-width: 0; }
.cp-root .cp-tblwrap {
    background: var(--cp-panel); border: 1px solid var(--cp-line); border-radius: 11px;
    overflow: auto; max-height: min(64vh, 660px);
    padding-bottom: 9px;
}
/* Calibri runs narrower and shorter than the app's mono face, so the size goes
   up a step to hold the same density; tabular figures align every date column */
.cp-root table.cp-table {
    width: 100%; border-collapse: separate; border-spacing: 0; min-width: 1320px;
    font-family: var(--cp-tblfont); font-weight: 700; font-size: 0.84rem;
    line-height: 1.3; letter-spacing: 0.004em; font-variant-numeric: tabular-nums;
    background: transparent;
}
.cp-root .cp-table tbody td, .cp-root .cp-table tbody th { font-weight: 700; }
.cp-root .cp-table input, .cp-root .cp-table select { font-family: var(--cp-tblfont); font-weight: 700; letter-spacing: 0; }
/* !important throughout the sheet: themes.css paints EVERY light-theme
   `table th` / `table td` with !important (background, colour, border), which
   would otherwise wipe the header band, the zebra rows and the selection fill. */
.cp-root .cp-table thead th {
    position: sticky; z-index: 3; background: var(--cp-th-bg) !important; color: var(--cp-th-txt) !important;
    border-color: var(--cp-th-line) !important;
    text-align: left; font-weight: 800; white-space: nowrap;
}
.cp-root .cp-table thead tr.cp-grp th {
    top: 0; height: 24px; line-height: 16px; padding: 4px 10px; background: var(--cp-th-grp) !important;
    font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase; opacity: 0.85;
    border-right: 1px solid rgba(255, 255, 255, 0.1);
}
.cp-root .cp-table thead tr.cp-grp th:last-child { border-right: none; }
.cp-root .cp-table thead tr.cp-cols th {
    top: 24px; height: 30px; padding: 0 10px; font-size: 0.68rem; letter-spacing: 0.05em; text-transform: uppercase;
    border-bottom: 2px solid var(--cp-th-line);
}
.cp-root .cp-table thead tr.cp-cols th.c { text-align: center; }
.cp-root .cp-table th.grpstart, .cp-root .cp-table td.grpstart { border-left: 1px solid var(--cp-line); }
.cp-root .cp-table thead tr.cp-cols th.grpstart { border-left: 1px solid rgba(255, 255, 255, 0.16); }

.cp-root .cp-table tbody tr { --cp-row-bg: var(--cp-panel); background: var(--cp-row-bg); }
.cp-root .cp-table tbody tr.alt { --cp-row-bg: var(--cp-row-alt); }
.cp-root .cp-table tbody tr:hover { --cp-row-bg: var(--cp-row-hover); }
.cp-root .cp-table tbody tr.sel { --cp-row-bg: var(--cp-row-sel); }
.cp-root .cp-table tbody tr.saved { --cp-row-bg: color-mix(in srgb, var(--cp-ok) 22%, var(--cp-panel)); }
.cp-root .cp-table tbody tr.flash { animation: cpFlash 1.1s ease; }
@keyframes cpFlash {
    0%, 100% { background: var(--cp-row-bg); }
    30%, 70% { background: color-mix(in srgb, var(--cp-acc) 26%, var(--cp-panel)); }
}
/* A row that has just been RE-SEATED (its ETA WHS moved it) is flashed so the
   reader can see where it went. The reduced-motion block above cancels every
   animation inside .cp-root, which would leave that reader with no cue at all —
   so they get the same highlight as a flat, un-animated tint instead. */
@media (prefers-reduced-motion: reduce) {
    .cp-root .cp-table tbody tr.flash {
        --cp-row-bg: color-mix(in srgb, var(--cp-acc) 26%, var(--cp-panel));
    }
}

/* ---- CUSTOMS SCAN — the register's flag, over the LEFT-HAND columns ---------
   A shipment marked "selected for a customs scan" in the Shipments Register
   wears the register's OWN colour here: #ffd43b with a #b8860b rim, the two
   literal values css/enhancements.css paints on
   `#tableBody td.customs-scan-flagged`.

   HOW FAR IT GOES (owner, r26B). FILE REF → CARRIER, and no further. REL. NOTE,
   PLANNED, FREIGHT, RELEASE, PHYTO and CUSTOMS keep their ordinary background.

   That is not a taste call: those six are the row's STATUS columns and the
   amber was measurably eating them. `td.cp-scell.warn` paints MISSING / ASKED
   neon #fbff00 with #f12121 text, and the neon-on-amber pairing is ~1.16:1 —
   the cell stopped reading as an alarm and simply merged into the band; under
   a deuteranopia simulation the two are the same colour and the cell vanished
   outright. The customs dot lost the same fight. Off the amber, the neon is
   back to ~10:1 against the panel and the dots to their full separation.

   WHICH CELLS. `td.cp-scanzone`, written by applyScanTo() in
   js/cargo-planner.js — NOT an :nth-child() count. The column order lives in
   renderTable() and a count restated here would be a silent second copy of it
   (see THE PAINT BOUNDARY in that file). `td.cp-scanedge` is the last painted
   cell and carries the seam rim.

   The row still gets `.cp-scan` — that is what the JS, the chip and the
   selectors below key off. It just no longer carries the background itself, so
   the unpainted half zebra-stripes, hovers and selects exactly like every other
   row in the table.

   THAT AMBER, NOT THE NEON #fbff00. The register picked it deliberately to sit
   apart from the `.cell-warn` yellow that PHYTO / Freight / Release already
   use — and this sheet restates that same neon for `td.cp-scell.warn` a few
   hundred lines below. The two now never touch at all: the neon cells are all
   outside the zone. This paragraph stays as the record of why they must not be
   the same hue even so — the chip, the legend swatch and the register's own
   cell are all still amber beside neon somewhere.

   Fixed in BOTH themes, for the register's own reason: the grid is white with
   dark text either way, so one opaque amber is legible in both. There is no
   light-theme override below and none is wanted.

   PRECEDENCE, highest first:
     1. .saved / .flash   transient (700ms / 1.1s) — "your edit landed" and
                          "the row moved" must never be swallowed by a flag
                          that will still be there afterwards. The zone stands
                          down for the duration (rule at the bottom of this
                          block) so the whole row, not just its right half,
                          shows the transient.
     2. .cp-scan zone     beats SELECTION, HOVER and the ZEBRA stripe INSIDE the
                          painted columns, exactly as the register excludes
                          .cell-warn from every hover and selection tint
                          (`:not(.cell-warn)` throughout enhancements.css). The
                          flag is information; the stripe is a reading aid.
     3. .sel / :hover / .alt — unchanged for every other row, and now also for
                          the six columns to the right of the seam, which stripe
                          and tint on a flagged row like any other.
   Selection and hover are NOT lost on a flagged row, they simply speak in the
   same yellow across the zone: two deeper tones, so the row still answers the
   pointer and still shows it is ticked while never stopping looking flagged.
   Because the amber is on the CELLS and the tint is on the ROW, one row can
   carry both at once without either being lost.

   The severity rail (inset box-shadow on td.ck) paints OVER the background and
   survives untouched; only its two pale tones are darkened below so they still
   read against yellow. */

/* THE FOUR AMBERS. Declared on the ROW, consumed by the ZONE — so hover and
   selection are still row-wide facts (the pointer is over the whole row, the
   tick applies to the whole row) while only the left-hand cells spend them.

   THE CALENDAR CARD IS DECLARED ON THESE SAME LINES ON PURPOSE (2026-08-12).
   One shipment gets looked at in the worklist and in the month grid inside the
   same minute, so the two surfaces have to be the same yellow — and two ambers
   written in two places eventually disagree by a digit, silently, months later.
   Grouped here they cannot: there is exactly one #ffd43b in this file and both
   surfaces read it through --cp-scan-bg.
   The card joins the BASE and the HOVER tone only. It has no `.sel`: the
   calendar never ticks a card (`.open` merely expands it), so the two deeper
   selection tones stay worklist-only rather than being invented for a state
   that does not exist over there. */
.cp-root .cp-table tbody tr.cp-scan,
.cp-root .cp-cal-row.cp-cal-scan { --cp-scan-bg: #ffd43b; --cp-scan-rim: #b8860b; }
.cp-root .cp-table tbody tr.cp-scan:hover,
.cp-root .cp-cal-row.cp-cal-scan:hover        { --cp-scan-bg: #f8c81f; }
.cp-root .cp-table tbody tr.cp-scan.sel       { --cp-scan-bg: #eab308; }
.cp-root .cp-table tbody tr.cp-scan.sel:hover { --cp-scan-bg: #d99e06; }

/* THE PAINTED ZONE — FILE REF → CARRIER.
   !important at (0,4,3): it has to beat this sheet's own
   `tbody td { background: transparent !important }` (0,2,2) and the sticky
   columns' `background: var(--cp-row-bg) !important` (0,3,0), which is also why
   the two sticky cells need no rule of their own — they are cells 1 and 2, so
   they are IN the zone and this rule is the one that wins on them. That is what
   keeps the pinned FILE REF amber while the table is scrolled sideways. */
.cp-root .cp-table tbody tr.cp-scan > td.cp-scanzone {
    background: var(--cp-scan-bg) !important;
    /* Ink. Every colour rule in this sheet resolves through these custom
       properties, so redefining them ON THE PAINTED CELL re-inks that cell and
       everything inside it — including the `!important` td colour — without a
       single specificity fight. Near-black on #ffd43b is ~13:1. Cells outside
       the zone never see these and keep the sheet's own ink. */
    --cp-txt-1: #1a1405;
    --cp-txt-2: #3f3110;
    --cp-txt-3: #63501c;
    --cp-link:  #0b4a6f;   /* sky #38bdf8 is unreadable on amber */
    /* the register's own rim colour, on the painted cells */
    --cp-line-soft: #b8860b;
    /* the note dot and the severity rail key off these; the pale tones vanish
       on yellow, so the family is stepped down one notch. The CUSTOMS dot is
       outside the zone now and deliberately keeps the sheet's own tones. */
    --cp-dot-ok:   #15803d;  --cp-dot-ok-l:   #14532d;
    --cp-dot-warn: #b45309;  --cp-dot-warn-l: #92400e;
    --cp-dot-bad:  #b91c1c;  --cp-dot-bad-l:  #7f1d1d;
    --cp-dot-off:  #6b7280;  --cp-dot-off-l:  #4b5563;
}

/* THE SEAM, at the CARRIER / REL. NOTE join. An inset shadow, never a border:
   a border-right on one row's cell would re-enter the auto-layout width
   calculation and shove the column sideways for flagged rows only. 2px of the
   register's rim colour reads as an edge against the amber on its left and
   against the panel on its right, in both themes, and it travels with the
   CARRIER column when the wrapper is scrolled. */
.cp-root .cp-table tbody tr.cp-scan > td.cp-scanedge {
    box-shadow: inset -2px 0 0 var(--cp-scan-rim);
}

/* the inline editors are the one thing that must NOT go yellow — they are
   controls, and a control has to look like a control. They read as white cards
   on the band in both themes (the dark theme's own field colour would sit on
   the yellow as a black hole). Both live inside the zone. */
.cp-root .cp-table tbody tr.cp-scan .cp-eta-date,
.cp-root .cp-table tbody tr.cp-scan .cp-eta-time,
.cp-root .cp-table tbody tr.cp-scan select.cp-carrier {
    background: rgba(255, 255, 255, 0.94);
    color: #1a1405;
    border-color: rgba(0, 0, 0, 0.34);
}

/* TRANSIENT WINS (see precedence 1). The zone YIELDS for the 700ms / 1.1s a
   `.saved` or `.flash` lasts — background, ink and seam all step aside — so a
   flagged row flashes exactly like an unflagged one: the tr's own background
   (and, for `.flash`, the tr's own animation) shows through the whole width.
   Nothing is set on the tr here: the generic `.saved` / `.flash` / reduced-
   motion rules above already give it the right colour, and re-stating them was
   only ever needed while the tr carried the amber itself.
   `box-shadow` is reset on the EDGE cell alone — td.ck's severity rail is an
   inset shadow too, and a blanket reset over the zone would erase it. */
.cp-root .cp-table tbody tr.cp-scan.saved > td.cp-scanzone,
.cp-root .cp-table tbody tr.cp-scan.flash > td.cp-scanzone {
    background: transparent !important;
    --cp-txt-1: inherit; --cp-txt-2: inherit; --cp-txt-3: inherit;
    --cp-link: inherit;  --cp-line-soft: inherit;
    --cp-dot-ok: inherit;   --cp-dot-ok-l: inherit;
    --cp-dot-warn: inherit; --cp-dot-warn-l: inherit;
    --cp-dot-bad: inherit;  --cp-dot-bad-l: inherit;
    --cp-dot-off: inherit;  --cp-dot-off-l: inherit;
}
.cp-root .cp-table tbody tr.cp-scan.saved > td.cp-scanedge,
.cp-root .cp-table tbody tr.cp-scan.flash > td.cp-scanedge { box-shadow: none; }
/* …except the two sticky cells, which must stay OPAQUE or the columns they pin
   would scroll through them. They take the row's own background, which is what
   every unflagged row's sticky cells already do. */
.cp-root .cp-table tbody tr.cp-scan.saved > td.stick1,
.cp-root .cp-table tbody tr.cp-scan.saved > td.stick2,
.cp-root .cp-table tbody tr.cp-scan.flash > td.stick1,
.cp-root .cp-table tbody tr.cp-scan.flash > td.stick2 {
    background: var(--cp-row-bg) !important;
}
/* the ETA WHS cell while its two halves are being written */
.cp-root .cp-table .cp-etaw.saving { opacity: 0.5; }

/* THE CONTAINER CELL WHILE THE CUSTOMS-SCAN FLAG IS BEING WRITTEN (ask 28.3).
   The flag itself is NEVER painted from the click — the server has the last
   word — so the gap between the click and the answer needs a state of its own,
   or the reader clicks again on what looks like a menu that did nothing.

   A RING AND A PULSE, NOT A COLOUR. Anything painted with `background` here
   would have to out-!important the sheet's own transparent-td rule and then win
   a specificity tie against the amber zone rule for the release case; an inset
   shadow paints over both without entering that fight, and no other rule puts a
   shadow on td.cont (td.ck's rail and td.cp-scanedge's seam are other cells).
   The pulse stands down under prefers-reduced-motion with everything else in
   this sheet. */
.cp-root .cp-table tbody td.cont.cp-scan-busy {
    box-shadow: inset 0 0 0 2px var(--cp-focus);
    cursor: progress;
    animation: cpScanBusy 1.05s ease-in-out infinite;
}
@keyframes cpScanBusy { 0%, 100% { opacity: 0.6; } 50% { opacity: 1; } }
/* the CELL is transparent so the ROW's --cp-row-bg (zebra / hover / selection)
   is what you see; only the two sticky columns paint it themselves */
.cp-root .cp-table tbody td {
    padding: 5px 10px; white-space: nowrap; vertical-align: middle;
    background: transparent !important; color: var(--cp-txt-1) !important;
    border-bottom: 1px solid var(--cp-line-soft) !important;
}

.cp-root .cp-table .stick1, .cp-root .cp-table .stick2 { position: sticky; z-index: 2; background: var(--cp-row-bg) !important; }
.cp-root .cp-table thead .stick1, .cp-root .cp-table thead .stick2 { z-index: 5; background: var(--cp-th-bg) !important; }
.cp-root .cp-table .stick1 { left: 0; width: 38px; }
.cp-root .cp-table .stick2 { left: 38px; border-right: 1px solid var(--cp-line); }

.cp-root .cp-table td.ck { box-shadow: inset 3px 0 0 var(--cp-rail, transparent); }
.cp-root .cp-table .fileref { font-weight: 800; color: var(--cp-link) !important; cursor: pointer; user-select: none; -webkit-user-select: none; }
.cp-root .cp-table .fileref:hover { text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 3px; }
.cp-root .cp-table .muted { color: var(--cp-txt-3) !important; font-size: 0.74rem; font-weight: 700; }
.cp-root .cp-table .cont b { display: block; font-weight: 800; color: var(--cp-txt-1) !important; }
.cp-root .cp-table .cont .muted { display: block; margin-top: 1px; }
.cp-root .cp-table .cust { max-width: 190px; overflow: hidden; text-overflow: ellipsis; }
.cp-root .cp-table .prod { max-width: 170px; overflow: hidden; text-overflow: ellipsis; }
.cp-root .cp-table .ves { color: var(--cp-txt-2) !important; font-size: 0.8rem; max-width: 170px; overflow: hidden; text-overflow: ellipsis; }

/* customer / product / vessel always read in caps — presentation only */
.cp-root .cp-uc { text-transform: uppercase; }
.cp-root .cp-term-chip {
    display: inline-block; font-size: 0.63rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--cp-link) !important; background: color-mix(in srgb, var(--cp-link) 13%, transparent);
    border: 1px solid color-mix(in srgb, var(--cp-link) 42%, transparent); border-radius: 4px; padding: 0 5px; margin-bottom: 2px;
}
.cp-root .cp-term-date { display: block; font-size: 0.79rem; color: var(--cp-txt-1) !important; }
.cp-root .cp-etaw { display: flex; gap: 4px; align-items: center; }
.cp-root .cp-etaw input[type=date] { width: 116px; padding: 3px 5px; font-size: 0.76rem; }
.cp-root .cp-etaw input[type=time] { width: 72px; padding: 3px 5px; font-size: 0.76rem; }
.cp-root select.cp-carrier { width: 84px; padding: 3px 5px; font-size: 0.76rem; font-weight: 700; }
.cp-root select.cp-carrier.saving { opacity: 0.5; }

/* ---- NOTE dot — every note-ish store on the register line in one mark ----
   COLOUR says who the line is written for: green = a planner note that rides
   out on the carrier email (cargo_plan_note), marine = internal only (notes /
   cell_comments). The NUMERAL says how many notes and comments the line
   carries. Hollow grey = nothing written. */
.cp-root .cp-note-dot {
    width: 12px; height: 12px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center; vertical-align: middle;
    cursor: help; color: #fff !important; background: transparent; border: 1.5px solid var(--cp-dot-off-l);
    font-family: var(--cp-tblfont); font-size: 0.6rem; font-weight: 800; line-height: 1; letter-spacing: 0;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.cp-root .cp-note-dot:hover, .cp-root .cp-note-dot:focus-visible { transform: scale(1.18); box-shadow: 0 0 0 3px color-mix(in srgb, var(--cp-txt-3) 26%, transparent); }
.cp-root .cp-note-dot.plan { background: var(--cp-dot-ok); border-color: var(--cp-dot-ok-l); }
.cp-root .cp-note-dot.intl { background: var(--cp-blue-strong); border-color: color-mix(in srgb, var(--cp-blue-strong) 74%, #000); }
.cp-root .cp-note-dot.multi { width: 17px; height: 17px; font-size: 0.64rem; }
/* THE NOTE IS (PARTLY) DERIVED — owner ask 28.1. The dot is lit by the
   "CUSTOMS SCAN" line the sheet writes for a flagged shipment, not only by
   something a colleague typed, and the ring says so without spending a second
   colour on a 12px circle. OUTLINE, not box-shadow: the hover/focus rule above
   owns box-shadow and would swallow a ring drawn with it, and an outline takes
   no space, so a flagged row's NOTES column is exactly as wide as any other.
   The rim colour is the row's own scan rim, so it is only ever seen on the
   amber it belongs to. */
.cp-root .cp-note-dot.scan { outline: 2px solid var(--cp-scan-rim, #b8860b); outline-offset: 1px; }
.cp-root .cp-legend .cp-note-dot { cursor: default; }

.cp-root .cp-table td.dotc { text-align: center; }
.cp-root .cp-sdot {
    width: 18px; height: 18px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
    font-size: 0.6rem; font-weight: 900; color: #fff !important; cursor: help; border: 2px solid transparent;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.cp-root .cp-sdot:hover, .cp-root .cp-sdot:focus-visible { transform: scale(1.2); box-shadow: 0 0 0 3px color-mix(in srgb, var(--cp-txt-3) 26%, transparent); }
.cp-root .cp-sdot.ok { background: var(--cp-dot-ok); border-color: var(--cp-dot-ok-l); }
.cp-root .cp-sdot.ok::after { content: '\2713'; }
.cp-root .cp-sdot.warn { background: var(--cp-dot-warn); border-color: var(--cp-dot-warn-l); }
.cp-root .cp-sdot.warn::after { content: '\2022'; }
.cp-root .cp-sdot.bad { background: var(--cp-dot-bad); border-color: var(--cp-dot-bad-l); }
.cp-root .cp-sdot.bad::after { content: '!'; }
/* AN OPEN T1 TRANSIT DOCUMENT. The glyph is not decoration: it is what makes
   the tone survive a greyscale print, a colour-blind reader and the one blue
   this file could not get further away from (see --cp-dot-transit). */
.cp-root .cp-sdot.transit { background: var(--cp-dot-transit); border-color: var(--cp-dot-transit-l); }
.cp-root .cp-sdot.transit::after { content: 'T'; }
.cp-root .cp-sdot.off { background: transparent; border-color: var(--cp-dot-off-l); }
.cp-root .cp-sdot.off::after { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--cp-dot-off); }
.cp-root .cp-sdot.sm { width: 14px; height: 14px; font-size: 0.52rem; }

.cp-root .cp-table tr.emptyrow td { text-align: center; padding: 34px 10px; color: var(--cp-txt-3); white-space: normal; }
.cp-root .cp-table tr.emptyrow .big { font-size: 0.8rem; color: var(--cp-txt-2) !important; display: block; margin-bottom: 8px; }

.cp-root .cp-legend { display: flex; gap: 18px; flex-wrap: wrap; align-items: center; font-size: 0.63rem; color: var(--cp-txt-3) !important; padding: 0 3px; margin: 10px 0 0 var(--cp-gut); }
.cp-root .cp-legend .li { display: inline-flex; align-items: center; gap: 6px; color: var(--cp-txt-3) !important; }
.cp-root .cp-legend .rail-key { width: 3px; height: 13px; border-radius: 2px; display: inline-block; background: var(--cp-dot-bad); }

/* ==========================================================================
   BODY-LEVEL PORTALS — tooltip, separator popover, row context menu.
   They live on <body>, outside .cp-root, so they carry the palette themselves.
   ========================================================================== */
.cp-tip, .cp-seppop, .cp-ctx-menu {
    font-family: 'Inter', 'Space Grotesk', system-ui, sans-serif;
}
.cp-tip *, .cp-seppop *, .cp-ctx-menu * { box-sizing: border-box; }
.cp-seppop[hidden], .cp-tip[hidden] { display: none !important; }

/* ---------- tooltip (singleton portal: the worklist is an overflow box) ---------- */
div.cp-tip {
    position: fixed; z-index: 99999; background: var(--cp-tip-bg); color: var(--cp-txt-1);
    border: 1px solid var(--cp-tip-line); font-size: 0.66rem; padding: 9px 12px; border-radius: 9px;
    min-width: 196px; max-width: 290px; box-shadow: var(--cp-shadow);
    opacity: 0; visibility: hidden; transform: translateY(4px); transition: opacity 0.12s, transform 0.12s;
    pointer-events: none; line-height: 1.45;
}
div.cp-tip.show { opacity: 1; visibility: visible; transform: translateY(0); }
div.cp-tip::before {
    content: ''; position: absolute; top: -6px; left: var(--cp-arrow-left, 50%); margin-left: -6px;
    border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 6px solid var(--cp-tip-line);
}
div.cp-tip.flip { transform: translateY(-4px); }
div.cp-tip.flip.show { transform: translateY(0); }
div.cp-tip.flip::before { top: auto; bottom: -6px; border-bottom: none; border-top: 6px solid var(--cp-tip-line); }
div.cp-tip.wide { min-width: 236px; max-width: 345px; padding: 10px 13px 11px; }
.cp-tip .cp-tip-title {
    font-size: 0.58rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase;
    margin: 0 0 7px; padding-bottom: 6px; border-bottom: 1px solid var(--cp-tip-line);
    display: flex; align-items: center; gap: 7px; color: var(--cp-txt-1) !important;
}
.cp-tip .cp-tip-title .tdot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.cp-tip .cp-tip-title .tf { margin-left: auto; font-size: 0.56rem; font-weight: 700; letter-spacing: 0.05em; text-transform: none; color: var(--cp-txt-3) !important; font-variant-numeric: tabular-nums; }
.cp-tip .cp-tip-row { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; padding: 2.5px 0; }
.cp-tip .cp-tip-row .k { flex: 0 0 auto; color: var(--cp-txt-3) !important; font-size: 0.6rem; letter-spacing: 0.03em; }
.cp-tip .cp-tip-row .v { font-weight: 700; text-align: right; min-width: 0; color: var(--cp-txt-1) !important; }
.cp-tip .cp-tip-note { margin-top: 8px; padding-top: 7px; border-top: 1px dashed var(--cp-tip-line); color: var(--cp-txt-3) !important; font-size: 0.62rem; line-height: 1.55; }
/* a comment written on this very column, quoted inside its own signal */
.cp-tip .cp-tip-quote {
    margin-top: 9px; padding: 6px 9px 7px; border-left: 2px solid var(--cp-link);
    border-radius: 0 7px 7px 0; background: color-mix(in srgb, var(--cp-link) 10%, transparent);
    font-size: 0.65rem; line-height: 1.55; color: var(--cp-txt-1) !important;
}
.cp-tip .cp-tip-quote .cl { display: block; margin-bottom: 2px; font-size: 0.5rem; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--cp-link) !important; }
/* the note panel: up to three groups, carrier-facing first */
.cp-tip .cp-tip-g + .cp-tip-g { margin-top: 9px; padding-top: 9px; border-top: 1px dashed var(--cp-tip-line); }
.cp-tip .cp-tip-g .gh { display: flex; align-items: center; gap: 7px; margin-bottom: 4px; font-size: 0.55rem; font-weight: 800; letter-spacing: 0.11em; text-transform: uppercase; color: var(--cp-txt-3) !important; }
.cp-tip .cp-tip-g .gtag { flex: 0 0 auto; font-size: 0.5rem; font-weight: 800; letter-spacing: 0.07em; padding: 0 5px; border: 1px solid currentColor; border-radius: 4px; opacity: 0.9; }
.cp-tip .cp-tip-g .gtag.out { color: var(--cp-ok) !important; }
.cp-tip .cp-tip-g .gtag.in { color: var(--cp-link) !important; }
/* "part of this note was written by the sheet, not by a person" — the scan rim
   again, so the tag, the note dot's ring and the row band are one signal */
.cp-tip .cp-tip-g .gtag.scan { color: #e0a800 !important; }
:root[data-theme="light"] .cp-tip .cp-tip-g .gtag.scan { color: #8a6100 !important; }
.cp-tip .cp-tip-g .gt { font-size: 0.67rem; line-height: 1.6; color: var(--cp-txt-1) !important; }
/* the small print under a group — why a line is there, in the panel that shows
   the line, rather than in a legend nobody opens */
.cp-tip .cp-tip-g .gs { margin-top: 4px; font-size: 0.58rem; line-height: 1.5; color: var(--cp-txt-3) !important; }
.cp-tip .cp-tip-cc { display: flex; flex-direction: column; gap: 5px; }
.cp-tip .cp-tip-cc .cc { display: flex; align-items: baseline; gap: 7px; }
.cp-tip .cp-tip-cc .cl {
    flex: 0 0 auto; font-size: 0.5rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--cp-link) !important; background: color-mix(in srgb, var(--cp-link) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--cp-link) 42%, transparent); border-radius: 4px; padding: 1px 5px;
}
.cp-tip .cp-tip-cc .ct { flex: 1 1 auto; min-width: 0; font-size: 0.65rem; line-height: 1.55; color: var(--cp-txt-1) !important; }

/* ==========================================================================
   SEPARATOR ROWS — gutter rail, the row itself, and its popover
   ========================================================================== */
.cp-root .cp-sepgut {
    position: relative; flex: 0 0 var(--cp-gut); width: var(--cp-gut); align-self: stretch;
    overflow: hidden; border-radius: 10px 0 0 10px; transition: background 0.14s;
}
.cp-root .cp-sepgut::before {
    content: ''; position: absolute; left: 50%; top: 6px; bottom: 6px; width: 1px; margin-left: -0.5px;
    background: var(--cp-line); opacity: 0; transition: opacity 0.14s;
}
.cp-root .cp-sepgut:hover { background: color-mix(in srgb, var(--cp-txt-3) 10%, transparent); }
.cp-root .cp-sepgut:hover::before, .cp-root .cp-sepgut:focus-within::before { opacity: 0.85; }
.cp-root .cp-sepgut-h {
    position: absolute; left: 50%; top: 0; width: 16px; height: 16px; margin: -8px 0 0 -8px; padding: 0;
    display: flex; align-items: center; justify-content: center; line-height: 1;
    font-size: 0.74rem; font-weight: 800;
    border: 1px solid var(--cp-txt-3) !important; background: var(--cp-panel) !important; color: var(--cp-txt-2) !important;
    border-radius: 50%; box-shadow: var(--cp-shadow-sm);
    opacity: 0; pointer-events: none;
    transition: opacity 0.12s, background 0.12s, color 0.12s, border-color 0.12s, transform 0.12s;
}
.cp-root .cp-sepgut-h.on, .cp-root .cp-sepgut-h.near, .cp-root .cp-sepgut-h.act,
.cp-root .cp-sepgut-h:hover, .cp-root .cp-sepgut-h:focus-visible { opacity: 1; pointer-events: auto; }
.cp-root .cp-sepgut-h:hover, .cp-root .cp-sepgut-h.act { background: var(--cp-acc) !important; border-color: var(--cp-acc) !important; color: #fff !important; transform: scale(1.1); }
.cp-root .cp-sepgut-h:focus-visible { outline: 2px solid var(--cp-focus); outline-offset: 2px; border-radius: 50%; }

/* the separator paints itself from two per-row custom properties set inline by
   the renderer — a plain inline `background` would lose to the sheet-wide
   `background: transparent !important` above */
.cp-root .cp-table tbody tr.seprow td {
    padding: 0; border-bottom: 1px solid var(--cp-line-soft) !important;
    background: var(--cp-sep-bg, #475569) !important;
    color: var(--cp-sep-fg, #ffffff) !important;
}
.cp-root .cp-sep-inner { display: flex; align-items: center; height: 23px; overflow: hidden; }
/* the band is painted out of flow: a nowrap loop must never widen the table */
.cp-root .cp-sep-body { position: relative; align-self: stretch; flex: 1 1 auto; min-width: 0; width: 0; overflow: hidden; }
.cp-root .cp-sep-line, .cp-root .cp-sep-loop { position: absolute; left: 0; right: 0; }
.cp-root .cp-sep-line { top: calc(50% - 1px); display: block; height: 0; border-top: 2px solid currentColor; opacity: 0.7; }
.cp-root .cp-sep-loop {
    top: 50%; transform: translateY(-50%); display: block; white-space: nowrap; overflow: hidden;
    font-family: var(--cp-tblfont); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.14em; line-height: 1;
    color: inherit !important;
}
.cp-root .cp-sep-x {
    position: sticky; left: 5px; flex: 0 0 auto; margin-right: 6px; z-index: 3;
    width: 15px; height: 15px; padding: 0; line-height: 1; font-size: 0.6rem; font-weight: 800;
    display: flex; align-items: center; justify-content: center;
    border: 1px solid currentColor !important; border-radius: 4px; background: transparent !important; color: inherit !important;
    opacity: 0; transition: opacity 0.12s, background 0.12s;
}
.cp-root .seprow:hover .cp-sep-x, .cp-root .cp-sep-x:focus-visible { opacity: 0.85; }
.cp-root .cp-sep-x:hover { opacity: 1; background: rgba(0, 0, 0, 0.18) !important; }

div.cp-seppop {
    position: fixed; z-index: 1500; width: 270px;
    background: var(--cp-panel); border: 1px solid var(--cp-line); border-radius: 11px;
    box-shadow: var(--cp-shadow); padding: 11px 12px 12px; color: var(--cp-txt-1);
    font-size: 13px;
}
.cp-seppop input, .cp-seppop select, .cp-seppop textarea {
    background: var(--cp-field); color: var(--cp-txt-1); border: 1px solid var(--cp-line);
    border-radius: 6px; font-size: 0.72rem; padding: 6px 8px; font-family: inherit;
}
/* single-row planner-note editor — same popover shell as the separator picker */
div.cp-notepop { width: 320px; }
.cp-notepop textarea { width: 100%; resize: vertical; min-height: 74px; line-height: 1.5; }
.cp-seppop button { font-family: inherit; cursor: pointer; }
.cp-seppop :focus-visible { outline: 2px solid var(--cp-focus); outline-offset: 2px; }
.cp-seppop .sp-h { font-size: 0.58rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; color: var(--cp-txt-3) !important; margin-bottom: 8px; }
.cp-root .cp-seg, .cp-seppop .cp-seg { display: flex; border: 1px solid var(--cp-line); border-radius: 7px; overflow: hidden; background: var(--cp-field); }
.cp-root .cp-seg button, .cp-seppop .cp-seg button {
    flex: 1; background: transparent !important; border: none !important; color: var(--cp-txt-3) !important;
    font-size: 0.61rem; font-weight: 800; padding: 6px 4px; letter-spacing: 0.04em;
}
.cp-root .cp-seg button:hover, .cp-seppop .cp-seg button:hover { color: var(--cp-txt-1) !important; }
.cp-root .cp-seg button.on, .cp-seppop .cp-seg button.on { background: var(--cp-blue-strong) !important; color: #fff !important; }
.cp-seppop .cp-seg { margin-bottom: 9px; }
.cp-seppop .cp-seg button { font-size: 0.58rem; padding: 5px 4px; }
.cp-seppop .cp-sp-row { display: flex; flex-direction: column; gap: 4px; margin-bottom: 9px; }
.cp-seppop .cp-sp-row > label { font-size: 0.56rem; font-weight: 800; letter-spacing: 0.09em; text-transform: uppercase; color: var(--cp-txt-3) !important; }
.cp-seppop .cp-sp-row input[type=text] { width: 100%; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.06em; }
.cp-seppop .cp-sw { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.cp-seppop .cp-swb {
    width: 20px; height: 20px; border-radius: 5px; padding: 0; border: 1px solid var(--cp-line) !important;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14); transition: transform 0.1s, outline-color 0.1s;
    outline: 2px solid transparent; outline-offset: 1px;
}
.cp-seppop .cp-swb:hover { transform: translateY(-1px); }
.cp-seppop .cp-swb.on { outline-color: var(--cp-focus); }
.cp-seppop .cp-swc { width: 26px; height: 20px; padding: 0; border: 1px solid var(--cp-line); border-radius: 5px; background: var(--cp-field); cursor: pointer; }
.cp-seppop .cp-sp-prev { position: relative; border: 1px solid var(--cp-line); border-radius: 6px; overflow: hidden; display: block; height: 23px; }
.cp-seppop .cp-sp-prev .cp-sep-line { position: absolute; left: 0; right: 0; top: calc(50% - 1px); display: block; height: 0; border-top: 2px solid currentColor; opacity: 0.7; }
.cp-seppop .cp-sp-prev .cp-sep-loop {
    position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%);
    display: block; white-space: nowrap; overflow: hidden;
    font-family: var(--cp-tblfont); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.14em; line-height: 1; color: inherit !important;
}
.cp-seppop .cp-sp-f { display: flex; gap: 7px; justify-content: flex-end; margin-top: 11px; }
.cp-seppop .cp-btn {
    display: inline-flex; align-items: center; gap: 6px; font-size: 0.64rem; padding: 5px 11px; border-radius: 7px; font-weight: 700;
    border: 1px solid var(--cp-line) !important; background: var(--cp-tert) !important; color: var(--cp-txt-1) !important;
}
.cp-seppop .cp-btn:hover { background: var(--cp-hover) !important; }
.cp-seppop .cp-btn.primary { background: var(--cp-blue-strong) !important; border-color: var(--cp-blue-strong) !important; color: #fff !important; }
.cp-seppop .cp-btn.ghost { background: transparent !important; }

/* ==========================================================================
   CONTEXT MENU (row actions)
   ========================================================================== */
div.cp-ctx-menu {
    position: fixed; z-index: 1600; min-width: 232px; display: none;
    background: var(--cp-panel); border: 1px solid var(--cp-line); border-radius: 9px;
    box-shadow: var(--cp-shadow); padding: 5px; color: var(--cp-txt-1); font-size: 0.72rem;
}
div.cp-ctx-menu.visible { display: block; }
.cp-ctx-menu .cp-ctx-item { padding: 7px 10px; border-radius: 6px; cursor: pointer; white-space: nowrap; color: var(--cp-txt-1) !important; }
.cp-ctx-menu .cp-ctx-item:hover { background: var(--cp-hover); }
.cp-ctx-menu .cp-ctx-danger { color: var(--cp-bad) !important; }
.cp-ctx-menu .cp-ctx-sep { height: 1px; background: var(--cp-line); margin: 4px 2px; }

/* ---- the CUSTOMS SCAN section (owner ask 28.3) ----
   A section HEADING, exactly as the register's menu carries one: these two
   items write to another board's flag, and a heading is what stops them
   reading as two more planner actions. [hidden] already collapses the whole
   block through .cp-ctx-menu [hidden] further up. */
.cp-ctx-menu .cp-ctx-label {
    padding: 6px 10px 3px; font-size: 0.55rem; font-weight: 800; letter-spacing: 0.11em;
    text-transform: uppercase; color: var(--cp-txt-3) !important; cursor: default;
}
/* WHO flagged it and WHEN, under the item's own label. Block, not inline: the
   menu is white-space:nowrap and a name plus a timestamp on the same line would
   push it to whatever width the longest colleague's name happens to be. */
.cp-ctx-menu .cp-ctx-hint { display: block; margin-top: 2px; font-size: 0.58rem; color: var(--cp-txt-3) !important; }
.cp-ctx-menu .cp-ctx-hint:empty { display: none; }
/* An action that has already happened. It STAYS ON SCREEN and inert rather than
   disappearing — "already selected, by Anna at 09:12" is the answer to the
   question the reader opened the menu to ask. */
.cp-ctx-menu .cp-ctx-item.cp-ctx-off { opacity: 0.55; cursor: default; }
.cp-ctx-menu .cp-ctx-item.cp-ctx-off:hover { background: transparent; }
.cp-ctx-menu .cp-ctx-item:focus-visible { background: var(--cp-hover); outline: 2px solid var(--cp-focus); outline-offset: -2px; }

/* ==========================================================================
   MODALS — planner sections inside the app's .modal-overlay / .modal-panel
   ========================================================================== */
.modal-panel.cp-modal { width: 1000px; }
/* The dispatch modal carries a NINE-column shipment table. At 1200px the table
   only fitted because the row padding and the time field had been shaved, so
   the panel is widened to 1500px and the extra width is handed to the table
   (the sidebar keeps a fixed, sensible column). 94vw — not calc(100vw - 2rem) —
   so there is still a visible gutter on a 1100px viewport, and the inherited
   .modal-panel max-width keeps it inside the viewport regardless. */
.modal-panel.cp-modal-dispatch { width: min(1500px, 94vw); font-size: 0.8rem; }
/* the app's .modal-panel scrolls as one block (header + body + footer). These
   two modals are tall, so the panel becomes a flex column and only the BODY
   scrolls — the step header and the send footer stay put. */
.modal-panel.cp-modal { display: flex; flex-direction: column; overflow: hidden; }
.cp-modal > .modal-header, .cp-modal > .modal-footer { flex: 0 0 auto; }
.cp-modal > .modal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 16px 18px; }
/* [hidden] must beat the author display:flex/grid on .cp-mix-warn, .cp-mrow … */
.cp-modal [hidden], .cp-seppop [hidden], .cp-ctx-menu [hidden] { display: none !important; }
.cp-modal *, .cp-modal *::before, .cp-modal *::after { box-sizing: border-box; }
.cp-modal input:not([type=checkbox]),
.cp-modal select,
.cp-modal textarea {
    background: var(--cp-field); color: var(--cp-txt-1);
    border: 1px solid var(--cp-line); border-radius: 6px;
    font-size: 0.72rem; padding: 6px 8px; font-family: inherit; transition: border-color 0.14s;
}
.cp-modal input:not([type=checkbox]):hover,
.cp-modal select:hover,
.cp-modal textarea:hover { border-color: var(--cp-txt-3); }
.cp-modal input[type=checkbox] { accent-color: var(--cp-blue-strong); cursor: pointer; margin: 0; }
.cp-modal :focus-visible { outline: 2px solid var(--cp-focus); outline-offset: 2px; }
.cp-modal .cp-grow { flex: 1 1 auto; }
.cp-modal .cp-modal-grid { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 14px; align-items: start; }
/* Re-balanced with the wider panel: the sidebar (carrier/recipients + delivery
   & schedule) is a FIXED column that never stretches, so every pixel the panel
   gains lands on the shipment table. It steps down once, then stacks — the
   stack point sits just under 1400px so the "no internal scroll at 1400+"
   contract is met by the two-column layout and by the stacked one below it. */
.cp-modal-dispatch .cp-modal-grid { grid-template-columns: minmax(0, 1fr) 340px; gap: 18px; }
@media (max-width: 1560px) { .cp-modal-dispatch .cp-modal-grid { grid-template-columns: minmax(0, 1fr) 310px; gap: 16px; } }
@media (max-width: 1360px) { .cp-modal-dispatch .cp-modal-grid { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 880px) { .cp-modal .cp-modal-grid { grid-template-columns: minmax(0, 1fr); } }

.cp-modal .cp-msec { border: 1px solid var(--cp-line-soft); border-radius: 10px; padding: 12px 13px 13px; background: var(--cp-inset); }
.cp-modal .cp-msec + .cp-msec { margin-top: 12px; }
.cp-modal .cp-msec .lg {
    font-size: 0.58rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; color: var(--cp-txt-3) !important;
    display: flex; align-items: center; gap: 8px; margin-bottom: 9px;
}
.cp-modal .cp-msec .lg .stepn {
    width: 17px; height: 17px; border-radius: 50%; background: var(--cp-blue-strong); color: #fff !important;
    display: inline-flex; align-items: center; justify-content: center; font-size: 0.56rem; flex: 0 0 auto;
}
.cp-modal .cp-msec .lg .rt { margin-left: auto; text-transform: none; letter-spacing: 0; font-weight: 600; }
.cp-modal .cp-mrow { display: flex; flex-direction: column; gap: 5px; }
.cp-modal .cp-mrow + .cp-mrow { margin-top: 10px; }
.cp-modal .cp-mrow label { font-size: 0.62rem; font-weight: 700; color: var(--cp-txt-2) !important; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cp-modal .cp-mrow textarea { resize: vertical; min-height: 54px; line-height: 1.5; }
.cp-modal .cp-hint { font-size: 0.61rem; color: var(--cp-txt-3) !important; line-height: 1.5; }
.cp-modal .cp-hint.ok { color: var(--cp-ok) !important; }
.cp-modal .cp-hint.warnc { color: var(--cp-warn) !important; }
.cp-modal .cp-lead { font-size: 0.68rem; color: var(--cp-txt-2) !important; margin: 0 0 12px; }
.cp-modal .cp-recognized {
    display: inline-flex; align-items: center; gap: 5px; font-size: 0.57rem; font-weight: 800; letter-spacing: 0.05em;
    color: var(--cp-ok) !important; border: 1px solid var(--cp-ok); border-radius: 999px; padding: 1px 8px;
    background: color-mix(in srgb, var(--cp-ok) 12%, transparent);
}
.cp-modal .cp-mix-warn {
    display: flex; gap: 9px; align-items: flex-start; font-size: 0.64rem; line-height: 1.55; color: var(--cp-txt-1) !important;
    border: 1px solid var(--cp-warn); border-left: 3px solid var(--cp-warn); border-radius: 8px; padding: 8px 10px; margin-bottom: 10px;
    background: color-mix(in srgb, var(--cp-warn) 11%, transparent);
}
/* "N shipments with carrier Client are collected by the customer and are not
   dispatched" — same anatomy as .cp-mix-warn but INFORMATIONAL, not a warning:
   nothing is wrong, the planner simply left those lines out. Blue rail instead
   of amber so the two never read as the same severity. Both themes come free —
   every colour is a --cp-* var and the wash is a color-mix over transparent. */
.cp-modal .cp-excl-note {
    display: flex; gap: 9px; align-items: flex-start; font-size: 0.64rem; line-height: 1.55; color: var(--cp-txt-1) !important;
    border: 1px solid color-mix(in srgb, var(--cp-blue) 55%, transparent);
    border-left: 3px solid var(--cp-blue); border-radius: 8px; padding: 8px 10px; margin-top: 8px;
    background: color-mix(in srgb, var(--cp-blue) 10%, transparent);
}
.cp-modal .cp-excl-note > span:first-child { color: var(--cp-blue) !important; font-size: 0.86rem; line-height: 1.2; }
.cp-modal .cp-mship { border: 1px solid var(--cp-line-soft); border-radius: 9px; overflow: hidden; background: var(--cp-panel); }
.cp-modal .cp-mship .scroll { max-height: 236px; overflow: auto; }
.cp-modal .cp-mship table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 0.66rem; }
/* same themes.css table armour as the worklist */
.cp-modal .cp-mship th {
    position: sticky; top: 0; z-index: 1; background: var(--cp-tert) !important; color: var(--cp-txt-2) !important;
    font-size: 0.55rem; text-transform: uppercase; letter-spacing: 0.08em; text-align: left; padding: 6px 9px; font-weight: 800;
    border-color: var(--cp-line) !important; border-bottom: 1px solid var(--cp-line) !important;
}
.cp-modal .cp-mship td {
    padding: 5px 9px; background: transparent !important; color: var(--cp-txt-1) !important;
    border-bottom: 1px solid var(--cp-line-soft) !important;
}
.cp-modal .cp-mship tr:last-child td { border-bottom: none !important; }
.cp-modal .cp-mship tr.dim td { opacity: 0.38; }
.cp-modal .cp-mship tr:hover td { background: var(--cp-hover) !important; }
.cp-modal .cp-mship input[type=time] { width: 72px; padding: 2px 4px; font-size: 0.64rem; }
.cp-modal .cp-carrier-chip, .cp-root .cp-carrier-chip {
    display: inline-block; font-size: 0.57rem; font-weight: 800; letter-spacing: 0.05em; border-radius: 4px; padding: 1px 6px;
    background: color-mix(in srgb, var(--cp-link) 14%, transparent); color: var(--cp-link) !important;
    border: 1px solid color-mix(in srgb, var(--cp-link) 45%, transparent);
}
.cp-modal .cp-carrier-chip.none { background: transparent; color: var(--cp-txt-3) !important; border-color: var(--cp-dot-off-l); border-style: dashed; }
.cp-modal .cp-maillist { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 2px; }
.cp-modal .cp-mailchip { font-size: 0.58rem; padding: 2px 7px; border-radius: 5px; background: var(--cp-tert); border: 1px solid var(--cp-line); color: var(--cp-txt-2) !important; }
.cp-modal .cp-btn {
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; font-weight: 700;
    border: 1px solid var(--cp-line) !important; background: var(--cp-tert) !important; color: var(--cp-txt-1) !important;
    border-radius: 7px; padding: 7px 13px; font-size: 0.71rem;
}
.cp-modal .cp-btn:hover:not(:disabled) { background: var(--cp-hover) !important; }
.cp-modal .cp-btn.primary { background: var(--cp-blue-strong) !important; border-color: var(--cp-blue-strong) !important; color: #fff !important; }
.cp-modal .cp-btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* dispatch modal runs a step larger throughout */
.cp-modal-dispatch .cp-msec { padding: 14px 15px 15px; border-radius: 11px; }
.cp-modal-dispatch .cp-msec + .cp-msec { margin-top: 14px; }
.cp-modal-dispatch .cp-msec .lg { font-size: 0.68rem; letter-spacing: 0.11em; margin-bottom: 11px; gap: 9px; }
.cp-modal-dispatch .cp-msec .lg .stepn { width: 21px; height: 21px; font-size: 0.66rem; }
.cp-modal-dispatch .cp-mrow { gap: 7px; }
.cp-modal-dispatch .cp-mrow + .cp-mrow { margin-top: 13px; }
.cp-modal-dispatch .cp-mrow label { font-size: 0.74rem; }
.cp-modal-dispatch input:not([type=checkbox]), .cp-modal-dispatch select, .cp-modal-dispatch textarea { font-size: 0.78rem; padding: 8px 10px; }
.cp-modal-dispatch textarea { min-height: 64px; }
.cp-modal-dispatch input[type=checkbox] { width: 16px; height: 16px; }
.cp-modal-dispatch .cp-hint { font-size: 0.72rem; }
.cp-modal-dispatch .cp-btn { font-size: 0.78rem; padding: 9px 16px; border-radius: 8px; }
.cp-modal-dispatch .cp-recognized { font-size: 0.65rem; padding: 2px 9px; }
.cp-modal-dispatch .cp-mix-warn { font-size: 0.74rem; padding: 10px 12px; margin-bottom: 12px; }
.cp-modal-dispatch .cp-excl-note { font-size: 0.72rem; padding: 10px 12px; margin-top: 10px; }
.cp-modal-dispatch .cp-mailchip { font-size: 0.68rem; padding: 3px 9px; }
.cp-modal-dispatch .cp-seg button { font-size: 0.7rem; padding: 8px 6px; }
.cp-modal-dispatch .cp-mship .scroll { max-height: 270px; }
.cp-modal-dispatch .cp-mship table { font-size: 0.76rem; }
.cp-modal-dispatch .cp-mship th { font-size: 0.63rem; padding: 8px 10px; white-space: nowrap; }
.cp-modal-dispatch .cp-mship td { padding: 7px 10px; white-space: nowrap; }
.cp-modal-dispatch .cp-mship td.cp-uc { max-width: 170px; overflow: hidden; text-overflow: ellipsis; text-transform: uppercase; }
/* Chrome's intrinsic width for a time field at this size is ~80px — the two
   HH:MM segments PLUS the calendar-picker indicator, which alone eats 26px.
   Anything under that silently clips the last digit (the field has no
   scrollbar, so scrollWidth never reports it). 96px = intrinsic + headroom. */
.cp-modal-dispatch .cp-mship input[type=time] { width: 96px; padding: 5px 7px; font-size: 0.74rem; }
.cp-modal-dispatch .cp-carrier-chip { font-size: 0.66rem; padding: 2px 8px; }

/* ---------- release-note coverage tally ----------
   Numerator = ticked lines carrying a matched note, denominator = every ticked
   line, so the tally always describes the email that will actually be sent. */
.cp-modal .cp-rn-cov {
    display: flex; flex-direction: column; gap: 7px;
    margin: -2px 0 11px; padding: 10px 12px;
    border: 1px solid var(--cp-line); border-left: 3px solid var(--cp-dot-off-l);
    border-radius: 9px; background: var(--cp-panel);
    transition: border-color 0.16s, background 0.16s;
}
.cp-modal .cp-rn-cov.part { border-left-color: var(--cp-warn); }
.cp-modal .cp-rn-cov.full { border-left-color: var(--cp-ok); background: color-mix(in srgb, var(--cp-ok) 9%, var(--cp-panel)); border-color: color-mix(in srgb, var(--cp-ok) 40%, var(--cp-line)); }
.cp-modal .cp-rn-cov .rc-h { display: flex; align-items: baseline; gap: 10px; }
.cp-modal .cp-rn-cov .rc-t { font-size: 0.79rem; font-weight: 800; color: var(--cp-txt-1) !important; }
.cp-modal .cp-rn-cov.full .rc-t { color: var(--cp-ok) !important; }
.cp-modal .cp-rn-cov .rc-p { margin-left: auto; font-size: 0.7rem; font-weight: 800; color: var(--cp-txt-3) !important; white-space: nowrap; }
.cp-modal .cp-rn-cov.part .rc-p { color: var(--cp-warn) !important; }
.cp-modal .cp-rn-cov.full .rc-p { color: var(--cp-ok) !important; }
.cp-modal .cp-rn-meter { height: 6px; border-radius: 4px; background: var(--cp-tert); overflow: hidden; display: block; }
.cp-modal .cp-rn-meter i { display: block; height: 100%; border-radius: 4px; background: var(--cp-warn); transition: width 0.2s ease, background 0.2s; }
.cp-modal .cp-rn-cov.full .cp-rn-meter i { background: var(--cp-ok); }
.cp-modal .cp-rn-miss { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; font-size: 0.7rem; color: var(--cp-txt-3) !important; }
.cp-modal .cp-rn-miss b { color: var(--cp-txt-2) !important; font-weight: 700; margin-right: 2px; }
.cp-modal .cp-miss-chip {
    font-size: 0.68rem; font-weight: 800; white-space: nowrap;
    color: var(--cp-warn) !important; background: color-mix(in srgb, var(--cp-warn) 13%, transparent);
    border: 1px solid color-mix(in srgb, var(--cp-warn) 45%, transparent);
    border-radius: 5px; padding: 1px 7px;
}
.cp-modal .cp-miss-chip.more { color: var(--cp-txt-2) !important; background: var(--cp-tert); border-color: var(--cp-line); cursor: help; }
.cp-modal-dispatch .modal-footer.cov-warn { border-top-color: color-mix(in srgb, var(--cp-warn) 55%, var(--cp-line)); background: color-mix(in srgb, var(--cp-warn) 7%, transparent); }
.cp-modal .cp-foot { font-size: 0.72rem; line-height: 1.55; color: var(--cp-txt-3) !important; flex: 1 1 auto; min-width: 240px; text-align: left; }
.cp-modal .cp-foot b { color: var(--cp-txt-1) !important; }
.cp-modal .cp-foot .foot-tag { display: inline-flex; align-items: center; gap: 5px; font-weight: 800; }
.cp-modal .cp-foot .foot-tag.warn { color: var(--cp-warn) !important; }
.cp-modal .cp-foot .foot-tag.ok { color: var(--cp-ok) !important; }

/* ---------- release notes: ONE dropbox, a LIST of result cards ----------
   The three fixed trays are gone: a dispatch can carry any number of release
   notes, so the drop surface is single and the results grow downwards, one card
   per PDF, each with its own state. */
.cp-modal .cp-rn-lead { font-size: 0.72rem; color: var(--cp-txt-3) !important; line-height: 1.55; margin: -4px 0 11px; }
.cp-modal .cp-grow { flex: 1 1 auto; }
.cp-modal .cp-rndrop {
    position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px; text-align: center; cursor: pointer; min-height: 108px; padding: 14px 16px;
    border: 1.5px dashed var(--cp-line); border-radius: 10px; background: var(--cp-panel); color: var(--cp-txt-2);
    transition: border-color 0.14s, background 0.14s, box-shadow 0.14s;
}
.cp-modal .cp-rndrop:hover { border-color: var(--cp-acc); background: color-mix(in srgb, var(--cp-acc) 8%, var(--cp-panel)); }
.cp-modal .cp-rndrop.over { border-color: var(--cp-acc); border-style: solid; background: color-mix(in srgb, var(--cp-acc) 16%, var(--cp-panel)); box-shadow: inset 0 0 0 1px var(--cp-acc); }
.cp-modal .cp-rndrop.busy { border-color: var(--cp-blue); }
.cp-modal .cp-rndrop .rn-ico { font-size: 1.35rem; line-height: 1; }
.cp-modal .cp-rndrop .rn-t { font-size: 0.78rem; font-weight: 800; color: var(--cp-txt-1) !important; }
.cp-modal .cp-rndrop .rn-s { font-size: 0.67rem; color: var(--cp-txt-3) !important; line-height: 1.5; }
.cp-modal .cp-rndrop .rn-q { font-size: 0.66rem; font-weight: 800; letter-spacing: 0.04em; color: var(--cp-blue) !important; margin-top: 2px; }

.cp-modal .cp-rncards { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.cp-modal .cp-rncards:empty { display: none; }
.cp-modal .cp-rncard {
    display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
    padding: 9px 11px; text-align: left;
    border: 1.5px solid var(--cp-line); border-radius: 10px; background: var(--cp-panel); color: var(--cp-txt-2);
    transition: border-color 0.14s, background 0.14s;
}
.cp-modal .cp-rncard.queued { border-style: dashed; }
.cp-modal .cp-rncard.reading { border-color: var(--cp-blue); }
.cp-modal .cp-rncard.ok { border-color: var(--cp-ok); background: color-mix(in srgb, var(--cp-ok) 9%, var(--cp-panel)); }
.cp-modal .cp-rncard.bad { border-color: var(--cp-bad); background: color-mix(in srgb, var(--cp-bad) 9%, var(--cp-panel)); }
.cp-modal .cp-rncard .rn-h { display: flex; align-items: center; gap: 7px; width: 100%; font-size: 0.74rem; }
.cp-modal .cp-rncard .rn-h .rn-mark { font-size: 0.88rem; font-weight: 900; line-height: 1; flex: 0 0 auto; }
.cp-modal .cp-rncard.ok .rn-h .rn-mark { color: var(--cp-ok) !important; }
.cp-modal .cp-rncard.bad .rn-h .rn-mark { color: var(--cp-bad) !important; }
.cp-modal .cp-rncard.reading .rn-h .rn-mark, .cp-modal .cp-rncard.queued .rn-h .rn-mark { color: var(--cp-blue) !important; }
.cp-modal .cp-rncard .rn-file { font-weight: 800; color: var(--cp-txt-1) !important; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.cp-modal .cp-rncard .rn-s { font-size: 0.67rem; color: var(--cp-txt-3) !important; line-height: 1.5; }
.cp-modal .cp-rncard .rn-kv { display: flex; justify-content: space-between; gap: 10px; width: 100%; font-size: 0.7rem; color: var(--cp-txt-3) !important; }
.cp-modal .cp-rncard .rn-kv b { color: var(--cp-txt-1) !important; font-weight: 800; }
.cp-modal .cp-rncard .rn-msg { font-size: 0.7rem; line-height: 1.55; color: var(--cp-txt-2) !important; }
.cp-modal .cp-rncard .rn-msg b { color: var(--cp-bad) !important; }
.cp-modal .cp-rncard .rn-bar { width: 100%; height: 4px; border-radius: 3px; background: var(--cp-tert); overflow: hidden; margin-top: 5px; display: block; }
.cp-modal .cp-rncard .rn-bar i { display: block; height: 100%; width: 42%; border-radius: 3px; background: var(--cp-blue); animation: cpRnScan 1s ease-in-out infinite alternate; }
@keyframes cpRnScan { from { transform: translateX(-12%); } to { transform: translateX(150%); } }
.cp-modal .cp-rncard .rn-x {
    flex: 0 0 auto; font-size: 0.63rem; font-weight: 800; letter-spacing: 0.04em;
    border: 1px solid var(--cp-line) !important; background: var(--cp-tert) !important; border-radius: 6px; padding: 3px 9px; color: var(--cp-txt-2) !important;
}
.cp-modal .cp-rncard .rn-x + .rn-x { margin-left: 5px; }
.cp-modal .cp-rncard .rn-x:hover { background: var(--cp-hover) !important; color: var(--cp-txt-1) !important; }
/* The chip now carries the depot's FULL master name (what the carrier email
   prints, e.g. "APM1-Hutchison Ports Delta II"), so it must wrap inside its
   column/tray instead of stretching the layout. */
.cp-modal .cp-er-chip {
    display: inline-flex; align-items: center; gap: 5px; margin-top: 5px;
    max-width: 100%; white-space: normal; text-align: left; line-height: 1.3;
    font-size: 0.63rem; font-weight: 800; letter-spacing: 0.04em;
    color: var(--cp-ok) !important; background: color-mix(in srgb, var(--cp-ok) 13%, transparent);
    border: 1px solid color-mix(in srgb, var(--cp-ok) 48%, transparent); border-radius: 5px; padding: 2px 8px;
}
/* Amber + "?" ONLY when the reader flagged the depot as a guess — the title
   attribute carries the explanation, hence the help cursor. A high-confidence
   read (or an older result with no confidence flag) keeps the green chip above
   on both the tray and the shipment line. */
.cp-modal .cp-er-chip.low {
    color: var(--cp-warn) !important; background: color-mix(in srgb, var(--cp-warn) 13%, transparent);
    border-color: color-mix(in srgb, var(--cp-warn) 48%, transparent); cursor: help;
}
.cp-modal .cp-mship .cp-er-chip { margin-top: 0; font-size: 0.62rem; padding: 1px 7px; }
.cp-modal .cp-er-none { color: var(--cp-txt-3) !important; }

/* ==========================================================================
   SECTION 4 — "Release notes (PDF)", COMPACT (r9)
   Same information, roughly 40% of the vertical footprint: the section frame,
   the coverage tally, the helper line, the dropbox and every result card are
   all re-laid out as tight rows. Scoped to .cp-rn-sec so nothing else in the
   modal shrinks with it.
   ========================================================================== */
.cp-modal-dispatch .cp-msec.cp-rn-sec { padding: 11px 13px 12px; }
.cp-modal-dispatch .cp-rn-sec .lg { margin-bottom: 8px; }

/* tally: title + % on one line, a 4px meter, then the missing chips */
.cp-modal .cp-rn-sec .cp-rn-cov { gap: 5px; margin: -1px 0 8px; padding: 7px 10px; border-radius: 8px; }
.cp-modal .cp-rn-sec .cp-rn-cov .rc-t { font-size: 0.72rem; }
.cp-modal .cp-rn-sec .cp-rn-cov .rc-p { font-size: 0.68rem; }
.cp-modal .cp-rn-sec .cp-rn-meter { height: 4px; }
/* chips wrap into a short band — two rows max, the rest folds into "+N more" */
.cp-modal .cp-rn-sec .cp-rn-miss { gap: 4px; font-size: 0.66rem; max-height: 46px; overflow: hidden; }
.cp-modal .cp-rn-sec .cp-miss-chip { font-size: 0.65rem; padding: 0 6px; }

/* helper text: ONE line */
.cp-modal .cp-rn-sec .cp-rn-lead { font-size: 0.66rem; line-height: 1.4; margin: 0 0 8px; }

/* dropbox: a row, not a stack — still dashed, still the whole width, still the
   obvious target, but 56px instead of 108px */
.cp-modal .cp-rn-sec .cp-rndrop {
    flex-direction: row; align-items: center; justify-content: flex-start; flex-wrap: wrap;
    gap: 4px 10px; text-align: left; min-height: 0; padding: 10px 14px; border-radius: 9px;
}
.cp-modal .cp-rn-sec .cp-rndrop .rn-ico { font-size: 1.1rem; flex: 0 0 auto; }
.cp-modal .cp-rn-sec .cp-rndrop .rn-t { font-size: 0.74rem; }
.cp-modal .cp-rn-sec .cp-rndrop .rn-s { font-size: 0.65rem; }
.cp-modal .cp-rn-sec .cp-rndrop .rn-q { margin-top: 0; margin-left: auto; font-size: 0.64rem; }

/* result cards: one compact row per PDF */
.cp-modal .cp-rn-sec .cp-rncards { gap: 6px; margin-top: 8px; }
.cp-modal .cp-rn-sec .cp-rncard { gap: 4px; padding: 6px 9px; border-radius: 8px; border-width: 1px; }
.cp-modal .cp-rn-sec .cp-rncard .rn-h { flex-wrap: wrap; gap: 5px 8px; font-size: 0.72rem; }
.cp-modal .cp-rn-sec .cp-rncard .rn-mark { font-size: 0.82rem; }
.cp-modal .cp-rn-sec .cp-rncard .rn-file { flex: 0 1 auto; max-width: 250px; }
.cp-modal .cp-rn-sec .cp-rncard .rn-s { font-size: 0.65rem; }
.cp-modal .cp-rn-sec .cp-rncard .rn-msg { font-size: 0.67rem; line-height: 1.4; padding-left: 20px; }
.cp-modal .cp-rn-sec .cp-rncard .rn-bar { margin-top: 3px; height: 3px; }
.cp-modal .cp-rn-sec .cp-rncard .rn-x { padding: 2px 8px; font-size: 0.62rem; }
.cp-modal .cp-rn-sec .cp-rncard .cp-er-chip { margin-top: 0; font-size: 0.62rem; padding: 1px 7px; white-space: nowrap; max-width: 260px; overflow: hidden; text-overflow: ellipsis; display: inline-block; }
/* the two facts that used to be their own <span class="rn-kv"> lines */
.cp-modal .cp-rn-sec .cp-rncard .rn-pill {
    font-size: 0.65rem; font-weight: 800; white-space: nowrap; letter-spacing: 0.02em;
    border-radius: 5px; padding: 1px 7px; border: 1px solid var(--cp-line);
    background: var(--cp-tert); color: var(--cp-txt-1) !important;
}
.cp-modal .cp-rn-sec .cp-rncard .rn-pill.ref {
    color: var(--cp-link) !important; background: color-mix(in srgb, var(--cp-link) 12%, transparent);
    border-color: color-mix(in srgb, var(--cp-link) 42%, transparent);
}

/* ---------- edit multiples ---------- */
.cp-modal .cp-bsec-t { font-size: 0.58rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; color: var(--cp-txt-3) !important; margin: 14px 2px 7px; }
.cp-modal .cp-bsec-t:first-child { margin-top: 0; }
.cp-modal .cp-brow {
    display: grid; grid-template-columns: 16px minmax(0, 190px) minmax(0, 1fr); gap: 9px 11px; align-items: center;
    padding: 8px 11px; border: 1px solid var(--cp-line-soft); border-radius: 9px; background: var(--cp-inset);
    transition: border-color 0.14s, background 0.14s;
}
.cp-modal .cp-brow + .cp-brow { margin-top: 7px; }
.cp-modal .cp-brow:hover { border-color: var(--cp-txt-3); }
.cp-modal .cp-brow.on { border-color: var(--cp-acc); background: color-mix(in srgb, var(--cp-acc) 9%, var(--cp-inset)); }
.cp-modal .cp-brow .bname { font-size: 0.66rem; font-weight: 700; color: var(--cp-txt-2) !important; }
.cp-modal .cp-brow.on .bname { color: var(--cp-txt-1) !important; }
.cp-modal .cp-brow .bname small { display: block; font-size: 0.55rem; font-weight: 600; color: var(--cp-txt-3) !important; letter-spacing: 0.04em; }
.cp-modal .cp-brow .bctl { display: flex; align-items: center; gap: 8px; min-width: 0; }
.cp-modal .cp-brow .bctl > input, .cp-modal .cp-brow .bctl > select { flex: 1 1 auto; min-width: 0; }
.cp-modal .cp-brow:not(.on) .bctl { opacity: 0.35; pointer-events: none; }
.cp-modal .cp-brow .unchanged { font-size: 0.58rem; color: var(--cp-txt-3) !important; font-style: italic; }
.cp-modal .cp-brow.on .unchanged { display: none; }
.cp-modal .cp-chiplist { display: flex; flex-wrap: wrap; gap: 6px; }
.cp-modal .cp-rowchip {
    display: inline-flex; align-items: center; gap: 6px; font-size: 0.6rem; font-weight: 700;
    padding: 3px 9px; border-radius: 999px; background: var(--cp-panel); border: 1px solid var(--cp-line); color: var(--cp-txt-2) !important;
}
.cp-modal .cp-rowchip b { color: var(--cp-link) !important; }

/* ==========================================================================
   CALENDAR
   ========================================================================== */
.cp-root .cp-cal-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 330px; gap: 14px; align-items: start; }
@media (max-width: 1150px) { .cp-root .cp-cal-wrap { grid-template-columns: minmax(0, 1fr); } }
.cp-root .cp-cal-head { display: flex; align-items: center; gap: 11px; flex-wrap: wrap; padding: 9px 11px; background: var(--cp-panel); border: 1px solid var(--cp-line); border-radius: 11px; margin-bottom: 12px; }
.cp-root .cp-cal-head h3 { font-size: 0.8rem; font-weight: 800; margin: 0; color: var(--cp-txt-1) !important; }
.cp-root .cp-cal-head .wk { font-size: 0.66rem; color: var(--cp-txt-3) !important; }
/* the month the grid is showing — the anchor of the whole view, so it reads
   like a heading rather than like the hint text beside it */
.cp-root .cp-cal-head .wk.mo { font-size: 0.78rem; font-weight: 800; letter-spacing: 0.03em; color: var(--cp-txt-1) !important; min-width: 118px; text-align: center; }
/* ---- calendar header: info icon + range stats ----
   The legend used to be a 400-character run of prose across this header. It is
   now one icon whose data-cp-tip renderCal() rebuilds on every paint, shown by
   the planner's existing delegated tooltip portal (hover AND keyboard focus),
   so the header has room for figures instead of instructions. */
.cp-root .cp-cal-head .cp-info {
    flex: 0 0 auto;
    font-style: normal;
    font-size: 0.95rem;
    line-height: 1;
    cursor: help;
    color: var(--cp-txt-3) !important;
    border-radius: 999px;
    transition: color 0.15s ease;
}
.cp-root .cp-cal-head .cp-info:hover { color: var(--cp-acc) !important; }
.cp-root .cp-cal-head .cp-info:focus-visible {
    outline: none;
    color: var(--cp-acc) !important;
    box-shadow: 0 0 0 2px var(--cp-panel), 0 0 0 4px var(--cp-acc);
}

.cp-root .cp-calstats { display: flex; gap: 8px; flex: 0 0 auto; }

/* The stat rail's tile, sized for a header row. Everything but the scale is
   inherited from .cp-tile, so the two rails cannot drift into two looks.
   NOT interactive: these figures are week/month scoped while the rail's filter
   (state.flag) is global, so a click would filter to something other than what
   the label says. Hence no hover lift and no pointer. */
.cp-root .cp-tile.sm {
    padding: 5px 10px 6px 12px;
    min-width: 104px;
    border-radius: 8px;
    cursor: default;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.cp-root .cp-tile.sm:hover { transform: none; border-color: var(--cp-line) !important; }
.cp-root .cp-tile.sm .k { font-size: 0.52rem; letter-spacing: 0.08em; }
.cp-root .cp-tile.sm .v { font-size: 0.95rem; line-height: 1.1; }
.cp-root .cp-tile.sm .s { font-size: 0.53rem; }

/* ---- WEEK / MONTH toggle ----
   The dispatch modal's segmented control, sized down so it sits between the
   ‹ › navigator and the Today button without out-shouting either. Everything
   else — the frame, the active fill, the focus ring — is inherited. */
.cp-root .cp-cal-head .cp-seg.cp-calseg { flex: 0 0 auto; }
.cp-root .cp-cal-head .cp-seg.cp-calseg button { flex: 0 0 auto; padding: 5px 12px; font-size: 0.6rem; letter-spacing: 0.06em; }
/* ---- MONTH GRID ----
   Five weekday columns (Mon-Fri; Sat/Sun are never rendered) by as many week
   rows as the month needs. The whole month is meant to sit on one page, so the
   GRID is the scroller of last resort — never the page — and it only ever
   scrolls vertically, which keeps the worklist wrapper the one horizontal
   scroller in the pane. */
.cp-root .cp-cal-mwrap { min-width: 0; }
.cp-root .cp-cal-dows {
    display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 7px; margin: 0 0 5px;
}
.cp-root .cp-cal-dows span {
    text-align: center; font-size: 0.58rem; font-weight: 800; letter-spacing: 0.14em;
    text-transform: uppercase; color: var(--cp-txt-3) !important;
}
/* No max-height and no scroller of its own: the POINT of the month view is that
   every week row is laid out at once. overflow-x stays hidden so a long carrier
   name can never turn the grid into a second horizontal scroller. */
.cp-root .cp-cal-grid {
    display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 7px;
    align-content: start; overflow-x: hidden;
}

/* ---- WEEK GRID ----
   Exactly the same five weekday columns, but ONE row of them instead of five or
   six, so the height a month spends on week rows goes to the day columns: a
   week column shows CAL_WEEK_CARDS cards before the "+N more" valve where a
   month cell shows three. Nothing else about a day changes — same centred ratio
   pill, same today ring, same cards, same expander. */
.cp-root .cp-cal-grid.wk .cp-mcell { min-height: 300px; }
/* In a month cell the body stretches because the cell is barely taller than its
   three cards. A week column is taller than its ten, so the body sizes to its
   content instead and the "+N more" valve stays docked under the LAST card
   rather than floating at the foot of an empty column. */
.cp-root .cp-cal-grid.wk .cp-mcell-b { flex: 0 0 auto; }

/* one weekday of the month */
.cp-root .cp-mcell {
    display: flex; flex-direction: column; min-width: 0;
    background: var(--cp-panel); border: 1px solid var(--cp-line); border-radius: 9px;
    padding: 0 6px 6px; min-height: 88px;
}
.cp-root .cp-mcell.past { background: color-mix(in srgb, var(--cp-panel) 82%, var(--cp-bg)); }
/* a day from the neighbouring month keeps the grid rectangular but must never
   compete for attention */
.cp-root .cp-mcell.out { opacity: 0.42; border-style: dashed; background: transparent; }
.cp-root .cp-mcell.today { border-color: var(--cp-acc); box-shadow: inset 0 0 0 1px var(--cp-acc); }

/* header = [day no · count] over a CENTRED dispatch pill. The side padding is
   deliberately symmetric so the pill's optical centre is the cell's centre. */
.cp-root .cp-mcell-h {
    flex: 0 0 auto; display: flex; flex-direction: column; align-items: stretch; gap: 3px;
    margin: 0 -6px 4px; padding: 5px 7px 5px; border-bottom: 1px solid var(--cp-line-soft);
}
.cp-root .cp-mcell-h .hrow { display: flex; align-items: baseline; gap: 5px; min-width: 0; }
.cp-root .cp-mcell-h .dnum { font-size: 0.82rem; font-weight: 800; color: var(--cp-txt-1) !important; line-height: 1; }
.cp-root .cp-mcell-h .dmo { font-size: 0.54rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--cp-txt-3) !important; }
.cp-root .cp-mcell.today .dnum { color: var(--cp-acc) !important; }
.cp-root .cp-mcell-h .dcnt {
    margin-left: auto; font-size: 0.56rem; font-weight: 800; line-height: 1.5; white-space: nowrap;
    color: var(--cp-cal-meta) !important; background: var(--cp-tert);
    border: 1px solid var(--cp-line-soft); border-radius: 999px; padding: 0 6px;
}
.cp-root .cp-mcell-h .dcnt.has { color: var(--cp-ok) !important; background: color-mix(in srgb, var(--cp-ok) 14%, transparent); border-color: color-mix(in srgb, var(--cp-ok) 48%, transparent); }
.cp-root .cp-mcell-b { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
/* overflow valve: everything past the first CAL_CELL_CARDS cards is hidden
   until the cell is expanded, so a busy day cannot stretch its week row */
.cp-root .cp-mcell .cp-cal-row.hid { display: none; }
.cp-root .cp-mcell.expanded .cp-cal-row.hid { display: flex; }
.cp-root .cp-mmore {
    flex: 0 0 auto; margin-top: 4px; align-self: center; width: 100%;
    font-size: 0.55rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
    background: transparent !important; color: var(--cp-link) !important;
    border: 1px dashed var(--cp-line) !important; border-radius: 6px; padding: 2px 6px; line-height: 1.4;
}
.cp-root .cp-mmore:hover { border-color: var(--cp-link) !important; background: color-mix(in srgb, var(--cp-link) 10%, transparent) !important; }

/* THE VALVE WHEN IT IS HIDING A FLAGGED SHIPMENT.
   A month day cell shows 3 cards, ordered by TIME — so a flagged shipment can
   sit behind the "+N more" fold and its amber never reaches the screen at all
   (measured: 10 flagged in a real month, 0 visible). The cards keep their
   chronological order; this is what tells the planner there is something
   painted inside. Solid amber, not the dashed ghost, so it reads as a state
   rather than a control — and the button's aria-label names the count, so the
   signal is not colour-only. */
.cp-root .cp-mmore.cp-mmore-scan {
    background: #ffd43b !important;
    color: #1a1405 !important;
    border: 1px solid #b8860b !important;
    border-style: solid !important;
}
.cp-root .cp-mmore.cp-mmore-scan:hover {
    background: #f8c81f !important;
    border-color: #8c6609 !important;
}

.cp-root .cp-cal-empty { flex: 0 0 auto; font-size: 0.62rem; color: var(--cp-cal-meta) !important; text-align: center; padding: 18px 4px; border: 1px dashed var(--cp-line-soft); border-radius: 8px; }

/* the card = hairline severity rail + body. There are no status dots on it any
   more: four 6px dots were unreadable at month density and the text needs the
   horizontal room far more than the pod did. */
.cp-root .cp-cal-row {
    flex: 0 0 auto;
    text-align: left; width: 100%; background: var(--cp-inset) !important; border: 1px solid var(--cp-line-soft) !important;
    border-radius: 8px; padding: 0; overflow: hidden; color: var(--cp-txt-1) !important;
    display: flex; align-items: stretch; transition: border-color 0.12s, background 0.12s;
}
.cp-root .cp-cal-row:hover { background: var(--cp-hover) !important; border-color: var(--cp-txt-3) !important; }
.cp-root .cp-cal-row.arrived { opacity: 0.55; }
.cp-root .cp-rib { flex: 0 0 3px; width: 3px; align-self: stretch; background: var(--cp-rail, var(--cp-line)); }

.cp-root .cp-cal-row .bd { flex: 1 1 auto; min-width: 0; padding: 5px 8px; display: flex; flex-wrap: wrap; align-items: center; gap: 1px 6px; }
.cp-root .cp-cal-row .time { font-size: 0.75rem; font-weight: 800; letter-spacing: -0.02em; flex: 0 0 auto; order: 1; color: var(--cp-txt-1) !important; }
.cp-root .cp-cal-row .cp-carrier-chip { order: 2; flex: 0 0 auto; }
.cp-root .cp-cal-row .fr { font-size: 0.75rem; font-weight: 800; color: var(--cp-link) !important; order: 3; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cp-root .cp-cal-row .meta { order: 5; flex: 1 1 100%; min-width: 0; display: flex; align-items: center; gap: 3px; font-size: 0.69rem; color: var(--cp-cal-meta) !important; }
.cp-root .cp-cal-row .meta > span { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: inherit !important; }
/* a clipped customer is still recognisable, a clipped container number is not */
.cp-root .cp-cal-row .meta .cu { flex-shrink: 0.6; color: var(--cp-cal-strong) !important; font-weight: 700; }
.cp-root .cp-cal-row .meta .pr { flex-shrink: 1.1; color: var(--cp-cal-strong) !important; font-weight: 700; }
.cp-root .cp-cal-row .meta .co { flex-shrink: 1.5; }
.cp-root .cp-cal-row .meta i { flex: 0 0 auto; font-style: normal; opacity: 0.55; color: inherit !important; }
.cp-root .cp-cal-det { order: 6; flex: 1 1 100%; display: none; margin-top: 5px; padding-top: 5px; border-top: 1px dashed var(--cp-line); font-size: 0.6rem; color: var(--cp-cal-meta) !important; line-height: 1.65; }
.cp-root .cp-cal-row.open .cp-cal-det { display: block; }
.cp-root .cp-cal-det .kv { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.cp-root .cp-cal-det .kv > span:first-child { flex: 0 0 auto; color: inherit !important; }
.cp-root .cp-cal-det .kv b { color: var(--cp-cal-strong) !important; font-weight: 700; text-align: right; min-width: 0; }
.cp-root .cp-cal-det .kv.cmt { display: block; margin-top: 4px; }
.cp-root .cp-cal-det .kv.cmt > span:first-child { display: block; font-size: 0.55rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--cp-link) !important; }
.cp-root .cp-cal-det .kv.cmt b { display: block; text-align: left; font-weight: 600; }
.cp-root .cp-cal-det .acts { display: flex; gap: 6px; margin-top: 6px; align-items: center; }

/* A card inside a month cell is ONE line by default — time · carrier · file ref
   · release tick — and only opens up to the meta line and the detail block on
   click. This is the collapse that lets a month fit where a week used to. */
.cp-root .cp-mcell .cp-cal-row { border-radius: 6px; }
.cp-root .cp-mcell .cp-cal-row:not(.open) .bd { flex-wrap: nowrap; padding: 2px 5px; gap: 4px; }
.cp-root .cp-mcell .cp-cal-row:not(.open) .time { font-size: 0.75rem; }
.cp-root .cp-mcell .cp-cal-row:not(.open) .fr { font-size: 0.75rem; }
.cp-root .cp-mcell .cp-cal-row:not(.open) .cp-carrier-chip { font-size: 0.62rem; padding: 0 3px; letter-spacing: 0.03em; max-width: 62px; overflow: hidden; text-overflow: ellipsis; }
.cp-root .cp-mcell .cp-cal-row:not(.open) .meta { display: none; }
.cp-root .cp-mcell .cp-cal-row.open .bd { padding: 4px 6px; }
.cp-root .cp-mcell .cp-cal-row.open .meta { font-size: 0.69rem; }

/* ==========================================================================
   CALENDAR CARD · SELECTED FOR A CUSTOMS SCAN          (added 2026-08-12)
   Owner: "on cargo planner calendar, on row of shipment in scan, make row on
   calendar card orange background same as row to sync color map."
   The worklist has painted a flagged line amber since the scan round; the month
   grid did not, so the same shipment looked flagged on one screen and ordinary
   on the other. This block closes that, and ONLY that.

   WHO GETS IT — the card carries `.cp-cal-scan` when scanStateOf(r) is
   'selected'. RELEASED is deliberately not painted: released means the scan is
   over and the shipment is nobody's problem any more, so it goes back to
   looking like every other card. Never-flagged is obviously untouched.

   The amber itself is NOT declared here — it is spent from --cp-scan-bg /
   --cp-scan-rim, which this card is declared on up in the worklist scan block
   beside the table row that shares them. See the comment there for why.
   ========================================================================== */
.cp-root .cp-cal-row.cp-cal-scan {
    /* background-COLOR, never the `background` shorthand: .cp-cal-row's own
       declaration is a shorthand, and re-stating a shorthand here would reset
       background-clip / origin / size along with the colour for no reason. The
       rail is a CHILD element (.cp-rib), so it is out of reach either way.
       (0,3,0) + !important beats both `.cp-cal-row` (0,2,0 !important) and its
       `:hover` (0,2,1 !important), which is why the hover tone below has to be
       restated rather than left to the generic rule. */
    background-color: var(--cp-scan-bg) !important;
    border-color: var(--cp-scan-rim) !important;

    /* INK. Exactly the move the worklist zone makes (see td.cp-scanzone): every
       colour in this sheet resolves through these custom properties, so
       redefining them ON THE PAINTED CARD re-inks the card and everything
       inside it — including the `!important` colours on .time, .fr and the
       detail block — without a single specificity fight. Near-black on #ffd43b
       is ~13:1; the muted tier measures 5.5:1 and the link tier 6.6:1, all on
       the amber, so nothing inside the card drops below AA. */
    --cp-txt-1: #1a1405;
    --cp-txt-2: #3f3110;
    --cp-txt-3: #63501c;
    --cp-link:  #0b4a6f;   /* sky #38bdf8 is unreadable on amber */
    /* the card's own two ink tiers: .meta / .cp-cal-det read --cp-cal-meta and
       .cu / .pr / .kv b read --cp-cal-strong, and BOTH map to app tokens that
       are pale greys in dark theme — i.e. invisible on yellow. They are not
       optional extras: without them the opened detail block is the one part of
       the card that stays unreadable. */
    --cp-cal-meta:   #63501c;
    --cp-cal-strong: #1a1405;
    /* Dividers. --cp-line-soft is the register's own rim, same value the
       worklist seam uses. --cp-line is stepped one shade darker because inside
       the card it draws two things that sit ON the amber rather than beside it:
       the dashed rule above the opened detail, and the border of the "Open row
       →" ghost button, which needs to stay identifiable as a control. */
    --cp-line-soft: var(--cp-scan-rim);
    --cp-line: color-mix(in srgb, var(--cp-scan-rim) 72%, #1a1405);
    /* the ghost button inside the detail hovers to --cp-hover, which is a dark
       grey in dark theme — a black hole punched in the amber. A white wash
       keeps the hover a lightening, as it is everywhere else. The CARD's own
       hover never reaches this: it is overridden with the amber hover tone
       below, before this value is ever consulted. */
    --cp-hover: rgba(255, 255, 255, 0.42);
    /* the severity rail re-tints ITSELF from these. calCardEl() writes
       `--cp-rail: var(--cp-dot-bad|warn|ok|off)` as an INLINE custom property,
       and that var() is substituted with the element's own computed value — so
       redefining the family here reaches the rail without touching the JS. The
       pale tones vanish on yellow; this is the same stepped-down family the
       worklist zone uses, so the two rails match. Measured on #ffd43b: bad
       #b91c1c 4.5:1, warn #b45309 and ok #15803d 3.5:1 each, and the grey
       "nothing recorded yet" 3.4:1 — all above the 3:1 a non-text graphic
       needs, where the un-stepped originals sat at 2.2:1 (warn) and 2.3:1
       (ok) — indistinguishable from the amber they were drawn on. */
    --cp-dot-ok:   #15803d;  --cp-dot-ok-l:   #14532d;
    --cp-dot-warn: #b45309;  --cp-dot-warn-l: #92400e;
    --cp-dot-bad:  #b91c1c;  --cp-dot-bad-l:  #7f1d1d;
    --cp-dot-off:  #6b7280;  --cp-dot-off-l:  #4b5563;
    /* the release tick / cross and the "release sent" label are drawn in
       --cp-ok / --cp-bad, which are the THEME greens and reds (#22c55e is a
       highlighter on yellow). Pointing them at the stepped family keeps one
       glyph one meaning on both surfaces. */
    --cp-ok:  #15803d;
    --cp-bad: #b91c1c;
    /* the carrier chip needs no rule of its own: it is a --cp-link wash with a
       --cp-link border, so it followed the ink above by itself. */
}

/* Hover. The generic card hover repaints the background to --cp-hover and the
   border to --cp-txt-3; both would erase the flag, so the flagged card answers
   the pointer in the worklist's own deeper amber instead. Selection is not
   restated — the calendar has no selected card. */
.cp-root .cp-cal-row.cp-cal-scan:hover {
    background-color: var(--cp-scan-bg) !important;   /* #f8c81f via the shared block */
    border-color: var(--cp-scan-rim) !important;
}

/* ARRIVED (= checked in) stays faded, but not as far. `.arrived` is a flat
   opacity: .55, and opacity fades the TEXT and its background together, so on
   the amber card the meta line composites down to ~3:1 in dark theme and the
   detail block stops being readable — the one state where the flag would be
   both visible and useless. .78 still reads as clearly stood-down beside a live
   card (which is what "already checked in" has to say) while holding the ink
   above AA. Nothing else about the arrived state changes. */
/* ARRIVED + FLAGGED. Plain arrived cards fade to .55; that same .55 on an
   amber card composites the FILE REF to 2.57:1 in light theme — the card's
   primary identifier, unreadable. .78 was the first correction and still failed
   light AA (file ref 3.92:1, meta 3.36:1, both measured over the white day
   cell). .88 clears 4.5:1 on the text that matters while still reading as
   faded next to a live card. Dark theme was never the problem. */
.cp-root .cp-cal-row.cp-cal-scan.arrived { opacity: 0.88; }

/* Not restated on purpose, and each for a reason:
   · `.hid` / `.cp-mcell.expanded .hid` — pure display, and nothing in this
     block touches display, so the overflow valve is untouched: a hidden
     flagged card stays hidden until its day is expanded.
   · collapsed vs `.open` — pure layout (padding, font-size, flex-wrap, and
     which of .meta / .cp-rel-mk / .cp-rel-lbl / .cp-cal-det is shown). The
     amber is a colour only, so a card opens and closes exactly as before and
     no width, gap or padding moves — no layout shift on either state.
   · `:focus-visible` — .cp-root draws a 2px --cp-focus ring at 2px OFFSET,
     i.e. outside the card on the cell background, never on the amber. */

.cp-root .cp-unp { background: var(--cp-panel); border: 1px solid var(--cp-line); border-radius: 11px; padding: 11px; align-self: start; }
.cp-root .cp-unp h4 { font-size: 0.72rem; font-weight: 800; display: flex; align-items: center; gap: 8px; margin: 0; color: var(--cp-txt-1) !important; }
.cp-root .cp-unp h4 .cnt { background: color-mix(in srgb, var(--cp-bad) 15%, transparent); color: var(--cp-bad) !important; border: 1px solid var(--cp-bad); font-size: 0.58rem; border-radius: 999px; padding: 0 8px; font-weight: 800; }
.cp-root .cp-unp .sub { font-size: 0.69rem; color: var(--cp-cal-meta) !important; margin: 3px 0 10px; line-height: 1.5; }
.cp-root .cp-unp-list { display: flex; flex-direction: column; gap: 5px; max-height: 560px; overflow: auto; }
/* same anatomy as the calendar card, squeezed to three hairline rows; the Plan
   affordance is a full-height ghost arrow on the right edge */
/* flex:0 0 auto — the list is a capped flex column scroller, so without it the
   cards shrink to a few pixels once there are more of them than fit */
.cp-root .cp-unp-card { flex: 0 0 auto; background: var(--cp-inset); border: 1px solid var(--cp-line-soft); border-radius: 8px; padding: 0; overflow: hidden; font-size: 0.75rem; display: flex; align-items: stretch; }
/* FLAGGED, in the unplanned sidebar. Same amber literal as the worklist row and
   the calendar card (grouped at the top of this sheet), and the same ink
   re-definition trick: redefining the custom properties ON the painted card
   re-inks everything inside it — including the rail — without a specificity
   fight. `background-color`, never the shorthand: the base rule sets `overflow`
   and the shorthand would reset the layer. */
.cp-root .cp-unp-card.cp-unp-scan {
    background-color: var(--cp-scan-bg, #ffd43b) !important;
    border-color: var(--cp-scan-rim, #b8860b) !important;
    --cp-txt-1: #1a1405;
    --cp-txt-2: #3f3110;
    --cp-txt-3: #63501c;
    --cp-link:  #0b4a6f;
    --cp-cal-meta:   #63501c;
    --cp-cal-strong: #1a1405;
    --cp-line-soft: #b8860b;
    --cp-line:      #8c6609;
    --cp-inset:     #ffd43b;
    --cp-hover:     rgba(255, 255, 255, 0.42);
    --cp-ok:  #15803d;  --cp-bad: #b91c1c;
    --cp-dot-ok:   #15803d;  --cp-dot-ok-l:   #14532d;
    --cp-dot-warn: #b45309;  --cp-dot-warn-l: #92400e;
    --cp-dot-bad:  #b91c1c;  --cp-dot-bad-l:  #7f1d1d;
    --cp-dot-off:  #6b7280;  --cp-dot-off-l:  #4b5563;
}
.cp-root .cp-unp-card .bd { flex: 1 1 auto; min-width: 0; padding: 4px 7px 5px; display: flex; flex-direction: column; gap: 0; }
.cp-root .cp-unp-card .r1 { display: flex; align-items: center; gap: 6px; min-width: 0; line-height: 1.35; }
.cp-root .cp-unp-card .fr { font-weight: 800; color: var(--cp-link) !important; flex: 0 0 auto; font-size: 0.75rem; }
.cp-root .cp-unp-card .cu { color: var(--cp-cal-strong) !important; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1 1 auto; min-width: 0; }
.cp-root .cp-unp-card .cp-rel-mk { margin-left: auto; flex: 0 0 auto; display: inline-flex; font-size: 0.62rem; font-weight: 900; line-height: 1; }
.cp-root .cp-unp-card .cp-rel-mk.on { color: var(--cp-ok) !important; }
.cp-root .cp-unp-card .cp-rel-mk.off { color: var(--cp-bad) !important; }
.cp-root .cp-unp-card .cp-rel-mk.client { color: color-mix(in srgb, var(--cp-ok) 70%, var(--cp-txt-3)) !important; font-weight: 600; }
.cp-root .cp-unp-card .r2, .cp-root .cp-unp-card .r3 { color: var(--cp-cal-meta) !important; font-size: 0.69rem; line-height: 1.4; display: flex; align-items: center; gap: 5px; min-width: 0; }
.cp-root .cp-unp-card .r2 > span, .cp-root .cp-unp-card .r3 > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; color: inherit !important; }
.cp-root .cp-unp-card .r2 i, .cp-root .cp-unp-card .r3 i { flex: 0 0 auto; font-style: normal; opacity: 0.5; color: inherit !important; }
.cp-root .cp-unp-card .r2 .pr { color: var(--cp-cal-strong) !important; font-weight: 700; flex: 0 1 auto; }
.cp-root .cp-unp-card .plan-btn {
    flex: 0 0 24px; width: 24px; align-self: stretch; padding: 0;
    font-size: 0.76rem; font-weight: 800; line-height: 1;
    border: none !important; border-left: 1px solid var(--cp-line-soft) !important;
    background: transparent !important; color: var(--cp-blue-strong) !important; border-radius: 0;
}
.cp-root .cp-unp-card .plan-btn:hover { background: var(--cp-blue-strong) !important; color: #fff !important; }

/* ==========================================================================
   RELEASE-SENT TRACKING (v4)
   One fact — "a release note for this row actually went out on a dispatch
   email" — surfaced in four places: the worklist carrier cell, the dispatch
   modal's shipment list, the calendar cards and the calendar day header.
   Everything below runs on the same --cp-* tokens, so both themes follow.
   ========================================================================== */

/* The planner modals sit outside .cp-root, so its focus ring never reached
   them — and the release-note dropbox is now a keyboard target. */
.modal-panel.cp-modal :focus-visible { outline: 2px solid var(--cp-focus); outline-offset: 2px; border-radius: 4px; }

/* ---- worklist: the RELEASE column, immediately right of CARRIER ----
   Round 8 hung a "RELEASE SENT" badge under the carrier select; it is gone.
   The fact now has a column of its own, states both cases, and carries the
   same tooltip — so the row says it exactly once. */
.cp-root .cp-table td.relc { text-align: center; }
.cp-root .cp-relchip {
    display: inline-block; font-family: var(--cp-tblfont);
    font-size: 0.62rem; font-weight: 800; letter-spacing: 0.07em; line-height: 1.4; text-transform: uppercase;
    white-space: nowrap; border-radius: 4px; padding: 0 6px; cursor: help;
}
.cp-root .cp-relchip.sent {
    color: var(--cp-dot-ok) !important; background: color-mix(in srgb, var(--cp-dot-ok) 15%, transparent);
    border: 1px solid color-mix(in srgb, var(--cp-dot-ok) 55%, transparent);
}
/* not sent = an outstanding job, so it reads red — but dashed and washed out,
   never as loud as a hard failure */
.cp-root .cp-relchip.not {
    color: var(--cp-dot-bad) !important; background: color-mix(in srgb, var(--cp-dot-bad) 9%, transparent);
    border: 1px dashed color-mix(in srgb, var(--cp-dot-bad) 45%, transparent);
}
/* CLIENT-arranged transport — the customer books its own truck, so no release
   note will ever exist for this line. It says SENT because nothing is owed,
   but it is the OUTLINE of the real chip: no fill, lighter rule, lighter
   weight. Same green family (it is done, not a warning); an audit separates it
   from a genuine send on sight, and the tooltip spells the reason out. */
.cp-root .cp-relchip.client {
    color: var(--cp-dot-ok) !important; background: transparent;
    border: 1px solid color-mix(in srgb, var(--cp-dot-ok) 42%, transparent);
    font-weight: 600;
}

/* ---- dispatch modal: the three-state RELEASE SENT column ----
   The glyph is 19px but the words "Release sent" on one line were 102px, which
   pushed the whole column past the right edge of the section-1 scroller — i.e.
   an invisible column. The head still wraps to two lines and shrinks to its
   content (cheap, and it keeps the column at glyph width); the row padding is
   back to a comfortable 10px now that the panel itself is 1500px wide. */
.cp-modal .cp-mship th.c, .cp-modal .cp-mship td.c { text-align: center; }
.cp-modal-dispatch .cp-mship th.c { white-space: normal; width: 1%; line-height: 1.25; }
.cp-modal-dispatch .cp-mship td.c { width: 1%; }
.cp-modal-dispatch .cp-mship th { padding: 9px 10px; }
.cp-modal-dispatch .cp-mship td { padding: 10px 10px; }
/* Two free-text columns are capped so a long customer name or a full depot
   name ("APM1-Hutchison Ports Delta II") can never push the table past the
   scroller — they ellipsis / wrap inside their own column instead. */
.cp-modal-dispatch .cp-mship td.cp-uc { max-width: 160px; }
.cp-modal-dispatch .cp-mship td.cp-erc { max-width: 190px; white-space: normal; }
.cp-modal-dispatch .cp-mship td.cp-carr { max-width: 150px; overflow: hidden; text-overflow: ellipsis; }

/* ---- dispatch modal: a row whose release note ALREADY went out ----
   This is a POSITIVE state ("done, on an earlier dispatch"), so it is painted
   green — not dimmed. The tint sits on the <tr>, while the tick-state fade
   (opacity) stays on the <td>s: a td is background-transparent, so fading it
   fades the CELL CONTENT and leaves the row's green at full strength. That is
   how "already sent" wins over "unticked" without either state disappearing. */
.cp-modal .cp-mship tr.relsent { background: var(--cp-sent-row); }
.cp-modal .cp-mship tr.relsent td:first-child { box-shadow: inset 3px 0 0 var(--cp-ok); }
/* hover and tr:hover td both carry !important upstream, so the green hover has
   to be stated on the same td and out-specify it (4 classes vs 3). */
.cp-modal .cp-mship tr.relsent:hover td { background: var(--cp-sent-row-h) !important; }
/* unticked AND already sent: reduced emphasis, but nowhere near the 0.38 fade
   a plain unticked row gets — the text must stay readable on the green. */
.cp-modal .cp-mship tr.relsent.dim td { opacity: 0.68; }

/* ---- dispatch modal: a CLIENT-arranged-transport row ----
   Settled by THE ONE RELEASE RULE, but nothing was ever sent for it, so it
   carries roughly half the wash of a real send and an OUTLINE rail instead of
   a solid one. Same green family, unmistakably a lighter statement. */
.cp-modal .cp-mship tr.relclient { background: var(--cp-client-row); }
.cp-modal .cp-mship tr.relclient td:first-child {
    box-shadow: inset 3px 0 0 color-mix(in srgb, var(--cp-ok) 45%, transparent);
}
.cp-modal .cp-mship tr.relclient:hover td { background: var(--cp-client-row-h) !important; }
.cp-modal .cp-mship tr.relclient.dim td { opacity: 0.68; }

/* ---- dispatch modal: a line HELD FOR A CUSTOMS SCAN ("warn, but still allow")
   A FOURTH row state, and the only one that is not about the release note — so
   it must be able to sit ON TOP of `.relsent` / `.relclient` rather than
   replace them. It takes the RAIL (declared after both, so it wins the
   first-cell shadow) and leaves their green wash alone: "this shipment's
   release is settled AND customs is holding it" is a real combination and both
   halves have to survive.

   The rail and the chip are the register's own #b8860b / #ffd43b, the same two
   values the worklist paints with, so the modal is quoting the sheet behind it
   rather than inventing a second vocabulary. No wash on the row: the modal is a
   dense list on a panel, and a full amber band here would fight the green ones
   for the reader's eye — the rail plus the SCAN chip say it without shouting.
   Send stays enabled; nothing here disables anything. */
.cp-modal .cp-mship tr.cs-hold td:first-child { box-shadow: inset 3px 0 0 #b8860b; }
.cp-modal .cp-mship tr.cs-hold .cp-scan-chip { margin-left: 6px; }
/* the chip must stay readable when the LINE is unticked and faded */
.cp-modal .cp-mship tr.cs-hold.dim td:nth-child(3) { opacity: 0.62; }

/* the note under the shipment list. Same anatomy as .cp-mix-warn and
   .cp-excl-note; the amber rail is the register's rim so the three notes read
   as three severities of one family (amber warn / gold hold / blue info). */
.cp-modal .cp-scan-note {
    display: flex; gap: 9px; align-items: flex-start;
    font-size: 0.64rem; line-height: 1.55; color: var(--cp-txt-1) !important;
    border: 1px solid color-mix(in srgb, #b8860b 62%, transparent);
    border-left: 3px solid #b8860b; border-radius: 8px; padding: 8px 10px; margin-top: 8px;
    background: color-mix(in srgb, #ffd43b 12%, transparent);
}
.cp-modal-dispatch .cp-scan-note { font-size: 0.72rem; padding: 10px 12px; margin-top: 10px; }
.cp-modal .cp-scan-note > .cp-scan-chip { flex: 0 0 auto; margin-left: 0; cursor: default; }
/* the footer verdict, beside the release-note one — gold, not the amber
   `.warn`, because the two lines say different things and must not blur */
.cp-modal .cp-foot .foot-tag.scan { color: #b8860b !important; }
[data-theme="dark"] .cp-modal .cp-foot .foot-tag.scan { color: #e0a800 !important; }
.cp-modal .cp-rs {
    display: inline-flex; align-items: center; justify-content: center;
    width: 19px; height: 19px; border-radius: 50%; cursor: help;
    font-size: 0.72rem; font-weight: 900; line-height: 1; border: 1.5px solid transparent;
}
.cp-modal .cp-rs.sent { color: var(--cp-ok) !important; border-color: color-mix(in srgb, var(--cp-ok) 55%, transparent); background: color-mix(in srgb, var(--cp-ok) 13%, transparent); }
/* client-arranged transport: the SAME tick as a real send (both are done) with
   the fill taken out — the outline says "nothing was ever sent, none is due" */
.cp-modal .cp-rs.client { color: var(--cp-ok) !important; border-color: color-mix(in srgb, var(--cp-ok) 42%, transparent); background: transparent; font-weight: 700; }
.cp-modal .cp-rs.pend { color: var(--cp-warn) !important; border-color: color-mix(in srgb, var(--cp-warn) 55%, transparent); background: color-mix(in srgb, var(--cp-warn) 13%, transparent); }
.cp-modal .cp-rs.none { color: var(--cp-bad) !important; border-color: color-mix(in srgb, var(--cp-bad) 50%, transparent); background: color-mix(in srgb, var(--cp-bad) 11%, transparent); }

/* ---- dispatch modal: the day subtitle (calendar entry path only) ---- */
.cp-modal .cp-modal-day {
    font-size: 0.68rem; font-weight: 800; letter-spacing: 0.05em; white-space: nowrap;
    color: var(--cp-acc) !important; background: color-mix(in srgb, var(--cp-acc) 13%, transparent);
    border: 1px solid color-mix(in srgb, var(--cp-acc) 45%, transparent); border-radius: 999px; padding: 2px 10px;
}

/* ---- calendar: the day header's dispatch pill ----
   A real <button>, tab-reachable, and it is the day's release SCOREBOARD:
   "Dispatch release <settled>/<planned>" for that day. Tone is the whole point
   — a finished day must read done at a glance across 25 cells.
   `align-self: center` is what centres it on the day card. */
.cp-root .cp-mcell-h .cp-cal-dbtn {
    flex: 0 0 auto; align-self: center; max-width: 100%; overflow: hidden;
    display: inline-flex; align-items: center; justify-content: center; gap: 4px;
    font-size: 0.6rem; font-weight: 800; letter-spacing: 0.04em; font-variant-numeric: tabular-nums;
    border: 1px solid var(--cp-line) !important; background: var(--cp-tert) !important; color: var(--cp-txt-2) !important;
    border-radius: 999px; padding: 1px 9px; line-height: 1.45; white-space: nowrap;
}
.cp-root .cp-mcell-h .cp-cal-dbtn .ico { font-size: 0.56rem; line-height: 1; }
/* The LABEL. Both grids are five equal columns, so "Dispatch release" fits in
   week AND month at any normal window width; the short variant is a safety
   valve that only engages once a day column itself gets too narrow for the
   full phrase. A CONTAINER query, not a media query: the column's width is
   what decides, and it is not a fixed function of the viewport (the "not
   planned" sidebar drops away under 1150px and the columns get wider again).
   Never two lines, never clipped — the pill is nowrap and the label swap
   happens well before the text would reach the pill's max-width. */
.cp-root .cp-mcell-h { container-type: inline-size; container-name: cpday; }
.cp-root .cp-mcell-h .cp-cal-dbtn .lbl { letter-spacing: 0.02em; }
.cp-root .cp-mcell-h .cp-cal-dbtn .lb-short { display: none; }
/* 174px = the measured full-label pill (161px at its widest ratio) plus a
   safety margin; below it the day column can no longer hold the phrase. */
@container cpday (max-width: 174px) {
    .cp-root .cp-mcell-h .cp-cal-dbtn .lb-full { display: none; }
    .cp-root .cp-mcell-h .cp-cal-dbtn .lb-short { display: inline; }
}
.cp-root .cp-mcell-h .cp-cal-dbtn:hover:not(:disabled) { border-color: var(--cp-blue-strong) !important; background: var(--cp-blue-strong) !important; color: #fff !important; }
.cp-root .cp-mcell-h .cp-cal-dbtn:disabled { opacity: 0.4; cursor: not-allowed; }
/* every release out */
.cp-root .cp-mcell-h .cp-cal-dbtn.done {
    color: var(--cp-dot-ok) !important; background: color-mix(in srgb, var(--cp-dot-ok) 15%, transparent) !important;
    border-color: color-mix(in srgb, var(--cp-dot-ok) 60%, transparent) !important;
}
/* some out, some still owed */
.cp-root .cp-mcell-h .cp-cal-dbtn.part {
    color: var(--cp-dot-warn) !important; background: color-mix(in srgb, var(--cp-dot-warn) 15%, transparent) !important;
    border-color: color-mix(in srgb, var(--cp-dot-warn) 60%, transparent) !important;
}
/* cargo planned, not one release sent */
.cp-root .cp-mcell-h .cp-cal-dbtn.zero {
    color: var(--cp-dot-bad) !important; background: color-mix(in srgb, var(--cp-dot-bad) 13%, transparent) !important;
    border-color: color-mix(in srgb, var(--cp-dot-bad) 55%, transparent) !important;
}
.cp-root .cp-mcell-h .cp-cal-dbtn.none { opacity: 0.38; }

/* ---- calendar cards: the release label ----
   Collapsed the card shows a tick/cross on the single line; opened, the full
   label takes its own full-width row and the meta + detail move down a slot. */
.cp-root .cp-cal-row .cp-rel-lbl {
    display: none; order: 5; flex: 1 1 100%; min-width: 0; margin-top: 1px;
    font-size: 0.55rem; font-weight: 800; letter-spacing: 0.07em; text-transform: uppercase; cursor: help;
}
.cp-root .cp-cal-row.open .cp-rel-lbl { display: block; }
.cp-root .cp-cal-row .cp-rel-lbl.on { color: var(--cp-ok) !important; }
.cp-root .cp-cal-row .cp-rel-lbl.off { color: var(--cp-txt-3) !important; }
.cp-root .cp-cal-row .cp-rel-lbl.off::before { content: '✗ '; color: var(--cp-bad) !important; font-weight: 900; }
.cp-root .cp-cal-row .cp-rel-lbl.on::before { content: '✓ '; font-weight: 900; }
/* client-arranged transport — done family, lighter than a real send */
.cp-root .cp-cal-row .cp-rel-lbl.client { color: color-mix(in srgb, var(--cp-ok) 78%, var(--cp-txt-3)) !important; font-weight: 600; }
.cp-root .cp-cal-row .cp-rel-lbl.client::before { content: '✓ '; font-weight: 700; opacity: 0.8; }
.cp-root .cp-cal-row .meta { order: 6; }
.cp-root .cp-cal-det { order: 7; }
/* compact marker — the collapsed card's release state */
.cp-root .cp-cal-row .cp-rel-mk { display: inline-flex; order: 4; flex: 0 0 auto; margin-left: auto; font-size: 0.6rem; font-weight: 900; line-height: 1; }
.cp-root .cp-cal-row.open .cp-rel-mk { display: none; }
.cp-root .cp-cal-row .cp-rel-mk.on { color: var(--cp-ok) !important; }
.cp-root .cp-cal-row .cp-rel-mk.off { color: var(--cp-bad) !important; }
.cp-root .cp-cal-row .cp-rel-mk.client { color: color-mix(in srgb, var(--cp-ok) 70%, var(--cp-txt-3)) !important; font-weight: 600; }

/* ==========================================================================
   ROUND 19  ·  EDITABLE STATUS TEXT CELLS + PLANNED MARK + MULTI-NOTE TRAY
   --------------------------------------------------------------------------
   Freight / Release / Phyto stopped being coloured dots: they print the
   Shipments Register's own value as PLAIN TEXT and are click-to-edit. The
   colour that used to live on the dot lives on the row's severity rail, which
   already said the same thing — so the cell can be read instead of decoded.
   ========================================================================== */

/* ---- the cell ----
   FIXED WIDTH on the inner .cp-sval, and that is load-bearing: the worklist is
   a table-layout:AUTO grid and StatusPending locks its pending chip to the
   host's MEASURED content box. If the host shrank to fit the value, the chip's
   min-content contribution would jump from "OK-PCS" to "spinner + SAVING" and
   the auto algorithm would widen the whole column for the life of every
   request. A host already wider than either state can never move.
   (Same class of fix as the .status-cell / .pos-status-host rules in
   css/status-pending.css — the register grid learned it first.) */
.cp-root .cp-table td.cp-scell { text-align: center; padding-left: 6px; padding-right: 6px; }
.cp-root .cp-table td.cp-scell > .cp-sval {
    display: inline-flex; align-items: center; justify-content: center;
    width: 82px; min-width: 82px; max-width: 82px; height: 19px;
    overflow: hidden; white-space: nowrap;
    font-family: var(--cp-tblfont);
    font-size: 0.72rem; font-weight: 700; letter-spacing: 0.03em;
    color: var(--cp-txt-1) !important;
    border: 1px solid transparent; border-radius: 4px;
    cursor: pointer; user-select: none; -webkit-user-select: none;
    transition: background 0.12s ease, border-color 0.12s ease;
}
.cp-root .cp-table td.cp-scell > .cp-sval > .t {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}
/* nothing recorded is a real state, not a blank: the em dash is muted so the
   eye skips it, and the row's severity rail is what shouts about it */
.cp-root .cp-table td.cp-scell > .cp-sval > .t.empty { color: var(--cp-txt-3) !important; font-weight: 600; }
/* the cell IS a button: it has to look like one on hover and on keyboard focus */
.cp-root .cp-table td.cp-scell > .cp-sval:hover {
    background: color-mix(in srgb, var(--cp-acc) 16%, transparent);
    border-color: color-mix(in srgb, var(--cp-acc) 55%, transparent);
}
.cp-root .cp-table td.cp-scell > .cp-sval:focus-visible {
    outline: 2px solid var(--cp-focus); outline-offset: 1px;
    background: color-mix(in srgb, var(--cp-acc) 12%, transparent);
}

/* ---- ASKED / ASKED ACC — the register's own warning treatment ----
   css/table.css paints `.excel-table td.cell-warn` #fbff00 with #f12121 bold
   text (and re-asserts it at higher specificity for the light theme). The two
   colours are restated here rather than reached for across files: they are
   fixed hues in BOTH themes (a warning is not brand), the planner never enters
   table.css's `.excel-table` scope, and the planner's own
   `tbody td { background: transparent !important }` has to be beaten by an
   !important of equal weight at higher specificity. */
.cp-root .cp-table tbody td.cp-scell.warn { background: #fbff00 !important; }
.cp-root .cp-table tbody td.cp-scell.warn > .cp-sval > .t { color: #f12121 !important; font-weight: 700 !important; }
.cp-root .cp-table tbody td.cp-scell.warn > .cp-sval:hover { background: rgba(0, 0, 0, 0.09); border-color: rgba(0, 0, 0, 0.35); }
.cp-root .cp-table tbody td.cp-scell.warn > .cp-sval:focus-visible { outline-color: #b91c1c; background: rgba(0, 0, 0, 0.07); }
/* the pending spinner sits on that yellow too — keep its arc and label readable */
.cp-root .cp-table tbody td.cp-scell.warn .sp-pending { --sp-accent: #b45309; }
.cp-root .cp-table tbody td.cp-scell.warn .sp-label { color: #7c2d12 !important; }
/* NOTE — this neon and the customs-scan amber (#ffd43b) are two different
   signals and they NO LONGER MEET. FREIGHT / RELEASE / PHYTO sit to the right
   of the customs-scan seam, so a warn cell on a flagged row is neon on the
   panel, never neon on amber, and it keeps its full contrast (~10:1 against the
   dark panel, ~1.16:1 against the amber it used to sit on — which is what a
   reviewer measured, and why the paint was bounded at CARRIER).

   This rule therefore needs NO reinforcement for the flagged case and must not
   grow one: the fix is the boundary, not a special-case colour. If a future
   column order ever puts a `.cp-scell` back inside `td.cp-scanzone`, this
   comment is the record that it would be a regression, not a style choice. */

/* ---- CUSTOMS SCAN — the non-colour half of the flag ----
   The amber band says it at a glance, but hue alone is not a signal: a
   colour-blind reader, a greyscale print and a washed-out screen all need the
   word — and now that the band stops at CARRIER, the word is also what carries
   the fact to a reader whose eye is on the status columns. The chip sits inside
   the CONTAINER cell — the cell the register flags from, and well inside the
   painted zone — and is written by applyScanTo() as a text node, never as
   markup. Deep amber-brown on that amber, keyed to the register's #b8860b rim. */
/* The dispatch modal is rendered OUTSIDE #cpRoot (index.html), so it is named
   here explicitly — one chip definition for both surfaces, because the modal is
   quoting the worklist and a second, drifting chip would defeat the point. */
.cp-root .cp-table .cp-scan-chip,
.cp-root .cp-cal-row .cp-scan-chip,
.cp-modal .cp-scan-chip {
    display: inline-block; vertical-align: middle; margin-left: 6px;
    padding: 0 5px; border-radius: 3px;
    font-size: 0.58rem; font-weight: 800; letter-spacing: 0.09em; line-height: 1.5;
    color: #fff8e1 !important; background: #7c5000; border: 1px solid #4d3100;
    text-transform: uppercase; cursor: help;
}
/* ON A CALENDAR CARD the chip has to survive a much tighter box than a table
   cell: the collapsed card is a single line and the file ref must not be pushed
   out of it. Smaller, tighter tracking, and it never grows the line — the card
   is flex, so `flex:0 0 auto` stops it being stretched by the row. The colour
   is inherited from the shared rule above so the three surfaces cannot drift. */
.cp-root .cp-cal-row .cp-scan-chip {
    flex: 0 0 auto;
    margin-left: 4px; padding: 0 4px;
    font-size: 0.52rem; letter-spacing: 0.06em; line-height: 1.45;
    cursor: inherit;   /* the whole card is a button; a help cursor here lies */
}

/* StatusPending inside the cell: the host already holds the geometry, so the
   inline WIDTH lock may be released (it is what would otherwise re-enter the
   auto-layout intrinsic calculation). The inline HEIGHT lock is untouched. */
.cp-root .cp-table td.cp-scell > .cp-sval > .sp-pending,
.cp-root .cp-table td.cp-scell > .cp-sval > .sp-failed { width: auto !important; max-width: 100%; }
.cp-root .cp-table td.cp-scell > .cp-sval .sp-label { font-size: 0.55rem; }

/* ---- PLANNED: an ✗ when nothing has been dispatched ----
   A hollow dot said "off"; a cross says "still to do", which is what the column
   is for. Carrier-Client rows keep the hollow dot (see plannedCell) — nobody
   owes that shipment a dispatch, so it must not be marked outstanding. */
.cp-root .cp-nomark {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; border-radius: 4px;
    font-size: 0.86rem; font-weight: 900; line-height: 1;
    color: var(--cp-dot-bad) !important; cursor: help;
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.cp-root .cp-nomark:hover, .cp-root .cp-nomark:focus-visible {
    transform: scale(1.18); box-shadow: 0 0 0 3px color-mix(in srgb, var(--cp-dot-bad) 24%, transparent);
}
.cp-root .cp-legend .cp-nomark { cursor: default; width: auto; height: auto; }

/* ---- the compacted legend ----
   Rebuilt by renderLegend() so it can only describe what renderTable() paints.
   One tidy line from ~1400px up; it wraps rather than clips below that. */
.cp-root .cp-legend { gap: 14px; }
.cp-root .cp-legend .lk-txt { color: var(--cp-txt-2) !important; font-weight: 800; letter-spacing: 0.04em; }
.cp-root .cp-legend .lk-warn {
    background: #fbff00; color: #f12121 !important; font-weight: 700;
    border-radius: 3px; padding: 0 4px; letter-spacing: 0.03em;
}
.cp-root .cp-legend .cp-sdot { cursor: default; }
/* the customs-scan key: the row colour and the chip in one swatch, so the
   legend shows exactly what the sheet paints */
.cp-root .cp-legend .lk-scan {
    background: #ffd43b; color: #4d3100 !important; font-weight: 800;
    border: 1px solid #b8860b; border-radius: 3px;
    padding: 0 4px; font-size: 0.62rem; letter-spacing: 0.07em;
}
.cp-root .cp-legend .lk-sub { color: var(--cp-txt-3) !important; font-style: italic; }

/* ---- dispatch modal: select-all in the section-1 header ---- */
.cp-modal-dispatch .cp-mship thead th:first-child { text-align: center; padding-left: 6px; padding-right: 6px; }
.cp-modal-dispatch .cp-mship thead th:first-child input[type=checkbox] { cursor: pointer; vertical-align: middle; }
.cp-modal-dispatch .cp-mship thead th:first-child input[type=checkbox]:disabled { cursor: not-allowed; opacity: 0.45; }

/* ---- dispatch modal: MORE THAN ONE release note on one shipment ----
   The ×N badge beside the RELEASE SENT glyph, and the card pills naming which
   note of the set a card is. The mark itself never changes: a line is covered
   once whether it carries one note or five. */
.cp-modal .cp-rs-n {
    display: inline-block; margin-left: 4px; vertical-align: middle;
    font-size: 0.58rem; font-weight: 900; letter-spacing: 0.02em; line-height: 1.5;
    color: var(--cp-warn) !important; background: color-mix(in srgb, var(--cp-warn) 15%, transparent);
    border: 1px solid color-mix(in srgb, var(--cp-warn) 50%, transparent);
    border-radius: 999px; padding: 0 5px; cursor: help;
}
.cp-modal .cp-rs.pend.multi { border-style: double; border-width: 3px; }
.cp-modal .cp-rncard .rn-pill.seq {
    color: var(--cp-warn) !important; background: color-mix(in srgb, var(--cp-warn) 14%, transparent);
    border-color: color-mix(in srgb, var(--cp-warn) 48%, transparent); font-weight: 800;
}
.cp-modal .cp-rncard .rn-pill.ref.multi {
    border-style: dashed; border-color: color-mix(in srgb, var(--cp-warn) 55%, transparent);
}
/* a second empty-return depot read from a second note: shown, but visibly NOT
   the one the email will carry (the payload holds one depot per shipment) */
.cp-modal .cp-er-chip.alt {
    opacity: 0.6; text-decoration: line-through; text-decoration-thickness: 1px;
    border-style: dashed;
}

/* ---- reduced motion ----
   The planner's global reduce block cancels animation inside .cp-root, which
   would freeze the StatusPending ring mid-arc and leave a static broken circle.
   Give that reader a pulse instead, so "working" stays visible without spin. */
@keyframes cpSpPulse { 0%, 100% { opacity: 0.28; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
    .cp-root .cp-table td.cp-scell .sp-spinner {
        animation: cpSpPulse 1.4s ease-in-out infinite !important;
        border-color: var(--sp-accent) !important;
    }
}

/* ==========================================================================
   ROUND 20  ·  BRAND UNDER THE PRODUCT · DISPATCH-PENDING CELLS · AFFORDANCE
   ========================================================================== */

/* ---- PRODUCT: the brand on a second line, for banana rows only ----
   Byte-for-byte the CONTAINER cell's treatment (`.cont b` / `.cont .muted`),
   because it IS the same treatment — one product over its brand reads exactly
   like one container over its BL. Scoped to `.stacked`, which renderTable only
   emits for a single-product banana row carrying a brand, so no other row grows
   a second line. `.prod`'s own max-width + ellipsis still bound both lines. */
.cp-root .cp-table .prod.stacked b { display: block; font-weight: 800; color: var(--cp-txt-1) !important; }
.cp-root .cp-table .prod.stacked .muted {
    display: block; margin-top: 1px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}

/* ---- PLANNED / REL. NOTE: the two cells a DISPATCH drives ----
   Same load-bearing geometry rule as `.cp-sval` above: the worklist is a
   table-layout:AUTO grid and StatusPending locks its chip to the host's
   MEASURED content box, so a host that is already wider than BOTH its resting
   mark and its pending chip is the only thing that stops the column widening
   for the life of every request. 62px clears "SENDING" + the 13px ring; both
   columns' headers ("Planned", "Rel. note") are wider than that, so the fixed
   host cannot become the column's intrinsic width in the first place. */
.cp-root .cp-table td.plannedc > .cp-planhost,
.cp-root .cp-table td.relc > .cp-relhost {
    display: inline-flex; align-items: center; justify-content: center;
    width: 62px; min-width: 62px; max-width: 62px; height: 19px;
    overflow: hidden; white-space: nowrap;
}
/* the host holds the geometry, so the chip's own inline width lock is released
   — leaving it in would re-enter the auto-layout intrinsic calculation */
.cp-root .cp-table td.plannedc > .cp-planhost > .sp-pending,
.cp-root .cp-table td.plannedc > .cp-planhost > .sp-failed,
.cp-root .cp-table td.relc > .cp-relhost > .sp-pending,
.cp-root .cp-table td.relc > .cp-relhost > .sp-failed { width: auto !important; max-width: 100%; }
.cp-root .cp-table td.plannedc > .cp-planhost .sp-label,
.cp-root .cp-table td.relc > .cp-relhost .sp-label { font-size: 0.55rem; }

/* ---- M4: the status cells LOOK editable when nothing is hovering them ----
   Freight / Release / Phyto are the only click-to-edit cells on the sheet whose
   affordance was hover-only — every other editable cell carries a control's
   border at rest. A hairline does it: it is inside the fixed 82px host, so it
   costs no width, and hover/focus still take over from it. */
.cp-root .cp-table td.cp-scell > .cp-sval { border-color: var(--cp-line-soft); }
.cp-root .cp-table tbody td.cp-scell.warn > .cp-sval { border-color: rgba(0, 0, 0, 0.28); }

/* the dispatch spinner obeys reduced motion exactly as the status cells' does */
@media (prefers-reduced-motion: reduce) {
    .cp-root .cp-table td.plannedc .sp-spinner,
    .cp-root .cp-table td.relc .sp-spinner {
        animation: cpSpPulse 1.4s ease-in-out infinite !important;
        border-color: var(--sp-accent) !important;
    }
}

/* ---- severity: "nothing recorded" is its own, neutral tone (round 20) ----
   A blank freight / release / phyto used to score `bad`, which red-railed all
   59 local rows and made "Action needed" meaningless. Blank now scores `none`
   and reads in the same muted tone the planner already uses for "nothing here"
   (.cp-sdot.off). It is deliberately NOT green: not-yet-recorded is not
   confirmed. */
.cp-root .cp-sevbar i.none { background: var(--cp-dot-off); }
.cp-root .cp-legend .rail-key.none { background: var(--cp-dot-off); }

/* ==========================================================================
   LEGEND — HIDDEN "FOR NOW"                            2026-08-12
   Owner: "remove the footer description map for now - hide on cargo planner."
   FOR NOW is the whole point, so this is one rule and nothing else: the markup
   in index.html is untouched, renderLegend() still runs and still rebuilds the
   contents on every render, and every .cp-legend rule above (the dot keys, the
   ASKED/MISSING wash, the SCAN swatch, the rail keys) is left exactly where it
   is. Deleting THIS ONE RULE brings the footer back, complete, with no other
   file involved.
   `!important` because the declaration at the top of the legend block sets
   `display: flex` at the same (0,2,0) specificity — without it the winner would
   depend on which of the two happened to be further down the file.
   No gap is left behind: the legend's `margin: 10px 0 0 var(--cp-gut)` goes
   with the box (a display:none element generates no box and therefore no
   margin), and its parent #cpViewPlanner is plain block layout with no `gap`
   of its own, so the worklist shell is simply the last thing on the pane and
   .cp-root's own 2.5rem bottom padding closes the page as before.
   ========================================================================== */
.cp-root .cp-legend { display: none !important; }

/* ==========================================================================
   REL. NOTE, SET BY HAND                                 P3 · 2026-08-12
   ==========================================================================
   Owner: "allow user on cargo planner to change the rel.note status manually
   like phyto button (tooltip on top and 2 options, sent / not set)".

   Two things to draw, and one thing that must not move.

   1 · THE CELL IS A BUTTON NOW. It gets the affordance the three status cells
       already have — a tint and a rule on hover, the sheet's own focus ring on
       keyboard focus — so the one editable cell that never advertised itself
       stops being the odd one out. The tint is painted with an INSET
       box-shadow, not a border: the host is a fixed 62px box whose width is
       load-bearing (it is what stops the column widening for the life of every
       write, see the geometry block above), and a border would spend two of
       those pixels on every row that is merely hovered.

   2 · A HAND-SET VALUE MUST NOT READ AS A DERIVED ONE, AND NOT BY COLOUR. The
       chip's three tones are already spoken for — filled green (sent), dashed
       red (not sent), outline green (carrier Client) — and a fourth tone would
       say "another kind of release" when what has changed is the AUTHORITY, not
       the state. Two SHAPE cues carry it instead: a dotted underline under the
       word and a small folded corner. Both survive greyscale, both survive a
       colour-blind reader, and neither costs a single pixel — text-decoration
       never enters layout, and the fold is an absolutely-positioned ::after
       inside the chip's own padding box. The reason, and who set it, are in the
       tooltip the chip has always carried.

   Both themes come free: every colour here is either currentColor (the chip's
   own tone, which the light theme has already re-inked) or the shared --cp-acc
   / --cp-focus pair, which both palettes define.
   ========================================================================== */

/* ---- 1 · the cell is a button ---- */
.cp-root .cp-table td.relc > .cp-relhost {
    cursor: pointer; user-select: none; -webkit-user-select: none;
    border-radius: 5px;
    transition: background 0.12s ease, box-shadow 0.12s ease;
}
.cp-root .cp-table td.relc > .cp-relhost:hover {
    background: color-mix(in srgb, var(--cp-acc) 14%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--cp-acc) 55%, transparent);
}
.cp-root .cp-table td.relc > .cp-relhost:focus-visible {
    outline: 2px solid var(--cp-focus); outline-offset: 1px;
    background: color-mix(in srgb, var(--cp-acc) 12%, transparent);
}
/* the chip is decoration inside that button: `cursor: help` was right while
   hovering it was the only thing it did, and would now under-sell the cell */
.cp-root .cp-table td.relc > .cp-relhost > .cp-relchip { cursor: inherit; }

/* ---- 2 · the hand-set marker ---- */
.cp-root .cp-relchip[data-manual],
.cp-root .cp-rel-lbl[data-manual],
.cp-root .cp-rel-mk[data-manual] {
    text-decoration: underline dotted currentColor;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}
/* the folded corner — worklist chip only. The calendar's mark is a single
   glyph and its label sits in a one-line card: there is no corner to fold in
   either, and the underline alone is the cue there. */
.cp-root .cp-relchip[data-manual] { position: relative; }
.cp-root .cp-relchip[data-manual]::after {
    content: ''; position: absolute; top: 1px; right: 1px;
    width: 0; height: 0;
    /* inset by a pixel so the fold sits INSIDE the chip's rule instead of
       cutting across it — the chip's own border is one of the three tones and
       must stay unbroken */
    border-top: 5px solid currentColor;
    border-left: 5px solid transparent;
    opacity: 0.9;
}

/* The pending spinner and the RETRY chip take the host over completely, so the
   button chrome underneath them would draw a second, contradicting box around a
   cell that is mid-write. */
.cp-root .cp-table td.relc > .cp-relhost[aria-busy="true"]:hover,
.cp-root .cp-table td.relc > .cp-relhost[data-sp="failed"]:hover {
    background: transparent; box-shadow: none;
}

/* ===========================================================================
   REL. NOTE PICKER — ONE ROW, OTHERWISE IDENTICAL TO EVERY OTHER PICKER
   ---------------------------------------------------------------------------
   The only thing wrong with this picker was that its options STACKED: two of
   the three carried `full: true`, which gives an option a whole row of its own
   at the foot of the popover. Dropping that flag (see REL_POP_DEF in
   cargo-planner.js) puts all three side by side, because `.cell-popover-opts`
   is already `row wrap`.

   NOTHING ELSE IS RESTYLED, deliberately. The buttons keep the shared look —
   icon above the label, the same padding, the same min-width — so this picker
   reads exactly like the phyto, freight and release ones next to it. An earlier
   cut of this block also flipped the buttons to icon-beside-label and shrank
   their padding; that made this one picker a stranger among its siblings.

   What remains here is only what the shared sheet cannot express:
     · never wrap — three short options belong on one line, and a wrap would
       reintroduce the stack this change exists to remove;
     · neutralise `full` WITHIN this popover, so re-adding that flag in a future
       edit of the options array cannot silently bring the column back.

   Scoped to `.cp-relpop`, which mountPop() hands to CellPopover.open() as
   `opts.cls` — it must arrive BEFORE the popover is measured, or it is anchored
   at one size and re-laid-out to another and ends up floating off its cell.
   Written here rather than in css/table.css because that sheet holds the shared
   popover for the whole app and belongs to another workstream. `.cell-popover`
   is appended to <body>, so these selectors are not `.cp-root`-scoped like the
   rest of this file.
   =========================================================================== */
.cell-popover.cp-relpop .cell-popover-opts { flex-wrap: nowrap; }

.cell-popover.cp-relpop .cell-popover-btn.cell-popover-btn-full {
    flex: 0 1 auto;
    flex-direction: column;
    margin-top: 0;
    padding: 8px 10px;
}

/* ==========================================================================
   HEADER v4 — owner-approved mockup "F", 2026-10-04
   label row · one command deck · day tabs on a sheet · one filter row.
   Appended LAST so it wins over the v3 header rules above at equal
   specificity; the v3 .cp-tile rules stay because the calendar's stat strip
   still uses them. Same .cp-root anchoring + !important-on-paint convention
   as the rest of this sheet (themes.css light rules on bare elements).
   ========================================================================== */
.cp-root .cp-viewbar { margin-bottom: 0; min-height: 30px; }
.cp-root .cp-ptitle { font-size: 1.12rem; gap: 9px; }
.cp-root .cp-ptitle svg { width: 20px; height: 20px; flex: none; fill: none; stroke: var(--cp-acc); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

.cp-root .cp-deck {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 12px;
    padding: 7px 8px; min-height: 50px; border-radius: 12px;
    background: var(--cp-panel); border: 1px solid var(--cp-line-soft);
}
.cp-root .cp-deck-vr { width: 1px; align-self: stretch; margin: 4px 0; background: var(--cp-line-soft); }
.cp-root .cp-weeknav { display: flex; align-items: center; gap: 6px; }
.cp-root .cp-wkarrow { width: 30px; justify-content: center; padding: 4px 0 !important; font-size: 1.05rem !important; line-height: 1; }
.cp-root .cp-wk { display: grid; text-align: center; line-height: 1.2; min-width: 116px; padding: 0 4px; }
.cp-root .cp-wk b { font-size: 0.86rem; font-weight: 800; color: var(--cp-txt-1) !important; }
.cp-root .cp-wk small { font-size: 0.62rem; color: var(--cp-txt-3) !important; white-space: nowrap; }
.cp-root .cp-deck .cp-todaybtn { padding: 5px 10px; font-size: 0.64rem; }
.cp-root .cp-selzone {
    display: flex; align-items: center; gap: 8px; padding: 4px 4px 4px 6px; border-radius: 9px;
    background: color-mix(in srgb, var(--cp-acc) 13%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--cp-acc) 55%, transparent);
}
.cp-root .cp-selzone.is-idle { visibility: hidden; }
.cp-root .cp-deck-tools { display: flex; align-items: center; gap: 6px; padding-left: 12px; border-left: 1px solid var(--cp-line-soft); }
.cp-root .cp-refresh .cp-live { font-size: 0.64rem; }
.cp-root:not([data-view="planner"]) .cp-plan-only { display: none !important; }

/* ---- day tabs ---- */
.cp-root .cp-folder { margin-top: 16px; }
.cp-root .cp-ftabline { display: flex; align-items: stretch; gap: 3px; min-width: 0; flex-wrap: wrap; }
.cp-root .cp-ftabs { display: flex; align-items: stretch; gap: 3px; min-width: 0; flex-wrap: wrap; }
.cp-root .cp-ftab {
    position: relative; top: 1px; display: grid; align-content: end; gap: 6px; min-width: 112px;
    padding: 10px 16px 11px; border-radius: 10px 10px 0 0; text-align: left;
    border: 1px solid transparent !important; border-bottom: 0 !important;
    background: transparent !important; color: var(--cp-txt-2) !important;
}
.cp-root .cp-ftab:hover:not(.on) { background: color-mix(in srgb, var(--cp-panel) 60%, transparent) !important; color: var(--cp-txt-1) !important; border-color: transparent !important; }
.cp-root .cp-ftab.on { background: var(--cp-panel) !important; border-color: var(--cp-line) !important; color: var(--cp-txt-1) !important; z-index: 1; }
.cp-root .cp-ftab.on::after { content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: var(--cp-panel); }
.cp-root .cp-ftab.on::before { content: ''; position: absolute; left: 12px; right: 12px; top: -1px; height: 2px; border-radius: 2px; background: var(--cp-acc); }
.cp-root .cp-ftab .tl { display: flex; align-items: center; justify-content: space-between; gap: 16px; white-space: nowrap; }
.cp-root .cp-ftab .dl { font-size: 0.9rem; font-weight: 800; color: inherit !important; }
.cp-root .cp-ftab .dl small { margin-left: 7px; font-size: 0.8rem; font-weight: 600; color: var(--cp-txt-3) !important; }
.cp-root .cp-ftab .dl em { margin-left: 8px; font-style: normal; font-size: 0.62rem; letter-spacing: 0.1em; color: var(--cp-today) !important; }
.cp-root .cp-ftab.today .dl { color: var(--cp-today) !important; }
.cp-root .cp-ftab.past .dl { color: var(--cp-txt-3) !important; }
.cp-root .cp-ftab .n { font-size: 0.68rem; white-space: nowrap; color: var(--cp-txt-3) !important; }
.cp-root .cp-ftab .n .arr { color: var(--cp-ok) !important; font-weight: 800; }
.cp-root .cp-ftab .n .opn { color: var(--cp-bad) !important; font-weight: 800; }
.cp-root .cp-ftab .n .zero { color: var(--cp-txt-3) !important; }
.cp-root .cp-ftab .cp-sevbar { height: 3px; margin-top: 3px; }
/* shipment count: small light-blue circle, navy figure; inverted on the open tab */
.cp-root .cp-dcnt {
    display: inline-grid; place-items: center; min-width: 21px; height: 21px; padding: 0 6px; border-radius: 999px;
    background: #bfdbfe !important; color: #0b2545 !important; box-shadow: 0 0 0 1px #93c5fd;
    font-size: 0.72rem; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums;
}
.cp-root .cp-ftab.on .cp-dcnt { background: #0b2545 !important; color: #bfdbfe !important; box-shadow: none; }
.cp-root .cp-ftab.add {
    display: flex; align-items: center; min-width: 0; padding: 0 12px 4px; align-self: center;
    font-size: 0.76rem; font-weight: 700; color: var(--cp-txt-3) !important;
}
.cp-root .cp-ftab.add.is-on { color: var(--cp-txt-1) !important; }

/* ---- the sheet: one filter row + the worklist ---- */
.cp-root .cp-sheet { border: 1px solid var(--cp-line); border-radius: 0 12px 12px 12px; background: var(--cp-panel); padding: 10px; }
.cp-root .cp-sheet.notfirst { border-top-left-radius: 12px; }
.cp-root .cp-sheet .cp-tblshell { margin-top: 0; }
.cp-root .cp-sheet .cp-tblwrap { max-height: min(1199px, calc(100vh - 120px)); }
.cp-root .cp-fbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 2px 2px 10px; }
.cp-root .cp-flbl { margin-right: -5px; font-size: 0.64rem; white-space: nowrap; color: var(--cp-txt-3) !important; }
.cp-root .cp-fvr { width: 1px; height: 22px; background: var(--cp-line-soft); }
.cp-root .cp-fseg { display: inline-flex; flex: none; overflow: hidden; border: 1px solid var(--cp-line); border-radius: 8px; background: var(--cp-inset); }
.cp-root .cp-fseg button {
    display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border-radius: 0;
    border: 0 !important; background: transparent !important; color: var(--cp-txt-3) !important;
    font-size: 0.66rem; font-weight: 700; white-space: nowrap;
}
.cp-root .cp-fseg button + button { border-left: 1px solid var(--cp-line) !important; }
.cp-root .cp-fseg button:hover { color: var(--cp-txt-1) !important; }
.cp-root .cp-fseg button.on { background: var(--cp-panel) !important; color: var(--cp-txt-1) !important; box-shadow: inset 0 -2px 0 var(--cp-link); }
.cp-root #cpStats button .sw { width: 7px; height: 7px; border-radius: 50%; background: var(--cp-tone) !important; }
.cp-root #cpStats button .k { color: inherit !important; }
.cp-root #cpStats button .v { font-weight: 800; color: var(--cp-txt-1) !important; }
.cp-root #cpStats button.on { background: color-mix(in srgb, var(--cp-tone) 13%, var(--cp-panel)) !important; box-shadow: inset 0 -2px 0 var(--cp-tone); }
.cp-root .cp-fbar .cp-srch { flex: 1 1 220px; max-width: 360px; min-width: 180px; }
.cp-root .cp-fbar kbd {
    margin-left: 4px; padding: 2px 5px; border-radius: 4px; border: 1px solid var(--cp-line);
    background: transparent; font-family: inherit; font-size: 0.56rem; font-weight: 700; line-height: 1; color: var(--cp-txt-3) !important;
}

/* ---- round 4 (2026-10-04): today's tab outline + read-only arrived rows ---- */
/* today: the old day-card look — a 2px outline in the today colour with the
   TODAY label sitting ON the top border (it paints the page colour behind itself) */
.cp-root .cp-ftab.today { border: 2px solid var(--cp-today) !important; border-bottom: 0 !important; padding: 9px 15px 11px; }
.cp-root .cp-ftab.today.on { border-color: var(--cp-today) !important; }
.cp-root .cp-ftab.today.on::before { display: none; }
.cp-root .cp-ftab .tdy {
    position: absolute; top: 0; left: 50%; transform: translate(-50%, -50%); pointer-events: none;
    padding: 3px 9px; border-radius: 999px; line-height: 1; white-space: nowrap; z-index: 2;
    font-size: 0.64rem; font-weight: 800; letter-spacing: 0.11em;
    /* a SOLID badge (owner 2026-10-04): filled in the today colour, white text,
       on every state of today's tab — the thin outline-coloured text was easy to miss */
    background: var(--cp-today) !important; color: #0b2545 !important;
    box-shadow: 0 0 0 2px var(--cp-bg);
}
:root[data-theme="light"] .cp-root .cp-ftab .tdy { color: #fff !important; }
/* (the badge is solid in every state now — see .tdy above) */
.cp-root .cp-ftabline { padding-top: 0; }   /* the TODAY badge sits in the gap above; it adds no height */

/* arrived = checked in: dimmed, stamped, every editor locked except the carrier */
/* arrived rows are GREENISH (owner 2026-10-04): done, at the warehouse. Same green
   family as the 'sent' rows (--cp-sent-row), a touch stronger so the two differ. */
.cp-root #cpBody tr.cp-arrived > td { background: color-mix(in srgb, var(--cp-ok) 17%, var(--cp-panel)) !important; }
.cp-root #cpBody tr.cp-arrived:hover > td { background: color-mix(in srgb, var(--cp-ok) 24%, var(--cp-panel)) !important; }
.cp-root #cpBody tr.cp-arrived > td:not(.carr) > * { opacity: 0.82; }
.cp-root #cpBody tr.cp-arrived > td.fileref { color: var(--cp-txt-2) !important; }
.cp-root #cpBody tr.cp-arrived input:disabled { cursor: not-allowed; }
.cp-root #cpBody tr.cp-arrived td:not(.carr) { cursor: default; }
.cp-root .cp-arr-chip {
    display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 999px; vertical-align: 1px;
    font-size: 0.6rem; font-weight: 800; letter-spacing: 0.04em; white-space: nowrap;
    background: color-mix(in srgb, var(--cp-ok) 18%, transparent) !important; color: var(--cp-ok) !important;
    border: 1px solid color-mix(in srgb, var(--cp-ok) 45%, transparent);
}

/* ---- round 5 (2026-10-04): actual arrival time + delay on arrived rows ---- */
.cp-root #cpBody tr.cp-arrived .cp-etaw { display: inline-flex; align-items: center; gap: 6px; }
.cp-root .cp-arr-time {
    display: inline-block; min-width: 46px; padding: 3px 7px; border-radius: 6px; text-align: center; white-space: nowrap;
    font-family: var(--cp-tblfont); font-weight: 800; font-size: 0.8rem; font-variant-numeric: tabular-nums;
    background: color-mix(in srgb, var(--cp-ok) 16%, transparent) !important; color: var(--cp-txt-1) !important;
    border: 1px solid color-mix(in srgb, var(--cp-ok) 40%, transparent);
}
.cp-root .cp-arr-time.none { background: transparent !important; border-color: var(--cp-line); color: var(--cp-txt-3) !important; }
.cp-root .cp-delay {
    display: inline-block; padding: 2px 7px; border-radius: 999px; white-space: nowrap;
    font-size: 0.64rem; font-weight: 800; letter-spacing: 0.02em; border: 1px solid transparent;
}
.cp-root .cp-delay.ok { color: var(--cp-ok) !important; background: color-mix(in srgb, var(--cp-ok) 16%, transparent) !important; border-color: color-mix(in srgb, var(--cp-ok) 40%, transparent); }
.cp-root .cp-delay.sm { color: #d97706 !important; background: color-mix(in srgb, #d97706 16%, transparent) !important; border-color: color-mix(in srgb, #d97706 45%, transparent); }
.cp-root .cp-delay.md { color: #ea580c !important; background: color-mix(in srgb, #ea580c 18%, transparent) !important; border-color: color-mix(in srgb, #ea580c 50%, transparent); }
.cp-root .cp-delay.lg { color: #fff !important; background: #dc2626 !important; border-color: #dc2626; }
/* the arrival pill and its delay are the point of an arrived row — never dimmed */
.cp-root #cpBody tr.cp-arrived > td:not(.carr) > .cp-etaw { opacity: 1; }
.cp-root .cp-eta-text { display: inline-block; min-width: 82px; font-family: var(--cp-tblfont); font-weight: 700; font-size: 0.84rem; font-variant-numeric: tabular-nums; color: var(--cp-txt-1) !important; white-space: nowrap; }

/* x/y pills on past-day / All-field tabs: green = complete, amber = something still open */
.cp-root .cp-dcnt.full { background: #bbf7d0 !important; color: #14532d !important; box-shadow: 0 0 0 1px #86efac; }
.cp-root .cp-dcnt.part { background: #fde68a !important; color: #78350f !important; box-shadow: 0 0 0 1px #fcd34d; }
.cp-root .cp-ftab.on .cp-dcnt.full { background: #14532d !important; color: #bbf7d0 !important; }
.cp-root .cp-ftab.on .cp-dcnt.part { background: #78350f !important; color: #fde68a !important; }

/* ---- selection group in the filter row (2026-10-04) ----
   #cpFSlot stacks "Showing x of y" and the selection actions in ONE grid cell;
   the cell is always as wide as the actions, so a tick swaps content, not layout. */
.cp-root .cp-fslot { display: grid; align-items: center; justify-items: end; flex: none; }
.cp-root .cp-fslot > * { grid-area: 1 / 1; }
.cp-root .cp-fnote { display: flex; align-items: center; gap: 8px; }
.cp-root .cp-fslot.has-sel > .cp-fnote { visibility: hidden; }
.cp-root .cp-fbar .cp-selzone { gap: 6px; padding: 3px 3px 3px 5px; border-radius: 9px; }
.cp-root .cp-fbar .cp-selzone .cp-selchip { padding: 3px 9px; font-size: 0.64rem; }
.cp-root .cp-fbar .cp-selzone .cp-btn.sm { padding: 4px 9px; }
.cp-root .cp-fbar .cp-srch { min-width: 150px; }

.cp-root .cp-fbar { gap: 9px; }
.cp-root .cp-fbar .cp-srch { flex: 1 1 140px; min-width: 120px; }
.cp-root .cp-fbar .cp-fseg button { padding: 0 9px; }
.cp-root .cp-fbar .cp-selzone { gap: 5px; padding: 2px 2px 2px 4px; }

/* PRIMARY button hover. `.cp-root .cp-btn:hover:not(:disabled)` (0,4,0) out-ranks
   `.cp-root .cp-btn.primary` (0,3,0) and paints --cp-hover — nearly white in the
   light theme — under the button's white label: Dispatch went blank on hover
   (owner 2026-10-04). The primary keeps its own fill and label in every state. */
.cp-root .cp-btn.primary:hover:not(:disabled),
.cp-root .cp-btn.primary:focus-visible:not(:disabled) {
    background: var(--cp-blue-strong) !important; border-color: var(--cp-blue-strong) !important;
    color: #fff !important; filter: brightness(1.12);
}
.cp-root .cp-btn.primary:hover:not(:disabled) > * { color: #fff !important; }

.cp-modal .cp-btn.primary:hover:not(:disabled),
.cp-seppop .cp-btn.primary:hover:not(:disabled) {
    background: var(--cp-blue-strong) !important; border-color: var(--cp-blue-strong) !important; color: #fff !important; filter: brightness(1.12);
}

/* ---- two weeks of tabs (2026-10-04): compact tabs + a marker where week 2 starts ---- */
.cp-root .cp-ftabs.two { flex-wrap: nowrap; }
.cp-root .cp-ftabs.two .cp-ftab:not(.all) { min-width: 0; padding-left: 11px; padding-right: 11px; }
.cp-root .cp-ftabs.two .cp-ftab.today { padding-left: 10px; padding-right: 10px; }
.cp-root .cp-ftabs.two .cp-ftab .tl { gap: 10px; }
.cp-root .cp-wksep {
    align-self: center; margin: 0 7px 4px 9px; padding-left: 9px; border-left: 1px solid var(--cp-line);
    font-size: 0.56rem; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; white-space: nowrap;
    color: var(--cp-txt-3) !important;
}

/* ---- two weeks WITH Sat/Sun: 14 tabs on one line (2026-10-04) ---- */
.cp-root .cp-ftabs.two.w14 .cp-ftab:not(.all) { padding-left: 8px; padding-right: 8px; }
.cp-root .cp-ftabs.two.w14 .cp-ftab.today { padding-left: 7px; padding-right: 7px; }
.cp-root .cp-ftabs.two.w14 .cp-ftab .tl { gap: 7px; }
.cp-root .cp-ftabs.two.w14 .cp-ftab .dl { font-size: 0.84rem; }
.cp-root .cp-ftabs.two.w14 .cp-ftab .dl small { font-size: 0.74rem; margin-left: 5px; }
.cp-root .cp-ftabs.two.w14 .cp-wksep { margin: 0 4px 4px 5px; padding-left: 6px; }
.cp-root .cp-ftab.we .dl { color: var(--cp-txt-3) !important; }
.cp-root .cp-ftab.we.today .dl { color: var(--cp-today) !important; }

/* ---- the Sat/Sun toggle after the first week's Friday (2026-10-04) ---- */
.cp-root .cp-ftabs.two .cp-ftab.add.wkadd { padding: 0 9px 4px; }
.cp-root .cp-ftabs.two.w14 .cp-ftab.add.wkadd { padding: 0 6px 4px; font-size: 0.9rem; }

/* ---- group by carrier (2026-10-04): the Carrier header is a toggle, each carrier gets a band ---- */
.cp-root .cp-table th.cp-th-group { cursor: pointer; user-select: none; white-space: nowrap; }
.cp-root .cp-table th.cp-th-group:hover { text-decoration: underline; text-underline-offset: 3px; }
.cp-root .cp-table th.cp-th-group .cp-grp-ico { margin-left: 5px; opacity: 0.55; font-size: 0.9em; }
.cp-root .cp-table th.cp-th-group.on { box-shadow: inset 0 -3px 0 var(--cp-acc); }
.cp-root .cp-table th.cp-th-group.on .cp-grp-ico { opacity: 1; color: var(--cp-acc) !important; }
.cp-root #cpBody tr.cp-grouprow > td {
    padding: 0 !important; border-top: 2px solid var(--cp-line) !important;
    background: color-mix(in srgb, var(--cp-link) 13%, var(--cp-panel)) !important;
}
.cp-root #cpBody tr.cp-grouprow.none > td { background: color-mix(in srgb, var(--cp-warn) 15%, var(--cp-panel)) !important; }
.cp-root .cp-grp-inner { position: sticky; left: 0; display: inline-flex; align-items: center; gap: 12px; padding: 7px 12px; }
.cp-root .cp-grp-name { font-size: 0.86rem; font-weight: 800; letter-spacing: 0.03em; text-transform: uppercase; color: var(--cp-txt-1) !important; }
.cp-root .cp-grp-n {
    padding: 2px 9px; border-radius: 999px; font-size: 0.68rem; font-weight: 800; white-space: nowrap;
    background: #bfdbfe !important; color: #0b2545 !important;
}
.cp-root .cp-grp-meta { font-size: 0.68rem; color: var(--cp-txt-3) !important; white-space: nowrap; }

/* ---- the selection group sits right AFTER the search box (owner 2026-10-04), not at the
   far right: the shared slot is left-aligned and the spacer moves behind it ---- */
.cp-root .cp-fbar > .cp-grow { order: 99; }
.cp-root .cp-fslot { justify-items: start; }

/* ---- LOCATION column + narrower ETA WHS / Carrier inputs (2026-10-04) ---- */
.cp-root .cp-etaw input[type=date] { width: 104px; padding: 3px 4px; }
.cp-root .cp-etaw input[type=time] { width: 62px; padding: 3px 4px; }
.cp-root select.cp-carrier { width: 70px; padding: 3px 4px; }
.cp-root .cp-eta-text { min-width: 74px; }
.cp-root .cp-loc-chip {
    display: inline-block; padding: 2px 7px; border-radius: 6px; white-space: nowrap;
    font-family: var(--cp-tblfont); font-size: 0.74rem; font-weight: 800; letter-spacing: 0.04em;
    color: var(--cp-txt-2) !important; background: var(--cp-inset) !important; border: 1px solid var(--cp-line);
}
/* a no-stock location (delivered elsewhere) stands out: it is the exception a planner must notice */
.cp-root .cp-loc-chip.ext { color: #d97706 !important; background: color-mix(in srgb, #d97706 16%, transparent) !important; border-color: color-mix(in srgb, #d97706 50%, transparent); }
.cp-root .cp-loc-chip.none { background: transparent !important; border-style: dashed; color: var(--cp-txt-3) !important; }
