/* MMD portal "GSP XP" skin — the shared semantic component layer for the
   gsp-xp design language (public/_design-system/design-language-gsp-xp.css).
   Moved out of the strategy app on 2026-08-22 when Order Management became
   the second app in this language: one source of truth, no per-app fork.

   Origin — Ben 2026-08-20 for the strategy app:
   Ben 2026-08-20: "have the design of the screens like SAP B1 screens, very
   windows XP era style, super functional and dense." Recorded override of the
   letterbox CDS look for the strategy app. SEMANTIC classes only — the app
   consumes these exactly like CDS classes; zero inline styles remain the rule
   (computed geometry travels as SVG/HTML attributes: line x/y, td colspan).
   One-screen constraint: the app frame locks to the portal body height and
   only pane interiors scroll; designed for 1366x768 upward. */

/* the portal body is the one scroll region; a GSP page opts out and fills it */
.shell > .body:has(> .gsp-app) { padding: 0; overflow: hidden; }

.gsp-app{font-family:var(--font-ui);font-size:11px;color:var(--ds-c-black-02);background:var(--ds-c-yellow-13);height:100%;display:flex;flex-direction:column;overflow:hidden}
.gsp-app *{box-sizing:border-box}

/* window + titlebar */
.gsp-window{border:1px solid var(--ds-c-blue-32);background:var(--ds-c-yellow-13);display:flex;flex-direction:column;min-height:0;min-width:0;flex:1}
/* Centered auth window (e.g. sign-in/register dialogs): the window sits
   centered in its own small frame rather than filling the full-bleed grid
   frame every other GSP screen uses. Canvas colour is the shell's own
   --paper-2 token, already loaded via shell.css -- not a new colour
   (promoted from supplier-xp.css 2026-09-10). */
.gsp-app-center{justify-content:center;align-items:center;background:var(--paper-2)}
.gsp-window-auth{width:max-content;max-width:100%;flex:none}
.gsp-window-auth .gsp-btn{flex:none;white-space:nowrap}
.gsp-window-auth .gsp-btnrow-note{white-space:nowrap}
.gsp-window-auth-body{min-height:0;overflow:auto}
.gsp-titlebar{background:linear-gradient(180deg,var(--ds-c-blue-24) 0%,var(--ds-c-blue-32) 100%);color:var(--ds-c-white-01);font-weight:700;font-size:11px;padding:3px 6px;display:flex;align-items:center;gap:6px;flex:none}
.gsp-titlebar-icon{width:14px;height:14px;background:var(--ds-c-yellow-13);border:1px solid var(--ds-c-white-01);flex:none;display:inline-flex;align-items:center;justify-content:center;color:var(--ds-c-blue-32);font-size:9px;font-weight:700}
.gsp-titlebar-spring{flex:1}

/* menu + toolbar */
/* Title-bar close — real XP chrome on every window and dialog (Ben
   2026-08-21: "add proper nav items, close windo icons"). Escape does the
   same thing. */
.gsp-titlebar-close{font:inherit;font-size:10px;line-height:1;font-weight:700;color:var(--ds-c-white-01);background:linear-gradient(180deg,var(--ds-c-red-11) 0%,var(--ds-c-red-14) 45%,var(--ds-c-red-20) 100%);border:1px solid var(--ds-c-red-23);border-radius:2px;min-width:17px;height:15px;padding:0 4px;cursor:pointer;margin-left:6px;flex:none}
.gsp-titlebar-close:hover{background:linear-gradient(180deg,color-mix(in srgb, var(--ds-c-red-11) 70%, white) 0%,color-mix(in srgb, var(--ds-c-red-14) 70%, white) 45%,color-mix(in srgb, var(--ds-c-red-20) 70%, white) 100%)}
.gsp-titlebar-close:active{background:var(--ds-c-red-20)}
.gsp-titlebar-close:focus-visible{outline:1px dotted var(--ds-c-white-01);outline-offset:1px}
/* Small titlebar action button (e.g. a record dialog's Back control) --
   same ink/border recipe as .gsp-btn, just smaller and inline in the
   titlebar row (promoted from supplier-xp.css 2026-09-10). */
.gsp-titlebar-btn{margin-left:6px;height:auto;min-width:0;font-size:10px;line-height:1}
/* One compact lead-company filter, never a row of country chips (Ben has
   rejected the chip row repeatedly); "All lead companies" is the default. */
.gsp-leadfilter{display:inline-flex;align-items:center;gap:4px;flex:none}
.gsp-leadfilter-label{font-size:10px;color:var(--ds-c-neutral-18);text-transform:uppercase;letter-spacing:.04em}
.gsp-leadfilter .gsp-select{max-width:210px}
.gsp-input-search{max-width:200px}
/* A toolbar is a flex row with min-width:0, so a native select or search
   box shrinks to a sliver once the row is full (seen live: the Catalogue's
   Group by / Rows selects and Find box). A control keeps a readable floor. */
.gsp-toolbar .gsp-select{min-width:120px}
.gsp-toolbar .gsp-input-search{min-width:150px}
/* wrap, never clip/scroll: same contract as .gsp-toolbar below — a tab strip
   (screen tabs, record tabs, PortalDesk's own section sub-menu, all sharing
   this one class) wider than its window folds to a second row at narrow
   viewports instead of cutting off trailing tabs (390px phone: Stock/
   Settings were unreachable behind a horizontal scrollbar). */
.gsp-menubar{background:var(--ds-c-yellow-13);border-bottom:1px solid var(--ds-c-yellow-25);padding:1px 4px;display:flex;flex-wrap:wrap;gap:2px;flex:none;min-width:0}
.gsp-menu{padding:2px 8px;cursor:pointer;color:var(--ds-c-black-02);text-decoration:none;border-radius:var(--ds-radius-sm);}
.gsp-menu:hover,.gsp-menu[aria-current="page"],.gsp-menu[data-active="true"]{background:var(--ds-c-blue-21);color:var(--ds-c-white-01)}
/* Secondary nav row (e.g. DevNav) sets aria-current="page" on its .gsp-btn
   links the same way the top .gsp-menu row does, but carried no active
   styling -- same "you are here" treatment, same tokens, reused rather
   than inventing a new look. */
.gsp-btn[aria-current="page"]{background:var(--ds-c-blue-21);color:var(--ds-c-white-01)}
/* wrap, never clip: a toolbar wider than its window folds to a second row
   instead of hiding controls off the right edge (MMDB-2404 catalogue). */
.gsp-toolbar{background:var(--ds-c-yellow-13);border-bottom:1px solid var(--ds-c-yellow-25);padding:2px 4px;display:flex;gap:2px;align-items:center;flex:none;flex-wrap:wrap;min-width:0}
.gsp-tool{border:1px solid transparent;background:transparent;color:var(--ink);padding:3px 8px;font-family:var(--ds-font-window);border-radius:var(--ds-radius-sm);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;line-height:1;gap:4px;white-space:nowrap}
.gsp-tool:hover{border-color:var(--hairline-dark);background:var(--paper-2)}
/* A tool that cannot act says so (MMDB-2416): greyed, inert cursor, no hover
   invitation — an enabled-looking dead button is a lie. */
.gsp-tool:disabled{color:var(--ink-faint);cursor:default}
.gsp-tool:disabled:hover{border-color:transparent;background:transparent}
.gsp-tool[data-primary="true"]{border:1px solid var(--ds-c-blue-31);background:linear-gradient(180deg,var(--ds-c-white-01) 0%,var(--ds-c-yellow-11) 47%,var(--ds-c-amber-12) 100%);box-shadow:inset 1px 1px 0 var(--ds-c-white-01)}
.gsp-tool[data-primary="true"]:hover{background:linear-gradient(180deg,var(--ds-c-white-01) 0%,var(--ds-c-amber-08) 47%,var(--ds-c-amber-16) 100%)}
.gsp-tool[data-on="true"]{border-color:var(--ds-c-blue-21);background:var(--ds-c-blue-09)}
.gsp-toolbar-sep{width:1px;align-self:stretch;background:var(--ds-c-yellow-25);margin:1px 3px}
.gsp-toolbar-spring{flex:1}
.gsp-toolbar-note{color:var(--ds-c-neutral-13);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}

/* status bar */
.gsp-statusbar{border-top:1px solid var(--ds-c-yellow-25);background:var(--ds-c-yellow-13);padding:2px 6px;display:flex;flex-wrap:wrap;gap:4px 8px;flex:none;color:var(--ds-c-neutral-18);align-items:center;min-width:0}
.gsp-statusbar-cell{border:1px inset var(--ds-c-amber-11);padding:0 6px;background:var(--ds-c-yellow-13);white-space:nowrap}
.gsp-statusbar-cell[data-tone="red"]{color:var(--ds-c-red-22);font-weight:700}
.gsp-statusbar-spring{flex:1}
/* A sentence-length status cell (a refresh result, a sync message): takes
   its own full-width row and wraps instead of running past the window. */
.gsp-statusbar-note{white-space:normal;min-width:0;flex:1 1 100%}
/* A read failure said here used to be the ONLY place it was ever shown, in a
   single-line, ellipsis-clipped cell squeezed behind five other counts — the
   exact text that reported a 20s timeout was invisible unless someone widened
   the window (audit, 2026-08-22). It still echoes here for anyone glancing at
   the status bar, but is never load-bearing any more: `om-read-stale` /
   `om-failure` above the grid carry the same message unclipped. Forced onto
   its own full-width line so it is never fighting the other cells for room,
   and never truncated. */
.gsp-statusbar-evidence{border:1px solid var(--ds-c-amber-23);background:var(--ds-c-yellow-19);color:var(--ds-c-yellow-26);font-weight:700;padding:1px 6px;white-space:normal;min-width:0;flex:1 1 100%}

/* ------------------------------------------------------------------ */
/* Why-What-How matrix (graphical, drawn connectors, chain isolation)  */
.gsp-matrix{display:grid;grid-template-columns:1fr 36px 1fr 36px 1.25fr;flex:1;min-height:0;padding:3px;gap:0;position:relative}
/* connectors sit UNDER the opaque columns so they only show in the gaps */
.gsp-matrix-svg{position:absolute;inset:0;pointer-events:none;z-index:1;width:100%;height:100%}
.gsp-edge{stroke:var(--ds-c-amber-17);stroke-width:1.5;fill:none}
.gsp-edge[data-on="true"]{stroke:var(--ds-c-blue-24);stroke-width:2.5}
.gsp-mcol{border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-white-01);display:flex;flex-direction:column;min-height:0;min-width:0;position:relative;z-index:2}
.gsp-mcol-head{background:linear-gradient(180deg,var(--ds-c-white-02) 0%,var(--ds-c-blue-07) 100%);border-bottom:1px solid var(--ds-c-neutral-06);padding:3px 6px;font-weight:700;color:var(--ds-c-blue-32);flex:none;display:flex;gap:6px;align-items:baseline}
.gsp-mcol-head-count{font-weight:400;color:var(--ds-c-neutral-13)}
.gsp-mcol-body{flex:1;overflow:auto;min-height:0;padding:4px;display:flex;flex-direction:column;gap:4px}
.gsp-mgap{min-width:0}
.gsp-node{border-radius:var(--ds-radius-sm);border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-yellow-05);padding:3px 6px;cursor:pointer;position:relative;text-align:left;font:inherit;width:100%;display:block}
.gsp-node:hover{background:var(--ds-c-yellow-09)}
.gsp-node[data-selected="true"]{border:2px solid var(--ds-c-blue-24);background:var(--ds-c-blue-04);padding:2px 5px}
.gsp-node[data-dim="true"]{opacity:.35}
.gsp-node-id{font-size:10px;color:var(--ds-c-blue-32);font-weight:700;margin-right:4px}
.gsp-node-sub{display:block;font-size:10px;color:var(--ds-c-neutral-10);margin-top:1px}
.gsp-node-open{display:inline-block;margin-left:6px;border:1px solid var(--ds-c-blue-31);background:linear-gradient(180deg,var(--ds-c-white-01) 0%,var(--ds-c-yellow-11) 47%,var(--ds-c-amber-12) 100%);box-shadow:inset 1px 1px 0 var(--ds-c-white-01);padding:0 6px;font-size:10px;font-weight:700;color:var(--ds-c-blue-32);cursor:pointer}
.gsp-node-open:hover{background:linear-gradient(180deg,var(--ds-c-white-01) 0%,var(--ds-c-amber-08) 47%,var(--ds-c-amber-16) 100%)}
.gsp-pane-foot{border-top:1px solid var(--ds-c-yellow-25);background:var(--ds-c-yellow-13);padding:2px 6px;color:var(--ds-c-neutral-13);flex:none}
.gsp-plan-state{font-size:10px;white-space:nowrap}
.gsp-plan-state[data-state="none"]{color:var(--ds-c-red-17);font-weight:700}
.gsp-plan-state[data-state="deck_derived"]{color:var(--rp-ink-mute)}
.gsp-plan-state[data-state="draft"]{color:var(--rp-ink-mute)}
.gsp-plan-state[data-state="unscheduled"]{color:var(--ds-c-red-17)}
.gsp-plan-state[data-state="confirmed"]{color:var(--ds-c-green-12)}

/* status chips */
.gsp-chip{display:inline-block;border:1px solid var(--ds-c-neutral-06);padding:0 4px;font-size:10px;background:var(--ds-c-white-01);white-space:nowrap;border-radius:var(--ds-radius-sm);}
.gsp-chip[data-tone="red"]{background:var(--ds-c-red-08);border-color:var(--ds-c-red-17);color:var(--ds-c-red-26)}
.gsp-chip[data-tone="amber"]{background:var(--ds-c-yellow-19);border-color:var(--ds-c-amber-23);color:var(--ds-c-yellow-26)}
.gsp-chip[data-tone="green"]{background:var(--ds-c-green-04);border-color:var(--ds-c-green-09);color:var(--ds-c-green-12)}
.gsp-chip[data-tone="blue"]{background:var(--ds-c-blue-07);border-color:var(--ds-c-blue-21);color:var(--ds-c-blue-32)}
/* "stop": a read failed and the true state is UNKNOWN — never the same claim
   as "red" (verified retired/unguarded). Hazard-striped on the same red
   tokens `red` already uses, so it reads as "more urgent than red", not as
   a fourth unrelated colour. */
.gsp-chip[data-tone="stop"]{background:repeating-linear-gradient(135deg,var(--ds-c-red-08),var(--ds-c-red-08) 4px,var(--ds-c-white-01) 4px,var(--ds-c-white-01) 8px);border-color:var(--ds-c-red-17);color:var(--ds-c-red-26);font-weight:700}
/* neutral tone for a read-only/reference status (e.g. an imported historic
   record, not a live workflow state) -- Ben, 2026-08-22 direct-purchase
   historic-rows task */
.gsp-chip[data-tone="grey"]{background:var(--ds-c-yellow-15);border-color:var(--ds-c-neutral-06);color:var(--ds-c-neutral-13)}
.gsp-link{color:var(--ds-c-blue-32);text-decoration:underline;cursor:pointer;background:none;border:0;font:inherit;padding:0}
.gsp-muted{color:var(--ds-c-neutral-08)}

/* ------------------------------------------------------------------ */
/* Objective program sheet (MMD Project Reporting Template mirror)     */
.gsp-sheet{display:grid;grid-template-columns:1fr 1fr 1fr;grid-auto-rows:min-content;gap:3px;padding:3px 3px 46px;flex:1;min-height:0;overflow:auto}
.gsp-card{border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-white-01);display:flex;flex-direction:column;min-height:0}
.gsp-card-head{background:linear-gradient(180deg,var(--ds-c-white-02),var(--ds-c-yellow-20));border-bottom:1px solid var(--ds-c-yellow-25);padding:2px 6px;font-weight:700;font-size:10px;letter-spacing:.04em;display:flex;gap:6px;align-items:baseline}
.gsp-card-head-note{font-weight:400;color:var(--ds-c-neutral-12);letter-spacing:0}
.gsp-card-body{padding:4px 6px;font-size:11px;line-height:1.35}
.gsp-card-body ul{margin:0;padding-left:14px}
/* Thumbnail tile (marketing assets register + any future media grid). Fixed
   square tile; the fallback covers missing/unsupported-format assets with a
   short label instead of a broken-image glyph. */
.gsp-thumb{position:relative;width:40px;height:40px;flex:none;border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-white-01);overflow:hidden;display:flex;align-items:center;justify-content:center}
.gsp-thumb-img{width:100%;height:100%;object-fit:cover;display:block}
.gsp-thumb-fallback{display:flex;align-items:center;justify-content:center;width:100%;height:100%;background:var(--ds-c-neutral-02);color:var(--ds-c-neutral-10);font-size:9px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;text-align:center;line-height:1.2;padding:2px}
.gsp-thumb-label{margin-top:2px;font-size:9px;color:var(--ds-c-neutral-10);text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:56px}
/* Dense tile grid for a row-as-card gallery view of thumbnails (DataGrid's
   cardRender seam, TASK-02.7). Registered as a primitive; not yet consumed by
   a live gallery toggle. */
.gsp-thumb-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(96px,1fr));gap:6px}
.gsp-span2{grid-column:span 2}
.gsp-span3{grid-column:span 3}
/* flex-shrink:0 is load-bearing, not decorative: this strip's own overflow:
   hidden removes a flex item's automatic (min-content) minimum size per the
   flexbox spec, so without an explicit shrink floor it silently collapses to
   0px height under any upstream height pressure in its flex-column parent
   (FE-POLISH P1, e.g. employee-file identity chips vanishing when the H1
   above briefly rendered taller than the .property-heading design height —
   confirmed live via getBoundingClientRect: headstrip height was exactly 0). */
.gsp-headstrip{display:flex;gap:8px;align-items:center;min-width:0;overflow:hidden;flex-shrink:0}
.gsp-headcell{border:1px inset var(--ds-c-amber-11);background:var(--ds-c-white-01);padding:1px 6px;white-space:nowrap;font-size:10px}
.gsp-rag{display:inline-block;width:12px;height:12px;border:1px solid var(--ds-c-neutral-12);vertical-align:middle}
.gsp-rag[data-rag="G"]{background:var(--ds-c-green-07)}.gsp-rag[data-rag="A"]{background:var(--ds-c-amber-20)}.gsp-rag[data-rag="R"]{background:var(--ds-c-red-14)}.gsp-rag[data-rag="N"]{background:var(--ds-c-yellow-24)}
.gsp-noplan{border:2px solid var(--ds-c-red-17);background:var(--ds-c-red-04);color:var(--ds-c-red-26);font-weight:700;padding:8px 10px;text-align:center}
.gsp-noplan .gsp-noplan-sub{display:block;font-weight:400;color:var(--ds-c-neutral-18);margin-top:2px}

/* phase timeline (computed month spans travel as td colspan attributes) */
/* Redline p8 (2026-09-25): fixed, small timeline columns. table-layout:fixed only takes effect when the
   table width is not auto, so width:1px lets the used width become exactly the sum of the <col> widths
   (never stretched to the card). .gsp-gantt-scroll scrolls horizontally only when that sum is wider. */
.gsp-gantt-scroll{max-width:100%;overflow-x:auto}
.gsp-gantt{width:1px;table-layout:fixed;border-collapse:collapse}
.gsp-gantt-col-name{width:150px}
.gsp-gantt-col-month{width:28px}
.gsp-gantt-col-nodate{width:140px}
.gsp-gantt th,.gsp-gantt td{border:1px solid var(--ds-c-yellow-15);font-size:9px;padding:1px 2px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:clip}
.gsp-gantt td.gsp-phase-name{text-align:left;font-size:10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gsp-gantt tr[data-kind="action"] td.gsp-phase-name{padding-left:10px}
.gsp-mark{display:block;width:9px;height:9px;margin:0 auto;background:var(--ds-c-blue-21)}
.gsp-mark[data-t="done"]{background:var(--ds-c-green-07)}
.gsp-mark[data-t="stalled"]{background:var(--ds-c-red-17)}
.gsp-mark[data-t="new"]{background:var(--ds-c-yellow-24)}
.gsp-bar{display:block;height:9px;background:repeating-linear-gradient(90deg,var(--ds-c-blue-21) 0,var(--ds-c-blue-21) 6px,var(--ds-c-blue-16) 6px,var(--ds-c-blue-16) 8px)}
.gsp-bar[data-state="done"]{background:var(--ds-c-green-07)}
.gsp-bar[data-state="planned"]{background:repeating-linear-gradient(90deg,var(--ds-c-yellow-24) 0,var(--ds-c-yellow-24) 4px,var(--ds-c-white-01) 4px,var(--ds-c-white-01) 6px)}
.gsp-action-row{display:flex;gap:6px;align-items:baseline;border-bottom:1px dotted var(--ds-c-yellow-20);padding:1px 0}
.gsp-traction{font-size:9px;border:1px solid var(--ds-c-neutral-06);padding:0 3px;white-space:nowrap;background:var(--ds-c-white-01)}
.gsp-traction[data-t="moving"],.gsp-traction[data-t="granted"],.gsp-traction[data-t="done"]{background:var(--ds-c-green-04);border-color:var(--ds-c-green-09)}
.gsp-traction[data-t="stalled"],.gsp-traction[data-t="high"]{background:var(--ds-c-red-08);border-color:var(--ds-c-red-17)}
.gsp-traction[data-t="new"],.gsp-traction[data-t="decision"],.gsp-traction[data-t="money"]{background:var(--ds-c-blue-07);border-color:var(--ds-c-blue-21)}
.gsp-traction[data-t="med"]{background:var(--ds-c-yellow-19);border-color:var(--ds-c-amber-23)}

/* overview rollup band — dense working strip above the grid */
.gsp-rollup{border-bottom:1px solid var(--ds-c-yellow-25);background:var(--ds-c-yellow-05);padding:2px 6px;display:flex;gap:8px;align-items:baseline;flex-wrap:wrap;flex:none}
.gsp-rollup-cell{border:1px inset var(--ds-c-amber-11);background:var(--ds-c-white-01);padding:0 6px;white-space:nowrap}
.gsp-rollup-cell[data-tone="red"]{color:var(--ds-c-red-22);font-weight:700}
.gsp-rollup-cell b{color:var(--ds-c-red-22)}
/* full-basis + ellipsis: the nowrap chase line's min-content width was
   wider than the viewport and dragged the whole window into page-level
   horizontal scroll */
.gsp-rollup-chase{flex:1 1 100%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* hub sections (Review & status page): stacked labeled blocks */
.gsp-hub-section{border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-white-01);margin:3px}
.gsp-hub-section .gsp-mcol-head{display:flex;align-items:baseline;gap:6px}

/* grids (SAP-B1 style, used by trail + overview) */
.gsp-grid{width:100%;border-collapse:collapse;font-size:11px}
.gsp-grid th{background:linear-gradient(180deg,var(--ds-c-white-02),var(--ds-c-yellow-20));border:1px solid var(--ds-c-yellow-25);border-top:none;padding:2px 5px;text-align:left;font-weight:700;position:sticky;top:0;white-space:nowrap;z-index:2}
.gsp-grid td{border-right:1px solid var(--ds-c-yellow-15);border-bottom:1px solid var(--ds-c-yellow-15);padding:2px 5px;vertical-align:top}
.gsp-grid tr:nth-child(even) td{background:var(--ds-c-yellow-05)}
/* Hover only invites a click where a click does something (MMDB-2416):
   a glowing row with no handler is a lying affordance. */
.gsp-grid tbody tr[data-click="true"]:hover td{background:var(--ds-c-yellow-09)}
.gsp-grid td[data-num="true"],.gsp-grid th[data-num="true"]{text-align:right;font-variant-numeric:tabular-nums}
.gsp-grid tr[data-group="true"] td{background:var(--ds-c-blue-07);color:var(--ds-c-blue-32);font-weight:700;border-bottom:1px solid var(--ds-c-neutral-06)}
/* imported historic/reference row -- dimmed + non-interactive look, no
   hover highlight, distinct from a live, clickable workflow row (Ben,
   2026-08-22 direct-purchase historic-rows task) */
.gsp-grid tr[data-historic="true"] td{background:var(--ds-c-yellow-08);color:var(--ds-c-neutral-12);font-style:italic}
.gsp-grid tr[data-historic="true"]:hover td{background:var(--ds-c-yellow-08)}
.gsp-grid tr[data-click="true"]{cursor:pointer}
.gsp-picker-results{max-height:220px;overflow-y:auto;border:1px solid var(--ds-c-neutral-06)}
.gsp-cell-tight{white-space:nowrap;max-width:240px;overflow:hidden;text-overflow:ellipsis}
/* 2026-09-27 (Ben's CWG portal UX audit, P2): `.gsp-cell-title` is
   deliberately NOT truncated everywhere it's used (it doubles as a
   clickable record-link label elsewhere, e.g. `.property-register-table
   .gsp-cell-title`, where reading the full name matters more than a tidy
   column) -- but inside a plain `.gsp-grid` sub-table (Suppliers - local's
   Contacts list is the confirmed live case) a long name with no width
   constraint at all wrapped 5 lines tall, forcing the whole row (and the
   NEXT contact's row) out of a fixed-height panel. Scoped to `.gsp-grid`
   only, mirroring `.gsp-cell-tight`'s own established single-line-ellipsis
   treatment right above -- every other `.gsp-cell-title` consumer is
   untouched. */
.gsp-grid .gsp-cell-title{white-space:nowrap;max-width:220px;overflow:hidden;text-overflow:ellipsis}
/* Line-item grid with a wide free-text column (e.g. a bid-lines proposal
   grid): third column caps width, last column keeps room for the note
   (promoted from supplier-xp.css 2026-09-10). */
.gsp-grid-bid-lines td:nth-child(3){max-width:200px}
.gsp-grid-bid-lines th:last-child,.gsp-grid-bid-lines td:last-child{min-width:230px}
/* frozen identity columns on the overview grid (UX P1: scrolling right to the
   status columns lost the ID/Objective a row belongs to) */
.gsp-col-pin{position:sticky;background:var(--ds-c-white-01);z-index:3}
th.gsp-col-pin{z-index:4}
.gsp-col-pin-id{left:0;min-width:84px;max-width:320px;border-right:1px solid var(--ds-c-neutral-06)}
.gsp-col-pin-title{left:84px;border-right:2px solid var(--ds-c-neutral-06)}
.gsp-grid-kpi .gsp-col-pin-id{max-width:230px}
.gsp-grid-kpi-plain tbody td:nth-child(4){max-width:180px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gsp-grid-kpi tbody td:nth-child(2){max-width:170px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gsp-grid tr:nth-child(even) td.gsp-col-pin{background:var(--ds-c-yellow-05)}
.gsp-grid tbody tr:hover td.gsp-col-pin{background:var(--ds-c-yellow-09)}
.gsp-group-label{position:sticky;left:6px;display:inline-block}
.gsp-group-toggle{background:none;border:0;font:inherit;font-weight:700;color:var(--ds-c-blue-32);cursor:pointer;padding:0;text-align:left}
.gsp-group-toggle:hover .gsp-group-chevron{color:var(--ds-c-red-22)}
.gsp-group-chevron{display:inline-block;width:12px;color:var(--ds-c-blue-21)}
.gsp-group-hint{font-weight:400;color:var(--ds-c-neutral-12);font-size:10px}
tr[data-group][data-collapsed="true"] td{border-bottom:2px solid var(--ds-c-neutral-06)}
/* open affordance on clickable rows (Ben: "make sure it's understood...
   they can double-click to open") */
.gsp-grid tr[data-click="true"] td:first-child::before{content:"▸ ";color:var(--ds-c-blue-21);font-size:9px}
.gsp-grid tr[data-click="true"]:hover td:first-child::before{color:var(--ds-c-red-22)}
/* sortable column headers (MMDB-2256: register/activity/status grids) */
.gsp-grid th[data-click="true"]{cursor:pointer}
.gsp-grid th[data-click="true"]:hover{background:var(--ds-c-blue-04)}
/* compound cell: bold primary line + gsp-node-sub secondary line, used where
   a DataGrid cell used to stack a title over an id/leader/lead sub-line */
.gsp-cell-title{font-weight:700}
/* the pane scrolls both ways — keep the scrollbar visible as the affordance;
   it is also the ONE region that grows/scrolls inside a gsp-window (the
   one-screen rule: everything else in the window is flex:none) */
.gsp-pane-body{flex:1;min-height:0;overflow:auto;padding-bottom:46px;scrollbar-width:thin;scrollbar-color:var(--ds-c-neutral-06) var(--ds-c-yellow-13)}

/* stacked sections inside one scrolling pane (MMDB-2256: register/status
   surfaces stack more than one gsp-grid under a single toolbar+statusbar) */
.gsp-section{border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-white-01);margin:3px;display:flex;flex-direction:column;min-height:0}
.gsp-section-head{background:linear-gradient(180deg,var(--ds-c-white-02) 0%,var(--ds-c-blue-07) 100%);border-bottom:1px solid var(--ds-c-neutral-06);padding:2px 6px;font-weight:700;color:var(--ds-c-blue-32);flex:none;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.gsp-section-head-note{font-weight:400;color:var(--ds-c-neutral-13)}

/* toolbar filter fields — fixed widths so they don't fight the toolbar's
   note/spring for growth (register/activity/status filter bars) */
.gsp-toolbar-label{color:var(--ds-c-neutral-18);white-space:nowrap}
.gsp-input[data-w="wide"]{flex:none;width:200px}
.gsp-select[data-w="wide"]{flex:none;width:168px}

/* forms (dense XP group boxes) + dialogs */
.gsp-fieldset{border:1px solid var(--ds-c-neutral-06);margin:4px;padding:4px 6px 6px;min-width:0}
.gsp-fieldset legend{color:var(--ds-c-blue-32);font-weight:700;padding:0 4px}
.gsp-form-row{display:flex;align-items:center;gap:6px;margin:2px 0}
.gsp-form-row label{flex:0 0 110px;text-align:right;color:var(--ds-c-neutral-18)}
.gsp-input,.gsp-select,.gsp-textarea{border:1px solid var(--ds-c-blue-13);background:var(--ds-c-white-01);font:inherit;padding:1px 3px;flex:1;min-width:0}
.gsp-input[data-w="narrow"]{flex:none;width:76px}
.gsp-select[data-w="narrow"]{flex:none;width:96px}
/* numeric/fill columns in a dense line-item grid (e.g. a bid-lines proposal
   form): price/qty columns get a narrow fixed width, the remarks-style
   column gets the freed space (promoted from supplier-xp.css 2026-09-10). */
.gsp-input[data-w="num"]{width:64px}
.gsp-input[data-w="fill"]{width:100%;min-width:120px}
.gsp-textarea{resize:none}
/* Inline field error/success (e.g. an OTP step or a proposal form) -- same
   red/green ink the rest of the skin already uses for these states
   (.gsp-chip[data-tone="red"/"green"], .gsp-plan-state[data-state=
   "confirmed"]), not a new colour (promoted from supplier-xp.css 2026-09-10). */
.gsp-form-error{color:var(--ds-c-red-22);font-weight:700;font-size:11px;margin:4px 6px 0}
.gsp-form-success{color:var(--ds-c-green-12);font-weight:700;font-size:11px;margin:4px 6px 0}
/* 2026-08-28 MMDB-1688/2395 locked-design rollout: gsp-btn is the ONE
   button class every windowed-desktop app (Strategy/Procurement2/
   Order-mgmt/Master-data/Dealer-portal) renders through -- 193 call sites
   across 47 files, all plain "gsp-btn" with no variant. It is now a thin
   alias onto the central .ds-btn recipe (flat, 1px border, hairline inset
   bottom edge, 4px radius, SF Pro, CDS tokens only -- zero new hex). */
.gsp-btn{display:inline-flex;align-items:center;justify-content:center;line-height:1;gap:6px;border:1px solid var(--hairline-dark);background:var(--paper);color:var(--ink);box-shadow:inset 0 -1px 0 color-mix(in srgb, var(--ink) 10%, transparent);font-family:var(--ds-font-window);font-weight:500;font-size:11px;padding:5px 13px;border-radius:var(--ds-radius-sm);cursor:pointer}
.gsp-btn:hover{border-color:var(--ink-mute);color:var(--ink)}
.gsp-btn[data-default="true"]{background:var(--baobab);color:var(--baobab-on);border-color:var(--baobab);box-shadow:inset 0 -1px 0 rgba(0,0,0,.18)}
.gsp-btn[data-default="true"]:hover{background:color-mix(in srgb, var(--baobab) 88%, black)}
.gsp-btn:disabled{color:var(--ink-faint);cursor:default;opacity:.6}
/* Selected tab state (FE-POLISH P2): a .gsp-btn used as a tab (e.g. the
   employee-file Personal/Job & organisation/... row, aria-pressed=true for
   the active tab) carried no active styling at all -- every tab looked the
   same. Same "you are here" treatment .gsp-menu[aria-current="page"] already
   uses elsewhere in this file, reused rather than inventing a new look. */
.gsp-btn[aria-pressed="true"]{background:var(--ds-c-blue-21);color:var(--ds-c-white-01);border-color:var(--ds-c-blue-32)}
.gsp-btn[aria-pressed="true"]:hover{background:var(--ds-c-blue-21);color:var(--ds-c-white-01)}
.gsp-btnrow{display:flex;gap:7px;justify-content:flex-end;align-items:center;padding:6px 10px;border-top:1px solid var(--hairline);background:var(--paper-2);flex:none}
.gsp-btnrow-note{margin-right:auto;font-family:var(--ds-font-window);color:color-mix(in srgb, var(--baobab) 72%, black)}
/* Plain-ink note (e.g. "test login is on") -- the base .gsp-btnrow-note ink
   is styled for a warning; not every note is one (promoted from
   supplier-xp.css 2026-09-10). */
.gsp-btnrow-note[data-tone="info"]{color:var(--ds-c-neutral-18);font-weight:400}
.gsp-dialog-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.25);display:flex;align-items:center;justify-content:center;z-index:60}
.gsp-dialog{border:1px solid var(--ds-c-blue-32);background:var(--ds-c-yellow-13);box-shadow:2px 2px 6px rgba(0,0,0,.4);width:min(860px,94vw);max-height:92vh;display:flex;flex-direction:column;font-family:var(--font-ui);font-size:11px}
.gsp-dialog *{box-sizing:border-box}
.gsp-dialog-body{overflow:auto;min-height:0}
.gsp-rowbtn{border:1px solid var(--hairline-dark);background:var(--paper);color:var(--ink);font-family:var(--ds-font-window);font-size:10px;padding:1px 6px;cursor:pointer;flex:none;border-radius:var(--ds-radius-sm)}
.gsp-rowbtn:hover{background:var(--baobab-bg);border-color:var(--baobab)}
.gsp-rowbtn:disabled{color:var(--ink-faint);cursor:default;opacity:.6}
.gsp-rowbtn:disabled:hover{background:var(--paper);border-color:var(--hairline-dark)}
.gsp-addrow{border:1px dashed var(--hairline-dark);background:var(--paper);color:var(--ink-mute);font-family:var(--ds-font-window);padding:2px 9px;cursor:pointer;margin:3px 0 0;border-radius:var(--ds-radius-sm)}
.gsp-addrow:hover{background:var(--paper-2);border-color:var(--ink-mute);color:var(--ink)}

/* progress cell (dense bar; widths via the CDS pct-step attribute scale) */
.gsp-meter{display:inline-flex;align-items:center;gap:4px;white-space:nowrap}
.gsp-meter-track{width:60px;height:8px;border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-white-01);display:inline-block}
.gsp-meter-fill{height:100%;background:repeating-linear-gradient(90deg,var(--ds-c-blue-21) 0,var(--ds-c-blue-21) 6px,var(--ds-c-blue-16) 6px,var(--ds-c-blue-16) 8px);display:block}
.gsp-meter-fill[data-pct="0"]{width:0}.gsp-meter-fill[data-pct="5"]{width:5%}.gsp-meter-fill[data-pct="10"]{width:10%}.gsp-meter-fill[data-pct="15"]{width:15%}.gsp-meter-fill[data-pct="20"]{width:20%}.gsp-meter-fill[data-pct="25"]{width:25%}.gsp-meter-fill[data-pct="30"]{width:30%}.gsp-meter-fill[data-pct="35"]{width:35%}.gsp-meter-fill[data-pct="40"]{width:40%}.gsp-meter-fill[data-pct="45"]{width:45%}.gsp-meter-fill[data-pct="50"]{width:50%}.gsp-meter-fill[data-pct="55"]{width:55%}.gsp-meter-fill[data-pct="60"]{width:60%}.gsp-meter-fill[data-pct="65"]{width:65%}.gsp-meter-fill[data-pct="70"]{width:70%}.gsp-meter-fill[data-pct="75"]{width:75%}.gsp-meter-fill[data-pct="80"]{width:80%}.gsp-meter-fill[data-pct="85"]{width:85%}.gsp-meter-fill[data-pct="90"]{width:90%}.gsp-meter-fill[data-pct="95"]{width:95%}.gsp-meter-fill[data-pct="100"]{width:100%}

/* action wizard (MMDB-2260): source plan / generated proposal / versions */
/* Wizard generation progress — a real, staged read-out of a job that runs on
   the gateway for the best part of a minute, not a spinner. */
.gsp-progress{display:flex;align-items:center;gap:8px;margin:3px 3px 0;padding:2px 6px;border:1px solid var(--ds-c-blue-21);background:var(--ds-c-blue-03);font-size:11px}
.gsp-progress[data-state="done"]{border-color:var(--ds-c-green-09);background:var(--ds-c-green-02)}
.gsp-progress[data-state="failed"]{border-color:var(--ds-c-red-17);background:var(--ds-c-red-03)}
.gsp-progress-step{font-size:9px;font-weight:700;color:var(--ds-c-blue-32);border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-white-01);padding:0 4px;white-space:nowrap}
.gsp-progress[data-state="failed"] .gsp-progress-step{color:var(--ds-c-red-17)}
.gsp-progress-text{font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}
.gsp-progress-detail{font-weight:400;color:var(--ds-c-blue-30)}
.gsp-progress-bar{position:relative;flex:none;width:190px;height:12px;border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-white-01);overflow:hidden}
.gsp-progress-fill{position:absolute;left:0;top:0;bottom:0;width:0;background:repeating-linear-gradient(90deg,var(--ds-c-blue-21) 0 8px,var(--ds-c-blue-17) 8px 12px);transition:width .4s linear}
.gsp-progress[data-state="done"] .gsp-progress-fill{background:repeating-linear-gradient(90deg,var(--ds-c-green-09) 0 8px,var(--ds-c-green-06) 8px 12px)}
.gsp-progress[data-state="failed"] .gsp-progress-fill{background:repeating-linear-gradient(90deg,var(--ds-c-red-17) 0 8px,var(--ds-c-red-12) 8px 12px)}
.gsp-progress-pct{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:700;color:var(--ds-c-blue-32);mix-blend-mode:normal}
.gsp-progress-elapsed{font-variant-numeric:tabular-nums;color:var(--ds-c-neutral-13);white-space:nowrap;flex:none}
.gsp-progress-note{color:var(--ds-c-neutral-13);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:none}
.gsp-progress-fill[data-pct="0"]{width:0%}
.gsp-progress-fill[data-pct="5"]{width:5%}
.gsp-progress-fill[data-pct="10"]{width:10%}
.gsp-progress-fill[data-pct="15"]{width:15%}
.gsp-progress-fill[data-pct="20"]{width:20%}
.gsp-progress-fill[data-pct="25"]{width:25%}
.gsp-progress-fill[data-pct="30"]{width:30%}
.gsp-progress-fill[data-pct="35"]{width:35%}
.gsp-progress-fill[data-pct="40"]{width:40%}
.gsp-progress-fill[data-pct="45"]{width:45%}
.gsp-progress-fill[data-pct="50"]{width:50%}
.gsp-progress-fill[data-pct="55"]{width:55%}
.gsp-progress-fill[data-pct="60"]{width:60%}
.gsp-progress-fill[data-pct="65"]{width:65%}
.gsp-progress-fill[data-pct="70"]{width:70%}
.gsp-progress-fill[data-pct="75"]{width:75%}
.gsp-progress-fill[data-pct="80"]{width:80%}
.gsp-progress-fill[data-pct="85"]{width:85%}
.gsp-progress-fill[data-pct="90"]{width:90%}
.gsp-progress-fill[data-pct="95"]{width:95%}
.gsp-progress-fill[data-pct="100"]{width:100%}
@media (prefers-reduced-motion:reduce){.gsp-progress-fill{transition:none}}
/* Action tree (MMDB-2282) — a tracked action per row: its id, what kind of
   work it is, the text, who else it serves, its traction, and the controls to
   break it down or hand it over. Depth is a data attribute so app code never
   carries an inline indent. */
.gsp-card-head-spring{flex:1}
/* The action tree is a working list, not a side panel: it takes the whole
   width of the sheet grid so a row reads on one line. */
.gsp-sheet > .gsp-card-wide{grid-column:1 / -1}
.gsp-card-wide .gsp-card-body{max-height:340px;overflow:auto}
.gsp-action-node{display:flex;gap:6px;align-items:baseline;border-bottom:1px dotted var(--ds-c-yellow-15);padding:2px 4px;min-height:19px}
.gsp-action-node:hover{background:var(--ds-c-yellow-09)}
.gsp-action-node[data-depth="1"]{padding-left:22px}
.gsp-action-node[data-depth="2"]{padding-left:40px}
.gsp-action-node[data-depth="3"]{padding-left:58px}
.gsp-action-node[data-depth="4"]{padding-left:76px}
.gsp-action-node[data-depth="5"]{padding-left:94px}
.gsp-action-node[data-depth="6"]{padding-left:112px}
.gsp-action-node[data-depth="7"]{padding-left:130px}
.gsp-action-node[data-depth="8"]{padding-left:148px}
.gsp-action-node[data-depth="1"],.gsp-action-node[data-depth="2"],.gsp-action-node[data-depth="3"],
.gsp-action-node[data-depth="4"],.gsp-action-node[data-depth="5"],.gsp-action-node[data-depth="6"],
.gsp-action-node[data-depth="7"],.gsp-action-node[data-depth="8"]{border-left:1px solid var(--ds-c-yellow-20)}
.gsp-tree-toggle{font:inherit;font-size:9px;line-height:1;width:13px;height:13px;padding:0;flex:none;border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-white-01);color:var(--ds-c-blue-32);cursor:pointer}
.gsp-tree-toggle:hover{background:var(--ds-c-blue-07)}
.gsp-tree-leaf{width:13px;flex:none}
.gsp-action-id{font-size:10px;font-weight:700;color:var(--ds-c-blue-32);white-space:nowrap;flex:none;font-variant-numeric:tabular-nums}
.gsp-action-text{flex:1;min-width:0}
.gsp-action-shared{font-size:10px;color:var(--ds-c-amber-28);border:1px solid var(--ds-c-amber-23);background:var(--ds-c-yellow-19);padding:0 4px;white-space:nowrap;flex:none}
.gsp-select-tight{font-size:10px;padding:0 2px;max-width:118px;flex:none}
.gsp-action-add{display:flex;gap:6px;align-items:center;padding:3px 4px;border-bottom:1px solid var(--ds-c-neutral-06);background:var(--ds-c-yellow-05)}
.gsp-action-add .gsp-input{flex:1;min-width:0}
.gsp-action-add .gsp-select{flex:none;max-width:150px}
.gsp-wiz-section{display:flex;gap:6px;align-items:baseline;border-bottom:1px solid var(--ds-c-yellow-20);padding:2px 0 1px;margin-top:2px}
.gsp-wiz-section-count{font-size:10px;color:var(--ds-c-neutral-12)}
.gsp-wiz-section-spring{flex:1}
.gsp-wiz{display:grid;grid-template-columns:0.9fr 1.6fr 0.8fr;gap:3px;padding:3px;flex:1;min-height:0}
.gsp-wiz-col{border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-white-01);display:flex;flex-direction:column;min-height:0}
.gsp-wiz-item{display:flex;gap:6px;align-items:baseline;border-bottom:1px dotted var(--ds-c-yellow-20);padding:2px 4px;cursor:pointer}
.gsp-wiz-kind{font-size:9px;border:1px solid var(--ds-c-neutral-06);padding:0 3px;white-space:nowrap;background:var(--ds-c-white-01)}
.gsp-wiz-kind[data-k="task"]{background:var(--ds-c-green-04);border-color:var(--ds-c-green-09)}
.gsp-wiz-kind[data-k="research"]{background:var(--ds-c-blue-07);border-color:var(--ds-c-blue-21)}
.gsp-wiz-kind[data-k="gap"]{background:var(--ds-c-yellow-19);border-color:var(--ds-c-amber-23)}
.gsp-wiz-kind[data-k="people"]{background:var(--ds-c-neutral-02);border-color:var(--ds-c-neutral-08)}
.gsp-version{border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-yellow-05);padding:3px 6px;cursor:pointer;display:block;width:100%;text-align:left;font:inherit;margin-bottom:3px}
.gsp-version[data-active="true"]{border:2px solid var(--ds-c-blue-24);background:var(--ds-c-blue-04)}
.gsp-version-meta{display:block;font-size:10px;color:var(--ds-c-neutral-10)}

/* popup record layout (XP popup kit) */
.gsp-record{display:flex;flex-direction:column}
.gsp-record-fields{display:grid;grid-template-columns:1fr 1fr;gap:1px 10px}
.gsp-record-field{display:flex;gap:6px;align-items:baseline;border-bottom:1px dotted var(--ds-c-yellow-15);padding:1px 0;min-width:0}
.gsp-record-field[data-wide="true"]{grid-column:span 2}
.gsp-record-field[data-empty="true"]{opacity:.55}
.gsp-record-field-l{flex:0 0 120px;color:var(--ds-c-neutral-13);font-size:10px;text-transform:uppercase;letter-spacing:.03em}
.gsp-record-field-v{min-width:0;overflow-wrap:anywhere}
.gsp-record-lead{display:flex;justify-content:space-between;align-items:baseline;gap:10px;border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-yellow-05);padding:3px 6px;margin:0 0 3px}
.gsp-record-lead[data-tone="warn"]{background:var(--ds-c-yellow-19);border-color:var(--ds-c-amber-23)}
.gsp-record-lead[data-tone="alert"]{background:var(--ds-c-red-08);border-color:var(--ds-c-red-17)}
.gsp-record-lead-id{min-width:0}
.gsp-record-lead-flag{display:flex;gap:5px;align-items:baseline;white-space:nowrap}

/* the id chip sits on the blue titlebar: keep its ink dark (UX round 1: white-on-white made it invisible) */
.gsp-titlebar .gsp-headcell{color:var(--ds-c-blue-32);background:var(--ds-c-yellow-13);font-weight:700}
/* dense popup form grid (UX round 1: letterbox fields inside an XP dialog) */
.gsp-field-row-2{display:grid;grid-template-columns:1fr 1fr;gap:2px 10px;padding:2px 0}
.gsp-field{display:flex;flex-direction:column;gap:1px;min-width:0}
.gsp-field-span-2{grid-column:span 2}
.gsp-label{font-size:10px;color:var(--ds-c-neutral-13);text-transform:uppercase;letter-spacing:.03em}
.gsp-field .gsp-input,.gsp-field .gsp-select,.gsp-field .gsp-textarea{flex:none;width:100%}
/* UX-REVIEW-INTRANET-20260927 round 5: dxg-core's content-field label
   (form.label -> .ds-label: 12px/weight 600/full ink) reads heavier and
   larger than every scalar field's .gsp-label (10px/inherited weight/
   --ink-mute) in the SAME window, once a content field (rich text/media/
   attachments) sits inside a .gsp-field here -- match .gsp-label's
   ACTUAL rendered appearance exactly (verified live via getComputedStyle:
   .gsp-label's own color:var(--ds-c-neutral-13) declaration is itself
   overridden elsewhere in the cascade to --ink-mute for real usage, and
   its font-weight is unset/inherited, not explicitly 400 -- copying the
   live values, not the stale source rule, so this stays correct if that
   cascade changes), scoped to this window chrome only. form.label keeps
   its normal appearance everywhere else it's used (finance/flowcase/TA
   and other hosts). */
.gsp-field .ds-label{font-size:10px;font-weight:inherit;color:var(--ink-mute);letter-spacing:.03em}
/* UX-REVIEW-INTRANET-20260927 round 5: collapse the dense 2-column popup
   grid to one column under ~600px so narrow-viewport fields don't render
   at an unreadable fraction of the row width (Marketing/Procurement share
   this same grid -- re-verified at 402px after this change). */
@media (max-width:600px){
  .gsp-field-row-2{grid-template-columns:1fr}
}
/* redline 2026-09-01 p9: the full-width rule above (0,2,0, later in file)
   beat the plain data-w="narrow" widths, so short fields rendered 413px.
   Inside a form field the narrow widths are sized to their content: the
   input fits a YYYY-MM date, a unit ("kT", "USD m") or a 10-digit number;
   the select fits "2027/8 plan" / "Year 2 plan" plus the drop arrow. */
.gsp-field .gsp-input[data-w="narrow"]{width:112px}
.gsp-field .gsp-select[data-w="narrow"]{width:132px}
.gsp-field .gsp-textarea{min-height:44px}

/* dock clearance (UX round 2): the portal's floating agent dock sits bottom-
   right and covered the dialog's primary action — reserve its width so
   [ Save ] / [ Submit ] are never under it. */
.gsp-dialog .gsp-btnrow{padding-right:150px}
.gsp-statusbar{padding-right:150px}
.gsp-sheet > .gsp-card:last-child .gsp-card-body,
.gsp-matrix .gsp-mcol:last-child .gsp-pane-foot,
.gsp-wiz .gsp-wiz-col:last-child .gsp-mcol-body{padding-bottom:52px}

/* ------------------------------------------------------------------ */
/* Order Management additions (2026-08-22) — the second app in this    */
/* language. Semantic objects only, added to the shared skin so the    */
/* app itself stays a pointer: order documents, line grids with a      */
/* reference sub-row, typeahead pickers, notes, and the step strip.    */

/* a document dialog is wider than a record dialog: an order line grid
   carries product, qty, price, total and a decision on one row */
.gsp-dialog-wide{width:min(1180px,96vw)}

/* document editor (strategy deck documents, 2026-09-25): a near full-screen
   dialog, and a fixed-height host for the ONLYOFFICE DocsAPI frame. The
   Document Server sizes its UI from the container at start, so the host must
   have a real height before the editor mounts. */
.gsp-dialog-full{width:96vw;height:94vh;max-height:94vh}
.gsp-dialog-full .gsp-dialog-body{flex:1}
.gsp-docs-editor{height:calc(94vh - 72px);min-height:420px}
.gsp-pane-body .gsp-docs-editor{height:calc(100vh - 190px)}

/* three-across field row for the commercial terms blocks */
.gsp-field-row-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:2px 10px;padding:2px 0}
.gsp-field-row-4{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:2px 10px;padding:2px 0}
.gsp-field[data-span="true"]{grid-column:1 / -1}

/* inline note: why a step cannot go yet, or a fact the user must read */
.gsp-note{border:1px solid var(--ds-c-amber-23);background:var(--ds-c-yellow-19);color:var(--ds-c-yellow-26);padding:3px 6px;margin:3px}
.gsp-note[data-tone="stop"]{border-color:var(--ds-c-red-17);background:var(--ds-c-red-08);color:var(--ds-c-red-26);font-weight:700}
.gsp-note[data-tone="info"]{border-color:var(--ds-c-blue-21);background:var(--ds-c-blue-07);color:var(--ds-c-blue-32)}
.gsp-note-title{font-weight:700;margin-right:6px}

/* the order document: header facts over the line grid, inside a dialog */
.gsp-doc{display:flex;flex-direction:column;gap:3px;padding:3px}
.gsp-doc-strip{display:flex;flex-wrap:wrap;gap:6px;align-items:baseline;border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-yellow-05);padding:3px 6px}
.gsp-doc-strip-cell{display:flex;gap:5px;align-items:baseline;white-space:nowrap}
.gsp-doc-strip-l{font-size:10px;color:var(--ds-c-neutral-13);text-transform:uppercase;letter-spacing:.03em}
.gsp-doc-strip-v{font-weight:700}
/* the dealer detail block fills its row as a responsive key-value grid, label
   above value (RL29-5, 2026-09-29), while the order-facts strip stays unchanged */
.gsp-dealer-strip .gsp-doc-strip{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(140px,100%),1fr));gap:10px 16px;width:100%;box-sizing:border-box;margin:0;padding:8px 10px;align-items:start}
.gsp-dealer-strip .gsp-doc-strip-cell{min-width:0;display:flex;flex-direction:column;align-items:center;gap:3px;white-space:normal;text-align:center}
.gsp-dealer-strip .gsp-doc-strip-v{max-width:100%;overflow-wrap:anywhere}
.gsp-doc-note{border:1px solid var(--ds-c-yellow-20);background:var(--ds-c-yellow-07);padding:2px 6px;color:var(--ds-c-neutral-18)}

/* totals under a line grid — the money, right-aligned in its own panel the eye
   lands on: a bordered box, figures larger than the grid's, and the quote
   total (data-strong) set apart as the one figure that decides the quote
   (RL29-6: the one-line strip was too easy to miss) */
.gsp-totals{display:flex;justify-content:flex-end;gap:14px;align-items:baseline;border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-yellow-13);padding:6px 10px;flex-wrap:wrap}
.gsp-totals-item{display:flex;gap:6px;align-items:baseline;white-space:nowrap}
.gsp-totals-l{font-size:10.5px;color:var(--ds-c-neutral-13);text-transform:uppercase;letter-spacing:.03em}
.gsp-totals-v{font-size:13px;font-variant-numeric:tabular-nums}
.gsp-totals-item[data-strong="true"]{border-left:1px solid var(--ds-c-neutral-06);padding-left:14px}
.gsp-totals-item[data-strong="true"] .gsp-totals-l{color:var(--ds-c-blue-32);font-weight:700}
.gsp-totals-item[data-strong="true"] .gsp-totals-v{font-weight:700;font-size:18px;line-height:1.1;color:var(--ds-c-blue-32)}

/* line grid: the muted reference row under a line (floor, cost, margin) */
.gsp-grid tr[data-ref="true"] td{background:var(--ds-c-yellow-05);border-bottom:1px solid var(--ds-c-neutral-06);padding:1px 5px}
.gsp-grid tr[data-ref="true"]:hover td{background:var(--ds-c-yellow-05)}
.gsp-ref-item{display:inline-flex;gap:4px;align-items:baseline;margin-right:10px;font-size:10px}
.gsp-ref-l{color:var(--ds-c-neutral-10);text-transform:uppercase;letter-spacing:.03em}
.gsp-ref-v{font-variant-numeric:tabular-nums}
.gsp-ref-v[data-tone="bad"]{color:var(--ds-c-red-22);font-weight:700}
.gsp-ref-v[data-tone="warn"]{color:var(--ds-c-amber-28);font-weight:700}
.gsp-ref-v[data-tone="good"]{color:var(--ds-c-green-12)}
.gsp-line-code{display:block;font-size:9px;color:var(--ds-c-neutral-10);font-family:var(--font-mono)}
.gsp-line-note{font-size:10px;color:var(--ds-c-neutral-13)}
.gsp-line-note[data-tone="bad"]{color:var(--ds-c-red-22);font-weight:700}

/* typeahead picker — dealer and product, over a live SAP search */
.gsp-picker{position:relative;display:flex;flex-direction:column;gap:1px;min-width:0}
.gsp-picker-chosen{display:flex;gap:6px;align-items:baseline;border:1px solid var(--ds-c-blue-13);background:var(--ds-c-white-01);padding:1px 3px;min-width:0}
.gsp-picker-chosen-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gsp-picker-change{border:1px solid var(--hairline-dark);background:var(--paper-2);color:var(--ink);font-family:var(--ds-font-window);font-size:10px;padding:1px 6px;cursor:pointer;flex:none;border-radius:var(--ds-radius-sm)}
.gsp-picker-change:hover{background:var(--paper);border-color:var(--ink-mute)}
.gsp-picker-list{position:absolute;top:100%;left:0;right:0;z-index:30;max-height:220px;overflow:auto;border:1px solid var(--ds-c-blue-32);background:var(--ds-c-white-01);box-shadow:2px 2px 4px rgba(0,0,0,.35)}
/* Clip-safe variant (PickerResults, order-mgmt/steps/fields.tsx) -- fixed-position so the option list escapes any scrollable ancestor; .olp-table-scroll on the dealer portal's request grid clipped it to the grid's own edge, so the options could only be reached by scrolling the grid. Coordinates and the fitted height are handed over as --gpl-x/--gpl-y/--gpl-b/--gpl-w/--gpl-h, the same mechanism as .rsel-results--fixed and .ds-hover-preview's --hp-x/--hp-y. The -9999px fallbacks keep the list off-screen for the one frame before it is measured. */
.gsp-picker-list--fixed{position:fixed;z-index:10200;top:var(--gpl-y,-9999px);bottom:var(--gpl-b,auto);left:var(--gpl-x,-9999px);right:auto;width:var(--gpl-w,auto);max-height:var(--gpl-h,220px)}
/* Stage/status tooltips reuse .gsp-picker-list, whose left:0/right:0 pins the
   panel to its TRIGGER's width. That is right for a dropdown, wrong for a
   tooltip: the "New request" brief is 569px of text in a 127px chip, so it
   rendered with a 444px horizontal scrollbar (redline RL-605, confirmed live
   2026-10-03). A tooltip answers to its content, not its anchor. */
.gsp-picker-list[role="tooltip"]{right:auto;width:max-content;min-width:12rem;max-width:min(32rem,calc(100vw - 2rem));overflow-x:hidden;overflow-y:auto;white-space:normal}
.gsp-picker-option{display:block;width:100%;text-align:left;font:inherit;border:0;border-bottom:1px dotted var(--ds-c-yellow-20);background:var(--ds-c-white-01);padding:2px 5px;cursor:pointer}
.gsp-picker-option:hover,.gsp-picker-option[aria-selected="true"]{background:var(--ds-c-blue-21);color:var(--ds-c-white-01)}
.gsp-picker-option-meta{display:block;font-size:10px;color:var(--ds-c-neutral-10)}
.gsp-picker-option:hover .gsp-picker-option-meta,.gsp-picker-option[aria-selected="true"] .gsp-picker-option-meta{color:var(--ds-c-blue-05)}
.gsp-picker-note{font-size:10px;color:var(--ds-c-neutral-10)}
.gsp-picker-note[data-tone="bad"]{color:var(--ds-c-red-22)}
.gsp-input[data-attention="true"],.gsp-select[data-attention="true"]{border-color:var(--ds-c-red-17);background:var(--ds-c-white-03)}

/* step strip: where the order stands in its own process. One horizontal
   track of points with the step's name under each point — filled and ticked
   behind the order, ringed at the live step, outlined ahead of it, and the
   line filled up to where the order is. The track is sized to its own labels
   and .gsp-steps scrolls it sideways, so a narrow window keeps it on one
   line instead of wrapping it into a block of pills (RL29-3). The markup is
   the design system's own ds-step-flow track; only the drawing is set here. */
.gsp-steps{display:block;overflow-x:auto;overflow-y:hidden;padding:2px 3px}
.gsp-steps .ds-step-flow-track{width:max-content;min-width:100%;justify-content:space-between;padding:0 6px}
.gsp-steps .ds-step-flow-item{flex:0 1 auto;min-width:0}
.gsp-steps .ds-step-flow-dot{display:flex;align-items:center;justify-content:center;font-size:9px;line-height:1;background:var(--paper);border-color:var(--hairline)}
.gsp-steps .ds-step-flow-dot--done{background:var(--ink);border-color:var(--ink);color:var(--paper)}
.gsp-steps .ds-step-flow-dot--current{background:var(--paper);border:2px solid var(--ink);box-shadow:none}
.gsp-steps .ds-step-flow-connector{background:var(--hairline)}
.gsp-steps .ds-step-flow-item[data-state="done"] .ds-step-flow-connector,
.gsp-steps .ds-step-flow-item[data-state="now"] .ds-step-flow-connector{background:var(--ink)}
.gsp-steps .ds-step-flow-label{max-width:none;font-family:var(--font-ui);font-size:10px;text-transform:none;letter-spacing:0;color:var(--ink-mute)}
.gsp-steps .ds-step-flow-label--current{color:var(--ink);font-weight:600}

/* terms box + tick — the dealer's explicit act before an order binds */
.gsp-terms{border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-white-01);margin:3px;padding:3px 6px}
.gsp-terms-title{font-weight:700;color:var(--ds-c-blue-32)}
.gsp-terms-text{max-height:120px;overflow:auto;border:1px inset var(--ds-c-amber-11);background:var(--ds-c-yellow-07);padding:3px 5px;margin:2px 0;white-space:pre-wrap}
.gsp-tick{display:flex;gap:5px;align-items:baseline}

/* dealer portal catalogue: dense card list, not a tile wall */
.gsp-cat{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:3px;padding:3px}
.gsp-cat-item{border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-white-01);padding:3px 6px;display:flex;flex-direction:column;gap:1px;text-align:left;font:inherit;cursor:pointer}
.gsp-cat-item:hover{background:var(--ds-c-yellow-09)}
.gsp-cat-name{font-weight:700}
.gsp-cat-meta{font-size:10px;color:var(--ds-c-neutral-10)}
.gsp-cat-price{font-variant-numeric:tabular-nums;color:var(--ds-c-blue-32);font-weight:700}

/* Gaps found while the order screens were being built (2026-08-22): a cell
   that carries more than one status chip, and a sortable header that must
   show which way it is sorted. Both were being worked around in app code,
   which is exactly what this layer exists to prevent. */
.gsp-chips{display:inline-flex;gap:3px;align-items:baseline;flex-wrap:wrap}
/* remove control inside an editable chip (strategy leaders, 2026-09-25) */
.gsp-chip-remove{border:0;background:none;color:inherit;font:inherit;padding:0 0 0 3px;margin:0;cursor:pointer;line-height:1}
.gsp-chip-remove:hover,.gsp-chip-remove:focus-visible{color:var(--ds-c-red-26)}
.gsp-grid th[data-sort]{padding-right:14px;position:relative}
.gsp-grid th[data-sort="asc"]::after{content:"\25B2";position:absolute;right:4px;font-size:8px;color:var(--ds-c-blue-32)}
.gsp-grid th[data-sort="desc"]::after{content:"\25BC";position:absolute;right:4px;font-size:8px;color:var(--ds-c-blue-32)}
/* a sub-line inside a tight cell: the ellipsis lives on the line, not the cell */
.gsp-cell-sub{display:block;font-size:10px;color:var(--ds-c-neutral-10);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* Procurement2 floating desktop (Ben 2026-08-22: "every main-menu
   destination opens as a WINDOW... several stay open at once... resizable,
   minimizable, repositionable"). DEAD as of 2026-08-30 (Ben: "turn these
   into tabs... we abandon the always floating windows") -- procurement2's
   top-level screens are `.gsp-tabpane` tabs now (see pxp.tsx), never this
   `.gsp-app--floating`/`.gsp-desktop-layer` chrome, and nothing in src/
   renders these classes any more. Left in place rather than deleted
   (no-deletion-of-working-code default) but not consumed by anything.
   CORRECTION 2026-08-31: this comment used to claim "the shell's generic
   ds-window chrome never built minimize/maximize" as the reason these
   classes existed -- WindowChrome.tsx now DOES carry minimize + maximize
   itself (every window it renders, docked to the whole work area), so that
   claim would be actively wrong left as written. */
.gsp-desktop-layer{position:fixed;inset:0;z-index:45;pointer-events:none}
.gsp-app--floating{position:fixed;left:var(--win-x,80px);top:var(--win-y,80px);width:var(--win-w,960px);height:var(--win-h,620px);z-index:var(--win-z,45);pointer-events:auto;box-shadow:2px 2px 10px rgba(0,0,0,.35)}
.gsp-app--floating.gsp-app--minimized{display:none}
.gsp-app--floating .gsp-window{height:100%}
.gsp-titlebar[data-draggable="true"]{cursor:move;user-select:none}
/* resize grip, bottom-right corner of a floating window only */
.gsp-window-resize{position:absolute;right:0;bottom:0;width:14px;height:14px;cursor:nwse-resize;background:repeating-linear-gradient(135deg,var(--ds-c-neutral-06) 0,var(--ds-c-neutral-06) 1px,transparent 1px,transparent 4px)}

/* taskbar -- always visible while inside the procurement2 app, real XP
   taskbar language (dark gradient bar, pressed-in look for the active
   window's chip). Chips restore a minimized window or bring one to front;
   Settings lives at the right end, same place a systray sits.

   CORRECTION 2026-08-22 (real root cause of "Settings never opens", found
   via a real Playwright trace, not guesswork): the shell's own Yarnball/
   CoFlow dock (.cowork-dock, globals.css) is `position:fixed; top:0; right:0;
   bottom:0` -- FULL VIEWPORT HEIGHT -- with `pointer-events:auto` and
   z-index:60, EVEN WHILE COLLAPSED (AgentDock.tsx COLLAPSED_W = 40px, never
   0). Because this taskbar was flush against the same right edge
   (`right:0`), its rightmost element (Settings) sat physically UNDER that
   permanent 40px strip: every real click -- even a Playwright forced click
   that bypasses the actionability check -- was delivered to the dock
   overlay, not the button underneath it. The taskbar chips' own overflow
   scrolling (below) never running off-screen was a red herring; the button
   was on-screen and "clickable" by inspection, just permanently covered.
   Mirrors the existing `.shell > .body { margin-right: var(--cowork-dock-w,
   0px); }` pattern (globals.css) so this taskbar keeps clear of the same
   reserved strip whether the dock is collapsed or expanded. */
.gsp-taskbar{position:fixed;left:0;right:var(--cowork-dock-w,0px);bottom:0;z-index:46;pointer-events:auto;display:flex;align-items:center;gap:3px;padding:3px 6px;background:linear-gradient(180deg,var(--ds-c-blue-20) 0%,var(--ds-c-blue-26) 50%,var(--ds-c-blue-28) 100%);border-top:1px solid var(--ds-c-blue-32);font-family:var(--font-ui);font-size:11px}
/* Chips scroll horizontally inside their own strip -- as MORE windows open,
   the row never pushes Settings (or later chips) past the viewport edge the
   way an unconstrained nowrap flex row did (confirmed live with 4 windows
   open: Settings ran off-screen). Settings itself stays a fixed, never-
   shrinking, always-reachable element outside the scroll area, same as a
   real OS taskbar's system tray never scrolling away with running apps. */
.gsp-taskbar-chips{display:flex;gap:3px;overflow-x:auto;flex:1;min-width:0;scrollbar-width:thin}
.gsp-taskbar-chip{font:inherit;color:var(--ds-c-white-01);background:linear-gradient(180deg,var(--ds-c-blue-15) 0%,var(--ds-c-blue-23) 100%);border:1px solid var(--ds-c-blue-32);border-radius:var(--ds-radius-sm);padding:2px 10px;cursor:pointer;max-width:220px;flex:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gsp-taskbar-chip:hover{background:linear-gradient(180deg,var(--ds-c-blue-12) 0%,var(--ds-c-blue-19) 100%)}
.gsp-taskbar-chip[data-active="true"]{background:linear-gradient(180deg,var(--ds-c-blue-27) 0%,var(--ds-c-blue-28) 100%);box-shadow:inset 1px 1px 2px rgba(0,0,0,.5)}
.gsp-taskbar-settings{font:inherit;color:var(--ds-c-white-01);background:linear-gradient(180deg,var(--ds-c-blue-15) 0%,var(--ds-c-blue-23) 100%);border:1px solid var(--ds-c-blue-32);border-radius:2px;padding:2px 12px;cursor:pointer;flex:none;margin-left:3px}
.gsp-taskbar-settings:hover{background:linear-gradient(180deg,var(--ds-c-blue-12) 0%,var(--ds-c-blue-19) 100%)}

/* App-level screen switcher, TOP bar (Ben 2026-08-22, explicit: "why would
   every page open a new popup with the whole main navigation" -- the
   eleven-screen menu used to render inside every open window, once per
   window; three windows open drew it three times -- THEN, on layout: "the
   main navigation must always stay at the top, not in the popups... put the
   main navigation at the top left to open a new item or create a new
   transaction... put Purchase or Master Data on the right"). One persistent
   bar, never inside a window: "New" trigger + flyout at top-left, direct
   quick-links to the highest-frequency browse destinations at top-right.
   z-index sits ABOVE the WindowManager's own z-order (WINDOW_Z_BASE=100,
   incrementing per focus) -- unlike .gsp-taskbar below (z-index 46, already
   under every floating window), this bar carries Ben's literal "must always
   stay at the top" requirement, so it is pinned above normal window
   stacking instead of sharing the taskbar's tier. */
.gsp-topbar{position:fixed;left:0;right:var(--cowork-dock-w,0px);top:0;z-index:200;pointer-events:auto;display:flex;align-items:center;justify-content:space-between;gap:6px;padding:3px 6px;background:linear-gradient(180deg,var(--ds-c-blue-20) 0%,var(--ds-c-blue-26) 50%,var(--ds-c-blue-28) 100%);border-bottom:1px solid var(--ds-c-blue-32);font-family:var(--font-ui);font-size:11px}
.gsp-topbar-left,.gsp-topbar-right{display:flex;align-items:center;gap:4px;min-width:0}
.gsp-topbar-new{font-family:var(--ds-font-window);font-weight:600;color:var(--paper);background:var(--baobab);border:1px solid var(--baobab);border-radius:var(--ds-radius-sm);padding:4px 14px;cursor:pointer;flex:none;box-shadow:inset 0 -1px 0 rgba(0,0,0,.18)}
.gsp-topbar-new:hover{background:color-mix(in srgb, var(--baobab) 88%, black)}
.gsp-topbar-new[data-open="true"]{background:color-mix(in srgb, var(--baobab) 80%, black);box-shadow:inset 0 1px 3px rgba(0,0,0,.35)}
.gsp-topbar-link{font-family:var(--ds-font-window);color:var(--paper);background:rgba(255,255,255,.16);border:1px solid rgba(255,255,255,.32);border-radius:var(--ds-radius-sm);padding:4px 10px;cursor:pointer;flex:none;white-space:nowrap}
.gsp-topbar-link:hover{background:rgba(255,255,255,.28)}
/* Flyout hangs below the top-left New button; the transparent full-viewport
   catcher behind it closes the menu on any outside click -- catcher's
   z-index sits below the flyout's so clicks inside the flyout itself are
   unaffected, and above .gsp-topbar so it also catches a click back onto
   the New button itself (closing, not re-toggling open, on that click). */
.gsp-startmenu-catcher{position:fixed;inset:0;z-index:200;background:transparent;pointer-events:auto}
.gsp-startmenu{position:fixed;left:6px;top:28px;z-index:210;background:var(--ds-c-yellow-13);border:1px solid var(--ds-c-blue-32);box-shadow:2px 2px 6px rgba(0,0,0,.45);display:flex;flex-direction:column;padding:2px;min-width:230px;max-height:80vh;overflow-y:auto;pointer-events:auto}
/* Section headers + dividers group the flyout (Ben: "Agreements and
   supplier admin should be in separate places") -- PROC_MENU_SECTIONS in
   nav.ts is the grouping; these two classes are just its visual expression. */
.gsp-startmenu-section{padding:3px 8px 1px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--ds-c-neutral-12)}
.gsp-startmenu-divider{border-top:1px solid var(--ds-c-yellow-23);margin:2px 4px}

/* Classic expanding menus in the menu bar (OmMenu): the trigger reads
   "Name  Value ▾"; the panel is a paper sheet that drops under it. Master
   Data's global Domain / Data type scope lives in these (MMDB-2407). */
.gsp-menu-drop{position:relative;display:inline-flex;flex:none}
.gsp-menu-drop>.gsp-menu{display:inline-flex;align-items:center;gap:5px;border:0;background:transparent;font:inherit}
.gsp-menu-name{font-weight:700}
.gsp-menu-value{color:inherit;opacity:.85;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.gsp-menu-caret{font-size:9px;opacity:.75}
.gsp-menu-panel{position:absolute;left:0;top:100%;z-index:60;min-width:190px;max-height:60vh;overflow:auto;background:var(--ds-c-white-01);border:1px solid var(--ds-c-neutral-06);box-shadow:2px 2px 0 var(--ds-c-yellow-25);padding:2px;display:flex;flex-direction:column}
/* R5-PEOPLE, 2026-09-28: a trigger docked at the right edge of its row (e.g.
   RecordBar's "More" overflow, which is always the rightmost element per its
   own design intent) opens this panel left-anchored off the viewport's right
   edge at common widths (confirmed 1280px: panel right edge landed ~92px past
   window.innerWidth, clipped by the shell's overflow-x:hidden, unreachable by
   a real pointer even though the DOM node still exists). This modifier flips
   the anchor so a right-docked trigger's panel grows leftward instead. */
.gsp-menu-panel[data-align="end"]{left:auto;right:0}
.gsp-menu-item{display:flex;align-items:center;gap:6px;text-align:left;border:0;background:transparent;font:inherit;padding:3px 10px 3px 6px;cursor:pointer;white-space:nowrap;color:var(--ds-c-black-02)}
.gsp-menu-item:hover,.gsp-menu-item:focus-visible{background:var(--ds-c-blue-21);color:var(--ds-c-white-01);outline:none}
.gsp-menu-item[data-on="true"]{font-weight:700}
.gsp-menu-item:disabled{color:var(--ds-c-neutral-06);cursor:default;background:transparent}
.gsp-menu-item-mark{display:inline-block;width:10px;text-align:center;font-size:10px}
.gsp-menubar-sep{width:1px;align-self:stretch;background:var(--ds-c-yellow-25);margin:1px 4px}
/* The app's scope group (what you are working on) sits in its own sunken
   frame at the head of the bar, apart from the screen entries that follow. */
.gsp-menubar-scope{display:inline-flex;align-items:center;gap:2px;flex:none;padding:0 3px;margin:0 2px 0 0;background:var(--ds-c-yellow-06);border:1px solid var(--ds-c-yellow-25);box-shadow:inset 1px 1px 0 var(--ds-c-white-01)}
.gsp-menubar-scope>.gsp-menu-drop+.gsp-menu-drop{border-left:1px solid var(--ds-c-yellow-21);padding-left:2px}


/* Controls in this structural layer that painted a box but never declared a
   radius, so they rendered square while the rest of the portal moved to the
   locked 4px. Found by measuring computed style on Procurement, Order
   Management and Strategy signed-in. These are definitions, not overrides:
   none of these rules set a radius anywhere. */
.gsp-tool,
.gsp-select,
.gsp-taskbar-settings { border-radius: var(--ds-radius-sm); }

/* Screen tabs (Ben, 2026-08-30 hand-annotation: "turn these into tabs",
   "launch as tabs only, we abandon the always floating windows", "max as
   per disply/window"). A `kind: "screen"` window (windows.tsx) no longer
   floats -- exactly one is ever current, filling the whole work area with
   no computed geometry. `data-eid="om-desktop"` names the OmAppFrame work
   area (order-mgmt/_lib/windows.tsx) -- the ONE component every consumer of
   it renders (Order Management itself, Master Data, the Dealer Portal
   popup, and Strategy's own tabbed desktop, which reuses the identical
   OmAppFrame under its `.slp` skin via a `wrapperClassName` prop rather
   than duplicating this file). `data-eid="proc-desktop"` names the
   equivalent work area in procurement2's OWN separate desktop
   (ProcDesktop.tsx / pxp.tsx), which does not use OmAppFrame at all but
   needed the identical CSS-only override. Both selectors are scoped
   tightly enough to leave the base `.gsp-matrix` rule above alone for its
   other, unrelated consumers -- Strategy's own Why-What-How matrix
   (MatrixSurface, a `.gsp-matrix` element rendered INSIDE one of its tab
   panes, carrying neither eid) chief among them. A record popup (kind:
   "record") still floats over either desktop exactly as before --
   position:fixed is set on its own node by OmWindowFrame, unaffected by
   the desktop's own display mode. */
.gsp-matrix[data-eid="om-desktop"],
.gsp-matrix[data-eid="proc-desktop"] { display: block; grid-template-columns: none; }
.gsp-tabpane{position:absolute;inset:0;display:none;flex-direction:column;min-height:0;min-width:0}
.gsp-tabpane[data-current="true"]{display:flex}

/* Record tabs (Ben, 2026-08-31: "we have generally abandoned the always
   popup design, make it tab that can be disconnected and turned into
   windows, for all pages/apps"). A record popup (order-mgmt windows.tsx
   `kind: "record"`, procurement2's own local record registry) now opens
   DOCKED by default: a tab in the SAME strip as the screens, visually
   distinct from a screen tab because it carries its own reference text
   PLUS an inline close × (a screen tab is never closeable). `.gsp-menu`
   supplies the base tab look; `.gsp-menu-record` only adjusts the padding
   to make room for the close button sitting inside it. `data-active` reuses
   the existing `.gsp-menu[data-active="true"]` rule above -- one active
   look for every tab, screen or record. */
.gsp-menu-record{display:inline-flex;align-items:center;gap:2px;padding:1px 3px 1px 2px}
.gsp-menu-record-label{font:inherit;color:inherit;background:transparent;border:0;padding:2px 6px;cursor:pointer}
.gsp-menu-close{font:inherit;display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:0;background:transparent;color:inherit;opacity:.7;cursor:pointer;border-radius:var(--ds-radius-sm);flex:none}
.gsp-menu-close:hover{opacity:1;background:rgba(0,0,0,.15)}
.gsp-menu-close svg{display:block;width:9px;height:9px}
.gsp-menu-record[data-active="true"] .gsp-menu-close:hover{background:rgba(255,255,255,.25)}

/* Compact uploaded-evidence document list (e.g. a supplier's own bid
   attachments): file name, size, download link, one row each. Reuses
   existing border/ink/link tokens, no new colour (promoted from
   supplier-xp.css 2026-09-10). */
.gsp-doc-list{list-style:none;margin:4px 6px;padding:0;display:flex;flex-direction:column;gap:2px}
.gsp-doc-item{display:flex;align-items:center;gap:8px;padding:2px 4px;border:1px solid var(--ds-c-neutral-06);background:var(--ds-c-white-01);color:var(--ds-c-neutral-18)}
.gsp-doc-item a{color:var(--ds-c-blue-32)}
/* Portalled overlay (FloatingLayer, order-mgmt/_lib/floatingLayer.tsx).
   Portal geometry only: position/z-index/top/bottom/left/right. Width,
   min-width, max-height, overflow and background stay on the consumer
   class (.gsp-picker-list / .gsp-menu-panel) so this later rule cannot
   clobber shrink-wrap menus. Pickers opt into matching the anchor via
   [data-stretch="anchor"]. [data-min-w] applies --gpl-min-w only when
   the JS set the var. [data-align=right] clamps right at 0px; JS also
   drops data-align and pins --gpl-x when the used box is still off the
   left edge. This block does not edit the existing .gsp-picker-list /
   .gsp-menu-panel rules. The -9999px fallbacks keep the layer
   off-screen for the one frame before it is measured. Later in this
   file than those classes, so position:fixed and z-index win when both
   class names share the node. */
.gsp-floating-layer{position:fixed;z-index:10200;top:var(--gpl-y,-9999px);bottom:var(--gpl-b,auto);left:var(--gpl-x,-9999px);right:auto}
.gsp-floating-layer[data-stretch="anchor"]{width:var(--gpl-w)}
.gsp-floating-layer[data-min-w]{min-width:var(--gpl-min-w)}
.gsp-floating-layer[data-align="right"]{left:auto;right:max(0px,calc(100% - var(--gpl-x,0px) - var(--gpl-w,0px)))}

/* Portalled overlay origin-theme parity (MMD-108 / WP-S-01). The layer is a
   child of <body> now (the A1 contract), so it is outside the `.olp` / `.slp`
   theme subtree and the ancestor-scoped picker chrome in the letterpress
   skins (`.olp .gsp-picker-option`, `.slp .gsp-picker-option`, ...) stops
   matching. Two things would then change for the consumers that are already
   migrated on main: the inherited type scale (`.gsp-picker-option` and
   `.gsp-menu-item` use `font:inherit`, so the theme root's font-size IS the
   option/menu box geometry -- without this block a panel grows ~25% the
   moment the primitive portals it to the body) and the picker ink. The ticket
   forbids the primitive changing any consumer's appearance, so FloatingLayer
   stamps its origin theme root on the node as `data-theme` and this block
   restores exactly that ancestor chrome for the layer and its descendants.
   The values are the letterpress skins' own declarations and tokens (the
   `.olp` picker shadow is the same --shadow-dialog the `.slp` rule already
   names); no .gsp-picker-list / .gsp-menu-panel rule itself is edited. A
   layer portalled out of a non-theme context carries no data-theme and keeps
   body's own type and ink, exactly as it inherited them before. */
.gsp-floating-layer[data-theme="olp"]{
  --olp-paper:var(--rp-white);
  --olp-paper-2:var(--rp-silver-2);
  --olp-paper-3:var(--rp-silver);
  --olp-hairline:var(--rp-line);
  --olp-hairline-dark:var(--rp-border-strong);
  --olp-ink:var(--rp-ink);
  --olp-ink-mute:var(--rp-ink-mute);
  /* The two skins spell the same on-fill ink differently (letterpress-order-mgmt
     uses this literal, letterpress-strategy uses --ds-c-white-01-a85), so each
     theme's rule below references its own spelling and a computed-style diff of
     the twin against the portalled panel is empty in both. */
  --gpl-ink-on-fill:rgba(255, 255, 255, 0.85);
  font-family:var(--font-ui,"PP Neue Machina","Segoe UI",sans-serif);
  font-size:12px;
  color:var(--olp-ink);
}
.gsp-floating-layer[data-theme="slp"]{
  --slp-paper:var(--rp-white);
  --slp-paper-2:var(--rp-silver-2);
  --slp-paper-3:var(--rp-silver);
  --slp-hairline:var(--rp-line);
  --slp-hairline-dark:var(--rp-border-strong);
  --slp-ink:var(--rp-ink);
  --slp-ink-mute:var(--rp-ink-mute);
  --slp-acc:var(--rp-black);
  font-family:var(--font-ui,"PP Neue Machina","Segoe UI",sans-serif);
  font-size:12px;
  color:var(--slp-ink);
}
.gsp-floating-layer[data-theme="olp"].gsp-picker-list{border:1px solid var(--olp-ink);background:var(--olp-paper);box-shadow:var(--shadow-dialog)}
.gsp-floating-layer[data-theme="slp"].gsp-picker-list{border:1px solid var(--slp-ink);background:var(--slp-paper);box-shadow:var(--shadow-dialog)}
.gsp-floating-layer[data-theme="olp"] .gsp-picker-option{background:var(--olp-paper);border-bottom:1px dotted var(--olp-hairline);color:var(--olp-ink)}
.gsp-floating-layer[data-theme="slp"] .gsp-picker-option{background:var(--slp-paper);border-bottom:1px dotted var(--slp-hairline);color:var(--slp-ink)}
.gsp-floating-layer[data-theme="olp"] .gsp-picker-option:hover,.gsp-floating-layer[data-theme="olp"] .gsp-picker-option[aria-selected="true"]{background:var(--rp-black);color:var(--rp-white)}
.gsp-floating-layer[data-theme="slp"] .gsp-picker-option:hover,.gsp-floating-layer[data-theme="slp"] .gsp-picker-option[aria-selected="true"]{background:var(--ds-c-black-02);color:var(--ds-c-white-01)}
.gsp-floating-layer[data-theme="olp"] .gsp-picker-option-meta{color:var(--olp-ink-mute)}
.gsp-floating-layer[data-theme="slp"] .gsp-picker-option-meta{color:var(--slp-ink-mute)}
.gsp-floating-layer[data-theme="olp"] .gsp-picker-option:hover .gsp-picker-option-meta,.gsp-floating-layer[data-theme="olp"] .gsp-picker-option[aria-selected="true"] .gsp-picker-option-meta{color:var(--gpl-ink-on-fill)}
.gsp-floating-layer[data-theme="slp"] .gsp-picker-option:hover .gsp-picker-option-meta,.gsp-floating-layer[data-theme="slp"] .gsp-picker-option[aria-selected="true"] .gsp-picker-option-meta{color:var(--ds-c-white-01-a85)}
.gsp-floating-layer[data-theme="olp"] .gsp-picker-note{color:var(--olp-ink-mute)}
.gsp-floating-layer[data-theme="slp"] .gsp-picker-note{color:var(--slp-ink-mute)}

/* OMS freshness banner (WP-S-11): one sentence, no narration. Fresh and empty
   render nothing in the component; this object is the line for stale/warming
   and the wrap around the existing .gsp-noplan failure box. */
.gsp-freshness-banner{display:flex;align-items:baseline;flex-wrap:wrap;gap:6px;padding:2px 6px;margin:2px 0;font-size:11px;line-height:1.3}
.gsp-freshness-banner[data-freshness-state="stale"]{border:1px solid var(--ds-c-amber-23);background:var(--ds-c-yellow-19);color:var(--ds-c-yellow-26)}
.gsp-freshness-banner[data-freshness-state="warming"]{color:var(--ds-c-neutral-13);padding:2px 0}
.gsp-freshness-banner[data-freshness-state="failed"]{flex-direction:column;align-items:stretch;padding:0;margin:0;gap:4px}
