/* Plan grid: the canonical cell grammar, one source (11 October 2026, Nicholas: the supplier page uses the real grid).
   Moved out of frame.css unchanged, in their original order: the `.pg` grid (Plan, Review, the PO page, Runs, Capacity) and its
   `.pplan .pg.pg-plan` cells, marks, selection and fold rules, with the tokens they read. frame.css pulls this file in; the supplier
   page links it WITHOUT frame.css (the app frame). Needs styles.css (tokens). Edit grid rules here, never in frame.css. */

.pg-wrap { position: relative; flex: 1; min-height: 0; overflow: auto; margin: 0 8px; outline: none; }
.pg { border-collapse: separate; border-spacing: 0; font-size: var(--fs-meta); font-variant-numeric: tabular-nums; }
.pg th, .pg td { height: 28px; padding: 0 8px; white-space: nowrap; box-shadow: inset -0.5px -0.5px 0 color-mix(in lch, var(--line-1) 60%, transparent); }
.pg thead th { position: sticky; background: var(--bg-canvas); color: var(--text-3); font-weight: var(--w-normal); text-align: left; z-index: 3; }
.pg .h-sup th { top: 0; height: 28px; color: var(--text-1); font-weight: var(--w-medium); }
.pg .h-wk th { top: 28px; height: 20px; font-size: var(--fs-micro); }
.pg .h-day th { top: 48px; height: 28px; box-shadow: inset 0 -0.5px 0 var(--line-2); }
.pg .h-day th.edge { color: var(--text-3); font-style: normal; }
.pg .h-day th.past { color: var(--text-4); }
.pg .fz { position: sticky; background: var(--bg-canvas); z-index: 2; }
.pg thead .fz { z-index: 4; top: 0; vertical-align: bottom; padding-bottom: 6px; box-shadow: inset 0 -0.5px 0 var(--line-2); }
.pg .f1 { left: 0; min-width: 132px; max-width: 132px; overflow: hidden; text-overflow: ellipsis; text-align: left; font-weight: var(--w-medium); }
.pg .f2 { left: 132px; min-width: 64px; color: var(--text-2); }
.pg .f3 { left: 196px; min-width: 96px; box-shadow: inset -1px 0 0 var(--line-2), inset 0 -0.5px 0 color-mix(in lch, var(--line-1) 60%, transparent); }
/* The column dividers add to the row's gridline, never replace it. */
.pg tbody .f2 { box-shadow: inset -1px 0 0 var(--line-2), inset 0 -0.5px 0 color-mix(in lch, var(--line-1) 60%, transparent); }
.pg thead .f2 { box-shadow: inset -1px 0 0 var(--line-2), inset 0 -0.5px 0 var(--line-2); }
.pg tbody .f3 + .c { box-shadow: inset -0.5px 0 0 color-mix(in lch, var(--line-1) 60%, transparent), inset 0 -0.5px 0 color-mix(in lch, var(--line-1) 60%, transparent); }
.pg thead .f3 { box-shadow: inset -1px 0 0 var(--line-2), inset 0 -0.5px 0 var(--line-2); }
.pg .num { text-align: right; }
.pg .gstart { box-shadow: inset 1px 0 0 var(--line-2), inset -0.5px -0.5px 0 color-mix(in lch, var(--line-1) 60%, transparent); }
.pg td.c { min-width: 60px; text-align: right; cursor: default; color: var(--text-1); }
.pg td.c .ico { width: 11px; height: 11px; vertical-align: -1px; margin-right: 3px; }
.pg td.c.edge { background: color-mix(in lch, var(--bg-chrome) 45%, var(--bg-canvas)); }
.pg td.c .bk { margin-left: 4px; font-size: var(--fs-micro); }
.pg td.c.mixed { background-image: linear-gradient(135deg, var(--text-4) 0 3px, transparent 3px); background-repeat: no-repeat; }
/* Notes: pale fills for everyone; a comment alone is a corner mark (decided 26 Sep) */
.pg td.c.n-comment { background-image: linear-gradient(225deg, var(--text-4) 0 5px, transparent 5px) !important; }
/* Selection: one accent outline, radius 6, accent-soft inside (PLN-VIS-03) */
/* A crisp thin ring, not a filled box (Nicholas, 29 Sep): one cell stays white;
   a range gets the faintest wash so its extent reads. */
/* The selection is a tile lifting off the sheet, not a focus ring (Nicholas,
   29 Sep): a whisper of forest green, no border, a soft vertical shadow, square
   like the cells. One cell lifts itself (td.pg-active); the overlay keeps the
   geometry the strip is placed by and draws only a range. It sits under the
   sticky header and frozen columns (z 1 < 2, 3), so it scrolls away with its
   cells instead of floating over the header. */
.pg-sel { position: absolute; pointer-events: none; border: 0; border-radius: 0; background: none; z-index: 1; visibility: hidden; }
.pg-sel.range { visibility: visible; background: var(--sel-press-range); box-shadow: var(--sel-press-shadow); }
/* Pressed in, not outlined or floating (Nicholas, 29 Sep, second pass): a pale
   forest green, a soft inset shade from the top-left, small corners, the value a
   shade stronger. */
.pg td.c.pg-active { z-index: 1; background: var(--sel-press); box-shadow: var(--sel-press-shadow); color: var(--text-1); }
.pg tbody td.c.pg-active, .pg tbody td.c.pg-active .q { color: var(--text-1); }
.pg tbody td.c.pg-active .q { font-weight: var(--w-medium); }
.pg td.c.copied { outline: 1.5px dashed var(--accent); outline-offset: -3px; }
/* Strip, panel, hover card */
.pg-strip, .pg-card { position: absolute; z-index: 6; background: var(--bg-raised); border: 0.5px solid var(--line-2); border-radius: var(--r-control); box-shadow: var(--shadow-raised); }
.pg-strip { display: flex; gap: 2px; padding: 3px; align-items: center; }
/* `display` beats the hidden attribute: a closed strip stayed on screen as a small empty box (29 Sep). */
.pg-strip[hidden], .pg-card[hidden], .pg-sel[hidden] { display: none; }
.pg-strip .sb { width: 28px; height: 28px; border: 0; background: none; border-radius: 6px; color: var(--text-2); display: grid; place-items: center; }
.pg-strip .sb:hover, .pg-strip .sb:focus-visible { background: var(--bg-hover); color: var(--text-1); outline: none; }
.pg-strip .sb .ico { width: 15px; height: 15px; }
.pg-strip > .src { padding: 0 8px; font-size: var(--fs-meta); }
.pg-card { padding: 8px 10px; width: 300px; font-size: var(--fs-meta); pointer-events: none; }
/* Bottom bar: information only */
.pg-bar { display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: baseline; padding: 8px 20px; border-top: 0.5px solid var(--line-2); font-size: var(--fs-meta); color: var(--text-2); min-height: 36px; }
.pg-bar b { color: var(--text-1); font-weight: var(--w-medium); }
/* The last change, said plainly, leads the bar on its own line (Nicholas, 4 Oct 2026). */
.pg-bar .bar-done { flex-basis: 100%; color: var(--text-1); }
/* Critique fixes (27 Sep): states must reach the cell (the base cell colour won) */
.pg td.c.s-earlier { font-weight: var(--w-medium); color: var(--text-1); }
.pg td.c.s-later, .pg td.c.s-overdue { color: var(--warning-ink); }
.pg td.c.s-awaiting, .pg td.c.s-awaiting_past, .pg td.c.s-booked { color: var(--text-3); }
/* Held at the supplier (0102): booked, not here yet; its date, in the attention ink. */
.pg td.c.s-held, .pg td.c.s-held_late { color: var(--warning-ink); font-style: italic; }
.pg td.c.s-plan { color: var(--text-3); font-style: italic; }
.pg td.c.s-delivered { font-weight: var(--w-semibold); }
/* A cell holding arrived and not-arrived parts (5 Oct): the arrived figure after the other, with its dot. */
.pg td.c.split { white-space: nowrap; }
.pg td.c .pg-arr { margin-left: 8px; }
.pg .muted { color: var(--text-3); }
/* The ship boundary: dashed, after the last column that counts; the date lives in the group head */
.pg td.cut { position: relative; }
.pg td.cut, .pg th.cut { box-shadow: inset -0.5px -0.5px 0 color-mix(in lch, var(--line-1) 60%, transparent); }
/* One corner mark only: comment-only notes; mixed cells get a dotted underline instead */
.pg td.c.mixed { background-image: none; text-decoration: underline dotted var(--text-4); text-underline-offset: 3px; }
/* The empty message stays in view on a wide grid */
.pg tbody .empty { position: sticky; left: 0; width: min(100%, calc(100vw - 300px)); }
.pg-bar .linkish { border: 0; background: none; color: var(--text-2); font: inherit; text-decoration: underline; text-underline-offset: 2px; padding: 0; cursor: default; }
.pg td.f3 { cursor: default; }
/* Critique B (27 Sep): contrast, colour-independence, focus */
.pg .h-day th { color: var(--text-2); }
.pg .h-day th.past, .pg .h-day th.edge { color: var(--text-3); }
.pg td.c .arr { margin-right: 3px; }
/* No ring round the grid itself (Nicholas, 30 Sep): drawn on the scroll area,
   it framed the empty space beside a narrow table and read as a stray border.
   The selected cell's tile is the focus; the arrow keys make one. */
/* Half the weight, light green (Nicholas, 29 Sep) */
.pg-strip .sb:focus-visible { outline: 0.75px solid var(--sel-ring); outline-offset: 0; background: var(--sel-press); }
/* Planning, visual review 27 Sep: folded weeks, row bands, provenance legend */
.pg th.fold, .pg td.fold { min-width: 16px; width: 16px; max-width: 16px; padding: 0; text-align: center; color: var(--text-4); background: color-mix(in lch, var(--bg-chrome) 35%, var(--bg-canvas)); cursor: default; }
.pg .h-wk th.fold, .pg .h-day th.fold { font-size: var(--fs-micro); color: var(--text-3); overflow: hidden; }
.pg th[data-openweek]:hover, .pg th[data-closeweek]:hover { color: var(--text-1); background: var(--bg-hover); }
.pg tr.pband th, .pg tr.pband td { height: 36px; padding: 0; background: var(--bg-canvas); box-shadow: none; }
.pg tr.pband .pband-cell { position: sticky; left: 0; z-index: 2; }
.pg tr.pband .band { margin: 4px 0 0; width: 100%; min-width: 292px; }
.pg tr.pband .pband-cell { overflow: visible; }
.pg tr.pband .band { position: absolute; left: 0; top: 4px; width: max-content; min-width: 280px; margin: 0; z-index: 3; }
.pg .f1 .blk { margin-left: 6px; font-size: var(--fs-micro); color: var(--warning-ink); font-weight: var(--w-medium); }
.pg tr.pband .band { top: 2px; height: 32px; }
/* Pass 2 critique: folds are findable and reachable; legend reads like the cells */
.pg th.fold, .pg td.fold { min-width: 20px; width: 20px; max-width: 20px; cursor: pointer; }
.pg .h-day th.fold { color: var(--text-3); font-size: var(--fs-meta); }
.pg .fold-b { all: unset; cursor: pointer; font-size: var(--fs-micro); color: var(--text-3); padding: 0 2px; border-radius: 3px; }
.pg .fold-b:hover, .pg .fold-b:focus-visible { color: var(--text-1); background: var(--bg-hover); outline: 1px solid var(--accent-ring); }
.pg td.fold.cut, .pg th.fold.cut { position: relative; }
.pg th.fold, .pg td.fold { background: color-mix(in lch, var(--bg-chrome) 75%, var(--bg-canvas)); }
/* One supplier at a time: the others fold to one total column each */
.pg th.sumh { vertical-align: bottom; padding: 0 6px 6px; min-width: 76px; max-width: 96px; text-align: right; }
.pg .sum-b { all: unset; cursor: pointer; font-weight: var(--w-medium); color: var(--text-2); white-space: normal; line-height: 1.2; display: inline-block; text-align: right; }
.pg .sum-b:hover, .pg .sum-b:focus-visible { color: var(--text-1); text-decoration: underline; text-underline-offset: 2px; }
.pg td.c.sum { min-width: 76px; background: color-mix(in lch, var(--bg-chrome) 40%, var(--bg-canvas)); color: var(--text-2); cursor: pointer; }
.pg th.focus-sup { color: var(--text-1); }
/* Supplier names are the grid's column heads: bold (review 27 Sep) */
.pg .h-sup th.gstart, .pg .sum-b { font-weight: var(--w-semibold); color: var(--text-1); }
/* Planning, 28 Sep: colours are labels. 3 Oct (Nicholas): five pale swatches from the
   categorical palette, painted as they are (never mixed into the canvas, which moved
   their hues). The stored keys stay as slots: yellow → teal, orange → rose,
   red → stone, blue → blue, purple → lavender. Red and orange are retired. */
:root {
  --note-yellow: var(--cat-teal-pale);
  --note-orange: var(--cat-rose-pale);
  --note-red: var(--tile-stone);
  --note-blue: var(--cat-blue-pale);
  --note-purple: var(--cat-lavender-pale);
  --pv-blue: lch(52% 58 268);
  --pv-blue-soft: lch(68% 38 268);
  /* Selection: the interaction tokens (styles.css A4), by their older names. */
  --sel-press: var(--accent-press);
  --sel-ring: var(--accent-ring-soft);
  --sel-press-edit: var(--accent-press-edit);
  --sel-press-range: var(--accent-press-range);
  --sel-press-shadow: var(--accent-press-shadow);
  /* Planning's active cell: a clear green, lighter than the workspace mark (8 Oct 2026); blue stays a supplier's presence. */
  --pn-sel: lch(52% 44 146);
  /* A cell this purchase adds to (Nicholas, 9 Oct 2026): a light pastel yellow, about #fff6cc. */
  --pm-add: lch(96.8% 21 95);
  /* Also read by the Runs tiles (frame.css): defined here because `--note-red` below is `--tile-stone`, and this file must stand alone. */
  --tile-stone: lch(94.2% 3.4 78);
}
.pg td.c.n-yellow { background: var(--note-yellow) !important; }
.pg td.c.n-orange { background: var(--note-orange) !important; }
.pg td.c.n-red { background: var(--note-red) !important; }
.pg td.c.n-blue { background: var(--note-blue) !important; }
.pg td.c.n-purple { background: var(--note-purple) !important; }
/* Supply on the supplier's own promised date in Visma: backed and traceable (28 Sep) */
.pg td.c { position: relative; }
/* A superscript on the number, lighter than the legend's key (Nicholas, 29 Sep) */
.pg td.c .q { position: relative; }
.pg td.c .q .pg-dot { position: absolute; top: -1px; right: -6px; width: 4px; height: 4px; margin: 0; background: var(--pv-blue-soft); }
.pg td.c > .pg-dot { position: absolute; top: 5px; right: 4px; width: 4px; height: 4px; margin: 0; background: var(--pv-blue-soft); }
.pg-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--pv-blue); margin-right: 5px; vertical-align: 1px; }
.lg-pv .pg-dot { background: var(--pv-blue-soft); }
/* The dot after a value in running text (a table cell, a popover row): small, raised, as on a grid cell (6 Oct 2026). */
.pg-dot.inline { width: 4px; height: 4px; margin: 0 0 0 2px; vertical-align: 0.55em; background: var(--pv-blue-soft); }

/* Planning, 28 Sep (Nicholas): the current week's header filled, dates as dd.mm,
   and the label icon in the labels' own colours, as in the mock. */
.pg .h-wk th.now { background: color-mix(in lch, var(--accent), white 16%); color: #fff; font-weight: var(--w-medium); border-radius: 4px 4px 0 0; }
.pg .h-wk th.now .fold-b { color: #fff; }
.pg th.f1.changed a.ref::after { content: ""; display: inline-block; width: 5px; height: 5px; margin-left: 6px; border-radius: 50%; background: var(--accent); vertical-align: 2px; }

/* Planning: a quantity typed in the cell, with ↵ beside it (29 Sep) */
.pg-strip.pg-edit { background: none; border: 0; box-shadow: none; padding: 0; overflow: visible; }
.pg-edit .pe-in { box-sizing: border-box; width: 100%; height: 100%; margin: 0; padding: 0 8px; border: 0; background: var(--sel-press-edit); outline: none; box-shadow: var(--sel-press-shadow); transform: none; font: inherit; font-variant-numeric: tabular-nums; text-align: right; color: var(--text-1); }
.pg-edit .pe-go { position: absolute; top: 50%; left: calc(100% + 6px); transform: translateY(-50%); width: 28px; height: 28px; border-radius: 7px; border: 0.75px solid var(--sel-ring); background: var(--sel-press); color: var(--accent); font: inherit; font-size: 15px; line-height: 1; display: grid; place-items: center; cursor: default; }
.pg-edit .pe-go:hover { background: color-mix(in lch, var(--accent) 18%, transparent); }
.pg-edit .pe-msg { position: absolute; top: calc(100% + 4px); left: 0; width: max-content; max-width: 320px; padding: 6px 8px; border-radius: var(--r-control); background: var(--bg-raised); border: 0.5px solid var(--line-2); box-shadow: var(--shadow-raised); font-size: var(--fs-meta); color: var(--text-1); z-index: 7; }
.pc-p .pc-q .pg-dot { position: absolute; top: 1px; right: 0; width: 4px; height: 4px; margin: 0; background: var(--pv-blue-soft); }

/* The ERP dot on a supplier's summary column, as on a cell (29 Sep) */
.pg td.c.sum { position: relative; }
.pg td.c.sum > .pg-dot { position: static; display: inline-block; width: 4px; height: 4px; margin: 0 0 0 2px; vertical-align: 0.55em; background: var(--pv-blue-soft); }
.pg td.c .fu-mark { position: absolute; left: 3px; top: 50%; transform: translateY(-50%); display: inline-flex; color: var(--text-3); }
.pg td.c .fu-mark .ico { width: 11px; height: 11px; }
/* A card that offers an action takes the pointer; the plain card never does. */
.pg-card.act { pointer-events: auto; width: 340px; }

/* Planning, all suppliers combined (DEC-2026-09-30-05, 30 Sep): one column
   group, counted incoming summed by date; Now, Overdue and Not promised sit
   apart and are never in a total. An item opens into its suppliers (E). */
.pg th.all-sup { color: var(--text-1); }
.pg th.all-sup .src { font-weight: var(--w-normal); }
.pg .xp { width: 16px; height: 16px; margin: 0 4px 0 -4px; padding: 0; border: 0; background: none; color: var(--text-3); display: inline-grid; place-items: center; vertical-align: -3px; border-radius: 4px; cursor: default; }
.pg .xp:hover { color: var(--text-1); background: var(--bg-hover); }
.pg .xp .ico { width: 12px; height: 12px; transition: transform var(--t-quick) var(--ease); }
.pg .xp.open .ico { transform: rotate(90deg); }
.pg tr.sub th.sub-name { padding-left: 28px; font-weight: var(--w-normal); color: var(--text-2); font-size: var(--fs-meta); }
.pg tr.sub td { font-size: var(--fs-meta); }
.pg td.sc { min-width: 60px; text-align: right; color: var(--text-2); font-variant-numeric: tabular-nums; }
.pg td.sc.edge { background: color-mix(in lch, var(--bg-chrome) 45%, var(--bg-canvas)); }
.pg td.sc .ico { width: 10px; height: 10px; vertical-align: -1px; margin-right: 3px; color: var(--warning); }
.pg td.sc .pg-dot { display: inline-block; width: 4px; height: 4px; margin: 0 0 0 2px; vertical-align: 0.55em; background: var(--pv-blue-soft); border-radius: 50%; }
.pg td.sc.s-later, .pg td.sc.s-overdue { color: var(--warning-ink); }
.pg td.sc.s-awaiting, .pg td.sc.s-awaiting_past { color: var(--text-3); }
.pg td.c.now .q { font-weight: var(--w-medium); }
@media (prefers-reduced-motion: reduce) { .pg .xp .ico { transition: none; } }

/* Coverage overlay (DEC-2026-09-30-05, 30 Sep): a lens on one run's Can Ship
   answer. Green (the ready leaf green, not the brand) = supply the run relies
   on; red = the real gap, at the ship-date line and in the lens column. Both
   are recorded exceptions confined to this opt-in overlay: red beyond
   emergencies, and a slow continuous breathing pulse. Colour never alone:
   the number, ✓ or ✗ always says it. Reduced motion keeps the state, still. */
.pg { --ov-green: var(--op-ready); --ov-red: var(--op-critical); }
/* A lens, not a fill (Nicholas, 30 Sep): an extremely light tint and a fine
   dotted perimeter on the cell's own edges, no rounding, on its own layer so
   the gridlines and the ship-date line stay as they are. The dots circulate
   slowly round the perimeter: "look here", never "these units are reserved".
   Reduced motion keeps tint and dots, still. */
.pg td.c.ov-rely::before, .pg td.c.ov-gap::before {
  --ov-dot: color-mix(in oklab, var(--ov-c) 28%, transparent);
  content: ""; position: absolute; inset: 1px; pointer-events: none;
  background:
    linear-gradient(90deg, var(--ov-dot) 50%, transparent 0) top left / 4px 1px repeat-x,
    linear-gradient(90deg, var(--ov-dot) 50%, transparent 0) bottom left / 4px 1px repeat-x,
    linear-gradient(0deg, var(--ov-dot) 50%, transparent 0) top left / 1px 4px repeat-y,
    linear-gradient(0deg, var(--ov-dot) 50%, transparent 0) top right / 1px 4px repeat-y,
    color-mix(in oklab, var(--ov-c) 2.5%, transparent);
  animation: ov-circulate 9s linear infinite;
}
.pg td.c.ov-rely { --ov-c: var(--ov-green); }
.pg td.c.ov-gap { --ov-c: var(--ov-red); }
.pg td.c.ov-gap::before { --ov-dot: color-mix(in oklab, var(--ov-c) 60%, transparent); background-color: color-mix(in oklab, var(--ov-c) 4%, transparent); }
.pg td.c.ov-gap .ov-x { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); font-size: var(--fs-micro); font-weight: var(--w-semibold); color: var(--ov-red); line-height: 1; }
.pg td.c.ov-gap .q { margin-right: 12px; }
@media (prefers-reduced-motion: reduce) {
  .pg td.c.ov-rely::before, .pg td.c.ov-gap::before { animation: none; }
}
.pg td.f3 .ov-ok, .pg td.f3 .ov-short { white-space: nowrap; }
.pg td.f3 .ov-on { margin-left: 5px; font-size: var(--fs-meta); color: var(--text-2); }
.pg td.f3 .ov-prio { display: block; font-size: var(--fs-micro); color: var(--text-2); white-space: nowrap; }
.pg td.f3 .ov-prio-short { color: var(--op-critical); }
.pg-card .pc-ov { margin-top: 8px; padding-top: 7px; border-top: 0.5px solid var(--line-2); display: grid; grid-template-columns: 12px 1fr; gap: 6px; color: var(--text-1); line-height: 1.45; }
.pg-card .pc-cov { display: grid; grid-template-columns: max-content 1fr; gap: 5px 10px; margin: 2px 0 8px; }
.pg-card .pc-cov dt { color: var(--text-3); }
.pg-card .pc-cov dd { margin: 0; color: var(--text-1); line-height: 1.45; }
.pg-card .pc-shared { line-height: 1.45; }

/* Planning's view keys in the bar (C, S): quiet, centred between title and tools. */
/* A date heading brings its items to the top (5 Oct): DataTable's header sort mark, in the grid's header. */
.pg .h-day th .th-sort { all: unset; cursor: default; display: inline-flex; align-items: center; gap: 2px; color: inherit; }
.pg .h-day th .th-sort:focus-visible { outline: 1px solid var(--accent-ring); outline-offset: 2px; border-radius: 3px; }
.pg .h-day th:hover, .pg .h-day th.sorted { color: var(--text-1); }
.pg .h-day th .arrow { width: 11px; height: 11px; margin-left: 1px; }
.pplan th.now, .pplan td.now { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.pplan .pg-dot { margin: 0 0 0 4px; background: var(--text-3); }
/* A supplier's grid (8 Oct 2026, night): the collaboration sheet's grid (design-system prototype, experiments/collab:
   tables.css + collab.css), scoped here; the Item column as Planning has it. The active cell is a thin green outline
   (the shape of a supplier's presence outline, in Planning's green; blue stays the supplier's); a range is a calm
   fill; a red arrow where SKUBA delayed units past the supplier's date. Proposals for `frontend`. */
.pplan .pn-main .pg-wrap { margin: 0; }
/* The sidecar floats over the grid (its right 408 px). Room is kept past the last week while it is open, so every week can be scrolled clear of it and clicked; arrow keys scroll the active cell out from under it. */
.pplan .pn-stage:has(.pn-dock) .pn-main .pg-wrap { padding-right: 424px; box-sizing: border-box; scroll-padding-right: 424px; }
.pplan .pg.pg-plan { width: max-content; min-width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--fs-meta); font-variant-numeric: tabular-nums; }
.pplan .pg.pg-plan th, .pplan .pg.pg-plan td { height: 28px; padding: 0 8px; white-space: nowrap; box-shadow: none; box-sizing: border-box; }
.pplan .pg.pg-plan thead th { position: sticky; top: 0; z-index: 2; height: 28px; background: var(--bg-canvas); color: var(--text-3); font-weight: var(--w-medium); text-align: left; border-bottom: 0.5px solid var(--line-2); vertical-align: middle; }
.pplan .pg.pg-plan thead th.num { text-align: right; }
.pplan .pg.pg-plan thead th.now { color: var(--text-1); }
.pplan .pg.pg-plan .f1 { position: sticky; left: 0; z-index: 1; min-width: 320px; max-width: 320px; overflow: hidden; text-overflow: ellipsis; padding-left: 10px; background: var(--bg-canvas); font-weight: var(--w-normal); text-align: left; }
.pplan .pg.pg-plan thead .f1 { z-index: 3; }
.pplan .pg.pg-plan tbody td, .pplan .pg.pg-plan tbody th { border-bottom: 0.5px solid color-mix(in lch, var(--line-1) 70%, transparent); }
.pplan .pg.pg-plan td.c { min-width: 64px; text-align: right; position: relative; cursor: cell; color: var(--text-1); background: none; border-right: 0.5px solid color-mix(in lch, var(--line-1) 60%, transparent); }
.pplan .pg.pg-plan .gs { border-left: 1px solid var(--line-2); }
/* The home grid (all suppliers): the supplier grid's lines and hover, one row per supplier; the current week keeps its shade. */
.pplan .pg.pg-plan.pg-home .f1 { min-width: 140px; max-width: 140px; }
.pplan .pg.pg-plan.pg-home tbody tr.hrow { cursor: pointer; }
.pplan .pg.pg-plan.pg-home td.c { cursor: pointer; }
.pplan .pg.pg-plan.pg-home td.pn-attn { padding-left: 14px; text-align: left; }
.pplan .pg.pg-plan.pg-home td.pn-attn .pn-att { margin-right: 12px; }
.pplan .pg.pg-plan th.now, .pplan .pg.pg-plan td.c.now { background: color-mix(in srgb, var(--accent) 6%, var(--bg-canvas)); }
.pplan .pg.pg-plan td.c:hover { background: var(--bg-hover); }
.pplan .pg.pg-plan td.c.pg-in, .pplan .pg.pg-plan td.c.pg-in:hover { background: var(--accent-soft); }
/* A clear green, lighter than the workspace mark so it reads as a selection, not as ink. */
.pplan .pg.pg-plan td.c.pg-active { box-shadow: inset 0 0 0 1.5px var(--pn-sel); }
.pplan .pg.pg-plan td.c.pg-active:not(.pg-in) { background: none; }
.pplan .pg.pg-plan .q .qi{ width: 10px; height: 10px; margin-left: 2px; vertical-align: -1px; }
/* The week's dates on hover of its header (collab's own). */
.pplan .pg.pg-plan th.wkh { position: sticky; cursor: default; } /* sticky is positioned too: the ::after tooltip anchors to it, and the week stays at the top of the scroller */
.pplan .pg.pg-plan th.wkh::after { content: attr(data-tip); position: absolute; top: calc(100% + 4px); right: 4px; white-space: nowrap; z-index: 5; padding: 3px 7px; border-radius: 6px; background: var(--text-1); color: var(--bg-canvas); font-size: var(--fs-micro); font-weight: var(--w-medium); opacity: 0; pointer-events: none; transition: opacity var(--t-quick) var(--ease); }
.pplan .pg.pg-plan th.wkh:hover::after { opacity: 1; transition-delay: 300ms; }
.pplan .pg.pg-plan tr.sub th.f1 { padding-left: 28px; color: var(--text-2); }
/* A supplier's band (Nicholas, 9 Oct 2026): a light shade, a darker line under it, bold. */
.pplan .pg.pg-plan tr.pm-band th, .pplan .pg.pg-plan tr.pm-band td { background: var(--bg-chrome); border-bottom: 1px solid var(--line-3); }
.pplan .pg.pg-plan tr.pm-band th.pm-band { padding-top: 10px; font-weight: var(--w-semibold); color: var(--text-1); }
.pplan .pg.pg-plan tr.pm-band th.pm-band .src { font-weight: var(--w-normal); }
.pplan .pg.pg-plan tr.pm-band td.c { cursor: default; }
/* Where this purchase adds units: the cell shows the total on a soft accent; what is added is in the hover. */
.pplan .pg.pg-plan td.c.pm-add, .pplan .pg.pg-plan td.c.pm-add:hover { background: var(--pm-add); }
/* Selected wins over added, so a Shift+arrow over the purchase's cells is seen. */
.pplan .pg.pg-plan td.c.pm-add.pg-in { background: var(--accent-soft); }
/* What was there, in italics on the left; the total with this purchase, in bold on the right. */
.pplan .pg.pg-plan td.c.pm-add .q { display: flex; justify-content: space-between; align-items: baseline; gap: 6px; }
.pplan .pg.pg-plan td.c.pm-add .q i { color: var(--text-3); font-style: italic; }
.pplan .pg.pg-plan td.c.pm-add .q b { font-weight: var(--w-semibold); }
/* After the shipment date (Purchasing's marks, over every supplier): a red border, in every band that has units there. */
.pplan .pg.pg-plan td.c.pm-late { box-shadow: inset 0 0 0 1.5px var(--danger); }
/* The caller's optional dot (marks().dots; Purchasing: inside lead time, Nicholas 9 Oct 2026): a red corner dot, like the blue no-statement dot. */
.pplan .pg.pg-plan td.c.pm-dotted { position: relative; }
.pplan .pg.pg-plan td.c > .pm-dot { position: absolute; top: 4px; right: 4px; width: 5px; height: 5px; border-radius: 50%; background: var(--danger); }
/* A dotted cell keeps its figure and the delayed arrow clear of the corner dot (Planning's review, 9 Oct). */
.pplan .pg.pg-plan td.c.pm-dotted > .q { padding-right: 6px; }
/* Received quantity and held units (10 Oct 2026): information, never attention. A small grey superscript after the figure; the
   detail is in the hover card. It does not count in Can Ship. */
.pplan .pg.pg-plan td.c:has(.rcv) { position: relative; }
.pplan .pg.pg-plan td.c > .rcv { position: absolute; top: 4px; left: 5px; display: inline-flex; align-items: center; gap: 2px; font-size: 9px; font-weight: var(--w-medium); color: var(--text-3); font-variant-numeric: tabular-nums; line-height: 1; }
.pplan .pg.pg-plan td.c > .rcv::before { content: ""; flex: none; width: 5px; height: 3px; border-left: 1.25px solid currentColor; border-bottom: 1.25px solid currentColor; transform: translateY(-1px) rotate(-45deg); margin-right: 1px; }
.pplan .pg.pg-plan td.c > .rcv.hld::before { width: 5px; height: 5px; border: 1.25px solid currentColor; border-radius: 50%; background: linear-gradient(90deg, currentColor 50%, transparent 50%); transform: none; margin-right: 2px; }
.pplan .pg.pg-plan td.c .q.q-nil { color: var(--text-3); }
.pplan .pg.pg-plan td.c.pm-late.pg-active { box-shadow: inset 0 0 0 1.5px var(--danger), inset 0 0 0 3px var(--pn-sel); }
/* The band's totals: italic, a darker line above the first and below the last, none between. */
.pplan .pg.pg-plan tr.pm-total th, .pplan .pg.pg-plan tr.pm-total td { font-style: italic; color: var(--text-2); border-bottom: 0; cursor: default; }
.pplan .pg.pg-plan tr.pm-total.first th, .pplan .pg.pg-plan tr.pm-total.first td { border-top: 1px solid var(--line-3); }
.pplan .pg.pg-plan tr.pm-total.last th, .pplan .pg.pg-plan tr.pm-total.last td { border-bottom: 1px solid var(--line-3); }
.pplan .pg.pg-plan tr.pm-other th .pn-item { font-weight: var(--w-normal); }
/* A family row (the line by family): its items added up, read only. */
.pplan .pg.pg-plan tr.pm-fam td.c { cursor: default; }
/* A page menu open over the grid: no active ring under it. */
.pm-menu-open .pplan .pg.pg-plan td.c.pg-active { box-shadow: none; }
.pm-menu-open .pplan .pg.pg-plan td.c.pm-late.pg-active { box-shadow: inset 0 0 0 1.5px var(--danger); }
/* The week-cell editor never changes the grid (Nicholas, 11 Oct 2026): a percentage-width input still lends its intrinsic width (~150 px) to an auto-layout
   column, so typing widened the whole column and pushed the others. width:0 with min-width:100% fills the cell and lends nothing. */
.pg td.c input.pn-edit { box-sizing: border-box; width: 0; min-width: 100%; max-width: 100%; height: 24px; border: 0; padding: 0 4px; background: var(--bg-raised); font: inherit; text-align: right; outline: none; }
.pplan .pg.pg-plan td.c input.pn-edit { width: 0; min-width: 100%; box-sizing: border-box; height: 24px; border: 0; padding: 0 4px; background: var(--bg-raised); font: inherit; text-align: right; outline: none; }
.pplan .pg.pg-plan td.c input.pn-edit[aria-invalid="true"] { color: var(--danger); }
.pplan.stb-plan .pg.pg-plan.sp-split { width: auto; min-width: 0; }
/* The split in the suppliers menu: the sheet's cells at menu width, on the menu's own surface. */
.pplan.stb-plan.sp-menu .pg.pg-plan.sp-split { width: 100%; margin: 2px 0 4px; }
.pplan.stb-plan.sp-menu .pg.pg-plan .f1 { padding-left: 12px; }
.sp-menu .pg.pg-plan .f1 { min-width: 0; max-width: none; width: auto; position: static; background: none; }
.sp-menu .pg.pg-plan thead th { position: static; background: none; }
/* "Call confirmed" and "not yet confirmed" (Nicholas, 9 Oct 2026). A Griptel entry counts at once; the supplier's yes on a call is provenance.
   The mark is quiet: a dotted underline under the figure, and a small ring in the header chip and the Attention text. No new colour. */
.pplan .pg.pg-plan td.c.unc .q { text-decoration: underline dotted; text-decoration-color: var(--text-3); text-underline-offset: 3px; }
/* Expandable column header (Later): the caret shows on hover and while open. */
.pg th.expandable .col-fold { all: unset; cursor: default; display: inline-flex; align-items: center; gap: 2px; color: inherit; }
.pg th.expandable .col-fold .caret { width: 10px; height: 10px; opacity: 0; transition: opacity var(--t-quick) var(--ease), transform var(--t-quick) var(--ease); }
.pg th.expandable:hover .col-fold .caret, .pg th.expandable .col-fold:focus-visible .caret, .pg th.expandable .col-fold[aria-expanded="true"] .caret { opacity: 1; }
.pg th.expandable .col-fold[aria-expanded="true"] .caret { transform: rotate(180deg); }
.pplan .pg.pg-plan td.c.pg-active::after { content: "↵"; position: absolute; left: calc(100% + 3px); top: 50%; transform: translateY(-50%); z-index: 3; padding: 0 4px; border: 0.5px solid var(--line-2); border-radius: 4px; background: var(--bg-raised); color: var(--text-3); font-size: 9px; line-height: 14px; pointer-events: none; }

/* The product column's content (item, description, marks, the unconfirmed dot): grid content, so it travels with the grid. Scoped under .pplan, as on the Plan page. */
.pplan .pn-desc { margin-left: 4px; }
.pplan .pn-item { font-weight: var(--w-medium); }
.pplan .pn-item + .mark.attn { display: inline-flex; vertical-align: -2px; margin-left: var(--s-1, 4px); }
.pplan .pn-mark { display: inline-flex; margin: 0 var(--s-2, 8px) 0 0; vertical-align: -2px; }
.pplan .pn-tick { margin: 0 var(--s-2, 8px) 0 0; vertical-align: -2px; }
.pplan .pn-uncdot { display: inline-block; width: 7px; height: 7px; margin-right: 6px; border-radius: 50%; border: 1px solid var(--text-3); vertical-align: 0; }

/* The action strip beside the active cell (Enter): moved with showStrip into supplier-ui.js, so the supplier page draws the same one. */
.pn-strip { position: fixed; z-index: 40; display: flex; align-items: center; gap: 4px; padding: 3px; background: var(--bg-raised); border: 0.5px solid var(--line-2); border-radius: 10px; box-shadow: var(--shadow-raised); font-size: var(--fs-meta); }
.pn-strip[hidden] { display: none; }
.pn-strip .ic.lbl { width: auto; flex: none; white-space: nowrap; display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 9px; border: 0; border-radius: 6px; background: none; font: inherit; font-size: var(--fs-meta); color: var(--text-1); cursor: pointer; }
.pn-strip .ic.lbl .ico { width: 14px; height: 14px; }
.pn-strip .ic.lbl:hover, .pn-strip .ic.lbl:focus-visible { background: var(--bg-hover); outline: none; }
.pn-strip .ic { width: 26px; height: 26px; display: grid; place-items: center; border: 0; border-radius: 6px; background: none; color: var(--text-2); cursor: pointer; padding: 0; }
.pn-strip .ic .ico { width: 15px; height: 15px; }
.pn-strip .ic:hover, .pn-strip .ic:focus-visible { background: var(--bg-hover); color: var(--text-1); outline: none; }
.pn-strip .pn-wkstep { display: inline-flex; align-items: center; gap: 2px; margin-left: 4px; padding-left: 6px; border-left: 0.5px solid var(--line-2); }
.pn-strip .pn-wkstep input { width: 34px; height: 24px; box-sizing: border-box; border: 0.5px solid var(--line-2); border-radius: 6px; background: var(--bg-canvas); color: var(--text-1); font: inherit; font-size: var(--fs-meta); text-align: center; -moz-appearance: textfield; }
.pn-strip .pn-wkstep input::-webkit-outer-spin-button, .pn-strip .pn-wkstep input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* Presence on a cell (S3; PlanCell corners): the cell the OTHER side is looking at, shown only while BOTH sides are live. The cell is outlined in the accent ring and a
   small initials badge sits in the TOP-RIGHT corner (`td.c.watched[data-presence="AL"]`); top-left stays for received/held. Quiet, no cursor, never blocks the cell. */
.pg td.c.watched { position: relative; z-index: 1; box-shadow: inset 0 0 0 1px var(--accent-ring); }
/* (::before, not ::after: the active cell's ↵ keycap is the ::after, so a cell that is both active and watched shows both.) The initials sit on the cell's BOTTOM edge, half over the border, to the right: clear of a right-aligned figure of any length and of the received/held mark (top-left). */
.pg td.c.watched::before { content: attr(data-presence); position: absolute; bottom: -6px; right: 4px; padding: 0 3px; border-radius: 3px; background: var(--bg-raised); border: 0.5px solid var(--accent-ring); color: var(--text-2); font-size: 9px; line-height: 11px; font-weight: var(--w-medium); pointer-events: none; }

/* The months row (supplier page; the Plan/PO grid can use it): ONE month label above all the weeks that fall in it (a week belongs to the month of its Thursday),
   left-aligned and quiet, a hairline where a month begins; blank cells over Overdue / Later / No date. Both header rows are sticky: the weeks row sits below it. */
.pplan .pg.pg-plan thead tr.mo th { top: 0; height: 22px; padding-top: 0; padding-bottom: 0; font-size: var(--fs-micro); font-weight: var(--w-medium); text-align: left; color: var(--text-3); border-bottom: 0; }
.pplan .pg.pg-plan thead tr.mo th.fz { z-index: 4; }
.pplan .pg.pg-plan thead tr.mo th.mo-h { overflow: visible; white-space: nowrap; box-shadow: inset 1px 0 0 var(--line-2); }
.pplan .pg.pg-plan thead tr.mo th.mo-none { box-shadow: none; }
.pplan .pg.pg-plan thead tr.mo + tr th { top: 22px; }
/* The hairline where a month begins runs the whole way down: `.ms` is the first week column of a month (a week belongs to the month of its Thursday), on its weeks-row header and on every body cell,
   the same line as `.mo-h` so it is one line from the months row through the weeks and the rows. Quiet; the cells keep their own bottom/right hairline. */
.pplan .pg.pg-plan td.c.ms { box-shadow: inset 1px 0 0 var(--line-2), inset -0.5px -0.5px 0 color-mix(in lch, var(--line-1) 60%, transparent); }
/* In the weeks header the line is drawn as a pseudo-element so it runs the whole cell INCLUDING the bottom border (an inset shadow stops at the border). */
.pplan .pg.pg-plan th.ms::before { content: ''; position: absolute; left: 0; top: 0; bottom: -0.5px; width: 1px; background: var(--line-2); pointer-events: none; }

/* A waiting suggestion, the ghost mark (both sides; a figure, not a corner mark): the proposed quantity as a small dashed figure in the TARGET week's cell
   (`td.c.has-prop` > `<span class="prop">12?</span>`), in the arrival AND the departure cell. The hover line says who proposed it and who it waits for. */
.pg td.c.has-prop { position: relative; }
/* A dashed box in the cell's BOTTOM-LEFT, absolutely placed so the row never grows and the figure never moves (the right-aligned figure keeps its place; the top-left stays free for received/held):
   only what the cell would hold if the suggestions were accepted (`12?`, `0?` where the units leave it), in every cell a suggestion touches. */
.pg td.c .prop { position: absolute; left: 4px; top: auto; bottom: 1px; height: auto; padding: 0 3px; border: 1px dashed var(--text-4); border-radius: 4px; color: var(--text-3); font-size: 9px; font-weight: var(--w-normal); font-variant-numeric: tabular-nums; line-height: 9px; pointer-events: none; }
/* The strip's units box (move part of a cell). */
.pn-strip .pn-qty { display: inline-flex; align-items: center; gap: 6px; margin-left: 4px; padding-left: 6px; border-left: 0.5px solid var(--line-2); font-size: var(--fs-meta); color: var(--text-2); }
.pn-strip .pn-qty label { display: inline-flex; align-items: center; gap: 6px; }
.pn-strip .pn-qty input { width: 52px; height: 24px; box-sizing: border-box; border: 0.5px solid var(--line-2); border-radius: 6px; background: var(--bg-canvas); font: inherit; font-variant-numeric: tabular-nums; text-align: center; color: var(--text-1); outline: none; }
.pn-strip .pn-qty input:focus { border-color: var(--accent-ring); }
.pn-strip .pn-qty-of { color: var(--text-3); }
/* The action strip, stacked when it carries units (the supplier's): Units on one line, the weeks (← n →) on the next, the action last. */
.pn-strip.stack { flex-direction: column; align-items: stretch; gap: 8px; padding: 8px 10px; }
.pn-strip.stack .pn-qty, .pn-strip.stack .pn-wkstep { margin: 0; padding: 0; border-left: 0; justify-content: space-between; }
.pn-strip.stack .pn-acts { display: flex; gap: 4px; justify-content: flex-end; }

/* A request card under the pointer (Plan page and supplier page): the cells it asks to change take the pending-purchase yellow, as Planning drew it (`.pn-hl`, set by the card's hover;
   the grid scrolls to the first). The selected cell (`.pg-active`) and a cell being edited (`.pg-in`) keep their own colour; the presence outline (`.watched`) is a shadow, so it stays. */
.pplan .pg.pg-plan td.c.pn-hl:not(.pg-active):not(.pg-in), .pplan .pg.pg-plan td.c.pn-hl:not(.pg-active):not(.pg-in):hover { background: var(--pm-add); }

