/* THE SUITE STYLESHEET. Every screen in the product is styled from here.
 *
 * It lived inline in public/index.html until 2026-09-06, where it was 424kB of the file's 480kB. That file
 * carries the ?v= cache-busting tokens for everything else, so it can never be cached itself — which meant
 * this stylesheet was re-sent and re-parsed on EVERY page load and every refresh, while the per-tab
 * stylesheets beside it were being served immutable and fetched once ever. Measured on live before the move:
 * index.html 480kB raw / 131kB on the wire, Cache-Control: no-cache. After: 56kB.
 *
 * IT IS LOADED IN THE POSITION THE <style> BLOCK OCCUPIED — first, before chat.css/omf.css/call.css/
 * content.css and the rest — because that order is load-bearing. This file states the base; a tab's own
 * sheet overrides it. Move the <link> and you change which rule wins, silently, with no test able to see it
 * (jsdom has no cascade). The one url() in here is absolute, /fonts/cormorant.woff2, so it resolves the
 * same from a stylesheet as it did from the page.
 *
 * The global rules with no scope — input{margin-bottom:16px} and .who{display:flex} among them — are the
 * ones CLAUDE.md warns about. They are unchanged by the move and still bite; test/global-element-rules.test.cjs
 * and test/css-duplicate-selectors.test.cjs read THIS FILE now, not index.html.
 */
  :root{
    /* the highlighter pen colours are NOT here — they live at :root in chat.css, beside the rules that use
       them, so the contrast gate (which injects chat.css alone) can measure them. See the note there. */
    /* HOW TALL A BOX YOU TYPE PROSE INTO IS ALLOWED TO GET — the one number, for the whole suite (owner
       2026-08-26: "when writing a long message the text box need to expand a little bit more on all chats …
       ensure this is the case for all chat boxes and job description or any text tab on the entire suite").
       Before this there was no shared answer at all: no bare `textarea{}` rule exists anywhere, so all ~60
       multi-line boxes were sized one at a time and drifted into ELEVEN different ceilings (120/126/140/150/
       160/170/180/220px, plus one at twelve lines) and `rows=` values of 1,2,3,4,5,6,8,9. The chat composer
       showed six lines of a seventeen-line message; the design brief showed four of eighteen and never grew
       at all.

       USE IT AS:  max-height: min(calc(<this box's own line-height>em * var(--ta-lines)), var(--ta-vh));

       The line-height stays LOCAL because boxes legitimately differ (1.45 / 1.5 / 1.55 / 1.65) — only the
       COUNT is shared, which is the part that was missing. --ta-vh is the guard for a short window: twelve
       lines is ~260px, so it only bites below roughly a 580px-tall viewport, i.e. a phone, where a box that
       ate half the screen would be worse than one that scrolls.

       This is deliberately NOT a bare `textarea{}` rule. `input{margin-bottom:16px}` (line ~93 below) is the
       standing proof of what an unscoped element rule does in this file — it has bitten five separate
       controls across chat and the routine. Each box opts in inside its own scope. */
    --ta-lines:12;
    --ta-vh:45vh;
    /* THE REPLY BUBBLE on a tab-homed channel row — the size, once, for all four rails that draw it.
       Its MARKUP is chat.js's single replyDotHtml(), but the PAINT cannot be: chat.css lives inside
       @scope (.wc-root) and cannot reach the Future Knights, Creatives or Online Orders rails, so each
       rail repaints it in its own palette. That is four copies of the same two numbers — they were all
       20×22 with a 13px glyph, and four copies of a number is how a number starts drifting.
       The COLOURS stay local on purpose: each rail's fill has to work on its own background, and one of
       them (Online Orders' lime) cannot carry white ink at all — see the note in omf.css. */
    --rd-h:22px; --rd-w:24px; --rd-ic:16px;
    --foot-h:26px; /* suite footer height — every full-height tab calc subtracts it so content never touches the bottom edge */
    --topbar-h:52px; /* top nav height — full-screen overlays (FK drawer, annotate stage) start below it so the nav + back/forward arrows stay reachable. Mission Rail v2: the tabs left the bar, so it slimmed 62→52. This is the ONE source of truth — every tab's viewport calc references it rather than repeating a number. */
    --rail-w:56px;   /* the app rail (Mission Rail v2) — tab-level destinations, left of #view. Overlays that deliberately start below the top bar so the nav stays reachable start right of the rail for the same reason. */
    /* ONE nav width and ONE content gutter for every tab (owner 2026-08-13: "all key components to be same as
       Future Knights"). Measured before this existed, the four tabs ran 222 / 194 / 202 / 218 wide and put
       their own name at four different x positions, so the one element every tab has moved every time you
       switched. These carry Future Knights' values, so adopting them changes nothing there and everything
       elsewhere. A tab that is drag-resizable still overrides its own width at runtime; this is the width it
       starts from and returns to on a double-click reset. */
    --tab-navw:224px;
    --tab-gut:20px;
    /* …but ONLY while the rail IS down the left. With the apps moved to the top bar the rail is not there, and
       an overlay inset by its width left a live, unscrimmed strip beside the open drawer — the FK nav panel
       stayed clickable through it. Every such layer insets by THIS, never by --rail-w directly. */
    --rail-inset:var(--rail-w);
    --bg:#15171f; --panel:#1c1f2b; --panel2:#222633; --line:#2c3140;
    --text:#cbd0dc; --dim:#8b93a7; --white:#fff;
    --accent:#00b8d9; --accent2:#e91e8c; --warn:#f5b914; --danger:#ff6b6b; --ok:#0ca678;  /* --accent2 = logo mark ONLY; 3.6:1, never use as text/fill */
    --on-accent:#04222a;          /* text/marks on an accent fill (was hard-coded inline) */
    /* …and its twin for a STAGE fill (the chosen cell of a segmented control). The stage hues are pastels
       on the dark board and a DEEP set on the three light themes, so one literal ink cannot serve both:
       #0A0C11 measured 2.70–3.59:1 on the deep set, which made the route you had just chosen the least
       readable cell on the page. Overridden with the palette, in the same blocks. */
    --on-stage:#0A0C11;
    --faint:#5b6273; --panel3:#2a2f3d; --line2:rgba(255,255,255,.14); --accent-soft:rgba(0,184,217,.14); /* mockup palette (job-page-staged): faint labels, raised chips, brighter hairline, accent tint */
    --danger-badge:#d92d39;       /* still red, for things that are actually BAD — low stock, failures (4.79:1 on white) */
    /* Unread COUNTS are not warnings (owner 2026-08-14: "make the colour to be blue of the notification
       circles rather than red"). Red said "something is wrong" about four colleagues saying hello. Blue at
       5.17:1 with white — better than the #C9252D it replaces (5.55) and far better than the --accent cyan
       these were nearly set in, which is 2.37 and fails AA outright. */
    --count-badge:#2563eb;
    --tab-accent:var(--accent);   /* per-tab signature hue — set on <body> by selectTab() */
    --btn-disabled-op:.45;        /* one disabled affordance for all buttons */
    --pad-1:8px; --pad-2:16px; --pad-3:24px;  /* spacing scale — shared content insets */
    --r-sm:8px; --r-md:12px; --r-lg:16px;     /* radius scale — controls / panels / overlays */
    --r-input:8px; --r-pill:999px;            /* control radius + full pill (alias/extend the radius scale) */
    --lh-base:1.5; --lh-tight:1.3;            /* readable body rhythm; tight for headings + table cells */
    --fs-micro:11px; --fs-xs:12px; --fs-sm:13px; --fs-base:14px; --fs-md:15px; --fs-lg:17px; --fs-xl:20px; --fs-display:25px; /* type scale (migrate hardcoded sizes onto these) */
    --focus-ring:2px solid var(--tab-accent); --focus-shadow:0 0 0 4px color-mix(in srgb,var(--tab-accent) 28%,transparent); /* keyboard focus, tied to the active-tab accent */
    /* One scale for the whole suite (owner G1 #10, 2026-08-12: "Team hub is the ideal, all other tabs we
       want to replace"). This was 1.1 while Team Hub cancelled it back down with its own zoom:.9 — so chat
       rendered at .99 and every other tab at 1.1, and the SAME css px produced two different sizes. 0.99 is
       exactly what Team Hub already rendered at, so Team Hub is unchanged and everything else meets it. */
    --app-zoom:0.99;
    /* the suite's one interface face. Every tab reads THIS rather than declaring its own stack. */
    --ui-font:'Geist','SF Pro Text',-apple-system,BlinkMacSystemFont,'Segoe UI Variable','Segoe UI',system-ui,sans-serif;
  }
  *{box-sizing:border-box}
  /* No image may be wider than what holds it. Every media rule in this suite is per-component, so anything
     arriving by a route nobody styled — a pasted screenshot in a contenteditable, an <img> from a future
     feature — used to render at its natural size, overflow its panel and scroll the whole page sideways.
     One paste took the Creatives project page apart that way (2026-07-20). This is the floor under all of it.
     Components that genuinely need to exceed their box (the lightbox) set their own max-width and win on
     specificity. `height:auto` keeps a clamped image in proportion instead of squashing it. */
  img,video,canvas,svg,iframe{max-width:100%}
  img,video{height:auto}
  /* whole-app 10% zoom — makes everything ~10% bigger. The full-height containers below use calc(100vh/1.1)
     so that, once zoomed, they still fill exactly one screen (no spurious page scrollbar). */
  /* Form controls do NOT inherit the page font: the browser hands them its own, which on Windows is Arial.
     That is where every stray Arial in the suite came from, including the notification badges, which are
     spans INSIDE .ritem buttons and so inherited the button's Arial rather than the page's Geist. */
  button,input,select,textarea{font-family:inherit}
  body{font-family:var(--ui-font);-webkit-font-smoothing:antialiased;background:var(--bg);color:var(--text);line-height:var(--lh-base);margin:0;zoom:var(--app-zoom);min-height:calc(100vh / var(--app-zoom));
    /* THE standard scrollbar properties, set once at the root and inherited by every scroller in the suite.
       Everything else here styles scrollbars with ::-webkit-scrollbar only, which is Chromium/Safari-only —
       so Firefox (and anything else non-Blink) fell back to the fat OS default and the app looked like a
       different product depending on which browser it was open in. Reported 2026-07-29 as "the scrollbar
       looks totally different on other accounts": it was never the account, it was the browser — the two
       accounts were signed in side by side in two different ones. Keep BOTH: webkit gives the finer control
       (hover states), this gives everyone else a scrollbar that belongs to the app. */
    scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.22) transparent}
  /* scrollbar-COLOR inherits; scrollbar-WIDTH does not, so it has to land on each scroller itself. A universal
     selector rather than a hand-kept list of every scrollable container — that list would go stale the first
     time someone adds a panel, and a missed one is exactly how this went unnoticed. Zero specificity, so the
     few places that deliberately say `none` (.notif-tabs, .tabs, .kz-root .subtabs) still win. */
  *{scrollbar-width:thin}
  .mark{width:44px;height:44px;border-radius:12px;background:conic-gradient(#00b8d9 0 25%,#e91e8c 0 50%,#f5b914 0 75%,#555 0 100%);display:flex;align-items:center;justify-content:center;font-size:22px;font-weight:800;color:#fff;flex:0 0 auto}

  /* ---------- auth (login / first-run) ---------- */
  #auth{display:flex;align-items:center;justify-content:center;min-height:calc(100vh / var(--app-zoom));padding:24px}
  .auth-card{width:100%;max-width:380px;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);padding:30px}
  .auth-card .mark{margin:0 auto 16px}
  .auth-card h1{color:var(--white);font-size:20px;text-align:center;margin:0 0 4px}
  .auth-card .sub{color:var(--dim);font-size:13px;text-align:center;margin:0 0 22px}
  label{display:block;font-size:12px;color:var(--dim);margin:0 0 6px}
  input{width:100%;background:var(--panel2);border:1px solid var(--line);border-radius:9px;color:var(--white);padding:11px 12px;font-size:14px;margin-bottom:16px}
  input:focus{outline:none;border-color:var(--accent)}
  /* A file picker is drawn by the browser: a white "Choose file" control on our dark panels (Import
     prospects, Add material — sweep 2026-09-18). Same field, same tokens, the button drawn like ours. */
  input[type=file]{padding:8px 10px;color:var(--dim);cursor:pointer}
  input[type=file]::file-selector-button{background:var(--panel);color:var(--white);border:1px solid var(--line);border-radius:7px;padding:6px 12px;margin-right:10px;font:inherit;font-size:13px;font-weight:600;cursor:pointer}
  input[type=file]::file-selector-button:hover{border-color:var(--accent)}
  input[readonly]{color:var(--dim)}
  button.primary{width:100%;background:var(--accent);color:var(--on-accent);border:none;border-radius:9px;padding:12px;font-size:14px;font-weight:700;cursor:pointer}
  button.primary:hover{filter:brightness(1.08)}
  button.primary:disabled{opacity:var(--btn-disabled-op);cursor:default}
  .msg{font-size:13px;border-radius:8px;padding:9px 11px;margin-bottom:16px;display:none}
  .msg.err{display:block;background:rgba(255,107,107,.12);color:var(--danger);border:1px solid rgba(255,107,107,.3)}
  .msg.info{display:block;background:rgba(0,184,217,.12);color:var(--accent);border:1px solid rgba(0,184,217,.3)}

  /* ---------- Moonflo login (scoped to #auth) ---------- */
  @font-face{font-family:'Cormorant Garamond';font-style:normal;font-weight:300;font-display:swap;src:url('/fonts/cormorant.woff2') format('woff2')}
  /* ---------- THE MOON FLO LOGO: Moon [mark] Flo (owner 2026-09-26, docs/prototype/brand/moonflo-brand-mock.html) ----------
     ONE lockup, drawn in two places: the top bar (40px mark, 22px words) and the login corner (84px, 38px).
     The words are the App name setting split around the mark (app.js applyBrand) — the WRITTEN name stays
     "Moonflo" everywhere else. Spacing is the brand lockup's own: word to ring .30em, ring to word .22em, and
     the ring sits 18/224 inside the mark's box, which is what the margins subtract. */
  .mf-lk{--box:40px;display:inline-flex;align-items:center;flex:none}
  .mf-lk-w{font-family:'Cormorant Garamond',Georgia,serif;font-weight:300;font-size:22px;line-height:1;color:#F5F7FA;letter-spacing:.01em;white-space:nowrap}
  .mf-lk-w:first-child{margin-right:calc(.30em - var(--box) * 18 / 224)}
  .mf-lk-w:last-child{margin-left:calc(.22em - var(--box) * 18 / 224)}
  .mf-lk-w:empty{display:none}   /* an App name that is not Moonflo: the mark, then the name */
  .mf-lk-m{width:var(--box);height:var(--box);flex:none;display:block}
  .mf-lk-m svg{width:100%;height:100%;display:block;overflow:visible}
  /* THE MOTION, as the brand designed it — taken from moon-flow-brand/moon-flow-logo.html, because the pack's
     "animated" SVG has none inside it. The glow breathes and a shine runs along the current, left to right.
     The login's mark also has ripples crossing the moon and fine lines drifting at its edge; the top bar's
     leaves them out, because at 40px they are 0.2px strokes that cannot be seen. */
  .mfm-bloom{transform-origin:100px 100px;animation:mfBloom 6s ease-in-out infinite}
  .mfm-shine{stroke-dasharray:44 300;animation:mfShine 4.2s cubic-bezier(.45,0,.25,1) infinite}
  .mfm-drift{animation:mfDrift 7.5s ease-in-out infinite}
  .mfm-d2{animation-delay:2.5s}
  .mfm-d3{animation-delay:5s}
  .mfm-rip{animation:mfRipple 5.4s ease-in-out infinite}
  .mfm-r1{animation-delay:.6s}
  .mfm-r2{animation-delay:1.4s}
  .mfm-r3{animation-delay:2.2s}
  @keyframes mfBloom{0%,100%{opacity:.6;transform:scale(1)}50%{opacity:1;transform:scale(1.04)}}
  @keyframes mfShine{0%{stroke-dashoffset:44;opacity:0}10%{opacity:1}70%{opacity:1}88%,100%{stroke-dashoffset:-240;opacity:0}}
  @keyframes mfDrift{0%{transform:translateX(-24px);opacity:0}25%{opacity:.55}70%{opacity:.35}100%{transform:translateX(26px);opacity:0}}
  @keyframes mfRipple{0%{transform:translateX(-14px);opacity:0}30%{opacity:.55}70%{opacity:.4}100%{transform:translateX(16px);opacity:0}}
  /* The logo KEEPS MOVING under reduced motion — in the top bar, on the login and on the loading screen (owner
     2026-09-27: "the main logo has a flowing motion … all these should show motion"). It rested for one day,
     on the brand pack's rule, and the owner never saw it move: Windows' "Animation effects" is off on his PC,
     and Chrome reports that to every page as reduced motion. So there is deliberately NO reduced-motion rule
     for the logo. The tabs' motion resets (chat.css's `*{animation-duration:.001ms!important}`, and omf,
     content, kaizen) are each scoped to their own tab's root, and the logo sits outside all of them. */
  /* #auth is hidden until /auth/me decides — otherwise the login screen flashes on every refresh before the
     session check resolves (owner 2026-07-25). The loading screen (#boot) covers the gap. */
  #auth{display:none;position:relative;overflow:hidden;background:radial-gradient(circle at 78% 18%,#0b5fd8 0%,#061a3a 36%,#020b1f 100%);color:#fff}
  /* THE LOADING SCREEN (owner 2026-09-26, docs/prototype/brand/update-splash-mock.html): the same screen when
     Moonflo opens and while it updates — the brand's night blue, the logo moving as designed, "Updating Moonflo"
     only during an Update, and a slim aurora line that sweeps rather than counts (there is no real percentage to
     report for a quarter-second job). Above everything, because the app is drawn underneath it before it lifts. */
  #boot{position:fixed;inset:0;display:grid;place-items:center;z-index:10000;overflow:hidden;color:#C8D0E0;
    background:radial-gradient(ellipse 70% 60% at 50% 44%,#0F1A45 0%,#060B23 72%);transition:opacity .3s ease-in}
  #boot.arriving{animation:bootIn .12s ease-out}
  #boot.lifting{opacity:0;pointer-events:none}
  @keyframes bootIn{from{opacity:0}to{opacity:1}}
  #boot .boot-col{display:flex;flex-direction:column;align-items:center;transform:translateY(-10px)}
  #boot .mf-lk{--box:128px}
  #boot .mf-lk-w{font-size:56px}
  #boot.updating .mf-lk-w{display:none}   /* opening Moonflo: the mark and the words; an update: the mark alone (owner 2026-09-27) */
  /* the words show only during an Update, but keep their place otherwise, so the logo sits exactly where it does
     on an ordinary open and nothing moves between the two (the mock's "same screen without the words") */
  #boot .boot-say{visibility:hidden;margin-top:30px;font:400 12.5px/1 'Geist Mono',Consolas,monospace;letter-spacing:.42em;padding-left:.42em;text-transform:uppercase;opacity:.72}
  #boot.updating .boot-say{visibility:visible}
  #boot .boot-msg{display:flex;flex-direction:column;align-items:center}
  #boot .boot-bar{margin-top:18px;width:180px;height:2px;border-radius:2px;background:rgba(200,208,224,.12);overflow:hidden;position:relative}
  #boot .boot-bar::after{content:"";position:absolute;top:0;bottom:0;left:0;width:45%;border-radius:2px;
    background:linear-gradient(90deg,rgba(79,214,196,0),#4FD6C4 30%,#5FA0FF 55%,#9E8CFF 80%,rgba(158,140,255,0));animation:bootSweep 1.4s cubic-bezier(.45,0,.25,1) infinite}
  @keyframes bootSweep{from{transform:translateX(-100%)}to{transform:translateX(225%)}}
  @keyframes bootspin{to{transform:rotate(360deg)}}   /* .navarrow.spinning — the top bar's Reload */
  /* Reduced motion: the logo keeps moving (above) and so does the line, which is part of the same brand moment
     (owner 2026-09-27). Nothing fades: the screen simply appears and goes. */
  @media (prefers-reduced-motion:reduce){
    #boot{transition:none}
    #boot.arriving{animation:none}
  }
  @media (max-width:760px){
    #boot .mf-lk{--box:84px}
    #boot .mf-lk-w{font-size:38px}
    #boot .boot-say{font-size:11px;margin-top:24px}
    #boot .boot-bar{width:140px}
  }
  /* The loading screen can SAY something. A server that is not answering is not a session that has ended,
     so a restart must not put a signed-in person on the login form (owner 2026-08-25). */
  #boot .boot-box{display:flex;flex-direction:column;align-items:center;gap:14px;margin-top:26px;text-align:center;max-width:340px;padding:0 20px;color:var(--fg,#e8eefc)}
  #boot .boot-box p{margin:0;font-size:14px;line-height:1.5;opacity:.86}
  #boot .boot-box p.lead{font-size:15px;font-weight:600;opacity:1}
  #boot .boot-retry{margin:0;padding:9px 18px;border-radius:8px;border:1px solid rgba(255,255,255,.22);background:rgba(255,255,255,.08);color:inherit;font:inherit;cursor:pointer}
  #boot .boot-retry:hover{background:rgba(255,255,255,.16)}
  #auth .mf-bg{position:absolute;inset:0;overflow:hidden;z-index:0;pointer-events:none}
  #auth .mf-grid{position:absolute;inset:0;background-image:linear-gradient(rgba(255,255,255,.045) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.045) 1px,transparent 1px);background-size:52px 52px;-webkit-mask-image:radial-gradient(circle at center,#000 0%,transparent 72%);mask-image:radial-gradient(circle at center,#000 0%,transparent 72%);animation:mf-gridMove 18s linear infinite}
  #auth .mf-orb{position:absolute;border-radius:50%;filter:blur(16px);opacity:.55;animation:mf-float 9s ease-in-out infinite}
  #auth .mf-orb.one{width:320px;height:320px;background:rgba(0,123,255,.28);top:8%;right:12%}
  #auth .mf-orb.two{width:220px;height:220px;background:rgba(45,187,255,.18);bottom:12%;left:10%;animation-delay:-3s}
  #auth .mf-ripplewrap{position:absolute;top:50%;left:50%;width:760px;height:760px;transform:translate(-50%,-50%);display:flex;align-items:center;justify-content:center;pointer-events:none}
  #auth .mf-rp{position:absolute;border-radius:50%;border:1px solid rgba(45,187,255,.30);box-shadow:0 0 28px rgba(45,187,255,.08),inset 0 0 24px rgba(45,187,255,.03);opacity:0;transform:scale(.6);animation:mf-rippleWave 7.5s cubic-bezier(.22,.61,.36,1) infinite;will-change:transform,opacity}
  #auth .mf-rp.one{width:300px;height:300px;animation-delay:0s}
  #auth .mf-rp.two{width:300px;height:300px;animation-delay:1.5s}
  #auth .mf-rp.three{width:300px;height:300px;animation-delay:3s}
  #auth .mf-rp.core{width:360px;height:360px;border-color:rgba(45,187,255,.18);opacity:.35;transform:scale(1);animation:none}
  #auth .mf-dataline{position:absolute;right:7%;bottom:12%;width:280px;height:140px;opacity:.55}
  #auth .mf-dataline svg{width:100%;height:100%;overflow:visible}
  #auth .mf-dataline path{fill:none;stroke:#2dbbff;stroke-width:3;stroke-dasharray:520;stroke-dashoffset:520;animation:mf-draw 4s ease-in-out infinite alternate}
  #auth .mf-node{fill:#2dbbff;filter:drop-shadow(0 0 8px #2dbbff);animation:mf-pulse 2.6s ease-in-out infinite}
  /* the corner: the logo, and the line under it centred beneath the whole lockup (mock section 3) */
  #auth .mf-corner{position:absolute;top:22px;left:24px;z-index:5;display:flex;flex-direction:column;align-items:center;gap:10px}
  #auth .mf-lk{--box:84px}
  #auth .mf-lk-w{font-size:38px}
  #auth .mf-corner-s{font-size:9px;color:#d6e4fb;letter-spacing:.34em;text-transform:uppercase;opacity:.82;white-space:nowrap}
  #auth .mf-foot{position:absolute;left:0;right:0;bottom:18px;z-index:5;text-align:center;font-size:11px;font-weight:400;color:#cfe0fb;opacity:.42;letter-spacing:.02em;padding:0 16px;user-select:none;pointer-events:none}
  #auth .auth-card{position:relative;z-index:2;width:min(420px,100%);max-width:420px;padding:34px;border-radius:26px;background:linear-gradient(145deg,rgba(255,255,255,.12),rgba(255,255,255,.045));border:1px solid rgba(255,255,255,.18);backdrop-filter:blur(22px);-webkit-backdrop-filter:blur(22px);box-shadow:0 30px 90px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.14)}
  #auth .auth-card h1{color:#fff;font-size:26px;text-align:left;letter-spacing:-.4px;margin:0 0 6px}
  #auth .auth-card .sub{color:#9db8d9;font-size:13.5px;text-align:left;margin:0 0 24px}
  #auth label{color:#cfe2ff;font-size:12.5px;font-weight:600;margin:0 0 7px}
  #auth input{background:rgba(2,11,31,.45);border:1px solid rgba(255,255,255,.14);border-radius:13px;color:#fff;height:50px;padding:0 15px;font-size:14.5px;margin-bottom:15px}
  #auth input::placeholder{color:rgba(207,226,255,.42)}
  #auth input:focus{outline:none;border-color:#2dbbff;box-shadow:0 0 0 4px rgba(45,187,255,.12),0 0 22px rgba(45,187,255,.16)}
  #auth input[readonly]{color:#9db8d9}
  #auth .mf-pass{position:relative;margin-bottom:15px}
  #auth .mf-pass input{margin-bottom:0;padding-right:48px}
  #auth .mf-eye{position:absolute;right:7px;top:50%;transform:translateY(-50%);width:36px;height:36px;display:flex;align-items:center;justify-content:center;background:none;border:none;color:#9db8d9;cursor:pointer;padding:0;border-radius:9px}
  #auth .mf-eye:hover{color:#cfe2ff}
  #auth .mf-eye:focus-visible{outline:2px solid #2dbbff;outline-offset:1px}
  #auth .mf-eye svg{width:20px;height:20px}
  #auth .mf-eye .ic-hide{display:none}
  #auth .mf-eye.showing .ic-show{display:none}
  #auth .mf-eye.showing .ic-hide{display:block}
  #auth button.primary{background:linear-gradient(135deg,#007bff,#25c7ff);color:#fff;border-radius:14px;height:52px;padding:0;font-size:15.5px;font-weight:800;box-shadow:0 14px 34px rgba(0,123,255,.34);position:relative;overflow:hidden;transition:transform .2s ease,box-shadow .2s ease}
  #auth button.primary::after{content:"";position:absolute;top:0;left:-120%;width:80%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.35),transparent);animation:mf-shine 3.5s ease-in-out infinite}
  #auth button.primary:hover{transform:translateY(-2px);box-shadow:0 18px 45px rgba(0,123,255,.48);filter:none}
  #auth .mf-status{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:20px;color:#b8d7ff;font-size:11.5px}
  #auth .mf-status span{width:8px;height:8px;border-radius:50%;background:#33ffba;box-shadow:0 0 14px #33ffba;animation:mf-pulse 1.7s ease-in-out infinite}
  @keyframes mf-float{0%,100%{transform:translate3d(0,0,0) scale(1)}50%{transform:translate3d(18px,-24px,0) scale(1.06)}}
  @keyframes mf-gridMove{from{background-position:0 0}to{background-position:104px 104px}}
  @keyframes mf-rippleWave{0%{opacity:0;transform:scale(.6)}14%{opacity:.16}36%{opacity:.3}72%{opacity:.12}100%{opacity:0;transform:scale(1.88)}}
  @keyframes mf-draw{to{stroke-dashoffset:0}}
  @keyframes mf-pulse{0%,100%{opacity:.55;transform:scale(1)}50%{opacity:1;transform:scale(1.18)}}
  @keyframes mf-shine{0%{left:-120%}45%,100%{left:140%}}
  /* The login's ambient motion is part of the Moonflo brand moment, so keep it running even when the
     OS/browser requests reduced motion (a global *{animation-duration:.001ms!important} in chat.css would
     otherwise freeze it). Higher specificity + !important re-assert each animation over that reset.
     The LOGO keeps moving too, by its own rule (see THE MOON FLO LOGO above). */
  @media (prefers-reduced-motion:reduce){
    #auth .mf-grid{animation:mf-gridMove 18s linear infinite!important}
    #auth .mf-orb{animation:mf-float 9s ease-in-out infinite!important}
    #auth .mf-orb.two{animation-delay:-3s!important}
    #auth .mf-rp{animation:mf-rippleWave 7.5s cubic-bezier(.22,.61,.36,1) infinite!important}
    #auth .mf-rp.core{animation:none!important}
    #auth .mf-rp.two{animation-delay:1.5s!important}
    #auth .mf-rp.three{animation-delay:3s!important}
    #auth .mf-dataline path{animation:mf-draw 4s ease-in-out infinite alternate!important}
    #auth .mf-node{animation:mf-pulse 2.6s ease-in-out infinite!important}
    #auth button.primary::after{animation:mf-shine 3.5s ease-in-out infinite!important}
    #auth .mf-status span{animation:mf-pulse 1.7s ease-in-out infinite!important}
  }
  @media (max-width:560px){#auth .mf-corner{top:14px;left:14px;transform:scale(.72);transform-origin:top left}#auth .auth-card{padding:26px;border-radius:20px}#auth .mf-dataline{display:none}}

  /* ---------- suite shell ---------- */
  #shell{display:none;height:calc(100vh / var(--app-zoom) - var(--foot-h));flex-direction:column;overflow:hidden}  /* bounded to viewport minus the fixed footer so every tab clears it */
  /* Mission Rail v2: the tabs left the bar for the rail, so the bar slims to 52px. Since 2026-09-27 it carries the
     mark on the left, the apps in the centre (top-bar layout only) and the controls on the right. */
  /* No border-bottom here. The top bar and the app rail are now the SAME surface, so a line between them was
     a seam drawn through the middle of one continuous piece of chrome — the owner's "this line which connects
     side bar and top bar should not show, should be flush" (2026-08-13). The line belongs where the chrome
     actually ends and the work begins, so #view carries it as a border-top and the rail column gets none. */
  .topbar{display:flex;align-items:center;gap:16px;padding:0 16px;height:var(--topbar-h);flex:none;background:var(--chrome);position:relative;z-index:30}
  /* the rail's permanent column: chrome whether or not the apps are living in it */
  .railslot{width:var(--rail-w);flex:none;display:flex;background:var(--chrome);border-right:1px solid var(--chrome-line)}
  body[data-nav="top"] .railslot{border-right-color:var(--chrome-line)}
  /* Team Hub only (owner 2026-07-17): the top bar adopts the chat theme's tone so chrome + chat read as one
     surface — no colour seam. Other tabs keep the standard suite chrome; Light keeps the dark bar (the
     established light-tab convention: Kaizen / Logistics / Online Orders all sit under dark chrome). */
  /* ONE value per theme, read by BOTH the top bar and the app rail (owner 2026-08-11: "the side strip
     always should match the top colour"). They were two hardcoded colours that could — and did — drift:
     the rail had no theme rule at all and stayed near-black, and when the chat palettes were retuned on
     2026-08-11 these top-bar values still carried the OLD rail colours. A shared custom property means a
     future palette change touches one line and both surfaces follow. The values ARE each theme's --rail,
     so the chrome is continuous with the channel sidebar it sits above. */
  /* …and now the SUITE's own default, not Team Hub's alone (owner 2026-08-13). The chrome is the top bar, the
     app rail and the footer: one L of frame around whatever tab is open. It was three separate hardcoded
     pairs, and the footer's was the retired palette — #15171F fill with a #2C3140 rule, which made the
     brightest line on screen the one around "All rights reserved." Every tab now brackets its work between
     the same two values, and the per-theme overrides below carry all three surfaces instead of two. */
  :root{--chrome:#0D1017;--chrome-line:#1B2230}
  body[data-active-tab="chat"]{--chrome:#0D1017;--chrome-line:#1B2230}
  body[data-active-tab="chat"][data-chat-theme="moonblue"]{--chrome:#081834;--chrome-line:rgba(150,185,235,.14)}
  body[data-active-tab="chat"][data-chat-theme="console"]{--chrome:#07080b;--chrome-line:rgba(255,255,255,.09)}
  /* light keeps the dark chrome deliberately (the established light-tab convention) — it just
     needs the two surfaces to agree, which the shared default already gives it. */
  /* These two rules are gone, not lost. .topbar and .railslot read --chrome themselves now, so the per-theme
     values above already reach them — and the declarations here had gone inert with the surfaces they named:
     .topbar has no bottom border to colour any more (the seam moved to #view), and .rail carries neither the
     fill nor the edge, which belong to the slot it sits in. A rule that colours a border which does not exist
     is the kind of line that costs the next reader ten minutes. */
  .notif{position:relative}
  .focus-pill{display:flex;align-items:center;gap:6px;flex:none;height:30px;padding:0 11px;border-radius:999px;background:rgba(245,185,20,.14);border:1px solid rgba(245,185,20,.45);color:#f5b914;font-size:12px;font-weight:700;font-family:inherit;cursor:pointer;white-space:nowrap}
  .focus-pill:hover{background:rgba(245,185,20,.22)}
  .notif-badge{position:absolute;top:-2px;right:-2px;min-width:16px;height:16px;padding:0 4px;border-radius:9px;background:var(--count-badge);color:#fff;font-size:10px;font-weight:700;display:flex;align-items:center;justify-content:center;line-height:1;box-sizing:border-box}
  .notif-panel{position:absolute;top:calc(100% + 8px);right:0;width:392px;max-height:440px;display:none;flex-direction:column;background:var(--panel);border:1px solid var(--line);border-radius:12px;box-shadow:0 14px 36px rgba(0,0,0,.45);z-index:70;overflow:hidden}
  .notif-panel.open{display:flex}
  .notif-head{display:flex;align-items:center;justify-content:space-between;padding:11px 14px;border-bottom:1px solid var(--line)}
  .notif-head b{color:var(--white);font-size:13px}
  .notif-readall{background:none;border:none;color:var(--accent);font-size:12px;cursor:pointer;font-family:inherit}
  .notif-readall:hover{text-decoration:underline}
  .notif-list{overflow-y:auto}
  /* per-app filter chips (plan phase 2): only apps with unread work appear, so every chip is worth pressing */
  /* flex:none on both bars — the panel is a flex column, so without it they shrink under the scrolling list
     and the chips end up half-hidden behind the first row */
  .notif-head{flex:none}
  .notif-tabs{flex:none;display:flex;gap:6px;padding:8px 12px;border-bottom:1px solid var(--line);overflow-x:auto;scrollbar-width:none}
  .notif-tabs:empty{display:none}
  .notif-tabs::-webkit-scrollbar{display:none}
  .ntab{flex:0 0 auto;background:var(--panel2);border:1px solid var(--line);color:var(--muted);font-family:inherit;font-size:11.5px;font-weight:600;border-radius:999px;padding:4px 10px;cursor:pointer;white-space:nowrap}
  .ntab:hover{color:var(--white)}
  .ntab.on{background:var(--accent);border-color:transparent;color:#fff}
  .ntab .n{opacity:.75;font-weight:700}
  /* grouped rows (plan phase 1): one entry per thing, latest line on top, earlier ones behind "+N earlier" */
  .notif-item .nbody{flex:1;min-width:0}
  .notif-item .ncount{display:inline-block;min-width:16px;padding:0 5px;border-radius:9px;background:var(--accent);color:#fff;font-size:10px;font-weight:700;line-height:15px;text-align:center;vertical-align:1px}
  .nmore{background:none;border:none;padding:0;color:var(--accent);font-family:inherit;font-size:inherit;cursor:pointer}
  .nmore:hover{text-decoration:underline}
  .nearlier{margin-top:6px;border-left:2px solid var(--line);padding-left:8px}
  .nline{display:flex;gap:8px;justify-content:space-between;font-size:11.5px;color:var(--muted);padding:2px 0}
  .nline span{flex:0 0 auto;opacity:.7}
  .nclear{flex:0 0 auto;align-self:flex-start;background:none;border:1px solid var(--line);border-radius:6px;color:var(--muted);font-size:11px;line-height:1;padding:3px 6px;cursor:pointer}
  .nclear:hover{color:var(--white);border-color:var(--accent)}
  .notif-item{display:flex;gap:9px;padding:10px 14px;border-bottom:1px solid var(--line);cursor:pointer}
  .notif-item:last-child{border-bottom:none}
  .notif-item:hover{background:var(--panel2)}
  .notif-item .dot{width:7px;height:7px;border-radius:50%;background:var(--accent);margin-top:5px;flex:none}
  .notif-item.read{opacity:.62}
  .notif-item.read .dot{background:transparent;border:1px solid var(--line)}
  .notif-item .body{font-size:12.5px;color:var(--text);line-height:1.4}
  .notif-item .meta{font-size:10.5px;color:var(--dim);margin-top:3px}
  .notif-empty{padding:26px 14px;text-align:center;color:var(--dim);font-size:12.5px}
  .audit-list{max-height:360px;overflow-y:auto;border:1px solid var(--line);border-radius:10px;background:var(--panel)}
  .audit-row{padding:8px 12px;border-bottom:1px solid var(--line)}
  .audit-row:last-child{border-bottom:none}
  .audit-body{font-size:12.5px;color:var(--text)}
  .audit-meta{font-size:10.5px;color:var(--dim);margin-top:2px}
  .audit-empty{padding:20px;text-align:center;color:var(--dim);font-size:12.5px}
  /* Admin Settings navigation: a grouped left rail (sticky while the panel scrolls) — replaces the flat tab strip */
  .set-layout{display:flex;gap:22px;align-items:flex-start}
  .set-rail{flex:0 0 188px;position:sticky;top:-20px;align-self:flex-start;display:flex;flex-direction:column;gap:1px;padding-top:2px}
  .set-rail-grp{font-size:10px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--dim);opacity:.65;margin:15px 0 4px 10px}
  .set-rail-grp:first-child{margin-top:0}
  .set-rail-item{display:flex;align-items:center;gap:9px;width:100%;text-align:left;background:none;border:none;border-radius:var(--r-sm);color:var(--dim);padding:8px 11px;font-size:13px;cursor:pointer;font-family:inherit}
  .set-rail-item:hover{background:var(--panel2);color:var(--text)}
  .set-rail-item.on{background:var(--panel2);color:var(--white);font-weight:600;box-shadow:inset 2px 0 0 var(--accent)}
  .set-rail-item svg{width:15px;height:15px;flex:none}
  .set-panel{flex:1;min-width:0}
  /* Automations panel (settings restructure): sticky jump chips + per-app section headers */
  .auto-chips{position:sticky;top:-20px;z-index:5;background:var(--panel);display:flex;gap:7px;flex-wrap:wrap;padding:6px 0 10px;border-bottom:1px solid var(--line);margin-bottom:14px}
  .auto-chip{background:var(--panel2);border:1px solid var(--line);border-radius:999px;color:var(--dim);padding:5px 13px;font-size:12px;font-weight:600;cursor:pointer;font-family:inherit}
  .auto-chip:hover{color:var(--white);border-color:var(--accent)}
  .auto-apph{display:flex;align-items:center;gap:9px;margin:20px 0 8px;scroll-margin-top:52px}
  .auto-apph:first-of-type{margin-top:2px}
  .auto-apph .dot{width:9px;height:9px;border-radius:50%;flex:none}
  .auto-apph b{color:var(--white);font-size:13.5px}
  .auto-apph small{color:var(--dim);font-size:11px}
  #orders-planner{overflow-x:auto;border-radius:10px}  /* the light omfh-root planner grid scrolls inside its card, never bleeds */
  @media(max-width:680px){.set-layout{flex-direction:column;gap:12px}.set-rail{flex-direction:row;flex-wrap:wrap;position:static;flex-basis:auto}.set-rail-grp{display:none}}
  /* Main Settings = windowed overlay — opens OVER the active tab (below the topbar, right of the nav) so its left nav (Main Dashboard…) stays visible */
  .set-backdrop{position:fixed;inset:0;background:rgba(8,10,16,.5);display:none;z-index:55}
  .set-backdrop.open{display:block}
  .set-window{position:absolute;inset:0;max-width:none;background:var(--panel);border:none;border-radius:0;box-shadow:none;display:flex;flex-direction:column;overflow:hidden}  /* full-screen takeover (owner 2026-07-25) — was a floating window beside the tab nav; Esc / ✕ close it */
  /* full-screen settings get roomier content: lift the FK-tab card caps (640/980px) inside the window only */
  #set-window .section{max-width:1280px}
  #set-window .fk-auto-card{max-width:1220px}
  .set-win-head{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;padding:18px 22px 14px;border-bottom:1px solid var(--line);flex:none}
  .set-win-head h2{color:var(--white);font-size:18px;margin:0;display:flex;align-items:center;gap:8px}
  .set-win-head h2 svg{width:18px;height:18px}
  .set-win-head .sub{color:var(--dim);font-size:12px;margin:3px 0 0;max-width:620px}
  .set-win-close{background:var(--panel2);border:1px solid var(--line);color:var(--text);width:34px;height:34px;border-radius:9px;font-size:15px;cursor:pointer;flex:none;line-height:1}
  .set-win-close:hover{border-color:var(--accent);color:var(--white)}
  .set-win-body{flex:1;min-height:0;overflow-y:auto;padding:20px 22px}
  .set-win-body::-webkit-scrollbar{width:10px}
  .set-win-body::-webkit-scrollbar-thumb{background:transparent;border-radius:9px;border:2px solid transparent;background-clip:padding-box}
  .set-win-body:hover::-webkit-scrollbar-thumb{background:rgba(255,255,255,.16);background-clip:padding-box}
  .set-win-body::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.3);background-clip:padding-box}
  .set-win-body::-webkit-scrollbar-track{background:transparent}
  @media (max-width:820px){ .set-window{left:12px;right:12px;width:auto;top:60px;bottom:12px} }
  /* Help ("How to use") — same in-app overlay pattern as Admin Settings, so the top menu stays put */
  /* Main Settings line-icons (header, sub-tabs, tab-assignment matrix) — monochrome, inherit currentColor */
  .view-head h2 svg{width:19px;height:19px;vertical-align:-3px;margin-right:6px}
  table.grid th svg{width:17px;height:17px;display:inline-block;margin-bottom:3px;color:var(--dim)}
  /* THE MARK, alone, in the left corner and as large as the bar allows (owner 2026-09-27, top bar mock 5): its
     circle is the bar's height less 5px above and below — "as large as possible but not to touch the bar lines".
     The circle is 188 of the mark's 224 units, so the box is (bar − 10) × 224/188: 50px in the 52px bar, 62px in
     the 62px bar the apps get in top-bar mode (measured: 5px clear of the top and of the line under the bar in
     both). The words are hidden here — the App name still writes them, for the login and the opening screen.
     -4px: the box's own transparent edge, so the circle sits where the bar's padding says. */
  .brand{display:flex;align-items:center;flex:none;margin-left:-4px}
  .brand .mf-lk{--box:50px;margin:0}
  body[data-nav="top"] .brand .mf-lk{--box:62px}
  .brand .mf-lk-w{display:none}
  /* ---------- top-right icon cluster ---------- */
  /* Its content's width, never a fixed one: Hyper Focus adds a ~148px pill to this box, and a hard width with
     flex:none once crushed the three icon buttons beside it to 2px each — invisible and unclickable on every tab.
     Its width is also what fitTabs() measures the room for the centred apps against. */
  .top-actions{display:flex;align-items:center;gap:6px;justify-content:flex-end;flex:none}
  /* an icon button has no min-content floor to fall back on — its child is a fixed-size SVG in a grid cell, so
     min-width:auto resolves to 0 and it compresses to its borders rather than stopping at the glyph */
  .icbtn{width:32px;height:32px;flex:none;border-radius:8px;border:1px solid transparent;background:transparent;color:#B6C0D2;display:grid;place-items:center;cursor:pointer;position:relative;padding:0}
  .icbtn:hover{background:#1A2133;color:#EEF2F8}
  .icbtn svg{width:18px;height:18px;display:block}
  .icbtn .ic{display:inline-flex;align-items:center;justify-content:center;line-height:0}
  /* one badge shape for every count in the chrome — bell, dock, rail (the rail overrides its seat colour) */
  .bdg,.notif-badge{position:absolute;top:-3px;right:-4px;min-width:16px;height:16px;padding:0 4px;border-radius:8px;background:var(--count-badge);color:#fff;font-size:10px;font-weight:700;display:grid;place-items:center;border:2px solid #0D1017;line-height:1;box-sizing:border-box;margin:0}
  .spacer{flex:1}
  .notif,.acct{flex:none}
  /* BACK, FORWARD AND RELOAD — ONE JOINED CONTROL (owner 2026-09-27, top bar mock option A): one rounded box, a
     thin line before Reload, beside search. Useful once installed, with no browser chrome of its own. */
  .navgroup{display:flex;align-items:center;height:32px;padding:0 2px;border-radius:10px;background:rgba(255,255,255,.035);border:1px solid rgba(255,255,255,.08);flex:none}
  .navarrows{display:flex;align-items:center;flex:none}
  .navarrow{width:30px;height:28px;display:grid;place-items:center;border:0;background:transparent;color:#AEB8CB;border-radius:7px;cursor:pointer;padding:0;transition:background .12s,color .12s}
  .navarrow svg{width:16px;height:16px;display:block}
  .navarrow:hover:not(:disabled){background:rgba(255,255,255,.08);color:#fff}
  .navarrow:disabled{opacity:.32;cursor:default}
  .navarrow:focus-visible{outline:2px solid #3ECFDC;outline-offset:1px}
  .navgroup .sep{width:1px;height:16px;background:rgba(255,255,255,.1);margin:0 2px;flex:none}
  .navarrow.spinning svg{animation:bootspin .7s linear infinite}   /* Reload: the page tearing down is not a dead button */
  @media (prefers-reduced-motion:reduce){ .navarrow.spinning svg{animation:none;opacity:.5} }
  /* ---------- the app rail: tab-level destinations, left of #view (Mission Rail v2) ---------- */
  /* NOTE: neither .rail nor .dock-row may gain overflow — the active marker paints at left:-9px and the
     tooltip at left:52px, both deliberately OUTSIDE the 56px column. Clipping either kills them. */
  /* the fill and the right edge belong to .railslot now, which stays put whether or not the rail is in it */
.rail{width:var(--rail-w);flex:none;display:flex;flex-direction:column;align-items:center;padding:12px 0 10px;gap:6px;background:none}
  .rail .sp{flex:1}
  .ritem{width:40px;height:40px;border-radius:11px;display:grid;place-items:center;color:#909BB0;cursor:pointer;position:relative;border:1px solid transparent;background:transparent;padding:0;flex:none}
  .ritem svg{width:18px;height:18px;display:block}
  /* the layout switch when it is living in the rail (it reparents with the apps) — sized as a .ritem so it
     sits in the same 40px column, and coloured by the rail's own tokens rather than the top bar's */
  .rail #navmode-btn{width:40px;height:40px;border-radius:11px;color:#909BB0}
  .rail #navmode-btn:hover{background:var(--chrome-hover,#1A2133);color:#EEF2F8}
  .ritem .ic{display:inline-flex;align-items:center;justify-content:center;line-height:0}
  .ritem:hover{color:#EEF2F8;background:#161D2C}
  .ritem.active{color:#3ECFDC;background:rgba(62,207,220,.13);border-color:rgba(62,207,220,.32)}
  .ritem.active::before{content:"";position:absolute;left:-9px;top:9px;bottom:9px;width:3px;border-radius:3px;background:#3ECFDC}
  .ritem.locked{color:#5b6273;cursor:not-allowed;opacity:.55}
  .ritem .bdg{top:-2px;right:-2px;min-width:15px;height:15px;padding:0 3px;font-size:10px;border-color:#0A0C11}
  .tooltip{display:none;position:absolute;left:52px;top:50%;transform:translateY(-50%);background:#1E2637;border:1px solid #333E58;color:#EEF2F8;font-size:12px;font-weight:600;padding:5px 10px;border-radius:7px;white-space:nowrap;box-shadow:0 6px 18px rgba(2,4,9,.5);z-index:40;pointer-events:none}
  .tooltip::before{content:"";position:absolute;left:-4px;top:50%;width:8px;height:8px;background:#1E2637;border-left:1px solid #333E58;border-bottom:1px solid #333E58;transform:translateY(-50%) rotate(45deg)}
  .ritem:hover .tooltip,.ritem:focus-visible .tooltip{display:block}
  /* The rail and the bar sit OUTSIDE #fk-shell, so the suite-wide :focus-visible paints them in
     var(--tab-accent) (#00b8d9 on FK) while the rail's own active state is the mock's #3ECFDC — two cyans
     in one view. The mock runs ONE accent, so these carry it explicitly, with its own offsets. */
  .ritem:focus-visible,.icbtn:focus-visible{outline:2px solid #3ECFDC;outline-offset:1px}
  .ritem .tlbl{display:none}  /* the rail is icon-only; the name is the .tooltip. Top-bar mode shows it instead. */

  /* ================= APPS ON THE TOP BAR (optional, per browser) =================
     #navmode-btn moves the SAME #rail element between .dock-row and .topbar — one render path, so the
     active state, the chat count and every .ritem[data-key] selector keep working in both layouts.
     Here the rail becomes the segmented strip the suite had before Mission Rail: names visible, raised
     active segment, the per-app accent in the icon. The 56px column returns to the page. */
  body[data-nav="top"] #rail{flex-direction:row;width:auto;flex:0 1 auto;min-width:0;align-items:center;overflow-x:auto;scrollbar-width:none;padding:3px;gap:2px;margin:0;background:#101219;border:1px solid var(--line);border-right:1px solid var(--line);border-radius:12px}
  /* 62px in TOP mode only. The bar slimmed 62→52 for Mission Rail v2 precisely BECAUSE the tabs left it —
     that reasoning does not hold in this mode, where they are back in it: a 38px tab plate in a 52px bar
     leaves 7px of air above and below and reads cramped. Rail mode keeps its 52px. (owner 2026-08-09) */
  body[data-nav="top"]{--topbar-h:62px}
  body[data-nav="top"] #rail::-webkit-scrollbar{display:none}
  /* A shortened or icon-only app shows its full name BELOW it, which a scrolling strip would cut off — so the strip
     only scrolls in the one case left over: not even the icons fit (t-over, set by fitTabs). */
  body[data-nav="top"] #rail:not(.t-over){overflow:visible}
  body[data-nav="top"] #rail.t-measure .tooltip{display:none!important}   /* measuring: a name on show must not count as width */
  /* 13.5/600 in an 8px radius, from the mock — was 14/500 at 9px. A tab is a label you pick from, not body
     copy: the heavier, slightly smaller face is what makes the row read as a set of controls. */
  body[data-nav="top"] .ritem{width:auto;height:auto;display:flex;gap:7px;padding:6px 13px;border-radius:8px;color:var(--dim);font-size:13.5px;font-weight:600;white-space:nowrap;flex:0 1 auto;min-width:0}
  body[data-nav="top"] .ritem .ic,body[data-nav="top"] .ritem .bdg{flex:none}
  /* a name gives way with "…", never below half its letters — --half is set by fitTabs() (owner 2026-09-27) */
  body[data-nav="top"] .ritem .tlbl{display:block;min-width:var(--half,0px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  body[data-nav="top"] .ritem svg{width:16px;height:16px}
  body[data-nav="top"] .ritem:not(.active):not(.locked):hover{background:rgba(255,255,255,.04);color:var(--text)}
  body[data-nav="top"] .ritem.active{background:var(--panel2);color:var(--white);border-color:transparent;box-shadow:0 1px 7px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.06)}  /* raised segment = unambiguous 'current app' */
  body[data-nav="top"] .ritem.active .ic{color:var(--tab-accent)}                       /* the per-app signature hue, confined to the icon */
  body[data-nav="top"] .ritem[data-key="chat"]:not(.locked) .ic{color:#fff}             /* Team Hub goes white — the moon (owner 2026-07-15) */
  body[data-nav="top"] .ritem.active::before{display:none}                              /* the left marker belongs to the rail */
  /* the name is on screen; a tooltip would just repeat it. This has to match the HOVER state, not the base
     one: `body[data-nav="top"] .tooltip` is (0,2,1) and loses to `.ritem:hover .tooltip` (0,3,0) no matter
     what order they sit in, so the tooltip still fired here — a rail-positioned pill (left:52px, vertically
     centred) painted over the hovered button's own visible label. The t-mini and t-cut rules below carry an id,
     so they still outrank this and bring the full name back where it is not on screen. */
  body[data-nav="top"] .ritem:hover .tooltip,body[data-nav="top"] .ritem:focus-visible .tooltip{display:none}
  body[data-nav="top"] .ritem .bdg{position:static;margin-left:6px;border:none;min-width:16px;height:16px;border-radius:5px;font-size:9px;font-weight:800}
  body[data-nav="top"] #rail .sp,body[data-nav="top"] #rail-settings{display:none}      /* a gear inside the app strip reads as an app; Admin Settings stays in the account menu */
  /* THE APPS STAY PUT, IN THE EXACT CENTRE (owner 2026-09-17: "it should stay in one area"; 2026-09-27: "in centre
     of the tab away from the Moon flo Mark"). The bar is three columns and the outer two are always EQUAL (the
     desktop grid below), so nothing either side does — the tour bulb, the chat panel button, Hyper Focus's pill —
     can move them. The invisible twin of the layout switch on their left is what centres the apps themselves
     rather than apps + switch. An absolutely-centred strip was tried once and overlapped its neighbours, because
     out of flow it reserves nothing; this stays in flow, and fitTabs() narrows it before it can touch either side. */
  .top-mid{display:flex;align-items:center;gap:8px;min-width:0}
  .mid-twin{display:none}
  body[data-nav="top"] .mid-twin{display:block;width:32px;height:32px;flex:none;visibility:hidden}
  /* Narrow windows in top-bar mode: fitTabs() measures the real room and adds these in order — full, tighter,
     names shortened (never below half, by --half above), then icons only (owner 2026-09-27, top bar mock 5). */
  body[data-nav="top"] #rail.t-tight{gap:1px}   /* no side margin: it would push the centred apps off the middle */
  body[data-nav="top"] #rail.t-tight .ritem{padding:7px 9px;gap:5px;font-size:13.5px}
  body[data-nav="top"] #rail.t-mini .ritem{padding:7px 10px;gap:0}
  body[data-nav="top"] #rail.t-mini .tlbl{display:none}        /* icon only — the name comes back as the tooltip */
  body[data-nav="top"] #rail.t-mini .tooltip{display:none}
  /* the full name on hover: every app when they are icons, and a SHORTENED one (t-cut) when its "…" hides the end */
  body[data-nav="top"] #rail.t-mini .ritem:hover .tooltip,body[data-nav="top"] #rail.t-mini .ritem:focus-visible .tooltip,
  body[data-nav="top"] #rail .ritem.t-cut:hover .tooltip,body[data-nav="top"] #rail .ritem.t-cut:focus-visible .tooltip{display:block;left:50%;top:calc(100% + 8px);transform:translateX(-50%)}
  body[data-nav="top"] #rail.t-mini .tooltip::before,body[data-nav="top"] #rail .ritem.t-cut .tooltip::before{left:50%;top:-4px;margin-left:-4px;border:none;border-left:1px solid #333E58;border-top:1px solid #333E58}
  body[data-nav="top"] #rail.t-mini .ritem .bdg{margin-left:3px}  /* the count stays: it is the reason to look */
  /* the toggle shows the layout you would GET by clicking it */
  body[data-nav="top"] .navm-top,body[data-nav="rail"] .navm-side{display:none}
  body[data-nav="top"]{--rail-inset:0px}   /* no rail down the left → overlays cover the full width */
  @media(max-width:1120px){ .topbar{gap:10px;padding:0 12px} }
  /* THE BAR IS THREE COLUMNS on anything wider than a phone (owner 2026-09-27, top bar mock 5): the mark on the
     left, the apps in the exact centre, the controls on the right. minmax(0,1fr) makes the two outer columns equal
     whatever they hold, and that is what centres the middle one. .top-actions takes its content's width, so its box
     grows with every button it gains and the ResizeObserver in app.js re-fits the apps. A phone keeps its own bar. */
  @media(min-width:761px){
    .topbar{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);column-gap:20px}
    .topbar > .brand{grid-column:1;grid-row:1;justify-self:start}
    .topbar > .top-mid{grid-column:2;grid-row:1}
    .topbar > .top-actions{grid-column:3;grid-row:1;justify-self:end;width:max-content}
    /* …unless not even the icons fit in the exact centre: a very wide right side (Order Process's extra buttons
       in a narrow window, the notifications-paused pill, a huddle strip) costs the centred apps TWICE its width,
       once on each side. Then the apps centre in the space the two sides leave instead — fitTabs() sets it, and
       only when the alternative is apps squeezed to nothing (review 2026-09-27). */
    .topbar.bar-loose{grid-template-columns:auto minmax(0,1fr) auto}
    .topbar.bar-loose > .top-mid{justify-self:center}
  }

  /* ================= PHONE (≤760px) — the rails stop being columns =================
     Measured in Chrome at 390x844 before this existed: the app rail (56px) plus the tab's own nav (224px)
     left 113px of content. Nothing overflowed the viewport, it was simply crushed — the Online Orders hero
     rendered 122px wide with its Clock button wrapped over two lines, and on Future Knights the word "Today"
     came out one letter per line. That tab is the landing screen for the external team, who clock in on
     phones. Approved from docs/prototype/phone-layout/phone-shell.html on 2026-08-14.

     Every tab sizes its nav from --tab-navw but owns the ELEMENT, so this is one block with a selector list
     rather than one selector. Nothing here moves a node: each nav stays exactly where its tab renders it and
     only its positioning changes, so a tab re-render cannot lose the drawer, and the drawer cannot lose a
     tab's own listeners. Setting the two width tokens to 0 is what hands the space back — every tab's
     viewport arithmetic already reads them, so no tab needs a rule of its own. */
  .phone-nav{display:none}
  .nav-scrim{display:none}
  .phone-title{display:none}
  .phone-mark{display:none}
  @media(max-width:760px){
    :root{ --rail-w:0px; --tab-navw:0px; --tab-gut:12px; }
    body{ --rail-inset:0px }                       /* overlays span the full width once the rail is off-canvas */
    .phone-nav{display:grid;place-items:center;width:44px;height:44px;flex:none;margin-left:-4px;
      border:0;background:transparent;color:var(--white);border-radius:11px;cursor:pointer}
    .phone-nav:active{background:#161D2C}
    .phone-nav svg{width:22px;height:22px;display:block}
    .phone-nav .pn-close{display:none}
    body.navdrawer .phone-nav .pn-open{display:none}
    body.navdrawer .phone-nav .pn-close{display:block}
    /* the top bar keeps only what a phone needs: menu, where I am, search, me */
    .phone-title{display:block;flex:1;min-width:0;font-weight:700;font-size:16px;color:var(--white);
      white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
    /* the small mark before it: the brand's small-size art, 26px (mock section 2) */
    .phone-mark{display:block;width:26px;height:26px;flex:none;margin:0 2px 0 -2px}
    .phone-mark svg{width:100%;height:100%;display:block}
    .brand{display:none}                           /* the title needs the room; the small mark stands in for it */
    /* a thumb's target — and exactly where it always sat: search now lives INSIDE .top-actions (6px gaps) where it
       used to stand beside it in the bar (10px), so the empty huddle slot steps out and 10px more goes before the
       bell. Measured against live at 390px: the phone bar is pixel-for-pixel what it was. */
    #search-btn{width:44px;height:44px;margin-right:10px}
    #huddle-slot:empty{display:none}
    #search-btn svg{width:19px;height:19px}
    .navgroup{display:none !important}             /* back/forward are the phone's own gesture; Reload never showed here */
    body:not([data-nav="top"]) .top-mid{display:none}   /* empty in this layout, and it would cost the title a gap */
    #navmode-btn,#dock-btn{display:none !important}

    /* ---- the drawer: the app rail as a labelled strip, the tab's nav beneath it ---- */
    .railslot{position:fixed;top:var(--topbar-h);left:0;width:var(--phone-drawer-w);height:var(--phone-apps-h);z-index:60;
      border-right:0;border-bottom:1px solid var(--chrome-line);
      transform:translateX(-102%);transition:transform .22s ease}
    .rail{width:100%;flex-direction:row;align-items:stretch;gap:8px;padding:10px 10px;overflow-x:auto;
      overflow-y:hidden;-webkit-overflow-scrolling:touch}
    .rail .sp{display:none}                        /* the column spacer would push Settings off a row */
    .ritem{width:auto;min-width:64px;max-width:76px;height:auto;flex:none;flex-direction:column;gap:5px;
      padding:7px 7px;display:flex;align-items:center;justify-content:flex-start}
    /* the label WRAPS rather than ellipsising: "Online Orders" and "Future Knights" are the two longest tab
       names in the suite and both truncated to "Online Or…"/"Future Kni…" on one line. Two short lines read;
       a cut-off word does not. Height is auto so a one-line name does not leave a hole under it. */
    .ritem .tlbl{display:block;font-size:10.5px;line-height:1.15;white-space:normal;text-align:center;
      max-width:62px;max-height:2.3em;overflow:hidden}
    .ritem.active::before{left:8px;right:8px;top:auto;bottom:-10px;width:auto;height:3px}
    .ritem .tooltip{display:none !important}       /* there is no hover on a phone; the label is on the tile */

    /* every tab's own nav, in the same drawer, below the app strip */
    .railslot,
    .omfh-root .pnav, .cc-root .side, .fk-navwrap, .logi-nav{
      transform:translateX(-102%);transition:transform .22s ease}
    .omfh-root .pnav, .cc-root .side, .fk-navwrap, .logi-nav{
      position:fixed;top:calc(var(--topbar-h) + var(--phone-apps-h));left:0;bottom:0;
      width:var(--phone-drawer-w) !important;flex-basis:var(--phone-drawer-w) !important;
      z-index:60;overflow-y:auto}
    .fk-navwrap .fk-navpanel{border-right:0;border-radius:0}
    body.navdrawer .railslot,
    body.navdrawer .omfh-root .pnav, body.navdrawer .cc-root .side,
    body.navdrawer .fk-navwrap, body.navdrawer .logi-nav{transform:none}
    .nav-scrim{position:fixed;top:var(--topbar-h);left:0;right:0;bottom:0;z-index:55;
      background:rgba(8,10,16,.55);display:block}
    .nav-scrim[hidden]{display:none}

    /* ---- thumbs, not cursors: nothing interactive in the drawer under 44px ----
       By CONTAINER, not by row class. Each tab names its rows differently (.pitem, and three others that
       are not called what you would guess), and a list of five class names is a list that goes stale the
       first time one is renamed — silently, because a tap target that is 28px still looks fine in a
       screenshot. Two classes plus an element also outranks each tab's own two-class row rule, which is
       why the first attempt at this did nothing at all. */
    .suite-hubnav .shub{min-height:44px}
    #railslot a, #railslot button,
    .omfh-root .pnav a, .omfh-root .pnav button,
    .cc-root .side a, .cc-root .side button,
    .fk-navwrap a, .fk-navwrap button,
    .logi-nav a, .logi-nav button{min-height:44px}

    /* ---- the content, now that it has the whole screen ---- */
    .main{padding:12px}
    .omfh-root .frame{flex-direction:column}
    /* Future Knights' Today rail is a desktop companion column. Even collapsed it holds clamp(64px,17vw,272px)
       and draws the word "Today" vertically, one letter per line — the single worst thing in the 390px shots.
       The board is what a phone came for. */
    .fk-todaywrap{display:none}
    /* A filter band on a phone is wider than the phone. Scrolling as one row keeps every chip reachable and
       full-width-labelled; wrapping stacked them into a five-line block above the board. */
    .fk-bandwrap>.fk-bandrow,.fk-bandwrap>div{overflow-x:auto;-webkit-overflow-scrolling:touch}
    .fk-bandwrap .fk-fchip,.fk-bandwrap .fk-btn,.fk-bandwrap .fk-input{flex:none}
    /* NB the band's own controls are held to their width further down, AFTER the desktop rules that would
       otherwise beat this line — see "the filter bar keeps its controls readable" near the .fk-bandwrap
       block. A media query adds no specificity, so a rule up here cannot win against an equal one below. */
  }
  /* Two rules read the app strip's height — its own, and the top of the nav that sits under it. One token,
     so they cannot drift apart and leave a gap or an overlap in the drawer. */
  :root{ --phone-drawer-w:min(300px, 82vw); --phone-apps-h:90px }
  .who{display:flex;align-items:center;gap:10px}
  .who .name{font-size:13px;color:var(--white);line-height:1.2}
  .who .dept{font-size:11px;padding:2px 8px;border-radius:20px;color:#fff;font-weight:600}
  .who .avatar{width:34px;height:34px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:14px}
  .icon-btn{background:var(--panel2);border:1px solid var(--line);color:var(--dim);border-radius:8px;padding:8px 10px;font-size:13px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}
  .icon-btn:hover{color:var(--white)}
  .icon-btn svg{width:15px;height:15px;display:block}
  /* account chip + dropdown (top-right) — folds in change-password, Admin Settings (admins), sign out */
  .acct{position:relative}
  .acct-chip{display:flex;align-items:center;background:none;border:1px solid transparent;border-radius:50%;padding:0;cursor:pointer;font-family:inherit}
  .acct-chip:hover{background:var(--panel2);border-color:var(--line)}
  .acct-chip .avatar{width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:12px;flex:none;margin-left:4px}  /* the mock's 30px — 34px + 2px chip padding made a 38px disc the heaviest object in a 52px bar */
  .acct-menu{position:absolute;top:calc(100% + 8px);right:0;width:270px;display:none;flex-direction:column;background:var(--panel);border:1px solid var(--line);border-radius:12px;box-shadow:0 14px 36px rgba(0,0,0,.45);z-index:70;overflow:hidden}
  .acct-menu.open{display:flex}
  .acct-head{display:flex;gap:11px;align-items:center;padding:14px 15px;border-bottom:1px solid var(--line)}
  .acct-head .avatar{width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:15px;flex:none}
  .acct-headinfo{min-width:0}
  .acct-name{font-size:14px;color:var(--white);font-weight:600}
  .acct-sub{font-size:11.5px;color:var(--dim);margin-top:2px;word-break:break-word}
  .acct-items{display:flex;flex-direction:column;padding:6px}
  .acct-item{display:flex;align-items:center;gap:10px;width:100%;background:none;border:none;color:var(--text);font-size:13px;text-align:left;padding:9px 11px;border-radius:8px;cursor:pointer;font-family:inherit}
  .acct-item:hover{background:var(--panel2);color:var(--white)}
  .acct-item svg{width:15px;height:15px;flex:none;color:var(--dim)}
  .acct-item:hover svg{color:var(--white)}
  .acct-item.danger:hover{color:var(--danger)}
  .acct-item.danger:hover svg{color:var(--danger)}
  .main{flex:1;padding:var(--pad-3);min-width:0}  /* min-width:0 → a wide child (e.g. the FK board) scrolls INTERNALLY not wider (owner 2026-07-18) */
  /* #view is THE scroller (the shell is bounded to viewport-minus-fixed-footer, so tall content scrolls here instead of being clipped). Scoped to #view — NOT the generic .main class — because modules reuse class="main" for inner panes (e.g. #cc-main); giving those overflow would trap their sticky children. */
  /* the chrome/work seam lives here, not on the top bar — so it stops at the rail instead of cutting across it */
  #view{min-height:0;overflow-y:auto;border-top:1px solid var(--chrome-line)}
  /* suite-wide copyright footer — a slim FIXED strip pinned to the viewport bottom. Every full-height tab
     carves --foot-h from its viewport calc (and the chat host is inset by it) so nothing draws underneath. */
  .suite-foot{position:fixed;left:0;right:0;bottom:0;height:var(--foot-h);z-index:40;display:flex;align-items:center;justify-content:center;font-size:11px;color:var(--dim);border-top:1px solid var(--chrome-line);background:var(--chrome);letter-spacing:.02em;user-select:none}
  .view-head{display:flex;align-items:center;gap:10px;margin:0 0 6px}
  .view-head h2{color:var(--white);font-size:20px;margin:0}
  .view-sub{color:var(--dim);font-size:13px;margin:0 0 22px}

  /* ---------- Main Settings ---------- */
  .section{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-md);padding:18px;margin-bottom:16px;max-width:980px;box-shadow:inset 0 1px 0 rgba(255,255,255,.025)}
  .section.section-wide{max-width:none} /* the Users table is wider than a form — let it use the full panel width */
  .section h3{color:var(--white);font-size:15px;margin:0 0 4px}
  .section .hint{color:var(--dim);font-size:12px;margin:0 0 14px}
  /* A LINK IN A HINT HAD NO COLOUR AT ALL. Every "Remove key" in Admin Settings → Integrations is a bare
     <a href="#">, and neither suite.css nor chat.css contains a single bare `a` rule — so all four fell back
     to the browser's own #0000EE on the #1c1f2b panel. Measured: 1.75:1 against a 4.5 floor, which is a
     destructive control nobody can read. --accent-ink is the token for the accent used as TEXT rather than
     as a fill; see the note beside .fk-stp.cur for why the two are not the same bar. */
  .section .hint a{color:var(--accent-ink,var(--accent));text-decoration:underline;text-underline-offset:2px}
  .section .hint a:hover{text-decoration-thickness:2px}
  .section .hint a:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:3px}
  /* the last-snapshot line in Admin Settings → Backup. Green when the nightly job is doing its job, red when
     it has not run for a day and a half or reported a failure — the state the panel used to have no way to
     express at all (audit 2026-08-20). */
  .bk-state{margin-top:14px;padding:11px 13px;border-radius:var(--r-sm);font-size:12.5px;line-height:1.55;
    border:1px solid var(--line);background:var(--panel2);color:var(--dim)}
  .bk-state b{color:var(--white);font-weight:650}
  .bk-state.ok{border-color:rgba(64,160,96,.34)}
  .bk-state.bad{border-color:rgba(224,73,73,.42);background:rgba(224,73,73,.07)}
  .bk-state.bad b{color:#ffc9c9}
  .bk-state .bk-note{color:var(--dim);opacity:.8}
  table.grid{border-collapse:collapse;width:100%;font-size:13px}
  table.grid th{color:var(--dim);font-weight:700;text-align:left;padding:8px 10px;border-bottom:1px solid var(--line);font-size:10.5px;text-transform:uppercase;letter-spacing:.08em}
  table.grid td{padding:8px 10px;border-bottom:1px solid var(--line);vertical-align:middle}
  table.grid tr:last-child td{border-bottom:none}
  table.grid .ctr{text-align:center}
  table.grid input[type=checkbox]{width:16px;height:16px;accent-color:var(--accent);margin:0;cursor:pointer;vertical-align:middle}
  table.grid input[type=checkbox]:disabled{cursor:not-allowed}
  input[type=color]{width:44px;height:28px;padding:2px;margin:0;background:none;border:1px solid var(--line);border-radius:6px;cursor:pointer;vertical-align:middle}
  /* Users table can be wide (6 columns + up to 5 action buttons): keep its natural width and scroll rather than crop */
  .users-scroll{overflow-x:auto}
  .users-scroll table.grid{min-width:1060px}
  .users-scroll .btn{padding:6px 9px;font-size:11.5px} /* compact action buttons so the row fits more screens */
  /* ---- the tab-assignment matrix (wrapped in .grid-scroll): sticky header + sticky User column, zebra, grouping ---- */
  .grid-scroll{overflow:auto;max-height:432px;border:1px solid var(--line);border-radius:var(--r-sm)}
  .grid-scroll table.grid{border-collapse:separate;border-spacing:0}
  .grid-scroll th{text-align:center;padding:9px 10px;letter-spacing:.06em;position:sticky;top:0;background:var(--panel);z-index:2;white-space:nowrap;vertical-align:bottom}
  .grid-scroll th.user{text-align:left;left:0;z-index:3}
  .grid-scroll td{padding:7px 10px;text-align:center}
  .grid-scroll td.user{text-align:left;position:sticky;left:0;background:var(--panel);border-right:1px solid var(--line);min-width:188px}
  .grid-scroll tbody tr:nth-child(even) td{background:rgba(255,255,255,.018)}
  .grid-scroll tbody tr:nth-child(even) td.user{background:#1e2230}
  .grid-scroll tbody tr:hover td{background:var(--panel2)}
  .grid-scroll tbody tr.grp td{position:sticky;left:0;background:var(--bg);padding:9px 10px 5px;text-align:left}
  .grid-scroll tbody tr.adminrow td{background:rgba(0,184,217,.05)}
  .grid-scroll tbody tr.adminrow td.user{background:rgba(0,184,217,.08);box-shadow:inset 2px 0 0 var(--accent)}
  .col-label{display:block;line-height:1.2;margin-top:2px}
  .col-count{display:block;font-size:9.5px;font-weight:700;color:var(--dim);margin-top:2px;letter-spacing:0;text-transform:none}
  .grid-bulk{font-size:9px;text-transform:uppercase;letter-spacing:.06em;color:var(--dim);background:none;border:1px solid var(--line);border-radius:5px;padding:1px 6px;cursor:pointer;font-family:inherit;margin-top:4px}
  .grid-bulk:hover{color:var(--white);border-color:var(--accent)}
  .admin-pill{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--accent);border:1px solid rgba(0,184,217,.4);border-radius:10px;padding:0 6px;margin-left:6px;vertical-align:middle}
  .mx-tools{display:flex;align-items:center;gap:10px;margin-bottom:12px}
  .mx-shown{color:var(--dim);font-size:12px}
  table.grid .gridchip{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.04em;color:#fff;padding:2px 9px;border-radius:20px}
  .field{background:var(--panel2);border:1px solid var(--line);border-radius:8px;color:var(--white);padding:8px 10px;font-size:12.5px;margin:0}
  .field:focus{outline:none;border-color:var(--accent)}
  table.grid .field{width:100%}
  .btn{background:var(--panel2);border:1px solid var(--line);color:var(--text);border-radius:var(--r-sm);padding:7px 12px;font-size:12.5px;cursor:pointer;white-space:nowrap}
  .btn:hover{color:var(--white);border-color:var(--accent)}
  .btn:disabled{opacity:var(--btn-disabled-op);cursor:default}
  .btn.accent{background:var(--accent);border-color:var(--accent);color:var(--on-accent);font-weight:700}
  .btn.danger{color:var(--danger);border-color:rgba(255,107,107,.4)}
  .btn.danger:hover{color:var(--white);background:rgba(255,107,107,.14);border-color:var(--danger)}
  .badge{font-size:10.5px;padding:2px 8px;border-radius:20px;font-weight:600;white-space:nowrap}
  .badge.setup{background:rgba(245,185,20,.15);color:var(--warn);border:1px solid rgba(245,185,20,.4)}
  .badge.off{background:rgba(255,107,107,.12);color:var(--danger);border:1px solid rgba(255,107,107,.3)}
  .badge.invited{background:rgba(0,184,217,.14);color:var(--accent);border:1px solid rgba(0,184,217,.4)}
  .badge.guest{background:rgba(249,115,22,.15);color:#f97316;border:1px solid rgba(249,115,22,.4)}
  .deptchip{font-size:10.5px;color:#fff;padding:2px 8px;border-radius:20px;font-weight:600;white-space:nowrap}
  .addrow{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:12px}
  .addrow .field{flex:1;min-width:130px}
  .org-line{font-size:12.5px;color:var(--dim);line-height:1.9}
  .org-line b{color:var(--text)}
  .set-panel .f{display:flex;flex-direction:column;gap:5px;margin-bottom:14px}   /* settings field — uniform rhythm; SCOPED to Admin Settings (FK forms reuse .f 118× with their own spacing) */
  .bizgrid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:8px}
  .bizgrid .f{display:flex;flex-direction:column;gap:5px}
  .set-panel .bizgrid .f{margin-bottom:0}   /* bizgrid uses its own grid gap, so no per-field bottom margin */
  .bizgrid .f.full{grid-column:1 / -1}
  .bizgrid label{font-size:11px;color:var(--dim)}
  .bizgrid .field{width:100%}
  .bizgrid textarea.field{resize:vertical;min-height:54px;font-family:inherit;line-height:1.5;max-width:100%;overflow-wrap:anywhere;field-sizing:content;max-height:min(calc(1.5em * var(--ta-lines)), var(--ta-vh));overflow-y:auto}
  /* rows=3 on the three business-details boxes; 54px was the old floor and is kept for anything without rows */
  .bizgrid textarea.field[rows="3"]{min-height:calc(1.5em * 3 + 20px)}
  #toast{position:fixed;left:50%;bottom:26px;transform:translateX(-50%);background:#262b3a;color:var(--white);border:1px solid var(--line);border-radius:10px;padding:10px 16px;font-size:13px;opacity:0;pointer-events:none;transition:opacity .25s;z-index:2000;max-width:80vw}  /* above every modal (.avc-modal z=1000) — a feedback toast must never hide behind a dialog */
  #toast.show{opacity:1}
  #toast.ok{border-color:rgba(12,166,120,.6)}

  /* THE UNDO BAR (owner 2026-09-05, naming ClickUp: "what you delete - you have few second to bring back").
     BOTTOM LEFT, deliberately away from #toast in the centre: a toast reports something that has happened and
     goes away on its own, this one is a thing you can still ACT on, and the two must never be mistaken for
     each other. Above #toast's z-index for the same reason — it is the only bar in the suite with a deadline.
     pointer-events are ON (a toast's are off): there is a button in here to hit. */
  #undobar{position:fixed;left:22px;bottom:26px;display:none;align-items:center;gap:14px;background:#262b3a;
    color:var(--white);border:1px solid var(--line);border-radius:10px;padding:9px 10px 9px 15px;font-size:13px;
    z-index:2100;box-shadow:0 8px 26px rgba(0,0,0,.34);max-width:min(520px,90vw)}
  #undobar.show{display:flex}
  #undobar .ub-m{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  #undobar .ub-u{flex:none;display:inline-flex;align-items:center;gap:8px;background:rgba(255,255,255,.1);
    color:var(--white);border:1px solid rgba(255,255,255,.22);border-radius:7px;padding:5px 11px;font:inherit;
    font-weight:700;cursor:pointer}
  #undobar .ub-u:hover{background:rgba(255,255,255,.19)}
  #undobar .ub-k{font-size:11px;opacity:.62;font-weight:600;letter-spacing:.02em}
  /* the seconds running out, shown rather than guessed at — the bar is the only place with a deadline */
  /* Admin Settings -> Functions: the one place that lists what the software does by itself. */
  .fn-own{border:1px solid var(--line);border-radius:10px;padding:14px 16px;margin:14px 0 6px;background:var(--panel2,#20242f)}
  .fn-secs{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:10px}
  .fn-secs input{width:84px;margin-bottom:0}
  .fn-secs .fn-note{color:var(--dim);font-size:12px}
  .fn-h{margin:22px 0 8px;font-size:13px;letter-spacing:.04em;text-transform:uppercase;color:var(--dim)}
  .fn-tbl{width:100%;border-collapse:collapse}
  .fn-tbl td{padding:9px 10px;border-top:1px solid var(--line);vertical-align:top}
  .fn-tbl .fn-n{font-weight:700;white-space:nowrap;width:1%}
  .fn-tbl .fn-w{color:var(--dim);font-size:13px}
  .fn-tbl .fn-go{width:1%;white-space:nowrap;text-align:right}
  /* one width for every jump, so the column aligns on BOTH edges — right-aligned buttons of differing width
     leave a ragged left edge, which is the thing the owner dislikes about run-on tables */
  .fn-tbl .fn-go .btn{min-width:178px}
  #undobar .ub-bar{position:absolute;left:0;bottom:0;height:2px;background:var(--accent,#3aa0ff);border-radius:0 0 10px 10px}

  /* Who can open the Cash Pot — a wrapping row of names, not a column, because it is a short list of people
     rather than a form. */
  .cashpot-people{display:flex;flex-wrap:wrap;gap:8px 16px;margin-top:8px}
  .cp-person{display:inline-flex;align-items:center;gap:7px;font-size:13px;font-weight:600;cursor:pointer}
  .cp-person input{margin:0;width:15px;height:15px;cursor:pointer}   /* the global input{margin-bottom:16px} would lift the name off the box */

  /* "A new version is ready" — raised when the server reports a build this tab is not running (app.js
     noticeBuild). Bottom-LEFT deliberately: the toast owns bottom-centre and a composer's send button owns
     the bottom-right, and this must not sit over either. Below #toast's z-index so a live action's feedback
     still wins; it is an offer with no deadline, not an alert.
     In the brand since 2026-09-26 (update-splash-mock.html, frame a): night blue, the small moon, and Update in
     the aurora colours, written in the brand's navy — the aurora's light end is too pale to carry white. */
  .build-bar{position:fixed;left:18px;bottom:22px;z-index:1900;display:flex;align-items:center;gap:12px;
    padding:9px 10px 9px 12px;border-radius:12px;background:linear-gradient(180deg,rgba(21,33,84,.97),rgba(11,20,55,.97));
    border:1px solid rgba(159,198,255,.2);box-shadow:0 12px 32px rgba(0,0,0,.45),inset 0 1px 0 rgba(255,255,255,.05);
    font:500 13.5px/1.2 'Geist','Segoe UI',sans-serif;color:#F5F7FA;white-space:nowrap;max-width:86vw}
  .build-bar .build-tx{margin-right:4px}
  .build-bar button{font:inherit;font-size:13px;border-radius:8px;padding:7px 14px;cursor:pointer;margin:0}
  .build-bar .build-reload{background:linear-gradient(90deg,#4FD6C4,#5FA0FF 50%,#9E8CFF);color:#06102A;font-weight:650;border:0}
  .build-bar .build-reload:hover{filter:brightness(1.08)}
  .build-bar .build-reload:disabled{cursor:default;filter:saturate(.6)}   /* "Waiting for your upload…" */
  .build-bar .build-later{background:transparent;color:#A9B4CC;border:1px solid rgba(200,208,224,.18);font-weight:500}
  .build-bar .build-later:hover{color:#F5F7FA}
  /* the small moon, in the bar and in the note after an update */
  .build-ic{width:22px;height:22px;flex:none}
  .build-ic svg{width:100%;height:100%;display:block}
  /* On a phone the bottom is the message box's buttons, so the bar comes in at the TOP, under the header,
     where it covers nothing anybody types into. */
  @media (max-width:760px){
    .build-bar{left:12px;right:12px;bottom:auto;top:calc(var(--topbar-h) + 10px);max-width:none;white-space:normal;font-size:13px;padding:10px 10px 10px 12px}
    .build-bar .build-tx{flex:1;line-height:1.3}
  }
  /* "Moonflo is up to date" — after an Update only, for 2.5 s (app.js noteUpToDate). Under #toast's z-index, so
     a live action's feedback still wins; no pointer events, since there is nothing in it to press. */
  .build-done{position:fixed;left:50%;bottom:28px;transform:translateX(-50%);z-index:1990;display:flex;align-items:center;gap:10px;
    padding:10px 16px 10px 12px;border-radius:999px;background:rgba(11,20,55,.96);border:1px solid rgba(159,198,255,.22);
    box-shadow:0 10px 28px rgba(0,0,0,.4);font:500 13.5px/1 'Geist','Segoe UI',sans-serif;color:#F5F7FA;white-space:nowrap;
    pointer-events:none;animation:buildDoneIn .3s ease-out;transition:opacity .3s}
  .build-done .build-ic{width:20px;height:20px}
  .build-done.going{opacity:0}
  @keyframes buildDoneIn{from{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%,0)}}
  @media (prefers-reduced-motion:reduce){ .build-done{animation:none;transition:none} }

  /* ---------- modal (change password) ---------- */
  .modal-bg{position:fixed;inset:0;background:rgba(8,10,16,.6);display:none;align-items:center;justify-content:center;z-index:40;padding:20px}
  .modal-bg.open{display:flex}
  .modal{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:26px;width:100%;max-width:360px}
  .modal h3{color:var(--white);font-size:16px;margin:0 0 16px}
  .modal .actions{display:flex;gap:8px;justify-content:flex-end;margin-top:4px}
  .modal .actions .btn{padding:9px 16px}
  /* uploaded photo fills any avatar circle (else initials show) */
  .avatar{position:relative}
  .avatar img,.av-img{width:100%;height:100%;object-fit:cover;display:block;border-radius:50%}
  /* status emoji sits TOP-right so the presence dot can own the bottom-right corner, the way it does on
     every other avatar in the suite. Two badges, two corners — stacking them would hide one behind the other. */
  .av-statusmoji{position:absolute;right:-3px;top:-3px;font-size:11px;line-height:1;background:var(--panel2);border-radius:50%;padding:1px 2px;border:2px solid var(--bg)}
  /* your own presence dot (owner G1 #1) — same reading as every teammate's: green live, amber idle, grey away.
     The ring reads as a cut-out only if it matches the surface behind it, and the two places this appears sit
     on different surfaces (and the top bar changes colour again on Team Hub) — so each one names its own. */
  .av-presence{position:absolute;right:-1px;bottom:-1px;width:11px;height:11px;border-radius:50%;border:2.5px solid var(--av-ring,var(--bg));background:#8199bb}
  /* Literally chat.css's own --online/--idle, not the suite's --ok/--warn. One state must be ONE colour: the
     first build used --warn (#f5b914) here and chat's #f5b14c there, so setting yourself to Lunch turned the
     top bar one orange and the Team Hub dots another — read side by side, that looks like two states. */
  .av-presence.online{background:#4ec98a}
  .av-presence.idle{background:#f5b14c}
  .topbar{--av-ring:#0D1017}
  body[data-active-tab="chat"] .topbar{--av-ring:var(--chrome)}
  .acct-menu{--av-ring:var(--panel)}
  /* My Settings modal */
  /* MY SETTINGS: A RAIL AND ONE PANE AT A TIME (owner 2026-09-17: "it needs to be neatly organised";
     built from docs/prototype/my-settings-mock.html after the two open questions were answered — Sound keeps
     its own group, and Security names the date the password was last changed).
     It was TWO COLUMNS holding everything at once: profile, status, password, two-step and eleven
     notification controls in one scroll, with the left column running out of content near the top and
     sitting blank for the rest of the height. Each setting is now grouped by the question "when would
     somebody come here to change this?", which is what puts Quiet hours beside Pause and both a long way
     from an email address. */
  /* ONE HEIGHT, WHICHEVER GROUP IS OPEN (owner 2026-09-17: "all option should be same — now box size
     changes"). Measured before: 684 / 687 / 492 / 460 as you moved down the rail, so the modal jumped and
     the Close and Save buttons moved under the pointer between one group and the next. A HEIGHT rather than
     a max-height: the short groups keep the empty space instead of collapsing, which is the whole ask. Sized
     to the tallest group (Notifications, 687) with a little over; capped at 88vh so a short screen still
     fits, and .ms-panes already scrolls when it has to. */
  .modal.ms-modal{max-width:920px;height:min(88vh,720px);position:relative;display:flex;flex-direction:column;overflow:hidden}
  .ms-body{display:grid;grid-template-columns:196px 1fr;gap:0;min-height:0;flex:1}
  .ms-modal .hint{color:var(--dim);font-size:11.5px;line-height:1.45;margin:0}

  .ms-rail{border-right:1px solid var(--line);padding:4px 10px 10px 0;display:flex;flex-direction:column;gap:2px}
  .ms-rgrp{font-size:10px;font-weight:800;letter-spacing:.7px;color:var(--faint);padding:12px 9px 5px;text-transform:uppercase}
  .ms-rgrp:first-child{padding-top:2px}
  .ms-rtab{display:block;width:100%;text-align:left;padding:8px 10px;border:0;border-radius:8px;background:none;
    color:var(--dim);font:inherit;font-size:13px;font-weight:600;cursor:pointer}
  .ms-rtab:hover{background:var(--panel2);color:var(--text)}
  .ms-rtab.on{background:var(--accent-soft,rgba(51,202,216,.12));color:var(--text);box-shadow:inset 2px 0 0 var(--accent)}
  .ms-railfoot{margin-top:auto;padding:10px 9px 0;color:var(--faint);font-size:11px;line-height:1.5;border-top:1px solid var(--line)}

  .ms-panes{min-width:0;overflow-y:auto;padding:0 2px 0 24px}
  .ms-pane-h{margin:0 0 2px;font-size:14.5px;font-weight:800}
  .ms-pane-lede{margin:0 0 16px;color:var(--faint);font-size:12px;line-height:1.5}
  /* the first section in a pane has nothing above it to be divided from */
  .ms-pane>.ms-sec:first-of-type{margin-top:0;padding-top:0;border-top:none}
  @media (max-width:860px){
    .modal.ms-modal{max-width:440px}
    /* the rail becomes a row of chips above the pane — a 196px column on a phone leaves nothing for the pane */
    .ms-body{grid-template-columns:1fr}
    .ms-rail{flex-direction:row;flex-wrap:wrap;border-right:0;border-bottom:1px solid var(--line);padding:0 0 10px;margin-bottom:12px}
    .ms-rgrp,.ms-railfoot{display:none}
    .ms-rtab{width:auto;border:1px solid var(--line);border-radius:99px;padding:6px 12px;font-size:12.5px}
    .ms-panes{padding:0}
  }
  /* corner close ✕ (owner: "add X close red icon top right") — 34x34 at top:12/right:14, which is the size
     and placement this suite has always used for a corner close, coloured with the existing --danger token
     (matches .ms-av-rm just below in this same modal) */
  .ms-close{position:absolute;top:12px;right:14px;z-index:2;background:var(--panel2);border:1px solid var(--line);color:var(--danger);width:34px;height:34px;border-radius:9px;font-size:15px;cursor:pointer;line-height:1}
  .ms-close:hover{border-color:var(--danger);background:rgba(255,107,107,.14)}
  .ms-sub{color:var(--dim);font-size:12px;margin:-8px 0 4px}
  .ms-form .hint{color:var(--dim);font-size:11.5px}
  .ms-sec{margin-top:18px;padding-top:16px;border-top:1px solid var(--line)}
  .ms-form .ms-sec:first-of-type{margin-top:12px;padding-top:0;border-top:none}
  .ms-sec-h{font-size:11px;font-weight:800;letter-spacing:1.1px;text-transform:uppercase;color:var(--faint);margin:0 0 12px;display:flex;align-items:center}
  .ms-sec-note{margin-left:auto;font-weight:600;letter-spacing:0;text-transform:none;color:var(--dim);font-size:11px}
  .ms-av-row{display:flex;align-items:center;gap:15px;margin:0 0 12px}
  .ms-av{width:60px;height:60px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:20px;flex:none;overflow:hidden}
  .ms-form label{margin-top:11px}
  .ms-form .ms-sec-h,.ms-form .ms-av-row+label{margin-top:0}
  /* avatar cropper (pan + zoom → circular crop) — ClickUp-style, owner 2026-07-25 */
  .avc-modal{position:fixed;inset:0;background:rgba(6,10,20,.66);display:grid;place-items:center;z-index:1000;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}
  .avc-card{background:var(--panel);border:1px solid var(--line);border-radius:18px;padding:20px 20px 18px;width:320px;max-width:92vw;box-shadow:0 30px 80px rgba(0,0,0,.6);color:var(--text)}
  .avc-head{font-weight:800;font-size:15px;margin:0 0 14px;text-align:center}
  .avc-stage{position:relative;width:264px;height:264px;margin:0 auto;border-radius:14px;overflow:hidden;background:#0b0e16;cursor:grab;touch-action:none;user-select:none}
  .avc-stage.grab{cursor:grabbing}
  .avc-img{position:absolute;left:0;top:0;max-width:none;user-select:none;-webkit-user-drag:none}
  .avc-ring{position:absolute;inset:0;border-radius:50%;box-shadow:0 0 0 9999px rgba(8,11,20,.55);pointer-events:none}
  .avc-ring::after{content:'';position:absolute;inset:0;border-radius:50%;border:2px solid rgba(255,255,255,.85)}
  .avc-zoom{display:flex;align-items:center;gap:11px;margin:16px 4px 2px}
  .avc-zoom .avc-zi{color:var(--dim);font-size:17px;font-weight:800;width:14px;text-align:center;line-height:1}
  .avc-slider{flex:1;accent-color:var(--accent);cursor:pointer}
  .avc-hint{color:var(--dim);font-size:11.5px;text-align:center;margin:8px 0 0}
  /* the same crop at the sizes the suite really draws you at (G5.1) — a face that reads at 38px is often a
     smudge at 19px in an assignee stack, and this is where you find that out */
  .avc-prev{margin-top:14px;border-top:1px solid var(--line);padding-top:12px}
  .avc-pl{font-size:10px;letter-spacing:.5px;text-transform:uppercase;color:var(--faint);font-weight:800;text-align:center}
  .avc-prow{display:flex;align-items:flex-end;justify-content:center;gap:14px;margin-top:10px}
  .avc-pit{display:flex;flex-direction:column;align-items:center;gap:5px}
  .avc-pit i{display:block;border-radius:50%;background:#0b0e16}
  .avc-pit span{font-size:9.5px;color:var(--faint);font-variant-numeric:tabular-nums;white-space:nowrap}
  /* My Settings photo row: the three actions, and the line explaining why the original is kept */
  .ms-av-btns{display:flex;gap:7px;flex-wrap:wrap;align-items:center}
  .ms-av-rm{color:var(--danger);border-color:transparent}
  .ms-av-rm:hover{border-color:var(--danger)}
  .avc-actions{display:flex;gap:10px;margin-top:16px}
  .avc-btn{flex:1;height:42px;border-radius:11px;font-weight:800;font-size:14px;cursor:pointer;border:1px solid transparent}
  .avc-btn.ghost{background:transparent;border-color:var(--line);color:var(--text)}
  .avc-btn.ghost:hover{background:var(--panel2)}
  .avc-btn.primary{background:var(--accent);color:var(--on-accent)}
  .avc-btn.primary:hover{filter:brightness(1.07)}
  .ms-status-row{display:flex;gap:8px}
  .ms-status-emoji{width:52px;flex:none;position:relative;background:var(--panel2);border:1px solid var(--line);
    color:var(--text);border-radius:9px;font-size:17px;line-height:1;cursor:pointer;padding:0;
    display:grid;place-items:center;font-family:inherit}
  .ms-status-emoji:hover{border-color:var(--accent)}
  .ms-status-emoji:empty::before{content:'🙂';opacity:.45}   /* nothing set yet, but it still reads as an emoji slot */
  .ms-status-emoji::after{content:'▾';position:absolute;right:4px;bottom:2px;font-size:8px;color:var(--faint)}
  .ms-clearafter{display:flex;align-items:center;gap:9px;margin-top:10px}
  .ms-clearafter label{margin:0;font-size:12px}
  .ms-clearafter .ms-cf{width:auto;padding:6px 8px;font-size:12px}
  .ms-clearafter .ms-cf-note{font-size:11px;color:var(--faint)}
  .ms-pw{border:none;margin:0}
  .ms-2fa-row{display:flex;align-items:center;gap:12px}
  .ms-2fa-row .ms-2fa-t{flex:1;min-width:0}
  .ms-2fa-row .ms-2fa-t b{color:var(--white);font-size:12.5px}
  .ms-2fa-row .ms-2fa-t .hint{margin:2px 0 0}
  #ms-email:disabled{opacity:.7;cursor:not-allowed}
  .modules{display:flex;flex-wrap:wrap;gap:10px}
  .module{background:var(--panel);border:1px solid var(--line);border-radius:11px;padding:14px 16px;min-width:150px}
  .module .mname{color:var(--white);font-size:14px;font-weight:600;text-transform:capitalize}
  .module .mtag{color:var(--dim);font-size:11px;margin-top:3px}
  .locked-note,.empty-note{background:var(--panel);border:1px dashed var(--line);border-radius:12px;padding:26px;color:var(--dim);font-size:14px;max-width:520px}
  .locked-note b,.empty-note b{color:var(--text)}

  /* ============ The four full-bleed app tabs ============
     Each of these hosts a shell that BOUNDS ITSELF to one screen and scrolls its own content pane, so #view
     must not also be a scroller for them — and it was, by one pixel. The chrome/work seam is #view's
     `border-top`, which shortens its CONTENT box; the shells size themselves off the viewport with
     `calc(100vh/zoom - topbar - foot)`, which is #view's BORDER box. Measured at 1366x768: shell 697.7px into
     a 697px content box on Future Knights and Creatives, so `overflow-y:auto` gave both a scrollbar that
     scrolls exactly one pixel — permanent, on every load, on the two most-used tabs, and on a machine with
     classic (non-overlay) scrollbars it also steals ~15px of board width.

     `overflow:hidden` here rather than a `- 1px` in three separate calcs: the seam's width is a chrome
     decision and the shells should not have to know it, and there is nothing on these tabs that #view
     scrolling could usefully reach — every one of them has its own scroll pane. */
  #view.fk-view,#view.call-view,#view.content-view,#view.logi-view{overflow:hidden}
  #view.fk-view{padding:0;display:flex;flex-direction:column;min-height:0}
  /* Online MOG/FT tab (key 'call') — the charcoal & lime hub (public/omf.js → window.OMF, public/omf.css)
     owns the whole content area full-bleed; #view supplies zero padding, the hub supplies its own insets. */
  #view.call-view{padding:0;display:flex;flex-direction:column;min-height:0}
  /* Creatives tab (key 'content') — the berry light studio (public/content.js → window.Content, public/content.css)
     owns the whole content area full-bleed; #view supplies zero padding, .cc-root supplies its own shell. */
  #view.content-view{padding:0;display:flex;flex-direction:column;min-height:0}
  /* Logistics — a LIGHT ("white") tab (like Kaizen): theme tokens overridden on .logi-root so the suite's dark
     theme can't bleed in. Resizable left "side-tab" nav via the shared Suite.makeResizer (--logi-navw on .logi-shell). */
  #view.logi-view{padding:0;display:flex;flex-direction:column;min-height:0}
  .logi-root{--bg:#f7f9fc;--panel:#ffffff;--panel2:#eef1f6;--line:#e3e8ef;--line2:#d3dae3;--text:#2b3742;--dim:#6b7280;--white:#1e2a33;
    --accent:#f97316;--accent-soft:rgba(249,115,22,.14);  /* logistics orange — token-based accents in the embedded Inventory view pick this up; Kaizen re-scopes its own gold under .kz-root */
    flex:1 1 auto;display:flex;flex-direction:column;min-height:0;background:var(--bg);color:var(--text)}
  .logi-shell{flex:1 1 auto;display:flex;min-height:0;min-width:0;position:relative}
  .logi-shell>.fk-resizer{left:var(--logi-navw, var(--tab-navw, 224px))}
  /* --hubnav-ink: FULL rail strength, --text, not the dimmer --dim the section rows rest at. Measured against
     the other three rails, which give the trio 9.66:1 (Future Knights), 9.99:1 (Online Orders) and 13.18:1
     (Creatives) against their own backgrounds — matching this LIGHT rail's dim item ink instead put it at
     4.83:1, over AA but the odd one out of four, and this is the row carrying unread counts. --text on
     #ffffff measures 12.15:1. Set on .logi-nav because custom properties inherit DOWN: .suite-hubnav and its
     SIBLING .suite-hubsep are both children of this element (a declaration one level off is silently dead —
     that is how the Future Knights trio once rendered at 1.5:1). */
  .logi-nav{flex:0 0 var(--logi-navw, var(--tab-navw, 224px));display:flex;flex-direction:column;gap:2px;padding:14px 10px;background:var(--panel);border-right:1px solid var(--line);overflow-y:auto;--hubnav-ink:var(--text)}
  /* A column rail with `gap` ADDS to the component's own margins: 16/10 became 18/12 here, the only rail out
     of rhythm with the other three. Creatives carries the identical correction for the identical reason.
     The class is DOUBLED because the component's own rule is `.suite-hubnav.suite-hubnav` — same specificity
     as a plain descendant selector, and declared LATER in this file, so it wins a tie. Measured: the first
     attempt at `.logi-nav .suite-hubnav` changed nothing at all. */
  .logi-nav .suite-hubnav.suite-hubnav{margin-bottom:14px}
  .logi-nav .suite-hubsep.suite-hubsep{margin-bottom:8px}
  .logi-nav-head{display:flex;align-items:center;gap:7px;font-size:12px;letter-spacing:.02em;color:var(--white);font-weight:800;padding:6px 8px 12px}
  .logi-nav-item{display:flex;align-items:center;gap:9px;width:100%;padding:9px 10px;background:none;border:0;border-radius:9px;cursor:pointer;text-align:left;font-family:inherit;font-size:13.5px;font-weight:600;color:var(--dim);transition:background .14s ease,color .14s ease}
  .logi-nav-item:hover{background:var(--panel2);color:var(--text)}
  .logi-nav-item.active{position:relative;background:linear-gradient(90deg,color-mix(in srgb,var(--tab-accent) 36%,transparent),color-mix(in srgb,var(--tab-accent) 14%,transparent) 50%,transparent);color:var(--white);font-weight:750}
  .logi-nav-item.active::before{content:"";position:absolute;left:0;top:19%;height:62%;width:3px;border-radius:0 3px 3px 0;background:var(--tab-accent)}
  .logi-nav-item.active .logi-ic{color:var(--tab-accent)}
  .logi-ic{flex:none;display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;color:var(--dim)}
  .logi-ic svg{width:18px;height:18px}
  .logi-lbl{flex:1 1 auto}
  /* a channel homed to this tab: the same row, with a # tile where a section has its icon, and the unread count */
  .logi-nav-item .logi-hash{width:18px;height:18px;border-radius:5px;background:var(--panel2);font-weight:800;font-size:12px;color:var(--dim)}
  .logi-nav-item.active .logi-hash{background:color-mix(in srgb,var(--tab-accent) 22%,transparent);color:var(--tab-accent)}
  .logi-nav-item .n{flex:none;background:var(--tab-accent);color:#fff;border-radius:999px;font-size:10px;font-weight:800;padding:1px 7px;margin-left:auto}
  .logi-main{flex:1 1 auto;min-width:0;min-height:0;overflow-y:auto;background:var(--bg)}
  /* the inline chat host: the panel scrolls itself, so this pane must not (the same exclusion #fk-main makes) */
  .logi-main.sect-channel{display:flex;padding:0;overflow:hidden}
  .logi-main.sect-channel[hidden]{display:none}
  /* No padding: .kz-root supplies its own, and its masthead full-bleeds back out of it. Paired with the
     `.kz-root{margin:0;padding:24px 24px 30px}` rule in kaizen.css — the two used to cancel each other
     (24px here, -24px there), which left the sticky masthead pinned 24px below the top of the pane. */
  .logi-main.sect-kaizen{padding:0}
  /* Inventory & Suppliers is FK markup (.fk-toolbar / .fk-page) hosted inside Logistics, and it USED to bring
     its own inset — hence the 0 here. Mission Rail zeroed both of those (the inset became .fk-main's frame,
     one source so nothing can disagree with the nav gutter), and .fk-main does not exist on this page. The
     result was the whole view flush against .logi-nav on the left and the window edge on the right. This
     restores exactly what .fk-page used to give it, on the host that actually owns the page here. */
  .logi-main.sect-inventory{padding:var(--pad-2) var(--pad-3)}
  /* Embedded Inventory / Suppliers (a Future Knights component) is mostly token-driven so it adapts to the light
     theme automatically; a few styles hardcode dark/cyan — nudge those (supplier cards, once populated). */
  .logi-root .fk-sup-card{background:var(--panel)}                                               /* was a white→#20273a gradient */
  .logi-root .fk-sup-card:hover{border-color:color-mix(in srgb,var(--accent) 45%,transparent)}   /* cyan → orange */
  .logi-root .fk-sup-pill{background:var(--accent-soft);color:var(--text);border-color:color-mix(in srgb,var(--accent) 30%,transparent)}
  /* Clamp the whole FK shell to one screen (topbar ≈61px) so the LEFT NAV scrolls internally and the top
     app bar never scrolls away — on a taskbar-squeezed laptop the lower nav items used to fall below the
     fold and reaching them scrolled the entire page (owner 2026-07-18). #fk-main scrolls its own content.
     Same 100vh/zoom convention as #shell/#auth. flex:none — else the parent's column grow overrides height. */
  .fk{--fk-gut:20px;--fk-gut-y:14px;display:flex;flex:none;height:calc(100vh / var(--app-zoom) - var(--topbar-h) - var(--foot-h));min-height:0;position:relative;overflow:hidden}   /* position:relative → containing block for the sidebar resize gutter. Top bar height comes from the token, not a repeated number, so a change to the bar can't leave this behind. */
  .fk.fk-chatview{overflow:hidden}   /* channel view: the chat panel manages its own scroll (kept for clarity; the clamp now lives on .fk) */
  #fk-main{overflow-y:auto}   /* list/board/settings content scrolls INSIDE the pane, not the page (chatmount is excluded — it hosts the self-scrolling chat) */
  /* Mission Rail v2: the nav is a floating rounded PANEL, not a flush sidebar. --fk-navw now sizes the WRAP
     (panel + its 12px gutter) — which is also where the drag gutter sits, so the two can no longer disagree.
     Before this, an untouched install rendered a 244px nav with its gutter drawn at 232px. */
  /* 8px gutter, not 12 (owner 2026-08-09) — the nav panel floats, but it was floating in more dead space than
     the panel is worth; the same 8px is now the frame everywhere (.fk-main, .fk-todaywrap). */
  .fk-navwrap{flex:none;width:var(--fk-navw,224px);padding:0;min-height:0}
  /* 10px, not 14 — the owner's note: the corners should be small, not too curved. 10px is the one panel
     radius across the tab now (nav, board columns, the band, Today), so nothing reads rounder than its
     neighbour. */
  .fk-navpanel{height:100%;background:#131826;border:0;border-right:1px solid #232B3C;border-radius:0;display:flex;flex-direction:column;overflow:hidden}
  /* No border here any more: the rule moved to the foot of the trio below (owner 2026-08-13), so the name and
     the shortcuts it offers read as one block instead of the name being ruled off on its own. */
  /* 18px on the left, to put the crown's ink on the same edge as every row icon below it. Measured, the
     column had FOUR left edges within 4px of each other: the pill box at 8, the crown at 14, the section
     caption at 16 and the row icons at 18 (nav padding 8 + row padding 9 + a 1px transparent border). The eye
     tracks the left edge down a stack of seventeen rows, so a 4px wobble accumulates — and this panel is the
     one being copied to three more tabs. One edge, top to bottom. */
  .fk-nphead{display:flex;align-items:center;gap:9px;padding:13px 14px 11px 18px}
  /* the trio sits with the head, OUTSIDE #fk-nav, so it does not scroll away with the list */
  .fk-navtop{flex:none;padding:0 8px}
  .fk-nphead .crown{color:#3ECFDC;display:inline-flex;line-height:0;flex:none}
  .fk-nphead .crown svg{width:16px;height:16px;display:block} /* 16, matching .fk-mod .ic — 17 read as a size of its own */
  /* --fk-nav-ink-hi is onyx's brighter ink for emphasis; the OTHER themes never set it, so the fallback must
     land on their own --fk-nav-ink. A literal here painted this title near-white on the light theme. */
  .fk-nphead b{flex:1;min-width:0;font-size:13px;font-weight:600;color:var(--fk-nav-ink-hi,var(--fk-nav-ink,#EEF2F8));white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* .fk-npfold and .fk-addch went with the head's chevron and ＋ (owner 2026-08-13) */
  /* A COLUMN, not a plain block (owner 2026-08-15: the channel row "is shorted compared to the others").
     Measured: 101px against every other row's 205px. .fk-mod is a <button>, and a button's width:auto is
     shrink-to-fit even at display:flex — every other row escapes that only because it is a direct flex CHILD
     of .fk-nav, where align-items:stretch overrides it. Wrapping these in a div took that away, so the
     channels sat at their text width. Making the wrapper a column puts them back under the same rule the
     rest of the rail already lives by, rather than pinning a width here that .fk-mod would then disagree with. */
  .fk-npgroup{margin-top:2px;display:flex;flex-direction:column}
  /* A row is either whole or dissolved, never sliced. At 1366x768 this list overflows by 127px and its own
     overflow:auto cut "WORKSPACE" horizontally through the middle of the letters, with no scrollbar worth
     seeing and nothing to say there was more below. The bottom padding gives the last row somewhere to land
     and the mask fades the final 28px, so the cut edge becomes a gradient (owner 2026-08-13). */
  .fk-nav{flex:1;min-height:0;overflow-y:auto;padding:8px 8px 34px;display:flex;flex-direction:column;gap:0;background:none;border-right:none;
    -webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - 28px),transparent);mask-image:linear-gradient(to bottom,#000 calc(100% - 28px),transparent)}
  /* …and no fade once you have reached the end, or the last row looks permanently half-there */
  .fk-nav.at-end{-webkit-mask-image:none;mask-image:none}
  /* 34px / 13px / 600, from the mock (owner 2026-08-09) — was 32px / 12px / 500. A nav row is a target as
     well as a label, and at 12px/500 it read as small print next to the board's own type. */
  .fk-mod{display:flex;align-items:center;gap:9px;height:34px;flex:none;background:none;border:1px solid transparent;color:var(--fk-nav-ink,#B6C0D2);padding:0 9px;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;text-align:left;font-family:inherit}
  .fk-mod:hover{background:#1A2133;color:#EEF2F8}
  .fk-mod.active{background:rgba(62,207,220,.13);border-color:rgba(62,207,220,.28);color:#EEF2F8;font-weight:600;box-shadow:none}
  .fk-mod .ic{width:16px;height:16px;flex:none;color:var(--dim);display:inline-flex;align-items:center;justify-content:center}
  .fk-mod .ic svg{width:16px;height:16px}
  .fk-mod:hover .ic{color:var(--text)}        /* stage icons keep their colour via inline style; neutral icons brighten on hover */
  .fk-mod.active .ic{color:var(--accent)}      /* neutral active icon → accent; coloured stages override via inline style */
  /* The mock frames the content pane exactly like the nav panel — 12px on every side — so the two share one
     even inset instead of the pane butting flush against the panel and the top bar (owner: "does not look
     even"). This is the mock's .stage{padding:12px;gap:10px}; .fk-toolbar and .fk-page take their horizontal
     inset from HERE now, rather than each carrying their own and disagreeing. */
  /* SEAMLESS (owner 2026-08-11: "I do not like the gaps ... should not look tacky or cheap but a premium
     UI"). The 8px frame that used to sit here is gone. It was the worst width available — too wide to be a
     seam, too narrow to be space — and the canvas behind it (#0A0C11) was DARKER than both the top bar and
     the cards, so the sliver read as a crack in the page rather than as breathing room. Nothing floats now:
     the band meets the top bar, the nav meets the suite rail, and single hairlines do the separating. */
  /* ---- THE CONTENT GUTTER (--fk-gut, owner 2026-08-12: "all info stuck on the edge of screen") ----------
     Removing the frame above also removed the only inset the CONTENT had, so every page ran to the glass:
     measured at 1920, the job table's gap to the window edge was 0px on both sides and .fk-table's own
     rounded border landed on the last column of pixels — the card it is styled as could never read as one.
     This is NOT the frame returning. That frame was a gap BETWEEN panels (a dark sliver, the crack). This is
     padding INSIDE the pane: the nav still meets the rail and the band still meets the top bar, seamlessly.
     20px because that is the inset the suite top bar already uses for its own right-hand controls, so a page
     lines up with the chrome above it rather than picking its own number.
     ONE token, read by the toolbar, the band and the page — the three used to carry separate insets and
     disagree (the title row ended 22px short of the table beneath it). Anything that already owns its
     padding (the drawer, modals) must NOT add this on top.
     Declared on .fk, so it exists ONLY inside this tab, and every use names 0px as its fallback. Logistics
     hosts FK markup (.fk-toolbar/.fk-page) for Inventory & Suppliers and supplies its own inset via
     .logi-main.sect-inventory — outside .fk the gutter resolves to 0 and that host is untouched. The
     fallback is written out rather than left to an undefined variable, so this is a decision on the page
     and not an accident of scope. */
  .fk-main{flex:1;display:flex;flex-direction:column;min-width:0;min-height:0;padding:0;gap:0}
  /* The title row is one height on every screen, so the page heading lands on the same line whatever else
     shares the row with it. It used to be as tall as its tallest child, and align-items:center then re-centred
     the 28.7px H2 against that — so the heading sat at six different heights across this tab's views (10.5px
     apart) while the nav title 20px to its left never moved. Click Quotes → Customer Database and the heading
     visibly dropped while the whole left side stayed frozen.
     8px of that spread was the suite's global input{margin-bottom:16px} (index.html, near the top) landing in
     a flex row for the SIXTH time — the same trap CLAUDE.md already documents for chat and the routine. Zero
     it here as those did, rather than discovering it again on the next screen. */
  .fk-toolbar{display:flex;align-items:center;gap:10px;min-height:36px;padding:0 var(--fk-gut,0px);border-bottom:none;background:none;flex-wrap:wrap}
  .fk-toolbar input,.fk-toolbar select{margin-bottom:0}  /* no band: the mock's title row sits on the same ground as the board, inside .fk-main's frame */
  /* …and the same idea vertically: the page's first row sat hard against the top bar, so the title read as
     part of the chrome rather than as the start of the page (owner 2026-08-12, "move down slightly away from
     the top bar"). Its own token, because the horizontal gutter and this are answering different questions —
     20px sideways would be too much air above a single line of title. Only the page's OWN first row takes it;
     a nested sub-header (the Quotes bar) follows the title and must not add a second gap. */
  .fk-main > .fk-toolbar{padding-top:var(--fk-gut-y,0px);padding-bottom:12px}
  /* EVERY toolbar takes the gutter, not just the page's title row: Quotes & Payment nests a second one (the
     Open/On Hold/Won pills + search + New Quote) two levels down, and a `.fk-main > .fk-toolbar` child
     selector sailed straight past it — leaving New Quote hard against the glass under a title that had moved.
     Inside the band the gutter is the BAND's, so zero it there or the two would stack to 40px. */
  .fk-bandwrap .fk-toolbar{padding-left:0;padding-right:0}
  .fk-toolbar-tabs{border-bottom:none;padding-bottom:0}
  /* ---- THE JOB BOARD'S BAND (owner 2026-08-09, from docs/prototype/fk-theme-forest.html) ----------------
     One dark header block holding BOTH control rows, instead of two rows of buttons floating on the board's
     own ground. Every colour comes from the theme's own --fk-band* / --fk-nav-* tokens, which all five
     themes already define for the nav rail, so this needs no per-theme work and cannot leave one behind.
     The controls inside are 30px, not the 34px they were: the mock's rhythm, and it makes the two rows read
     as one instrument panel. .fk-main has a 12px pad + 10px gap, so the band pulls out to the frame edge. */
  /* It was a rounded panel in a frame (owner 2026-08-09, "ensure top hero bar also is curved") for as long
     as the frame existed. With the frame gone (2026-08-11) a floating card would leave the very sliver this
     change removes, so it is flush again — and the bottom hairline, not a gutter, is what separates it from
     the board. */
  .fk-bandwrap{flex:none;display:flex;flex-direction:column;gap:5px;padding:var(--fk-gut-y,10px) var(--fk-gut) 12px;border-radius:0;
    background:var(--fk-band,var(--panel));border:0;border-bottom:1px solid var(--fk-band-line,var(--line))}
  .fk-bandwrap .fk-toolbar{gap:8px}
  /* ONE row, always. A <select> sizes itself to its widest OPTION, not to the short label it displays —
     "Print Machine operator" made the depts filter 180px wide while showing the word "All depts" — and the
     row's contents came to 1181px inside 1139px, so + New Job dropped onto a line of its own. Capped to the
     label they actually show, and no wrapping: the controls compress before the row breaks. */
  .fk-bandwrap .fk-toolbar-filters{padding-top:0;border-bottom:none;flex-wrap:nowrap}
  .fk-bandwrap .fk-input{min-width:0}
  .fk-bandwrap #fk-q{flex:0 1 210px;width:auto}
  .fk-bandwrap select.fk-input{flex:0 1 auto;max-width:132px;text-overflow:ellipsis}
  /* the band is dark in every theme, so the ink inside it is the band's, not the board's */
  .fk-bandwrap .fk-boardsub{color:var(--fk-band-sub,var(--dim));margin-left:6px}
  /* search + every dropdown + the toggle: one chip shape, one height, one hairline */
  .fk-bandwrap .fk-input,.fk-bandwrap .fk-fchip,.fk-bandwrap .fk-btn{
    height:30px;padding:0 11px;border-radius:8px;font-size:12.5px;font-weight:600;
    border:1px solid var(--fk-band-line,var(--line2));background:var(--fk-nav-hover,var(--panel2));
    color:var(--fk-band-ink,var(--text));margin:0;line-height:28px}
  .fk-bandwrap select.fk-input{line-height:normal}
  .fk-bandwrap .fk-input::placeholder{color:var(--fk-band-sub,var(--dim));font-weight:600}
  .fk-bandwrap .fk-input:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
  /* THE FILTER BAR KEEPS ITS CONTROLS READABLE ON A PHONE.
     At 390px the search box and all four filters collapsed to a 24px chevron — five controls that looked
     identical, and no way to search. A rule to prevent it already existed in the phone block far above
     (`.fk-bandwrap .fk-input{flex:none}`), and lost: the two rules immediately overhead are more specific
     (an element name, an id) and carry no media query, so they won at every width. The two controls that
     survived — "Overdue only" and "Customise" — are the two nothing else matches, which is what named the
     cause. It has to live HERE, after them: a media query adds no specificity, so an equal rule higher up
     the file can never win.
     Scrolling sideways is the intended design — the band is already overflow-x:auto with touch momentum —
     and these controls simply have to keep their width for it to work. */
  @media(max-width:760px){
    .fk-bandwrap select.fk-input,.fk-bandwrap #fk-q{flex:none;max-width:none}
  }
  /* BETWEEN THE PHONE AND A WIDE DESK, THE FILTERS WRAP RATHER THAN CRUSH. Measured 2026-09-11 at 175% zoom
     (a 1097px window): the four selects shrank to "All cu…", "A…" and "All pay…" and the search box read
     "Search code, titl" — five controls you cannot tell apart, which is the same defect the phone rule above
     was written for, arriving from the other direction. Above 760 there is room to put them on a second line,
     so they keep their width and wrap; the phone keeps its sideways scroll, which is what a phone expects. */
  @media(min-width:761px) and (max-width:1400px){
    .fk-bandwrap .fk-toolbar-filters{flex-wrap:wrap; row-gap:8px}
    .fk-bandwrap select.fk-input,.fk-bandwrap #fk-q{flex:none; max-width:none}
  }
  .fk-bandwrap .fk-fchip{display:inline-flex;align-items:center;gap:7px;cursor:pointer;white-space:nowrap;user-select:none}
  .fk-bandwrap .fk-fchip:hover,.fk-bandwrap .fk-btn:hover{border-color:var(--fk-band-sub,var(--line2))}
  /* the checkbox itself is replaced by the chip's dot — kept in the DOM so the control, its id and its
     change handler are untouched; only the presentation moves */
  .fk-bandwrap .fk-fchip input{position:absolute;opacity:0;width:0;height:0;margin:0}
  .fk-bandwrap .fk-fchip::before{content:"";width:7px;height:7px;border-radius:50%;flex:none;
    border:1.5px solid var(--fk-band-sub,var(--dim));background:transparent}
  .fk-bandwrap .fk-fchip.on{border-color:var(--accent);color:var(--fk-band-ink,var(--white))}
  .fk-bandwrap .fk-fchip.on::before{background:var(--accent);border-color:var(--accent)}
  /* the primary action keeps the accent; Customize stays a quiet chip beside it */
  .fk-bandwrap .fk-btn.accent{background:var(--accent);border-color:transparent;color:var(--on-accent);font-size:13px;font-weight:700;padding:0 13px}
  .fk-bandwrap .fk-btn.accent:hover{filter:brightness(1.06)}
  /* the segmented tabs sit on the band too — the same translucent plate the mock uses */
  .fk-bandwrap .fk-segtabs{background:var(--fk-nav-hover,var(--panel2));border:1px solid var(--fk-band-line,var(--line));border-radius:10px;padding:3px}
  .fk-bandwrap .fk-segtab{color:var(--fk-band-sub,var(--dim));font-size:12.5px;font-weight:600;padding:5px 13px;border-radius:8px}
  .fk-bandwrap .fk-segtab.on{background:var(--fk-nav-badge,var(--panel3));color:var(--fk-band-ink,var(--white));box-shadow:inset 0 0 0 1px var(--fk-band-line,var(--line2))}
  /* the board's headline count, beside its tabs (the Forest mock's "12 active jobs · 1 overdue") — tabular
     figures so the number does not jitter as jobs move, and --dim rather than --faint because this is read */
  .fk-boardsub{color:var(--dim);font-size:12.5px;font-weight:600;margin-left:2px;font-variant-numeric:tabular-nums;white-space:nowrap}
  .fk-toolbar h2{color:var(--white);font-size:20px;margin:0;margin-right:6px}
  .fk-toolbar .grow{flex:1}
  .fk-input{background:var(--panel2);border:1px solid var(--line);border-radius:8px;color:var(--white);padding:7px 10px;font-size:12.5px;font-family:inherit}
  .fk-input:focus{outline:none;border-color:var(--accent)}
  /* THE OPEN LIST WEARS THE THEME (owner 2026-09-15: "fix the drop down white blanks unless hovering — drop down
     should remain blue if theme is blue, with white text"). A themed <select> passes its white text down to its
     options, but Chrome paints the popup's rows on its OWN default white unless the option says otherwise — so
     every row was white on white until the hover highlight showed one. Every select FK draws, in every surface
     FK themes (the shell, the order drawer, modals, the column menu), from the same two tokens the box uses. */
  #fk-shell select option,#fk-drawer-backdrop select option,#fk-modal-backdrop select option,#fk-colmenu select option{background-color:var(--panel2);color:var(--white)}
  .fk-toggle{display:inline-flex;align-items:center;gap:6px;color:var(--dim);font-size:12.5px;cursor:pointer;user-select:none}
  .fk-toggle input{accent-color:var(--accent)}

  /* ============ THE ONE GEOMETRY (Mission Rail v2) ============
     The pipeline strip and the board are TWO ROWS OF IDENTICAL FLEX TRACKS inside ONE horizontal scroller,
     so the drawing and the columns can never disagree. Tracks: a single column is flex:1 1 180px floored at
     150px; the print band is flex:2.5 1 470px floored at 468px so its two route cells never drop below
     ~225px; the archived stub is a fixed 40px; 10px gaps throughout.
     NOTE: the mock leaves .cols as a block with a height:100% scroller AND an 8px proxy bar inside it, which
     overflows by the bar's height. Made a real flex column here — same intent, without the overflow. */
  /* the frame used to inset the columns; with it gone they carry their own breathing room */
  /* the board's columns take the SAME gutter as the band above them — at 14px the first column sat 6px
     inside the band's first control, which is exactly the ragged edge the gutter exists to remove */
  .fk-cols{flex:1;min-height:0;position:relative;margin-top:0;padding:12px var(--fk-gut,14px) 0;display:flex;flex-direction:column}
  /* edge fades BOTH sides: right while more exists that way, left once scrolled — a part-shown column at
     either edge reads as continuation, never as a chip cut mid-glyph at a hard edge */
  /* Lighter since 2026-09-15 (owner: "reduce the shadow effect"). It was 76px turning SOLID at 62%, which blacked
     out most of a part-shown column — photographed with the side chat docked, the third column was unreadable.
     36px that never goes past 55% still says "more this way", and the scrollbar under the board says it too. */
  .fk-cols::before,.fk-cols::after{content:"";position:absolute;top:12px;bottom:12px;width:36px;pointer-events:none;opacity:0;transition:opacity .15s;z-index:2}
  .fk-cols::before{left:0;background:linear-gradient(to left,transparent,color-mix(in srgb,var(--bg) 55%,transparent))}
  .fk-cols::after{right:0;background:linear-gradient(to right,transparent,color-mix(in srgb,var(--bg) 55%,transparent))}
  .fk-cols.can-left::before{opacity:1}
  .fk-cols.can-scroll::after{opacity:1}
  .fk-colscroll{flex:1;min-height:0;display:flex;flex-direction:column;gap:4px;overflow-x:auto;overflow-y:hidden;padding:6px 0 2px;scrollbar-width:none}
  .fk-colscroll::-webkit-scrollbar{display:none}
  /* The native bar is hidden and replaced by an always-visible PROXY bar: Windows overlay scrollbars ignore
     ::-webkit-scrollbar styling wholesale, so a "styled" native bar simply is not there. This is what makes
     Archived Jobs discoverably reachable on a 1280 screen. */
  .fk-hbar{flex:none;height:8px;border-radius:4px;background:var(--panel3);position:relative;cursor:pointer;margin-top:4px}
  /* the thumb is the only thing that says the board scrolls — it has to clear 3:1 as non-text UI, and
     --faint measured 2.18:1 on the light themes' track */
  .fk-hbar .hthumb{position:absolute;top:1px;bottom:1px;border-radius:3px;background:var(--dim);min-width:40px}
  .fk-hbar:hover .hthumb,.fk-hbar.dragging .hthumb{background:var(--text)}
  .fk-hbar[hidden]{display:none}
  /* The print band is TWO columns, so it takes exactly TWO shares — its basis is two single columns plus the
     ONE gap between them, and it grows at twice the rate. That makes a print cell exactly as wide as any
     other column at every viewport. The mock's 2.5/470 made each print cell 25–49% wider than the rest of the
     board (owner: keep each group symmetrical).
     Was 380/320, which allowed for 20px of the band's own chrome (6px gap + 2×6px padding + 2×1px border).
     That chrome is gone (owner 2026-08-09 — see .fk-printband), so the allowance is now just the 10px gap
     every other pair of columns already has. Leaving 380 here would have made the two print cells wider than
     the rest by exactly the chrome that no longer exists. */
  /* ONE column width, stated once. Everything on the board derives from it, because the moment the number
     lives in two places they drift — which is exactly what happened when this went 180 → 230 and the print
     band kept its old hand-computed 365: In-house and Outsourcing stayed 180px wide while every column beside
     them grew, and the board went visibly ragged (owner 2026-08-13, "why are some job cards big in width and
     some skinny").
     230px, not 150: at 1366 the columns squeezed to 184 and the board truncated 10 separate strings —
     "Design & Proo…", "Delivery / Coll…" and the customer name on every card, while the job code beside it
     always got its full width. Measured, labels and card meta both fit cleanly from ~230px. Below that the
     board scrolls sideways instead of shrinking, which is what the horizontal bar and the edge fades above
     were built for and never got to do. */
  .fk-board{--fk-colw:230px; --fk-bandgap:5px}   /* --fk-bandgap must equal .fk-printband's own gap */
  /* Filtered to nothing: a banner ABOVE the columns, not a card instead of them. Sits in the board's own
     gutter so it reads as a message about the board rather than a second piece of chrome. */
  .fk-boardbanner{display:flex;align-items:center;gap:12px;margin:0 var(--fk-gut,14px) 10px;padding:10px 14px;
    background:var(--panel2);border:1px solid var(--line);border-radius:10px;font-size:13px;color:var(--text)}
  .fk-boardbanner .bb-ic{font-size:16px;flex:none;line-height:1}
  .fk-boardbanner .bb-t{flex:1;min-width:0;color:var(--dim)}
  .fk-boardbanner .bb-t b{color:var(--white);font-weight:650;margin-right:6px}
  .fk-boardbanner .fk-btn{flex:none}
  .fk-trk{flex:1 1 var(--fk-colw);min-width:var(--fk-colw)}
  /* The print band holds TWO columns, so it is two columns plus the one gap between them, and it grows at
     twice the rate. The shrink factor is not 2, because flex-shrink is weighted by BASIS: to shed exactly two
     columns' worth the factor is (2 × colw) / basis. Written as that calculation rather than as the answer,
     so changing --fk-colw above can never leave this behind again — which is the bug this comment replaces. */
  .fk-trk-print{flex:2 calc(2 * var(--fk-colw) / (2 * var(--fk-colw) + var(--fk-bandgap)))
                  calc(2 * var(--fk-colw) + var(--fk-bandgap));
                min-width:calc(2 * var(--fk-colw) + var(--fk-bandgap))}
  /* …and when one half of the band is folded to its 40px spine, the band must stop reserving room for two
     full columns — otherwise the space an empty Outsourcing gives back is never actually returned to the
     board, which is the whole reason for folding it. Written from the same tokens for the same reason. */
  .fk-trk-print.has-stub{flex:1 calc(var(--fk-colw) / (var(--fk-colw) + 40px + var(--fk-bandgap)))
                  calc(var(--fk-colw) + 40px + var(--fk-bandgap));
                min-width:calc(var(--fk-colw) + 40px + var(--fk-bandgap))}
  .fk-trk-print.both-stub{flex:none;
                min-width:calc(40px + 40px + var(--fk-bandgap));
                flex-basis:calc(40px + 40px + var(--fk-bandgap))}
  .fk-trk-stub{flex:none;width:40px;min-width:0}
  /* the board and the Today panel share one row; the board takes what is left */
  .fk-boardrow{flex:1;min-height:0;min-width:0;display:flex}
  .fk-boardrow > .fk-cols{flex:1;min-width:0}
  /* Dismissing hides the PANEL, never the wrap — the strip that brings it back lives in the wrap, so hiding
     the wrap dismissed the panel permanently (and it persisted, so a reload did not rescue it either).
     Dismissed collapses the wrap to the docked strip's width and shows the strip at ANY viewport. */
  body.fk-today-off .fk-todaywrap{width:64px}
  body.fk-today-off .fk-today{display:none}
  body.fk-today-off .fk-today-dock{display:flex;flex-direction:column;align-items:center;gap:10px;padding:13px 0 10px;height:100%;width:100%;background:var(--panel);border:1px solid var(--line);border-radius:10px;box-shadow:0 10px 28px rgba(2,4,9,.45);cursor:pointer;color:var(--text)}
  /* ================= TODAY panel — what is on fire, beside the board ================= */
  /* Progressive, not a switch. This was a flat 272px that dropped to 64px below 1485px, so a monitor 234px
     wider than a shop PC handed 206px of that gain to "Nothing due today" and left the board just 6px better
     off — measured 184px columns at 1366 against 190px at 1600, with MORE truncation at the larger size, not
     less. clamp() lets the panel take a share of what there is instead of all or nothing. */
  .fk-todaywrap{flex:none;width:clamp(64px, 17vw, 272px);padding:0;min-height:0}
  .fk-today{height:100%;background:var(--panel);border:0;border-left:1px solid var(--line);border-radius:0;display:flex;flex-direction:column;overflow:hidden}
  .fk-td-head{display:flex;align-items:center;gap:9px;padding:13px 14px 11px;border-bottom:1px solid var(--fk-nav-hline,var(--line))}
  .fk-td-head b{font-size:13px;font-weight:650;color:var(--white)}
  .fk-td-head .date{color:var(--dim);font-size:12px;font-weight:600}
  .fk-td-head .dock{margin-left:auto;color:var(--dim);background:none;border:none;cursor:pointer;width:26px;height:26px;display:grid;place-items:center;border-radius:7px;padding:0}
  .fk-td-head .dock:hover{color:var(--white);background:var(--panel3)}
  .fk-td-body{flex:1;overflow-y:auto;padding:6px 8px 10px}
  /* the board's columns all wear a persistent thin bar so nothing hides silently — this list must too */
  .fk-td-body::-webkit-scrollbar{width:6px}
  .fk-td-body::-webkit-scrollbar-thumb{background:var(--line2);border-radius:3px}
  .fk-td-body::-webkit-scrollbar-track{background:transparent}
  .fk-td-sec{padding:8px 6px 2px}
  .fk-td-sec-h{display:flex;align-items:center;gap:7px;padding:4px 2px 6px}
  .fk-td-sec-h .s-ic{width:14px;height:14px;flex:0 0 14px}
  .fk-td-sec-h b{font-size:12px;font-weight:650;flex:1;color:var(--white)}
  .fk-td-sec-h .n{min-width:20px;height:18px;padding:0 6px;border-radius:9px;background:var(--panel3);color:var(--text);font-size:11px;font-weight:700;display:grid;place-items:center}
  .fk-td-sec-h.dueh .s-ic{color:var(--danger)}
  .fk-td-sec-h.proofh .s-ic{color:var(--warn)}
  .fk-td-sec-h.thrh .s-ic{color:var(--accent)}
  .fk-td-row{display:grid;grid-template-columns:8px 1fr auto;align-items:center;column-gap:9px;padding:7px 8px;border-radius:8px;cursor:pointer;background:none;border:0;width:100%;text-align:left;font-family:inherit;color:var(--white)}
  .fk-td-row:hover{background:var(--fk-nav-hover,#1A2133)}
  .fk-td-row:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
  .fk-td-row .dot{width:8px;height:8px;border-radius:50%}
  .fk-td-row .tt{font-size:12px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-td-row .ss{grid-column:2;color:var(--dim);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-td-row .val{font-size:12px;font-weight:700;text-align:right;font-variant-numeric:tabular-nums}
  .fk-td-row .when{grid-column:3;grid-row:2;color:var(--dim);font-size:11px;font-weight:600;text-align:right}
  .fk-td-row .chase{grid-column:3;grid-row:1 / span 2;align-self:center;height:24px;padding:0 10px;margin:0;border-radius:7px;background:var(--panel2);border:1px solid var(--line2);color:var(--text);font-size:11px;font-weight:650;cursor:pointer;font-family:inherit}
  .fk-td-row .chase:hover{color:var(--white);border-color:var(--accent)}
  .fk-td-row.thr{grid-template-columns:26px 1fr auto}
  .fk-td-row.thr .fk-avatar{width:26px;height:26px;font-size:10px;grid-row:1 / span 2}
  .fk-td-row .ub{grid-column:3;grid-row:1 / span 2;align-self:center;min-width:20px;height:20px;padding:0 6px;border-radius:10px;background:var(--accent);color:var(--on-accent);font-size:11px;font-weight:800;display:grid;place-items:center}
  .fk-td-div{height:1px;background:var(--fk-nav-hline,var(--line));margin:8px 8px 2px}
  .fk-td-none{color:var(--dim);font-size:11px;padding:2px 8px 6px}
  /* Docked to a 64px strip below 1486px, so the five stage tracks always fit. Each count keeps its section's
     own icon — the three badges never rely on colour alone to tell them apart. */
  .fk-today-dock{display:none}
  .fk-today-dock .vlabel{writing-mode:vertical-rl;font-size:12px;font-weight:650;color:var(--text);letter-spacing:.03em}
  .fk-today-dock .mrow{display:flex;align-items:center;gap:4px}
  .fk-today-dock .mrow .s-ic{width:13px;height:13px;flex:0 0 13px}
  .fk-today-dock .mrow.due .s-ic{color:var(--danger)}
  .fk-today-dock .mrow.proof .s-ic{color:var(--warn)}
  .fk-today-dock .mrow.thr .s-ic{color:var(--accent)}
  /* the *-ink tokens: these three 11px numbers ARE the Today panel below 1486px — the panel itself is
     display:none there — so they are the whole surface, not a decoration. Raw --danger measured 2.42:1 and
     raw --accent 1.23:1 on Marine. The icons beside them keep the FILL colour, which is a 3:1 job, not 4.5. */
  .fk-today-dock .mini{min-width:20px;height:18px;padding:0 5px;border-radius:9px;background:var(--panel3);font-size:11px;font-weight:700;display:grid;place-items:center}
  .fk-today-dock .mini.due{color:var(--danger-ink,var(--danger))}
  .fk-today-dock .mini.proof{color:var(--warn)}
  .fk-today-dock .mini.thr{color:var(--accent-ink,var(--accent))}
  @media (max-width:1485px){
    /* Below this width the panel becomes the collapsed dock, and the dock is 64px — the clamp above must not
       reach in here, or the strip inflates to 17vw of empty (measured 230px at 1366, stealing from the very
       board the clamp was added to protect). The clamp governs the range ABOVE this breakpoint, where the
       panel is real; the dock governs below it. */
    .fk-todaywrap{width:64px}
    .fk-today{display:none}
    .fk-today-dock{display:flex;flex-direction:column;align-items:center;gap:10px;padding:13px 0 10px;height:100%;width:100%;background:var(--panel);border:1px solid var(--line);border-radius:14px;box-shadow:0 10px 28px rgba(2,4,9,.45);cursor:pointer;color:var(--text)}
    /* …but the strip is a BUTTON that says "Show the Today panel", and it could not: the rule above hides the
       panel on viewport alone, so clicking it changed a body class and nothing else. The rows it opens are
       not decoration — Chase exists on no other screen in the tab, so on a 1440 laptop (which this shop uses)
       chasing a proof was unreachable entirely. The panel opens as an OVERLAY here rather than by widening
       the wrapper, so the five stage tracks keep the room the breakpoint exists to give them. */
    body.fk-today-open .fk-todaywrap{position:relative}
    body.fk-today-open .fk-today{display:flex;position:absolute;top:0;right:0;width:272px;height:100%;z-index:9;
      box-shadow:0 18px 44px rgba(2,4,9,.55)}
    body.fk-today-open .fk-today-dock{display:none}
    body.fk-today-open .fk-td-head .dock{display:inline-flex}   /* and it closes the way it opened */
  }
  .fk-today-dock:hover{border-color:var(--line2)}
  .fk-today-dock:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
  /* above the breakpoint the panel is docked by choice, so "dismiss" is the control that undoes it; below,
     the panel is a strip by layout and the overlay above is what the strip opens */
  @media (max-width:1485px){ body:not(.fk-today-open) .fk-td-head .dock{display:none} }


  .fk-band{flex:1;min-height:0;display:flex;gap:5px}
  /* ONE ROW, TWO ROUTES. Stacking the lanes read fine only because they held 0 and 1 jobs — at real volume
     each lane took half the board height and you scrolled two short wells instead of one tall one. Finishing
     folds INTO the in-house column as its Stage 2, exactly as the order drawer already models it. */
  /* NO border, NO background, NO padding of its own (owner 2026-08-09). It used to be a bordered, recessed
     well holding two columns that each already carry a border and a radius — a box inside a box, and the only
     place on the board where that happened. It also set its own 6px gap while every other pair of columns is
     10px apart, so the two production columns sat closer together AND inset by 7px from their neighbours: the
     one group on the board with different spacing on all four sides. The band is now purely a 2-up grid on the
     same 10px rhythm as .fk-band, so In-house and Outsourcing are ordinary columns that happen to share a
     track. */
  .fk-printband{display:grid;grid-template-columns:1fr 1fr;gap:5px;min-height:0}
  /* A FOLDED HALF TAKES 40px, NOT HALF THE BAND. The band is a two-cell grid, so a spine dropped into an
     untouched `1fr` cell sat in 137px of nothing while the live column beside it was squeezed to 134 — the
     fold gave its space to empty grid, not to the work. The cell has to shrink to the spine. */
  .fk-printband.out-stub{grid-template-columns:1fr 40px}
  .fk-printband.in-stub{grid-template-columns:40px 1fr}
  .fk-printband.both-stub{grid-template-columns:40px 40px}
  .fk-printband > .fk-col{min-width:0;min-height:0}
  .fk-col{display:flex;flex-direction:column;background:var(--panel2);border:1px solid var(--line);border-radius:10px;min-height:0;position:relative}
  .fk-col-head{padding:10px 12px 8px;border-bottom:1px solid var(--line);display:block}
  .fk-col-head .r1{display:flex;align-items:center;gap:8px}
  .fk-col-head .dot{width:8px;height:8px;border-radius:50%;flex:none}
  .fk-col-head .lbl{color:var(--white);font-size:12px;font-weight:650;flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* THE NAME AS A LINK to that stage's queue (owner 2026-08-26). A <button> inherits none of the type above
     it, and `font:inherit` would take the HEAD's 13px/400 rather than the label's own — so the shorthand is
     followed by the two values it must not lose. The ellipsis moves to .txt: on the button, overflow lives on
     the flex child, and left on the button itself it would clip the chevron instead of the long name. */
  .fk-col-head .lbl.link{font:inherit;font-size:12px;font-weight:650;background:none;border:0;padding:0;
    text-align:left;cursor:pointer;display:flex;align-items:center;gap:4px;border-radius:4px}
  .fk-col-head .lbl.link .txt{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* the chevron says WHERE it goes, and only on hover — resting, the header must look exactly as it did */
  .fk-col-head .lbl.link .go{display:flex;flex:none;opacity:0;transform:translateX(-3px);transition:opacity .12s,transform .12s}
  .fk-col-head .lbl.link .go .s-ic{width:12px;height:12px;flex:0 0 12px}
  .fk-col-head .lbl.link:hover,.fk-col-head .lbl.link:focus-visible{color:var(--accent-ink,var(--accent))}
  .fk-col-head .lbl.link:hover .txt{text-decoration:underline;text-underline-offset:2px}
  .fk-col-head .lbl.link:hover .go,.fk-col-head .lbl.link:focus-visible .go{opacity:1;transform:none}
  .fk-col-head .n{min-width:20px;height:18px;padding:0 6px;border-radius:9px;background:var(--panel3);color:var(--text);font-size:11px;font-weight:700;display:grid;place-items:center;flex:none}
  .fk-col-head .kebab{flex:none;color:var(--dim);cursor:pointer;border:none;background:none;width:26px;height:26px;display:grid;place-items:center;border-radius:5px;padding:0;font-size:15px;line-height:1} /* was 17x18 and clicked all day (owner 2026-09-17) */
  .fk-col-head .kebab:hover{color:var(--white);background:var(--panel3)}
  /* Fold this column to a strip. It sits ON the stage dot rather than beside it: a column is only ~156px at
     1600, and an extra in-flow control cost every header 18px of NAME — enough that both print columns
     truncated to "Prin…". Hovering swaps the dot for the chevron, which costs nothing. */
  .fk-col-head .r1{position:relative}
  /* THE FOLD ARROW SITS IN THE ROW, NOT ON THE DOT (owner 2026-09-06: "the arrow to collaps should not hide
     behind the category colour dot"). It was position:absolute at left:-3px, which is exactly where the 8px
     stage dot is — measured on the running board, dot x310–318 against arrow x307–325, an 8×8px overlap, so
     the arrow covered the dot completely the moment it appeared. It was also opacity:0 until the column was
     hovered, which is the same undiscoverable-control problem as the basket's ✎ earlier the same day: a
     control nobody can see is a control nobody uses, and it does not exist at all on a touch screen.
     In normal flow it costs ~26px of the column name, which is why it was overlaid in the first place. That
     is the right trade now the button is the only way to fold two of the columns. */
  /* 18px was under the 24px anyone can reliably hit, and this one folds a whole board column (2026-09-17) */
  .fk-col-head .foldc{flex:none;width:26px;height:26px;display:grid;place-items:center;border:0;
    background:none;color:var(--faint);border-radius:5px;cursor:pointer;padding:0;transition:color .12s,background .12s}
  .fk-col:hover .fk-col-head .foldc{color:var(--dim)}
  .fk-col-head .foldc:hover,.fk-col-head .foldc:focus-visible{color:var(--white);background:var(--panel3)}
  .fk-col-head .foldc .s-ic{width:12px;height:12px;flex:0 0 12px;transform:rotate(180deg)}   /* points the way the column folds */
  /* who owns the stage — read once here, never per card */
  .fk-col-head .owner{display:block;margin-top:5px;color:var(--dim);font-size:11px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-col-head .owner .s-ic{width:12px;height:12px;flex:0 0 12px;vertical-align:-2px;margin-right:5px}
  /* narrow boards fold the owner line into the header's title tooltip, so the stage name renders whole */
  @media (max-width:1400px){ .fk-col-head .owner{display:none} }
  .fk-printband .fk-col-head .owner{font-size:10.5px}   /* half-width cells fold sooner — they carry two stage names */
  .fk-colmenu{position:fixed;z-index:var(--z-dropdown,60);min-width:190px;background:var(--panel);border:1px solid var(--line);border-radius:10px;box-shadow:0 12px 30px rgba(0,0,0,.5);padding:5px;display:none}
  .fk-colmenu.open{display:block}
  .fk-colmenu button{display:flex;align-items:center;gap:8px;width:100%;text-align:left;background:transparent;border:none;color:var(--white);font-size:12.5px;padding:8px 10px;border-radius:7px;cursor:pointer}
  .fk-colmenu button:hover{background:var(--panel2)}
  .fk-colmenu button.danger{color:var(--danger)}
  /* a stage move must not sit flush against the bin — one hairline between groups of unlike things.
     The forward items take no colour of their own: in this menu colour means DESTRUCTIVE (the red bin), and
     a third ink would spend that signal. The arrow/tick icon and this rule are what group them. */
  .fk-colmenu .fk-cm-sep{height:1px;background:var(--line);margin:5px 4px}
  /* who the menu is about, so a ⋯ opened from a long list still says which row it belongs to */
  .fk-colmenu .fk-cm-head{font-size:9.5px;font-weight:700;letter-spacing:.7px;text-transform:uppercase;
    color:var(--faint);padding:6px 10px 4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:260px}
  .fk-colmenu .fk-cm-g{width:16px;display:inline-block;text-align:center;flex:none}
  /* THE ⋯ ITSELF. Square, so a column of them lines up rather than wandering with each row's label width. */
  .fk-kebab{width:27px;padding:0;justify-content:center;font-size:15px;letter-spacing:1px}
  /* THE CUSTOMER, promoted (owner 2026-09-06: "the customer name/ Business needs to be more clear
     (preferably highlighted in a different colour)", then "cyan is fine for black layout but white theme it
     should be Actual blue so its visible").
     --accent-ink is that answer and it already exists: FK defines it per theme for precisely this job — the
     accent used as TEXT rather than as a fill — so this is cyan on the dark themes, #0a5570 on Light Box,
     navy on Marine and green on Forest, without a single new colour being chosen. Measured 9.4:1 on the dark
     panel and 8.2:1 on the light one. */
  .fk-cust-nm{color:var(--accent-ink,var(--accent));font-weight:700;font-size:13px}
  .fk-cust-co{color:var(--dim);font-size:11px;font-weight:400}
  .fk-cust-job{color:var(--text);font-size:12px;margin-top:2px}
  .fk-col-body{flex:1;overflow-y:auto;padding:8px;display:flex;flex-direction:column;gap:8px;min-height:60px}
  /* a persistent thin bar, so an overflowing column is never a secret */
  .fk-col-body::-webkit-scrollbar{width:6px}
  .fk-col-body::-webkit-scrollbar-thumb{background:var(--line2);border-radius:3px}
  .fk-col-body::-webkit-scrollbar-track{background:transparent}
  .fk-col-body.dragover{background:rgba(62,207,220,.06);outline:2px dashed rgba(62,207,220,.35);outline-offset:-4px;border-radius:8px}
  .fk-col-empty{color:var(--dim);font-size:11.5px;text-align:center;padding:14px 6px;opacity:.6}
  /* The dashed .fk-colempty panel that used to sit in an empty board column is gone (owner 2026-08-26) —
     the column header's count already said 0, and the panel said it again, larger. Nothing draws it now.
     `.fk-col-empty` above is a DIFFERENT rule and is still in use: it is the plain "Loading…" line in the
     FK nav and the reports page. The two names are one hyphen apart, so read carefully before reviving either. */
  /* the collapsed Archived stub */
  /* `position:relative` so the spine can carry a full-height drop body behind its label (see .stubbody below) */
  .fk-col.collapsed{flex:none;width:40px;min-width:0;align-items:center;padding:10px 0;gap:10px;cursor:pointer;position:relative}
  .fk-col.collapsed:hover{border-color:var(--line2)}
  .fk-col.collapsed .vlabel{writing-mode:vertical-rl;font-size:12px;font-weight:650;color:var(--text);letter-spacing:.03em}
  /* The stub's .dot and .n are DIRECT children of .fk-col.collapsed, not of .fk-col-head — so they matched
     neither of the rules at 818/820 and got nothing. The dot computed to 0x0 with square corners (the stage
     colour the stub is supposed to keep was simply not drawn) and the count fell back to bare 13px text
     inheriting the SUITE root ink rather than the FK theme's: 1.42:1 on the light themes. Archived renders
     folded by DEFAULT, so this was the first thing on the board on a fresh browser. */
  /* The spine's drop area: the whole spine, behind its label, so there is something real to aim at. It sits
     under the dot/label/count rather than beside them — those stay visible and the body takes the rest.
     `position:relative` for it belongs on the .fk-col.collapsed rule ABOVE, not on a second one down here:
     a repeated top-level selector is the collision test/css-duplicate-selectors.test.cjs fails the build on,
     and it fails it because the later rule silently wins and jsdom cannot see a cascade. */
  .fk-col.collapsed .fk-col-body.stubbody{position:absolute;inset:0;padding:0;margin:0;background:none;
    border:0;min-height:40px;pointer-events:auto;z-index:0}
  .fk-col.collapsed > .dot,.fk-col.collapsed > .vlabel,.fk-col.collapsed > .n,.fk-col.collapsed > .chev{position:relative;z-index:1}
  .fk-col.collapsed .dot{width:8px;height:8px;border-radius:50%;flex:none}
  .fk-col.collapsed .n{min-width:20px;height:18px;padding:0 6px;border-radius:9px;background:var(--panel3);color:var(--text);font-size:11px;font-weight:700;display:grid;place-items:center;flex:none}
  .fk-col.collapsed .chev{width:14px;height:14px;color:var(--dim);transform:rotate(90deg);margin-top:auto}
  .fk-col.collapsed:hover .chev{color:var(--white)}

  /* cursor:POINTER, not grab (owner 2026-08-26: "it shows they are clickable"). A card both opens and drags,
     and grab advertised only the second of those — the click is what people actually do. :active below still
     turns it to a grabbing hand the moment a drag starts, so nothing is lost. */
  .fk-card{position:relative;background:var(--panel3);border:1px solid var(--line2);border-radius:var(--r-card,10px);padding:10px 11px 9px;cursor:pointer;display:flex;flex-direction:column;gap:7px;transition:transform .12s,box-shadow .12s,border-color .12s}
  /* A HOVER THAT CAN ACTUALLY BE SEEN. The old rule was already a lift — translateY(-1px) and a shadow — and
     rendered as nothing: rgba(2,4,9,.18) is near-black at 18% against a near-black column, and 1px is below
     noticing. Photographed on the real board, the only visible change was the border colour.
     No accent glow: the border is already turning accent, so a coloured halo over it is decoration. What was
     missing is the shadow's WEIGHT. --fk-cardsh carries it, because pure black at half opacity is right on
     Onyx and a bruise on the three light themes, which set their own. */
  .fk-card:hover{border-color:var(--accent);box-shadow:0 8px 22px var(--fk-cardsh,rgba(0,0,0,.5));transform:translateY(-3px) scale(1.015)}
  .fk-card:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
  /* Per-card ⋯ (G7 #2.2). Sits over the card's top-right corner rather than in the flow, so it costs the
     card no height; the title reserves room for it so a long product name never runs underneath. */
  .fk-cardkebab{position:absolute;top:4px;right:4px;width:24px;height:24px;display:flex;align-items:center;justify-content:center;
    background:transparent;border:none;border-radius:6px;color:var(--dim);font-size:15px;line-height:1;cursor:pointer;padding:0;margin:0;opacity:0;transition:opacity .12s,background .12s}
  .fk-card:hover .fk-cardkebab,.fk-cardkebab:focus-visible{opacity:1}
  .fk-cardkebab:hover{background:var(--panel);color:var(--white)}
  .fk-colmenu button.off{opacity:.45}
  /* Suite.icon() output. Sized once here so a tab never picks its own; inherits currentColor, which is the
     whole point of moving off emoji — a bin on a danger button is red because the label is. */
  .s-ic{width:15px;height:15px;flex:0 0 15px;display:inline-block;vertical-align:-2.5px}
  /* The file-type badge (Suite.fileIcon). Deliberately NOT sized here the way .s-ic is: it carries a word,
     and the size it needs depends on the slot it lands in, so every call site passes its own. This rule is
     only the things that are true everywhere. One global class name, owned by this one feature — the safe
     version of the unscoped rules in this file, not another `.who` waiting to collide. */
  .s-fic{display:inline-block;vertical-align:-4px;flex:none}
  .fk-card:active{cursor:grabbing}
  .fk-card.dragging{opacity:.4;cursor:grabbing}
  /* one line, always — the JS trims the spec off the title, and this catches a hand-typed title with no dash
   in it so a long walk-in description can still never grow the card (G7 #2) */
  /* the artwork strip LEADS the card: 36px, rounded, full card width so it never steals title room in a
     150px column. A print shop recognises a job by its artwork before its code. */
  .fk-card .thumb{height:36px;flex:none;border-radius:7px;overflow:hidden;display:block;width:100%;object-fit:cover;border:1px solid var(--line2);background:var(--panel2)}
  /* --text, not --dim: this is a STATE ("Awaiting artwork" / "Artwork attached"), not a caption, and --dim
     on the light themes' card measured 4.08:1 — under AA for 11px */
  .fk-card .thumb.none{border-style:dashed;border-color:var(--line2);background:none;display:flex;align-items:center;justify-content:center;gap:6px;color:var(--text);font-size:11px;font-weight:600}
  .fk-card .thumb.none .s-ic{width:13px;height:13px;flex:0 0 13px}
  .fk-card .r-title{display:flex;align-items:flex-start;gap:8px}
  .fk-card .t{color:var(--white);font-size:13px;font-weight:600;line-height:1.3;flex:1;min-width:0;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;padding-right:22px}
  .fk-card .thread{display:flex;align-items:center;gap:4px;color:var(--dim);font-size:11px;font-weight:600;flex:none;padding-top:1px}
  .fk-card .thread .s-ic{width:13px;height:13px;flex:0 0 13px}
  .fk-card .thread.unread{color:var(--accent)}
  .fk-card .r-cust{display:flex;align-items:baseline;gap:6px;min-width:0;padding-right:22px} /* clears the ⋯ at the top-right, as the title used to */
  /* customer · product on ONE line (owner 2026-09-15). The name never shrinks below its own width — a short one
     read "B." beside a long product in the mock — and stops at 55% so the product always shows; the product
     takes what is left and shortens with an ellipsis. */
  .fk-card .r-cust b{color:var(--cust-ink,#7CC4FF);font-size:13.5px;font-weight:700;flex:0 0 auto;max-width:55%;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-card .r-cust .sep{font-style:normal;color:var(--dim);flex:none}
  .fk-card .r-cust .t{display:block;flex:1 1 auto;padding-right:0;white-space:nowrap;text-overflow:ellipsis;-webkit-line-clamp:unset}
  .fk-card .r-meta{display:flex;align-items:baseline;gap:8px}
  .fk-card .c{flex:1;color:var(--text);font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-card .code{color:var(--dim);font-size:11px;font-weight:600;letter-spacing:.02em}
  .fk-card .meta{display:flex;flex-wrap:wrap;gap:4px}
  .fk-card .amt{margin-left:auto;color:var(--white);font-size:13px;font-weight:700;letter-spacing:.01em;font-variant-numeric:tabular-nums}
  .fk-chip{display:inline-flex;align-items:center;gap:4px;height:20px;padding:0 7px;border-radius:var(--r-chip,6px);font-size:11px;font-weight:650;white-space:nowrap;background:var(--panel2);color:var(--text);border:1px solid transparent;max-width:100%;overflow:hidden}
  .fk-chip .s-ic{width:11px;height:11px;flex:0 0 11px}
  /* A chip that is allowed to wrap. The base chip is one fixed-height line with overflow:hidden, which is
     right for "✓ Paid" and wrong for a sentence — a board card is ~190px wide and "⚠ Not paid · Pay on
     collection" came out as "⚠ Not paid · Pay on collecti". Truncating THAT sentence is worse than not
     showing it, so this one wraps instead of being cut. */
  .fk-chip.wrap{white-space:normal;height:auto;min-height:20px;line-height:1.28;padding:3px 7px;text-align:left}
  /* The mock defines five looks, not thirteen: neutral · danger · ok · warn · route. The live class names all
     survive (jobCard and the four themes reference them) — they just map onto those five. */
  .fk-chip.due-late,.fk-chip.dep-no,.fk-chip.paid-no{background:rgba(255,138,133,.12);color:var(--danger);border-color:rgba(255,138,133,.3)}
  .fk-chip.due-soon,.fk-chip.proof-wait,.fk-chip.paid-part{background:rgba(245,184,78,.11);color:var(--warn)}
  .fk-chip.proof-ok,.fk-chip.paid-ok{background:rgba(90,221,154,.11);color:var(--ok)}
  .fk-chip.due-ok,.fk-chip.proof-no{background:var(--panel2);color:var(--text)}
  .fk-chip.mode{background:rgba(169,139,250,.13);color:#C4AEFF}          /* Outsourced — the route's own violet */
  .fk-chip.mode-in{background:rgba(242,127,184,.13);color:#F7A8CD}       /* In-house — the route's own pink */
  .fk-chip.poc{background:rgba(62,207,220,.13);color:var(--accent)}
  /* CANCEL ORDER (owner 2026-10-06; docs/prototype/cancel-order/): the dialog, the red banner, the amber line, the struck-through total. Every class is .fk-co-*; the dialog's
     inputs are zeroed because the global input{margin-bottom:16px} (top of this file) would lift a radio off the text beside it. */
  .fk-co-btn{display:inline-flex;align-items:center;gap:6px}
  .fk-co-btn svg,.fk-co-dlg h3 svg,.fk-co-ban svg{flex:0 0 auto;width:15px;height:15px}
  .fk-co-dlg h3{display:flex;align-items:center;gap:9px}
  .fk-co-dlg h3 svg{width:20px;height:20px;color:var(--danger-ink,var(--danger))}
  /* .fk-modal label{display:block} and .fk-modal input{width:100%;padding:9px 11px} are MORE specific than a bare .fk-co-* class, so these carry the .fk-modal prefix (the same trap .fk-gb-switch records
     below): without it the label stopped being a flex row and the radio sat above its words — found by photographing it, not by a test. */
  .fk-modal .fk-co-dlg input{margin:0}
  .fk-modal .fk-co-opt{display:flex;align-items:center;gap:10px;margin:0 0 8px;padding:10px 12px;border:1px solid var(--line);border-radius:8px;font-size:13px;color:var(--text);cursor:pointer}
  .fk-modal .fk-co-opt:has(input:checked){border-color:var(--accent);background:rgba(62,207,220,.06)}
  .fk-modal .fk-co-opt input{width:16px;height:16px;flex:none;margin:0;padding:0;accent-color:var(--accent)}
  .fk-co-nb{white-space:nowrap}
  .fk-co-warn{margin:10px 0 2px;padding:10px 12px;border:1px solid rgba(245,184,78,.45);background:rgba(245,184,78,.09);border-radius:8px;font-size:12.5px;line-height:1.45;color:var(--warn-ink,var(--warn))}
  .fk-co-warn b{color:var(--white)}
  .fk-co-ban{display:flex;align-items:flex-start;gap:10px;padding:10px 14px;border:1px solid rgba(255,138,133,.38);background:rgba(255,138,133,.09);border-radius:8px;font-size:13px;line-height:1.5;color:var(--text)}
  .fk-co-ban svg{width:18px;height:18px;margin-top:2px;color:var(--danger-ink,var(--danger))}
  .fk-co-ban b{color:var(--danger-ink,var(--danger))}
  .fk-co-top{margin:14px 0 4px}
  .fk-pjv .fk-co-ban{width:100%}
  .fk-tl-node .tl-state.tl-cancelled{color:var(--danger-ink,var(--danger));font-weight:650}
  .fk-co-was{color:var(--dim);font-weight:650;text-decoration:line-through}
  /* THE TWO-STAGE INDICATOR on an in-house card: Stage 1 Print hands to Stage 2 Finishing.
     Filled = done · ringed = where the job is now · hollow = still to come. This is what lets Finishing stop
     being a column of its own without the stage becoming invisible. */
  /* NB .fk-cstage, not .fk-pstage — that name belongs to the Prospects pipeline accordion further down.
     Disjoint properties do not override, they COMBINE: this rule's display:flex + align-items:center was
     laying every expanded Prospects section BESIDE its header instead of under it. */
  .fk-cstage{display:flex;align-items:center;gap:0;margin-top:2px}
  .fk-cstage .st{display:flex;align-items:center;gap:4px;font-size:10px;font-weight:650;color:var(--dim);white-space:nowrap;min-width:0}
  .fk-cstage .st b{font-weight:650;overflow:hidden;text-overflow:ellipsis}
  /* --ring-todo, and NOT --line2. This is the "still to come" state — the only thing distinguishing it from
     the filled done dot and the ringed current one — so it owes 3:1 as a non-text indicator, which is a
     harder bar than a hairline. The mock's literal #3A4560 clears it on a white card (8.32:1) and fails on
     the mock's own dark one (1.59:1 on Onyx, the DEFAULT theme; 1.93:1 on Blackout). --line2 would fail the
     other way round — it is deliberately faint on the light themes. Hence a token of its own, per theme. */
  .fk-cstage .sd{width:11px;height:11px;border-radius:50%;flex:none;border:1.5px solid var(--ring-todo,#3A4560);box-sizing:border-box}
  .fk-cstage .st.done .sd{background:var(--ok);border-color:var(--ok)}
  .fk-cstage .st.done{color:var(--text)}
  /* --stage-cur, not the literal #F0875C: that is the mock's orange on the mock's dark card, and it measured
     2.20:1 as TEXT on the two light-work-area themes. The token keeps the mock's value where the mock's
     ground is, and deepens it where the ground is white. */
  .fk-cstage .st.cur .sd{border-color:var(--stage-cur,#F0875C);background:transparent;box-shadow:0 0 0 2.5px color-mix(in srgb,var(--stage-cur,#F0875C) 22%,transparent)}
  .fk-cstage .st.cur{color:var(--stage-cur,#F0875C)}
  .fk-cstage .lnk{flex:1;height:1.5px;background:var(--line2);margin:0 5px;min-width:8px}
  .fk-cstage .st.done + .lnk{background:var(--ok);opacity:.5}
  /* THE PROOF STATE STRIP on a design card. A proof has a VERSION, a HOLDER and an AGE, and a designer needs
     all three without opening the job — one chip can only say one of them. Colour-keyed by WHO IS BLOCKING:
     amber = with the customer (we wait) · red = back with us (we act) · green = approved.
     The state wraps rather than ellipsizes: "Changes re…" is not a state you can act on. */
  .fk-pstate{display:grid;grid-template-columns:auto 1fr;align-items:center;gap:6px;min-height:24px;padding:3px 7px;border-radius:6px;background:var(--panel2);border:1px solid var(--line2);font-size:11px;font-weight:650}
  .fk-pstate .pv{font-size:10.5px;font-weight:700;letter-spacing:.02em;padding:1px 5px;border-radius:4px;background:var(--line2);color:var(--text);font-variant-numeric:tabular-nums}
  .fk-pstate .ps{color:var(--text);white-space:normal;line-height:1.25;min-width:0}
  .fk-pstate .ps em{font-style:normal;color:var(--dim);font-weight:600}
  /* the *-ink tokens, not the raw fills: on this strip the colour IS the signal AND it is 11px text sitting
     on a pale tint of itself, which is the hardest contrast case in the sheet. Raw --danger measured 2.30:1
     and raw --ok 2.63:1 on the light themes; the .pv chip (10.5px on a .18 tint) failed on all four. */
  .fk-pstate.cust{background:rgba(245,184,78,.07);border-color:rgba(245,184,78,.30)}
  .fk-pstate.cust .pv{background:rgba(245,184,78,.18);color:var(--warn-ink,var(--warn))}
  .fk-pstate.cust .ps{color:var(--warn-ink,var(--warn))}
  .fk-pstate.us{background:rgba(255,138,133,.07);border-color:rgba(255,138,133,.32)}
  .fk-pstate.us .pv{background:rgba(255,138,133,.18);color:var(--danger-ink,var(--danger))}
  .fk-pstate.us .ps{color:var(--danger-ink,var(--danger))}
  .fk-pstate.done{background:rgba(90,221,154,.07);border-color:rgba(90,221,154,.28)}
  .fk-pstate.done .pv{background:rgba(90,221,154,.18);color:var(--ok-ink,var(--ok))}
  .fk-pstate.done .ps{color:var(--ok-ink,var(--ok))}
  /* Customize view (owner 2026-07-31): card footer holds amount + assignee on their own aligned row (was mixed
     into the chip wrap); card-size variants + the ⚙ Customize panel. Field visibility is built in jobCard(). */
  /* THE CARD'S FACTS, ALIGNED (owner 2026-08-23, option C of the card redesign mock). A label column that
     shrinks to its content and a value column that fills the rest, right-aligned, so the values line up down
     a whole column of cards. Nothing wraps: every value is written short enough to sit on one line, and
     `white-space:nowrap` makes a long one clip rather than push the card taller than its neighbours. */
  .fk-card .fk-facts{display:grid;grid-template-columns:auto 1fr;gap:3px 10px;margin:0 0 8px;font-size:11.5px}
  .fk-card .fk-facts dt{color:var(--faint);font-weight:600;white-space:nowrap}
  .fk-card .fk-facts dd{margin:0;text-align:right;color:var(--text);font-weight:650;
    font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* The -ink tokens, for the reason the light-theme block at the foot of this file gives: --ok and --danger
     are FILLS as well as text, so they cannot be darkened globally, and the text-only job has its own token.
     These three rules were the "and were missed" the comment there names. Measured on the running board,
     2026-08-26, on all three light themes: "In full" 2.72:1 and "Unpaid" 2.42:1 against the card — both under
     AA for 11.5px. (dd.warn already passed at 4.52:1, since --warn itself was re-pointed; it joins them so a
     row and the amount below it are never two shades of the same answer.) Onyx is unaffected on warn and
     gains the matching green/red its foot now uses. */
  .fk-card .fk-facts dd.ok{color:var(--ok-ink,var(--ok))} .fk-card .fk-facts dd.warn{color:var(--warn-ink,var(--warn))} .fk-card .fk-facts dd.bad{color:var(--danger-ink,var(--danger))}
  .fk-card .fk-cardfoot{display:flex;align-items:center;gap:8px;margin-top:0;padding-top:7px;border-top:1px solid var(--line2)}
  .fk-card .fk-cardfoot .amt{margin-left:auto;color:var(--white);font-size:13px;font-weight:700;letter-spacing:.01em;font-variant-numeric:tabular-nums}
  /* THE AMOUNT IN THE COLOUR OF ITS PAYMENT STATE (owner 2026-08-26). fk.js decides WHICH class from the one
     paymentState() the Paid row above also reads; these three decide what each one looks like.
     The -ink tokens, not the raw fills: three of the four FK themes have a white card, and raw --ok (#0ca678)
     measures 3.0:1 on it — under AA for 13px bold. --ok-ink is #0a6045 there and #78EBB8 on Onyx, and is
     already what the rest of FK uses wherever these colours are TEXT (.fk-clk.done, .fk-ptag.ok, .fk-pstate). */
  .fk-card .fk-cardfoot .amt.paid{color:var(--ok-ink,var(--ok))}
  .fk-card .fk-cardfoot .amt.part{color:var(--warn-ink,var(--warn))}
  .fk-card .fk-cardfoot .amt.owed{color:var(--danger-ink,var(--danger))}
  /* …and what a PART-PAID card says is LEFT TO PAY. Only part-paid: on an unpaid or a pay-on-collection job
     the total already IS the balance.
     RED, not amber (owner 2026-08-26). That single colour choice is what gives the card's money one rule
     instead of four: amber is what came IN (the Paid row's figure), red is what is still OWED — which is why
     an unpaid and a pay-on-collection total are red too, and why a settled one is green.
     ITS OWN ROW, not a second line inside the foot's right-hand cell. Nested there it competed with "Order
     with" for the foot's 186px and won: an ordinary £2,000 order with its 50% deposit taken prints "£1,000.00
     left to pay" (107px) and left 50px for a label wanting 56, so the card read "Order w…". A full-width row
     competes with nothing, and looks the same — right-aligned, directly under the total. */
  .fk-card .fk-carddue{text-align:right;margin-top:1px;font-size:10.5px;font-weight:650;line-height:1.2;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
    color:var(--danger-ink,var(--danger));font-variant-numeric:tabular-nums}
  /* assignee reads left, money right — the mock's foot is one aligned row, not a chip wrap */
  .fk-card .fk-cardfoot .asg{display:flex;align-items:center;gap:6px;color:var(--text);font-size:11px;font-weight:600;flex:1;min-width:0}
  /* "Order with" then the face (owner 2026-08-23). The label is what makes a photo on a card mean something
     — an avatar on its own is decoration until it says what it is answering. It carries the ellipsis rather
     than the picture, which the old `> span:last-child` rule would now be clipping instead. */
  .fk-card .fk-cardfoot .asg .asg-l{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--dim);font-weight:600}
  /* …and since 2026-09-01 the NAME replaces that label, because the face plus a name says what "Order with"
     was there to say and gives back the 56px those two words cost. `min-width:0` so it is the half that
     truncates, `padding-right:1px` because without it the ellipsis lands on a sub-pixel and a name that
     just fits is cut anyway [[lmc-one-line-row]]. The amount never shrinks: a clipped price is worse than
     a clipped name. Measured at the real 210px card — "Mohammed F. · 10d" fits, the full name does not. */
  .fk-card .fk-cardfoot .asg .asg-n{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
    min-width:0;padding-right:1px;color:var(--dim);font-weight:600}
  .fk-card .fk-cardfoot .asg .asg-age{color:var(--dim);font-variant-numeric:tabular-nums;font-weight:600}
  .fk-card .fk-cardfoot .asg .asg-age.hot{color:var(--warn-ink,var(--warn));font-weight:700}
  .fk-card .fk-cardfoot .fk-avatar{width:18px;height:18px;font-size:9px;flex:none;margin-left:0}
  /* THE EXCEPTION ROW. Full width by construction so it competes with nothing — the balance line learned that
     the hard way when nesting it in the foot clipped "Order with" on any four-figure job. It WRAPS: the whole
     point is to stop a real warning being cut off mid-word ("30 Aug · 1d late · stalle…"), so it may take two
     lines and `overflow-wrap:anywhere` keeps a long unbroken figure inside the card. */
  .fk-card .fk-cardalert{display:flex;gap:6px;align-items:flex-start;margin-top:7px;padding:6px 8px;
    border-radius:4px;font-size:11px;line-height:1.42;overflow-wrap:anywhere;text-align:left}
  .fk-card .fk-cardalert .ic{flex:none}
  .fk-card .fk-cardalert b{font-weight:700}
  .fk-card .fk-cardalert.bad{background:color-mix(in srgb,var(--danger) 15%,transparent);color:var(--danger-ink,var(--danger));
    box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--danger) 32%,transparent)}
  .fk-card .fk-cardalert.warn{background:color-mix(in srgb,var(--warn) 15%,transparent);color:var(--warn-ink,var(--warn));
    box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--warn) 32%,transparent)}
  .fk-card .fk-cardalert.info{background:color-mix(in srgb,var(--accent) 13%,transparent);color:var(--accent-ink,var(--accent));
    box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--accent) 30%,transparent)}
  /* THE JOB SEARCH, ON SCREEN (owner 2026-10-03, option A of docs/prototype/job-search/): the strip under the box and the
     "Found in" line at a card's foot. Both are the band's and the card's own colours, neutral on purpose — an alert row says
     something is wrong, this says why a card is here. NAMES: the parts inside the line are .fw-*, never .who — this file
     carries a bare .who{display:flex} (a different screen's) and a span called .who inside the line came out as a flex box. */
  .fk-sstrip{display:flex;flex-wrap:wrap;align-items:center;gap:0 8px;min-height:28px;padding:2px 12px;margin-top:1px;border-radius:8px;
    background:var(--fk-sunk,rgba(0,0,0,.18));box-shadow:inset 0 0 0 1px var(--fk-band-line,var(--line));
    font-size:12.5px;font-weight:600;line-height:20px;color:var(--fk-band-sub,var(--dim));font-variant-numeric:tabular-nums}
  .fk-sstrip[hidden]{display:none}
  .fk-sstrip b{color:var(--fk-band-ink,var(--white));font-weight:700}
  .fk-sstrip .ss-dot{opacity:.75}
  .fk-sstrip .ss-gap{width:1px;height:14px;background:var(--fk-band-line,var(--line2));margin:0 6px;align-self:center}
  .fk-sstrip .ss-btn{display:inline-flex;align-items:center;gap:8px;min-height:28px;padding:0 2px;margin:0;background:none;border:0;border-radius:6px;font:inherit;color:inherit;cursor:pointer;white-space:nowrap}
  .fk-sstrip .ss-btn b{color:var(--accent)}
  .fk-sstrip .ss-btn:hover b{text-decoration:underline}
  .fk-sstrip .ss-btn:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
  .fk-sstrip .ss-fail{color:var(--warn-ink,var(--warn));font-weight:700}   /* the server could not be asked: never worded as "nothing found" */
  .fk-sstrip .ss-wait{display:inline-flex;align-items:center;gap:8px}
  .fk-sstrip .ss-spin{display:inline-block;flex:none;width:11px;height:11px;border-radius:50%;border:2px solid transparent;border-color:color-mix(in srgb,currentColor 30%,transparent);border-top-color:var(--accent);animation:ss-spin .9s linear infinite}
  @keyframes ss-spin{to{transform:rotate(1turn)}}
  @media (prefers-reduced-motion:reduce){.fk-sstrip .ss-spin{animation:none}}
  .fk-card .fk-found{display:flex;gap:6px;align-items:flex-start;margin:0;padding:6px 8px;border-radius:4px;font-size:11px;line-height:1.42;
    color:var(--dim);background:var(--fk-sunk,rgba(0,0,0,.18));box-shadow:inset 0 0 0 1px var(--line2);text-align:left;container-type:inline-size}
  .fk-card .fk-found .s-ic{flex:none;width:12px;height:12px;margin-top:2px;color:var(--dim)}
  /* two lines at most, an ellipsis after them, and an unbroken 90-letter word wraps inside the card instead of through it */
  .fk-card .fk-found .fw{flex:1;min-width:0;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;overflow-wrap:anywhere}
  .fk-card .fk-found b{color:var(--white);font-weight:700}
  /* the words that matched: the same picking-out the Product Range search uses (.fk-cp-row .hit) */
  .fk-found mark{background:var(--accent-soft);color:var(--white);font-weight:700;border-radius:2px;padding:0 2px;
    box-shadow:0 0 0 1px var(--accent-line,color-mix(in srgb,var(--accent) 55%,transparent));-webkit-box-decoration-break:clone;box-decoration-break:clone}
  /* a narrow card has about 27 characters a line, so the name and the date go first and the words that matched stay on screen */
  .fk-found .fw-bf1{display:none}
  @container (max-width:230px){.fk-found .fw-who,.fk-found .fw-bf{display:none}.fk-found .fw-bf1{display:inline}}
  @media (max-width:760px){
    .fk-sstrip{padding:4px 12px}
    .fk-sstrip .ss-btn{min-height:34px;white-space:normal;text-align:left}
    .fk-sstrip .ss-gap{display:none}
  }
  .fk-board.card-compact .fk-card{padding:9px 10px}
  .fk-board.card-compact .fk-card .t{font-size:12.5px;margin-bottom:2px}
  .fk-board.card-compact .fk-card .r-cust b{font-size:12.5px}
  .fk-board.card-compact .fk-card .meta{margin-top:6px;gap:5px}
  .fk-board.card-compact .fk-card .fk-cardfoot{margin-top:8px;padding-top:7px}
  .fk-board.card-large .fk-card .thumb{height:150px}
  .fk-board.card-large .fk-card .t{font-size:14px}
  /* the ⚙ Customize slide-in panel (right edge of the FK shell) */
  #fk-shell .fk-cvpanel{position:absolute;top:0;right:0;height:100%;width:300px;max-width:88%;background:var(--panel);border-left:1px solid var(--line);box-shadow:-14px 0 40px rgba(0,0,0,.35);z-index:40;display:flex;flex-direction:column;transform:translateX(100%);transition:transform .2s cubic-bezier(.4,0,.2,1);overflow-y:auto}
  #fk-shell .fk-cvpanel.open{transform:translateX(0)}
  .fk-cvhead{display:flex;align-items:center;gap:10px;padding:15px 16px 12px;border-bottom:1px solid var(--line)}
  .fk-cvhead b{font-size:14.5px;flex:1;color:var(--white)}
  .fk-cvx{background:none;border:none;color:var(--dim);font-size:18px;cursor:pointer;line-height:1;padding:2px 4px}
  .fk-cvx:hover{color:var(--white)}
  .fk-cvbody{padding:6px 14px 22px;display:flex;flex-direction:column}
  .fk-cvrow{display:flex;align-items:center;gap:10px;padding:11px 2px;border-bottom:1px solid var(--line)}
  .fk-cvl{font-size:13px;flex:1;color:var(--text)}
  .fk-cvl .fk-cvs{display:block;font-size:11px;color:var(--dim);margin-top:1px}
  .fk-cvseg{display:inline-flex;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:2px}
  .fk-cvseg button{font-family:inherit;font-size:11.5px;font-weight:600;border:none;background:none;color:var(--dim);padding:5px 9px;border-radius:7px;cursor:pointer}
  .fk-cvseg button.on{background:var(--panel);color:var(--white);box-shadow:0 1px 2px rgba(0,0,0,.25)}
  .fk-cvsw{position:relative;width:38px;height:22px;border-radius:99px;background:var(--panel2);border:1px solid var(--line);cursor:pointer;flex:none;transition:.15s;padding:0}
  .fk-cvsw::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.4);transition:.15s}
  .fk-cvsw.on{background:var(--accent);border-color:var(--accent)}
  .fk-cvsw.on::after{transform:translateX(16px)}
  .fk-cvsec{font-size:10px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;color:var(--dim);padding:16px 2px 4px}
  .fk-cvchk{display:flex;align-items:center;gap:10px;padding:8px 2px;cursor:pointer;font-size:13px;color:var(--text)}
  .fk-cvchk input{appearance:none;-webkit-appearance:none;width:18px;height:18px;border:1.5px solid var(--line2);border-radius:5px;cursor:pointer;position:relative;flex:none;background:var(--panel2)}
  .fk-cvchk input:checked{background:var(--accent);border-color:var(--accent)}
  .fk-cvchk input:checked::after{content:"✓";position:absolute;inset:0;display:grid;place-items:center;color:var(--on-accent);font-size:12px;font-weight:800}
  .fk-cvreset{margin-top:14px;background:none;border:1px solid var(--line);border-radius:9px;color:var(--dim);font-family:inherit;font-size:12.5px;font-weight:600;padding:9px;cursor:pointer}
  .fk-cvreset:hover{border-color:var(--accent);color:var(--accent)}
  .fk-btn#fk-cardview.active{border-color:var(--accent);color:var(--accent)}
  .fk-avatar{position:relative;overflow:hidden;width:20px;height:20px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;color:#fff;font-size:9px;font-weight:700;background:#3a4255}
  .fk-avatar img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}  /* uploaded profile photo covers the initials; removed on 404 (no photo) */

  .fk-empty{margin:40px auto;max-width:460px;text-align:center;color:var(--dim)}
  .fk-empty .big{font-size:40px;margin-bottom:10px}
  .fk-empty h3{color:var(--white);margin:0 0 6px;font-size:17px}

  /* The scrim dims the board it opened from AND THE TODAY PANEL (owner 2026-09-28, FK audit M6). From 2026-09-11 the
     panel was lifted above it to stay lit and usable beside an open order; lit beside a modal drawer it read as part
     of the order, and a click on one of its rows opened a different job over the one being worked on. The drawer
     covers the dimmed panel (owner 2026-09-28) and stops only at the docked side chat — see .fk-drawer's right. */
  /* The scrim COVERS the board and the Today panel, rather than being cut short of the
     panel's width. Cutting it short left a live, undimmed column of board beside the drawer for the whole
     height the panel does NOT occupy — the panel starts below the board's toolbar, so at 150% zoom the
     Customize button sat in that column, half dimmed and half bright, and still clickable behind a modal
     drawer. Measured 2026-09-11: scrim ended at x1034, the button spanned x977..1077.
     `bottom` clears the fixed footer for the same reason every full-height tab subtracts --foot-h: the
     drawer used to run 14px under it, so the copyright line and the drawer's last row painted over one
     another. The drawer keeps its own distance from the panel — see .fk-drawer's right. */
  .fk-drawer-backdrop{position:fixed;top:var(--topbar-h);left:var(--rail-inset);right:0;bottom:var(--foot-h);background:rgba(5,7,12,.86);display:none;z-index:45}  /* starts below the top nav AND right of the app rail, so the bar, the arrows and the other apps all stay visible and clickable while the drawer is open */
  /* THE DOCKED CHAT PANEL IS NOT THE BOARD (owner 2026-09-22: "fix side chat panel when opening FK
     job that side panel still can be used if openned"). The backdrop is position:fixed to right:0, so it
     ran straight over a panel that is a flex SIBLING of the page it is dimming. Measured before the fix:
     backdrop 55,51 1545x923 against a dock at 1184,51 416x923 — every click in the panel, the composer
     included, landed on div#fk-drawer-backdrop. You keep it open precisely so you can answer someone while
     you work, which is exactly what opening a job is. The one thing lifted above the scrim, in one line. */
  body.fk-drawer-lock.chat-docked #chat-host{position:relative;z-index:46}
  .fk-drawer-backdrop.open{display:block}
  body.fk-drawer-lock{overflow:hidden} /* lock the page behind the drawer so the wheel scrolls the chat, not the board */
  /* floating panel — inset from every edge so the chat scrollbar, composer & content never hug the screen edge */
  /* Inset from its BACKDROP on all four sides, not sized from the viewport. It used to be
     width:min(1560px, 96vw/zoom) anchored right — fine while the backdrop was the whole screen, but the
     backdrop now stops short of the app rail AND the Today panel, so a viewport-sized drawer hung its left
     edge off-screen (measured at x=-120) and covered the rail it was meant to leave reachable. */
  /* right: the docked side chat's width plus the same 12px gap, so the drawer stops beside the dock — the one thing
     lifted above the scrim — rather than under it. It runs OVER the dimmed Today panel: that column was ~250px the
     order could not use (owner 2026-09-28). 0 when no chat is docked; published by fk.js publishDockInset. */
  .fk-drawer{position:absolute;top:12px;right:calc(var(--fk-dock-inset,0px) + 12px);bottom:12px;left:12px;height:auto;width:auto;background:var(--panel);border:1px solid var(--line);border-radius:16px;box-shadow:0 24px 70px rgba(0,0,0,.55);overflow:hidden;display:flex}
  /* default split puts the chat at the mock's 360px; the gutter still overrides it and the width persists */
  .fk-drawer-left{flex:0 0 var(--fk-drawer-splitw,calc(100% - 360px));min-width:0;overflow-y:scroll;overscroll-behavior:contain;padding:0}
  .fk-drawer-right{flex:1;min-width:0;display:flex;flex-direction:column;border-left:1px solid var(--line)}
  /* the mock's band rhythm: the identity band runs full-bleed to the drawer's edges, everything below it is
     inset once, here, rather than each band carrying its own padding and drifting out of step */
  .fk-drawer-left > *:not(.fk-timeline){margin-left:22px;margin-right:22px}
  .fk-drawer-left > *:last-child{margin-bottom:20px}
  /* draggable gutter on the order-detail | chat split (uses the shared Suite.makeResizer, like Team Chat) */
  /* shared draggable gutter (Suite.makeResizer) — one base, positioned per split */
  .fk-resizer{position:absolute;top:0;bottom:0;margin-left:-6px;width:11px;z-index:12;cursor:col-resize;user-select:none;touch-action:none;outline:none}
  .fk-resizer::after{content:"";position:absolute;top:0;bottom:0;left:50%;width:1px;transform:translateX(-50%);background:transparent;transition:background .14s,width .14s}
  .fk-resizer:hover::after,.fk-resizer.dragging::after,.fk-resizer:focus-visible::after{background:color-mix(in srgb,var(--tab-accent) 60%,transparent);width:3px}
  .fk-drawer .fk-resizer{left:var(--fk-drawer-splitw,calc(100% - 360px))}   /* same var AND same fallback as .fk-drawer-left, or the gutter draws away from the seam it moves */
  .fk>.fk-resizer{left:var(--fk-navw,224px)}   /* the FK nav | main-content gutter — same var AND same fallback as .fk-navwrap, so an untouched install can't draw them apart */
  .fk-msg-wrap>.fk-resizer{left:var(--fk-msgw,282px)}   /* Customer Messages: list | conversation gutter */
  /* ===== SP2: the docked chat panel — the ONE chat instance shown beside any tab (D6/G7) ===== */
  .dock-row{flex:1;display:flex;min-height:0;position:relative}
  body.chat-docked #chat-host{flex:0 0 var(--dockw,420px);min-width:0;border-left:1px solid var(--line)}
  #dock-row>.fk-resizer{left:auto;right:var(--dockw,420px);margin-left:0;margin-right:-6px}
  /* the ✕ is plainly red and its glyph is an SVG centred by flex (owner 2026-10-07); top:17px puts its middle on the
     "‹ Conversations" bar's middle, and #dock-max sits one button-width to its left */
  #dock-close,#dock-max{position:absolute;top:17px;z-index:50;width:26px;height:26px;padding:0;border-radius:8px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;line-height:1}
  #dock-close{right:10px;border:1px solid #c62828;background:#d93030;color:#fff}
  #dock-close:hover{background:#e53e3e;border-color:#e53e3e}
  #dock-max{right:42px;border:1px solid var(--line);background:var(--panel2);color:var(--dim)}
  #dock-max:hover{color:var(--text);border-color:var(--tab-accent)}
  #dock-max .dm-in,#dock-max.on .dm-out{display:none}
  #dock-max.on .dm-in{display:block}
  @media (max-width:900px){#dock-max{display:none!important}}
  /* MAXIMISED: the ONE chat panel lays itself over the tab's page and stops at the tab's own nav rail (app.js
     paintDockMax measures where, into --dockmax-left), so Inbox · Replies · Tasks on that rail stay clickable.
     The page underneath is not closed or reflowed; it is covered. chat-docked stays on, so chat.js still treats
     this as the dock. */
  body.chat-docked.chat-max #chat-host{position:absolute;top:0;bottom:0;right:0;left:var(--dockmax-left,0px);flex:none;max-height:none;z-index:45;border-left:1px solid var(--line)}
  body.chat-max #dock-resizer{display:none}
  /* ---- Team Hub's Inbox · Replies · Tasks, repeated at the top of every tab's own nav rail ----
     Four rails, four palettes: Future Knights navy, Online Orders charcoal & lime, Creatives berry LIGHT,
     Kaizen light. So the trio takes NO colour of its own — everything is currentColor mixed into the rail it
     lands in, which is why it reads as part of each rail rather than a strip bolted on. Same three-tile shape
     as Team Hub's own (chat.css .nav-pair), because it is meant to be recognised as the same menu. */
  /* --hubnav-ink: a rail sets this when its CONTAINER colour is dimmer than the items inside it. Online
     Orders is the case that forced it: .pnav inherits a faint ink while .pitem paints itself #b9bda9, so the
     trio inherited the faint one and read like the LOCKED "Email" row sitting under it. The rail knows its own
     item colour; the component should not have to guess it, and should not be restyled four times. */
  /* Owner 2026-08-13, docs/prototype/nav-rail-layout-mock.html: tab name, trio, RULE, then the list. The rule
     used to sit under the tab name; it belongs under the shortcuts, so the name and the things it offers read
     as one block. 16px of air above it and 10px below puts it near the middle of the gap rather than hugging
     the icons. It ships as part of the component so all three rails share one rhythm. */
  /* The doubled class is load-bearing, not a typo. Online Orders and Creatives each open with a blanket
     `.omfh-root *{margin:0}` / `.cc-root *{margin:0}` reset, which is the SAME specificity as a single class —
     and their stylesheets load after this one, so they won and flattened the rule's spacing to nothing.
     Measured: 16px of air became 0 on Online Orders and 2 on Creatives. (chat.css carries the same note about
     content.css loading later; this is that trap again, one file along.) */
  .suite-hubnav.suite-hubnav{display:flex;gap:6px;margin:0 0 16px;flex:none;color:var(--hubnav-ink, inherit);
    container-type:inline-size;container-name:hubnav}
  /* the rule takes --hubnav-ink too. It is a SIBLING of .suite-hubnav, not a child, so without this it
     inherits the rail container's dimmer colour and all but disappeared on Online Orders. */
  .suite-hubsep.suite-hubsep{height:1px;flex:none;margin:0 0 10px;color:var(--hubnav-ink, inherit);
    background:var(--hubnav-line, color-mix(in srgb, currentColor 22%, transparent))}
  .suite-hubnav .shub{position:relative;flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;
    justify-content:center;gap:4px;padding:8px 3px;border-radius:8px;cursor:pointer;font:inherit;font-size:11.5px;
    font-weight:500;letter-spacing:.1px;color:inherit;
    /* NO resting opacity. It looked right on the navy and berry rails and left the trio reading fainter than
       "Record Error" on Online Orders — whose rail already inherits a dim colour, so the two dimmings stacked
       and the rows sat at the same weight as the LOCKED Email item. The tile and its border do the grouping;
       the text stays at whatever strength the rail it landed in uses. */
    /* NOTHING AT REST (owner 2026-08-14: "make sure the icons on other tabs do not have the boxed outline
       around them - similar to Team hub"). Team Hub's own row is `border:1px solid transparent;
       background:transparent` and paints only on hover or when it is the open view; these copies drew a
       tile permanently, so the same three rows read as buttons here and as plain rows there. The border
       stays declared, transparent, so hover and .on can colour it without the row changing size. */
    border:1px solid transparent; background:transparent}
  .suite-hubnav .shub:hover{background:color-mix(in srgb, currentColor 13%, transparent)}
  .suite-hubnav .shub.on{border-color:color-mix(in srgb, currentColor 36%, transparent);
    background:color-mix(in srgb, currentColor 17%, transparent)}
  .suite-hubnav .shub:focus-visible{outline:2px solid currentColor;outline-offset:2px}
  .suite-hubnav .shub-i{display:inline-flex;align-items:center;justify-content:center}
  .suite-hubnav .shub-i .ic{width:18px;height:18px;stroke-width:1.5}
  /* the label may shrink to an ellipsis; the COUNT never may — it is the whole reason the row is on this tab */
  .suite-hubnav .shub-l{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .suite-hubnav .shub-n{position:absolute;top:3px;right:5px;min-width:15px;height:15px;padding:0 3px;border-radius:8px;
    /* the same blue every other count wears (owner 2026-08-14). This one was missed on the first pass because
       it fills with --danger directly rather than through the badge token — worth noting, since --danger is
       ALSO the wrong contrast for white text (3.1:1) as well as the wrong meaning. */
    font-size:9px;font-weight:700;line-height:15px;text-align:center;background:var(--count-badge);color:#fff}
  .suite-hubnav .shub-n.hide{display:none}
  /* Future Knights' rail can be dragged down to 168px, which leaves each tile ~46px and clipped "Replies" to
     a ragged "Replie…". Found by driving the resizer to its stop, not by looking at the default width. The
     rows measure THEMSELVES, so this holds for any rail anyone narrows in future. */
  @container hubnav (max-width:175px){
    .suite-hubnav{gap:4px}
    .suite-hubnav .shub{padding:8px 2px;font-size:10.5px;letter-spacing:0;gap:3px}
    .suite-hubnav .shub-i .ic{width:16px;height:16px}
    .suite-hubnav .shub-n{top:2px;right:3px;min-width:13px;height:13px;font-size:8.5px;line-height:13px}
  }
  /* (The horizontal-bar variant of the trio lived here. Kaizen's sub-tab bar was its only host, and the trio
     moved off it onto the Logistics rail — a bar belonging to one SECTION could not carry a shortcut meant to
     work anywhere in the tab, and it vanished on Inventory & Suppliers. The rules went with it rather than
     sitting here matching nothing, which is how dead CSS keeps a test green while proving nothing.

     Worth keeping the lesson, because it cost a shipped bug: container-type:inline-size makes an element's
     intrinsic width 0. In the vertical rails that is harmless — they are COLUMN flex containers, so the box
     stretches to the rail. In a ROW flex bar with flex:none it meant 0px wide: margin-left:auto parked the
     empty box at the right edge and all three pills painted past it into an overflow whose scrollbar is
     deliberately hidden. Measured: nav width 0 at x=1327, pills at 1327/1428/1517 off the end of a 1040px bar.
     Any future horizontal host of .suite-hubnav must set container-type:normal.) */
  .fk-dr-head{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:16px 18px 12px;border-bottom:1px solid var(--line);flex:none}
  /* Following an order (v85): a quiet outline until you are following, then filled — the same on/off
     idiom the board pills use, so it reads as a STATE rather than an action. margin-left:auto keeps it
     beside ✕ while the heading block takes the space it needs. */
  /* My Settings → Notifications (v86). A row per category, each a real switch with its own explanation —
     a bare list of words would make people guess what "updates" covers. */
  .ms-subh{color:var(--faint);font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;margin:14px 0 7px}
  .ms-segs{display:flex;gap:6px;flex-wrap:wrap}
  .ms-segs button{flex:1;min-width:62px;background:var(--panel2);border:1px solid var(--line);color:var(--text);
    border-radius:8px;padding:6px 8px;font:inherit;font-size:12px;cursor:pointer}
  .ms-segs button:hover{border-color:var(--line2);color:var(--white)}
  .ms-segs button.on{background:var(--accent-soft);border-color:var(--accent);color:var(--white);font-weight:650}
  /* the sound SET: four cards, each naming its character, so choosing does not mean guessing from a word */
  .ms-sndset{display:flex;gap:6px;margin-top:9px;flex-wrap:wrap}
  .ms-sndset button{flex:1;min-width:78px;background:var(--panel2);border:1px solid var(--line);color:var(--text);
    border-radius:8px;padding:7px 8px;font:inherit;font-size:12px;font-weight:650;cursor:pointer;
    display:flex;flex-direction:column;gap:2px;align-items:flex-start;text-align:left}
  .ms-sndset button small{font-weight:500;font-size:10.5px;color:var(--muted)}
  .ms-sndset button:hover{border-color:var(--line2);color:var(--white)}
  .ms-sndset button.on{background:var(--accent-soft);border-color:var(--accent);color:var(--white)}
  /* …and a press-to-hear for each of the three, because a sound you cannot audition is a setting you get
     wrong once and never revisit */
  /* the three sounds, each with its own switch and its own press-to-hear. A row per sound rather than a row
     of previews: switching one off is the thing people came here to do. */
  .ms-snd3{display:grid;grid-template-columns:auto 1fr auto;gap:7px 10px;align-items:center;margin-top:9px}
  .ms-snd3 .s3-sw{min-width:44px;background:var(--panel2);border:1px solid var(--line);color:var(--muted);
    border-radius:999px;padding:4px 10px;font:inherit;font-size:11px;font-weight:750;cursor:pointer}
  .ms-snd3 .s3-sw.on{background:var(--accent-soft);border-color:var(--accent);color:var(--white)}
  .ms-snd3 .s3-n{display:flex;flex-direction:column;font-size:12.5px;font-weight:650;color:var(--text);min-width:0}
  .ms-snd3 .s3-n small{font-weight:500;font-size:10.5px;color:var(--muted)}
  .ms-snd3 .s3-try{width:28px;height:28px;background:none;border:1px solid var(--line);color:var(--muted);
    border-radius:8px;font:inherit;font-size:11px;cursor:pointer}
  .ms-snd3 .s3-try:hover{border-color:var(--accent);color:var(--white)}
  .ms-dnd-state:empty{display:none}
  /* margin-bottom:0 — the suite's global input{margin-bottom:16px} would push these rows apart */
  .ms-quiet{display:flex;align-items:center;gap:8px;margin-top:9px;color:var(--dim);font-size:12px;flex-wrap:wrap}
  .ms-quiet input{margin-bottom:0;width:auto;flex:none;padding:5px 8px;font-size:12px}
  .ms-kw{display:flex;gap:6px;align-items:center}
  .ms-kw input{flex:1;min-width:0;margin-bottom:0}
  .ms-notifperm{display:block;width:100%;margin-top:8px;background:var(--panel2);border:1px solid var(--line);
    color:var(--text);border-radius:8px;padding:7px 10px;font:inherit;font-size:12px;cursor:pointer;text-align:left}
  .ms-notif{display:grid;grid-template-columns:1fr 1fr;gap:2px 14px;margin-bottom:8px}
  @media (max-width:860px){ .ms-notif{grid-template-columns:1fr} }
  .ms-notif label{display:flex;align-items:flex-start;gap:10px;padding:7px 8px;border-radius:8px;cursor:pointer}
  .ms-notif label:hover{background:var(--card2,#f6f7f4)}
  .ms-notif input{width:16px;height:16px;margin:1px 0 0;flex:none;accent-color:var(--accent,#2f6df6)}
  .ms-notif b{display:block;font-size:13px;font-weight:600}
  .ms-notif small{display:block;color:var(--mut,#6b7280);font-size:11.5px;line-height:1.45}
  .ms-snd{display:flex;align-items:flex-start;gap:10px;padding:7px 8px;border-radius:8px;cursor:pointer}
  .ms-snd:hover{background:var(--card2,#f6f7f4)}
  .ms-snd input{width:16px;height:16px;margin:1px 0 0;flex:none;accent-color:var(--accent,#2f6df6)}
  .ms-snd b{display:block;font-size:13px;font-weight:600}
  .ms-snd small{display:block;color:var(--mut,#6b7280);font-size:11.5px;line-height:1.45}
  .fk-dr-head .fk-watch{margin-left:auto;white-space:nowrap}
    /* ANYTHING FILLED WITH --accent WRITES IN --on-accent, NEVER A LITERAL (owner 2026-09-08: "Yellow should
     be with NAVY blue not Yellow with White"). Marine's accent is yellow (#ffd54a) with --on-accent set to
     its navy ink for exactly this reason — Forest's own comment calls it "the same split Marine makes with
     its yellow" — and a hard-coded color:#fff here was the one control that never read it: fine on every
     dark/saturated FK accent, close to invisible on a pastel one. test/fk-theme-accent-ink.test.cjs sweeps
     the whole sheet for this shape so a fourth copy fails the build instead of shipping quietly. */
  .fk-dr-head .fk-watch.on{background:var(--accent,#2f6df6);border-color:var(--accent,#2f6df6);color:var(--on-accent);font-weight:700}
  /* THE CONVERSATION FILLS THE PANE UNDER THE HEADER (unified discussion, Task 7, 2026-09-23). #fk-thread hosts the
     shared discussion component, which scrolls its own feed and keeps its own composer at the foot; the host
     only gives it the room. The component's root is a .wc-root, and chat.css's @scope :scope rule asks every
     one of those for height:100% and a graphite gradient — right for Team Hub's panel, wrong on a drawer that
     is its own ground. The id out-specifies :scope, and a flex item sizes itself. */
  #fk-thread{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
  #fk-thread>.wc-root{flex:1 1 auto;min-height:0;height:auto;background:none}
  /* THE JOB'S ACTIVITY LOG SITS AT THE FOOT AND OPENS UPWARD (owner 2026-08-25: "activity log should remain on
     the bottom of the list and expand up when clicked"). fk.js moves its row into the conversation's own row
     above the composer (the component's inst.slot, which never shrinks), so it is always on the composer
     whatever the length of the thread. column-reverse is what makes it grow UP: the summary is first in the DOM,
     so reversing paints it at the foot and the entries open into the space above it, the header staying put.
     Scoped to THIS details — the left pane's sections are ordinary top-down disclosures. */
  #fk-thread .fk-actrow{padding:8px 18px;border-top:1px solid var(--line)}
  /* the switch is laid over the summary's line, inside the row's own padding rather than on the pane's edge */
  #fk-thread .fk-actrow>.fk-actsw{top:8px;right:18px}
  .fk-drawer .fk-actrow>details[data-sec="activity"]{display:flex;flex-direction:column-reverse;margin-top:0}
  /* ---------- the order's history (owner 2026-08-25) ----------
     Woven into the conversation it is the discussion component's own quiet system line (Task 7); these are the
     Activity log's rows and chips. */
  /* ONE colour per kind of thing, used by the log row and its filter chip alike, so a stage move looks like
     a stage move in both places. Semantic, not decorative: warn is the suite's warn, money its ok green.
     A row whose kind could not be told falls to the default grey above and is never hidden by it. */
  .fk-cmt.act.k-warn::before,.fk-actchip.k-warn i{background:var(--warn)}
  .fk-cmt.act.k-money::before,.fk-actchip.k-money i{background:var(--ok,#35d39a)}
  .fk-cmt.act.k-file::before,.fk-actchip.k-file i{background:#9d7bff}
  .fk-cmt.act.k-stage::before,.fk-actchip.k-stage i{background:var(--accent)}
  .fk-cmt.act.k-edit::before,.fk-actchip.k-edit i{background:var(--line2,#2d3a52)}
  .fk-cmt.act.k-other::before,.fk-actchip.k-other i{background:var(--dim)}
  /* the log's own rows: a colour stripe rather than a dot, because the row is two lines tall */
  .fk-cmt.act{position:relative;padding-left:14px}
  .fk-cmt.act::before{content:"";position:absolute;left:5px;top:9px;bottom:9px;width:3px;border-radius:2px;background:var(--line2,#2d3a52)}
  .fk-actchips{display:flex;flex-wrap:wrap;gap:5px;margin:0 0 8px}
  .fk-actchip{display:inline-flex;align-items:center;gap:5px;font-size:10px;font-weight:750;white-space:nowrap;
    padding:3px 9px;border-radius:999px;border:1px solid var(--line2,#2d3a52);background:none;color:var(--dim);cursor:pointer;font-family:inherit}
  .fk-actchip:hover{border-color:var(--accent);color:var(--white)}
  /* INK IS THE GROUND TOKEN, NOT A LITERAL. Every light theme sets --white to its ink (#1c2733) and --panel to
     its ground (#ffffff); the dark base is the other way round. So a chip that fills with --white must write
     in --panel to invert in every theme — the hard-coded #0e131c that sat here was ink on ink in the white
     theme (owner 2026-09-08: "colour is not visible black on black in a white theme"). */
  .fk-actchip.on{background:var(--white);border-color:var(--white);color:var(--panel)}
  .fk-actchip i{width:6px;height:6px;border-radius:50%;background:var(--dim);flex:none}
  .fk-actchip.on i{opacity:.75}
  .fk-actolder{display:block;width:100%;margin-top:6px;padding:7px;border:1px dashed var(--line2,#2d3a52);
    border-radius:7px;background:none;color:var(--accent);font:inherit;font-size:11px;font-weight:700;cursor:pointer}
  .fk-actolder:hover{border-color:var(--accent)}
  .fk-actolder:disabled{opacity:.6;cursor:default}
  /* the edge fade — only present while there is more that way, and never over the pointer */
  #fk-activity{position:relative}
  #fk-activity.more-below{-webkit-mask-image:linear-gradient(#000 calc(100% - 22px),transparent);
    mask-image:linear-gradient(#000 calc(100% - 22px),transparent)}
  #fk-activity.more-above.more-below{-webkit-mask-image:linear-gradient(transparent,#000 18px,#000 calc(100% - 22px),transparent);
    mask-image:linear-gradient(transparent,#000 18px,#000 calc(100% - 22px),transparent)}
  #fk-activity.more-above:not(.more-below){-webkit-mask-image:linear-gradient(transparent,#000 18px);
    mask-image:linear-gradient(transparent,#000 18px)}
  /* The switch beside Follow — says which state it is IN, so `on` is the lit one.
     THE HEAD IS 356px WIDE AND NOW CARRIES THREE CONTROLS. Written out as "🗒 Activity" it pushed the count
     onto three wrapped lines, and once the row was allowed to wrap it took the buttons to a second row and
     made the head taller than the thing it labels. The count is what the head is FOR, so it keeps its line;
     the switch is a square, named by its tooltip and aria-label and lit when it is on — the same shape as
     the ★ beside it. */
  /* "in thread" — the switch, living on the Activity log's own row. Small, quiet when off, lit when on;
     the row reads as one sentence: ACTIVITY LOG · in thread. It sits inside the <summary>, so it must not
     look like part of the disclosure label — hence its own pill shape and its own hit area. */
  /* …and it is a SIBLING of the disclosure now, not a child of its summary (2026-09-16 — Chrome's Issues
     panel, and it was right: inside the summary it could not be reached by keyboard at all). Laid over the
     summary's own line so the row still reads ACTIVITY LOG · in thread, which is the whole point of it. */
  .fk-drawer .fk-actrow{position:relative}
  .fk-drawer .fk-actrow>.fk-actsw{position:absolute;top:0;right:0;cursor:pointer;
    font-size:9.5px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;line-height:1.6;
    padding:3px 8px;border-radius:999px;border:1px solid var(--line2,#2d3a52);color:var(--dim);background:none}
  .fk-drawer .fk-actrow>.fk-actsw:hover{border-color:var(--accent,#2f6df6);color:var(--white)}
  .fk-drawer .fk-actrow>.fk-actsw.on{background:var(--accent,#2f6df6);border-color:var(--accent,#2f6df6);color:var(--on-accent)}
  .fk-drawer .fk-actrow>.fk-actsw:focus-visible{outline:2px solid var(--accent,#2f6df6);outline-offset:2px}
  .fk-mention-pop,.fk-emoji-pop{position:absolute;left:0;bottom:calc(100% + 6px);background:var(--panel);border:1px solid var(--line);border-radius:10px;box-shadow:0 12px 30px rgba(0,0,0,.5);z-index:80;display:none}
  .fk-mention-pop.open,.fk-emoji-pop.open{display:block}
  .fk-emoji-pop{padding:7px;display:none;grid-template-columns:repeat(8,1fr);gap:2px;right:auto}
  .fk-emoji-pop.open{display:grid}
  .fk-emoji-pop button{background:none;border:none;font-size:18px;cursor:pointer;padding:4px;border-radius:6px;line-height:1}
  .fk-emoji-pop button:hover{background:var(--panel2)}
  /* auto-hiding themed scrollbars — the thumb is transparent and only fades in while you hover a genuinely
     scrollable pane, so an area with nothing (or barely anything) to scroll never shows a persistent full bar */
  .fk-drawer-left::-webkit-scrollbar,.fk-page::-webkit-scrollbar,.fk-col-body::-webkit-scrollbar,.fk-board::-webkit-scrollbar,.fk-nav::-webkit-scrollbar,.fk-msg-body::-webkit-scrollbar,.fk-msg-list::-webkit-scrollbar,.cmdk-results::-webkit-scrollbar,.fk-modal::-webkit-scrollbar,.main::-webkit-scrollbar{width:12px;height:12px}
  .fk-drawer-left::-webkit-scrollbar-thumb,.fk-page::-webkit-scrollbar-thumb,.fk-col-body::-webkit-scrollbar-thumb,.fk-board::-webkit-scrollbar-thumb,.fk-nav::-webkit-scrollbar-thumb,.fk-msg-body::-webkit-scrollbar-thumb,.fk-msg-list::-webkit-scrollbar-thumb,.cmdk-results::-webkit-scrollbar-thumb,.fk-modal::-webkit-scrollbar-thumb,.main::-webkit-scrollbar-thumb{background:rgba(255,255,255,.26);border-radius:7px}
  .fk-drawer-left:hover::-webkit-scrollbar-thumb,.fk-page:hover::-webkit-scrollbar-thumb,.fk-col-body:hover::-webkit-scrollbar-thumb,.fk-board:hover::-webkit-scrollbar-thumb,.fk-nav:hover::-webkit-scrollbar-thumb,.fk-msg-body:hover::-webkit-scrollbar-thumb,.fk-msg-list:hover::-webkit-scrollbar-thumb,.cmdk-results:hover::-webkit-scrollbar-thumb,.fk-modal:hover::-webkit-scrollbar-thumb,.main:hover::-webkit-scrollbar-thumb{background:rgba(255,255,255,.32)}
  .fk-drawer-left::-webkit-scrollbar-thumb:hover,.fk-page::-webkit-scrollbar-thumb:hover,.fk-col-body::-webkit-scrollbar-thumb:hover,.fk-board::-webkit-scrollbar-thumb:hover,.fk-nav::-webkit-scrollbar-thumb:hover,.fk-msg-body::-webkit-scrollbar-thumb:hover,.fk-msg-list::-webkit-scrollbar-thumb:hover,.cmdk-results::-webkit-scrollbar-thumb:hover,.fk-modal::-webkit-scrollbar-thumb:hover,.main::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.45)}
  .fk-drawer-left::-webkit-scrollbar-track,.fk-page::-webkit-scrollbar-track,.fk-col-body::-webkit-scrollbar-track,.fk-board::-webkit-scrollbar-track,.fk-nav::-webkit-scrollbar-track,.fk-msg-body::-webkit-scrollbar-track,.fk-msg-list::-webkit-scrollbar-track,.cmdk-results::-webkit-scrollbar-track,.fk-modal::-webkit-scrollbar-track,.main::-webkit-scrollbar-track{background:rgba(255,255,255,.06)}
  .fk-drawer-right{position:relative}
  @media (max-width:860px){
    .fk-drawer{flex-direction:column;overflow-y:auto;width:auto;left:2vw;right:calc(var(--fk-dock-inset,0px) + 2vw);top:10px;bottom:10px;height:auto;border-radius:14px}   /* the side chat can still be docked down to 761px, so this stops at it too */
    .fk-drawer .fk-resizer{display:none}   /* stacked layout — no vertical gutter */
    .fk-drawer-left,.fk-drawer-right{flex:none;overflow:visible}
    .fk-drawer-right{border-left:none;border-top:1px solid var(--line);min-height:62vh}
  }
  .fk-drawer h3{color:var(--white);font-size:17px;margin:0 0 2px}
  .fk-drawer .sub{color:var(--dim);font-size:12px;margin-bottom:14px}
  /* THE IDENTITY BAND. It was a full-bleed sticky strip of its own above the flow; the owner asked for it
     inside the order box ("all in one place within one box"), so .fk-drawer-head is gone and this markup is
     rendered by orderIdent() into whichever box is showing. The 3px stage band went to .fk-timeline with it.
     Kept: every measurement below, which is the mock's (paid-job-v2). */
  /* THE HEADER, to the mock's measurements (paid-job-v2): the identity reads as a sentence on the left, the
     two dates as label OVER value on the right, everything on one baseline grid. The old .fk-hwrap/.fk-hgrid
     pair put a caps label beside every value, which spent a third of the line on words that never change. */
  .fk-hd{display:grid;grid-template-columns:minmax(0,1fr) auto auto;column-gap:28px;align-items:start}
  /* `.idl`, NOT `.who`: suite.css declares a bare, unscoped `.who{display:flex}` for a different screen,
     and it won — the order number, the customer and the phone came out side by side on one line instead
     of the mock's two. Same shape as the `.fk-band` collision that broke the Job Board on live. A tab's
     markup must not reuse a bare common class name. */
  .fk-hd .idl{min-width:0}
  .fk-hd .no{font-size:13px;font-weight:600;color:var(--dim);letter-spacing:.02em;margin-left:14px} /* the small grey thing after the name (owner 2026-09-09) */
  .fk-hd .cust{display:inline-flex;align-items:baseline;gap:14px;min-width:0}
  .fk-hd .cust b{font-size:20px;font-weight:600;color:var(--cust-ink,#7CC4FF);letter-spacing:-.2px} /* first and largest, in the customer's sky blue (owner 2026-09-29; amber until then) — each theme sets the shade its surface reads */
  .fk-hd .cust span{font-size:14px;font-weight:400;color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .fk-hd .contact{margin-top:10px;font-size:13px;color:var(--text)}
  .fk-hd .kv{min-width:74px}
  .fk-hd .kv .k{display:block;font-size:12px;color:var(--dim)}
  .fk-hd .kv b{display:block;font-size:14px;font-weight:600;color:var(--white);margin-top:6px}
  .fk-hd .kv small{display:block;font-size:12px;color:var(--dim);margin-top:4px}
  .fk-hd .kv .fk-input{margin:0;background:none;border-color:transparent;padding-left:0;width:118px}
  .fk-hd .kv .fk-input:hover,.fk-hd .kv .fk-input:focus{background:var(--panel2);border-color:var(--line2);padding-left:6px}
  .fk-hd .kv .fk-chip{font-size:11px;padding:1px 6px}
  .fk-hwrap{display:flex;gap:34px;flex-wrap:wrap;align-items:flex-start}
  .fk-hgrid{display:grid;grid-template-columns:auto 1fr;gap:6px 14px;align-items:center}
  .fk-hgrid .hk{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);font-weight:800;white-space:nowrap}
  .fk-hgrid .hv{font-size:13px;color:var(--text);display:flex;align-items:center;gap:7px;flex-wrap:wrap}
  .fk-hgrid .hv b{color:var(--white);font-size:14px}
  .fk-hgrid .hv .code{color:var(--accent);font-weight:800;letter-spacing:.02em}
  .fk-phchip{font-size:11.5px;font-weight:800;color:#463500;background:#f6c445;border-radius:999px;padding:3px 12px;white-space:nowrap}
  /* persistent key-facts strip — always-on money/proof summary at the top of the order (Artwork & Proofing blueprint C.1) */
  .fk-keyfacts{display:flex;gap:22px;flex-wrap:wrap;padding:11px 0;margin-bottom:6px;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
  .fk-keyfacts .kf{display:flex;flex-direction:column;gap:2px}
  .fk-keyfacts .kf .k{font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--faint)}
  .fk-keyfacts .kf .v{font-size:14px;color:var(--white);font-weight:600;font-variant-numeric:tabular-nums}
  .fk-keyfacts .kf .v.owed{color:var(--warn)} .fk-keyfacts .kf .v.ok{color:var(--ok)}
  /* the production-slip download — one recognisable YELLOW action wherever it appears (drawer key-facts,
     stage-list bulk bar) so the press/dispatch always spots it. Dark ink for contrast on the amber fill. */
  .fk-btn.slip{background:#f6c445;color:#463500;border-color:#e3ad2b}
  .fk-btn.slip:hover{background:#f1bb2f;border-color:#d29d1c;color:#463500}
  .fk-btn.slip svg{width:14px;height:14px}
  /* stage-tab navigator (blueprint C.2): the drawer's sections grouped into clickable stage tabs, no endless scroll */
  /* ---- order TIMELINE (owner-approved build target fk-drawer-live.html): FIVE phases —
     Request → Design → Production → Delivery → Archived. Sizes match the mockup exactly.
     Tokens only, so all FK themes + the dark default work. ---- */
  .fk-timeline{position:relative;display:flex;align-items:flex-start;padding:19px 22px 10px;margin:0 0 12px}
  /* THE STAGE BAND (spec §6): 3px of the current stage's colour across the top of the pane, so the page
     you are on is identifiable before you read a word of it. It lived on .fk-drawer-head, the full-bleed
     sticky strip; the flow is the top of the pane now and takes its place as the ONE child exempted from
     the pane's 22px gutter, so the band still reaches both edges without a negative margin. --band is set
     inline per render; the fallback keeps it invisible rather than wrong if a stage ever has no colour. */
  .fk-timeline::after{content:"";position:absolute;left:0;right:0;top:0;height:3px;background:var(--band,transparent)} /* borderless (owner 2026-08-02) — clear gap under the sticky header; the header chip carries the phase, the yellow sub-line the stage */
  .fk-tl-node{position:relative;flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;gap:4px;background:none;border:none;cursor:pointer;padding:8px 4px;font-family:inherit;border-radius:11px}
  .fk-tl-node .bar{position:absolute;top:71px;left:-50%;width:100%;height:3px;background:var(--line2);z-index:0}  /* the face's vertical centre, measured — not a guess */
  .fk-tl-node:first-child .bar{display:none}
  .fk-tl-node.done .bar,.fk-tl-node.here .bar{background:var(--ok)}
  /* PASSED WITHOUT BEING DONE — the third state (owner 2026-09-01). Jobs are moved straight past stages here
     on purpose: a returning customer reordering off a file we already hold does not need a Design round. So
     this is not an error style, it is an honest one — a dashed outline saying "not done here", with the
     connector into it dashed too so the gap reads along the whole strip rather than only in the caption.
     `.soft` is the legitimate kind (the print file exists): same dashed circle, no badge, nothing red. */
  /* The connector INTO a skipped node only. Dashing the one out of it as well read as "the move to Delivery
     did not happen either", which is false — that move is exactly what did happen. */
  .fk-tl-node.skipped .bar{background:repeating-linear-gradient(90deg,var(--faint) 0 4px,transparent 4px 8px)}
  /* ABOVE THE NAME, NOT ON IT. At top:-2px the pill covered the top 6px of the stage's own label — measured
     2026-09-11 on a job that skipped Design and Production, where "Design" and "Production" each had their
     first 6px painted over by the badge describing them. It moves up into the timeline's own top padding
     rather than pushing the label down, so every node still starts at the same y whether it was skipped or
     not — a row of names that do not line up is a worse fault than the one being fixed. */
  .fk-tl-node .tl-skip{position:absolute;top:-16px;left:50%;transform:translateX(-50%);z-index:2;
    font-size:9px;font-weight:800;letter-spacing:.05em;padding:2px 5px;border-radius:3px;
    /* Owner 2026-09-01: "the skipped message looks very dark make it lighter". It was reaching for
       `--warn-bg`, which is not defined anywhere in this suite — so every badge rendered the fallback,
       #3a2a10, a near-black brown that read as a smudge rather than a label.
       Solid amber with dark ink instead — the pair the numbered dot used for "pay attention here" before the
       face replaced it — so the strip has one attention colour rather than two. Literals for the same reason
       that rule used them: they must hold across all four FK themes, and a token that does not exist is how
       this got dark in the first place. */
    background:#f6c445;color:#463500;border:1px solid #e3ad2b}
  .fk-tl-node.skipped:not(.soft) .tl-st{color:var(--warn-ink,var(--warn));font-weight:650}
  /* ---- the Production FORK: one node that shows both routes and which one this job took ---- */
  /* .fk-timeline-scoped: the fork also carries .fk-stab (the click handler selects on it), and .fk-stab is
     declared LATER at equal specificity — it was overriding flex, padding and border, squeezing the fork to
     236px of its declared 300 and giving it the tab bar's divider, gradient and underline. */
  .fk-timeline .fk-tl-fork{position:relative;flex:0 0 300px;min-width:0;display:flex;flex-direction:column;background:none;border:none;cursor:pointer;padding:8px 10px;font-family:inherit;border-radius:11px;text-align:left}
  .fk-timeline .fk-tl-fork.on{background:none;box-shadow:none}
  .fk-timeline .fk-tl-fork.on::after{display:none}
  .fk-tl-fork .bar{position:absolute;top:24px;left:-50%;width:100%;height:3px;background:var(--line2);z-index:0}
  .fk-tl-fork.done .bar,.fk-tl-fork.here .bar{background:var(--ok)}
  .fk-flane{border-radius:10px;display:flex;align-items:center;gap:7px;padding:0 11px;min-width:0;position:relative;z-index:1}
  .fk-flane.take{height:46px;background:var(--panel3);border:1px solid var(--line2)}
  .fk-flane.skip{height:34px;margin-top:8px;border:1px dashed var(--line2);color:var(--dim)}   /* the route this job did NOT take, named rather than hidden */
  .fk-flane.skip .s-ic{width:13px;height:13px;flex:0 0 13px}
  .fk-flane.skip .t{font-size:11px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-mnode{width:18px;height:18px;border-radius:50%;display:grid;place-items:center;flex:none;font-size:10px;font-weight:800;background:var(--panel2);color:var(--dim)}
  .fk-mnode.done{background:var(--ok);color:#04281A}
  .fk-mnode.cur{background:var(--warn);color:#2A1D04;box-shadow:0 0 0 3px rgba(245,184,78,.18)}
  .fk-mnode.cur i{width:6px;height:6px;border-radius:50%;background:#2A1D04;display:block}
  .fk-flane .mlbl{min-width:0}
  .fk-flane .mlbl b{display:block;font-size:11.5px;font-weight:650;line-height:1.2;white-space:nowrap;color:var(--white)}
  .fk-flane .mlbl span{display:block;font-size:10px;color:var(--dim);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-flane .mconn{flex:1 1 10px;min-width:6px;height:2px;background:var(--line2)}
  .fk-flane .mconn.done{background:var(--ok)}
  .fk-tl-fork .fcap{text-align:center;margin-top:9px}
  .fk-tl-fork .fcap b{font-size:12px;font-weight:650;color:var(--dim)}
  .fk-tl-fork.here .fcap b{color:var(--here-ink,#f6c445)}
  .fk-tl-fork.on .fcap b{color:var(--white)}
  .fk-tl-fork .fcap .mt{display:block;font-size:11px;color:var(--dim);font-weight:650;margin-top:1px}
  .fk-tl-fork.here .fcap .mt{color:var(--here-ink,#f6c445)}
  .fk-tl-node .tl-lb{font-size:13px;font-weight:700;color:var(--dim);line-height:1.25;text-align:center;display:flex;align-items:center;gap:6px;justify-content:center}
  .fk-tl-node.here .tl-lb{color:var(--here-ink,#f6c445)}
  .fk-tl-node.on .tl-lb{color:var(--white)}
  /* the timeline nodes also carry the shared .fk-stab class (old tab-nav styling) — its .fk-stab.on gradient
     background + bottom bar leaked through here; higher specificity strips both, leaving just the dot/label */
  .fk-timeline .fk-tl-node.on{background:none}
  .fk-timeline .fk-tl-node.on::after{display:none}
  /* the owner's real photo, not a generic person glyph (owner 2026-08-11). fkAvatar() falls back to coloured
     initials, and to a dashed empty ring when nobody is on the stage — three states, all recognisable at 18px */
  /* THE PERSON IS THE MARKER (spec §5.2, 2026-09-08). The node used to carry a numbered dot on the
     connector and a 18px face below it — two circles about one stage. The face sits on the line now, at a
     size a real photograph is worth having, and its background is --panel so it punches a hole in the
     connector rather than sitting on top of it.
     THE RING IS THE PEOPLE-STATE AND NOTHING ELSE (spec §6): on it = solid green, waiting = dashed amber,
     nobody = dashed faint. Stage colour lives on the NAME above it, which is why the two never collide
     even though Design amber and waiting amber are a hex apart. */
  .fk-tl-node .tl-ow{display:flex;flex-direction:column;align-items:center;gap:8px;font-size:15px;color:var(--white);font-weight:600;max-width:100%;min-width:0}
  /* the ink goes with the fill: .fk-avatar is white text on a dark disc, and this swaps the disc for the theme's own
     panel — near-white on Marine, where the initials vanished (owner 2026-09-29) — so the text takes the theme's ink */
  .fk-tl-node .tl-ow .fk-avatar{width:72px;height:72px;font-size:22px;flex:none;background:var(--panel2);color:var(--white);z-index:1}
  .fk-tl-node .tl-ow.on .fk-avatar{box-shadow:0 0 0 2px var(--panel),0 0 0 4px var(--ok)}
  .fk-tl-node .tl-ow.was .fk-avatar{box-shadow:0 0 0 2px var(--panel),0 0 0 3px var(--ok)}
  .fk-tl-node .tl-ow.was{position:relative}
  .fk-tl-node .tl-ow.was .tl-tick{position:absolute;left:calc(50% + 14px);top:50px;width:22px;height:22px;border-radius:50%;background:var(--ok);
    border:2px solid var(--panel);color:#04241a;font-size:12px;font-weight:800;font-style:normal;display:grid;place-items:center;line-height:1;z-index:2}
  .fk-tl-node .tl-ow.wait .fk-avatar{outline:2px dashed var(--warn);outline-offset:2px}
  .fk-tl-node .tl-ow .fk-avatar.unassigned{background:var(--panel);border:1.5px dashed var(--faint)}
  .fk-tl-node .tl-ow .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:100%}
  .fk-tl-node .tl-ow.none{color:var(--faint);font-weight:400}
  /* the one line that says whether they KNOW they are up. Two words of colour, on the words only. */
  .fk-tl-node .tl-state{font-size:11.5px;font-weight:600;line-height:1.3;text-align:center;max-width:100%;color:var(--dim)}
  .fk-tl-node .tl-state.on{color:var(--ok)}
  .fk-tl-node .tl-state.wait{color:var(--warn)}
  .fk-tl-node .tl-state.done{color:var(--dim);font-weight:500}
  .fk-tl-node .tl-accept{margin-top:4px;height:30px;padding:0 13px;font-size:12px}
  /* --dim, not --faint. This line carries the phase's actual state ("route: trade", "or collection", the
     invoice number) at 10.5px, so it owes 4.5:1 — and --faint gave 3.85 on Onyx and 2.5 on the two light
     themes. The earlier theme sweep measured only the .here variant, which has its own ink and passed. */
  .fk-tl-node .tl-st{font-size:10.5px;color:var(--dim);max-width:96%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .fk-tl-node.here .tl-st{color:var(--here-ink,#f6c445);font-weight:700}
  /* internal-stage stepper (Design + Production panels) + the Request route picker — from the build target */
  .fk-steps{display:flex;gap:8px;margin:0 0 14px}
  .fk-stp{flex:1;min-width:0;border:1.5px solid var(--line2);border-radius:11px;padding:9px 13px;background:var(--panel);cursor:pointer;text-align:left;font-family:inherit;position:relative}
  .fk-stp .n{display:block;font-size:10px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--faint)}
  .fk-stp b{display:block;color:var(--dim);font-size:13.5px;margin-top:1px}
  .fk-stp .w{display:block;font-size:11.5px;color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .fk-stp.todo{opacity:.72}
  .fk-stp.done{border-color:rgba(12,166,120,.55)} .fk-stp.done .n{color:var(--ok)}
  .fk-stp.done::after{content:"✓";position:absolute;top:8px;right:9px;width:17px;height:17px;line-height:17px;text-align:center;background:var(--ok);color:#fff;border-radius:50%;font-size:11px;font-weight:800}
  /* CURRENT sub-stage — the next action; carries the NEXT badge (one marker, like the timeline's single current) */
  /* --accent-ink: the accent used as TEXT, which is a harder contrast bar than the same colour as a fill with
     white on it. A theme sets it only when its accent is bright enough to need it (Light Box, Marine); every
     other theme falls back to --accent and is unchanged. */
  .fk-stp.cur{border-width:2px;border-color:var(--accent);background:var(--accent-soft);box-shadow:0 3px 9px color-mix(in srgb,var(--accent) 20%,transparent);padding:8px 12px;opacity:1} .fk-stp.cur b,.fk-stp.cur .n{color:var(--accent-ink,var(--accent))}
  .fk-stp.cur::after{content:"NEXT";position:absolute;top:7px;right:8px;background:var(--accent);color:var(--on-accent);padding:2px 8px;border-radius:6px;font-size:9px;font-weight:800;letter-spacing:.06em}
  /* SELECTED/viewed sub-stage — a ring only, NEVER a badge, so a done stage keeps its ✓ and the current keeps NEXT */
  .fk-stp.sel{box-shadow:0 0 0 2px var(--accent),0 3px 9px color-mix(in srgb,var(--accent) 18%,transparent);opacity:1}
  /* when the WORK began on a sub-stage — not when the job reached it. Sits under the owner line on the card. */
  .fk-stp-go{display:block;margin-top:4px;font-size:11.5px;font-weight:700;color:var(--ok)}
  .fk-stp-no{display:block;margin-top:4px;font-size:11.5px;color:var(--faint)}
  .fk-stp.cur .fk-stp-go{color:var(--ok)}
  /* the Finishing start tick — a record once ticked, so it reads as a control only while it is one */
  .fk-tick{display:flex;align-items:center;gap:11px;width:100%;text-align:left;background:var(--panel);border:1.5px solid var(--line2);border-radius:var(--r-sm);padding:11px 13px;cursor:pointer;margin:0 0 4px}
  .fk-tick:hover{border-color:var(--accent)}
  .fk-tick .bx{width:19px;height:19px;border-radius:5px;border:2px solid var(--line2);flex:none}
  .fk-tick:hover .bx{border-color:var(--accent)}
  .fk-tick .t b{display:block;font-size:13.5px;color:var(--white)}
  .fk-tick .t span{display:block;font-size:11.5px;color:var(--dim);margin-top:1px}
  /* the accent is a FILL here, so the ink must be --on-accent like every other accent-filled control.
     These two rules hardcoded #fff and were the only ones that did: 1.4:1 on Marine's yellow, 2.2:1 on
     Forest's green — both themes' own comments say "never white" on the accent. */
  .fk-stof{font-size:11.5px;font-weight:800;color:var(--on-accent);background:var(--accent);padding:3px 11px;border-radius:999px;box-shadow:0 2px 6px color-mix(in srgb,var(--accent) 30%,transparent);white-space:nowrap}
  .fk-route{display:flex;gap:8px;margin-top:8px}
  .fk-ropt{flex:1;border:2px solid var(--line2);border-radius:11px;padding:11px 14px;cursor:pointer;background:var(--panel);text-align:left;font-family:inherit}
  .fk-ropt b{display:block;color:var(--white);font-size:13.5px}
  .fk-ropt span{font-size:12px;color:var(--dim)}
  .fk-ropt.on{border-color:var(--accent);background:var(--accent-soft)}
  .fk-ropt.on b{color:var(--accent)}
  .fk-ropt:disabled{cursor:default;opacity:.75}
  .fk-modechip{display:inline-flex;align-items:center;gap:6px;background:var(--accent-soft);color:var(--accent);border-radius:20px;padding:4px 12px;font-size:12px;font-weight:800}
  /* thumbnails: visible previews that EXPAND via the suite lightbox (download only inside it) */
  .fk-thumbtile{display:inline-block;width:84px;height:60px;border-radius:9px;overflow:hidden;border:1px solid var(--line2);cursor:zoom-in;position:relative;text-decoration:none}
  .fk-thumbtile img{width:100%;height:100%;object-fit:cover;display:block}
  /* a non-image, non-PDF file gets its type badge centred in the tile rather than an image filling it —
     the tile is position:relative already, which is what makes this the whole change */
  .fk-thumbtile > .s-fic{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%)}
  .fk-thumbtile.sm{width:64px;height:46px}
  /* a PDF has no image to preview, but it deserves a real thumbnail slot too (not a bare filename link) —
     a tinted tile with a PDF badge, same size/shape as an image thumbnail; clicking opens it inline (PDF is
     in the server's SAFE_INLINE list, same as chat's PDF preview) */
  /* a PDF tile now previews its first page behind the badge, so it stops being a grid cell and becomes a
     frame with something in it */
  .fk-thumbtile-pdf{background:rgba(216,67,58,.07);position:relative;overflow:hidden;cursor:pointer}
  /* the preview fills the tile and is INERT: pointer-events off, so the click belongs to the <a> around it
     exactly as it would for an <img>. Scaled up and offset so the PDF viewer's own margins fall outside. */
  .fk-pdfprev{position:absolute;inset:-8%;width:116%;height:116%;border:0;pointer-events:none;
    background:#fff;transform-origin:top left}
  /* the badge sits ON the preview, so a PDF is still recognisable as one at a glance */
  .fk-thumbtile-pdf .fk-pdf-badge{position:absolute;left:5px;bottom:5px;z-index:1;
    background:rgba(216,67,58,.92);color:#fff}
  .fk-pdf-badge{font-size:10.5px;font-weight:800;color:var(--danger);letter-spacing:.03em;background:rgba(216,67,58,.14);border-radius:5px;padding:2px 7px}
  .fk-thumbtile.sm .fk-pdf-badge{font-size:9px;padding:1px 5px}
  .fk-pdf-badge.sm{font-size:9px;padding:1px 5px}
  .fk-ff-ic-pdf{background:rgba(216,67,58,.07);border-color:rgba(216,67,58,.25);cursor:pointer}
  .fk-thumbgrid{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:10px}
  /* proofing revision timeline */
  .fk-rev{display:flex;flex-direction:column;margin-top:4px}
  .fk-rv{display:flex;gap:12px;align-items:flex-start;position:relative;padding:8px 0}
  .fk-rv + .fk-rv::before{content:"";position:absolute;left:11px;top:-7px;height:14px;width:2px;background:var(--line2)}
  .fk-rdot{width:23px;height:23px;border-radius:50%;display:grid;place-items:center;font-size:11px;font-weight:800;border:2px solid var(--line2);color:var(--faint);background:var(--panel);flex:none;margin-top:1px}
  .fk-rv.ok .fk-rdot{background:var(--ok);border-color:var(--ok);color:#fff}
  .fk-rv.chg .fk-rdot{border-color:var(--warn);color:var(--warn)}
  .fk-rline{font-size:13px;color:var(--dim);display:flex;align-items:center;gap:9px;flex-wrap:wrap;min-width:0}
  .fk-rline b{color:var(--white)}
  .fk-rres{font-size:12px;font-weight:700;border-radius:8px;padding:3px 9px}
  .fk-rres.bad{background:rgba(240,173,78,.16);color:var(--warn-ink,var(--warn))}
  .fk-rres.good{background:rgba(12,166,120,.15);color:var(--ok-ink,var(--ok))}
  /* Customer proof MARKUP (v21) — what the customer pinned, shown where the designer works.
     .fk-rv is a flex row (dot | content); .fk-rv-main is the content column so this panel stacks UNDER the
     status line rather than landing beside the dot. */
  .fk-rv-main{flex:1;min-width:0}
  .fk-mk{display:flex;gap:14px;align-items:flex-start;margin:9px 0 2px;padding:11px;border:1px solid var(--line2);border-radius:11px;background:var(--panel2);flex-wrap:wrap}
  .fk-mk-art{flex:0 1 300px;min-width:190px}
  /* the layer wraps ONLY the image, so a pin's % position maps to the artwork itself, not a padded box —
     this is what makes the customer's phone markup land in the right place here */
  .fk-mk-layer{position:relative;display:block;border-radius:7px;overflow:hidden;background:#fff;cursor:zoom-in}
  .fk-mk-layer img{display:block;width:100%;height:auto}
  /* affordance: the thumbnail is small by design, so say plainly that it opens — and keep the hint out of the
     way until hover so it never covers a pin while the designer is reading the marks */
  .fk-mk-layer::after{content:"⤢ Expand";position:absolute;right:6px;bottom:6px;background:rgba(6,8,16,.72);color:#fff;
    font:700 10px/1 system-ui,-apple-system,'Segoe UI',sans-serif;letter-spacing:.03em;padding:5px 8px;border-radius:7px;
    opacity:0;transition:opacity .12s ease;pointer-events:none}
  .fk-mk-layer:hover::after{opacity:1}
  .fk-mk-pin{position:absolute;width:21px;height:21px;margin:-10.5px 0 0 -10.5px;border-radius:999px;
    background:#c0392b;border:2px solid #fff;box-shadow:0 2px 6px rgba(0,0,0,.4);
    color:#fff;font:700 10.5px/1 system-ui,-apple-system,'Segoe UI',sans-serif;display:grid;place-items:center;cursor:default}
  .fk-mk-notes{flex:1 1 260px;min-width:0}
  .fk-mk-h{font-size:11px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--warn);margin-bottom:8px}
  /* aligned columns: number | note | time — never a ragged run-on string */
  /* G4.5: the pin list is a CHECKLIST — a leading tick column, so the designer works down the customer's
     points and the next revision stays blocked until they are all cleared. */
  .fk-mk-row{display:grid;grid-template-columns:20px 22px 1fr auto;gap:9px;align-items:start;padding:6px 0;border-top:1px solid var(--line2)}
  .fk-mk-row:first-of-type{border-top:none}
  .fk-mk-tick{width:20px;height:20px;margin-top:1px;padding:0;display:grid;place-items:center;border:1.5px solid var(--line2);
    border-radius:6px;background:transparent;color:var(--ok);font-size:12px;font-weight:800;line-height:1;cursor:pointer}
  .fk-mk-tick:hover{border-color:var(--ok)}
  .fk-mk-tick[data-mkdone="1"]{background:var(--ok);border-color:var(--ok);color:#fff}
  .fk-mk-row.done .fk-mk-b{color:var(--dim);text-decoration:line-through;text-decoration-color:var(--line2)}
  .fk-mk-row.done .fk-mk-n{background:var(--ok)}
  .fk-mk-prog{float:right;font-size:10.5px;font-weight:800;letter-spacing:.04em;color:var(--dim);text-transform:none}
  .fk-mk-prog.all{color:var(--ok)}
  .fk-mk-n{width:20px;height:20px;border-radius:999px;background:#c0392b;color:#fff;font-size:10.5px;font-weight:800;display:grid;place-items:center;margin-top:1px}
  .fk-mk-b{font-size:12.5px;color:var(--white);line-height:1.45;word-break:break-word}
  .fk-mk-t{font-size:11px;color:var(--faint);white-space:nowrap;margin-top:2px}
  /* customer change-request photos for this round — they arrive with the feedback, so they live with it */
  .fk-mk-atts{display:flex;flex-wrap:wrap;gap:7px}
  .fk-mk-att{width:56px;height:56px;border-radius:8px;overflow:hidden;border:1px solid var(--line2);background:var(--panel);display:grid;place-items:center;flex:none}
  .fk-mk-att img{width:100%;height:100%;object-fit:cover;display:block}
  .fk-mk-att-f{color:var(--faint);display:grid;place-items:center}
  /* Money paperwork rows. The status BANNER that used to head this card (.fk-paybar) is gone with the Paid
     Job rework — the same five states are now the one .fk-owed line under the total they are a fraction of.
     --danger/--warn/--ok are tuned for a DARK panel; as text on a pale tint they measured 2.15–4.29:1 on the
     three light themes, which is why the tags below take the --*-ink tokens instead. */
  .fk-paper{display:flex;flex-direction:column;gap:7px;margin-top:11px}
  .fk-prow{display:flex;align-items:center;gap:10px;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:9px 13px;font-size:13px;flex-wrap:wrap}
  .fk-prow b{color:var(--white)}
  .fk-prow .act{margin-left:auto;display:flex;gap:7px}
  .fk-ptag{font-size:10.5px;font-weight:800;border-radius:14px;padding:2px 9px;letter-spacing:.03em}
  .fk-ptag.ok{background:rgba(12,166,120,.14);color:var(--ok-ink,var(--ok))}
  .fk-ptag.warn{background:rgba(240,173,78,.16);color:var(--warn-ink,var(--warn))}
  .fk-ptag.red{background:rgba(216,67,58,.12);color:var(--danger-ink,var(--danger))}
  /* file tiles: image thumbnail (click = suite lightbox) or a compact chip, each with its delete ✕ */
  .fk-filetile{position:relative;display:inline-block}
  .fk-filetile .fk-fdel{position:absolute;top:-6px;right:-6px}
  .fk-fdel{width:18px;height:18px;border-radius:50%;border:none;background:rgba(0,0,0,.55);color:#fff;font-size:10px;line-height:1;cursor:pointer;display:grid;place-items:center}
  .fk-filechip{display:inline-flex;align-items:center;gap:8px;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:7px 10px;font-size:12px}
  .fk-filechip .s{color:var(--dim);font-size:11px}
  .fk-stagenav{container-type:inline-size;display:flex;align-items:stretch;background:var(--panel);border:1px solid var(--line);border-radius:12px;overflow:hidden;margin:2px 0 16px}
  .fk-stab{flex:1;min-width:0;display:flex;align-items:center;gap:9px;padding:11px 11px;cursor:pointer;background:transparent;border:none;border-right:1px solid var(--line);position:relative;transition:.15s;font-family:inherit;text-align:left}
  .fk-stab:last-child{border-right:none}
  .fk-stab:hover{background:rgba(255,255,255,.03)}
  .fk-stab .bub{width:25px;height:25px;border-radius:50%;display:grid;place-items:center;font-weight:700;font-size:12px;background:var(--panel3);border:1.5px solid var(--line2);color:var(--dim);flex:none;transition:.15s}
  .fk-stab .lab{font-size:12px;color:var(--dim);font-weight:600;line-height:1.16;min-width:0}
  .fk-stab .lab .t{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-stab .lab .s{display:block;font-size:9.5px;color:var(--faint);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:1px}
  /* the tab bar degrades as the pane narrows (the gutter is user-draggable): drop the sub-labels, then labels → bubbles only */
  @container (max-width:560px){
    .fk-stab{gap:7px;padding:10px 8px}
    .fk-stab .lab .s{display:none}
  }
  @container (max-width:440px){
    .fk-stab{justify-content:center;padding:10px 4px}
    .fk-stab .lab{display:none}
  }
  .fk-stab.done .bub{background:rgba(12,166,120,.16);border-color:rgba(12,166,120,.5);color:var(--ok)}
  .fk-stab.done .lab{color:var(--text)}
  .fk-stab.on{background:linear-gradient(180deg,var(--accent-soft),transparent)}
  .fk-stab.on .bub{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
  .fk-stab.on .lab{color:var(--white)}
  .fk-stab.on::after{content:'';position:absolute;left:0;right:0;bottom:0;height:2.5px;background:var(--accent)}
  .fk-navsep{width:1px;background:var(--line2);margin:8px 0;flex:none}
  .fk-stab.money .bub{background:rgba(245,185,20,.14);border-color:rgba(245,185,20,.5);color:var(--warn)}
  .fk-stab.money.on{background:linear-gradient(180deg,rgba(245,185,20,.12),transparent)}
  .fk-stab.money.on .bub{background:var(--warn);border-color:var(--warn);color:#3a2c00}
  .fk-stab.money.on::after{background:var(--warn)}
  .fk-stage{display:none}
  .fk-stage.on{display:block}
  .fk-sec{background:var(--panel2);border:1px solid var(--line);border-radius:11px;padding:13px 15px;margin-bottom:11px}
  .fk-sec h4{color:var(--dim);font-size:11px;text-transform:uppercase;letter-spacing:.06em;margin:0 0 10px}
  /* h4.zone is FK-only (5 sites). The colour was declared ONLY under .fk-sec, so the drawer's panel titles —
     Paid Job, Design, Production, Delivery, Archived, Team chat — matched no rule and inherited the SUITE
     root --text instead of the FK theme's. Inheritance passes a computed colour, so being inside the themed
     subtree does not help: they came out #cbd0dc on all four themes. 11.46:1 on Onyx, 1.54:1 on Light Box. */
  h4.zone{color:var(--white)}
  .fk-sec h4.zone{color:var(--white);font-size:13.5px;font-weight:700;text-transform:none;letter-spacing:0;margin:0 0 9px}
  .fk-sub-h{color:var(--dim);font-size:11px;text-transform:uppercase;letter-spacing:.06em;font-weight:700;margin:16px 0 8px}
  /* numbered band label — the 5-band rhythm marker (Timeline · Stage · Who · Files · Sign-off) */
  .fk-band-l{display:flex;align-items:center;gap:8px;font-size:10px;text-transform:uppercase;letter-spacing:.07em;color:var(--faint);font-weight:800;margin:15px 0 8px}
  .fk-band-l .n{width:17px;height:17px;border-radius:50%;background:var(--panel3);color:var(--dim);display:grid;place-items:center;font-size:10px;flex:none}
  /* ---- the ARTWORK ROUTE fork (Design panel): taken vs not taken, same language as the Production node.
     NOT .fk-route — that name is already declared above for the old .fk-ropt picker, and two rules on one
     class name is how the .fk-pstage and .fk-empty collisions happened. ---- */
  .fk-aroute{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:0 0 12px}
  .fk-art{display:flex;align-items:center;gap:10px;padding:11px 13px;border-radius:10px;border:1px dashed var(--line2);background:none;min-width:0}
  .fk-art.on{border-style:solid;border-color:color-mix(in srgb,var(--accent) 45%,transparent);background:var(--accent-soft)}
  .fk-art .ic{flex:none;display:inline-flex;color:var(--dim)}
  .fk-art.on .ic{color:var(--accent)}
  .fk-art .ic .s-ic{width:15px;height:15px;flex:0 0 15px}
  /* a flex COLUMN, or the title and its sub-line run together into one sentence */
  .fk-art .rtx{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}
  .fk-art .rtx b{font-size:12.5px;font-weight:650;color:var(--text)}
  .fk-art.on .rtx b{color:var(--white)}
  /* --dim measured 3.94:1 on the tinted ground of the TAKEN card on Light Box — the sub-line carries the
     route's actual meaning, so it takes --text there rather than being dimmed below the floor */
  /* WRAPS to two lines rather than ellipsising. The @media (max-width:860px) below asks the VIEWPORT, but this
     pane is narrow because the chat and Today panels take the width, not because the window is small — at a
     614px pane inside a 1280px window the query never fires and the line read "Pre-flight check instead, no
     custo…", losing the words that say what the route actually does. Two lines cost 14px and always work. */
  .fk-art .rtx span{font-size:11px;color:var(--dim);line-height:1.35;
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .fk-art.on .rtx span{color:var(--text)}
  /* likewise --dim on --panel3 measured 4.08:1; 10px bold is not "large text", so it needs the full 4.5 */
  .fk-art .tag{flex:none;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;padding:3px 7px;border-radius:5px;background:var(--panel3);color:var(--text)}
  .fk-art.on .tag{background:var(--accent);color:var(--on-accent)}
  @media (max-width:860px){ .fk-aroute{grid-template-columns:1fr} }
  /* ---- THE DESIGN STAGES, drawn as a timeline and stacked (owner 2026-08-08) ----------------------------
     The row itself is .fk-timeline / .fk-tl-node, reused from the phase timeline above it with no changes.
     .fk-dtl is the one override: that row spreads FIVE nodes whose states are short ("or collection"), and
     three design stages across a 614px pane give each node ~195px while the state that matters most —
     "revision 2 · with the customer" — needs 210px, so it truncated mid-word on the shop's own laptop. */
  .fk-dtl .tl-st{white-space:normal;line-height:1.35;max-width:100%;
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .fk-dtl .tl-ow{max-width:100%}
  .fk-dtl .fk-tl-node{cursor:pointer}
  .fk-dtl .fk-tl-node:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:10px}
  /* Each stage is its own block, and all three are on screen: the brief a designer re-reads while working is
     no longer a click away from the artwork it describes. */

  /* ═══ THE PHASE PANEL AS ONE SPINE (owner 2026-08-16) ═══════════════════════════════════════════
     "i do not like the layout of processing orders … Same steps by UI is confusing and very bad."
     Three stacked cards became one continuous spine, ported from the approved mock,
     docs/prototype/future-knights/order-drawer-full.html. Measured before: the panel spent 244px — 35% of
     its stage area — on two cards whose whole content was "you cannot do this yet", while Stage 2 rendered
     six real controls purely to disable them.
     The rail carries the step's NAME (never a number: one numbering rule, digits belong to phases) and the
     dot carries the state. No tinted cards: the owner asked for no colour coding, so state is the dot and
     the type weight, and the only accent left on the screen is the step you are standing on. */
  .fk-phhead{display:flex;align-items:center;gap:14px;padding:0 0 13px;margin-bottom:0;border-bottom:1px solid var(--line)}
  .fk-phhead .t{flex:1;min-width:0}
  .fk-phhead h4{font-size:15px;font-weight:700;color:var(--white);margin:0;letter-spacing:-.1px}
  .fk-phhead .sub{font-size:12px;color:var(--dim);margin-top:2px}
  .fk-routechip{flex:none;border:1px solid var(--line2);background:var(--panel2);border-radius:999px;
    padding:6px 13px;font-size:12px;color:var(--dim);white-space:nowrap}
  .fk-routechip b{color:var(--white);font-weight:650}
  /* THE DESIGN CLOCK. One chip, three modes, so it always answers the same question: who has it, and how
     long. Amber is the only colour it uses, and only when the proof is due today or past — otherwise a
     screen that is always coloured tells you nothing when something is actually wrong. */
  .fk-clk{flex:none;display:inline-flex;align-items:center;gap:7px;white-space:nowrap;
    border:1px solid var(--line2);background:var(--panel2);border-radius:999px;padding:6px 13px;
    font-size:12px;color:var(--dim)}
  .fk-clk b{color:var(--white);font-weight:700;font-variant-numeric:tabular-nums}
  .fk-clk.hold{color:var(--faint)}
  .fk-clk.done,.fk-clk.done b{color:var(--ok-ink,var(--ok))}
  .fk-clk.late{border-color:rgba(199,120,0,.5);background:rgba(240,173,78,.12);color:var(--warn-ink,var(--warn))}
  .fk-clk.late b{color:var(--warn-ink,var(--warn))}
  /* (.fk-pfrow — the pre-flight checks — is defined ONCE, further down. Not here: a second rule for the same
     class, later in the same sheet, is what turned the Job Board into a two-column grid this morning.) */
  /* WHAT THE FILE SAYS ABOUT ITSELF — read off the bytes at upload, never asked of anyone. Quiet by
     default: a row of small facts under the revision line, with amber only on the ones worth a second look.
     Deliberately NOT a card and NOT a badge — it is a read-out beside the file, not an alarm about it, and
     nothing here is ever a gate. */
  .fk-facts{display:flex;flex-wrap:wrap;gap:6px;margin:7px 0 0}
  .fk-facts .f{font-size:11.5px;color:var(--dim);background:var(--panel2);border:1px solid var(--line);
    border-radius:6px;padding:3px 8px;font-variant-numeric:tabular-nums}
  .fk-facts .f.warn{color:var(--warn-ink,var(--warn));border-color:rgba(199,120,0,.42);background:rgba(240,173,78,.10)}
  .fk-facts .f.unknown{color:var(--faint);border-style:dashed}
  /* under a thumbnail rather than under a row: narrower, and it must not stretch the tile it belongs to */
  .fk-facts.sm{display:flex;max-width:190px;margin-top:5px;gap:4px}
  .fk-facts.sm .f{font-size:10.5px;padding:2px 6px}
  /* WHICH LINE a print file is for (v90). Only ever rendered on an itemised order — on a single-product job
     "the whole order" is the only thing it could mean, and saying so is noise. */
  .fk-ff-for{display:inline-block;font-size:11.5px;color:var(--dim);background:var(--panel3);border-radius:5px;
    padding:1px 7px;margin-top:3px}
  .fk-ff-pick{display:flex;align-items:center;gap:9px;margin:0 0 10px;font-size:12.5px;color:var(--dim);flex-wrap:wrap}
  .fk-ff-pick .fk-input{margin-bottom:0;max-width:260px}
  /* the gate's own reason, in the gate's own words — amber because it is the thing keeping Production shut */
  .fk-ff-missing{margin:9px 0 0;padding:8px 12px;font-size:12.5px;border-radius:9px;
    background:rgba(240,173,78,.11);border:1px solid rgba(199,120,0,.4);color:var(--warn-ink,var(--warn))}
  .fk-ff-missing b{color:inherit;font-weight:700}
  /* THE PROOF CHECK (v91). Quiet by construction: a clean result is a single grey line, because a check that
     shouts when it is happy stops meaning anything when it is not. Findings are amber — the same amber as
     everything else on this screen that wants a second look — and nothing here is ever red, because nothing
     here decides anything. */
  /* ONE report per file: a summary line you can scan, the whole thing on click. It replaced a row of loose
     chips plus a block underneath — which gave a measurement and a warning the same visual weight, said the
     same fact twice, and never explained what any of it meant. */
  .fk-chk{margin:8px 0 0;font-size:12.5px;border-radius:9px;border:1px solid var(--line);background:var(--panel2)}
  /* `.fk-drawer` in the selector on purpose. The drawer styles EVERY <details> summary as a small uppercase
     label (`.fk-drawer details>summary`, for Activity log and the like), which out-specifies a bare
     `.fk-chk>summary` by one type selector — so a one-line verdict arrived SHOUTING IN CAPITALS. This is an
     override of a deliberate generic rule, not a second definition of the same thing. */
  .fk-drawer .fk-chk>summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:10px;
    padding:8px 12px;text-transform:none;letter-spacing:normal;font-size:12.5px;font-weight:400;color:var(--dim)}
  .fk-drawer .fk-chk>summary::-webkit-details-marker{display:none}
  .fk-drawer .fk-chk>summary:after{content:"▾";margin-left:auto;color:var(--faint);font-size:11px}
  .fk-drawer .fk-chk[open]>summary:after{content:"▴"}
  .fk-drawer .fk-chk>summary:hover{background:color-mix(in srgb,var(--white) 4%,transparent);border-radius:8px}
  .fk-chk>summary:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
  .fk-chk .v{font-weight:650;color:var(--dim)}
  .fk-chk .s{font-size:11.5px;color:var(--faint)}
  .fk-chk.clean .v{color:var(--ok-ink,var(--ok))}
  .fk-chk.hit{border-color:rgba(199,120,0,.42);background:rgba(240,173,78,.08)}
  .fk-chk.hit .v{color:var(--warn-ink,var(--warn))}
  .fk-chk.pending .v{color:var(--faint)}
  /* "nobody read this" must be visibly its OWN state, not a quieter version of clean — a dashed edge and no
     tick. `.fk-chk.unknown` is a compound on the panel; `.fk-chk .row.unknown` below is a descendant on one
     row. Different selectors, deliberately, and neither shadows the other. */
  /* WHERE THIS JOB HAS BEEN (v93). Names checked against this file before use — `.fk-band` taught us what a
     bare common word costs, and `seg` is exactly the kind of name a second feature reaches for, so it is
     scoped under .fk-journey and never used alone. */
  /* ============ ADMIN SETTINGS → USERS (rebuilt 2026-08-18) ============
     Every class here is prefixed `u-` and every name was checked against this file before use. `.stat`,
     `.menu`, `.grid` and `.tabs` are exactly the words a second feature reaches for, and `.fk-band` already
     cost us a live Job Board once. */
  .u-teams{display:flex;gap:2px;border-bottom:1px solid var(--line);margin:2px 0 14px}
  .u-team{background:none;border:0;border-bottom:2px solid transparent;color:var(--dim);font:inherit;
    font-size:14px;padding:9px 15px;cursor:pointer;display:flex;align-items:center;gap:8px}
  .u-team:hover{color:var(--text)}
  .u-team.on{color:var(--white);border-bottom-color:var(--accent);font-weight:650}
  .u-team .n{font-size:11px;font-variant-numeric:tabular-nums;background:var(--panel3);color:var(--dim);
    border-radius:var(--r-pill);padding:1px 8px}
  .u-team.on .n{background:var(--accent-soft);color:var(--accent)}

  .u-table td{vertical-align:middle}
  .u-nm{color:var(--white);font-weight:600}
  .u-you{font-size:11px;color:var(--faint);font-weight:400}
  .u-em,.u-rl{color:var(--dim)}
  .u-st{white-space:nowrap}
  .u-active{font-size:12px;color:var(--faint)}
  .u-empty{padding:30px 0;text-align:center;color:var(--faint)}
  tr.u-open{background:var(--panel2)}
  .u-exp{background:none;border:0;color:var(--dim);cursor:pointer;font-size:12px;padding:3px 6px;border-radius:5px}
  .u-exp:hover{background:var(--panel3);color:var(--white)}
  .u-kw{position:relative;display:inline-block;float:right}
  .u-kebab{background:none;border:1px solid transparent;border-radius:6px;color:var(--dim);cursor:pointer;
    font-size:17px;line-height:1;padding:1px 9px}
  .u-kebab:hover{background:var(--panel3);color:var(--white);border-color:var(--line)}
  .u-menu{position:absolute;right:0;top:100%;margin-top:4px;background:var(--panel2);border:1px solid var(--line2);
    border-radius:var(--r-sm);box-shadow:0 14px 34px -12px rgba(0,0,0,.7);min-width:206px;z-index:30;padding:5px;
    text-align:left;white-space:nowrap}
  .u-menu .btn{display:block;width:100%;text-align:left;background:none;border:0;margin:0;border-radius:6px}
  .u-menu .btn:hover{background:var(--panel3)}
  .u-menu hr{border:0;border-top:1px solid var(--line);margin:5px 3px}

  .u-det-in{padding:16px 18px 18px;background:var(--panel2)}
  .u-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px 26px}
  .u-h{font-size:10.5px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--faint);margin:0 0 8px}
  .u-fields{display:grid;grid-template-columns:96px 1fr;gap:8px 10px;align-items:center}
  .u-fields label{font-size:13px;color:var(--dim)}
  .u-fields .field{margin:0;width:100%}
  .u-tabs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 12px}
  .u-tk{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text);background:var(--panel);
    border:1px solid var(--line);border-radius:6px;padding:6px 9px;cursor:pointer}
  .u-tk input{margin:0;width:15px;height:15px;accent-color:var(--accent);flex:none}
  .u-tk.on{border-color:rgba(0,184,217,.4);background:var(--accent-soft)}

  /* the department's modules — READ ONLY, and dashed so it reads as a statement rather than a control */
  .u-ro{background:var(--panel);border:1px dashed var(--line2);border-radius:var(--r-sm);padding:10px 12px}
  .u-why{font-size:12px;color:var(--faint);line-height:1.5;margin:0 0 8px}
  .u-nomods{font-size:12px;color:var(--faint)}
  .u-mgrp{display:flex;gap:10px;align-items:baseline;padding:5px 0;border-top:1px solid var(--line)}
  .u-mgrp:first-of-type{border-top:0;padding-top:1px}
  .u-mgrp > b{color:var(--text);font-size:12px;font-weight:650;flex:0 0 100px}
  .u-allof{font-size:11px;color:var(--faint);font-style:italic}
  .u-mods{display:flex;flex-wrap:wrap;gap:5px}
  .u-mod{font-size:11px;background:var(--panel3);color:var(--text);border-radius:var(--r-pill);padding:2px 9px}
  .u-mod.no{opacity:.35;text-decoration:line-through;color:var(--dim)}

  .u-stats{display:flex;gap:8px;flex-wrap:wrap}
  .u-stat{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-sm);padding:8px 12px;min-width:100px}
  .u-stat b{display:block;font-size:17px;font-weight:650;color:var(--white);font-variant-numeric:tabular-nums;line-height:1.25}
  .u-stat span{display:block;font-size:10.5px;color:var(--faint);text-transform:uppercase;letter-spacing:.05em;margin-top:2px}
  .u-stat.quiet b{color:var(--dim)}

  /* WHERE THE TIME HAS GONE — the mock's .row.time (paid-job-v2), measurement for measurement. It was a
     bordered panel: a header row with a running total, a 26px bar of per-visit segments, and up to three
     clear-by sentences under it. The owner asked for the drawing instead — "I want this exact one" — so it
     is a 128px label beside one hairline track with two facts under it, and nothing else.
     128px is the same label column .fk-pj rows use, which is what puts every label on the page — this one,
     Money, Artwork, Next — on ONE left edge. `.lbl`, `.val`, `.bar` and `.tl` are the mock's own class
     names and are scoped under .fk-journey for that reason: three of the four are words a second feature
     would reach for, and .fk-band already cost us a live Job Board once. */
  .fk-journey{display:grid;grid-template-columns:128px 1fr;align-items:start;column-gap:16px;
    margin:0 var(--fk-gut) 4px;padding:11px 0 10px;border-top:1px solid var(--line)}
  .fk-journey .lbl{padding-top:1px;line-height:1.3;font-size:13px;font-weight:500;color:var(--dim)}
  .fk-journey .val{min-width:0}
  .fk-journey .bar{height:8px;border-radius:4px;background:var(--panel3);overflow:hidden;margin-top:6px}
  .fk-journey .bar i{display:block;height:100%;border-radius:4px}
  .fk-journey .tl{display:flex;justify-content:space-between;gap:16px;margin-top:7px;font-size:12px;color:var(--dim)}
  .fk-journey .tl b{color:var(--text);font-weight:500;font-variant-numeric:tabular-nums}
  /* late is the ONE state that recolours this line; the fill goes red with it, so the bar and the words say
     the same thing rather than a full green bar sitting over the word "past". */
  .fk-journey .tl .late,.fk-journey .tl .late b{color:var(--danger-ink,var(--danger))}
  /* AT RISK: amber, because it has not gone wrong yet. `due-late` red already means it has. */
  .fk-chip.risk-now{background:rgba(240,173,78,.16);color:var(--warn-ink,var(--warn));font-weight:700}
  .fk-chk.unknown{border-style:dashed}
  .fk-chk.unknown .v{color:var(--dim)}
  /* the amend-round count. Names checked against public/index.html first — .fk-band taught us what a bare
     common name costs, and `.pip` is exactly the kind of word two features reach for. Scoped under .fk-rounds. */
  .fk-rounds{display:flex;align-items:center;gap:9px;margin:0 0 10px;font-size:12.5px;color:var(--dim)}
  .fk-rounds .n{font-weight:650;color:var(--white)}
  .fk-rounds.over .n{color:var(--warn-ink,var(--warn))}
  .fk-rounds .pips{display:flex;gap:4px;margin-left:2px}
  .fk-rounds .pip{width:18px;height:4px;border-radius:3px;background:var(--panel3)}
  .fk-rounds .pip.used{background:var(--accent)}
  .fk-rounds .pip.over{background:var(--warn)}
  .fk-chk .b{padding:2px 12px 11px}
  .fk-chk .sec{font-size:10.5px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--faint);margin:9px 0 5px}
  .fk-chk .row{display:flex;flex-direction:column;gap:2px;padding:7px 0;border-top:1px solid var(--line)}
  .fk-chk .row b{color:var(--white);font-weight:600}
  .fk-chk .row span{color:var(--dim);font-size:11.5px;line-height:1.5}
  .fk-chk .row.warn b{color:var(--warn-ink,var(--warn))}
  .fk-chk .row.ok b{color:var(--ok-ink,var(--ok))}
  .fk-chk .row.unknown b{color:var(--faint)}
  .fk-chk .n{margin-top:10px;padding-top:9px;border-top:1px solid var(--line);font-size:11.5px;color:var(--faint)}

  /* what the order IS — repeated on every phase, because .fk-stage hides all but the open panel and the
     line items used to live on Paid Job alone */
  .fk-lines{padding:13px 0;border-bottom:1px solid var(--line)}
  .fk-lines .lh{display:flex;align-items:baseline;gap:10px;margin-bottom:8px}
  .fk-lines .lh b{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--faint);font-weight:700}
  .fk-lines .lh .n{margin-left:auto;font-size:11.5px;color:var(--dim)}
  .fk-lines .ln{display:flex;align-items:baseline;gap:12px;padding:6px 0;border-top:1px solid var(--line)}
  .fk-lines .ln:first-of-type{border-top:0}
  .fk-lines .ln .d{flex:1;min-width:0;font-size:13px;color:var(--white);font-weight:600}
  .fk-lines .ln .sp{display:block;font-size:11.5px;color:var(--faint);font-weight:400;margin-top:1px}
  /* a line after a credit note: "was 10 · CN1" under the words, or the words struck when it was removed */
  .fk-lines .ln .was{display:block;font-size:11.5px;color:var(--warn);font-weight:500;margin-top:1px}
  /* the strike goes on the WORDS only (.dt) — a parent's line-through propagates to every descendant and a
     child cannot undo it, so striking .d took "Removed · CN2" down with it (seen on screen) */
  .fk-lines .ln.removed .dt{text-decoration:line-through;color:var(--dim)}
  .fk-lines .ln.removed .sp{color:var(--dim)}
  .fk-cnmode{display:flex;gap:16px;margin:0 0 12px}
  .fk-cnpreview{font-size:13px;color:var(--text);margin:2px 0 12px;min-height:18px}
  /* Rename a line in place (owner 2026-08-26) — the WORDS only; the ×qty and the £ beside it are not part of
     this control. The pencil is hidden until the row is hovered or focus is inside it, so the block still
     reads as a list; it appears rather than the text being silently clickable, because a span that quietly
     accepts a click is not an affordance. :focus-within keeps it reachable by keyboard, where hover cannot go. */
  .fk-lines .ln .lnpen{flex:none;display:inline-flex;align-items:center;justify-content:center;width:24px;height:22px;
    padding:0;border:0;background:none;color:var(--faint);border-radius:5px;cursor:pointer;opacity:0;transition:.12s}
  .fk-lines .ln .lnpen .s-ic{width:14px;height:14px}
  .fk-lines .ln:hover .lnpen,.fk-lines .ln:focus-within .lnpen{opacity:1}
  .fk-lines .ln .lnpen:hover{color:var(--accent);background:var(--accent-soft,rgba(62,207,220,.13))}
  .fk-lines .ln .lnpen:focus-visible{opacity:1;outline:var(--focus-ring);outline-offset:1px}
  /* the field takes the description's place exactly — same flex slot, same weight, so nothing jumps */
  .fk-lines .ln .lnedit{flex:1;min-width:0}
  .fk-lines .ln .lnedit input{width:100%;margin-bottom:0;font-size:13px;font-weight:600;line-height:1.35;padding:4px 8px}
  .fk-lines .ln .q{flex:none;font-size:12.5px;color:var(--dim);font-variant-numeric:tabular-nums}
  /* Paid Job · step 1 renders the SAME list priced, inside the money area, and applyDrawerStage hides the
     band above while that panel is open — so the lines appear once per page either way. */
  .fk-lines.priced{padding:0;border-bottom:0}
  .fk-lines .ln .amt{flex:none;min-width:76px;text-align:right;font-size:13px;color:var(--text);font-variant-numeric:tabular-nums}
  .fk-pjtot{display:flex;align-items:baseline;gap:8px;justify-content:flex-end;margin-top:9px;padding-top:9px;
    border-top:1px solid var(--line);font-size:12px;color:var(--faint)}
  .fk-pjtot b{font-size:16px;color:var(--white);font-weight:700;letter-spacing:-.2px}
  /* what is still owed: ONE line under the total it is a fraction of, not the old full-width banner. The
     banner was 15.5px/800 and bordered in its own colour, so on a page where the money is already the first
     thing it shouted at a reader who had just read the same figure. The state still leads, and still leads
     in the state's colour — it just no longer needs a box of its own to be found. */
  .fk-owed{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:13px;padding-top:13px;
    border-top:1px solid var(--line2)}
  .fk-owed .h{font-size:14px;color:var(--white);font-weight:650}
  .fk-owed.warn .h{color:var(--warn-ink,var(--warn))}
  .fk-owed.bad .h{color:var(--danger-ink,var(--danger))}
  .fk-owed.ok .h{color:var(--ok-ink,var(--ok))}
  .fk-owed .act{margin-left:auto;display:flex;gap:8px;flex-wrap:wrap}
  .fk-owed .s{width:100%;font-size:11.5px;color:var(--dim)}
  /* the four allocation decisions as label | control, so they line up instead of sitting as loose columns
     that re-flow at every width. The zeroed margin is the global `input{margin-bottom:16px}` (index.html
     head) reaching selects through .fk-input — in a grid cell it inflates the row and lifts the text off
     the baseline the label sits on. */
  /* ── THE PAID JOB PAGE (spec §5/§6, mock paid-job-v2) ─────────────────────────────────────────────────
     ONE grid, header to send: a 128px label column, one value column, one action column, so every button's
     right edge lands on the same x and the eye reads down the labels. Rows are hairlines; the only outlined
     box is "The job", because that is the only thing on the page that is a thing rather than a fact about it.
     Names are all `fk-pj*` on purpose. The mock's own class names — .row, .btn, .who, .sub, .st — are each
     already taken by an unscoped rule in this sheet, and `.fk-band` is what happens when that is not checked:
     the Job Board broke on live while 3,495 tests stayed green, because jsdom has no cascade. */
  .fk-pjrow{display:grid;grid-template-columns:128px minmax(0,1fr) auto;column-gap:16px;align-items:center;
    min-height:44px;padding:8px 0;border-top:1px solid var(--line)}
  .fk-pjrow.fk-pjrow-art{align-items:start}
  .fk-pjrow.fk-pjrow-art .fk-pjl{padding-top:18px}   /* optically centred on the CONTROL, not on control+tail */
  .fk-pjl{font-size:13px;font-weight:500;color:var(--dim)}
  .fk-pjv{min-width:0;font-size:13px;color:var(--text)}
  .fk-pjv.dim{color:var(--dim)}
  .fk-pja{display:flex;gap:8px;align-items:center;justify-self:end}
  /* `input{margin-bottom:16px}` is global and reaches every .fk-input; in a grid cell it inflates the row by
     16px and lifts the text off the baseline the label sits on. Five controls in this suite have been bitten. */
  .fk-pjrow .fk-input,.fk-pjjob .fk-input{margin-bottom:0}
  /* the one outlined box */
  .fk-pjjob{border:1px solid var(--line2);border-radius:12px;margin:2px 0 34px;overflow:hidden;background:var(--panel2)}  /* a shade lighter than the panel, and room before the stage (owner 2026-09-10) */
  /* The order box opens with who it is for and when it is due, then says what the order is. Both boxes
     that can hold it — the priced one on Paid Job, #fk-lines on every other page — get the same band,
     and the child combinator keeps it off the .fk-hd of anything nested later. */
  .fk-pjjob>.fk-hd{padding:12px 14px 13px;border-bottom:1px solid var(--line2)}
  .fk-pjjob>.fk-lines{padding:0;border-bottom:0}
  .fk-pjjob>.fk-lines>.lh{padding:8px 14px;margin:0;border-bottom:1px solid var(--line2)}
  .fk-pjjob-t{padding:7px 14px;font-size:13px;font-weight:600;color:var(--white);border-bottom:1px solid var(--line2);display:flex;align-items:center;gap:10px;min-height:38px}
  /* ✎ Edit order sits at the right of the job box's title — the door beside the lines it opens (owner 2026-09-10);
     the money row below keeps its one action */
  .fk-pjjob-t .fk-btn{margin-left:auto}
  .fk-pjjob .fk-lines.priced{padding:0}
  .fk-pjjob .fk-lines .ln{padding:7px 14px;gap:16px}
  .fk-pjjob .fk-lines .ln .q{width:56px;text-align:right;font-size:14px;font-weight:600;color:var(--white)}
  .fk-pjjr{display:grid;grid-template-columns:56px minmax(0,1fr);column-gap:16px;padding:9px 14px;border-top:1px solid var(--line)}
  .fk-pjjr .k{font-size:13px;font-weight:500;color:var(--dim);text-align:right}
  .fk-pjjr .k small{display:block;font-size:10.5px;color:var(--faint);line-height:1.2;margin-top:2px}
  .fk-pjjr .v{min-width:0}
  .fk-pjchat{display:flex;align-items:center;gap:9px;margin-top:9px;font-size:12.5px;color:var(--white);cursor:pointer}
  .fk-pjchat input{margin:0;width:15px;height:15px;flex:0 0 auto}
  /* the money line: state · total · invoice, hairline-separated (the mock's replacement for middle dots) */
  .fk-pjrow .fk-owed{display:flex;align-items:center;flex-wrap:wrap;gap:0;margin:0;padding:0;border-top:0}
  .fk-pjrow .fk-owed i{display:inline-block;width:1px;height:12px;background:var(--line2);margin:0 12px}
  .fk-pjrow .fk-owed .tot,.fk-pjrow .fk-owed .inv{font-size:13px;color:var(--text)}
  .fk-pjrow .fk-owed .s{flex-basis:100%;width:auto;margin-top:2px}
  .fk-pjmore{padding:4px 0 12px;border-top:1px dashed var(--line)}
  .fk-pjmore .fk-prow:first-child{border-top:0}
  /* the segmented control — one press, three cells, the chosen one filled in the colour of the stage it
     leads to (the same colour that stage wears on the flow above). Unchosen cells are NOT dimmed: they are
     choices, not disabled things. */
  .fk-pjseg{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));border:1px solid var(--line2);
    border-radius:8px;overflow:hidden;background:var(--panel2)}
  .fk-pjcell{display:flex;flex-direction:column;gap:3px;align-items:center;justify-content:center;min-height:58px;
    padding:7px 10px;background:none;border:0;border-left:1px solid var(--line2);cursor:pointer;font-family:inherit;text-align:center}
  .fk-pjcell:first-child{border-left:0}
  .fk-pjcell b{font-size:13.5px;font-weight:500;color:var(--white);line-height:1.2}
  .fk-pjcell small{font-size:11.5px;color:var(--dim);line-height:1.25}
  .fk-pjcell:hover:not(.on):not(:disabled){background:var(--panel3)}
  .fk-pjcell:focus-visible{outline:var(--focus-ring);outline-offset:-2px}
  .fk-pjcell.on{background:var(--cell)}
  .fk-pjcell.on b{color:var(--on-stage);font-weight:600}
  .fk-pjcell.on small{color:var(--on-stage);opacity:.8}
  .fk-pjcell:disabled{cursor:default;opacity:.7}
  /* the tail: the ONE thing the chosen route needs decided */
  .fk-pjtail{display:grid;grid-template-columns:auto minmax(0,1fr) auto;column-gap:16px;align-items:center;
    margin-top:8px;padding:2px 0 2px 14px;border-left:1px solid var(--line2);min-height:38px}
  .fk-pjtail .l{font-size:13px;color:var(--dim)}
  .fk-pjtail .v{display:flex;align-items:center;gap:8px;min-width:0;color:var(--white);font-size:13px}
  .fk-pjtail .v .fk-avatar{width:24px;height:24px;font-size:10px;flex:none}
  .fk-pjtail .from{color:var(--dim);margin-left:8px}
  .fk-pjtail .dim{color:var(--dim)}
  .fk-pjtail .e{display:flex;gap:8px;align-items:center;font-size:12px;color:var(--dim);justify-self:end}
  .fk-pjtail .e.ok{color:var(--ok-ink,var(--ok))}
  .fk-pjtail .e.wait{color:var(--warn-ink,var(--warn))}
  .fk-pjv.locked b{color:var(--white);font-weight:650}
  .fk-pjv.locked .s{display:block;font-size:11.5px;color:var(--dim);margin-top:2px}
  /* "use a file we printed before" — one row per previous print file, the order it came off under the name */
  .fk-reuse{display:flex;flex-direction:column;gap:6px;max-height:320px;overflow:auto}
  .fk-reuse-row{display:flex;flex-direction:column;gap:2px;align-items:flex-start;padding:9px 12px;
    border:1px solid var(--line2);border-radius:8px;background:var(--panel2);cursor:pointer;font-family:inherit;text-align:left}
  .fk-reuse-row b{font-size:13px;color:var(--white)}
  .fk-reuse-row span{font-size:11.5px;color:var(--dim)}
  .fk-reuse-row:hover{background:var(--panel3)}
  .fk-alloc{display:grid;grid-template-columns:106px minmax(0,1fr);gap:9px 12px;align-items:center}
  .fk-alloc > label{font-size:12.5px;color:var(--dim)}
  .fk-alloc .fk-input{margin-bottom:0;max-width:250px}
  /* ownerSel() always stamps .fk-wf-owner, and that class is styled for the workflow ROW it was written for:
     25px tall, 11px text, max-width 168px, and margin-left:8px. Dropped into this label|control grid the
     margin was 8px of overflow at phone width, and the height made Responsible and Designer visibly
     different controls from the two selects sitting between them. Neutralised here, not at the source —
     the workflow row still wants those numbers. Padding is restated because this selector outranks
     .fk-input's own. */
  .fk-alloc .fk-wf-owner{margin-left:0;max-width:250px;height:auto;font-size:12.5px;padding:7px 10px}
  .fk-alloc .fk-wf-ownerro{display:inline-flex;align-items:center;gap:8px;margin-left:0;font-size:12.5px;color:var(--text)}
  .fk-warntxt{color:var(--warn-ink,var(--warn))}

  /* the spine itself. NOT .fk-band — that name was already taken by the Job BOARD's column row (line ~1216),
     unscoped, and this rule came later in the same sheet at the same specificity, so it won everywhere: the
     board's five columns became a `150px 1fr` grid and wrapped into three rows with the headings clipped.
     Green suite, broken main screen. Bare, common class names do not get reused across a tab's screens. */
  .fk-stepband{display:grid;grid-template-columns:150px 1fr;border-bottom:1px solid var(--line);
    background:none;border-radius:0;padding:0;margin:0;scroll-margin-top:12px}
  .fk-stepband:last-of-type{border-bottom:0}
  .fk-stepband > .when{padding:16px 0 16px 21px;position:relative;min-width:0}
  .fk-stepband > .when .n{display:block;font-size:12.5px;color:var(--white);font-weight:650;line-height:1.3}
  .fk-stepband > .when .s{display:block;font-size:11px;color:var(--faint);margin-top:2px;line-height:1.35}
  /* the state, as words rather than a coloured chip */
  .fk-stepband > .when .st{display:block;font-size:11px;color:var(--dim);margin-top:6px;line-height:1.35}
  .fk-stepband > .when:before{content:"";position:absolute;left:8px;top:22px;width:9px;height:9px;border-radius:50%;
    background:var(--line2);box-shadow:0 0 0 3px var(--panel)}
  .fk-stepband:not(:last-of-type) > .when:after{content:"";position:absolute;left:12px;top:35px;bottom:-8px;
    width:1px;background:var(--line2)}
  .fk-stepband.here > .when:before{background:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
  .fk-stepband.here > .when .n{color:var(--accent-ink,var(--accent))}
  /* done = a ring, drawn with an inset shadow so it keeps the same 9px box and never crowds its label */
  .fk-stepband.done > .when:before{background:var(--panel);box-shadow:inset 0 0 0 2px var(--dim),0 0 0 3px var(--panel)}
  /* 12px on the right, not 2px: a right-aligned control (Record payment, the totals line) sat flush against
     the panel edge with 2px, which was invisible on Design because nothing there is right-aligned. */
  .fk-stepband > .fields{padding:16px 12px 18px 6px;min-width:0}
  /* a step you have not reached states its one condition and takes a line — it does not need a card to say
     "not yet". The old .fk-cta.locked block inside it is redundant now the rail says the same thing. */
  .fk-stepband.todo > .fields{color:var(--dim);font-size:12.5px}
  .fk-stepband.done > .fields{padding-top:13px;padding-bottom:14px}

  /* sub-headings inside a step — no letter circle, because with the steps named there is nothing to count */
  /* the contact, collapsed into the header so it is reachable from every phase rather than from Paid Job
     alone. Closed it costs one line and shows the number you would ring; open it lists the rest. */
  .fk-contact{display:inline-block;min-width:0}
  .fk-contact>summary{cursor:pointer;list-style:none;color:var(--text);font-size:13px}
  .fk-contact>summary::-webkit-details-marker{display:none}
  .fk-contact>summary:after{content:" ▾";color:var(--dim);font-size:11px}
  .fk-contact[open]>summary:after{content:" ▴"}
  .fk-contact-b{display:grid;grid-template-columns:auto 1fr;gap:4px 12px;margin-top:7px;font-size:12.5px}
  .fk-contact-b .k{color:var(--faint);font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;font-weight:700;padding-top:2px}
  .fk-contact-b .v{color:var(--text);min-width:0;overflow-wrap:anywhere}
  /* a step you have not reached: one line, not a card. The rail beside it already names the step and
     shows an unfilled dot, so a bordered block repeating the condition was the same fact twice. */
  .fk-await{font-size:12.5px;color:var(--dim);margin:0}
  .fk-sub-l{font-size:10.5px;letter-spacing:.07em;text-transform:uppercase;color:var(--faint);font-weight:800;
    margin:15px 0 7px}
  .fk-stepband > .fields > .fk-sub-l:first-child{margin-top:0}

  @media (max-width:760px){
    /* minmax(0,…) not 1fr: a bare 1fr is minmax(AUTO,1fr) and a wide child (a select, a button row) grows the
       track past the panel, which is how the phone pane came to scroll sideways by 8px */
    .fk-stepband{grid-template-columns:minmax(0,1fr)}
    .fk-stepband > .when{padding:14px 0 0 21px}
    .fk-stepband:not(:last-of-type) > .when:after{display:none}
    .fk-stepband > .fields{padding:10px 0 16px}
    /* the allocation grid's 106px label track leaves ~180px for a select on a phone-width pane — labels go
       above their control instead, and the money line stops trying to keep its button on the same row */
    .fk-alloc{grid-template-columns:minmax(0,1fr);gap:4px 0}
    .fk-alloc > label{margin-top:7px}
    .fk-alloc .fk-input{max-width:none;width:100%}
    .fk-owed .act{margin-left:0;width:100%}
  }

  .fk-dstage{background:var(--panel2);border:1px solid var(--line);border-radius:11px;padding:13px 15px;margin-bottom:11px;scroll-margin-top:12px}
  .fk-dstage.done{background:var(--panel)}
  .fk-dstage.here{border-color:color-mix(in srgb,var(--here-ink,#f6c445) 45%,transparent)}
  .fk-dstage.todo{background:var(--panel);border-style:dashed;border-color:var(--line2)}
  /* the ring a timeline node leaves on the block it scrolled you to. TEMPORARY on purpose — nothing was
     hidden, so a latched "selected" state would imply a mode this panel no longer has. */
  .fk-dstage.lit{box-shadow:0 0 0 2px var(--accent),0 6px 22px color-mix(in srgb,var(--accent) 13%,transparent)}
  .fk-dstage .ds-h{display:flex;align-items:center;gap:9px;margin-bottom:10px}
  .fk-dstage .ds-h .sn{font-size:10px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;color:var(--dim);background:var(--panel3);border-radius:5px;padding:3px 7px;flex:none}
  .fk-dstage.done .ds-h .sn{background:color-mix(in srgb,var(--ok) 14%,transparent);color:var(--ok-ink,var(--ok))}
  .fk-dstage.here .ds-h .sn{background:color-mix(in srgb,var(--here-ink,#f6c445) 16%,transparent);color:var(--here-ink,#f6c445)}
  .fk-dstage .ds-h b{font-size:13.5px;font-weight:700;color:var(--white);flex:1;min-width:0}
  /* Points INSIDE a stage are LETTERS (owner 2026-08-11) — the digits belong to the stages and nothing else
     in this panel may count. Same band as everywhere else, so a nested point still reads as a point. */
  .fk-dstage .fk-band-l{margin:14px 0 7px}
  .fk-dstage .fk-band-l:first-of-type{margin-top:2px}
  .fk-dstage .fk-band-l .n{text-transform:lowercase;font-weight:800}
  /* WHO IT IS FOR, in Stage 1 — deliberately neutral. The green past-tense card in Stage 2 is what says the
     work has begun; if these two ever looked alike, the whole point of splitting them would be lost. */
  .fk-srcline{display:flex;align-items:center;gap:10px;background:var(--panel);border:1px solid var(--line);border-radius:9px;padding:9px 11px;margin-top:8px}
  .fk-srcline .fk-avatar{width:30px;height:30px;font-size:12px;flex:none}
  .fk-srcline .fk-avatar.unassigned{background:transparent;border:1.5px dashed var(--line2)}
  .fk-srcline .who{font-size:12.5px;color:var(--text);min-width:0}
  .fk-srcline .who b{color:var(--white)}
  .fk-srcline .who b.none{color:var(--faint);font-weight:600}
  .fk-srcline .who .by{display:block;font-size:11px;color:var(--dim);margin-top:1px}
  .fk-dstage.todo .ds-h b{color:var(--dim)}
  .fk-dstage .ds-tag{font-size:10.5px;font-weight:700;padding:3px 8px;border-radius:6px;flex:none;white-space:nowrap}
  .fk-dstage .ds-tag.ok{background:color-mix(in srgb,var(--ok) 13%,transparent);color:var(--ok-ink,var(--ok))}
  .fk-dstage .ds-tag.wait{background:color-mix(in srgb,var(--warn) 13%,transparent);color:var(--warn-ink,var(--warn))}
  .fk-dstage .ds-tag.old{background:var(--panel3);color:var(--dim)}
  /* ---- pre-flight / internal-check ticks. These had NO rule at all — every one of them was styled by
     inline style= attributes on the label and the input, which is why they could not follow a theme. ---- */
  /* One ROW of pills, not three stacked full-width cards (owner 2026-08-17). Each check is three or four
     words; each was taking a 48px bordered block, so the shortest content on the panel occupied the most
     vertical space on it. inline-flex + wrap means they sit on one line on a desktop pane and stack by
     themselves on a phone, with no media query to keep in step. */
  .fk-pfrow{display:inline-flex;align-items:center;gap:9px;padding:8px 14px 8px 11px;border:1px solid var(--line);
    border-radius:999px;margin:0 8px 8px 0;cursor:pointer;font-size:12.5px;max-width:100%;user-select:none}
  .fk-pfrow:hover{border-color:var(--line2);background:var(--panel2)}
  .fk-pfrow:has(.fk-pfck:checked){border-color:color-mix(in srgb,var(--ok) 45%,transparent);background:color-mix(in srgb,var(--ok) 7%,transparent)}
  .fk-pfrow:has(.fk-pfck:disabled){opacity:.62;cursor:default}
  .fk-pfrow input.fk-pfck{margin:0;width:16px;height:16px;flex:0 0 auto;accent-color:var(--ok)}  /* margin:0 defeats the global input{margin-bottom:16px} */
  .fk-pfrow span{min-width:0;text-align:left}
  /* context strip — shows only when the panel you're VIEWING isn't the job's live stage (shared-screen safety) */
  .fk-ctx{display:flex;align-items:center;gap:8px;background:rgba(245,185,20,.10);border:1px solid rgba(245,185,20,.34);border-radius:9px;padding:8px 13px;margin:-6px 0 14px;font-size:12.5px;color:var(--warn)}
  .fk-ctx b{color:var(--white)}
  .fk-drawer details{margin-top:14px}
  /* display:flex is here rather than in a second rule of its own — the "in thread" switch below needs
     margin-left:auto to sit at the far end, and a duplicate top-level selector is what
     test/css-duplicate-selectors.test.cjs exists to stop (a bare class defined twice is how the Job Board
     broke on live while 3,495 tests stayed green). */
  .fk-drawer details>summary{cursor:pointer;color:var(--dim);font-size:11px;text-transform:uppercase;letter-spacing:.06em;font-weight:700;list-style:none;user-select:none;display:flex;align-items:center;gap:8px}
  .fk-drawer details>summary::-webkit-details-marker{display:none}
  .fk-drawer details>summary::before{content:'▸ '}
  .fk-drawer details[open]>summary::before{content:'▾ '}
  .fk-dl{display:grid;grid-template-columns:96px 1fr;gap:7px 10px;font-size:13px;align-items:center}
  .fk-dl .k{color:var(--dim)}
  .fk-dl .v{color:var(--text)}
  .fk-dl select,.fk-dl input{width:100%;background:var(--panel2);border:1px solid var(--line);border-radius:8px;color:var(--white);padding:6px 8px;font-size:12.5px;font-family:inherit}
  /* the delivery address is a box with lines (FK audit M5): the .fk-input skin, the inputs' padding beside it, and it
     grows to the address it holds — up to the suite's shared ceiling */
  .fk-dl textarea{width:100%;max-width:100%;margin:0;padding:6px 8px;resize:vertical;line-height:1.45;overflow-wrap:anywhere;field-sizing:content;min-height:calc(1.45em * 3 + 14px);max-height:min(calc(1.45em * var(--ta-lines)), var(--ta-vh));overflow-y:auto}
  .fk-money{display:flex;flex-wrap:wrap;gap:10px}
  .fk-money .m{flex:1;min-width:78px;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:9px 11px}
  .fk-money .m b{display:block;color:var(--white);font-size:15px;font-variant-numeric:tabular-nums}
  .fk-money .m span{color:var(--dim);font-size:10.5px;text-transform:uppercase;letter-spacing:.05em}
  .fk-money .m b.neg{color:var(--danger)} .fk-money .m b.pos{color:var(--ok)}
  .fk-gate{display:flex;gap:8px;flex-wrap:wrap;margin-top:4px}
  .fk-gate .g{display:inline-flex;align-items:center;gap:6px;border-radius:20px;padding:5px 11px;font-size:12px;font-weight:700}
  .fk-gate .g.ok{background:rgba(12,166,120,.15);color:var(--ok)}
  .fk-gate .g.no{background:rgba(255,107,107,.13);color:var(--danger)}
  .fk-gate .g.pend{background:var(--panel2);color:var(--dim)} /* not-yet-relevant gate — neutral, not alarming red */
  /* one-line gate strip (workflow "Proposed B") — replaces the chip row + the gated footnote */
  .fk-gatestrip{display:flex;align-items:center;gap:9px;font-size:12.5px;color:var(--dim);background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:8px 13px;margin-bottom:12px;flex-wrap:wrap}
  .fk-gatestrip b{color:var(--white)}
  .fk-gatestrip .gk{display:inline-flex;align-items:center;gap:5px;font-weight:700}
  .fk-gatestrip .gk.ok{color:var(--ok)} .fk-gatestrip .gk.no{color:var(--warn)} .fk-gatestrip .gk.pend{color:var(--dim)}
  .fk-gatestrip .sep{color:var(--line2)}
  .fk-proofhist{margin:12px 0 4px;padding:10px 12px;background:var(--panel2);border:1px solid var(--line);border-radius:10px}
  .fk-pv-h{color:var(--dim);font-size:11px;text-transform:uppercase;letter-spacing:.06em;font-weight:700;margin-bottom:6px}
  .fk-pv-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:5px 0;font-size:12.5px}
  .fk-pv-row+.fk-pv-row{border-top:1px solid var(--line)}
  .fk-pv-b{display:inline-flex;align-items:center;gap:5px;border-radius:20px;padding:3px 9px;font-size:11.5px;font-weight:700;background:rgba(255,255,255,.05);color:var(--text)}
  .fk-pv-b.ok{background:rgba(12,166,120,.15);color:var(--ok)}
  .fk-pv-b.no{background:rgba(245,185,20,.14);color:var(--warn)}
  .fk-pv-b.dim{color:var(--dim);background:transparent}
  .fk-pv-note{flex-basis:100%;font-size:11.5px;color:#c9b8f5;background:rgba(167,139,250,.09);border-left:2px solid rgba(167,139,250,.5);border-radius:0 8px 8px 0;padding:4px 9px;margin-top:3px}
  /* Design & Proofing tab enrichment (spec 2026-07-03) */
  /* field-sizing makes the browser ignore rows= (measured), so the OPENING height is min-height from here on:
     this box used to open at its rows and never grow, and now opens at min-height and grows to twelve lines. */
  .fk-brief{width:100%;max-width:100%;overflow-wrap:anywhere;resize:vertical;min-height:64px;line-height:1.5;field-sizing:content;max-height:min(calc(1.5em * var(--ta-lines)), var(--ta-vh));overflow-y:auto}
  /* the design brief is drawn at rows=3 on the Paid Job card and rows=5 in Design Stage 1 — two sizes, and
     they must stay two sizes. 64px stays as the floor for any copy drawn without a rows. */
  .fk-brief[rows="3"]{min-height:calc(1.5em * 3 + 16px)}
  .fk-brief[rows="5"]{min-height:calc(1.5em * 5 + 16px)}
  .fk-brief[rows="6"]{min-height:calc(1.5em * 6 + 16px)}  /* the quote builder's Design instructions */
  /* THE ORDER'S BRIEF (owner 2026-09-08): "2x larger, and extends when more text is added, up to 5x bigger,
     then it's fixed and a scroll bar comes." The growing and the scrollbar were already here (field-sizing:
     content + the --ta-lines cap above); only the numbers were wrong. Ten rows to start, twenty-five before it
     scrolls — TWICE the shared count, not a number of its own. --ta-lines is the suite's one line count,
     defined once at :root, and two guards hold that line: no second definition anywhere, and no prose box
     with a hand-written ceiling. Both are right — a shared number stops being shared the first time somebody
     writes 25 beside it — so the brief's ceiling is expressed as a multiple of the shared count: 24 lines at
     today's 12, within a line of the "5x" asked for, and it moves with the one number if that ever changes.
     Both the Design panel's box and its Paid Job mirror carry rows="10", so this one rule sizes both. */
  .fk-brief[rows="10"]{min-height:calc(1.5em * 10 + 16px);max-height:min(calc(1.5em * var(--ta-lines) * 2), var(--ta-vh))}
  .fk-brief-hint{color:var(--dim);font-size:11px;margin-top:6px}  /* --dim, not --faint: this is the drawer's explanatory copy at 11px and it measured 2.30:1 on the light themes */

  /* ---- THE ADD-LINE PICKER'S SECOND TAB (owner 2026-08-26) -------------------------------------------
     "should be able to add any product from Product range — currently we can only select from our services."
     The picker offered the 10 calculators; the other 145 products had no door from a quote. Rows rather than
     cards for those 145: at the modal's real 891px a card grid fits three across, so twelve fill it and the
     rest is scrolling — and a row can carry the category and supplier, which is what tells "Flyers" apart
     from "Recycled Flyers". */
  .fk-altabs{display:flex;gap:4px;margin:12px 0 12px;border-bottom:1px solid var(--line)}
  .fk-altabs .fk-altab{background:none;border:0;border-bottom:2px solid transparent;color:var(--dim);
    font:inherit;font-size:13px;font-weight:600;padding:8px 12px;margin-bottom:-1px;cursor:pointer}
  .fk-altabs .fk-altab:hover{color:var(--text)}
  .fk-altabs .fk-altab.on{color:var(--white);border-bottom-color:var(--accent)}
  .fk-altabs .fk-altab .n{color:var(--faint);font-size:11px;margin-left:6px;font-variant-numeric:tabular-nums}
  .fk-alsearch{display:flex;align-items:center;gap:9px;background:var(--panel2);border:1px solid var(--line);
    border-radius:9px;padding:8px 12px;margin:0 0 12px}
  .fk-alsearch .s-ic{width:14px;height:14px;flex:0 0 14px;color:var(--faint)}
  /* the suite-wide input{margin-bottom:16px} would inflate this bar and lift its text off the baseline —
     the trap this file has now sprung on six separate controls */
  .fk-alsearch input{flex:1;min-width:0;margin:0;background:none;border:0;color:var(--white);font:inherit;
    font-size:13px;outline:none;padding:0}
  .fk-alsearch input::placeholder{color:var(--faint)}
  .fk-alsearch .k{color:var(--faint);font-size:11px;border:1px solid var(--line2);border-radius:5px;
    padding:1px 6px;font-variant-numeric:tabular-nums;flex:none}
  .fk-alsplit{display:grid;grid-template-columns:190px 1fr;gap:16px;align-items:start}
  @media (max-width:720px){ .fk-alsplit{grid-template-columns:1fr} .fk-alrail{max-height:150px} }
  .fk-alrail{border-right:1px solid var(--line);padding-right:12px;max-height:min(52vh,470px);overflow:auto}
  .fk-alrail .cap{color:var(--faint);font-size:10.5px;font-weight:700;letter-spacing:.08em;margin:0 0 8px}
  .fk-alrail button{display:flex;align-items:center;gap:8px;width:100%;background:none;border:0;
    color:var(--text);font:inherit;font-size:12.5px;padding:6px 8px;border-radius:7px;text-align:left;
    margin-bottom:1px;cursor:pointer}
  .fk-alrail button:hover{background:var(--panel2)}
  .fk-alrail button .n{margin-left:auto;color:var(--faint);font-size:11px;font-variant-numeric:tabular-nums}
  .fk-alrail button.on{background:var(--accent);color:var(--on-accent,#062227);font-weight:650}
  .fk-alrail button.on .n{color:inherit;opacity:.72}
  /* …and the list inside it grew with it (same 2026-09-16 note): 470px showed ~9 of 145 products, so the scroll
     did all the work the screen could have done. Still a min() — the modal must not outgrow a short laptop. */
  .fk-alrows{max-height:min(68vh,760px);overflow:auto;padding-right:4px}
  .fk-alrows .r{display:flex;align-items:center;gap:11px;padding:8px 10px;border-radius:9px;
    border-bottom:1px solid var(--line)}
  .fk-alrows .r:hover{background:var(--panel2)}
  .fk-alrows .th{width:42px;height:32px;border-radius:6px;flex:none;overflow:hidden;background:var(--panel3);
    border:1px solid var(--line2)}
  .fk-alrows .th img{width:100%;height:100%;object-fit:cover;display:block}
  .fk-alrows .nm{flex:1;min-width:0}
  .fk-alrows .nm b{display:block;color:var(--white);font-size:12.5px;font-weight:600;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-alrows .nm span{color:var(--faint);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}
  .fk-alrows .lp{color:var(--dim);font-size:11.5px;font-weight:600;flex:none}

  /* ---- THE DESIGN BRIEF'S SIX IMPROVEMENTS (owner 2026-08-26) --------------------------------------- */
  /* 5 · say that you can drop on it. The outline is INSET so it cannot change the card's size and shove the
     page about while a file is being dragged over it — the bug that "user content cannot break layout" names. */
  /* #fk-pjbrief-card is an ID on a .fields div, not a class of its own — written as .fk-pjbrief-card first,
     which matched nothing at all and would have shipped a drop zone that never appeared. */
  #fk-pjbrief-card,#qd-brief-card,#fk-drawer .fk-stepband{position:relative}
  #fk-pjbrief-card.dropping::after,#qd-brief-card.dropping::after,#fk-drawer .fk-stepband.dropping::after{content:'Drop to attach to this brief';
    position:absolute;inset:2px;border:2px dashed var(--accent);border-radius:10px;background:var(--panel);
    display:grid;place-items:center;color:var(--accent);font-size:13px;font-weight:650;pointer-events:none;z-index:2}
  /* 4 · the number a brief can point at. On a thumbnail it sits over the top-left corner; on a file chip it
     leads the row, because a chip has no corner to spare. */
  .fk-tilenum{position:absolute;top:-6px;left:-6px;width:20px;height:20px;border-radius:50%;border:0;
    background:var(--accent);color:var(--on-accent,#062227);font-size:11px;font-weight:700;line-height:1;
    display:grid;place-items:center;cursor:pointer;padding:0;font-family:inherit;z-index:1}
  .fk-tilenum:hover{filter:brightness(1.12)}
  /* NOT a second `.fk-filetile{position:relative}` — it already says that at :2099, and a duplicate top-level
     selector is the shape that broke the Job Board on live while 3,495 tests stayed green.
     test/css-duplicate-selectors.test.cjs caught this one before it shipped. */
  .fk-filechip > .fk-tilenum{position:static;width:17px;height:17px;font-size:10px;flex:none;margin-right:2px}
  .fk-briefref{border:0;padding:0 5px;margin:0 1px;border-radius:5px;background:var(--accent-soft,rgba(62,207,220,.14));
    color:var(--accent-ink,var(--accent));font:inherit;font-size:.92em;font-weight:700;cursor:pointer;
    font-variant-numeric:tabular-nums}
  .fk-briefref:hover{filter:brightness(1.1)}
  .fk-filetile.flash,.fk-filechip.flash{animation:fk-tileflash .9s ease-out}
  @keyframes fk-tileflash{0%{box-shadow:0 0 0 0 var(--accent)}40%{box-shadow:0 0 0 3px var(--accent)}100%{box-shadow:0 0 0 0 transparent}}
  /* 2 · the two boxes overwriting each other. It sits ABOVE the box, so the text you typed is still visible
     underneath it — the whole promise of the bar is that nothing has been thrown away. */
  .fk-briefclash{display:flex;align-items:center;gap:9px;margin:0 0 9px;padding:7px 11px;border-radius:8px;
    font-size:12px;background:rgba(245,184,78,.11);border:1px solid rgba(199,120,0,.42);color:var(--warn-ink,var(--warn))}
  .fk-briefclash .i{flex:none} .fk-briefclash .t{flex:1;min-width:0} .fk-briefclash b{color:var(--white)}
  .fk-briefcompare{display:grid;grid-template-columns:1fr 1fr;gap:12px}
  @media (max-width:640px){ .fk-briefcompare{grid-template-columns:1fr} }
  .fk-briefcol h4{margin:0 0 6px;font-size:12px;font-weight:650;color:var(--white);display:flex;
    align-items:baseline;gap:7px}
  .fk-briefcol h4 span{color:var(--dim);font-size:11px;font-weight:400}
  .fk-briefcol .bf-ro{max-height:38vh;overflow:auto}  /* a long brief scrolls inside its column, as it always did */
  .fk-preflight{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:7px 14px}
  .fk-preflight label{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--text);cursor:pointer;user-select:none}
  .fk-preflight input{width:15px;height:15px;accent-color:var(--accent);cursor:pointer;flex:none}
  .fk-pf-count{display:inline-block;margin-left:6px;padding:1px 8px;border-radius:999px;background:rgba(245,185,20,.14);color:var(--warn);font-weight:700;letter-spacing:0}
  .fk-pf-count.ok{background:rgba(12,166,120,.15);color:var(--ok)}
  .fk-signoff{margin-bottom:11px;padding:9px 12px;border-radius:10px;background:rgba(12,166,120,.1);border:1px solid rgba(12,166,120,.3);color:var(--text);font-size:12.5px}
  .fk-signoff b{color:var(--ok)}
  .fk-linkbar{margin-top:11px;padding:8px 11px;background:var(--panel);border:1px dashed var(--line2);border-radius:9px;color:var(--dim);font-size:12.5px}
  .fk-pv-d{color:var(--dim);font-size:11px}
  .fk-pv-latest{margin-left:auto;font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--accent);border:1px solid var(--accent);border-radius:10px;padding:1px 7px}
  .fk-pv-c{flex-basis:100%;color:var(--dim);font-size:12px;font-style:italic;margin:2px 0 2px 4px}
  /* payment milestones — full payment is the goal, deposit is a sub-step */
  .fk-payhead{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin:2px 0 11px}
  .fk-payhead .amt{font-size:25px;font-weight:800;font-variant-numeric:tabular-nums;line-height:1}
  .fk-payhead .amt.neg{color:var(--danger)} .fk-payhead .amt.pos{color:var(--ok)}
  .fk-payhead .lbl{color:var(--dim);font-size:12.5px}
  .fk-paytrack{display:flex;gap:6px;margin:0 0 12px}
  .fk-paytrack .pt{flex:1;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:7px 10px;min-width:0}
  .fk-paytrack .pt .t{font-size:12px;font-weight:700;color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-paytrack .pt .sub{font-size:10px;color:var(--dim);text-transform:uppercase;letter-spacing:.04em;font-variant-numeric:tabular-nums}
  .fk-paytrack .pt.done{border-color:rgba(12,166,120,.45);background:rgba(12,166,120,.08)}
  .fk-paytrack .pt.done .t{color:var(--ok)}
  .fk-paytrack .pt.active{border-color:var(--accent);background:rgba(0,184,217,.1)}
  .fk-paytrack .pt.active .t{color:var(--white)}
  .fk-paytrack .pt.skip{border-style:dashed;opacity:.65}
  .fk-paytrack .pt.skip .t{color:var(--faint);text-decoration:line-through}
  .fk-paytrack .pt.skip .sub{color:var(--faint);text-transform:none;letter-spacing:0}
  /* line icons (the chat's ic() set) used as drawer chrome — one icon vocabulary across both panes */
  .fk-drawer-left .ic{width:14px;height:14px;vertical-align:-2px;display:inline-block}
  .fk-btn .ic{width:13px;height:13px;vertical-align:-2px}
  .fk-danger-zone{margin-top:2px}
  /* a job somebody has asked Management to delete — the request sits above the delete controls in the drawer */
  .fk-delreq{margin:10px 0 6px;padding:10px 12px;border:1px solid var(--danger);border-radius:10px;background:color-mix(in srgb,var(--danger) 10%,transparent)}
  .fk-delreq-h{font-size:12.5px;color:var(--text);display:flex;align-items:center;gap:6px}
  .fk-delreq-why{margin-top:5px;font-size:13px;color:var(--text);white-space:pre-wrap}
  .fk-delreq-acts{display:flex;gap:8px;margin-top:10px}
  .fk-delreq-acts .fk-btn{flex:1 1 0;justify-content:center}
  .fk-danger-zone>summary{color:var(--faint);font-size:11px;text-transform:uppercase;letter-spacing:.06em;font-weight:700;cursor:pointer;list-style:none;user-select:none}
  .fk-danger-zone>summary::before{content:'▸ '}
  .fk-danger-zone[open]>summary::before{content:'▾ '}
  /* stage hand-off CTA (D&P → production, production → delivery) + the artwork-source line */
  .fk-cta{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:11px;padding:12px 14px;border-radius:11px;background:rgba(12,166,120,.09);border:1px solid rgba(12,166,120,.3)}
/* ── which press, at the end of Design (owner 2026-08-19) ──────────────────────────────────────
     Two real choices side by side rather than one button and a dropdown: the press is not a detail of the
     handoff, it IS the handoff, and one click should do both. They wrap on a narrow drawer. */
  .fk-press-picks{display:flex;gap:9px;flex-wrap:wrap;margin-left:auto}
  .fk-press{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-width:170px;
    padding:9px 14px;border-radius:9px;cursor:pointer;text-align:left;
    background:rgba(12,166,120,.16);border:1px solid rgba(12,166,120,.45);color:var(--white);font:inherit}
  .fk-press:hover{background:rgba(12,166,120,.28);border-color:rgba(12,166,120,.7)}
  .fk-press:focus-visible{outline:2px solid var(--ok,#0ca678);outline-offset:2px}
  .fk-press[disabled]{opacity:.55;cursor:progress}
  .fk-press b{font-size:13px;font-weight:750;line-height:1.25}
  .fk-press span{font-size:11px;color:var(--dim);font-weight:400}
  .fk-cta .m{flex:1;min-width:160px}
  .fk-cta .m b{color:var(--white);font-size:13px}
  .fk-cta .m .s{color:var(--dim);font-size:12px;margin-top:2px}
  .fk-cta.locked{background:rgba(245,185,20,.07);border-color:rgba(245,185,20,.3)}
  .fk-cta.locked .m b{color:var(--warn)}
  .fk-cta.muted{background:transparent;border:1px dashed var(--line)} .fk-cta.muted .m b{color:var(--dim)}
  /* image previews: the files list + the upload queue show what the print file actually looks like */
  .fk-thumb{width:46px;height:46px;object-fit:cover;border-radius:8px;border:1px solid var(--line2);background:var(--panel2);flex:none;display:block}
  .fk-thumb.sm{width:32px;height:32px;border-radius:6px}
  /* final print files: a LIST of lines (a job can need several separate files — front/back, multiple SKUs),
     each with its optional note; replaces the old single-file fk-ff-done box */
  .fk-ff-list{display:flex;flex-direction:column;gap:8px}
  .fk-ff-item{display:flex;align-items:center;gap:11px;padding:9px 12px;border-radius:10px;background:rgba(12,166,120,.08);border:1px solid rgba(12,166,120,.28)}
  .fk-ff-item .m{flex:1;min-width:0;font-size:12.5px}
  .fk-ff-ic{width:34px;height:34px;flex:none;display:grid;place-items:center;background:var(--panel2);border:1px solid var(--line);border-radius:8px;color:var(--dim);text-decoration:none}
  .fk-ff-ic .ic{width:16px;height:16px}
  .fk-ff-note-row{margin-top:2px;display:flex;align-items:center;gap:6px;font-size:12px}
  .fk-ff-note-txt{color:var(--dim)}
  .fk-ff-note-edit{border:none;background:none;color:var(--accent);cursor:pointer;font-size:11.5px;padding:0;font-weight:600}
  .fk-srcline{display:flex;align-items:center;gap:8px;margin-bottom:11px;padding:9px 13px;border-radius:10px;background:var(--panel2);border:1px solid var(--line);color:var(--text);font-size:12.5px}
  .fk-srcline b{color:var(--white)}
  .fk-row{display:flex;gap:8px;align-items:center;margin-top:8px}
  /* "or" rule between the two send channels and "Paid — no invoice needed": the third button is not a third
     way to send, it is the way out of sending, and stacked identically it read as one (owner 2026-08-15). */
  .fk-orline{display:flex;align-items:center;gap:9px;color:var(--dim);font-size:11px;text-transform:uppercase;letter-spacing:.06em;margin:2px 0}
  .fk-orline span{flex:1;height:1px;background:var(--line)}
  .fk-due-head-in{box-sizing:border-box;height:24px;padding:0 6px;font-size:12px;font-weight:600;width:130px;line-height:22px;vertical-align:middle;margin:0} /* the global input{margin-bottom:16px} (line ~40, for stacked forms) was skewing the flex-centered row */
  .fk-thread{display:flex;flex-direction:column;gap:9px;max-height:230px;overflow-y:auto;margin-bottom:10px}
  .fk-cmt{background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:8px 10px}
  .fk-cmt .who{font-size:11px;font-weight:700}
  .fk-cmt .when{color:var(--dim);font-size:10.5px;margin-left:6px}
  .fk-cmt .body{color:var(--text);font-size:12.5px;margin-top:3px}
  .fk-thread-empty{color:var(--dim);font-size:12px;text-align:center;padding:16px;opacity:.7}
  .fk-btn{background:var(--panel2);border:1px solid var(--line);color:var(--text);border-radius:var(--r-sm);padding:7px 12px;font-size:12.5px;cursor:pointer;font-family:inherit;white-space:nowrap}
  .fk-btn:hover{color:var(--white);border-color:var(--accent)}
  .fk-btn.accent{background:var(--accent);border-color:var(--accent);color:var(--on-accent);font-weight:700}
  .fk-btn.ok{background:var(--ok);border-color:var(--ok);color:#04241a;font-weight:700}
  .fk-btn.ok:hover{color:#04241a;border-color:var(--ok);filter:brightness(1.08)}
  .fk-btn.danger{color:var(--danger-ink,var(--danger));border-color:rgba(255,107,107,.4)}  /* danger as TEXT — 2.56:1 on every light theme as --danger (audit 2026-08-09) */
  /* the ONE reserved "advance to the next step / process" look — cyan pill + arrow, used wherever a job moves forward */
  .fk-btn.advance{background:var(--accent);border-color:var(--accent);color:var(--on-accent);font-weight:600;border-radius:7px;padding:0 16px;height:34px}
  .fk-btn.advance:hover{filter:brightness(1.06);color:var(--on-accent);border-color:var(--accent)}
  /* Quick-Quote bottom action bar: Save & close + the paid-walk-in fast-track */
  .fk-qd-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:6px;padding-top:14px;border-top:1px solid var(--line)}
  .fk-qd-actions .grow{flex:1}
  .fk-btn.danger:hover{background:rgba(255,107,107,.1)}

  /* V3-style workflow nav */
  /* (width lives on .fk-navwrap now — Suite.makeResizer still drives --fk-navw, min 168 / max 340) */
  /* 10px, not 8: this sits inside .fk-nav's own 8px, and .fk-mod adds 9 plus a 1px transparent border, so 8
     here landed the caption 2px left of every row under it. The old comment claimed these aligned; they never
     did, because it did not count the border. */
  .fk-sub{font-size:11px;letter-spacing:.09em;color:var(--dim);font-weight:700;text-transform:uppercase;padding:0 8px 5px 10px;margin-top:12px}  /* group separator = whitespace, not a ruled line; 8px L-pad aligns with .fk-mod */
  .fk-sub:first-child{margin-top:0}
  /* collapsible group header — a fold toggle; keeps the .fk-sub type/colour/padding */
  .fk-sub-toggle{display:flex;align-items:center;gap:7px;width:100%;background:none;border:0;cursor:pointer;text-align:left;font-family:inherit;border-radius:8px;transition:box-shadow .18s ease,color .15s ease}
  .fk-sub-toggle:hover{color:var(--text);box-shadow:0 0 12px -8px color-mix(in srgb,var(--tab-accent,var(--accent)) 55%,transparent)}
  .fk-sub-toggle.coll{box-shadow:0 0 11px -8px color-mix(in srgb,var(--tab-accent,var(--accent)) 45%,transparent)}  /* slight glow on the collapsed group chips */
  .fk-sub-toggle .fk-sub-t{flex:1 1 auto}
  /* order:2 puts the chevron AFTER the label. Leading it indented every caption to ~24px, so the group
     headings sat under the item labels instead of hanging at 8px with the icon column, as the mock does. */
  .fk-sub-toggle .nav-chev{flex:none;order:2;opacity:.65;transition:transform .15s ease;transform:rotate(90deg)}  /* expanded → chevron points down */
  .fk-sub-toggle.coll .nav-chev{transform:rotate(0)}  /* collapsed → points right */
  .fk-sub-n{font-size:9.5px;font-weight:800;letter-spacing:0;color:var(--dim);background:var(--panel2);border-radius:999px;padding:1px 7px;text-transform:none}
  .fk-subdiv{margin-top:6px;padding-top:8px;color:var(--dim)}
  /* admin ＋ on the Tab-channels header (replaced the full-width dashed "Add channel" row, owner 2026-07-18) */
  .fk-chanhead{display:flex;align-items:center;justify-content:space-between;padding-right:5px}
  .fk-addch{flex:none;width:20px;height:20px;display:grid;place-items:center;background:none;border:0;border-radius:6px;color:var(--dim);font-size:15px;font-weight:700;line-height:1;cursor:pointer;padding:0;font-family:inherit}
  .fk-addch:hover{color:var(--text);background:var(--panel2)}
  .fk-dot{width:8px;height:8px;border-radius:50%;display:inline-block;flex:none;margin:0 4px}
  .fk-mod-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-count{min-width:20px;height:18px;padding:0 6px;border-radius:9px;background:#1E2637;color:#B6C0D2;font-size:11px;font-weight:700;display:grid;place-items:center;font-variant-numeric:tabular-nums;flex:none}
  .fk-count.zero{background:transparent;color:var(--dim);opacity:.45}
  .fk-count.warn{background:rgba(245,185,20,.18);color:var(--warn)}
  .fk-count.urgent{background:rgba(255,107,107,.18);color:var(--danger)}
  /* The reply bubble on a tab-homed channel row (owner 2026-08-25: "same as team hub"). The MARKUP is
     chat.js's one definition; the paint has to be ours, because chat.css's .reply-dot lives inside
     @scope (.wc-root) and reads chat's --accent. Painted like a .fk-count so one row speaks one language.
     margin-left:auto by default; when a count sits beside it, the count owns the gap. */
  /* NO CHIP — just the cloud (owner 2026-08-26: "this needs to be just a simple white cloud, just simple
     and clean"). It had a filled square behind it, and at 24x22 that square WAS the thing you saw. The box
     stays only as the hit area: 16px is a small thing to aim at, so the button keeps its size and paints
     nothing. Mock: docs/prototype/reply-bubble-mock.html, option A. */
  .fk-mod .reply-dot{flex:none;display:inline-flex;align-items:center;justify-content:center;height:var(--rd-h);width:var(--rd-w);
    padding:0;margin-left:auto;border:none;background:none;color:#fff;cursor:pointer;transition:.14s}
  .fk-mod .fk-count ~ .reply-dot{margin-left:4px}
  /* SOLID, not an outline (owner 2026-08-26). ic() draws every glyph fill:none + stroke, which at 13px
     read as a thin hollow ring; a filled bubble is legible at a glance. CSS beats the presentation
     attributes on the <svg>, so this is the whole change. */
  /* color HERE, on the svg, not only on the .reply-dot around it. ic() emits <svg class="ic">, so this glyph
     also matches `.fk-mod .ic{color:var(--dim)}` — which sets colour ON THE SVG, while the white sits on its
     parent. Inheritance loses to a rule that names the element, so fill:currentColor resolved to --dim and the
     cloud painted #909BB0 grey on every FK theme. `.fk-mod .reply-dot svg` (0,2,1) beats `.fk-mod .ic` (0,2,0)
     whatever the source order. Found by a verification sweep after this shipped LOOKING white in the mock. */
  .fk-mod .reply-dot svg{width:var(--rd-ic);height:var(--rd-ic);color:#fff;fill:currentColor;stroke:rgba(0,0,0,.55);stroke-width:1;paint-order:stroke fill;stroke-linejoin:round}
  /* …and again with the ID, because that is what actually wins. Reading the file said `.fk-mod .ic` (0,2,0)
     was the competitor and the rule above (0,2,1) beat it — wrong. ENUMERATING the rules that really match
     the element on the running page found a third one, `body[data-fk-theme] #fk-shell .fk-mod .ic` at (1,3,1),
     which outranks anything without an id. Since fkTheme() always sets a theme, that rule always applies, so
     the cloud stayed grey. This one is (1,4,1). The lesson is the one this file already records: when layout
     or colour goes wrong with no rule in sight to explain it, list the rules that match rather than the rules
     you expect to match. */
  body[data-fk-theme] #fk-shell .fk-mod .reply-dot svg{color:#fff}
  /* brightness() cannot brighten white — a hover that does nothing is a dead affordance. Opacity works on
     any ink, so all four rails fade rather than brighten now. */
  .fk-mod .reply-dot:hover{opacity:.72}
  .fk-mod .reply-dot:focus-visible{outline:2px solid var(--accent,#3d8bff);outline-offset:1px}

  /* list pages */
  /* roomier inset across every view so content isn't flush to the screen edge (more on the right) */
  .fk-page{flex:1;min-height:0;overflow-y:auto;overflow-x:auto;padding:0 var(--fk-gut,0px) var(--fk-gut,0px)} /* overflow-x: a production list is wider than a 1280px screen (picture + stacked buttons, 2026-09-09); it scrolls INSIDE the page rather than clipping the actions off the right edge */   /* the content gutter — one source (--fk-gut on .fk), so the page, the band and the title row can never disagree */
  .fk-table{width:100%;border-collapse:collapse;background:var(--panel);border:1px solid var(--line);border-radius:12px;overflow:hidden;font-size:13px}
  .fk-table thead th{text-align:left;color:var(--dim);font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;font-weight:700;padding:10px 12px;border-bottom:1px solid var(--line);background:var(--panel)}
  .fk-table td{padding:10px 12px;border-bottom:1px solid var(--line);color:var(--text);vertical-align:middle;max-width:520px;overflow-wrap:anywhere}
  /* USER TEXT CANNOT WIDEN THE TABLE. A table sizes to its content, so ONE pasted share link — 92 characters
     with no spaces to break at — took the Title cell from 219px to 520px and pushed the Actions column's
     buttons off the right of the screen, with no scrollbar to reach them. Measured on Paid Jobs at a 1400px
     viewport: "Out Prod" ended at 1520. `table-layout:fixed` is not the fix (it would ignore the natural
     widths every other queue depends on); capping the cell and letting an unbroken run BREAK is. The row
     grows a line taller instead — 60px to 76px — which is the correct thing to spend. */
  .fk-table tbody tr:nth-child(even){background:rgba(255,255,255,.015)}  /* subtle zebra aids scanning; same specificity as :hover/.sel, placed first so those win on source order */
  .fk-table tr:last-child td{border-bottom:none}
  .fk-table tbody tr:hover{background:rgba(255,255,255,.045)}
  /* customer multi-select checkboxes — slightly enlarged for easy ticking */
  /* customer multi-select boxes: soft light-grey (not stark white), compact, aligned to the customer's first line */
  .cust-chk,#cust-chkall{-webkit-appearance:none;appearance:none;width:10px;height:10px;border-radius:3px;background:#39404e;border:1px solid #565d6d;cursor:pointer;flex:none;margin:0;padding:0;position:relative;vertical-align:top}
  .cust-chk:checked,#cust-chkall:checked{background:var(--accent);border-color:var(--accent)}
  .cust-chk:checked::after,#cust-chkall:checked::after{content:"";position:absolute;left:3px;top:0;width:2px;height:5px;border:solid var(--on-accent);border-width:0 2px 2px 0;transform:rotate(45deg)}
  /* bigger custom checkboxes for the job multi-select (Payment Processing + stage queues) */
  .fk-jchk,.fk-jchkall{-webkit-appearance:none;appearance:none;width:13px;height:13px;border-radius:4px;background:#39404e;border:1px solid #565d6d;cursor:pointer;flex:none;margin:0 auto;padding:0;position:relative;display:block}
  .fk-jchk:checked,.fk-jchkall:checked{background:var(--accent);border-color:var(--accent)}
  .fk-jchk:checked::after,.fk-jchkall:checked::after{content:"";position:absolute;left:4px;top:1px;width:3px;height:6px;border:solid var(--on-accent);border-width:0 2px 2px 0;transform:rotate(45deg)}
  .fk-jsel-cell{cursor:pointer;text-align:center;vertical-align:middle}
  .fk-table th:has(.fk-jchkall){text-align:center}
  .fk-table td.cust-sel-cell{vertical-align:top;padding-top:13px}
  /* persistent "add another" affordance shown under a list (e.g. New Quotes) — grey-white, dashed, secondary to the toolbar button */
  .fk-addrow{width:100%;margin-top:10px;padding:11px 13px;background:none;border:1px dashed var(--line);border-radius:8px;color:var(--text);font-size:13px;font-weight:600;cursor:pointer;font-family:inherit;display:flex;align-items:center;gap:8px}
  .fk-addrow:hover{border-color:var(--accent);color:var(--accent);background:var(--panel2)}
  .fk-trash-note{color:var(--dim);font-size:12.5px;margin:0 0 12px;background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:9px 12px}
  .fk-table .r{text-align:right;font-variant-numeric:tabular-nums}   /* line up £ digits in every right-aligned money column */
  .fk-table .c{text-align:center}
  .fk-table .s{color:var(--dim);font-size:11px;margin-top:2px}
  .fk-table td.fk-custcell b{color:var(--cust-ink,#7CC4FF);font-weight:700} /* the stage lists lead with the customer (owner 2026-09-09), in sky blue since 2026-09-29 — amber was every warning's colour too */
  /* Cells that must never break mid-token. The table's overflow-wrap:anywhere exists for long titles; with
     the Customer column in the row it also broke "FK-O-2130" into "FK-O-" / "2130" and "£55.20" into
     "£55.2" / "0" at the real 1400px (measured 2026-09-09). The name stays on one line; a long trading
     name under it ellipses inside 220px rather than pushing every other column narrower. */
  .fk-table td.fk-custcell{white-space:nowrap;max-width:220px}
  .fk-table td.fk-custcell .s{overflow:hidden;text-overflow:ellipsis}
  .fk-table td.fk-codecell,.fk-table td.fk-valcell,.fk-table td.fk-qtycell{white-space:nowrap} /* …and the quantity, which broke "252" into "25"/"2" on Paid Jobs once the picture had its width */
  /* THE PRODUCTION LISTS (Design & Proofing · In-house · Outsourcing · Delivery; owner 2026-09-09): a picture of
     the artwork leads each row (the small copy the board card already asks for), the rows are a touch taller
     to carry it, the advance button is green and the production slip is one yellow button at the end. */
  .fk-table.fk-prodlist td{padding:13px 12px}
  .fk-table td.fk-thumbcell,.fk-table th.fk-thumbcell{width:112px;padding-right:0}
  .fk-rowthumb{display:block;width:112px;height:80px;object-fit:cover;border-radius:6px;background:var(--panel2);border:1px solid var(--line)}
  .fk-rowthumb.none{border:1px dashed var(--line2);background:none}
  /* The two buttons STACK in the actions cell — advance above, slip below — because side by side they cost
     330px and the title paid for it. The title cell keeps a floor so no other column can squeeze it away. */
  .fk-table.fk-prodlist td.fk-actions{width:1%;white-space:nowrap}
  /* An inline GRID, so the stack is as wide as its widest button and every button stretches to that. The
     first cut set width:100% on block buttons, and the table resolved the cell from the SHORTER one —
     "Production slip" poked out of its own pill on the owner's screen (2026-09-09). */
  .fk-actstack{display:inline-grid;gap:6px;justify-items:stretch}
  .fk-actstack .fk-btn{margin:0;text-align:center;white-space:nowrap}
  .fk-table .fk-advsel{padding:4px 28px 4px 9px;font-size:11.5px;min-width:128px;cursor:pointer} /* Paid Jobs' route dropdown (2026-09-09), sized like the small buttons the other lists carry */
  /* THE TITLE HAS A FLOOR ON EVERY QUEUE, not only the production lists. Paid Jobs had none, so when the window
     narrowed the nine other columns kept their natural widths (850px, measured at a 1280 viewport) and the
     title took the whole squeeze: 55px, one word per line, a 525px-tall row (owner 2026-09-11). */
  .fk-table td.fk-titlecell{min-width:180px}
  .fk-table td.fk-asgcell{width:1%}   /* the face only — the column is as wide as its heading, never wider */
  .fk-table b{color:var(--white)}
  .fk-actions{white-space:nowrap}
  .fk-actions .fk-btn{margin-left:4px}
  /* NARROW WINDOWS SHARE THE SQUEEZE (owner 2026-09-11: "when downsizing screen the content need to equally
     adjust — currently just title does and makes the list look weird"). Measured on Paid Jobs at a 1280 viewport
     (1003px of page): the picture cost 123px, the route dropdown 193, the side padding 240 across ten cells, and
     the title was left 55. Below 1400px every cell gives up 4px of side padding, the picture and the dropdown
     shrink, and the title keeps its floor; below 1200px the picture column goes altogether — at that width a
     picture costs more than it tells, and the row's words are what the list is for. */
  @media (max-width:1400px){
    .fk-table td,.fk-table thead th{padding-left:6px;padding-right:6px}
    .fk-table thead th{letter-spacing:.05em}                            /* the headings set the floor of the narrow columns */
    .fk-table.fk-prodlist td{padding-left:6px;padding-right:6px}
    .fk-table td.fk-titlecell{min-width:170px}
    .fk-table td.fk-thumbcell,.fk-table th.fk-thumbcell{width:84px;padding-right:0}
    .fk-rowthumb{width:84px;height:60px}
    .fk-table .fk-advsel{width:120px;min-width:0;padding-right:22px}   /* a select is as wide as its longest option — cap it; the list opens full */
    .fk-actstack .fk-btn{padding:5px 9px;font-size:11.5px}             /* the stacked buttons cost the title 20px they did not need */
  }
  @media (max-width:1200px){
    .fk-table td.fk-thumbcell,.fk-table th.fk-thumbcell{display:none}
  }
  .fk-btn.sm{padding:4px 9px;font-size:11.5px}
  .fk-link{color:var(--accent-ink,var(--accent));cursor:pointer;text-decoration:none}
  .fk-link:hover{text-decoration:underline}

  /* filter pills + quote badges */
  .fk-pills{display:flex;gap:5px;flex-wrap:wrap}
  .fk-pill{background:var(--panel2);border:1px solid var(--line);color:var(--dim);border-radius:20px;padding:5px 12px;font-size:12px;cursor:pointer;font-family:inherit}
  .fk-pill.on{background:var(--accent);border-color:var(--accent);color:var(--on-accent);font-weight:700}
  .fk-qbadge{font-size:10.5px;font-weight:700;padding:3px 9px;border-radius:20px;white-space:nowrap}
  .fk-qbadge.q-draft{background:var(--panel2);color:var(--dim);border:1px solid var(--line)}
  /* --accent-ink, not --accent: the accent here is TEXT on its own pale tint, which is the job that token
     exists for. Measured as --accent it was 1.94:1 on Forest, 1.23:1 on Marine and 4.14:1 on Light Box —
     the badge was effectively blank on two of the five themes. (contrast audit 2026-08-09) */
  .fk-qbadge.q-open{background:rgba(0,184,217,.15);color:var(--accent-ink,var(--accent))}  /* an active (open) quote — reads as live, not an unfinished draft */
  .fk-qbadge.q-sent{background:rgba(0,184,217,.15);color:var(--accent-ink,var(--accent))}
  .fk-qbadge.q-accepted{background:rgba(12,166,120,.15);color:var(--ok)}
  .fk-qbadge.q-declined{background:rgba(255,107,107,.13);color:var(--danger)}
  .fk-qbadge.q-hold{background:rgba(245,185,20,.15);color:var(--warn)}
  .fk-qbadge.q-stale{background:rgba(245,185,20,.25);color:var(--warn)}

  /* payment-processing sections */
  .fk-section{margin-bottom:22px}
  .fk-section h3{color:var(--white);font-size:14px;margin:0 0 10px;display:flex;align-items:center;gap:8px}
  .fk-section h3 .n{background:var(--panel2);color:var(--dim);border-radius:20px;padding:1px 9px;font-size:11px;font-weight:700}
  /* section headings are TEXT, so they take the -ink variants: as --ok/--danger the Archived page's
     "Completed & paid" measured 2.75:1 and "Completed — payment outstanding" 2.45:1 on every light theme */
  .fk-section h3.warn{color:var(--warn-ink,var(--warn))} .fk-section h3.ok{color:var(--ok-ink,var(--ok))} .fk-section h3.bad{color:var(--danger-ink,var(--danger))}
  .fk-section h3 .fk-sec-tot{margin-left:auto;font-size:12px;font-weight:600;color:var(--dim);font-variant-numeric:tabular-nums} /* per-section money total, right-aligned + colour-neutral */
  .fk-pay-out{display:flex;align-items:baseline;gap:7px;font-variant-numeric:tabular-nums}
  .fk-pay-out .lbl{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--dim)}
  .fk-pay-out b{font-size:17px;color:var(--text)}

  /* dashboard */
  .fk-segtabs{display:inline-flex;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:3px;gap:2px}
  .fk-segtab{background:none;border:none;color:var(--dim);font-family:inherit;font-size:13px;font-weight:600;padding:5px 14px;border-radius:7px;cursor:pointer;display:flex;align-items:center;gap:6px}
  .fk-segtab.on{background:rgba(255,255,255,.12);color:var(--white)}  /* calm neutral 'raised chip' selected state (perceptible vs the panel2 track) — not a loud accent fill */
  .fk-segtab:not(.on):hover{color:var(--white)}
  .fk-trash-cats{margin:0 0 14px}
  .fk-trash-cats .fk-segtabs{flex-wrap:wrap}
  .fk-seg-n{font-size:11px;font-weight:700;opacity:.6;margin-left:1px}
  .fk-tiles{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:18px}
  .fk-tile{flex:1;min-width:118px;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:13px 15px}
  .fk-tile .v{color:var(--white);font-size:22px;font-weight:700;font-variant-numeric:tabular-nums}
  .fk-tile .l{color:var(--dim);font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;margin-top:3px}
  .fk-tile.bad .v{color:var(--danger)} .fk-tile.warn .v{color:var(--warn)}
  .fk-tile.money{border-color:rgba(0,184,217,.35)}
  /* Reports — horizontal bar breakdowns */
  .rep-sec{margin-bottom:20px}
  .rep-h{color:var(--white);font-size:14px;margin:0 0 11px}
  .rep-bars{display:flex;flex-direction:column;gap:7px}
  .rep-row{display:flex;align-items:center;gap:12px}
  .rep-rl{flex:0 0 140px;font-size:12px;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .rep-rtrack{flex:1;height:18px;background:var(--panel2);border-radius:5px;overflow:hidden;min-width:0}
  .rep-rbar{height:100%;background:var(--accent);border-radius:5px;min-width:3px}
  .rep-rv{flex:0 0 96px;text-align:right;font-size:12px;font-weight:600;color:var(--white);font-variant-numeric:tabular-nums}
  @media (max-width:680px){ .rep-rl{flex-basis:92px} .rep-rv{flex-basis:72px} }
  /* product picker (Quick Quote) */
  .fk-prodhd{color:var(--white);font-size:13px;font-weight:600;margin:2px 0 12px}
  .fk-prodgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:12px}
  .fk-prodcard{display:flex;flex-direction:column;gap:5px;min-height:104px}
  .fk-prodcard .ico{font-size:26px;line-height:1;display:flex;align-items:flex-start;gap:6px}
  .fk-prodcard .soon{font-size:9.5px;color:var(--dim);border:1px solid var(--line);border-radius:20px;padding:1px 7px;height:fit-content;margin-top:2px}

  /* ===== Product range shop (2026-07-31 overhaul) — browse view + configurator; themes via FK tokens ===== */
  .fk-shop{display:grid;grid-template-columns:212px 1fr 320px;grid-template-rows:auto minmax(0,1fr);height:100%;min-height:0}
  /* THE TWO RANGES (owner 2026-09-18). One row across the top of the range, spanning rail, grid and basket:
     TP Products is everything bought in from Tradeprint, Our services is the work we do ourselves. */
  .fk-shop-tabs{grid-column:1/-1;display:flex;gap:2px;align-items:center;padding:10px 14px 0;border-bottom:1px solid var(--line);background:var(--panel)}
  .fk-shop-tab{display:inline-flex;align-items:center;gap:8px;background:none;border:0;border-bottom:2px solid transparent;color:var(--dim);
    font:inherit;font-size:14px;font-weight:600;padding:9px 14px;margin-bottom:-1px;cursor:pointer;border-radius:var(--r-sm) var(--r-sm) 0 0}
  .fk-shop-tab:hover{color:var(--white);background:rgba(255,255,255,.04)}
  .fk-shop-tab.on{color:var(--white);border-bottom-color:var(--accent,#6ee7c7)}
  .fk-shop-tab .n{font-size:11.5px;font-weight:700;color:var(--dim);background:var(--panel2);border:1px solid var(--line);border-radius:999px;padding:1px 8px}
  .fk-shop-tab.on .n{color:var(--white)}
  .fk-shop-rail{border-right:1px solid var(--line);padding:14px 10px;overflow:auto;display:flex;flex-direction:column;gap:2px}
  .fk-shop-search{display:flex;align-items:center;gap:8px;height:36px;padding:0 10px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel2);margin-bottom:12px}
  .fk-shop-search svg{width:14px;height:14px;color:var(--dim);flex:none}
  .fk-shop-search input{border:none;outline:none;background:none;color:var(--text);font:inherit;font-size:13px;width:100%}
  .fk-shop-cap{font-size:10px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--dim);opacity:.7;margin:8px 4px 5px}
  .fk-shop-cat{display:flex;align-items:center;gap:9px;width:100%;text-align:left;background:none;border:1px solid transparent;border-radius:var(--r-sm);color:var(--dim);padding:8px 10px;font:inherit;font-size:13.5px;cursor:pointer}
  .fk-shop-cat:hover{background:var(--panel2);color:var(--text)}
  /* accent-ink, not accent: this is the accent used as TEXT on a tint of itself. With Marine's yellow the raw
     accent measured 1.18:1 here — the label was all but invisible on its own highlight. */
  .fk-shop-cat.on{background:var(--accent-soft);color:var(--accent-ink,var(--accent));font-weight:600;border-color:var(--accent-soft)}
  .fk-shop-cat.on .n{color:var(--accent-ink,var(--dim))}
  .fk-shop-cat .ic{font-size:14px;width:18px;text-align:center;flex:none}
  .fk-shop-cat .n{margin-left:auto;font-size:11px;color:var(--dim);font-variant-numeric:tabular-nums}
  .fk-shop-main{padding:18px 20px;overflow:auto}
  .fk-shop-grp{font-size:13.5px;font-weight:700;color:var(--white);margin:2px 2px 12px;display:flex;align-items:baseline;gap:8px}
  .fk-shop-grp span{font-size:11.5px;color:var(--dim);font-weight:500}
  .fk-shop-grp:not(:first-child){margin-top:22px}
  .fk-shop-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(176px,1fr));gap:13px}
  /* Product Range top bar: search + the Rows/Grid pick (owner 2026-08-05). Search used to sit in the rail;
     it belongs over the results it filters. Sticky so it stays reachable down a 155-product list. */
  .fk-shop-bar{display:flex;align-items:center;gap:12px;margin-bottom:16px;position:sticky;top:0;z-index:2;background:var(--bg);padding-bottom:2px}
  .fk-shop-bar .fk-shop-search{flex:1;margin:0;height:38px}
  .fk-shop-bar .fk-shop-search input{margin-bottom:0}   /* the global input{margin-bottom:16px} would offset it in a flex row */
  .fk-shop-seg{display:flex;flex:0 0 auto;border:1px solid var(--line);border-radius:var(--r-sm);overflow:hidden}
  .fk-shop-seg button{background:var(--panel2);border:none;color:var(--dim);font-size:12.5px;font-weight:600;padding:0 14px;height:38px;cursor:pointer}
  .fk-shop-seg button+button{border-left:1px solid var(--line)}
  .fk-shop-seg button:hover{color:var(--white)}
  .fk-shop-seg button.on{background:var(--panel);color:var(--white)}
  /* Range filters (owner G8 #4.2). A second line under the search rather than crowding the bar, and they
     scroll away with the list — the search stays sticky because it is used constantly; a filter is set once. */
  .fk-shop-filters{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin:-6px 0 14px}
  .fk-shf{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--dim)}
  .fk-shf select{height:30px;padding:0 8px;font-size:12px;font-family:inherit;border:1px solid var(--line);
    border-radius:var(--r-sm);background:var(--panel2);color:var(--text);margin-bottom:0}  /* global input margin would shift the row */
  .fk-shf select:hover{border-color:var(--accent)}
  .fk-shf-todo{height:30px;padding:0 11px;font-size:12px;font-weight:600;font-family:inherit;cursor:pointer;
    border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel2);color:var(--dim)}
  .fk-shf-todo:hover{color:var(--white)}
  .fk-shf-todo.on{background:var(--warn);border-color:var(--warn);color:#15171f}
  .fk-shf-clear{background:none;border:none;color:var(--accent);font-size:12px;font-family:inherit;cursor:pointer;padding:0;text-decoration:underline}
  .fk-shf-count{font-size:11.5px;color:var(--dim);margin-left:auto}
  .fk-lnkbtn{background:none;border:none;color:var(--accent);font:inherit;cursor:pointer;text-decoration:underline;padding:0}
  /* A row carries the same information as a card in a fifth of the height — the range is 155 products and
     the card deck showed about four a screen. */
  .fk-shop-rows{display:flex;flex-direction:column;border:1px solid var(--line);border-radius:var(--r-sm);overflow:hidden}
  .fk-shop-row{display:flex;align-items:center;gap:12px;padding:8px 12px;background:var(--panel2);cursor:pointer;position:relative}
  .fk-shop-row+.fk-shop-row{border-top:1px solid var(--line)}
  .fk-shop-row:hover{background:var(--panel)}
  /* 68px, double the original 34 (owner 2026-08-06): at 34 a printed product was a smudge — you could not
     tell a folded leaflet from a flat one, which is the whole use of having the supplier's photo. */
  .fk-shop-row .rthumb{flex:0 0 68px;width:68px;height:68px;display:flex;align-items:center;justify-content:center;background:var(--bg);border:1px solid var(--line);border-radius:8px;font-size:24px;overflow:hidden}
  .fk-shop-row .rthumb img{width:100%;height:100%;object-fit:cover}
  .fk-shop-row .rmain{flex:1;min-width:0}
  .fk-shop-row .nm{font-size:13px;font-weight:600;color:var(--white);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-shop-row .ds{font-size:11.5px;color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-shop-row .rprice{flex:0 0 auto;text-align:right;font-size:12.5px;font-weight:600;color:var(--white);padding-right:4px}
  .fk-shop-row .rprice small{font-weight:500;color:var(--dim)}
  .fk-shop-row.fk-shop-soon{opacity:.55;cursor:default}
  .fk-shop-redit{flex:0 0 auto;background:transparent;border:none;color:var(--dim);cursor:pointer;font-size:13px;padding:4px;opacity:0;transition:opacity .12s}
  .fk-shop-row:hover .fk-shop-redit,.fk-shop-redit:focus-visible{opacity:1}
  .fk-shop-redit:hover{color:var(--white)}
  .fk-shop-card{position:relative;background:var(--panel);border:1px solid var(--line);border-radius:var(--r);overflow:hidden;cursor:pointer;display:flex;flex-direction:column;transition:transform .12s,box-shadow .12s,border-color .12s}
  .fk-shop-card:hover{transform:translateY(-3px);box-shadow:0 10px 24px rgba(0,0,0,.28);border-color:var(--accent)}
  .fk-shop-thumb{height:94px;display:grid;place-items:center;background:linear-gradient(160deg,var(--panel2),var(--panel));border-bottom:1px solid var(--line);font-size:30px;overflow:hidden}
  /* a photo fills the tile; object-fit keeps any aspect ratio from distorting or breaking the card height */
  .fk-shop-thumb img{width:100%;height:100%;object-fit:cover;display:block}
  .fk-shop-body{padding:11px 13px 12px;display:flex;flex-direction:column;flex:1}
  .fk-shop-nm{font-size:13.5px;font-weight:650;color:var(--white)}
  .fk-shop-ds{font-size:11.5px;color:var(--dim);margin-top:3px;line-height:1.35}
  .fk-shop-foot{margin-top:auto;padding-top:10px;font-size:12px;color:var(--text);font-weight:650}
  .fk-shop-foot small{color:var(--dim);font-weight:500}
  .fk-shop-empty{padding:44px;text-align:center;color:var(--dim);font-size:13px}
  .fk-shop-soon{opacity:.55;cursor:default;position:relative}
  .fk-shop-soon:hover{transform:none;box-shadow:none;border-color:var(--line)}
  .fk-shop-soonbadge{position:absolute;top:8px;right:8px;z-index:1;font-size:8.5px;font-weight:700;color:var(--dim);background:var(--panel2);border:1px solid var(--line);border-radius:999px;padding:1px 7px}
  /* ===== Supplier catalogue (2026-08-03) — a MIRROR of what a supplier sells, browsed here and published
     into the range one product at a time. It takes the grid AND the quote column: you are choosing what to
     sell, not filling a basket. A table rather than cards, because 145 rows are for scanning. All FK theme
     tokens, so the tab's theme picker keeps working. */
  /* NOTE the prefix: `fk-sup-` was already taken by the SUPPLIERS panel further down this file (it defines
     .fk-sup-row/.fk-sup-pill/.fk-sup-meta as flex rules). Same specificity, declared later, so it silently
     won and this table laid out as inline flex. Hence `fk-supcat-`. */
  .fk-shop.supcat{grid-template-columns:212px 1fr}
  .fk-supcat{border-left:1px solid var(--line);background:var(--panel);display:flex;flex-direction:column;min-height:0;overflow:hidden}
  .fk-supcat-hd{padding:16px 20px 0;flex:none}
  .fk-supcat-t{display:flex;align-items:flex-start;gap:14px}
  .fk-supcat-t h3{margin:0;font-size:17px;font-weight:700;color:var(--white);letter-spacing:-.2px}
  .fk-supcat-meta{margin:4px 0 0;font-size:11.5px;color:var(--dim)}
  .fk-supcat-meta .ok{color:var(--ok);font-weight:600}
  .fk-supcat-meta .no{color:var(--danger);font-weight:600}
  .fk-supcat-act{margin-left:auto;display:flex;align-items:center;gap:8px}
  /* the suite-wide input{margin-bottom:16px} would inflate this bar and lift its text off the baseline */
  .fk-supcat-act input{margin:0;width:190px;height:34px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel2);color:var(--text);font:inherit;font-size:12.5px;padding:0 11px;outline:none}
  .fk-supcat-act input:focus{border-color:var(--accent)}
  .fk-supcat-sync{height:34px;padding:0 14px;border:0;border-radius:var(--r-sm);background:var(--accent);color:var(--on-accent,#042a33);font:inherit;font-size:12px;font-weight:700;cursor:pointer;white-space:nowrap}
  .fk-supcat-sync:disabled{opacity:.6;cursor:default}
  .fk-supcat-chips{display:flex;gap:6px;padding:14px 20px 12px;flex-wrap:wrap;flex:none}
  .fk-supcat-chip{height:28px;padding:0 11px;display:inline-flex;align-items:center;gap:6px;border-radius:999px;border:1px solid var(--line);background:var(--panel);color:var(--dim);font:inherit;font-size:11.5px;font-weight:600;cursor:pointer}
  .fk-supcat-chip:hover{color:var(--text);border-color:var(--line2)}
  .fk-supcat-chip.on{background:var(--accent-soft);border-color:var(--accent-soft);color:var(--accent)}
  .fk-supcat-chip b{font-weight:700}
  .fk-supcat-chip .z{opacity:.55;font-weight:500}
  .fk-supcat-tbl{flex:1;overflow:auto;min-height:0;border-top:1px solid var(--line)}
  /* minmax(0,…) not plain fr: an fr track floors at min-content, and since each row is its own grid a long
     options string would widen that row's column alone and the columns would stop lining up down the table. */
  .fk-supcat-row{display:grid;grid-template-columns:minmax(0,1.7fr) minmax(0,2.1fr) 88px 96px 116px;align-items:center;gap:14px;padding:0 20px;min-height:52px;border-bottom:1px solid var(--line)}
  /* Prices cell: a tick box for batching plus the current state */
  .fk-supcat-pr{display:inline-flex;align-items:center;gap:7px;cursor:pointer;font-size:11.5px;color:var(--dim)}
  .fk-supcat-pr input{margin:0;width:14px;height:14px;accent-color:var(--accent);cursor:pointer}
  .fk-supcat-pr span.on{color:var(--ok);font-weight:700;font-variant-numeric:tabular-nums}
  .fk-supcat-dim{color:var(--faint);font-size:11.5px}
  .fk-supcat-foot .pick{display:inline-flex;align-items:center;gap:8px}
  .fk-supcat-foot .pick b{color:var(--accent)}
  .fk-supcat-foot .fk-supcat-add,.fk-supcat-foot .fk-supcat-chip{height:26px;padding:0 10px;font-size:11.5px}
  .fk-supcat-row.hd{position:sticky;top:0;z-index:1;min-height:33px;background:var(--panel2);font-size:10px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--dim)}
  .fk-supcat-row:not(.hd):hover{background:var(--panel2)}
  .fk-supcat-nm{font-size:13px;font-weight:650;color:var(--white)}
  .fk-supcat-key{font-size:10.5px;color:var(--faint);font-family:ui-monospace,"Cascadia Mono",Consolas,monospace;margin-top:1px}
  .fk-supcat-opt{font-size:11.5px;color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .fk-supcat-n{font-size:11.5px;color:var(--text);font-variant-numeric:tabular-nums;line-height:1.35}
  .fk-supcat-n b{color:var(--white);font-weight:650}
  .fk-supcat-pill{display:inline-flex;align-items:center;gap:5px;height:25px;padding:0 10px;border-radius:999px;font-size:11px;font-weight:700;border:0;font-family:inherit}
  .fk-supcat-pill.in{background:color-mix(in srgb,var(--ok) 16%,transparent);color:var(--ok);cursor:pointer}
  .fk-supcat-pill.out{background:var(--panel3);color:var(--faint)}
  .fk-supcat-add{height:30px;padding:0 12px;border:1px solid var(--line);background:var(--panel);border-radius:var(--r-sm);font:inherit;font-size:11.5px;font-weight:700;color:var(--accent);cursor:pointer;white-space:nowrap}
  .fk-supcat-add:hover{background:var(--accent-soft);border-color:var(--accent-soft)}
  .fk-supcat-gone .fk-supcat-nm{color:var(--faint);text-decoration:line-through}
  .fk-supcat-gone .fk-supcat-opt,.fk-supcat-gone .fk-supcat-n,.fk-supcat-gone .fk-supcat-n b{color:var(--faint)}
  .fk-supcat-vals{padding:2px 20px 15px;display:grid;grid-template-columns:150px minmax(0,1fr);gap:7px 16px;align-items:baseline}
  .fk-supcat-vals .v{display:flex;flex-wrap:wrap;gap:5px}
  .fk-supcat-foot{padding:11px 20px;border-top:1px solid var(--line);background:var(--panel2);font-size:11.5px;color:var(--dim);flex:none}
  .fk-supcat-blank{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;text-align:center;padding:20px 56px}
  .fk-supcat-blank .ico{width:56px;height:56px;border-radius:16px;background:var(--accent-soft);display:grid;place-items:center;font-size:25px}
  .fk-supcat-blank h4{margin:0;font-size:16px;font-weight:700;color:var(--white)}
  .fk-supcat-blank p{margin:0;max-width:400px;font-size:12.5px;line-height:1.55;color:var(--dim)}
  .fk-supcat-blank .fk-supcat-sync{height:38px;padding:0 18px;font-size:13px}
  /* delivery-speed picker in the supplier configurator: one API call returns all three, so all three are
     priced on screen and you pick one — no separate quantity x delivery table needed. */
  .fk-supq{display:flex;gap:8px;flex-wrap:wrap}
  .fk-supq-b{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-width:96px;padding:8px 11px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel);font:inherit;cursor:pointer;text-align:left}
  .fk-supq-b b{font-size:12px;font-weight:650;color:var(--white)}
  .fk-supq-b span{font-size:12.5px;color:var(--dim);font-variant-numeric:tabular-nums}
  /* the arrival date Tradeprint gave us — quieter than the price, because the price is what is being compared */
  .fk-supq-b i{font-style:normal;font-size:11px;color:var(--faint);white-space:nowrap}
  .fk-supq-b.on{border-color:var(--accent);background:var(--accent-soft)}
  .fk-supq-b.on b,.fk-supq-b.on span{color:var(--accent)}
  .fk-supq-b.on i{color:var(--accent);opacity:.85}
  /* trade order hand-off, in the drawer's outsourced route */
  .fk-tpo{border:1px solid var(--line);border-radius:var(--r-sm);padding:10px 12px;margin-bottom:8px;background:var(--panel2)}
  .fk-tpo-h{display:flex;align-items:baseline;gap:9px;margin-bottom:7px}
  .fk-tpo-h b{font-size:13px;color:var(--white)}
  .fk-tpo-key{font-size:10.5px;color:var(--faint);font-family:ui-monospace,"Cascadia Mono",Consolas,monospace}
  .fk-tpo-g{display:grid;grid-template-columns:minmax(0,120px) minmax(0,1fr);gap:4px 12px;font-size:12px;align-items:baseline}
  .fk-tpo-g span{color:var(--dim)}
  .fk-tpo-g b{color:var(--text);font-weight:600;word-break:break-word}
  .fk-tpo-warn{margin-top:10px;border:1px solid color-mix(in srgb,var(--warn) 40%,transparent);background:color-mix(in srgb,var(--warn) 10%,transparent);border-radius:var(--r-sm);padding:9px 12px;font-size:12px;color:var(--text)}
  .fk-tpo-warn ul{margin:6px 0 0;padding-left:18px}
  .fk-tpo-warn li{margin:2px 0}
  .fk-tpo-ok{margin-top:10px;border:1px solid color-mix(in srgb,var(--ok) 40%,transparent);background:color-mix(in srgb,var(--ok) 10%,transparent);border-radius:var(--r-sm);padding:9px 12px;font-size:12px;color:var(--text)}
  /* the one control in the suite that spends money — given its own weight so it cannot be clicked absently */
  .fk-tpo-place{margin-top:12px;border:1px solid color-mix(in srgb,var(--accent) 45%,var(--line));border-radius:var(--r-sm);padding:11px 13px;background:color-mix(in srgb,var(--accent) 7%,transparent)}
  .fk-tpo-place-h{display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex-wrap:wrap}
  .fk-tpo-place-h b{font-size:13px;color:var(--white)}
  .fk-tpo-place-h span{font-size:12px;font-weight:600;color:var(--accent);font-variant-numeric:tabular-nums}
  /* the global input{margin-bottom:16px} would drop this field off the row's baseline (see CLAUDE.md) */
  .fk-tpo-place input{margin-bottom:0}

  /* the shop's right-hand quote panel (basket + customer + Create quote) */
  .fk-shop-quote{border-left:1px solid var(--line);background:var(--panel);display:flex;flex-direction:column;overflow:hidden;min-height:0}
  .fk-sq-hd{padding:14px 16px 11px;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--dim);display:flex;align-items:center;gap:8px;border-bottom:1px solid var(--line)}
  .fk-sq-n{font-size:11px;font-weight:700;color:var(--accent);background:var(--accent-soft);border-radius:999px;padding:1px 8px}
  .fk-sq-cust{padding:12px 16px;border-bottom:1px solid var(--line)}
  .fk-sq-for{font-size:12.5px;color:var(--dim);line-height:1.4}
  .fk-sq-for b{color:var(--white)}
  .fk-sq-change{background:none;border:none;color:var(--accent);font:inherit;font-size:12px;cursor:pointer;padding:0 0 0 4px}
  /* remove is the destructive twin of change, so it must not compete with it: dim ink, red only on hover.
     The separator is the pseudo-element rather than markup, and pins its own colour so it stays dim while
     the word beside it turns red. */
  .fk-sq-change.rm{color:var(--dim)}
  .fk-sq-change.rm::before{content:'·';padding-right:5px;color:var(--dim);opacity:.6}
  .fk-sq-change.rm:hover{color:var(--danger-ink,var(--danger))}
  .fk-sq-lines{flex:1;overflow:auto;padding:6px 8px;min-height:0}
  /* TWO COLUMNS, TWO ROWS. It was four columns across one line, and putting the word "Edit" on the button
     (owner 2026-09-06) squeezed the product name into three wrapped lines at this panel's real 330px. The
     name is the longest thing here and the thing being read, so it gets the full width; the controls drop to
     the second row beside the quantity, where there was space doing nothing. */
  .fk-sq-line{display:grid;grid-template-columns:1fr auto;gap:3px 10px;align-items:center;padding:9px 8px;border-radius:9px}
  .fk-sq-line:hover{background:var(--panel2)}
  .fk-sq-nm{font-size:12.5px;color:var(--text);font-weight:500;grid-column:1;grid-row:1;line-height:1.3}
  /* EACH SIZE ON ITS OWN ROW (owner 2026-09-21) — the panel is ~330px, so these wrap rather than run off
     the edge, and the size leads because that is what somebody counting a box reads down. */
  .fk-sq-vars{margin-top:5px;display:flex;flex-direction:column;gap:2px}
  .fk-sq-var{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px;font-size:11px;line-height:1.35}
  .fk-sq-var b{color:var(--white);font-weight:650;letter-spacing:.01em}
  .fk-sq-var .n{color:var(--text);font-variant-numeric:tabular-nums}
  .fk-sq-var .p{color:var(--dim)}
  .fk-sq-meta{font-size:11px;color:var(--dim);grid-column:1;grid-row:2;display:flex;align-items:center;gap:6px}
  .fk-sq-qty{width:60px;margin-bottom:0;padding:2px 6px;font-size:11.5px;text-align:center;font-variant-numeric:tabular-nums}
  .fk-sq-amt{font-size:12.5px;color:var(--white);font-weight:650;font-variant-numeric:tabular-nums;grid-column:2;grid-row:1;text-align:right}
  .fk-sq-vt{font-size:9.5px;font-weight:600;letter-spacing:.03em;color:var(--dim);margin-top:1px;white-space:nowrap}
  .fk-sq-acts{grid-column:2;grid-row:2;display:flex;align-items:center;gap:6px;justify-content:flex-end}
  /* ✎ EDIT, WITH THE WORD ON IT (owner 2026-09-06: "ensure edit is very clear - icon with the word edit").
     It shipped as a bare ✎ revealed on hover, matching the ✕ beside it — which meant the one control on this
     panel nobody had seen before was also the one you had to already know about to find, and invisible on a
     touch screen entirely. It is a labelled button now and it is always there. The ✕ keeps its hover reveal:
     it is destructive, it is the one control everybody already understands, and a delete standing permanently
     beside a labelled Edit is an invitation to the wrong one. */
  .fk-sq-ed{display:inline-flex;align-items:center;gap:4px;align-self:center;
    background:var(--panel3);border:1px solid var(--line2);color:var(--text);font:600 11px/1 inherit;
    font-family:inherit;border-radius:6px;padding:5px 8px;cursor:pointer;white-space:nowrap}
  .fk-sq-ed:hover{border-color:var(--accent);color:var(--white)}
  .fk-sq-rm{background:none;border:none;color:var(--dim);font-size:13px;cursor:pointer;opacity:.55;padding:0}
  .fk-sq-line:hover .fk-sq-rm{opacity:1}
  .fk-sq-rm:hover,.fk-sq-rm:focus-visible{opacity:1;color:var(--danger-ink,var(--danger))}
  /* …and on the quote builder's Line items table, where there is room, both stay visible like every other
     control in that row. Same pair, two densities, because the two surfaces have different budgets. */
  .fk-line-acts{white-space:nowrap}
  .fk-line-acts .fk-btn+.fk-btn{margin-left:5px}
  .fk-sq-foot{border-top:1px solid var(--line);padding:13px 16px 15px}
  .fk-sq-sum{display:flex;justify-content:space-between;font-size:12.5px;color:var(--dim);margin-bottom:6px;font-variant-numeric:tabular-nums}
  .fk-sq-sum.tot{margin-top:8px;padding-top:9px;border-top:1px solid var(--line);color:var(--white);font-weight:700;font-size:14px}
  .fk-sq-empty{padding:28px 16px;text-align:center;color:var(--dim);font-size:12.5px}
  /* ---- garment lines: one tool run = one group of separate lines (mock state 4, owner 2026-09-24) ---- */
  .fk-gl-grp{border:1px solid var(--line2);border-radius:11px;margin:4px 0;background:rgba(255,255,255,.015);overflow:hidden}
  .fk-gl-grphd{padding:9px 10px 8px;border-bottom:1px solid var(--line);background:var(--panel2)}
  .fk-gl-grphd b{display:block;font-size:12.5px;color:var(--white);font-weight:650}
  .fk-gl-grphd span{display:block;font-size:11px;color:var(--dim);margin-top:1px}
  .fk-gl-grphd .fk-gl-tag{display:inline-block;margin-top:5px;font-size:10.5px;font-weight:650;color:var(--accent);background:var(--accent-soft);border-radius:999px;padding:1px 8px}
  .fk-gl-grphd .fk-gl-tag.drop{color:var(--ok-ink);background:rgba(90,221,154,.12)}
  .fk-gl-grp .fk-sq-line{border-radius:0;padding:8px 10px}
  .fk-gl-grp .fk-sq-line+.fk-sq-line{border-top:1px solid var(--line)}
  /* a line the last change re-priced, and the box that was typed into (the mock's right-hand basket) */
  .fk-gl-moved{background:rgba(90,221,154,.06)}
  .fk-sq-qty.fk-gl-typed{border-color:var(--accent)}
  .fk-gl-lab{color:var(--white);font-weight:650;letter-spacing:.01em}
  .fk-gl-each{color:var(--dim);font-variant-numeric:tabular-nums}
  .fk-gl-each s{color:var(--faint);margin-right:3px}
  .fk-gl-each.drop{color:var(--ok-ink)}
  /* the shared garment prices did not load (fix wave 2026-09-25, F1): the basket's and the review page's totals give
     way to the tool's one sentence, because every garment figure there would be the shop defaults */
  .fk-gl-down{padding:10px 12px;border:1px solid var(--warn);border-radius:9px;color:var(--warn-ink,var(--warn));font-size:12.5px;font-weight:600;line-height:1.4}
  /* buyer configurator — mockup frame 5: two columns (option cards + sticky price panel) */
  .fk-cfg-back{position:fixed;inset:0;background:rgba(8,10,16,.6);display:flex;align-items:center;justify-content:center;z-index:62;padding:24px}
  .fk-cfg-panel{width:940px;max-width:96vw;max-height:92vh;overflow:auto;background:var(--panel);border:1px solid var(--line);border-radius:16px;box-shadow:0 24px 70px rgba(0,0,0,.5)}
  .fk-cfg-h{display:flex;align-items:center;gap:12px;padding:18px 22px;border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--panel);z-index:1}
  .fk-cfg-h .ttl{font-size:17px;font-weight:800;color:var(--white)}
  .fk-cfg-h .ttl small{display:block;font-size:12px;font-weight:500;color:var(--dim);margin-top:3px}
  .fk-cfg-pill{margin-left:auto;font-size:12px;font-weight:700;color:var(--accent);background:var(--accent-soft,rgba(8,145,168,.12));border:1px solid var(--line);border-radius:999px;padding:4px 12px}
  /* The supplier's own product page, one click from the configurator (owner 2026-08-06) — for the other
     photos and the finishes. Sits between the pill and the ✕; the pill already claims margin-left:auto, so
     this only needs to not claim it too, or the two would fight over the free space. */
  .fk-cfg-link{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;color:var(--dim);
    background:var(--panel2);border:1px solid var(--line);border-radius:999px;padding:5px 12px;text-decoration:none;white-space:nowrap;transition:color .12s,border-color .12s}
  .fk-cfg-link:hover{color:var(--white);border-color:var(--accent)}
  .fk-cfg-h:not(:has(.fk-cfg-pill)) .fk-cfg-link{margin-left:auto}   /* no pill? then this takes the slack */
  /* Price against the market (owner 2026-08-06). Management sets it here; everyone sees the dot on the range.
     These three are their OWN tokens, not the suite's --ok/--warn/--danger: those are tuned for text and
     status chips, where --warn reads amber and --danger reads a soft coral. The owner asked for a traffic
     light — bright orange, bright red — so this set is deliberately more saturated than the suite palette
     and is defined once here for both the swatch and the thumbnail dot. */
  :root{--eff-low:#12b76a; --eff-standard:#ff7a00; --eff-high:#ff2323}
  .fk-eff{display:inline-flex;align-items:center;gap:8px}
  .fk-eff-lbl{font-size:11px;font-weight:600;color:var(--dim);white-space:nowrap}
  /* a listbox, not a <select>: an OS-drawn option popup cannot carry a swatch reliably */
  .fk-eff-pick{position:relative;display:inline-flex}
  .fk-eff-trigger{display:inline-flex;align-items:center;gap:7px;height:32px;padding:0 9px;font-size:12px;font-family:inherit;
    border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel2);color:var(--text);cursor:pointer;white-space:nowrap}
  .fk-eff-trigger:hover{border-color:var(--accent)}
  .fk-eff-caret{color:var(--dim);font-size:10px}
  .fk-eff-list{position:absolute;top:calc(100% + 4px);left:0;min-width:100%;display:flex;flex-direction:column;
    background:var(--panel);border:1px solid var(--line);border-radius:var(--r-md);padding:4px;z-index:var(--z-dropdown,60);
    box-shadow:0 12px 32px rgba(0,0,0,.45)}
  .fk-eff-list[hidden]{display:none}
  .fk-eff-opt{display:flex;align-items:center;gap:8px;width:100%;text-align:left;background:transparent;border:none;
    color:var(--text);font-size:12.5px;font-family:inherit;padding:6px 8px;border-radius:var(--r-sm);cursor:pointer;white-space:nowrap}
  .fk-eff-opt:hover{background:var(--panel2);color:var(--white)}
  .fk-eff-opt[aria-selected="true"]{color:var(--white);font-weight:600}
  .fk-eff-sw{flex:0 0 11px;width:11px;height:11px;border-radius:50%;background:var(--eff-none,transparent)}
  .fk-eff-sw.eff-none{background:transparent;border:1.5px dashed var(--dim)}   /* not judged: an empty ring, never a colour */
  .fk-eff-sw.eff-low{background:var(--eff-low)}
  .fk-eff-sw.eff-standard{background:var(--eff-standard)}
  .fk-eff-sw.eff-high{background:var(--eff-high)}
  .fk-eff-save{height:32px;padding:0 12px;font-size:12px;font-weight:600;border:1px solid var(--line);
    border-radius:var(--r-sm);background:var(--panel2);color:var(--text);cursor:pointer;white-space:nowrap}
  .fk-eff-save:not(:disabled):hover{border-color:var(--accent);color:var(--white)}
  .fk-eff-save:disabled{opacity:.4;cursor:default}   /* nothing to save until the pick actually differs */
  /* The dot sits beside the PRICE (owner 2026-08-06), not over the thumbnail — the judgement is about the
     price, so it belongs next to it, and it no longer covers part of the product photo. Inline rather than
     absolute now, so it needs no positioning context and cannot be clipped. */
  .fk-eff-dot{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:7px;vertical-align:0;
    box-shadow:0 0 0 1px rgba(0,0,0,.28)}
  .fk-eff-dot.eff-low{background:var(--eff-low)}
  .fk-eff-dot.eff-standard{background:var(--eff-standard)}
  .fk-eff-dot.eff-high{background:var(--eff-high)}
  .fk-cfg-h .x{margin-left:auto;width:34px;height:34px;border-radius:9px;border:1px solid var(--line);background:var(--panel2);color:var(--text);font-size:15px;cursor:pointer}
  .fk-cfg{display:grid;grid-template-columns:1fr 322px;gap:26px;align-items:start;padding:18px 22px 22px}
  .fk-cfg-opts{min-width:0}
  .fk-cfg-og{padding:15px 0;border-bottom:1px solid var(--line)}
  .fk-cfg-og:first-child{padding-top:2px}
  .fk-cfg-oglbl{font-size:12.5px;font-weight:650;color:var(--white);margin-bottom:10px;display:flex;align-items:center;gap:9px}
  .fk-cfg-drop{width:100%;max-width:370px;height:38px;background:var(--panel2);border:1px solid var(--line);border-radius:var(--r-sm);color:var(--white);padding:0 11px;font:inherit;font-size:13.5px;margin:0}
  .fk-cfg .rec{font-size:10px;font-weight:700;color:#9a6a12;background:rgba(245,185,20,.18);border-radius:5px;padding:2px 7px}
  .fk-cfg-ocards{display:flex;flex-wrap:wrap;gap:10px}
  .fk-cfg-ocard{width:112px;border:1.5px solid var(--line);border-radius:11px;background:var(--panel);padding:11px 8px 9px;cursor:pointer;text-align:center;transition:border-color .12s,box-shadow .12s}
  .fk-cfg-ocard:hover{border-color:var(--accent)}
  .fk-cfg-ocard.sel{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent);background:var(--accent-soft,rgba(8,145,168,.1))}
  .fk-cfg-ocard .oc-ic{height:42px;display:grid;place-items:center;margin-bottom:6px}
  .fk-cfg-ocard .oc-ic svg{width:46px;height:38px;display:block}
  .fk-cfg-ocard .oc-lb{font-size:11.5px;font-weight:600;color:var(--white);line-height:1.2}
  .fk-cfg-ocard .oc-rec{display:inline-block;margin-top:5px;font-size:8.5px;font-weight:700;color:#9a6a12;background:rgba(245,185,20,.18);border-radius:4px;padding:1px 5px}
  .fk-cfg-price{border:1px solid var(--line);border-radius:14px;background:var(--panel2);padding:16px 17px;position:sticky;top:78px}
  .fk-cfg-price .cfor{font-size:11.5px;color:var(--dim);line-height:1.45;margin-bottom:13px;padding-bottom:12px;border-bottom:1px solid var(--line)}
  .fk-cfg-price .cfor b{color:var(--white);font-weight:700}
  .fk-cfg-price .prow{display:flex;justify-content:space-between;align-items:center;font-size:12.5px;color:var(--dim);margin-bottom:11px}
  .fk-cfg-price .prow .num{color:var(--white);font-weight:600;font-variant-numeric:tabular-nums}
  .fk-cfg-price .prow small{font-weight:400;color:var(--dim)}
  .fk-cfg-edit{display:inline-flex;align-items:center;gap:4px;background:var(--panel);border:1px solid var(--line);border-radius:7px;padding:2px 8px}
  .fk-cfg-edit input{width:52px;background:none;border:none;color:var(--white);font:inherit;font-size:13px;font-weight:600;text-align:right;padding:2px 0;margin:0;font-variant-numeric:tabular-nums}
  .fk-cfg-edit span{color:var(--dim);font-size:12px}
  .fk-cfg-price .yourprice{border-top:1px solid var(--line);padding-top:12px;margin-top:2px}
  .fk-cfg-price .yp-l{font-size:10.5px;color:var(--dim);text-transform:uppercase;letter-spacing:.05em}
  .fk-cfg-price .yp-v{font-size:26px;font-weight:780;color:var(--white);letter-spacing:-.01em;font-variant-numeric:tabular-nums;line-height:1.15}
  .fk-cfg-price .yp-inc{font-size:11.5px;color:var(--dim);margin-top:2px}
  .fk-cfg-price .cfg-src{font-size:10.5px;color:var(--dim);margin-top:11px;line-height:1.45}
  /* the Price settings row (owner 2026-09-18) — stands in for the three money rows until a member of staff opens it */
  .fk-cfg-ps{width:100%;display:flex;justify-content:space-between;align-items:center;background:none;border:0;border-radius:8px;padding:6px 2px;margin:-4px -2px 9px;font:inherit;font-size:12.5px;color:var(--dim);cursor:pointer;text-align:left}
  .fk-cfg-ps:hover{color:var(--white);background:rgba(255,255,255,.035)}
  .fk-cfg-ps:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
  .fk-cfg-ps .chev{width:16px;height:16px;display:grid;place-items:center;transition:transform .15s}
  .fk-cfg-ps[aria-expanded="true"]{color:var(--white)}
  .fk-cfg-ps[aria-expanded="true"] .chev{transform:rotate(90deg)}
  .fk-cfg-psbody{margin-bottom:2px}
  @media (prefers-reduced-motion:reduce){.fk-cfg-ps .chev{transition:none}}
  @media(max-width:720px){.fk-cfg{grid-template-columns:1fr}.fk-cfg-price{position:static}}
  /* ---- product rule builder (＋ New product) ---- */
  .fk-pb-back{position:fixed;inset:0;background:rgba(8,10,16,.6);display:flex;align-items:center;justify-content:center;z-index:62;padding:24px}
  .fk-pb{width:680px;max-width:96vw;max-height:92vh;background:var(--panel);border:1px solid var(--line);border-radius:14px;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 24px 70px rgba(0,0,0,.5)}
  .fk-pb-h{display:flex;align-items:center;gap:12px;padding:16px 20px;border-bottom:1px solid var(--line)}
  .fk-pb-h .nm{font-size:16px;font-weight:800;color:var(--white)}
  .fk-pb-h .nm small{display:block;font-size:11.5px;font-weight:500;color:var(--dim);margin-top:2px}
  .fk-pb-pill{margin-left:auto;font-size:12px;font-weight:700;color:var(--accent);background:var(--panel2);border:1px solid var(--line);border-radius:999px;padding:4px 12px}
  .fk-pb-h .x{margin-left:auto;width:32px;height:32px;border-radius:8px;border:1px solid var(--line);background:var(--panel2);color:var(--text);font-size:15px;cursor:pointer}
  .fk-pb-b{padding:18px 20px;overflow:auto;flex:1}
  .fk-pb-fields{display:grid;grid-template-columns:1fr 1fr;gap:12px}
  .fk-pb-f{margin:0}
  .fk-pb-f.wide{grid-column:1/-1}
  .fk-pb-f label{display:block;font-size:11px;font-weight:600;color:var(--dim);margin-bottom:5px}
  .fk-pb-opt2{font-weight:500;color:var(--dim)}
  .fk-pb-f input,.fk-pb-f select{width:100%;height:38px;background:var(--panel2);border:1px solid var(--line);border-radius:var(--r-sm);color:var(--white);padding:0 11px;font:inherit;font-size:13.5px;margin:0}
  .fk-pb-q{font-size:12px;font-weight:700;color:var(--white);margin:18px 0 10px}
  .fk-pb-rules{display:grid;grid-template-columns:1fr 1fr;gap:9px}
  .fk-pb-rule{display:flex;gap:11px;align-items:flex-start;text-align:left;padding:12px 13px;background:var(--panel2);border:1.5px solid var(--line);border-radius:11px;cursor:pointer;transition:border-color .12s,box-shadow .12s}
  .fk-pb-rule:hover{border-color:var(--accent)}
  .fk-pb-rule.on{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
  .fk-pb-rule .rk{font-size:15px;width:26px;height:26px;flex:none;display:flex;align-items:center;justify-content:center;border-radius:7px;background:var(--panel);color:var(--accent);font-weight:800}
  .fk-pb-rule .rn{display:block;font-size:13px;font-weight:700;color:var(--white)}
  .fk-pb-rule .rd{display:block;font-size:11px;color:var(--dim);margin-top:2px;line-height:1.35}
  .fk-pb-rule .rex{display:inline-block;font-size:10px;color:var(--accent);margin-top:5px;font-weight:600}
  .fk-pb-seclab{font-size:11px;font-weight:700;color:var(--white);text-transform:uppercase;letter-spacing:.04em;margin:18px 0 4px}
  .fk-pb-seclab span{font-weight:500;text-transform:none;letter-spacing:0;color:var(--dim)}
  .fk-pb-sechint{font-size:11.5px;color:var(--dim);margin-bottom:9px}
  .fk-pb-note{font-size:12.5px;color:var(--dim);background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:11px 13px;line-height:1.5;margin-top:6px}
  /* Product categories manager (rail → ⚙ Manage categories). The global input{margin-bottom:16px} is zeroed
     first: used as a table cell it both inflates the row by 16px and lifts the text off the row's baseline —
     the same trap that has bitten five other controls in this suite. */
  .fk-catmgr{max-width:720px}
  .fk-catmgr .fk-input{margin-bottom:0;width:100%;height:34px}
  .fk-catmgr .fk-input.ic{width:44px;text-align:center;padding:0}
  .fk-catmgr .fk-input.num{width:70px}
  .fk-catmgr-t{width:100%;border-collapse:collapse}
  .fk-catmgr-t th{text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--dim);font-weight:600;padding:0 8px 7px;border-bottom:1px solid var(--line)}
  .fk-catmgr-t td{padding:5px 8px;border-bottom:1px solid var(--line);vertical-align:middle}
  .fk-catmgr-t tr:last-child td{border-bottom:none}
  .fk-catmgr-t th.r,.fk-catmgr-t td.r{text-align:right}
  .fk-catmgr-t td.r{font-variant-numeric:tabular-nums;color:var(--text)}
  .fk-catmgr-t td.empty{color:var(--dim);font-size:12.5px;text-align:center;padding:18px 8px}
  .fk-catmgr-t tr.off .fk-input{opacity:.6}
  .fk-catmgr-t .warn{color:var(--warn)}
  .fk-catmgr-add{display:flex;gap:8px;align-items:center}
  .fk-catmgr-add .fk-input{margin-bottom:0}
  .fk-pb-money{display:flex;align-items:center;gap:6px;background:var(--panel2);border:1px solid var(--line);border-radius:var(--r-sm);padding:0 11px;height:38px;max-width:200px}
  .fk-pb-money span{color:var(--dim);font-size:13px}
  .fk-pb-money input{flex:1;min-width:0;background:none;border:none;color:var(--white);font:inherit;font-size:14px;padding:0;height:100%;margin:0}
  .fk-pb-money.r{max-width:120px}
  .fk-pb-inline{display:flex;align-items:center;gap:12px;margin-top:10px}
  .fk-pb-inline label{font-size:12px;font-weight:600;color:var(--dim)}
  .fk-pb-seg{display:inline-flex;border:1px solid var(--line);border-radius:9px;overflow:hidden;margin-top:4px}
  .fk-pb-seg button{background:var(--panel2);border:none;border-right:1px solid var(--line);color:var(--dim);font:inherit;font-size:12.5px;padding:8px 14px;cursor:pointer}
  .fk-pb-seg button:last-child{border-right:none}
  /* the ink follows the accent — #07222a was written for the default cyan and is unreadable on Marine's yellow */
  .fk-pb-seg button.on{background:var(--accent);color:var(--on-accent);font-weight:700}
  .fk-pb-opt{display:flex;align-items:flex-start;gap:10px;padding:11px;background:var(--panel2);border:1px solid var(--line);border-radius:10px;margin-bottom:9px}
  .fk-pb-oname{width:170px;flex:none;height:34px;background:var(--panel);border:1px solid var(--line);border-radius:8px;color:var(--white);padding:0 10px;font:inherit;font-size:13px;margin:0}
  .fk-pb-vals{display:flex;flex-wrap:wrap;gap:6px;flex:1}
  .fk-pb-chip{display:inline-flex;align-items:center;background:var(--panel);border:1px solid var(--line);border-radius:7px;height:32px}
  .fk-pb-chip input{width:84px;background:none;border:none;color:var(--white);font:inherit;font-size:12.5px;padding:0 8px;height:100%;margin:0}
  .fk-pb-chip button,.fk-pb-qb button,.fk-pb-optrm,.fk-pb-tier button{background:none;border:none;color:var(--dim);cursor:pointer;font-size:12px;padding:0 6px}
  .fk-pb-chip button:hover,.fk-pb-qb button:hover,.fk-pb-optrm:hover,.fk-pb-tier button:hover{color:#e26d6d}
  .fk-pb-optrm{flex:none;align-self:center}
  .fk-pb-star{background:none;border:none;color:var(--line);cursor:pointer;font-size:12px;padding:0 3px;line-height:1}
  .fk-pb-star:hover,.fk-pb-star.on{color:#e6a817}
  .fk-pb-add{background:var(--panel2);border:1px dashed var(--line);border-radius:8px;color:var(--accent);font:inherit;font-size:12px;font-weight:600;padding:7px 12px;cursor:pointer;margin-top:2px}
  .fk-pb-add:hover{border-color:var(--accent)}
  .fk-pb-add.sm{padding:0 10px;height:32px;border-radius:7px;margin-top:0}
  .fk-pb-photos{display:flex;flex-wrap:wrap;gap:9px;margin-top:4px}
  .fk-pb-photos .sh{position:relative;width:104px;height:76px;border:1px solid var(--line);border-radius:9px;overflow:hidden;background:var(--panel2)}
  .fk-pb-photos .sh img{width:100%;height:100%;object-fit:cover;display:block}
  .fk-pb-photos .sh .cv{position:absolute;left:5px;bottom:5px;font-size:9.5px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--on-accent,#042a33);background:var(--accent);border-radius:5px;padding:1px 6px}
  .fk-pb-photos .sh button{position:absolute;top:4px;right:4px;width:20px;height:20px;border-radius:6px;border:none;background:rgba(8,10,16,.66);color:#fff;font-size:11px;line-height:1;cursor:pointer;padding:0}
  .fk-pb-photos .sh button:hover{background:#c9483f}
  .fk-pb-photos .add{width:104px;height:76px;border:1px dashed var(--line);border-radius:9px;background:var(--panel2);color:var(--accent);font:inherit;font-size:17px;cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px}
  .fk-pb-photos .add span{font-size:11px;font-weight:600}
  .fk-pb-photos .add:hover{border-color:var(--accent)}
  /* "3" badge on a card whose product has more than one photo */
  /* a supplier line's quantity is fixed by the configurator, so it reads as a value not an input */
  .fk-qty-fixed{display:inline-block;font-size:13px;font-weight:650;color:var(--white);font-variant-numeric:tabular-nums;padding:0 6px}
  .fk-shop-nph{position:absolute;right:7px;bottom:7px;font-size:10px;font-weight:700;color:#fff;background:rgba(8,10,16,.62);border-radius:6px;padding:1px 6px}
  .fk-shop-thumb{position:relative}
  .fk-pb-tablewrap{overflow-x:auto;margin-top:4px}
  .fk-pb-ptable{border-collapse:collapse;font-size:12.5px}
  .fk-pb-ptable th{background:var(--panel2);color:var(--dim);font-weight:600;text-align:left;padding:7px 9px;border:1px solid var(--line);white-space:nowrap}
  .fk-pb-ptable tbody th{color:var(--white)}
  .fk-pb-ptable td{border:1px solid var(--line);padding:2px}
  .fk-pb-cell{display:flex;align-items:center;gap:3px;padding:0 6px}
  .fk-pb-cell span{color:var(--dim);font-size:12px}
  .fk-pb-cell input{width:66px;background:none;border:none;color:var(--white);font:inherit;font-size:13px;padding:5px 0;margin:0}
  .fk-pb-breaks{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:4px}
  .fk-pb-tiers,.fk-pb-bundle{display:flex;flex-direction:column;align-items:flex-start;gap:8px;margin-top:4px}
  .fk-pb-qb{display:inline-flex;align-items:center;gap:5px;background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:4px 4px 4px 9px;font-size:12px;color:var(--dim)}
  .fk-pb-qb input{width:48px;background:var(--panel);border:1px solid var(--line);border-radius:6px;color:var(--white);font:inherit;font-size:12px;padding:3px 5px;margin:0}
  .fk-pb-tier{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--dim);background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:7px 10px}
  .fk-pb-tier input{width:74px;background:var(--panel);border:1px solid var(--line);border-radius:6px;color:var(--white);font:inherit;font-size:12.5px;padding:5px 7px;margin:0}
  .fk-pb-part{display:flex;align-items:center;gap:10px}
  .fk-pb-plabel{width:190px;height:38px;background:var(--panel2);border:1px solid var(--line);border-radius:var(--r-sm);color:var(--white);padding:0 11px;font:inherit;font-size:13px;margin:0}
  .fk-pb-foot{display:flex;align-items:center;gap:10px;padding:14px 20px;border-top:1px solid var(--line);background:var(--panel2)}
  .fk-pb-prev{margin-left:auto;font-size:12.5px;color:var(--accent);font-weight:600;font-variant-numeric:tabular-nums}
  .fk-pb-del{background:none;border:1px solid var(--line);color:#e26d6d;font:inherit;font-size:12.5px;font-weight:600;padding:8px 13px;border-radius:9px;cursor:pointer}
  .fk-shop-new{margin-top:12px;width:100%;background:var(--panel2);border:1px dashed var(--line);border-radius:9px;color:var(--accent-ink,var(--accent));font:inherit;font-size:12.5px;font-weight:700;padding:9px;cursor:pointer}
  .fk-shop-new:hover{border-color:var(--accent)}
  /* was opacity:0 until hover, which made it unfindable — you cannot hover on a touch screen, and an admin
     looking for "where do I edit this product" had nothing to aim at. Visible, and stronger on hover. */
  .fk-shop-edit{position:absolute;top:7px;right:7px;z-index:2;width:26px;height:26px;border-radius:7px;border:1px solid var(--line);background:var(--panel);color:var(--dim);font-size:12px;cursor:pointer;opacity:.65;transition:opacity .12s,color .12s,border-color .12s}
  .fk-shop-card:hover .fk-shop-edit,.fk-shop-edit:focus-visible{opacity:1}
  .fk-shop-edit:hover{color:var(--accent);border-color:var(--accent)}
  .fk-shop-import{margin-top:7px;width:100%;background:var(--accent-soft,rgba(8,145,168,.12));border:1px solid transparent;border-radius:9px;color:var(--accent-ink,var(--accent));font:inherit;font-size:12.5px;font-weight:700;padding:9px;cursor:pointer}
  .fk-shop-import:hover{background:var(--accent);color:var(--on-accent,#fff)}
  /* importer: paste box + parsed feedback + margin chip + worked example */
  .fk-pb-paste{width:100%;min-height:120px;background:var(--panel2);border:1px solid var(--line);border-radius:var(--r-sm);color:var(--white);padding:10px 12px;font:inherit;font-size:13px;line-height:1.7;font-variant-numeric:tabular-nums;resize:vertical;max-width:100%;overflow-wrap:anywhere;field-sizing:content;max-height:min(calc(1.7em * var(--ta-lines)), var(--ta-vh));overflow-y:auto}
  .fk-pb-parsed{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--accent);font-weight:600;margin-top:9px}
  .fk-pb-parsed .tk{width:16px;height:16px;border-radius:50%;background:var(--accent);color:var(--on-accent);display:flex;align-items:center;justify-content:center;font-size:10px;flex:none}
  .fk-pb-parsed.bad{color:#c9773a}
  .fk-pb-basis{display:flex;align-items:center;gap:14px;background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:12px 14px;margin-top:6px}
  .fk-pb-basis .t{font-size:12px;color:var(--dim);line-height:1.5;flex:1}
  .fk-pb-basis .t b{color:var(--white)}
  .fk-pb-mchip{display:inline-flex;align-items:center;gap:10px;background:var(--panel);border:1px solid var(--line);border-radius:999px;padding:5px 8px;font-weight:800;color:var(--white);font-size:14px;white-space:nowrap}
  .fk-pb-mchip button{width:24px;height:24px;border-radius:50%;border:1px solid var(--line);background:var(--panel2);color:var(--accent);font-size:15px;line-height:1;cursor:pointer;padding:0}
  .fk-pb-eg{margin-top:12px;border:1px solid var(--line);border-radius:10px;overflow:hidden}
  .fk-pb-eg .r{display:grid;grid-template-columns:1fr auto auto;gap:14px;padding:8px 13px;font-size:12.5px;font-variant-numeric:tabular-nums;border-bottom:1px solid var(--line)}
  .fk-pb-eg .r:last-child{border-bottom:none}
  .fk-pb-eg .r.hd{background:var(--panel2);color:var(--dim);font-weight:600;font-size:10.5px;text-transform:uppercase;letter-spacing:.05em}
  .fk-pb-eg .r span{text-align:right;color:var(--text)}
  .fk-pb-eg .r span:first-child{text-align:left}
  .fk-pb-eg .r .s{color:var(--accent);font-weight:700}
  .foothint{margin-right:auto;font-size:11.5px;color:var(--dim);max-width:340px;line-height:1.5}
  /* surcharge (modifier) option editor */
  .fk-pb-opt.col{flex-direction:column;align-items:stretch;gap:9px}
  .fk-pb-oname.wide{width:auto}
  .fk-pb-mvals{display:flex;flex-direction:column;gap:6px}
  .fk-pb-mval{display:flex;align-items:center;gap:7px}
  .fk-pb-mval>input:first-child{flex:1;height:32px;background:var(--panel);border:1px solid var(--line);border-radius:7px;color:var(--white);padding:0 9px;font:inherit;font-size:12.5px;margin:0}
  .fk-pb-mval .d{color:var(--dim);font-size:12px}
  .fk-pb-mval input[data-delta]{width:78px;height:32px;background:var(--panel);border:1px solid var(--line);border-radius:7px;color:var(--white);padding:0 8px;font:inherit;font-size:12.5px;margin:0}
  .fk-pb-optrm.mod{align-self:flex-start;width:auto;font-size:11px;color:var(--dim);border:1px solid var(--line);border-radius:7px;padding:4px 9px;background:var(--panel2)}
  @media(max-width:600px){.fk-pb-fields,.fk-pb-rules{grid-template-columns:1fr}.fk-pb-oname{width:130px}}
  .fk-shop-basket{position:fixed;bottom:16px;left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:16px;padding:9px 12px 9px 20px;background:var(--panel);border:1px solid var(--line);border-radius:999px;box-shadow:0 12px 34px rgba(0,0,0,.42);z-index:30}
  .fk-shop-basket span{font-size:13px;color:var(--text)}
  .fk-shop-basket b{color:var(--white)}
  .fk-line-prod{font-weight:600;color:var(--white);line-height:1.35;white-space:normal;max-width:340px}
  /* ---- the garment builder (replaces the five-field Garment + Print calculator, 2026-09-20) ---- */
  .fk-gb-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;align-items:stretch}
  .fk-gb-card{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px}
  .fk-gb-step{display:flex;gap:10px;align-items:flex-start;margin-bottom:12px}
  .fk-gb-step b{flex:none;width:26px;height:26px;border-radius:8px;display:grid;place-items:center;background:var(--accent-soft,rgba(255,255,255,.07));color:var(--accent);font-size:13px}
  .fk-gb-step h4{margin:0;font-size:14px;color:var(--white)}
  .fk-gb-step small{color:var(--dim);font-size:11.5px}
  .fk-gb-lbl{display:block;font-size:11px;color:var(--dim);font-weight:600;margin-bottom:5px}
  .fk-gb-two{display:grid;grid-template-columns:1fr 1fr;gap:10px}
  .fk-gb-two .fk-input{width:100%;height:36px}
  .fk-gb-prod{display:grid;grid-template-columns:240px 1fr;gap:12px;align-items:center;margin-top:12px}
  .fk-gb-photo{height:180px;border:1px solid var(--line);border-radius:10px;background:var(--panel2);overflow:hidden}
  .fk-gb-photo img{width:100%;height:100%;object-fit:contain;display:block}
  .fk-gb-nm{font-weight:650;color:var(--white);font-size:14px}
  .fk-gb-sku{margin-left:6px;padding:2px 6px;border-radius:999px;background:var(--panel2);border:1px solid var(--line);font-size:9.5px;color:var(--dim);vertical-align:middle}
  .fk-gb-ds{font-size:11.5px;color:var(--dim);margin-top:2px}
  .fk-gb-cost{font-size:15px;font-weight:700;color:var(--white);margin-top:7px}
  .fk-gb-cost small{font-size:10.5px;font-weight:500;color:var(--dim);margin-left:4px}
  .fk-gb-seg{display:flex;gap:6px;margin-top:12px}
  .fk-gb-seg button{flex:1;border:1px solid var(--line);background:var(--panel2);color:var(--text);border-radius:9px;padding:8px;font-weight:600;font-size:12px;cursor:pointer}
  /* --on-accent, not a literal: FK themes RE-HUE the accent, so #fff is readable on some of them and
     not others. test/fk-theme-accent-ink.test.cjs is the guard that caught this. */
  .fk-gb-seg button.on{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
  .fk-gb-vat{margin-top:8px;padding:7px 10px;border-radius:9px;font-size:11px;font-weight:600;background:var(--panel2);border:1px solid var(--line);color:var(--dim)}
  .fk-gb-vat.zero{border-color:var(--ok);color:var(--ok)}
  .fk-gb-cols{display:grid;grid-template-columns:repeat(7,1fr);gap:7px}
  .fk-gb-col{border:0;background:none;padding:2px;cursor:pointer;display:flex;flex-direction:column;align-items:center;gap:3px}
  .fk-gb-col span{width:30px;height:30px;border-radius:50%;border:2px solid var(--line);display:block}
  .fk-gb-col small{font-size:8.5px;color:var(--dim);line-height:1.1;text-align:center}
  .fk-gb-col.on span{outline:2px solid var(--accent);outline-offset:2px}
  .fk-gb-col.on small{color:var(--white)}
  .fk-gb-qty{max-width:180px}
  .fk-gb-qty .fk-input{width:100%;height:36px}
  .fk-gb-sizes{display:grid;grid-template-columns:repeat(5,1fr);gap:7px;margin-top:10px}
  .fk-gb-size{border:1px solid var(--line);background:var(--panel2);border-radius:9px;padding:7px;text-align:center;display:block}
  .fk-gb-size b{display:block;font-size:10.5px;color:var(--dim);margin-bottom:4px}
  .fk-gb-size .fk-input{width:100%;height:30px;text-align:center;padding:0}
  /* the running total — the number being checked against the customer order, so it reads as a line
     rather than a footnote (owner 2026-09-20) */
  .fk-gb-note{margin-top:10px;padding:8px 11px;border-radius:9px;background:var(--panel2);border:1px solid var(--line);font-size:13px;font-weight:650}
  .fk-gb-note.ok{color:var(--ok)}
  .fk-gb-note.warn{color:var(--warn)}
  /* the suite-wide input{margin-bottom:16px} lifts a checkbox out of its own row — the trap CLAUDE.md
     records biting five controls already. Zero it here, and give the box a fixed size so the label sits
     beside it rather than under it. */
  /* .fk-modal label{display:block} and .fk-modal input{width:100%} are BOTH more specific than a bare
     .fk-gb-* class (or tie it and come later), so without the .fk-modal prefix here the label stops being a
     flex row and the checkbox stretches to 620px. Enumerated with getComputedStyle rather than guessed.
     Same family as the suite-wide input{margin-bottom:16px} that CLAUDE.md records biting five controls. */
  .fk-modal .fk-gb-switch{display:flex;align-items:center;gap:9px;font-size:12.5px;color:var(--text);cursor:pointer;margin:0 0 10px;padding:9px 11px;border:1px solid var(--line);border-radius:10px;background:var(--panel2)}
  .fk-modal .fk-gb-switch input{margin:0;width:16px;height:16px;flex:none;accent-color:var(--accent)}
  .fk-gb-switch span{font-weight:600}
  /* The price-settings gate. Prefixed with .fk-modal for the same reason .fk-gb-switch is: the modal sets
     `label{display:block}` and `input{width:100%}`, which out-specify a bare .fk-gb-* rule and stretched
     the print checkbox to 620px when that was first written. The code box is sized to three digits. */
  .fk-modal .fk-gb-pin{padding:22px 4px;max-width:420px}
  .fk-modal .fk-gb-pin h4{margin:0 0 6px;font-size:15px}
  .fk-modal .fk-gb-pin p{margin:0 0 14px;font-size:12.5px;color:var(--muted);line-height:1.5}
  .fk-modal .fk-gb-pin input{width:86px;margin:0;text-align:center;letter-spacing:6px;font-size:18px;font-weight:700;
    padding:8px 10px;border:1px solid var(--line);border-radius:9px;background:var(--panel2);color:var(--text)}
  .fk-modal .fk-gb-pin .fk-gb-why{margin-top:12px}
  /* ── WINDOW GRAPHICS & APPLICATION ─────────────────────────────────────────────────────────────── */
  /* NOT align-items:start (which the garment grid used until 2026-09-25): the material picker is roughly twice the height
     of the panes card beside it, and "start" left a 240px hole under the short one. Stretching makes the
     two cards in a row the same height, so the hole becomes card rather than background. */
  .fk-modal .fk-wg-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}
  .fk-modal .fk-wg-card{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px}
  .fk-modal .fk-wg-step{display:flex;gap:10px;align-items:flex-start;margin-bottom:12px}
  .fk-modal .fk-wg-step b{flex:none;width:26px;height:26px;border-radius:8px;display:grid;place-items:center;
    background:var(--accent-soft,rgba(255,255,255,.07));color:var(--accent);font-size:12.5px}
  .fk-modal .fk-wg-step h4{margin:0;font-size:14px}
  .fk-modal .fk-wg-step small{color:var(--muted);font-size:11.5px;line-height:1.4}
  /* tables: compact, right-aligned numbers, and inputs that do NOT inherit the modal full width */
  .fk-modal .fk-wg-tbl{width:100%;border-collapse:collapse;font-size:12.5px}
  .fk-modal .fk-wg-tbl th{text-align:left;font-size:10.5px;text-transform:uppercase;letter-spacing:.4px;
    color:var(--muted);font-weight:700;padding:0 6px 6px 0;white-space:nowrap}
  .fk-modal .fk-wg-tbl td{padding:4px 6px 4px 0;border-top:1px solid var(--line);vertical-align:middle}
  .fk-modal .fk-wg-tbl input,.fk-modal .fk-wg-tbl select{width:100%;min-width:68px;max-width:110px;margin:0;
    padding:5px 7px;font-size:12.5px;background:var(--panel2);border:1px solid var(--line);border-radius:7px;color:var(--text)}
  .fk-modal .fk-wg-tbl small.fk-wg-was{display:block;color:var(--muted);font-size:10px;text-decoration:line-through}
  .fk-modal .fk-wg-band{font-size:10.5px;padding:2px 7px;border-radius:999px;background:var(--panel2);color:var(--muted);white-space:nowrap}
  .fk-modal .fk-wg-auto{color:var(--muted);font-variant-numeric:tabular-nums}
  .fk-modal .fk-wg-meta{font-size:11.5px;color:var(--muted)}
  .fk-modal .fk-wg-meta b{color:var(--text)}
  .fk-modal .fk-wg-note{font-size:11.5px;color:var(--warn,#c9a227)}
  /* the material picker: a real photograph per material, because "one-way vision" means nothing in words */
  /* 420, not 280: measured at 742px of content, so 280 showed two and a half categories and cut the third
     row of tiles through the middle — which reads as a rendering fault rather than a scroll area. The card
     beside it is stretched tall by the grid anyway, so the room costs nothing. */
  .fk-modal .fk-wg-pick{max-height:420px;overflow-y:auto;padding-right:4px}
  .fk-modal .fk-wg-cat h5{margin:10px 0 6px;font-size:10.5px;text-transform:uppercase;letter-spacing:.4px;color:var(--muted)}
  .fk-modal .fk-wg-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(112px,1fr));gap:8px}
  .fk-modal .fk-wg-tile{display:flex;flex-direction:column;gap:4px;padding:6px;border-radius:10px;cursor:pointer;
    background:var(--panel2);border:1px solid var(--line);text-align:left;color:var(--text)}
  .fk-modal .fk-wg-tile img{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:6px;display:block}
  .fk-modal .fk-wg-tile span{font-size:11px;line-height:1.3}
  .fk-modal .fk-wg-tile b{font-size:11px;color:var(--muted)}
  .fk-modal .fk-wg-tile.on{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
  .fk-modal .fk-wg-detail{display:flex;gap:10px;align-items:center;margin-top:12px;padding-top:12px;border-top:1px solid var(--line)}
  .fk-modal .fk-wg-detail img{width:76px;height:57px;object-fit:cover;border-radius:8px;flex:none}
  .fk-modal .fk-wg-detail > div{min-width:0;flex:1}
  .fk-modal .fk-wg-detail b{display:block;font-size:12.5px}
  .fk-modal .fk-wg-detail small{display:block;color:var(--muted);font-size:11px;line-height:1.4;margin:2px 0 3px}
  .fk-modal .fk-wg-field{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:8px 0 0;font-size:12.5px}
  .fk-modal .fk-wg-field input,.fk-modal .fk-wg-field select{width:auto;min-width:150px;max-width:230px;margin:0;
    padding:6px 9px;font-size:12.5px;background:var(--panel2);border:1px solid var(--line);border-radius:8px;color:var(--text)}
  .fk-modal .fk-wg-switch{display:flex;align-items:center;gap:9px;font-size:12.5px;color:var(--text);cursor:pointer;
    margin:0;padding:9px 11px;border:1px solid var(--line);border-radius:10px;background:var(--panel2)}
  .fk-modal .fk-wg-switch input{margin:0;width:16px;height:16px;flex:none;accent-color:var(--accent)}
  /* the answer, and where it came from */
  .fk-modal .fk-wg-foot{margin-top:12px;padding:14px;border:1px solid var(--line);border-radius:12px;background:var(--panel)}
  .fk-modal .fk-wg-sums{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}
  .fk-modal .fk-wg-sums > div{background:var(--panel2);border-radius:10px;padding:9px 11px}
  .fk-modal .fk-wg-sums span{display:block;font-size:10.5px;text-transform:uppercase;letter-spacing:.4px;color:var(--muted)}
  .fk-modal .fk-wg-sums b{font-size:16px;font-variant-numeric:tabular-nums}
  .fk-modal .fk-wg-sums .tot b{color:var(--accent)}
  .fk-modal .fk-wg-why{margin-top:10px;font-size:11.5px;color:var(--muted);line-height:1.5}
  .fk-modal .fk-wg-set h5{margin:16px 0 6px;font-size:10.5px;text-transform:uppercase;letter-spacing:.4px;color:var(--muted)}
  @media (max-width:900px){ .fk-modal .fk-wg-grid{grid-template-columns:1fr} .fk-modal .fk-wg-sums{grid-template-columns:repeat(2,1fr)} }
  .fk-gb-prints{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
  .fk-gb-print{border:1px solid var(--line);background:var(--panel2);border-radius:10px;padding:0;overflow:hidden;cursor:pointer;text-align:left;display:block}
  .fk-gb-print img{width:100%;height:104px;object-fit:contain;background:var(--panel);display:block}
  .fk-gb-print span{display:block;padding:7px 8px}
  .fk-gb-print b{display:block;font-size:11px;color:var(--white);line-height:1.25}
  .fk-gb-print small{font-size:10px;color:var(--dim)}
  .fk-gb-print.on{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}
  /* the price settings screen, inside the same modal as the builder */
  .fk-gb-shead{display:flex;justify-content:space-between;align-items:flex-start;gap:14px;margin-bottom:12px}
  .fk-gb-shead h4{margin:0;font-size:15px;color:var(--white)}
  .fk-gb-shead small{color:var(--dim);font-size:11.5px}
  .fk-gb-mk{display:grid;grid-template-columns:repeat(7,1fr);gap:8px}
  .fk-gb-mkcell{display:flex;flex-direction:column;gap:4px;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:8px;position:relative}
  .fk-gb-mkcell span{font-size:10.5px;color:var(--dim);font-weight:700}
  .fk-modal .fk-gb-mkcell .fk-input{width:100%;height:30px;text-align:center;padding:0 14px 0 6px;margin:0}
  .fk-gb-mkcell i{position:absolute;right:12px;bottom:14px;font-style:normal;font-size:10.5px;color:var(--dim);pointer-events:none}
  /* why the Add button is not available — beside it, not in another card where it is not looked at */
  .fk-gb-why{font-size:11.5px;color:var(--warn);font-weight:600}
  .fk-gb-scroll{overflow-x:auto}
  .fk-modal .fk-gb-ptab .fk-input{width:66px;height:28px;text-align:right;padding:0 6px;margin:0}
  .fk-gb-ptab td,.fk-gb-ptab th{white-space:nowrap}
  .fk-gb-costs{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
  .fk-gb-costcell{display:flex;align-items:center;justify-content:space-between;gap:10px;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:8px 10px}
  .fk-gb-costcell>span:first-child{font-size:11.5px;color:var(--text)}
  .fk-gb-costcell i{font-style:normal;color:var(--dim);font-size:9.5px;margin-left:4px}
  .fk-modal .fk-gb-costcell .fk-input{width:84px;height:28px;text-align:right;padding:0 6px;margin:0}
  @media(max-width:900px){.fk-gb-mk{grid-template-columns:repeat(4,1fr)}.fk-gb-costs{grid-template-columns:1fr 1fr}}
  @media(max-width:1000px){.fk-gb-grid{grid-template-columns:1fr}.fk-gb-prints{grid-template-columns:repeat(3,1fr)}}
  @media(max-width:620px){.fk-gb-cols{grid-template-columns:repeat(5,1fr)}.fk-gb-sizes{grid-template-columns:repeat(3,1fr)}.fk-gb-prints{grid-template-columns:repeat(2,1fr)}.fk-gb-two{grid-template-columns:1fr}.fk-gb-prod{grid-template-columns:120px 1fr}.fk-gb-photo{height:120px}}

  /* THE COLOUR-FIRST TOOL (garment lines Task 6, 2026-09-24) — ported from the mock's .gm-* rules,
     docs/prototype/garment-tool/mock.css, renamed gm- -> fk-gl-. Every rule of the tool is scoped to .fk-modal
     (Task 10): the modal's own `input{width:100%}` and `label{display:block}` out-rank a bare class, and the
     tool only ever draws inside #fk-modal. */
  /* THE GARMENT TOOL FITS THE SCREEN (owner 2026-09-24: "＋ Add another colour" was cut off). The modal is a fixed
     90vh column; the tool's body scrolls; the total bar stays at the foot. Checked at 1600×1000 and 1366×768.
     fk.js puts .fk-modal-gl on the modal for the garment tool only, and closeModal takes it off again. */
  .fk-modal.fk-modal-gl{height:90vh;display:flex;flex-direction:column;overflow:hidden;padding-bottom:0}
  .fk-modal.fk-modal-gl #al-calc{flex:1;min-height:0;display:flex;flex-direction:column}
  .fk-modal .fk-gl{flex:1;min-height:0;display:flex;flex-direction:column}
  .fk-modal .fk-gl-scroll{flex:1;min-height:0;overflow-y:auto;padding-bottom:20px}
  /* the Garment column is the mock's 600px wherever the print tiles still get 520px beside it; on a narrower laptop
     (1001–1150px) it gives way rather than squeezing the tiles to 77px pictures — the prints keep at least half
     (fix wave 2026-09-25) */
  .fk-modal .fk-gl-top{grid-template-columns:minmax(0,600px) minmax(min(520px,50%),1fr)}
  /* wraps, and a select never outgrows its card: "Customer's own garment — print only" is wider than a phone */
  .fk-modal .fk-gl-pick{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap}
  .fk-modal .fk-gl-pick>div{min-width:0;max-width:100%}
  .fk-modal .fk-gl-pick select{width:auto;max-width:100%;height:36px;margin:0;padding-right:30px}
  .fk-modal .fk-gl-fitrow{display:flex;align-items:center;gap:12px;margin-top:14px;flex-wrap:wrap}
  .fk-modal .fk-gl-fitrow .fk-gb-vat{margin:0}
  .fk-modal .fk-gl-seg{display:inline-flex;margin:0}
  .fk-modal .fk-gl-seg button{flex:none;padding:8px 18px}
  .fk-modal .fk-gb-switch.fk-gl-nat{display:inline-flex;padding:9px 14px 9px 11px}
  .fk-modal .fk-gb-switch.fk-gl-nat+.fk-gb-prints{margin-top:0}
  .fk-modal .fk-gb-card>.fk-gb-switch.fk-gl-nat{margin-bottom:12px}

  /* CUSTOM GARMENT / CUSTOMER'S OWN GARMENT (garment lines Task 8, 2026-09-24) — ported from the mock's
     .gm-form* rules, docs/prototype/garment-tool/mock.css "the custom / customer's own form", renamed
     gm- -> fk-gl-. .gm-fitrow / .gm-seg were already ported above (Task 6) as .fk-gl-fitrow / .fk-gl-seg, so
     only the form itself — and the seg's form-local look — are new here. */
  .fk-modal .fk-gl-form{margin-top:14px;padding:12px 14px 14px;border:1px solid var(--line2);border-radius:10px;background:var(--panel2)}
  .fk-modal .fk-gl-formhd{font-size:13px;font-weight:650;color:var(--white);margin-bottom:10px;display:flex;align-items:center;gap:10px}
  .fk-modal .fk-gl-formhd span{font-size:11px;font-weight:500;color:var(--dim)}
  .fk-modal .fk-gl-formhd .fk-gl-only{font-weight:650;color:var(--accent);background:var(--accent-soft);border-radius:999px;padding:2px 9px}
  .fk-modal .fk-gl-frow{display:flex;gap:14px;align-items:flex-end;flex-wrap:wrap}
  .fk-modal .fk-gl-frow+.fk-gl-frow{margin-top:12px}
  /* a field never outgrows the form: the Garment name box is 260px wide and a phone's form is narrower */
  .fk-modal .fk-gl-frow>div{min-width:0;max-width:100%}
  .fk-modal .fk-gl-frow .fk-gb-lbl i{font-style:normal;font-weight:500;color:var(--faint)}
  .fk-modal .fk-gl-form input{margin:0;height:34px;background:var(--panel);max-width:100%}
  /* the money boxes are drawn the way the mock draws them (Task 10): £, the box, and its hint BESIDE the box —
     not all three inside one bordered group, where the extra's two hints ran together as one phrase. */
  .fk-modal .fk-gl-form .fk-money-in{display:inline-flex;align-items:center;flex-wrap:wrap;gap:5px 3px;height:auto;line-height:normal;padding:0;border:0;background:none}
  .fk-modal .fk-gl-form input.fk-gl-money{width:84px;text-align:right;padding:0 9px;border:1px solid var(--line);border-radius:8px}
  .fk-modal .fk-gl-form input.fk-gl-money:focus{border-color:var(--accent)}
  .fk-modal .fk-gl-form input.fk-gl-masked{letter-spacing:2px;color:var(--dim)}
  .fk-modal .fk-gl-hidden{font-size:10.5px;color:var(--faint);margin-left:8px;white-space:nowrap}
  /* with Show costs off a MASKED extra box carries two hints — "hidden · Show costs to see it", then "2XL is charged
     as standard" — and side by side they read as one run-on phrase. The second takes a line of its own — but only
     while the first is showing (F7, fix wave 2026-09-25): beside an empty box the "hidden" hint is [hidden], and
     wrapping anyway is what stacked cost and extra on two rows where mock 6 draws them side by side. */
  .fk-modal .fk-gl-hidden:not([hidden])+.fk-gl-hidden{flex-basis:100%;margin-left:0}
  /* the retired-run sentence under "Extra for bigger sizes" is two sentences, not a hint: it wraps (review round 4
     — nowrap pushed its full stop onto the form's border at 1400px and cut it off on a phone). It sits on a row of
     its own and wraps at the form's width, now that the tool fits a phone (Task 10 — it was capped at 260px while
     the whole tool was a fixed 734px wide there). */
  .fk-modal .fk-gl-extranote{white-space:normal;margin:6px 0 0}
  /* "N hand-typed prices were removed" under the bar total: a price the person agreed has changed (round 5). It
     wraps inside the money column rather than widening it — at 1400px a one-line message squeezed every other
     figure on the bar onto two lines. */
  .fk-modal .fk-gl-stat .fk-gl-dropped{color:var(--warn);font-weight:600;max-width:230px}
  .fk-modal .fk-gl-form .fk-gl-seg button{padding:7px 14px;background:var(--panel)}
  .fk-modal .fk-gl-form .fk-gl-seg button.on{background:var(--accent)}

  /* step 3 — one row per colour, the sizes on the SAME row as the colour they belong to */
  .fk-modal .fk-gl-colours{margin-top:12px}
  .fk-modal .fk-gl-cb{display:grid;grid-template-columns:190px 1fr 92px 28px;gap:14px;align-items:center;border:1px solid var(--line);background:var(--panel2);border-radius:11px;padding:10px 12px}
  .fk-modal .fk-gl-cb+.fk-gl-cb{margin-top:8px}
  .fk-modal .fk-gl-cbcol{display:flex;align-items:center;gap:10px;border:0;background:none;padding:0;cursor:pointer;text-align:left;font-family:inherit}
  /* round 4: the supplier card has five near-black swatches — the theme's outlined-button colour gives every
     swatch a visible edge on this navy ground. Folded in here rather than a second rule for this selector. */
  .fk-modal .fk-gl-cbcol .sw{width:34px;height:34px;border-radius:50%;border:2px solid var(--line2);border-color:var(--fk-gl-edge,rgba(160,200,250,.40));flex:none}
  .fk-modal .fk-gl-cbcol b{display:block;color:var(--white);font-size:14px;font-weight:650}
  /* longhands: `font:600 11px/1.2 inherit` is invalid (inherit cannot sit inside the shorthand), so the browser
     dropped the whole declaration and "Change colour" drew at the button default, 13.33px — the mock's is 11px */
  .fk-modal .fk-gl-chg{border:0;background:none;padding:0;color:var(--accent);font-family:inherit;font-weight:600;font-size:11px;line-height:1.2;cursor:pointer;display:block}
  .fk-modal .fk-gl-sizes{display:grid;grid-template-columns:repeat(10,1fr);gap:7px}
  .fk-modal .fk-gl-sizes .fk-gb-size{background:var(--panel);padding:6px}
  .fk-modal .fk-gl-sizes .fk-gb-size.has{border-color:var(--accent-line)}
  .fk-modal .fk-gl-sizes .fk-gb-size.has b{color:var(--white)}
  .fk-modal .fk-gl-cbn{text-align:right;font-variant-numeric:tabular-nums}
  .fk-modal .fk-gl-cbn b{display:block;font-size:18px;color:var(--white);font-weight:700;line-height:1.1}
  .fk-modal .fk-gl-cbn small{font-size:11px;color:var(--dim)}
  .fk-modal .fk-gl-cbx{border:0;background:none;color:var(--dim);font-size:14px;cursor:pointer;opacity:.7;padding:0}
  /* a row with no colour yet: (a) colour, then (b) sizes — in that order, top to bottom */
  .fk-modal .fk-gl-cb.pick{display:block;padding:12px 14px 14px;border-color:var(--accent-line)}
  .fk-modal .fk-gl-cbstep{display:flex;align-items:center;gap:8px;font-size:12px;font-weight:650;color:var(--white);margin-bottom:8px}
  .fk-modal .fk-gl-cbstep b{width:20px;height:20px;border-radius:6px;display:grid;place-items:center;background:var(--accent-soft);color:var(--accent);font-size:11px}
  .fk-modal .fk-gl-cbstep span{font-weight:500;color:var(--faint);font-size:11px}
  .fk-modal .fk-gl-cbstep.wait{margin-top:14px;color:var(--dim)}
  .fk-modal .fk-gl-cbstep.wait b{background:var(--panel3);color:var(--dim)}
  .fk-modal .fk-gl-pal{display:grid;grid-template-columns:repeat(21,1fr);gap:4px}
  .fk-modal .fk-gl-sizes.wait{opacity:.45}
  .fk-modal .fk-gl-sizes.wait .fk-gb-size{background:transparent;border-style:dashed}
  .fk-modal .fk-gl-pal .fk-gb-col.used{opacity:.3;cursor:not-allowed}
  .fk-modal .fk-gl-addcol{margin-top:10px;border:1px dashed var(--line2);background:none;color:var(--accent);border-radius:10px;padding:9px 16px;font-weight:650;font-size:12.5px;cursor:pointer;font-family:inherit}
  .fk-modal .fk-gl-sizes .fk-gb-size .fk-input,.fk-modal .fk-gl-cbcol .fk-input{margin:0}

  /* the running total — the FOOT of the fixed modal (.fk-modal-gl, above). It is outside .fk-gl-scroll, so it
     never moves, and the scroller's own padding-bottom keeps the last control clear of it. It wraps rather than
     overflowing when the figures do not fit on one line. */
  .fk-modal .fk-gl-bar{flex:none;margin:0 -24px;padding:12px 24px 14px;background:var(--panel);border-top:1px solid var(--line2);box-shadow:0 -10px 24px var(--fk-gl-barsh,rgba(2,10,26,.45));display:flex;flex-wrap:wrap;align-items:center;gap:10px 26px}
  .fk-modal .fk-gl-stat .v{color:var(--white);font-size:22px;font-weight:700;font-variant-numeric:tabular-nums;line-height:1.15}
  .fk-modal .fk-gl-stat .v small{font-size:13px;font-weight:600;color:var(--text);margin-left:3px}
  .fk-modal .fk-gl-stat .l{color:var(--dim);font-size:11.5px;margin-top:2px;font-variant-numeric:tabular-nums}
  .fk-modal .fk-gl-stat.money .v{color:var(--accent)}
  .fk-modal .fk-gl-sep{width:1px;align-self:stretch;background:var(--line2)}
  .fk-modal .fk-gl-next{display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:10px;background:rgba(90,221,154,.08);border:1px solid rgba(90,221,154,.35);font-size:12.5px;color:var(--white);font-weight:600}
  .fk-modal .fk-gl-next i{font-style:normal;color:var(--ok);font-size:14px}
  .fk-modal .fk-gl-next small{display:block;font-size:11px;color:var(--dim);font-weight:500}
  .fk-modal .fk-gl-acts{margin-left:auto;display:flex;align-items:center;gap:10px}
  .fk-modal .fk-gl-addbtn{padding:10px 18px;font-size:13px}
  /* SHOW COSTS (garment lines Task 7), ported from mock.css's .gm-costsw, .gm-costs and .gm-tilecost — the
     switch is a real button, so its own rule resets it before the layout declarations that follow. */
  .fk-modal .fk-gl-costsw{background:none;border:0;padding:0;font:inherit;display:inline-flex;align-items:center;gap:7px;font-size:12px;color:var(--dim);cursor:pointer;user-select:none;margin:0}
  .fk-modal .fk-gl-costsw .tr{width:30px;height:17px;border-radius:999px;background:var(--panel3);border:1px solid var(--line2);position:relative;flex:none}
  .fk-modal .fk-gl-costsw .tr::after{content:'';position:absolute;top:2px;left:2px;width:11px;height:11px;border-radius:50%;background:var(--dim)}
  .fk-modal .fk-gl-costsw.on{color:var(--white)}
  .fk-modal .fk-gl-costsw.on .tr{background:var(--accent-soft);border-color:var(--accent-line)}
  .fk-modal .fk-gl-costsw.on .tr::after{left:15px;background:var(--accent)}
  /* behind Show costs only: the arithmetic, in the shop's own words */
  .fk-modal .fk-gl-costs{flex:none;margin:0 -24px;padding:9px 24px 10px;background:var(--panel2);border-top:1px dashed var(--line2);font-size:12px;color:var(--text);display:flex;flex-wrap:wrap;gap:6px 22px;font-variant-numeric:tabular-nums}
  .fk-modal .fk-gl-costs b{color:var(--white);font-weight:650}
  .fk-modal .fk-gl-costs span{color:var(--dim)}
  .fk-modal .fk-gl-tilecost{display:block;font-size:9.5px;color:var(--faint);margin-top:1px}

  /* round 4: the supplier card has five near-black swatches — the theme's outlined-button colour gives every
     swatch a visible edge on this navy ground (the palette's own swatches; .fk-gl-cbcol .sw's edge is set
     alongside the rest of that rule, above, rather than a second rule for it) */
  .fk-modal .fk-gl-pal .fk-gb-col span{border-color:var(--fk-gl-edge,rgba(160,200,250,.40))}
  /* THE TOOL ON A NARROWER SCREEN (Task 10). After every rule above on purpose: a media query adds no
     specificity, so the old @media(max-width:1000px) further up — written before .fk-gl-top existed — never
     reached the tool, and at phone width it stayed 734px wide inside a 302px modal with the Supplier code box
     cut off at the edge. Photographed at --phone (390px) and 1366×768. */
  @media(max-width:1000px){
    /* minmax(0,…), not 1fr: a 1fr track is never narrower than the widest thing in it, and the Product list
       ("Customer's own garment — print only") is wider than a phone, so the cards stood 20px past the edge */
    .fk-modal .fk-gl-top{grid-template-columns:minmax(0,1fr)}
    /* the colour row: colour, count and ✕ along the top, its size boxes the full width underneath */
    .fk-modal .fk-gl-cb{grid-template-columns:1fr auto 28px}
    .fk-modal .fk-gl-cb>.fk-gl-sizes{grid-column:1/-1;grid-row:2}
    /* as many swatches to a line as fit (all 21 while there is room), never narrower than a swatch */
    .fk-modal .fk-gl-pal{grid-template-columns:repeat(auto-fit,minmax(34px,1fr))}
  }
  @media(max-width:620px){
    .fk-modal .fk-gl-sizes{grid-template-columns:repeat(5,1fr)}
    /* the bar: the figures on top, then the next-price hint, then the buttons — Add as wide as the screen */
    .fk-modal .fk-gl-bar{gap:8px 16px}
    .fk-modal .fk-gl-stat .v{font-size:18px}
    .fk-modal .fk-gl-sep{display:none}
    .fk-modal .fk-gl-next{flex-basis:100%}
    .fk-modal .fk-gl-acts{margin-left:0;flex-basis:100%;flex-wrap:wrap}
    .fk-modal .fk-gl-addbtn{flex:1}
  }
  .fk-cpanel{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px}
  .fk-calc-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(155px,1fr));gap:10px;align-items:start}
  .fk-calc-fields .f{display:flex;flex-direction:column;gap:5px}
  .fk-calc-fields label{font-size:11px;color:var(--dim);font-weight:600}
  .fk-calc-fields .fk-input{width:100%;height:36px}  /* selects + number input identical height so labels/controls line up */
  .fk-calc-ref{overflow-x:auto}
  .fk-calc-out{display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:8px;margin-top:12px}
  .fk-calc-out .fk-tile{min-width:0;padding:10px 12px}
  .fk-calc-out .fk-tile .v{font-size:17px}
  .fk-calc-note{font-size:11px;color:var(--dim);margin-top:10px;line-height:1.5}
  .fk-vatrow{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--text);cursor:pointer}
  .fk-calc-fields .fk-vatrow{display:flex;align-items:center;height:36px;margin:0;color:var(--text)}  /* match input height + beat .fk-modal label{display:block} */
  .fk-cart-tot{margin-top:10px;border-top:1px solid var(--line);padding-top:8px;font-size:13px}
  .fk-cart-tot>div{display:flex;justify-content:space-between;padding:2px 0;color:var(--dim)}
  .fk-cart-tot>div b{color:var(--text)}
  .fk-cart-tot .g{border-top:1px solid var(--line);margin-top:4px;padding-top:6px;color:var(--white);font-size:14px}
  .fk-cart-tot .g b{color:var(--white)}
  /* THE DISCOUNT BOX (public/quotediscount.js, owner 2026-10-06): one quiet link while closed, one row of controls when open. Every control here
     carries margin:0 (also inline) — the global input{margin-bottom:16px} would otherwise lift each off the row's baseline (CLAUDE.md). The
     [hidden] rule is needed because .fk-cart-tot>div sets display:flex, which beats the attribute. */
  .fk-cart-tot .fk-qdisc-add{padding:3px 0}
  .fk-cart-tot .fk-qdisc-add button{background:none;border:0;padding:0;font:inherit;font-weight:600;color:var(--accent);cursor:pointer}
  .fk-cart-tot .fk-qdisc-add button:hover{text-decoration:underline}
  .fk-cart-tot>div.fk-qdisc{align-items:center;flex-wrap:wrap;gap:8px;padding:5px 0}
  .fk-qdisc .tg{display:inline-flex;border:1px solid var(--line);border-radius:7px;overflow:hidden}
  .fk-qdisc .tg button{background:transparent;border:0;border-radius:0;padding:6px 12px;min-width:34px;font:inherit;color:var(--dim);cursor:pointer}
  .fk-qdisc .tg button.on{background:var(--accent);color:var(--on-accent);font-weight:700}
  .fk-qdisc .v{width:86px;text-align:right;-moz-appearance:textfield}
  .fk-qdisc .v::-webkit-outer-spin-button,.fk-qdisc .v::-webkit-inner-spin-button{-webkit-appearance:none;margin:0} /* the spinner arrows sat on top of the right-aligned figure while it had focus */
  .fk-qdisc .why{flex:1 1 220px;min-width:150px}
  .fk-qdisc .rm{background:none;border:0;padding:0;font:inherit;color:var(--dim);text-decoration:underline;cursor:pointer}
  .fk-cart-tot>div.fk-qdisc b{margin-left:auto}
  .fk-cart-tot>div.fk-qdisc-err{color:var(--danger-ink,var(--danger));font-size:12px;padding:0 0 4px}
  .fk-cart-tot>div[hidden]{display:none}
  .fk-vatrow .fk-switch{flex:none;width:42px;height:23px;padding:0}  /* beat .fk-modal input{width:100%;padding} when the calc is in the modal */
  .fk-cart-qty{width:76px;text-align:center;display:inline-block}
  /* fixed-layout line-items table so columns never shift when the description text changes length */
  .fk-qd-table{table-layout:fixed}
  .fk-qd-table th:nth-child(1),.fk-qd-table td:nth-child(1){width:36px}
  .fk-qd-table th:nth-child(3),.fk-qd-table td:nth-child(3){width:96px}
  .fk-qd-table th:nth-child(4),.fk-qd-table td:nth-child(4){width:112px}
  .fk-qd-table th:nth-child(5),.fk-qd-table td:nth-child(5){width:92px}
  .fk-qd-table th:nth-child(6),.fk-qd-table td:nth-child(6){width:112px}
  /* 46px was right for a lone ✕. "✎ Edit" beside it needs 104 (measured: 54 + 29 + a 5px gap + 16 of
     padding), and this table is table-layout:fixed, so a column that is too narrow does not grow — it
     CLIPS, silently, and the button the owner asked to be made obvious was half off the edge of the table.
     The width comes out of the description, which is the only column here that can absorb it: everything
     else holds a fixed-size control or a money figure. */
  .fk-qd-table th:nth-child(7),.fk-qd-table td:nth-child(7){width:104px}
  .fk-qd-table td{padding-left:8px;padding-right:8px}                                    /* tighter gutters so each control fits its column */
  .fk-qd-table tbody td:nth-child(3) .fk-input,.fk-qd-table tbody td:nth-child(5) .fk-input{width:100%;height:34px} /* qty/VAT controls fill their column; money fields (unit/total) shrink to content so the £ stays tight to the number */
  .fk-qd-table tbody td{vertical-align:top;line-height:34px}                              /* controls row + value cells line up at the TOP (was middle → values sat lower than the controls); 34px line-height centres bare text (# and the static unit £) in the same box as the inputs */
  .fk-qd-table td.fk-line-desc{line-height:1.4}                                           /* description cell keeps normal spacing for its controls + the note that hangs below */
  .fk-qd-table .fk-line-txt,.fk-qd-table .fk-line-sel,.fk-qd-table .fk-line-cost{height:34px} /* description-cell controls match the 34px value controls */
  .fk-qd-table .r,.fk-cart-tot b{font-variant-numeric:tabular-nums} /* align stacked prices at the decimal */
  /* inline-editable line options (product/size/desc/unit) on the order page */
  .fk-line-desc{white-space:normal}
  .fk-line-sel{width:auto;max-width:100%;height:30px;padding:4px 22px 4px 8px;font-size:12px;margin:0 6px 4px 0}
  .fk-line-sel.sz{padding-right:20px}
  .fk-line-txt{width:100%;height:30px;padding:5px 8px;font-size:12.5px}
  /* money fields: the .fk-money-in WRAPPER is the bordered box; the input inside is transparent and hugs its content (field-sizing), so "£471.00" reads as ONE tight unit with the £ inside the box right before the number. Fallback without field-sizing: max-width keeps the box snug. */
  .fk-line-unit,.fk-line-cost,.fk-line-tot{field-sizing:content;width:auto;min-width:2.5ch;max-width:11ch;text-align:left;appearance:textfield;-moz-appearance:textfield}
  .fk-line-unit,.fk-line-cost{font-size:12.5px}
  .fk-line-tot{font-size:13px;font-weight:700}
  .fk-line-pre{font-size:11px;color:var(--dim);margin-right:2px}
  .fk-money-in{display:inline-block;white-space:nowrap;height:34px;line-height:34px;padding:0 9px;background:var(--panel2);border:1px solid var(--line);border-radius:8px;vertical-align:middle;box-sizing:border-box} /* the box: 34px tall like the other controls; £ + number sit inline, vertically centred */
  /* selecting a quote line cell shows just the text cursor — no accent ring/border (the suite-wide a11y focus ring stays on every other input) */
  .fk-money-in:focus-within{border-color:var(--line)}
  .fk-qd-table .fk-input:focus,.fk-qd-table .fk-input:focus-visible{outline:none;border-color:var(--line)}
  .fk-money-in>.fk-line-pre{margin:0 1px 0 0;font-size:12px;vertical-align:baseline}
  .fk-money-in .fk-input{border:none;background:transparent;border-radius:0;padding:0;height:34px;line-height:34px;vertical-align:baseline} /* naked input hugs its width (field-sizing); full box height + shared baseline keeps £ level with the digits */
  .fk-line-unit::-webkit-inner-spin-button,.fk-line-cost::-webkit-inner-spin-button,.fk-line-tot::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
  /* nowrap: a one-word label must never split — "print" rendered as "pri / nt" beside its box when the
     description column got tight (owner 2026-09-10) */
  .fk-line-chk{font-size:12px;color:var(--text);display:inline-flex;align-items:center;gap:4px;margin:0 8px 4px 0;cursor:pointer;vertical-align:middle;white-space:nowrap}
  .fk-line-chk input{margin:0}
  /* My Tasks — personal work list (jobs at a stage this user owns) */
  .fk-mt-row{display:flex;align-items:center;gap:12px;width:100%;text-align:left;background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:10px 14px;margin-top:6px;cursor:pointer;color:var(--text);font-family:inherit;font-size:13px}
  .fk-mt-row:hover{border-color:var(--accent)}
  .fk-mt-code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-weight:700;color:var(--white);flex:none;min-width:88px}
  .fk-mt-cust{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-mt-due{flex:none;margin-left:auto}
  /* keep every line's editors on ONE row, shrinking the selects/inputs to fit */
  .fk-line-ctrls{display:flex;align-items:center;gap:6px;min-width:0}
  .fk-line-ctrls > *{margin:0}
  .fk-line-ctrls .fk-line-sel,.fk-line-ctrls .fk-line-txt{min-width:0;max-width:none}
  .fk-line-ctrls .fk-line-chk,.fk-line-ctrls .fk-line-cost,.fk-line-ctrls .fk-line-unit,.fk-line-ctrls .fk-line-pre,.fk-line-ctrls .fk-money-in{flex:none}
  /* quote document (Quick Quote main page) */
  .fk-qd{display:grid;grid-template-columns:1fr 300px;gap:16px;align-items:start;max-width:1320px;margin:0 auto}
  @media(max-width:880px){.fk-qd{grid-template-columns:1fr}}
  .fk-qd .fk-section{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px;margin-bottom:16px}
  .fk-qd .fk-section h3{margin:0 0 12px;font-size:14px;color:var(--white)}
  .fk-qd-hd{display:flex;align-items:center;gap:8px;margin-bottom:12px}
  .fk-qd-nocust{background:rgba(245,185,20,.08);border:1px solid rgba(245,185,20,.3);border-radius:10px;padding:12px;text-align:center;color:var(--warn);font-weight:600;font-size:13px}
  .fk-qd-nocust .s{color:var(--dim);font-weight:400;font-size:11.5px;margin-top:5px;line-height:1.5}
  .fk-qd-cust .s{color:var(--dim);font-size:12px;margin-top:3px}
  .fk-wf{display:flex;flex-direction:column;gap:1px}
  /* fixed grid — dot | stage | assignee | action — so every row's columns sit dead straight */
  .fk-wf-step{display:grid;grid-template-columns:12px minmax(112px,150px) minmax(90px,1fr) max-content;align-items:center;gap:9px;padding:5px 8px;font-size:12.5px;color:var(--dim);border:1px solid transparent}
  .fk-wf-step .lbl{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-wf-owner{width:100%;min-width:0}
  .fk-wf-move{justify-self:end}
  .fk-wf-step .dot{width:11px;height:11px;border-radius:50%;border:2px solid var(--line);flex:none}
  .fk-wf-step.on{color:var(--white);font-weight:600}
  .fk-wf-step.on .dot{background:var(--accent);border-color:var(--accent)}
  .fk-wf-step.done{color:var(--ok)}
  .fk-wf-step.done .dot{background:var(--ok);border-color:var(--ok)}
  .fk-wf-step .lbl{flex:none}
  .fk-wf-jump{cursor:pointer;color:var(--text);border:1px solid var(--line);border-radius:8px;padding:5px 8px;margin:2px 0;transition:background .12s,border-color .12s,color .12s}
  .fk-wf-jump .dot{border-color:var(--dim)}
  .fk-wf-step .go{margin-left:auto;color:var(--accent);font-weight:700;font-size:11px;opacity:.6;transition:opacity .12s,transform .12s;white-space:nowrap}
  .fk-wf-jump:hover{background:rgba(0,184,217,.12);border-color:var(--accent);color:var(--accent)}
  .fk-wf-jump:hover .dot{border-color:var(--accent);background:rgba(0,184,217,.4)}
  .fk-wf-jump:hover .go{opacity:1;transform:translateX(3px)}
  .fk-wf-jump:active{background:rgba(0,184,217,.22)}
  /* job-drawer rail — every reachable stage is clickable (move there); the next step is the emphasised "Proceed" target */
  /* moves are explicit .fk-wf-move buttons now — the row itself is inert (stray-click safety) */
  .fk-wf-move{white-space:nowrap}
  .fk-wf-step.is-next{border:1px solid var(--accent);background:rgba(0,184,217,.12);color:var(--white);border-radius:8px;padding:6px 8px;margin:2px 0}
  .fk-wf-step.is-next .dot{border-color:var(--accent);background:rgba(0,184,217,.4)}
  #fk-undo{position:fixed;left:50%;bottom:64px;transform:translate(-50%,12px);display:flex;align-items:center;gap:12px;background:var(--panel2);border:1px solid var(--line2);border-radius:999px;padding:8px 10px 8px 16px;font-size:13px;color:var(--text);box-shadow:0 12px 34px rgba(0,0,0,.5);z-index:210;opacity:0;pointer-events:none;transition:opacity .18s,transform .18s}
  #fk-undo.show{opacity:1;transform:translate(-50%,0);pointer-events:auto}
  .fk-wf-locked{opacity:.42}
  .fk-wf-here{margin-left:auto;font-size:9.5px;font-weight:700;color:var(--accent);text-transform:uppercase;letter-spacing:.06em;opacity:.85}
  .fk-wf-gate{margin-left:auto;font-size:10px;font-weight:700;color:var(--warn);letter-spacing:.03em}
  .fk-wf-hint{font-size:11px;color:var(--warn);margin:8px 0 0;line-height:1.45}
  .fk-wf-bal{margin-top:10px;font-size:13px;font-weight:700;font-variant-numeric:tabular-nums;display:flex;align-items:center;gap:10px}
  .fk-wf-bal .fk-btn{margin-left:auto}
  .fk-wf-bal.owed{color:var(--danger)} .fk-wf-bal.paid{color:var(--ok)}
  /* per-stage owner, inline on the workflow row (the picker; click is isolated from the row's move) */
  .fk-wf-owner{flex:1;min-width:0;max-width:168px;height:25px;font-size:11px;padding:2px 18px 2px 7px;margin-left:8px;color:var(--text)}
  .fk-wf-ownerro{display:inline-flex;align-items:center;gap:6px;flex:none;margin-left:8px;font-size:11px;color:var(--dim);white-space:nowrap}
  .fk-wf-ownerro .fk-avatar{width:20px;height:20px;font-size:9px;flex:none}
  .fk-gate-warn{background:rgba(245,185,20,.13);color:var(--warn);border:1px solid rgba(245,185,20,.3);border-radius:8px;padding:7px 11px;font-size:12px;font-weight:600;margin-bottom:10px}
  .fk-qd-vat{width:74px}
  .fk-lbl{display:block;font-size:11px;color:var(--dim);font-weight:600;margin-bottom:5px}
  /* pick-one rows in the "customer approved off the link" box. The selected state is an accent BORDER and a
     tint, never accent behind text — the FK themes swap the accent and one of them fails contrast that way.
     Wraps, because three channel buttons do not fit a narrow drawer on one line. */
  .fk-pickrow{flex-wrap:wrap;gap:8px;margin-bottom:12px}
  .fk-pick{flex:0 1 auto}
  /* The chosen one wears a RING, on box-shadow — a property no theme touches. Border and background are not
     enough: Moon Blue flattens every plain modal button (border rgba(160,200,250,.4), background transparent)
     with a selector that outranks this one, and measured under it on 2026-09-10 the chosen button and its
     neighbours were byte-for-byte the same colour ("all buttons look same when you select one"). */
  .fk-pick.on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 14%,transparent);color:var(--white);font-weight:600;box-shadow:0 0 0 2px var(--accent)}
  .soon-card{opacity:.5}
  /* 900 -> 1600 (owner 2026-09-16: "the add product page - screen is small - can be double the size"). It is a
     catalogue of 145 products read side by side with the basket behind it, and at 900px it sat in the middle of
     a 1900px screen using half of it. min() rather than a flat 1600 so a laptop still gets a modal with a margin
     round it rather than one clipped at the edges. */
  .fk-modal.fk-modal-wide{max-width:min(1600px,94vw)}  /* two-class selector beats .fk-modal's 440px regardless of source order */
  /* COLLECTION OR DELIVERY, asked at every door (owner 2026-09-29, mocks 4 + 5). 560px so the hint and the three
     buttons sit on one line; the bulk box is a row per job — who, and where a delivery goes — beside its two buttons. */
  .fk-modal.fk-modal-ready{max-width:560px}
  .fk-modal.fk-modal-readyall{max-width:640px}
  .fk-rdy-row{display:grid;grid-template-columns:1fr auto;gap:12px;align-items:center;padding:11px 0;border-top:1px solid var(--line)}
  .fk-rdy-cust{color:var(--cust-ink,#7CC4FF);font-weight:600}   /* the customer's colour the stage lists lead with (.fk-custcell b) */
  .fk-rdy-note{color:var(--dim);font-size:12.5px;margin-top:3px}
  /* a phone: the buttons under the name, not squeezing it; and the foot wraps — "Confirm → 2 to Collection, 1 to
     Delivery" pushed Cancel off the box's left edge at 390px (photographed 2026-09-29) */
  @media (max-width:520px){.fk-rdy-row{grid-template-columns:1fr}.fk-modal.fk-modal-ready .actions,.fk-modal.fk-modal-readyall .actions{flex-wrap:wrap}}
  /* sales income panel (collected, by month) */
  .fk-income{display:flex;align-items:center;gap:16px;background:var(--panel);border:1px solid rgba(0,184,217,.35);border-radius:12px;padding:13px 18px;margin-bottom:14px}
  .fk-inc-left{display:flex;flex-direction:column;gap:2px}
  .fk-inc-l{color:var(--dim);font-size:10.5px;text-transform:uppercase;letter-spacing:.06em}
  .fk-inc-v{color:var(--accent);font-size:27px;font-weight:800;font-variant-numeric:tabular-nums;line-height:1.05}
  .fk-inc-sub{color:var(--dim);font-size:11px}
  .fk-inc-nav{display:flex;align-items:center;gap:8px}
  .fk-inc-month{color:var(--white);font-weight:600;min-width:118px;text-align:center}
  .fk-btn:disabled{opacity:var(--btn-disabled-op);cursor:default}
  .fk-allclear{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:20px;color:var(--dim);text-align:center;font-size:13px}
  .fk-focus-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));gap:12px}
  .fk-focus{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:13px 14px}
  .fk-focus h4{color:var(--white);font-size:13px;margin:0 0 10px;display:flex;align-items:center;gap:7px}
  .fk-focus h4 .n{background:var(--panel2);color:var(--dim);border-radius:20px;padding:1px 8px;font-size:10.5px;font-weight:700}
  /* The rows past the sixth. The card names its true total, so the rest have to be reachable FROM it — they
     were rendered nowhere at all, and 97 of 103 overdue jobs could not be got at from the card counting
     them. Hidden by default so the resting height is unchanged. */
  .fk-focus:not(.showall) .fk-frow-more{display:none}
  .fk-focus-more{display:block;width:100%;margin-top:6px;padding:7px 10px;font:inherit;font-size:12px;
    font-weight:600;color:var(--accent);background:none;border:1px dashed var(--line2);border-radius:8px;cursor:pointer}
  .fk-focus-more:hover{background:var(--panel2);border-style:solid}
  .fk-focus-more:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
  /* One button, two labels, swapped with display so a screen reader reads exactly one of them. The first
     version hid the spare with font-size:0 — invisible, but still announced, so the button read
     "Show all 11 Show fewer". */
  .fk-focus-more .less{display:none}
  .fk-focus.showall .fk-focus-more .more{display:none}
  .fk-focus.showall .fk-focus-more .less{display:inline}
  .fk-focus.showall .fk-focus-more{color:var(--dim);font-size:11.5px}
  .fk-frow{display:flex;align-items:center;gap:8px;padding:8px 9px;border-radius:8px;cursor:pointer;border:1px solid transparent}
  .fk-fnum{flex:none;width:22px;height:22px;display:grid;place-items:center;background:var(--panel2);border:1px solid var(--line);border-radius:6px;font-size:11px;font-weight:700;color:var(--dim);font-variant-numeric:tabular-nums} /* running file number */
  .fk-file-queue{display:flex;flex-direction:column;gap:4px}
  .fk-file-queue:not(:empty){margin-bottom:8px}
  .fk-fq-item{display:flex;align-items:center;gap:8px;padding:5px 9px;background:var(--panel2);border:1px solid var(--line);border-radius:8px;font-size:12.5px;position:relative;overflow:hidden} /* relative+hidden: the upload bar is drawn across the foot of this row */
  .fk-fq-item .n{flex:none;width:20px;height:20px;display:grid;place-items:center;background:var(--panel);border-radius:6px;font-size:11px;font-weight:700;color:var(--dim);font-variant-numeric:tabular-nums}
  .fk-fq-item .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text)}
  .fk-fq-item .sz{flex:none;color:var(--dim);font-size:11px}
  .fk-fq-x{flex:none;background:none;border:none;color:var(--dim);cursor:pointer;font-size:13px;padding:2px 5px;border-radius:5px;line-height:1}
  .fk-fq-x:hover{color:var(--danger);background:rgba(255,107,107,.12)}
  /* UPLOAD PROGRESS ON THE ROW ITSELF (owner 2026-09-09). The bar is a hairline across the FOOT of the row
     rather than a block beside the name — it has to be readable at a glance on a queue of eight files
     without any of them growing taller and pushing the rest down mid-upload. The row is position:relative
     for it; the percentage sits where the eye already is, next to the size. */
  .fk-fq-pc{flex:none;color:var(--accent-ink,var(--accent));font-size:11px;font-weight:700;font-variant-numeric:tabular-nums;min-width:30px;text-align:right}
  .fk-fq-bar{position:absolute;left:0;right:0;bottom:0;height:2px;background:transparent}
  .fk-fq-bar i{display:block;height:100%;width:0;background:var(--accent);transition:width .15s linear}
  /* once it is going, the ✕ stops offering to take a file back that is already half sent */
  .fk-fq-item.up .fk-fq-x{visibility:hidden}
  .fk-fq-add{align-self:flex-start;margin-top:2px}
  .fk-frow:hover{background:var(--panel2);border-color:var(--line)}
  .fk-frow .m{flex:1;min-width:0;font-size:12.5px;color:var(--text)}
  .fk-frow .m b{color:var(--white)}
  .fk-frow .m .s{color:var(--dim);font-size:11px;margin-top:1px}
  /* what a reprint cost — a figure someone typed, and the invitation to type it when nobody has */
  .fk-lnk{flex:none;background:var(--panel2);border:1px solid var(--line);color:var(--text);font-size:11.5px;
    font-weight:700;padding:3px 10px;border-radius:20px;cursor:pointer;font-variant-numeric:tabular-nums}
  .fk-lnk:hover{border-color:var(--accent);color:var(--white)}
  .fk-lnk.dim{background:none;color:var(--dim);font-weight:600;border-style:dashed}
  .fk-chip.sm{background:var(--panel2);color:var(--dim);border:1px solid var(--line);font-weight:600;margin-left:4px}

  /* calendar */
  .fk-dash-cal{margin:22px auto 0;padding-top:18px;border-top:1px solid var(--line);max-width:1230px}
  .fk-cal-bar{display:flex;align-items:center;gap:8px;margin-bottom:12px}
  .fk-cal-bar h3{margin:0;font-size:15px;color:var(--white)}
  .fk-cal-month{min-width:150px;text-align:center;color:var(--white);font-weight:600}
  .fk-cal-legend{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:12px;align-items:center}
  .fk-cal-leg{display:inline-flex;align-items:center;gap:6px;background:var(--panel2);border:1px solid var(--line);color:var(--dim);border-radius:20px;padding:4px 10px;font-size:11.5px;cursor:pointer;font-family:inherit}
  .fk-cal-leg.on{border-color:var(--accent);color:var(--white)}
  .fk-cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:1px;background:var(--line);border:1px solid var(--line);border-radius:10px;overflow:hidden}
  .fk-cal-dow{background:var(--panel);padding:8px;text-align:center;font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--dim)}
  .fk-cal-cell{background:var(--panel);min-height:94px;padding:5px 6px 7px;display:flex;flex-direction:column;gap:3px}
  .fk-cal-cell.other{background:#171a24}
  .fk-cal-cell.other .fk-cal-daynum{opacity:.45}
  .fk-cal-cell.weekend{background:#191c27}
  .fk-cal-cell.today{box-shadow:inset 0 0 0 2px var(--accent)}
  .fk-cal-daynum{font-size:12px;font-weight:600;color:var(--dim)}
  .fk-cal-cell.today .fk-cal-daynum{color:var(--accent)}
  .fk-cal-events{display:flex;flex-direction:column;gap:2px;overflow:hidden}
  .fk-cal-pill{font-size:10.5px;padding:2px 6px;border-radius:4px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;background:var(--panel2);color:var(--text);border-left:3px solid var(--pc,#888)}
  .fk-cal-pill:hover{filter:brightness(1.25)}
  .fk-cal-pill.overdue{background:rgba(255,107,107,.16);border-left-color:var(--danger);color:#ffb3b3}
  .fk-cal-more{font-size:10px;color:var(--dim);padding:1px 4px}

  /* cash pot */
  .fk-cash-hero{background:linear-gradient(135deg,rgba(12,166,120,.12),var(--panel));border:1px solid rgba(12,166,120,.3);border-radius:12px;padding:18px 20px;margin-bottom:16px;display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:12px}
  .fk-cash-hero .lbl{color:var(--dim);font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;margin-bottom:4px}
  .fk-cash-hero .bal{font-size:30px;font-weight:800;color:var(--ok);font-variant-numeric:tabular-nums;line-height:1.1}
  .fk-cash-hero .bal.neg{color:var(--danger)}
  .fk-cash-hero .io{text-align:right;font-size:13px;font-variant-numeric:tabular-nums}
  .fk-cash-hero .io .in{color:var(--ok);font-weight:700} .fk-cash-hero .io .out{color:var(--danger);font-weight:700}
  .fk-cash-acc{background:var(--panel);border:1px solid var(--line);border-radius:10px;margin-bottom:8px;overflow:hidden}
  .fk-cash-acc-head{display:flex;align-items:center;gap:10px;padding:11px 14px;cursor:pointer;background:none;border:0;width:100%;font-family:inherit;text-align:left}
  .fk-cash-acc-head:hover{background:var(--panel2)}
  .fk-cash-acc-head .lbl{flex:1;color:var(--white);font-weight:600;font-size:13px}
  .fk-cash-acc-head .tot{font-variant-numeric:tabular-nums;font-weight:700}
  .fk-cash-acc .fk-table{border:none;border-radius:0}
  .fk-amt-in{color:var(--ok-ink,var(--ok));font-variant-numeric:tabular-nums;font-weight:700}  /* money IN is text, not a fill — 3.12:1 as --ok on every light theme (audit 2026-08-09) */
  .fk-amt-out{color:var(--danger);font-variant-numeric:tabular-nums;font-weight:700}

  /* z-index 58, was 48 (owner G11 #3: "Empty trash bin icon is not working"). It was not the icon and not
     the route — the confirm opened correctly every time, at 48, UNDERNEATH the Admin Settings window at 55.
     Trash lives inside Admin Settings, so its confirm was always born buried: elementFromPoint on the OK
     button returned the settings table behind it, which is a dead button by any definition. A modal has to
     outrank whatever opened it. 58 clears Settings and Help (both 55) and stays under the command palette
     (60) and the config/product-builder backdrops (62). Delete-forever in the same panel was equally stuck. */
  .fk-modal-backdrop{position:fixed;inset:0;background:rgba(8,10,16,.6);display:none;align-items:center;justify-content:center;z-index:58;padding:20px}
  .fk-modal-backdrop.open{display:flex}
  .fk-modal{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:24px;width:100%;max-width:440px;max-height:90vh;overflow-y:auto}
  .fk-modal h3{color:var(--white);font-size:16px;margin:0 0 16px}
  .fk-modal label{display:block;font-size:12px;color:var(--dim);margin:0 0 6px}
  .fk-modal .f{margin-bottom:13px}
  .fk-modal .f2{display:grid;grid-template-columns:1fr 1fr;gap:10px}
  .fk-modal input,.fk-modal select,.fk-modal textarea{width:100%;background:var(--panel2);border:1px solid var(--line);border-radius:8px;color:var(--white);padding:9px 11px;font-size:13px;font-family:inherit}
  /* FOOTGUN GUARD: the rule above forces width:100% on EVERY bare input in a modal (specificity 0,1,1). A
     compact inline input (qty/price box in a flex row) WILL stretch to full width and crush its siblings — the
     "qty box shoved to the edge" bug. Fix: give it a selector that out-specifies the above, e.g. a parent-scoped
     `.fk-row-class .my-qty{width:64px;flex:none}` (0,2,0). See `.fk-stock-item .fk-stock-qty` below for the pattern. */
  .fk-modal textarea{resize:vertical;line-height:1.5;min-height:48px;max-width:100%;overflow-wrap:anywhere;field-sizing:content;max-height:min(calc(1.5em * var(--ta-lines)), var(--ta-vh));overflow-y:auto}
  /* seven boxes share this rule at four different sizes, and the CSV-paste box is the one that matters:
     rows=6 opened at 137px and would have collapsed to 58px — three lines to paste a hundred rows into. */
  .fk-modal textarea[rows="2"]{min-height:calc(1.5em * 2 + 20px)}
  .fk-modal textarea[rows="3"]{min-height:calc(1.5em * 3 + 20px)}
  .fk-modal textarea[rows="6"]{min-height:calc(1.5em * 6 + 20px)}
  .fk-modal input:focus,.fk-modal select:focus,.fk-modal textarea:focus{outline:none;border-color:var(--accent)}
  /* CUSTOMER PICKER (owner 2026-08-23: "if we have 200+ will be hard to select"). A search box over a
     scrolling, sectioned list — in NORMAL FLOW, because .fk-modal is overflow-y:auto and would clip a
     floating panel. Every class is scoped under .fk-cp: `.hit` in particular is a name this file already
     uses for something else (.fk-chk.hit), and a bare common class is how the board broke on live. */
  .fk-cp{display:flex;flex-direction:column;gap:8px}
  .fk-cp-bar{display:flex;gap:8px;align-items:center}
  /* the global input{margin-bottom:16px} in this file inflates any input used as a flex cell and lifts its
     text off the row's baseline — zeroed here, as .wc-root .search input and the routine's cells already do */
  .fk-cp-bar .fk-cp-q{flex:1;min-width:0;margin-bottom:0}
  .fk-cp-bar .fk-cp-new{flex:none;background:var(--panel3);border:1px solid var(--line2);color:var(--text);
    border-radius:8px;padding:9px 12px;font-size:12.5px;font-weight:600;cursor:pointer;white-space:nowrap;font-family:inherit}
  .fk-cp-bar .fk-cp-new:hover{border-color:var(--accent);color:var(--white)}
  .fk-cp-list{max-height:236px;overflow-y:auto;border:1px solid var(--line);border-radius:9px;background:var(--panel2);padding:5px}
  .fk-cp-sec{font-size:10.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--faint);padding:8px 9px 5px}
  .fk-cp-sec:first-child{padding-top:4px}
  .fk-cp-row{display:flex;align-items:center;width:100%;text-align:left;background:none;border:0;border-radius:7px;
    color:var(--text);font:inherit;font-size:13px;padding:8px 9px;cursor:pointer}
  .fk-cp-row:hover{background:var(--panel3);color:var(--white)}
  .fk-cp-row.on{background:var(--accent-soft);color:var(--white)}      /* the ↑↓ cursor */
  .fk-cp-row.sel{background:var(--accent-soft);color:var(--white);font-weight:700}
  /* flex:1 so the ✎ that follows it is pushed to the row's right edge; min-width:0 is what lets the
     ellipsis above actually fire inside a flex item */
  .fk-cp-row .pn{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .fk-cp-row .hit{background:var(--accent-soft);border-radius:2px;font-weight:800;color:var(--white)}
  .fk-cp-none{padding:12px 10px;font-size:12.5px;color:var(--dim);line-height:1.5}
  .fk-cp-chosen{font-size:12.5px;font-weight:600;color:var(--ok,#1f9d55)}
  /* the way back once ＋ Add new or ✎ Edit has replaced the list — see showPane() in fk.js */
  .fk-cp-back{align-self:flex-start;background:var(--panel2);border:1px solid var(--line2);color:var(--text);
    border-radius:7px;padding:8px 11px;font-size:12px;font-weight:600;cursor:pointer;font-family:inherit}
  .fk-cp-back:hover{border-color:var(--accent);color:var(--white)}
  /* ✎ ON A ROW (owner 2026-09-06). ALWAYS VISIBLE, only dim: a control that appears on hover cannot be found
     by anyone who does not already know it is there, and never appears at all on a touch screen. It brightens
     with the row and again on itself, so it reads as a target before it is pressed rather than after. */
  .fk-cp-ed{flex:none;margin-left:8px;display:inline-flex;align-items:center;gap:4px;height:24px;padding:0 8px;
    border-radius:6px;font-size:11px;font-weight:600;line-height:1;color:var(--dim);border:1px solid var(--line2);
    background:var(--panel2);white-space:nowrap}
  .fk-cp-row:hover .fk-cp-ed{color:var(--text)}
  .fk-cp-ed:hover{background:var(--panel);border-color:var(--accent);color:var(--white)}
  .fk-cp-ed:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
  /* the customer's details, drawn OVER the list rather than in a second modal — there is one modal slot in
     this tab and it is usually holding a half-typed quote or job. See openEdit() in fk.js. */
  .fk-cp-edit{border:1px solid var(--line);border-radius:9px;background:var(--panel2);padding:12px 13px}
  .fk-cp-edh{font-size:12.5px;font-weight:700;color:var(--white);margin-bottom:10px}
  /* "Billing address" is a heading over four fields, not a label for the postcode box under it (owner
     2026-08-25: a postcode was sitting in what read as the address field). Used by every addrFieldsHtml. */
  .fk-addr-h{font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--white);
    margin:16px 0 9px;padding-top:14px;border-top:1px solid var(--line)}
  /* --dim, not --faint: the hint used to inherit the <label>'s colour, and --faint is 2.4:1 on a light
     theme's white panel. A new use of a token is a new contrast decision, not an inherited one. */
  .fk-addr-h span{font-size:11px;font-weight:400;letter-spacing:0;text-transform:none;color:var(--dim);margin-left:7px}
  /* suppliers */
  .fk-sup-tools{display:flex;align-items:center;gap:8px;flex-wrap:nowrap}  /* single clean row — search + Add never stack (owner 2026-07-18) */
  .fk-sup-search{min-width:0;width:230px;flex:0 1 230px}
  .fk-sup-tools .fk-btn{flex:none;white-space:nowrap}
  .fk-sup-overview{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;margin-bottom:18px}
  .fk-sup-stat{background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);border-radius:12px;padding:12px 14px}
  .fk-sup-stat span{display:block;color:var(--dim);font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;margin-bottom:5px}
  .fk-sup-stat strong{color:var(--white);font-size:24px;line-height:1;font-variant-numeric:tabular-nums}
  .fk-sup-cat{margin-bottom:18px}
  .fk-sup-cat header{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 10px}
  .fk-sup-cat h3{color:var(--white);font-size:14px;margin:0;display:flex;align-items:center;gap:8px}
  .fk-sup-cat header span{background:var(--panel2);color:var(--dim);border-radius:20px;padding:1px 9px;font-size:11px;font-weight:700}
  .fk-sup-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px}
  .fk-sup-card{background:linear-gradient(180deg,var(--panel),#20273a);border:1px solid var(--line);border-radius:12px;padding:14px 15px;box-shadow:inset 0 1px 0 rgba(255,255,255,.03)}
  .fk-sup-card:hover{border-color:rgba(0,184,217,.45);transform:translateY(-1px);transition:transform .12s,border-color .12s}
  .fk-sup-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;margin-bottom:10px}
  .fk-sup-head>div:first-child{min-width:0}
  .fk-sup-head b{display:block;color:var(--white);font-size:14px;word-break:break-word;margin-top:6px}
  .fk-sup-pill{display:inline-flex;align-items:center;gap:6px;background:rgba(0,184,217,.12);color:var(--accent);border:1px solid rgba(0,184,217,.2);border-radius:999px;padding:2px 8px;font-size:10.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase}
  .fk-sup-actions{display:flex;gap:4px;flex-shrink:0}
  .fk-sup-body{display:flex;flex-direction:column;gap:4px}
  .fk-sup-row{font-size:12.5px;color:var(--text);display:flex;align-items:center;gap:6px;flex-wrap:wrap}
  .fk-sup-icon{width:18px;text-align:center;color:var(--dim);flex:none}
  .fk-sup-meta{color:var(--dim);font-size:11.5px}
  .fk-sup-row code{background:var(--panel2);border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-size:11.5px;color:var(--white)}
  .fk-sup-notes{font-size:12px;color:var(--dim);margin-top:10px;white-space:pre-line;background:var(--panel2);border-radius:9px;padding:9px 10px;border:1px solid var(--line)}
  .fk-sup-how{font-size:12px;margin-top:9px;background:rgba(0,184,217,.08);border:1px solid rgba(0,184,217,.18);border-radius:9px;padding:9px 10px}
  .fk-sup-how b{color:var(--accent);font-size:10px;text-transform:uppercase;letter-spacing:.05em;display:block;margin-bottom:4px}
  .fk-sup-how div{white-space:pre-line;color:var(--text)}
  /* inventory */
  .fk-inv-alert{background:rgba(245,185,20,.12);border:1px solid rgba(245,185,20,.4);color:var(--warn);border-radius:10px;padding:10px 14px;margin-bottom:14px;font-size:13px}
  /* inventory categories — collapsible sections (accordion), all on one page */
  .fk-cat-sec{border:1px solid var(--line);border-radius:12px;margin-bottom:12px;background:var(--panel)}
  .fk-cat-head{display:flex;align-items:center;gap:9px;padding:12px 14px;cursor:pointer;user-select:none;border-radius:12px}
  .fk-cat-head:hover{background:var(--panel2)}
  .fk-cat-chev{color:var(--dim);font-size:11px;transition:transform .15s;display:inline-block;width:12px}
  .fk-cat-sec.closed .fk-cat-chev{transform:rotate(-90deg)}
  .fk-cat-title{color:var(--white);font-weight:600;font-size:14px}
  .fk-cat-count{background:var(--panel2);color:var(--dim);border-radius:20px;padding:1px 9px;font-size:11.5px;font-weight:700;font-variant-numeric:tabular-nums}
  .fk-cat-body{padding:0 14px 14px}
  .fk-cat-sec.closed .fk-cat-body{display:none}
  .fk-iconbtn{background:none;border:1px solid var(--line);color:var(--dim);border-radius:7px;padding:3px 9px;cursor:pointer;font-family:inherit;font-size:12px}
  .fk-iconbtn:hover{background:var(--panel);color:var(--text)}
  .fk-iconbtn.danger:hover{color:var(--danger);border-color:var(--danger)}
  .fk-inv-emptycat{color:var(--dim);text-align:center;padding:22px 12px;font-size:13px}
  /* merged Inventory / Suppliers sub-tabs + drag-to-recategorise */
  .fk-subtabs{display:flex;gap:4px;margin-bottom:16px;border-bottom:1px solid var(--line)}
  .fk-subtab{background:none;border:none;border-bottom:2px solid transparent;color:var(--dim);padding:9px 15px;font-size:14px;font-weight:600;cursor:pointer;font-family:inherit;margin-bottom:-1px}
  .fk-subtab:hover{color:var(--text)}
  .fk-subtab.on{color:var(--white);border-bottom-color:var(--accent)}
  /* ============================================================================
     FK per-user THEMES. Three picks, all dark-chrome (Moon Blue · Onyx · Marine). Marine keeps a LIGHT
     work area (board/cards/tables/drawer/modals); Moon Blue and Onyx repaint that too — Onyx joined Blackout
     there when it took the Mission Rail palette verbatim (2026-08-07), so any rule reasoning about "the light
     themes" now means Marine, and the dark ones need their own value;
     the nav + toolbar band are skinned per theme. Scoped to the FK containers (#fk-shell + the static
     drawer/modal backdrops) so the shared dark topbar and every other tab are
     untouched. `data-fk-theme` is set on <body> by fk.js; the default dark FK
     look stays whenever the attribute is absent. ============================ */
  /* shared: the work area goes light in every FK theme.
     `color` as well as the tokens — and that is not tidiness. These blocks only ever REDEFINED the token
     values; they never told the shell to USE one. So any text with no colour rule of its own inherited from
     <body>, which is the dark suite's #cbd0dc, and landed at 1.36:1 on a light board. It is a whole class:
     "1 of 1" on Customer Database and "2 of 2" on Prospects were found by audit, and every future unstyled
     span had the same fate waiting. One declaration closes it for all five themes. (audit 2026-08-09) */
  /* #fk-colmenu joined this list on 2026-09-06 and had been missing since the menu was written. It is the
     THIRD thing FK renders outside #fk-shell — it has to be, because a menu inside a table is clipped by the
     overflow:hidden that rounds the table's corners — and being outside the shell means being outside the
     theme. The ⋯ came up as a dark panel on a white page, which is not merely inconsistent: the dark panel's
     tokens assume light text on it. Photographed on Light Box; every theme block below gets it too. */
  body[data-fk-theme] #fk-shell,
  body[data-fk-theme] #fk-drawer-backdrop,
  body[data-fk-theme] #fk-modal-backdrop,body[data-fk-theme] #fk-colmenu{
    color:var(--text);
    --bg:#eef1f5;--panel:#ffffff;--panel2:#f2f6fb;--panel3:#eaf0f7;--line:#e6ecf4;--line2:#d6dfea;
    --text:#3d4a59;--dim:#5c6879;--white:#1c2733;--faint:#9aa5b3;--tab-accent:var(--accent);
    /* the accent at 55%, for an edge that says "this one" (the garment tool's filled size boxes, its Show-costs
       switch). Only Moon Blue named one, below, so on every other theme var(--accent-line) was undefined and
       the border fell back to currentColor: a white rim on Onyx, the default (garment lines Task 10). Derived
       from each theme's own --accent, so a new theme cannot miss it; Moon Blue's own value still wins. */
    --accent-line:color-mix(in srgb,var(--accent) 55%,transparent);
    --warn:#a15c00; /* the default --warn is a bright yellow tuned for dark panels — unreadable as text on a
      light one. Every FK theme has a light work area, so this single override fixes every yellow-on-white
      spot suite-wide (money card, revision timeline, gate hints, chips) without touching the dark default. */
    /* --ok and --danger have the SAME problem and were missed, which is why the proof-state strip measured
       2.30:1 and the Today strip's overdue count 2.42:1 on the light themes. They cannot be re-pointed the
       way --warn was, because unlike --warn they are also solid FILLS (14 sites for --ok — done ticks, the
       green button, timeline bars) and two of those pair the fill with a DARK ink, which darkening would
       invert. So they follow --accent-ink instead: a separate token for the colour-as-TEXT job only, read
       as var(--ok-ink,var(--ok)) so the dark default still applies wherever it is not set. */
    --ok-ink:#0a6045;--danger-ink:#b42318;--warn-ink:#7d4700;
    /* THE CUSTOMER'S NAME (owner 2026-09-29: "not yellow or red"). It was --warn: the same amber as "Due today",
       "at risk" and every warning box on the same card. Sky blue means nothing else in Future Knights. Deep here,
       on a light work area (Marine: 4.6:1 on its card); the dark themes set the light shade in their own blocks. */
    --cust-ink:#1F6FB2;
    --fk-sunk:rgba(28,39,51,.04);   /* a sunk strip (.fk-orderhalf) on a light drawer — the dark themes keep 18% black */
    /* Two more colours the mock specifies as literals, each of which is a FILL in some places (with its own
       dark ink, which is fine anywhere) and TEXT in others (which is not). Same split, same treatment:
         --stage-cur  the card's "where the job is now" orange (#F0875C on the mock's dark card) — 2.20:1 here
         --here-ink   the timeline's "pay attention here" yellow (#f6c445) — 1.44:1 on Marine, 1.52:1 here */
    --stage-cur:#9a4a12;--here-ink:#7a5600;--ring-todo:#3A4560;
    /* the card's hover shadow. Pure black at half opacity lifts a card off Onyx; on a white column the same
       value is a bruise, so these themes mix their own from the panel's own blue-grey. */
    --fk-cardsh:rgba(20,30,50,.20);
    /* the garment tool's total bar lifts off the body with a SOFT shadow here, and a white swatch keeps an edge on a
       pale row (fix wave 2026-09-25): the dark defaults painted a heavy grey band and all but lost the White swatch */
    --fk-gl-barsh:rgba(20,30,50,.10);--fk-gl-edge:rgba(28,39,51,.30)}
  /* The board chips had the SAME problem --warn was fixed for, and were missed: their text colours are the
     dark-panel palette sitting on a light card. Measured on the running board, 2026-08-05:
     "Outsourced" 1.59:1 and "✓ Paid" 2.46:1 — the two chips the press and the counter read most often.
     Scoped to the FK shell, so the dark suite default is untouched. */
  /* THESE DEEP INKS ARE FOR A WHITE CARD, so they name the themes that have one. They used to match
     body[data-fk-theme] — every theme — and each dark theme then had to buy its own way out by name below.
     Moon Blue arrived after that list was written and was never added to it, so "Outsourced" landed at
     1.53:1 and "✓ Paid" at 1.59:1 on its navy card (owner 2026-09-11, measured on the running page). Scoped
     to the light cards, a dark theme keeps the pastel base values and no future one has to be remembered —
     which is the whole fix: Moon Blue was NOT added to Onyx and Blackout's by-name list below, because a
     change nothing can catch is a change to leave out. The pastel base reads on all three (measured). */
  body[data-fk-theme="marine"] #fk-shell .fk-chip.mode{background:rgba(112,72,232,.14);color:#4c2fb8}
  body[data-fk-theme="marine"] #fk-shell .fk-chip.proof-ok,body[data-fk-theme="marine"] #fk-shell .fk-chip.paid-ok{background:rgba(12,166,120,.15);color:#0a6045}
  /* ---- THE STAGE PALETTE ON A LIGHT WORK AREA ----------------------------------------------------------
     fk.js emits every stage colour as var(--st-<key>, <the mock's pastel>). Mission Rail's pastels are tuned
     to sit on #131826 and all seven measured 1.61–2.49:1 against the light board — a stage dot is a non-text
     state indicator and owes 3:1, and on the pipeline strip the dots are the ONLY thing drawn, so on a
     light board the whole strip was seven near-invisible specks. These are the same seven hues taken down to
     where they read on white. Onyx and Blackout say nothing here and keep the mock exactly, via the
     fallback. Scoped to Marine by name rather than to the shared light block, because that block
     also matches Onyx and Blackout before they override it. */
  body[data-fk-theme="marine"] #fk-shell,body[data-fk-theme="marine"] #fk-drawer-backdrop,body[data-fk-theme="marine"] #fk-modal-backdrop,body[data-fk-theme="marine"] #fk-colmenu{
    --on-stage:#ffffff;
    --st-paid_allocate:#12794a;--st-artwork:#8f5a04;--st-in_production:#b02a68;--st-out_production:#5f38c9;
    --st-finishing:#9c4712;--st-delivery:#8c2fa3;--st-invoiced:#0c7062}
  /* …except Marine's NAV panel, which is deep navy while its board is light. The dots there sit on --fk-nav
     (#12304f), so inside it the pastels are the readable set and the deep ones would disappear — measured on
     a deep nav, four of the seven deep hues fall to 2.5–2.9:1 while every pastel clears 6.7:1. */
  body[data-fk-theme="marine"] #fk-shell .fk-navpanel{
    --on-stage:#0A0C11;
    --st-paid_allocate:#4ADE80;--st-artwork:#F5B04E;--st-in_production:#F27FB8;--st-out_production:#A98BFA;
    --st-finishing:#F0875C;--st-delivery:#DF7DF2;--st-invoiced:#38CDB9}
  /* Ocean Teal and Graphite removed by the owner (2026-08-05). Four added the same day, from
     docs/prototype/fk-themes-round{1,2,3}.html. Each changes BOTH the chrome hue and the accent hue — the two
     that remained ran the same cyan, which is why a third grey read as redundant. */

  /* Rich Black and Midnight Navy removed by the owner (2026-08-05). */

  /* Light Box and Forest Press removed by the owner (2026-09-26); fk.js moves anyone on them to Moon Blue. */

  /* --- Blackout — the ONLY theme that repaints the work area too, so it overrides the light palette above.
         No accent hue at all: the only colour on screen is the job's own status dots. --- */
  body[data-fk-theme="blackout"] #fk-shell,body[data-fk-theme="blackout"] #fk-drawer-backdrop,body[data-fk-theme="blackout"] #fk-modal-backdrop,body[data-fk-theme="blackout"] #fk-colmenu{--accent:#e8e8ea;--accent-soft:rgba(232,232,234,.10);--on-accent:#000;--fk-band:#0e0e10;--fk-band-ink:#fff;--fk-band-sub:rgba(255,255,255,.66);
    --bg:#000;--panel:#0b0b0c;--panel2:#0e0e10;--panel3:#141416;--line:#232326;--line2:#2e2e33;--text:#e8e8ea;--dim:#a2a2a8;--white:#fff;--faint:#75757c;--warn:#f5b914;
    /* the work area is dark here, so the three status inks go back to their bright-on-dark values, exactly as
       --warn does on the line above — the light block's deep shades would be near-invisible on #141416 */
    --ok-ink:#3ddc97;--danger-ink:#ff9a95;--warn-ink:#f5b914;--stage-cur:#F0875C;--here-ink:#f6c445;--ring-todo:#767680;
    --fk-thread-ink:#d6d6da;--fk-gl-barsh:rgba(2,10,26,.45);--fk-gl-edge:rgba(160,200,250,.40)}   /* the @name in the order thread — monochrome, like everything in this theme; see Moon Blue's note */
  body[data-fk-theme="blackout"] #fk-shell{--fk-nav:#000;--fk-nav-ink:rgba(255,255,255,.90);--fk-nav-icon:rgba(255,255,255,.58);--fk-nav-cap:rgba(255,255,255,.50);--fk-nav-line:rgba(255,255,255,.10);--fk-nav-hover:rgba(255,255,255,.07);--fk-nav-badge:rgba(255,255,255,.15);--fk-nav-on-bg:#e8e8ea;--fk-nav-on-ink:#000;--fk-band:#0e0e10;--fk-band-ink:#fff;--fk-band-line:rgba(255,255,255,.12);--fk-band-sub:rgba(255,255,255,.66)}

  /* --- Marine — deep marine rail, bright yellow on the things you press. Dark navy ink sits ON the yellow,
         never white. The same dark ink is used wherever the accent would be TEXT (a selected rail row, a
         button on a pale yellow tint): gold-on-gold was legible but muddy, and the owner asked for black
         (2026-08-05). One ink for both jobs, which is also why the theme reads as a single idea. --- */
  body[data-fk-theme="marine"] #fk-shell,body[data-fk-theme="marine"] #fk-drawer-backdrop,body[data-fk-theme="marine"] #fk-modal-backdrop,body[data-fk-theme="marine"] #fk-colmenu{--accent:#ffd54a;--accent-ink:#14243d;--accent-soft:rgba(255,213,74,.22);--on-accent:#14243d;--fk-band:#1a4067;--fk-band-ink:#fff;--fk-band-sub:rgba(255,255,255,.68)}
  body[data-fk-theme="marine"] #fk-shell{--fk-nav:#12304f;--fk-nav-ink:rgba(255,255,255,.90);--fk-nav-icon:rgba(255,255,255,.60);--fk-nav-cap:rgba(255,255,255,.52);--fk-nav-line:rgba(255,255,255,.11);--fk-nav-hover:rgba(255,255,255,.08);--fk-nav-badge:rgba(255,255,255,.16);--fk-nav-on-bg:#ffd54a;--fk-nav-on-ink:#14243d;--fk-band:#1a4067;--fk-band-ink:#fff;--fk-band-line:rgba(255,255,255,.14);--fk-band-sub:rgba(255,255,255,.68)}

  /* --accent-ink (2026-08-05): cyan as TEXT on its own pale tint measured 1.97:1 on the live app — the
     current-stage card's title. The cyan FILL is untouched, so Onyx looks exactly as it did; only the text
     that could not be read changes. */
  /* --- Onyx (default) — carries Mission Rail v2 verbatim, WORK AREA INCLUDED (owner 2026-08-07).
         Like Blackout, it overrides the shared light palette above: the mock draws one dark ground with the
         panel and the board floating on it as cards, and the light work area left a hard white seam against
         the #0A0C11 app rail. Tokens are the mock's own, mapped onto the suite's names:
         ground→--bg · panel→--panel · card→--panel2 · ink/sec/mut→--white/--text/--dim. --- */
  body[data-fk-theme="onyx"] #fk-shell,body[data-fk-theme="onyx"] #fk-drawer-backdrop,body[data-fk-theme="onyx"] #fk-modal-backdrop,body[data-fk-theme="onyx"] #fk-colmenu{--accent:#3ECFDC;--accent-soft:rgba(62,207,220,.13);--on-accent:#062227;--fk-band:#131826;--fk-band-ink:#EEF2F8;--fk-band-sub:#B6C0D2;
    --bg:#0A0C11;--panel:#131826;--panel2:#161C29;--panel3:#1E2637;--line:#232B3C;--line2:#262F43;
    --text:#B6C0D2;--dim:#909BB0;--white:#EEF2F8;--faint:#6B7688;--ok:#5ADD9A;--warn:#F5B84E;--danger:#FF8A85;
    /* like Blackout, this repaints the work area dark, so the light block's deep status inks would vanish.
       Lifted ABOVE the matching fill rather than set equal to it: the hardest case these serve is the proof
       strip's 10.5px version chip on a .18 tint of itself, which measured 4.29:1 with the raw fill colour. */
    --ok-ink:#78EBB8;--danger-ink:#FFB0AB;--warn-ink:#F5B84E;--stage-cur:#F0875C;--here-ink:#f6c445;--ring-todo:#7987AB;
    --cust-ink:#7CC4FF;   /* the customer's name, light sky blue on this dark work area (8.1:1 on the card) */
    --fk-sunk:rgba(0,0,0,.18);
    --fk-thread-ink:#7ee3ec;   /* the @name in the order thread — this theme's cyan, lifted; see Moon Blue's note */
    /* …and the card hover shadow, for the same reason as every token above it: the shared block that sets
       these is body[data-fk-theme], which matches Onyx BEFORE Onyx repaints the work area dark. Its light
       value (a 20% blue-grey) is invisible on #161C29, so this dark theme states its own. */
    --fk-cardsh:rgba(0,0,0,.55);--fk-gl-barsh:rgba(2,10,26,.45);--fk-gl-edge:rgba(160,200,250,.40)}
  /* the three chip fixes above were tuned for a LIGHT card; on the mock's dark card they read as mud */
  body[data-fk-theme="onyx"] #fk-shell .fk-chip.mode,
  body[data-fk-theme="blackout"] #fk-shell .fk-chip.mode{background:rgba(169,139,250,.16);color:#C9B6FF}
  /* mode-in is the in-house half of the same pair and needs the same two fixes, or it renders pink-on-white
     at ~1.6:1 on the light themes — an "In-house" chip you cannot read.
     BOTH dark-work-area themes take the dark variant. Blackout was written into neither list when this pair
     was added, so the deep magenta below landed on its near-black card at 1.99:1. */
  body[data-fk-theme="marine"] #fk-shell .fk-chip.mode-in{background:rgba(199,49,140,.13);color:#8d1f63}
  body[data-fk-theme="onyx"] #fk-shell .fk-chip.mode-in,
  body[data-fk-theme="blackout"] #fk-shell .fk-chip.mode-in{background:rgba(242,127,184,.16);color:#F7A8CD}
  body[data-fk-theme="onyx"] #fk-shell .fk-chip.proof-ok,
  /* Blackout needs it for the same reason Onyx does, and was missed: the rule above hands every themed FK a
     DEEP green ink (#0a6045) chosen for a light board, and on a black card that measured 2.00–2.19:1. The
     two dark themes take the light green back. (audit 2026-08-09) */
  body[data-fk-theme="onyx"] #fk-shell .fk-chip.paid-ok,
  body[data-fk-theme="blackout"] #fk-shell .fk-chip.paid-ok{background:rgba(90,221,154,.15);color:#5ADD9A}
  /* Onyx carries the Mission Rail v2 palette verbatim. It is the DEFAULT theme and body[data-fk-theme] is
     always set, so these tokens — not the base rules — are the look the mock actually specifies. The other
     three themes are unchanged: they remain alternatives to this, in their own hues. */
  body[data-fk-theme="onyx"] #fk-shell{--fk-nav:#131826;--fk-nav-ink:#B6C0D2;--fk-nav-ink-hi:#EEF2F8;--fk-nav-icon:#909BB0;--fk-nav-cap:#909BB0;--fk-nav-line:#232B3C;--fk-nav-hline:#1D2434;--fk-nav-hover:#1A2133;--fk-nav-badge:#1E2637;--fk-nav-on-bg:#3ECFDC;--fk-nav-on-ink:#062227;--fk-band-ink:#fff;--fk-band-line:rgba(255,255,255,.11);--fk-band-sub:rgba(255,255,255,.62)}
  /* paint the themed canvas — the FK content areas (board/list/reports) don't set their own background, so in
     the default theme the dark <body> shows through; a light theme must paint it or the pages read dark */
  /* Stays --bg, deliberately. The canvas being darker than everything is what made the old 8px frame read
     as a crack, but the fix for that was removing the frame, not repainting the canvas: with every gutter
     at 0 the canvas is only ever seen as the board's OWN ground, which is exactly what --bg is.
     Pointing it at --fk-band was tried and reverted the same day — it turned Marine's light board navy,
     because Marine and Forest deliberately pair a dark band with a light board. */
  body[data-fk-theme] #fk-shell{background:var(--bg)}

  /* ============ MOON BLUE (v115, owner 2026-09-09) ============
     "Instead of full black I want full blue (same style as Team Hub Blue Moon theme)", then: "make these
     buttons yellow — and for other buttons we do not see, be creative with them — so no blue on blue."
     Every blue below is Blue Moon's own, lifted from chat.css's body[data-chat-theme="moonblue"] block —
     no colour here was invented for this theme. Its depth ladder is the point and is preserved:
       #05122a  the ground everything floats on      (Blue Moon's --bg-1, the gutter)
       #081834  the nav rail and the top chrome      (--rail)
       #0f2748  panels, cards, board columns         (--bg-0, a clear step lighter)
       #143059 / #1a3a68  raised rows, chips, hovers (--surface / --surface-2)
     THE ACCENT IS GOLD, and that is the whole button answer. .fk-btn.accent and .fk-btn.advance already
     paint with var(--accent)/var(--on-accent), so naming gold here turns every accent-filled control gold
     by construction — including the ones that are not buttons at all (.fk-actsw, the unread pill), which is
     exactly what a hand-written list of selectors missed on the first pass.
     Measured: gold reads 9.3–13.2:1 on all four grounds and navy #04162c on gold is 12.86:1. The ink is
     navy and NEVER white — white on this yellow is 1.41:1, the same defect test/fk-theme-accent-ink.test.cjs
     exists to catch on Marine. */
  body[data-fk-theme="moonblue"] #fk-shell,body[data-fk-theme="moonblue"] #fk-drawer-backdrop,body[data-fk-theme="moonblue"] #fk-modal-backdrop,body[data-fk-theme="moonblue"] #fk-colmenu{
    --accent:#ffd54a;--accent-soft:rgba(255,213,74,.16);--accent-ink:#ffd54a;--accent-line:rgba(255,213,74,.55);--on-accent:#04162c;
    --fk-band:#0f2748;--fk-band-ink:#eef4fd;--fk-band-sub:#a9c1e0;--fk-band-line:rgba(150,185,235,.18);
    --bg:#05122a;--panel:#0f2748;--panel2:#143059;--panel3:#1a3a68;
    --line:rgba(150,185,235,.10);--line2:rgba(150,185,235,.18);
    --text:#c3d6ef;--dim:#a9c1e0;--white:#eef4fd;--faint:#8199bb;
    --ok:#5ADD9A;--warn:#F5B84E;--danger:#FF8A85;
    --ok-ink:#78EBB8;--danger-ink:#FFB0AB;--warn-ink:#F5B84E;--stage-cur:#F0875C;--here-ink:#ffd54a;--ring-todo:#7987AB;
    --cust-ink:#7CC4FF;   /* the customer's name, light sky blue on this navy (6.1:1 on the card) */
    --fk-sunk:rgba(0,0,0,.18);
    /* THE @NAME IN THE ORDER THREAD (owner 2026-09-11: "for the @ name can be same as team hub — the blue
       there is light enough"). The thread is Team Hub's markup mounted in the drawer, and chat.css's FK
       bridge hands it the LIGHT chat palette — written in July 2026, when every FK theme had a light drawer.
       Three dark themes have arrived since, and the bridge's deep teal #096069 measured 2.06:1 here on the
       running page (2.44 on Onyx, 2.71 on Blackout). This is Team Hub Blue Moon's own accent ink, so the
       same name is the same colour in both apps. The bridge reads it; light themes declare none and keep the
       teal, which is what it was chosen for. */
    --fk-thread-ink:#9cc6f5;
    --fk-cardsh:rgba(2,10,26,.55);--fk-gl-barsh:rgba(2,10,26,.45);--fk-gl-edge:rgba(160,200,250,.40)}
  body[data-fk-theme="moonblue"] #fk-shell{--fk-nav:#081834;--fk-nav-ink:#c3d6ef;--fk-nav-ink-hi:#eef4fd;--fk-nav-icon:#a9c1e0;--fk-nav-cap:#8199bb;--fk-nav-line:rgba(150,185,235,.14);--fk-nav-hline:rgba(150,185,235,.09);--fk-nav-hover:rgba(79,155,234,.14);--fk-nav-badge:rgba(79,155,234,.22);--fk-nav-on-bg:#4f9bea;--fk-nav-on-ink:#04162c}
  /* THE SECONDARY BUTTON IS OUTLINED HERE, and only here. .fk-btn fills with --panel2 on a --panel card —
     one step of the ladder, which was plenty on a near-black board and is nothing on this one: measured, 12
     ordinary buttons ("＋ Add their files", "☆ Follow", "⋯", "✕", "Issue & download") sat at 1.14:1 against
     the card behind them. The edge does the work instead of the tint. The three FILLED kinds are excluded by
     name — this rule outranks them on specificity, so without the :not() it would flatten them too. The
     yellow slip button is the fourth (2026-09-09: it went white on this theme, on the production lists). */
  body[data-fk-theme="moonblue"] #fk-shell .fk-btn:not(.accent):not(.advance):not(.ok):not(.slip),
  body[data-fk-theme="moonblue"] #fk-drawer-backdrop .fk-btn:not(.accent):not(.advance):not(.ok):not(.slip),
  body[data-fk-theme="moonblue"] #fk-modal-backdrop .fk-btn:not(.accent):not(.advance):not(.ok):not(.slip){
    background:transparent;border-color:rgba(160,200,250,.40);color:var(--white)}
  body[data-fk-theme="moonblue"] #fk-shell .fk-btn:not(.accent):not(.advance):not(.ok):not(.slip):hover,
  body[data-fk-theme="moonblue"] #fk-drawer-backdrop .fk-btn:not(.accent):not(.advance):not(.ok):not(.slip):hover,
  body[data-fk-theme="moonblue"] #fk-modal-backdrop .fk-btn:not(.accent):not(.advance):not(.ok):not(.slip):hover{
    background:rgba(160,200,250,.10);border-color:var(--accent-line)}
  /* --fk-thread-ink — THE @NAME IN AN ORDER THREAD, declared by each dark theme above and read by chat.css's
     FK bridge (owner 2026-09-11: "for the @ name can be same as team hub — the blue there is light enough").
     See the note beside --fk-thread-ink in the Moon Blue block. */

  /* the send key is a hard-coded teal gradient rather than a token, so the accent cannot reach it */
  body[data-fk-theme="moonblue"] #fk-drawer-backdrop .wc-root{--accent:#ffd54a;--on-accent:#04162c;--accent-line:rgba(255,213,74,.55)}
  body[data-fk-theme="moonblue"] #fk-drawer-backdrop .wc-root .send{background:linear-gradient(150deg,#ffe27a,#f0b429);color:#04162c;box-shadow:0 5px 14px -5px rgba(255,213,74,.55),inset 0 1px 0 rgba(255,255,255,.45)}
  /* FK surfaces whose background is a literal hex rather than a token — a palette cannot reach these */
  body[data-fk-theme="moonblue"] .fk-navpanel{background:#081834;border-right-color:rgba(150,185,235,.14)}
  body[data-fk-theme="moonblue"] .fk-mod:hover{background:#143059;color:#eef4fd}
  body[data-fk-theme="moonblue"] #fk-shell .fk-count{background:#1a3a68;color:#c3d6ef}
  body[data-fk-theme="moonblue"] #fk-shell .fk-cal-cell.other{background:#0b1f3d}
  body[data-fk-theme="moonblue"] #fk-shell .fk-cal-cell.weekend{background:#0d2444}
  body[data-fk-theme="moonblue"] #fk-shell .fk-today-dock,body[data-fk-theme="moonblue"] #fk-shell .fk-col.collapsed{background:#0f2748;border:1px solid rgba(150,185,235,.30)}
  /* ---- the shared chrome, ONLY while Future Knights is the tab you are on ----
     body[data-fk-theme] is set once and never removed, so an unscoped chrome rule here would paint the top
     bar navy on Order Process and Creatives too — tabs with their own palettes that nobody asked to change.
     data-active-tab is what app.js sets for exactly this ("lets CSS scope per-tab chrome"). */
  body[data-fk-theme="moonblue"][data-active-tab="fk"]{--chrome:#081834;--chrome-line:rgba(150,185,235,.16)}
  body[data-fk-theme="moonblue"][data-active-tab="fk"] .icbtn:hover{background:#143059;color:#eef4fd}
  body[data-fk-theme="moonblue"][data-active-tab="fk"] .ritem:hover{background:#12294a}
  body[data-fk-theme="moonblue"][data-active-tab="fk"] .tooltip,body[data-fk-theme="moonblue"][data-active-tab="fk"] .tooltip::before{background:#1a3a68;border-color:rgba(150,185,235,.26);color:#eef4fd}
  body[data-fk-theme="moonblue"][data-active-tab="fk"][data-nav="top"] #rail{background:#081834}
  body[data-fk-theme="moonblue"][data-active-tab="fk"] .grid-scroll tbody tr:nth-child(even) td.user{background:#12294a}
  body[data-fk-theme="moonblue"][data-active-tab="fk"] .avc-stage,body[data-fk-theme="moonblue"][data-active-tab="fk"] .avc-pit i{background:#05122a}

  /* The Team Hub trio takes this rail's ITEM ink, per theme (owner 2026-08-13: "make sure the icons colour
     shades are adaptable to lighter themes"). Every item in this rail paints itself — .fk-mod sets
     var(--fk-nav-ink) — while the rail CONTAINER keeps a dimmer colour for its captions, so the trio, which
     inherits, came out barely legible on Forest Press (aqua #0a5f70) while "Product Range" beside it was
     white. Pointing at the token rather than a literal means all four themes, and any added later, follow by
     construction. The icons are stroke:currentColor, so they follow the same value. */
  /* .fk-navpanel, NOT #fk-nav. The trio used to live inside the scrolling list, so scoping the token there
     worked — until the rows moved up beside the head into .fk-navtop, a SIBLING of that list, and a custom
     property inherits down rather than sideways. The declaration went dead the moment the markup moved, and
     the trio fell back to the WORK AREA's ink on a dark rail: 1.5:1 on Marine, 1.2:1 on Forest Press, with
     the new rule invisible too. Onyx hid it by coincidence — its --text happens to equal --fk-nav-ink — which
     is exactly how it would have shipped. The panel is the parent of both, so it covers whatever either gains
     later. */
  body[data-fk-theme] #fk-shell .fk-navpanel{--hubnav-ink:var(--fk-nav-ink)}
  /* TYPE. Mission Rail v2 was drafted in a system font stack, which was an authoring slip, not a design
     choice — the suite ships Geist, self-hosted (public/fonts/geist-var.woff2) so it renders identically on
     Mac, Windows, iOS and Android. A web app cannot depend on a Windows-only face, so the MOCK was corrected
     to Geist rather than the product (owner 2026-08-08). What the mock does contribute here is its base
     metrics: 13px/1.45, and the `input,button,select{font:inherit}` reset — without that reset every button
     sits at the UA's `normal` line-height and the panel's vertical rhythm comes out ~2px short per row. */
  #fk-shell,#fk-drawer-backdrop,#fk-modal-backdrop{font-size:13px;line-height:1.45}
  /* …and inside the Brief box (public/briefbox.css), which sizes its own tools: this reset is (1,0,1) and out-ranks the box's (0,2,1) rules
     (Brief box round 2, 2026-10-04 — test/brief-box-leak-helper.cjs asks every sheet of every box on the real screens) */
  #fk-shell input,#fk-shell button:where(:not(.bf *)),#fk-shell select,
  /* …except inside the order thread, which is the chat's discussion component and sizes its own controls
     (Task 7 fix round, 2026-09-23: at (1,0,1) this out-ranked every button and field the component draws).
     The Activity log's row is FK's own markup sitting in the component's slot, so it is named back in. */
  #fk-drawer-backdrop input:where(:not(#chat-host *, .wc-root.disc *)),#fk-drawer-backdrop button:where(:not(#chat-host *, .wc-root.disc *, .bf *)),#fk-drawer-backdrop select,
  #fk-drawer-backdrop .fk-actrow input,#fk-drawer-backdrop .fk-actrow button,
  #fk-modal-backdrop input,#fk-modal-backdrop button:where(:not(.bf *)),#fk-modal-backdrop select{font-family:inherit;line-height:inherit}
  /* nav + band read the per-theme tokens (only while a theme is active — default dark look untouched) */
  /* the themed surface is the PANEL now (Mission Rail v2) — theming the inner body instead would leave the
     panel head at the default colour and split the card in two tones under every theme */
  body[data-fk-theme] #fk-shell .fk-navpanel{background:var(--fk-nav);border-color:var(--fk-nav-line)}
  /* the head's own divider went with the head's border — the rule lives under the trio now, and takes its
     colour from --hubnav-ink like everything else in that block */
  body[data-fk-theme] #fk-shell .fk-nphead .crown{color:var(--fk-nav-on-bg)}
  body[data-fk-theme] #fk-shell .fk-mod{color:var(--fk-nav-ink)}
  body[data-fk-theme] #fk-shell .fk-mod .ic{color:var(--fk-nav-icon)}
  /* the un-themed .fk-mod:hover rules are (0,2,0) and these are (1,2,1), so they always won and hover
     collapsed to a background tint — the mock lifts the row's ink and its icon at the same time */
  body[data-fk-theme] #fk-shell .fk-mod:hover{background:var(--fk-nav-hover);color:var(--fk-nav-ink-hi,var(--fk-nav-ink))}
  body[data-fk-theme] #fk-shell .fk-mod:hover .ic{color:var(--fk-nav-ink)}
  /* rows sit at gap:0, so a +2px ring paints over its neighbours — the mock insets it for exactly that */
  #fk-shell .fk-mod:focus-visible{outline-offset:-2px}
  body[data-fk-theme] #fk-shell .fk-count{background:var(--fk-nav-badge);color:var(--fk-nav-ink)}  /* a count is a quantity to read, not a dim label — the mock sets it at item-text weight */
  /* warn/urgent are real state — money owed, something overdue. They were DECLARED at (0,2,0) and silently
     lost to the themed rule above at (1,2,1), so every count painted the same grey. Restored at parity. */
  /* A count sits on the NAV, and a theme's nav lightness is independent of its board's — Marine pairs a
     light board with a dark nav. So neither --warn (tuned for dark panels) nor --warn-ink (tuned for
     the light board) is right here: measured 1.42:1 and 2.32:1. --fk-nav-warn/-danger follow the NAV, like
     every other --fk-nav-* token, and fall back to the base colour for any theme that does not set them. */
  body[data-fk-theme] #fk-shell .fk-count.warn{background:color-mix(in srgb,var(--warn) 18%,transparent);color:var(--fk-nav-warn,var(--warn))}
  body[data-fk-theme] #fk-shell .fk-count.urgent{background:color-mix(in srgb,var(--danger) 18%,transparent);color:var(--fk-nav-danger,var(--danger))}
  body[data-fk-theme="marine"] #fk-shell,body[data-fk-theme="onyx"] #fk-shell{--fk-nav-warn:#f5b84e;--fk-nav-danger:#ff8a85}
  /* the zero pill kept only its opacity:.45 through that same cascade, landing at 3.10:1 — below AA.
     Quiet it with colour instead of transparency so it stays readable. */
  /* the zero pill reads its ink against the BADGE fill, which lightens the surface under it and cost it the
     bar (3.36:1 on Light Box). No fill: the same quiet ink, now measured against the nav itself. */
  body[data-fk-theme] #fk-shell .fk-count.zero{background:transparent;color:var(--fk-nav-cap);opacity:1}
  /* Scoped to #fk-nav. --fk-nav-cap is the caption ink for the NAV RAIL, and .fk-sub is used both there and
     as a section heading on PAGES (Cash Pot's "Past months"). Unscoped, the page heading was painted in a
     colour chosen for a dark rail: 1.09:1 on Forest, 1.07:1 on Marine. On a page it keeps --dim. */
  body[data-fk-theme] #fk-shell #fk-nav .fk-sub,body[data-fk-theme] #fk-shell #fk-nav .fk-sub-toggle,body[data-fk-theme] #fk-shell #fk-nav .fk-sub-toggle .fk-sub-t{color:var(--fk-nav-cap)}
  /* Mission Rail v2 active item: a flat tint of the theme's own accent with a matching hairline, replacing
     the 90deg gradient + 3px left rail. Each theme keeps its own hue, so all four stay coherent. */
  body[data-fk-theme] #fk-shell .fk-mod.active{background:color-mix(in srgb,var(--fk-nav-on-bg) 13%,transparent);color:var(--fk-nav-ink-hi,var(--fk-nav-ink));border-color:color-mix(in srgb,var(--fk-nav-on-bg) 28%,transparent);box-shadow:none;font-weight:600}
  body[data-fk-theme] #fk-shell .fk-mod.active .ic{color:var(--fk-nav-on-bg)}
  body[data-fk-theme] #fk-shell .fk-mod.active .fk-count{background:var(--fk-nav-badge);color:var(--fk-nav-ink)}
  /* the mock lightens the accent for the active count so 11px on a thin tint still clears 5.5:1 */
  body[data-fk-theme="onyx"] #fk-shell .fk-mod.active .fk-count{background:rgba(62,207,220,.14);color:#5FD9E4}
  body[data-fk-theme] #fk-shell .fk-toolbar{background:none;border-bottom-color:transparent}  /* the band is gone in every theme; --fk-band still dresses the order drawer's head */
  /* --white (the board's own heading ink), NOT --fk-band-ink. The line above removes the band's background
     from the toolbar, but this rule kept painting the heading in the ink that was chosen to sit ON that band
     — so on any theme whose band is dark and whose BOARD is light, the page title was white on white:
     Marine measured 1.07:1 and Forest 1.13:1, i.e. invisible, and Marine has been that way since the band
     was removed. Onyx and Blackout are unaffected (their --white is the same white), Light Box gains
     nothing and loses nothing (14.89 → 14.12). (owner spotted it on Forest, 2026-08-09) */
  body[data-fk-theme] #fk-shell .fk-toolbar h2{color:var(--white)}
  /* light-mode fixes for the few hardcoded-dark content elements (calendar muted cells, bulk-select boxes, overdue pill) */
  body[data-fk-theme] #fk-shell .fk-cal-cell.other{background:var(--panel2)}
  body[data-fk-theme] #fk-shell .fk-cal-cell.weekend{background:var(--panel3)}
  /* only the UNCHECKED box takes the light theme's panel bg — else this rule's specificity (1,2,1) beat
     .fk-jchk:checked (0,2,0), so a ticked box kept the light bg and read as un-ticked (owner 2026-07-18) */
  body[data-fk-theme] #fk-shell .fk-jchk:not(:checked),body[data-fk-theme] #fk-shell .fk-jchkall:not(:checked){background:var(--panel2);border-color:var(--line2)}
  body[data-fk-theme] #fk-shell .fk-cal-pill.overdue{color:#b42318}
  /* muted-hint text (empty states) carries opacity:.7 — fine over the dark default, but on the light work area
     it drops --dim below readable contrast. Lift to full opacity in every FK theme so the hint stays legible. */
  body[data-fk-theme] #fk-shell .fk-thread-empty,
  body[data-fk-theme] #fk-drawer-backdrop .fk-thread-empty,
  body[data-fk-theme] #fk-modal-backdrop .fk-thread-empty{opacity:1}
  /* the job drawer's top identity band takes the theme's chrome colour, like the toolbar band (owner 2026-07-18) */
  /* border-bottom-color as well as the background: the base rule hardcodes BOTH (#0C1017 plate, #1B2230 rule)
     and this repainted only the plate, leaving a near-black seam under a #eceef3 band on Light Box and under
     the blue one on Marine. Every theme already defines --fk-band-line for exactly this edge. */
  /* the theme swatch picker (nav footer) */
  /* behind one button, opening UPWARD like Team Hub's Quick settings (owner 2026-09-10). The bar is the foot
     of the rail, so the popover hangs off its top edge — downward would be off-screen. Shown by a CLASS, never
     the `hidden` attribute: the popover carries an author `display`, which outranks the UA's [hidden] rule, so
     a hidden-attribute version rendered in the browser while jsdom read it as hidden and passed. */
  .fk-themebar{position:relative;margin-top:auto;padding:12px 9px 4px;display:flex;flex-direction:column;align-items:stretch}
  .fk-themebtn{display:flex;align-items:center;gap:8px;height:30px;background:none;border:1px solid var(--fk-nav-line,rgba(255,255,255,.1));color:var(--fk-nav-ink,#B6C0D2);border-radius:8px;padding:0 9px;font-size:12px;font-weight:600;cursor:pointer;font-family:inherit;text-align:left;white-space:nowrap}
  .fk-themebtn:hover,.fk-themebtn.open{background:var(--fk-nav-hover,#1A2133);color:var(--fk-nav-ink-hi,#EEF2F8)}
  .fk-themedot{width:12px;height:12px;border-radius:4px;flex:none;box-sizing:border-box;border:1px solid var(--fk-nav-line,rgba(255,255,255,.22))}  /* an edge, so Onyx's near-black dot shows on its own near-black rail */
  /* THE ROOM IS THE RAIL'S, AND THE RAIL CLIPS. .fk-navpanel is overflow:hidden, so this popover cannot spill
     over the board the way a fixed-position menu could — measured: forced to 400px it was cut off at the rail's
     edge. The whole budget is the nav's 168px minimum, and a panel's own padding comes out of it: at 8px a side
     the five 22px swatches wrapped to two rows. 4px a side leaves 130px of content — exactly the row (5×22 +
     4×5) — inside a 140px box with 10px still clear of the rail. max-width is the bar itself, so a sixth theme
     wraps to a second row rather than being silently cut in half. */
  .fk-themepop{display:none;position:absolute;left:9px;bottom:100%;margin-bottom:6px;z-index:30;width:max-content;max-width:100%;
    background:var(--panel3);border:1px solid var(--line2);border-radius:12px;padding:7px 4px;box-shadow:0 18px 40px rgba(0,0,0,.45);
    justify-content:center;align-items:center;gap:5px;flex-wrap:wrap}
  .fk-themepop.open{display:flex}
  .fk-themesw{flex:none;width:22px;height:22px;border-radius:7px;border:2px solid transparent;cursor:pointer;padding:0;box-shadow:inset 0 0 0 1px rgba(0,0,0,.15)}
  .fk-themesw.on{border-color:var(--accent);box-shadow:0 0 0 2px color-mix(in srgb,var(--accent) 40%,transparent)}
  .fk-inv-table tr[draggable]{cursor:grab}
  .fk-inv-table tr[draggable]:active{cursor:grabbing}
  .fk-cat-sec.dragover{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
  .fk-inv-table{width:100%;border-collapse:collapse;font-size:13.5px}
  .fk-inv-table th{text-align:left;color:var(--dim);font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;font-weight:700;padding:6px 10px;border-bottom:1px solid var(--line)}
  .fk-inv-table td{padding:9px 10px;border-bottom:1px solid var(--line);color:var(--text)}
  .fk-inv-table .r{text-align:right;font-variant-numeric:tabular-nums}
  .fk-inv-table tr.low td{background:rgba(255,107,107,.06)}
  .fk-inv-low{background:var(--danger-badge);color:#fff;font-size:9.5px;font-weight:700;border-radius:4px;padding:1px 5px;letter-spacing:.04em}
  /* inventory product thumbnails + the quick-quote 'In stock items' picker */
  .fk-inv-name{display:flex;align-items:center;gap:10px}
  .fk-inv-thumb{width:34px;height:34px;border-radius:7px;object-fit:cover;border:1px solid var(--line);flex:none;background:var(--panel2)}
  .fk-inv-thumb.ph{display:inline-flex;align-items:center;justify-content:center;color:var(--dim);font-size:15px}
  .fk-inv-thumb.lg{width:54px;height:54px;border-radius:9px}
  .fk-hint{font-size:11.5px;color:var(--dim);margin-top:5px}
  .fk-line-name{font-size:12.5px;color:var(--text);display:inline-flex;align-items:center;gap:4px}
  .fk-stock-list{display:flex;flex-direction:column;gap:8px;max-height:340px;overflow:auto;padding-right:2px}
  .fk-stock-item{display:flex;align-items:center;gap:11px;background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:8px 10px}
  .fk-stock-thumb{width:40px;height:40px;border-radius:8px;object-fit:cover;border:1px solid var(--line);flex:none;background:var(--panel)}
  .fk-stock-thumb.ph{display:inline-flex;align-items:center;justify-content:center;font-size:18px}
  .fk-stock-info{flex:1;min-width:0}
  .fk-stock-info .nm{color:var(--white);font-size:13.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-stock-info .mt{color:var(--dim);font-size:11.5px;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-stock-noprice{color:var(--warn)}
  /* the two-class selector beats .fk-modal input{width:100%} so the qty box stays compact and doesn't crush the row */
  .fk-stock-item .fk-stock-qty{width:64px;height:34px;text-align:right;padding:5px 8px;font-size:12.5px;flex:none;box-sizing:border-box}
  .fk-stock-item .fk-btn{flex:none}
  .fk-stock-empty{color:var(--dim);font-size:13px;padding:18px 6px;text-align:center}
  .fk-inv-waste{margin-top:22px;padding-top:16px;border-top:1px solid var(--line)}
  .fk-inv-waste h3{font-size:14px;color:var(--white);margin:0 0 10px}
  .fk-sup-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));gap:12px}
  .fk-sup-card{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px 15px}
  .fk-sup-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;margin-bottom:8px}
  .fk-sup-head b{color:var(--white);font-size:14px;word-break:break-word}
  .fk-sup-actions{display:flex;gap:4px;flex-shrink:0}
  .fk-sup-row{font-size:12.5px;color:var(--text);margin:5px 0;display:flex;align-items:center;gap:6px;flex-wrap:wrap}
  .fk-sup-row code{background:var(--panel2);border:1px solid var(--line);border-radius:5px;padding:1px 6px;font-size:11.5px;color:var(--white)}
  .fk-sup-notes{font-size:12px;color:var(--dim);margin-top:8px;white-space:pre-line;background:var(--panel2);border-radius:8px;padding:8px 10px}
  .fk-sup-how{font-size:12px;margin-top:8px;background:rgba(0,184,217,.08);border:1px solid rgba(0,184,217,.2);border-radius:8px;padding:8px 10px}
  .fk-sup-how b{color:var(--accent);font-size:10px;text-transform:uppercase;letter-spacing:.05em;display:block;margin-bottom:3px}
  .fk-sup-how div{white-space:pre-line;color:var(--text)}
  .fk-prlog{border-top:1px solid var(--line);margin-top:14px;padding-top:12px}
  .fk-prlog h4{margin:0 0 8px;font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:var(--dim)}
  /* targets */
  .fk-tg-h{margin:18px 0 10px;font-size:13px;color:var(--white)}
  .fk-tg-h:first-child{margin-top:2px}
  .fk-tg-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:12px}
  .fk-tg-tile{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px}
  .fk-tg-tile.met{border-color:rgba(12,166,120,.5)}
  .fk-tg-top{display:flex;align-items:center;gap:7px;color:var(--dim);font-size:12px}
  .fk-tg-ic{font-size:15px}
  .fk-tg-nums{display:flex;align-items:baseline;gap:6px;margin:8px 0 7px}
  .fk-tg-nums b{font-size:26px;color:var(--white);line-height:1}
  .fk-tg-nums span{color:var(--dim);font-size:13px}
  .fk-tg-bar{height:6px;background:var(--panel2);border-radius:4px;overflow:hidden}
  .fk-tg-bar>span{display:block;height:100%;background:var(--accent);border-radius:4px;transition:width .3s}
  .fk-tg-tile.met .fk-tg-bar>span{background:var(--ok)}
  .fk-tg-foot{margin-top:6px;font-size:11px;color:var(--dim)}
  .fk-tg-tile.met .fk-tg-foot{color:var(--ok)}
  .fk-tg-table td{vertical-align:top}
  .fk-tg-cell{font-size:13px;color:var(--text)}
  .fk-tg-cell b{color:var(--white)}
  .fk-tg-cell.met b{color:var(--ok)}
  .fk-tg-cell.under b{color:var(--warn)}
  .fk-tg-cbar{height:4px;background:var(--panel2);border-radius:3px;overflow:hidden;margin-top:4px;max-width:90px}
  .fk-tg-cbar>span{display:block;height:100%;background:var(--accent)}
  .fk-tg-me{background:rgba(0,184,217,.06)}
  .fk-tg-tot td{border-top:2px solid var(--line);color:var(--dim)}
  .fk-tg-tot b{color:var(--white)}
  /* help & training */
  .fk-help-intro{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px 18px;max-width:820px}
  .fk-help-intro h3{margin:0 0 6px;color:var(--white);font-size:16px}
  .fk-help-intro p{margin:0;color:var(--dim);font-size:13px;line-height:1.6}
  .fk-help-sec{margin:22px 0 12px;font-size:13px;color:var(--white)}
  .fk-help-pipe{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
  .fk-help-stage{display:flex;flex-direction:column;gap:2px;background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:9px 13px;min-width:110px}
  .fk-help-stage b{color:var(--white);font-size:12.5px}
  .fk-help-stage span:last-child{color:var(--dim);font-size:10.5px}
  .fk-help-arrow{color:var(--dim)}
  .fk-help-gate{margin-top:12px;background:rgba(245,185,20,.08);border:1px solid rgba(245,185,20,.25);border-radius:10px;padding:11px 14px;font-size:12.5px;color:var(--text);line-height:1.6;max-width:820px}
  .fk-help-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));gap:12px}
  .fk-help-card{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px 16px}
  .fk-help-card h4{margin:0 0 8px;color:var(--white);font-size:13.5px}
  .fk-help-card ol{margin:0;padding-left:18px;color:var(--text);font-size:12.5px;line-height:1.7}
  .fk-help-card li{margin-bottom:3px}
  .fk-help-card b{color:var(--white)}
  /* customer messages (WhatsApp-style) */
  .fk-msg-wrap{flex:1;display:flex;min-height:0;position:relative}
  .fk-msg-list{width:var(--fk-msgw,282px);border-right:1px solid var(--line);display:flex;flex-direction:column;min-height:0}
  .fk-msg-search{padding:10px;border-bottom:1px solid var(--line)}
  .fk-msg-search .fk-input{width:100%}
  .fk-msg-rows{flex:1;overflow-y:auto}
  .fk-msg-row{padding:10px 12px;border-bottom:1px solid var(--line);cursor:pointer;border-left:3px solid transparent}
  .fk-msg-row:hover{background:var(--panel2)}
  .fk-msg-row.on{background:rgba(0,184,217,.08);border-left-color:var(--accent)}
  .fk-msg-row .nm{display:flex;justify-content:space-between;align-items:center;gap:6px}
  .fk-msg-row .nm b{color:var(--white);font-size:13px}
  .fk-msg-row .ct{font-size:10px;background:var(--panel2);color:var(--dim);border-radius:10px;padding:1px 7px;flex:none}
  .fk-msg-row .ph{font-size:11px;color:var(--dim);margin-top:2px}
  .fk-msg-row .ph .nophone{color:var(--warn)}
  .fk-msg-row .lm{font-size:11.5px;color:var(--dim);margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .fk-msg-main{flex:1;display:flex;flex-direction:column;min-height:0;min-width:0}
  .fk-msg-empty{margin:auto;color:var(--dim);font-size:13px;padding:30px;text-align:center}
  .fk-msg-head{padding:12px 16px;border-bottom:1px solid var(--line);flex:none}
  .fk-msg-head b{color:var(--white);font-size:14px}
  .fk-msg-body{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:8px;background:var(--bg)}
  .fk-bub{max-width:75%;padding:8px 11px;border-radius:12px}
  .fk-bub .bd{color:var(--text);font-size:13px;line-height:1.45;white-space:pre-wrap;word-break:break-word}
  .fk-bub .mt{font-size:10px;color:var(--dim);margin-top:4px}
  .fk-bub.out{align-self:flex-end;background:rgba(0,184,217,.14);border:1px solid rgba(0,184,217,.25);border-bottom-right-radius:3px}
  .fk-bub.in{align-self:flex-start;background:var(--panel);border:1px solid var(--line);border-bottom-left-radius:3px}
  .fk-msg-compose{border-top:1px solid var(--line);padding:10px 12px;flex:none}
  .fk-msg-compose textarea{width:100%;background:var(--panel2);border:1px solid var(--line);border-radius:8px;color:var(--white);padding:8px 10px;font-size:13px;font-family:inherit;resize:none;line-height:1.5;max-width:100%;overflow-wrap:anywhere;field-sizing:content;max-height:min(calc(1.5em * var(--ta-lines)), var(--ta-vh));overflow-y:auto}
  .fk-msg-compose textarea[rows="2"]{min-height:calc(1.5em * 2 + 18px)}
  .fk-msg-compose textarea:focus{outline:none;border-color:var(--accent)}
  .fk-msg-cbtns{display:flex;align-items:center;gap:8px;margin-top:8px}
  /* automations */
  .fk-auto-card{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px 18px;margin-bottom:14px;max-width:640px}
/* ── Who work goes to (Admin Settings → Apps → Future Knights) ─────────────────────────────────
     One row per stage/press: the name on the left, the person on the right, and — where nobody is set —
     the fallback spelled out, because "who actually gets this" is the whole question the screen answers.
     The global input{margin-bottom:16px} is zeroed on the select: used as a grid cell it inflates the row
     and lifts its own text off the baseline the label sits on (the same bite recorded in CLAUDE.md). */
  .fk-route-row{display:grid;grid-template-columns:minmax(0,1fr) 260px;align-items:center;gap:10px 14px;
    padding:9px 0;border-bottom:1px solid var(--line)}
  .fk-route-row:last-of-type{border-bottom:0}
  .fk-route-row .fk-route-n{font-size:13px;font-weight:650;color:var(--white);min-width:0}
  .fk-route-row .fk-route-n small{display:block;font-weight:400;font-size:11.5px;color:var(--faint);margin-top:1px}
  .fk-route-row select.field{margin:0;width:100%}
  .fk-route-row .hint{grid-column:2;margin-top:-4px;font-size:11.5px}
  /* the outsourced half of a stage that splits by route: a follow-on question, not a stage of its own, so
     it is indented under the row above and does not repeat the divider between stages. */
  .fk-route-row.fk-route-sub{border-top:0;border-bottom:0;padding-top:0;padding-left:18px}
  .fk-route-row.fk-route-sub .fk-route-n{font-weight:400;color:var(--dim)}
  @media (max-width:620px){ .fk-route-row{grid-template-columns:1fr} .fk-route-row .hint{grid-column:1} }
/* ── Record Error list editor (Admin Settings → Apps → Online Orders) ──────────────────────────────
     Replaces two blank text boxes that each held a whole list as key:Label CSV. One row per option, so
     "add one" is a button rather than retyping ten pairs from memory and losing whatever you forget. */
  .ellist{margin:14px 0 6px}
  .elhead{display:flex;align-items:center;gap:9px;margin:0 0 8px}
  .elhead b{font-size:13px;color:var(--white)}
  .elhead .fk-btn.small{margin-left:0}
  .elhead .fk-btn.ghost{background:transparent;border:1px solid var(--line);color:var(--dim)}
  .elrow{display:grid;grid-template-columns:1fr 150px 92px auto auto auto;align-items:center;gap:8px;
    padding:6px 8px;border:1px solid var(--line);border-radius:8px;margin-bottom:6px;background:var(--panel2)}
  .elrow.off{opacity:.6;background:transparent;border-style:dashed}
  /* the suite-wide input{margin-bottom:16px} would break the row's baseline — the trap CLAUDE.md names */
  .elrow .ellabel{margin-bottom:0;height:32px;background:var(--panel);border:1px solid var(--line);
    border-radius:6px;color:var(--white);padding:0 9px;font-size:13px;width:100%}
  .elrow .ellabel:disabled{color:var(--dim);background:transparent}
  .elrow .elkey{font-size:11.5px;color:var(--dim);font-family:ui-monospace,Menlo,Consolas,monospace;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .elrow .eluse{font-size:11.5px;color:var(--dim);text-align:right;font-variant-numeric:tabular-nums}
  .elrow .elmove,.elrow .elact{height:28px;border-radius:6px;border:1px solid var(--line);
    background:var(--panel);color:var(--dim);font-size:12px;cursor:pointer;padding:0 8px}
  .elrow .elmove{width:28px;padding:0}
  .elrow .elmove:disabled{opacity:.35;cursor:default}
  .elrow .elact:hover{color:var(--white);border-color:var(--dim)}
  .elrow .elact.danger:hover{color:var(--danger);border-color:var(--danger)}
  .elsave{display:flex;align-items:center;gap:12px;margin:12px 0 2px}
  .elsave .fk-auto-help{margin:0;color:var(--warn)}
  .fk-auto-card h3{margin:0 0 6px;color:var(--white);font-size:14px}
  .fk-auto-help{margin:0 0 6px;color:var(--dim);font-size:12px;line-height:1.6}
  .fk-auto-row{display:flex;justify-content:space-between;align-items:center;gap:14px;padding:11px 0;border-top:1px solid var(--line)}
  .fk-auto-row>span:first-child{display:flex;flex-direction:column;gap:2px}
  .fk-auto-row b{color:var(--text);font-size:13px}
  .fk-auto-row small{color:var(--dim);font-size:11.5px}
  .fk-auto-num{display:flex;align-items:center;gap:6px;color:var(--dim);font-size:12px;white-space:nowrap}
  .fk-auto-num input{width:64px;background:var(--panel2);border:1px solid var(--line);border-radius:8px;color:var(--white);padding:7px 9px;font-size:13px;font-family:inherit;text-align:center}
  /* 64px fits a percentage or a day count; a money field does not — "1000" clipped to "100C".
     sauNum adds .wide whenever the allowed maximum runs past 3 digits, so this never needs
     revisiting per-setting. */
  .fk-auto-num input.wide{width:104px}
  .fk-auto-num input:focus{outline:none;border-color:var(--accent)}
  .fk-switch{appearance:none;-webkit-appearance:none;width:42px;height:23px;border-radius:20px;background:var(--panel2);border:1px solid var(--line);position:relative;cursor:pointer;flex:none;transition:background .15s}
  .fk-switch::after{content:'';position:absolute;top:2px;left:2px;width:17px;height:17px;border-radius:50%;background:var(--dim);transition:transform .15s,background .15s}
  .fk-switch:checked{background:rgba(0,184,217,.25);border-color:var(--accent)}
  .fk-switch:checked::after{transform:translateX(19px);background:var(--accent)}
  .fk-auto-tpl{padding:11px 0;border-top:1px solid var(--line)}
  /* the proof-checks editor (Admin Settings → Apps → Future Knights). input{margin-bottom:16px} is global — zeroed */
  .pchecks{display:flex;flex-direction:column;gap:8px;margin:8px 0 12px}
  .pcheck-row{display:flex;align-items:center;gap:8px}
  .pcheck-row input{flex:1;min-width:0;margin:0}
  .pcheck-x{flex:none;width:34px;height:34px;border-radius:8px;border:1px solid var(--line);background:none;color:var(--dim);cursor:pointer;font-family:inherit;font-size:13px}
  .pcheck-x:hover{color:var(--white);border-color:var(--line2)}
  .fk-auto-tpl label{display:block;margin-bottom:6px}
  .fk-auto-tpl label b{color:var(--text);font-size:13px;display:block}
  .fk-auto-tpl label small{color:var(--dim);font-size:11.5px}
  /* one rule, boxes written rows=2/4/6/8 — with field-sizing every one of them now sizes to what it actually holds (the rows= attribute stops being consulted), up to the shared twelve. */
  .fk-auto-tpl textarea{width:100%;background:var(--panel2);border:1px solid var(--line);border-radius:8px;color:var(--white);padding:8px 10px;font-size:12.5px;font-family:inherit;resize:vertical;line-height:1.5;max-width:100%;overflow-wrap:anywhere;field-sizing:content;max-height:min(calc(1.5em * var(--ta-lines)), var(--ta-vh));overflow-y:auto}
  /* the six message templates are rows=2; the three call-log lists are rows=6/8/4 and are never empty in
     practice, but an empty one collapsing from 168px to 37px is still a box that lost its shape. */
  .fk-auto-tpl textarea[rows="2"]{min-height:calc(1.5em * 2 + 18px)}
  .fk-auto-tpl textarea[rows="4"]{min-height:calc(1.5em * 4 + 18px)}
  .fk-auto-tpl textarea[rows="6"]{min-height:calc(1.5em * 6 + 18px)}
  .fk-auto-tpl textarea[rows="8"]{min-height:calc(1.5em * 8 + 18px)}
  .fk-auto-tpl textarea:focus{outline:none;border-color:var(--accent)}
  /* prospects pipeline (V3-style funnel + collapsible stage sections) */
  .fk-pfunnel{display:flex;align-items:center;flex-wrap:wrap;gap:4px;margin-bottom:14px}
  .fk-pfstep{display:flex;align-items:center;gap:6px;background:var(--panel);border:1px solid var(--line);border-radius:9px;padding:7px 10px;cursor:pointer;font-family:inherit}
  .fk-pfstep:hover{border-color:var(--sc)}
  .fk-pfstep .num{width:16px;height:16px;border-radius:50%;background:var(--panel2);color:var(--dim);font-size:10px;display:flex;align-items:center;justify-content:center;flex:none}
  .fk-pfstep .em{font-size:13px}
  .fk-pfstep .nm{font-size:12px;color:var(--white)}
  .fk-pfstep .ct{font-size:11px;font-weight:700;color:var(--sc);background:var(--panel2);border-radius:10px;padding:1px 7px;min-width:18px;text-align:center}
  .fk-pfarrow{color:var(--dim)}
  .fk-pbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-bottom:12px}
  .fk-pbar .fk-input{padding:7px 10px}
  .fk-pbulk{display:flex;gap:8px;flex-wrap:wrap;align-items:center;background:rgba(0,184,217,.08);border:1px solid rgba(0,184,217,.3);border-radius:10px;padding:9px 12px;margin-bottom:12px}
  .fk-pbulk .ct{color:var(--accent);font-size:12px}
  .fk-pbulk .fk-input{padding:6px 9px}
  .fk-ppipe{display:flex;flex-direction:column;gap:8px}
  .fk-pstage{border:1px solid var(--line);border-left:3px solid var(--sc);border-radius:10px;overflow:hidden}
  .fk-pstage-hd{width:100%;display:flex;align-items:center;gap:9px;background:var(--panel);border:none;padding:10px 13px;cursor:pointer;font-family:inherit;text-align:left}
  .fk-pstage-hd:hover{background:var(--panel2)}
  .fk-pstage.open .fk-pstage-hd{border-bottom:1px solid var(--line)}
  .fk-pstage-hd .chev{color:var(--sc);font-size:12px;width:12px;flex:none}
  .fk-pstage-hd .num{width:18px;height:18px;border-radius:50%;background:var(--panel2);color:var(--dim);font-size:10px;display:flex;align-items:center;justify-content:center;flex:none}
  .fk-pstage-hd .em{font-size:15px}
  .fk-pstage-hd .nm{font-weight:600;color:var(--white);font-size:13px}
  .fk-pstage-hd .ct{margin-left:auto;font-size:12px;font-weight:700;color:var(--sc);background:var(--panel2);border-radius:10px;padding:1px 9px}
  .fk-pstage-body{background:var(--panel)}
  .fk-pstage-body .fk-table{border:none;border-radius:0}
  .fk-prow.sel,.fk-table tbody tr.sel{background:rgba(0,184,217,.07)}
  .fk-prow td{vertical-align:top}
  /* customer 360 detail */
  .fk-cd-top{display:flex;gap:14px;flex-wrap:wrap;margin-bottom:6px}
  .fk-cd-profile{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:14px 16px;min-width:230px}
  .fk-cd-row{font-size:13px;color:var(--text);padding:3px 0}
  .fk-cd-row.s{color:var(--dim);font-size:11.5px;padding-top:6px}
  .fk-cd-h{margin:18px 0 10px;font-size:13px;color:var(--white)}
  /* pinned footer: the action buttons stay put at the bottom while a tall form scrolls above them — on a
     squeezed laptop the New Job modal's Create/Cancel used to fall below the fold (owner 2026-07-18). Negative
     margins span the 24px modal padding; the solid bg + top keyline stop scrolled fields showing through. */
  .fk-modal .actions .fk-why{margin-right:auto;align-self:center;font-size:12px;color:var(--dim)} /* why a Confirm is still disabled — left of the buttons */
  .fk-modal .actions{display:flex;gap:8px;justify-content:flex-end;position:sticky;bottom:-24px;margin:14px -24px -24px;padding:13px 24px;background:var(--panel);border-top:1px solid var(--line);z-index:1}

  /* command palette */
  .kbd-hint{font-size:9px;background:rgba(255,255,255,.08);border:1px solid var(--line);border-radius:4px;padding:1px 4px;margin-left:6px;color:var(--dim);font-family:inherit}
  .cmdk-backdrop{position:fixed;inset:0;background:rgba(8,10,16,.6);display:none;align-items:flex-start;justify-content:center;padding-top:12vh;z-index:60}
  .cmdk-backdrop.open{display:flex}
  .cmdk{width:min(620px,94vw);background:var(--panel);border:1px solid var(--line);border-radius:14px;box-shadow:0 24px 60px rgba(0,0,0,.5);overflow:hidden;display:flex;flex-direction:column;max-height:72vh}
  .cmdk-search{display:flex;align-items:center;gap:10px;padding:13px 16px;border-bottom:1px solid var(--line)}
  .cmdk-search .cmdk-ic{color:var(--dim);font-size:16px}
  .cmdk-search input{flex:1;background:none;border:none;outline:none;color:var(--white);font-size:15px;font-family:inherit}
  .cmdk-search kbd,.cmdk-foot kbd{font-size:10px;background:var(--panel2);border:1px solid var(--line);border-radius:4px;padding:2px 5px;color:var(--dim);font-family:inherit}
  .cmdk-results{flex:1;overflow-y:auto;padding:6px}
  .cmdk-group{font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--dim);font-weight:700;padding:9px 10px 4px}
  /* ONE line per row, three aligned columns: glyph · name · state. The old two-line row spent its second line
     on the row's TYPE ("Tab", six times over) and left the right half of a 620px box empty; the state column
     is what turns a row from a link into an answer ("INV-1012 · £60 owed"). */
  .cmdk-item{display:grid;grid-template-columns:18px 1fr auto;align-items:center;gap:10px;padding:7px 11px;border-radius:8px;cursor:pointer;min-height:34px}
  .cmdk-item.active{background:var(--panel2)}
  .cmdk-g{color:var(--dim);font-size:12.5px;text-align:center;line-height:1}
  .cmdk-label{color:var(--white);font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .cmdk-dim{color:var(--dim)}
  /* a job number (Creatives CDS-N / CWE-N) is a small rounded chip before the title — the mock's .num, on the dark palette */
  .cmdk-num{display:inline-block;font-weight:650;font-size:12px;line-height:1.2;color:var(--text);background:rgba(255,255,255,.09);border-radius:6px;padding:3px 7px;letter-spacing:.01em;margin-right:8px;vertical-align:middle}
  /* --dim, not --faint: this column is read. --faint is 2.7:1 on --panel and unreadable at 11.5px. */
  .cmdk-meta{color:var(--dim);font-size:11.5px;white-space:nowrap;font-variant-numeric:tabular-nums}
  .cmdk-sub{color:var(--dim);font-size:11.5px}
  /* verbs are short; as full rows they would cost four times the height to say the same thing */
  .cmdk-chips{display:flex;flex-wrap:wrap;gap:6px;padding:2px 11px 8px}
  .cmdk-chip{background:var(--panel2);border:1px solid var(--line);border-radius:var(--r-pill);padding:5px 12px;
    font-size:11.5px;color:var(--text);font-family:inherit;cursor:pointer;line-height:1.4}
  .cmdk-chip.active{border-color:var(--accent);color:var(--white)}
  .cmdk-hint{padding:22px 16px;color:var(--dim);font-size:12.5px;text-align:center}
  .cmdk-hint b{color:var(--text);font-weight:600}
  .cmdk-keys{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;margin-top:12px;font-size:11.5px}
  .cmdk-keys i{font-style:normal;color:var(--accent);font-weight:700;margin-right:4px}
  .cmdk-empty{padding:26px;text-align:center;color:var(--dim);font-size:13px}
  /* "still looking" — deliberately quiet and inline, so a half-arrived list does not jump when the rest lands */
  .cmdk-loading{padding:10px 11px;color:var(--dim);font-size:11.5px;display:flex;align-items:center;gap:9px}
  .cmdk-loading::before{content:'';width:10px;height:10px;flex:none;border-radius:50%;border:1.5px solid var(--line2);border-top-color:var(--accent);animation:cmdk-spin .7s linear infinite}
  @keyframes cmdk-spin{to{transform:rotate(360deg)}}
  @media (prefers-reduced-motion:reduce){ .cmdk-loading::before{animation:none;border-top-color:var(--dim)} }
  .cmdk-foot{display:flex;gap:16px;padding:8px 14px;border-top:1px solid var(--line);font-size:11px;color:var(--dim);align-items:center;flex-wrap:wrap}
  .cmdk-foot-sp{flex:1}
  .cmdk-scopes{display:flex;gap:13px}
  .cmdk-scopes i{font-style:normal;color:var(--accent);font-weight:700;margin-right:4px}

  /* disabled form controls read as clearly unavailable (e.g. when a workflow gate locks a field) */
  input:disabled,.field:disabled,.fk-input:disabled,
  .fk-modal input:disabled,.fk-modal select:disabled,.fk-modal textarea:disabled,
  .fk-dl input:disabled,.fk-dl select:disabled{opacity:.55;cursor:not-allowed}

  /* ---------- a11y: visible keyboard focus across the suite (mouse focus stays clean) ---------- */
  /* Placed last AND matched to each control's specificity so the various :focus{outline:none} / base outline:none rules lose on keyboard focus. */
  /* :focus-visible never matches a pointer click, so clicking buttons/inputs shows no ring. */
  :focus-visible{outline:var(--focus-ring);outline-offset:2px}
  input:focus-visible,.field:focus-visible,.fk-input:focus-visible,
  .fk-modal input:focus-visible,.fk-modal select:focus-visible,.fk-modal textarea:focus-visible,
  .fk-dl input:focus-visible,.fk-dl select:focus-visible,
  .cmdk-search input:focus-visible,
  .fk-msg-compose textarea:focus-visible,.fk-auto-num input:focus-visible,.fk-auto-tpl textarea:focus-visible{outline:var(--focus-ring);outline-offset:2px}
  /* halo only on controls that DON'T use box-shadow for their state (so the .tab raised-segment shadow / .fk-mod bar survive focus) */
  .btn:focus-visible,.fk-btn:focus-visible,.fk-pill:focus-visible,.fk-segtab:focus-visible,
  .set-rail-item:focus-visible,.fk-subtab:focus-visible,.acct-item:focus-visible,.acct-chip:focus-visible,
  .icon-btn:focus-visible,.set-win-close:focus-visible,.notif-readall:focus-visible{box-shadow:var(--focus-shadow)}
  /* shared image lightbox (Suite.lightbox) — click an uploaded image / GIF to view it centred & dismissable (backdrop / ✕ / Esc), never 100% full-screen */
  /* WHAT SITS BEHIND A PICTURE IS ABOUT THE PICTURE (owner 2026-09-11, mock
     docs/prototype/image-viewer-backdrop-mock.html, option A: "they show very dark background. compare to
     clickup they have more lighter backdrop which can support dark images and lighter images png").
     The ground was rgba(6,8,16,.82) with a #0b0e18 plate, and Moon Blue overrode the plate to #05122a —
     near-black, which only ever suited artwork that is light. A navy wrap with black script had no edge and
     its ink disappeared. One neutral mid grey is the only ground that serves both, so it is a token here and
     not a colour repeated per theme: the theme is what the person picked, the artwork is what the customer
     is paying for. --lb-chip is DARK on purpose — every control in this viewer is white ink on a translucent
     chip, and translucent WHITE on a grey ground is invisible, which is how lightening a backdrop quietly
     breaks its own close button. */
  .suite-lightbox{--lb-ground:#797d85;--lb-chip:rgba(0,0,0,.36);--lb-chip-hi:rgba(0,0,0,.56);
    position:fixed;inset:0;z-index:4000;display:flex;align-items:center;justify-content:center;padding:min(6vh,56px) min(6vw,56px) 96px;background:rgba(121,125,133,.96);backdrop-filter:blur(4px);opacity:0;transition:opacity .14s ease;cursor:zoom-out}
  .suite-lightbox.open{opacity:1}
  /* THE FRAME IS WHAT CLIPS (zoom, 2026-08-24). The picture used to size itself with max-width/max-height;
     now it is laid out at its fitted size and moved by a transform, and this box is what it is moved INSIDE.
     Its width/height are set from JS on every zoom step — never here — so there is one place that decides
     how big the viewer is. The media is positioned absolutely, never centred by flex: centring it and THEN
     transforming it is two things owning the position, and a picture wider than the box hangs off both edges
     before it is ever scaled (found in the mockup, by looking at it). */
  .suite-lightbox .lb-frame{position:relative;overflow:hidden;border-radius:12px;box-shadow:0 18px 60px rgba(0,0,0,.34);background:var(--lb-ground);cursor:default;max-width:min(1100px,92vw);max-height:calc(100vh - 200px)}
  .suite-lightbox .lb-frame > *{position:absolute;left:0;top:0;transform-origin:0 0}
  .suite-lightbox .lb-frame.lb-pannable{cursor:grab}
  .suite-lightbox .lb-frame.lb-panning{cursor:grabbing}
  .suite-lightbox img{display:block;object-fit:contain;cursor:inherit;user-select:none;-webkit-user-drag:none}
  .suite-lightbox .lb-frame > video{position:static}
  /* lightbox overlay box: shrink-wraps the expanded image so percentage-positioned children (FK's customer
     proof pins) land on the ARTWORK, not on the padded backdrop. line-height:0 kills the inline-block
     descender gap that would otherwise offset every pin by a few pixels vertically. */
  .suite-lightbox .lb-fig{position:relative;display:inline-block;line-height:0;max-width:100%}
  .suite-lightbox .lb-fig img{display:block}
  /* video attachments expand in the same overlay as images (owner 2026-07-20) — matched sizing so the two
     media types feel like one viewer rather than two */
  .suite-lightbox .lb-vid{max-width:min(1100px,92vw);max-height:88vh;border-radius:12px;box-shadow:0 24px 90px rgba(0,0,0,.6);background:#000;display:block;outline:none}
  .suite-lightbox .lb-x{position:fixed;top:18px;right:22px;width:40px;height:40px;border-radius:50%;background:var(--lb-chip);color:#fff;border:none;font-size:17px;line-height:1;cursor:pointer;display:grid;place-items:center;transition:background .12s}
  .suite-lightbox .lb-x:hover{background:var(--lb-chip-hi)}
  /* Copy and Download share the corner as one row (mock 4, owner 2026-09-29); Download keeps the edge it has had since July */
  .suite-lightbox .lb-acts{position:fixed;bottom:22px;right:22px;display:flex;align-items:center;gap:8px}
  .suite-lightbox .lb-dl{background:var(--lb-chip);color:#fff;border-radius:12px;padding:9px 16px;font-weight:700;font-size:13px;text-decoration:none;transition:background .12s}
  .suite-lightbox .lb-dl:hover{background:var(--lb-chip-hi)}
  .suite-lightbox .lb-copy{background:var(--lb-chip);color:#fff;border:0;border-radius:12px;padding:9px 16px;font:inherit;font-weight:700;font-size:13px;line-height:normal;cursor:pointer;transition:background .12s}
  .suite-lightbox .lb-copy:hover{background:var(--lb-chip-hi)}
  .suite-lightbox .lb-copy[hidden]{display:none}
  /* a marked picture downloads WITH its marks; the untouched file is the quieter link above it (owner 2026-09-29) */
  .suite-lightbox .lb-dlo{position:fixed;bottom:66px;right:22px;background:var(--lb-chip);color:rgba(255,255,255,.82);border-radius:10px;padding:6px 12px;font-weight:600;font-size:12px;text-decoration:none;transition:background .12s,color .12s}
  .suite-lightbox .lb-dlo:hover{background:var(--lb-chip-hi);color:#fff}
  .suite-lightbox .lb-dlo[hidden]{display:none}
  /* paging through the images posted together: arrows sit clear of the picture, the counter says how far in
     you are. Both appear ONLY when there is more than one — a single image looks exactly as it always did. */
  .suite-lightbox .lb-nav{position:fixed;top:50%;transform:translateY(-50%);width:46px;height:46px;border-radius:50%;background:var(--lb-chip);color:#fff;border:none;font-size:26px;line-height:1;padding-bottom:3px;cursor:pointer;display:grid;place-items:center;transition:background .12s}
  .suite-lightbox .lb-nav:hover{background:var(--lb-chip-hi)}
  .suite-lightbox .lb-nav.prev{left:16px}
  .suite-lightbox .lb-nav.next{right:16px}
  /* ONE bar along the bottom middle: how far into a group you are, and the zoom. They both wanted this spot
     and two stacked pills is clutter. Download keeps its own corner. */
  .suite-lightbox .lb-bar{position:fixed;left:50%;bottom:22px;transform:translateX(-50%);display:flex;align-items:center;gap:2px;padding:5px;border-radius:14px;background:var(--lb-chip);backdrop-filter:blur(10px)}
  .suite-lightbox .lb-count{color:#fff;font-size:12.5px;font-weight:700;letter-spacing:.02em;padding:0 10px;font-variant-numeric:tabular-nums}
  .suite-lightbox .lb-sep{width:1px;height:22px;background:rgba(255,255,255,.18);margin:0 4px}
  .suite-lightbox .lb-zoom{display:flex;align-items:center;gap:2px}
  .suite-lightbox .lb-zoom[hidden]{display:none}
  .suite-lightbox .lb-btn{appearance:none;border:0;background:transparent;color:#fff;width:36px;height:34px;border-radius:10px;display:grid;place-items:center;cursor:pointer;transition:background .12s}
  .suite-lightbox .lb-btn:hover:not(:disabled){background:var(--lb-chip-hi)}
  .suite-lightbox .lb-btn:disabled{color:rgba(255,255,255,.4);cursor:default}
  .suite-lightbox .lb-btn svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
  @media (max-width:640px){ .suite-lightbox .lb-nav{width:38px;height:38px;font-size:22px} .suite-lightbox .lb-nav.prev{left:6px} .suite-lightbox .lb-nav.next{right:6px} .suite-lightbox .lb-acts,.suite-lightbox .lb-dlo{display:none} }
  @media (prefers-reduced-motion: reduce){ .suite-lightbox{transition:none} }

  /* ═══ ONE-BOX PANELS (owner 2026-09-10) — Production and Design & Proofing, built from
     docs/prototype/fk-production-one-box-mock.html and fk-design-one-box-mock.html. The header carries the route,
     the machine and the responsible person's name; the box is a shade lighter than the panel; its bottom line
     carries the state and one button. The timeline node carries the assign. ═══ */
  .fk-obhead{position:relative;display:flex;align-items:center;gap:12px;margin:0 0 12px;flex-wrap:wrap}
  .fk-obhead h4{font-size:16px;font-weight:700;color:var(--white);margin:0}
  .fk-obchip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:999px;background:var(--panel3);color:var(--white);font-size:12.5px;font-weight:600;white-space:nowrap}
  .fk-obchip.q{background:transparent;border:1px solid var(--line2);color:var(--dim)}
  .fk-obchip.q b{color:var(--white)}
  .fk-chipsel{height:26px;padding:0 26px 0 11px;border-radius:999px;background:transparent;border:1px solid var(--line2);color:var(--white);font-size:12.5px;font-weight:600;width:auto;margin:0}
  /* the name and whatever sits after it (Accept, or the counter) are ONE group, pushed right together */
  .fk-whogrp{margin-left:auto;display:inline-flex;align-items:center;gap:10px;white-space:nowrap}
  .fk-whohead{display:inline-flex;align-items:center;gap:9px;font-size:13.5px;color:var(--white);font-weight:600;white-space:nowrap}
  .fk-whohead .fk-avatar{width:28px;height:28px;font-size:11px}
  .fk-whohead small{font-size:12px;color:var(--faint);font-weight:500}
  .fk-whohead.none{color:var(--faint);font-weight:500}
  .fk-whohead.can{cursor:pointer;border-radius:9px;padding:3px 8px;margin-right:-8px}
  .fk-whohead.can:hover{background:rgba(255,255,255,.07)}
  .fk-obhead>.fk-assignpick{left:auto;right:0;transform:none}
  /* ACCEPT, AND THE COUNTER THAT TAKES ITS PLACE (owner 2026-09-11). Both sit right after the name and are
     the same height, so the row does not move when one becomes the other. Green rather than the theme accent:
     this is the same "I'm on it" the timeline node offers, and it reads as a state, not as the next step. */
  .fk-acceptbtn{height:30px;padding:0 13px;border-radius:8px;border:1px solid var(--ok);
    background:color-mix(in srgb,var(--ok) 14%,transparent);color:var(--ok);font-size:12.5px;font-weight:700;white-space:nowrap}
  .fk-acceptbtn:hover{background:color-mix(in srgb,var(--ok) 22%,transparent);border-color:var(--ok)}
  .fk-onit{display:inline-flex;align-items:center;gap:7px;height:30px;padding:0 12px;border-radius:8px;
    border:1px solid color-mix(in srgb,var(--ok) 35%,transparent);background:color-mix(in srgb,var(--ok) 10%,transparent);
    color:var(--ok);font-size:12.5px;font-weight:600;white-space:nowrap}
  .fk-onit b{font-weight:800}
  .fk-onebox{background:var(--panel2);border:1px solid var(--line2);border-radius:14px;overflow:hidden;margin-bottom:12px}
  .fk-obx{padding:16px 20px}
  .fk-obacts{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:12px}
  .fk-btn.line{background:transparent;border:1px solid var(--line2);color:var(--white);height:36px;padding:0 15px;border-radius:8px;font-weight:600;display:inline-flex;align-items:center;gap:7px;font-size:13px}
  .fk-btn.go{background:var(--ok);border-color:var(--ok);color:#04241a;font-weight:700;height:38px;padding:0 18px;border-radius:8px;font-size:13px}
  .fk-btn.acc{background:var(--accent);border-color:var(--accent);color:var(--on-accent);font-weight:700;height:38px;padding:0 18px;border-radius:8px;font-size:13px}
  .fk-btn.go:disabled,.fk-btn.acc:disabled{opacity:.45;cursor:default}
  .fk-obfoot{display:flex;align-items:center;gap:14px;padding:14px 20px;border-top:1px solid var(--line2);background:rgba(90,221,154,.06)}
  .fk-obfoot .m{min-width:0;flex:1}
  .fk-obfoot .q{font-size:14px;font-weight:700;color:var(--white)}
  .fk-obfoot .h{font-size:12.5px;color:var(--dim);margin-top:3px;line-height:1.45}
  .fk-obfoot .h b{color:var(--text);font-weight:600}
  .fk-obfoot.on .q{color:var(--ok)}
  .fk-obfoot.wait{background:rgba(245,184,78,.06)}
  .fk-obfoot.wait .q{color:var(--warn)}
  .fk-obfoot.idle{background:none}
  /* WHERE SHOULD THIS GO TO BE REVIEWED — the question and its three answers (owner 2026-09-11). It sits under
     the foot rather than in it, because a question with three answers is not a sentence with a button. */
  .fk-ask{border-top:1px solid var(--line2);padding:16px 20px 18px;background:rgba(2,10,26,.18)}
  .fk-ask .q{font-size:14px;font-weight:700;color:var(--white);margin-bottom:12px}
  .fk-ask .opts{display:flex;gap:10px;flex-wrap:wrap}
  .fk-opt{display:inline-flex;align-items:center;gap:10px;height:44px;padding:0 16px;border-radius:10px;
    border:1px solid var(--line2);background:transparent;color:var(--white);font-size:13.5px;font-weight:600;
    font-family:inherit;cursor:pointer;white-space:nowrap;text-align:left}
  .fk-opt:hover{border-color:var(--accent-line,var(--line2));background:rgba(255,255,255,.04)}
  .fk-opt .ic{width:26px;height:26px;border-radius:7px;background:var(--panel3);display:grid;place-items:center;font-size:13px;flex:none}
  .fk-opt .fk-avatar{width:26px;height:26px;font-size:10.5px;flex:none}
  .fk-opt .stk{display:flex;flex-direction:column;line-height:1.15}
  .fk-opt .stk small{font-size:11.5px;color:var(--faint);font-weight:500;margin-top:1px}
  /* the ordinary route leads. The modifier is NOT called "primary": suite.css owns `button.primary` unscoped,
     and it sets width:100% — photographed 2026-09-11 with "The customer" stretched across the whole box while
     the answer beside it sat at its own width. A bare, common modifier on a button is the same trap .fk-band
     fell into on the Job Board. */
  .fk-opt.fk-lead{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
  .fk-opt.fk-lead:hover{filter:brightness(1.05);background:var(--accent)}
  .fk-opt.fk-lead .ic{background:rgba(0,0,0,.14)}
  .fk-opt.fk-lead .stk small{color:color-mix(in srgb,var(--on-accent) 72%,transparent)}
  /* drawn before the checks are ticked, so the screen does not grow a question under the hand — just not
     pressable yet, and the foot above says what unlocks them */
  .fk-ask.locked .q{color:var(--dim)}
  .fk-opt[disabled]{opacity:.45;cursor:not-allowed}
  .fk-opt[disabled]:hover{border-color:var(--line2);background:transparent}
  .fk-opt.fk-lead[disabled]:hover{background:var(--accent)}
  /* what came back from an internal check, above the question the designer is answering again */
  .fk-revback{padding:12px 20px;border-top:1px solid var(--line2);font-size:13px;color:var(--warn);line-height:1.5}
  .fk-revback b{color:var(--white);font-weight:600}
  .fk-obfoot .fk-btn{flex:none}
  .fk-linkbtn{background:none;border:0;padding:0;color:var(--dim);font:inherit;text-decoration:underline;text-decoration-style:dotted;text-underline-offset:3px;cursor:pointer}
  .fk-linkbtn:hover{color:var(--white)}
  .fk-after{margin:10px 2px 0;font-size:12.5px;color:var(--faint)}
  .fk-after summary{cursor:pointer;color:var(--dim)}
  .fk-finnotes textarea{margin-top:8px}
  .fk-after-list:empty{display:none}
  /* the print-file rows inside the box: the per-file Download goes (the Print file button IS the download), and the uploader reads as a link */
  .fk-onebox .fk-ff-item > a.fk-btn{display:none}
  .fk-onebox .fk-ff-box .fk-btn,.fk-dsgrid .fk-ff-box .fk-btn{background:none;border:0;color:var(--dim);padding:6px 4px;font-size:12.5px}
  .fk-onebox .fk-ff-box .fk-btn:hover,.fk-dsgrid .fk-ff-box .fk-btn:hover{color:var(--white)}
  /* Design: the rail beside the box — the fine full-height line with a hollow circle at each step, kept from the old panel */
  .fk-dsgrid{display:grid;grid-template-columns:172px 1fr;column-gap:18px;row-gap:0;position:relative;margin-bottom:12px}
  .fk-dsgrid::before{content:"";position:absolute;left:5px;top:14px;bottom:16px;width:1px;background:var(--line2)}
  .fk-dsr{position:relative;padding:4px 0 14px 20px;min-width:0}
  .fk-dsr i{position:absolute;left:0;top:7px;width:11px;height:11px;border-radius:50%;border:1.5px solid var(--faint);background:var(--panel);z-index:1}
  .fk-dsr.done i{border-color:var(--ok)}
  .fk-dsr.here i{border-color:var(--st-artwork,var(--accent))}
  .fk-dsr b{display:block;font-size:13px;font-weight:700;color:var(--white);line-height:1.3}
  .fk-dsr span{display:block;font-size:11.5px;color:var(--faint);margin-top:2px;line-height:1.35}
  .fk-dsr em{display:block;font-style:normal;font-size:11.5px;font-weight:600;color:var(--dim);margin-top:5px}
  .fk-dsr em.ok{color:var(--ok)}
  .fk-dsr em.wait{color:var(--warn)}
  .fk-dsgrid .fk-obx{background:var(--panel2);border-left:1px solid var(--line2);border-right:1px solid var(--line2)}
  .fk-dsgrid .fk-obx.first{border-top:1px solid var(--line2);border-radius:14px 14px 0 0;display:flex;align-items:center;padding:12px 20px}
  .fk-dsgrid .fk-obx.mid{border-top:1px solid var(--line)}
  .fk-dsgrid .fk-obx.last{border-bottom:1px solid var(--line2);border-radius:0 0 14px 14px}
  /* the bottom of the Design box is three stacked things now — the state line, what came back from an internal
     check, and the question — and this is a TWO-COLUMN grid, so they travel as one child or the last of them
     lands in the step rail. The wrapper carries the box's bottom edge; the foot inside gives its own up. */
  .fk-dsgrid .fk-ds3{min-width:0;background:var(--panel2);border:1px solid var(--line2);border-top:0;border-radius:0 0 14px 14px;overflow:hidden}
  .fk-dsgrid .fk-ds3 .fk-obx.last{border-left:0;border-right:0;border-bottom:0;border-radius:0}
  .fk-reqline{font-size:12.5px;color:var(--dim)}
  .fk-reqline b{color:var(--white);font-weight:600}
  .fk-obchecks{margin-top:10px}
  .fk-obflip{margin-top:10px;font-size:12.5px;color:var(--dim)}
  .fk-obflip b{color:var(--white)}
  /* the timeline node: the current node's empty ring wears the stage's own colour; the assign link; a clickable face */
  .fk-tl-node.here .tl-ow.none .fk-avatar.unassigned{border-color:var(--nc,var(--faint))}
  .fk-tl-node .tl-state.none{color:var(--faint);font-weight:500}
  .tl-assign{font-size:11.5px;font-weight:700;color:var(--accent-ink,var(--accent));background:none;border:0;padding:0;cursor:pointer;font-family:inherit;text-decoration:underline;text-decoration-style:dotted;text-underline-offset:3px}
  .fk-tl-node .tl-ow.can{cursor:pointer}
  .fk-assignpick{position:absolute;top:100%;left:50%;transform:translateX(-50%);margin-top:4px;width:232px;background:var(--panel3);border:1px solid var(--line2);border-radius:12px;padding:6px;box-shadow:0 18px 40px rgba(0,0,0,.45);z-index:30;text-align:left}
  .fk-assignpick .t{font-size:11px;color:var(--faint);font-weight:600;padding:6px 8px 4px}
  .fk-assignpick .row{display:flex;align-items:center;gap:9px;width:100%;padding:7px 8px;border-radius:8px;color:var(--white);font-size:13px;cursor:pointer;background:none;border:0;font-family:inherit;text-align:left}
  .fk-assignpick .row:hover,.fk-assignpick .row.on{background:rgba(255,255,255,.08)}
  /* somebody Future Knights cannot reach (owner 2026-10-01): listed, greyed, the sentence under the name, nothing to press */
  .fk-assignpick .row.nt{flex-wrap:wrap;row-gap:2px;cursor:not-allowed}
  .fk-assignpick .row.nt:hover{background:none}
  .fk-assignpick .row.nt .fk-avatar{opacity:.62}
  .fk-assignpick .row.nt .nm{flex:1;min-width:0;opacity:.62}
  /* the sentence is the point: full strength and the body-text colour — a fade on the whole row left it at about 2.4:1 */
  .fk-assignpick .row.nt .why{flex:1 0 calc(100% - 33px);margin-left:33px;font-size:11px;line-height:1.35;color:var(--text);text-align:left}
  /* THE PRODUCTION TEAM (owner 2026-09-17, mock docs/prototype/fk-production-team-mock.html): several faces on the
     In Production node, the tick-box picker, and the stacked faces in the panel header, card and list */
  .fk-assignpick.team{width:260px}
  .fk-assignpick .row .tk{width:16px;height:16px;border-radius:5px;border:1.5px solid var(--faint);flex:none;display:grid;place-items:center}
  .fk-assignpick .row.on .tk{background:var(--ok);border-color:var(--ok)}
  .fk-assignpick .row.on .tk::after{content:'✓';color:#04241a;font-size:11px;font-weight:800;line-height:1}
  .fk-assignpick .ft{display:flex;align-items:center;justify-content:space-between;gap:8px;border-top:1px solid var(--line2);margin-top:6px;padding:8px 4px 2px}
  .fk-assignpick .ft .clr{font-size:12px;color:var(--dim);background:none;border:0;padding:0;cursor:pointer;font-family:inherit;text-align:left}
  .fk-tl-node .tl-faces{display:flex;justify-content:center}
  .fk-tl-node .tl-f{position:relative;border-radius:50%;flex:none}
  .fk-tl-node .tl-f + .tl-f{margin-left:-22px}
  .fk-tl-node .tl-f .fk-avatar{box-shadow:0 0 0 3px var(--panel)}
  .fk-tl-node .tl-f.on .fk-avatar{box-shadow:0 0 0 2px var(--panel),0 0 0 4px var(--ok)}
  .fk-tl-node .tl-f.wait .fk-avatar{outline:2px dashed var(--warn);outline-offset:2px}
  .fk-tl-node .tl-f .tl-tick{position:absolute;right:-2px;bottom:0;width:22px;height:22px;border-radius:50%;background:var(--ok);border:2px solid var(--panel);color:#04241a;font-size:12px;font-weight:800;font-style:normal;display:grid;place-items:center;line-height:1;z-index:2}
  .fk-tl-node .tl-f .tl-more{background:var(--panel3);color:var(--white);font-size:18px;border:1px solid var(--line2)}
  .fk-tl-node .tl-teamst .on{color:var(--ok)}
  .fk-tl-node .tl-teamst .wait{color:var(--warn)}
  .fk-whofaces{display:inline-flex;align-items:center;flex:none}
  .fk-whofaces .fk-avatar{box-shadow:0 0 0 2px var(--panel2)}
  .fk-whofaces .fk-avatar + .fk-avatar{margin-left:-8px}
  .fk-card .fk-cardfoot .fk-whofaces .fk-avatar + .fk-avatar{margin-left:-4px}   /* 18px card faces: -8px hid the initials (screenshot 2026-09-17) */
  .fk-card .fk-cardfoot .fk-whofaces .fk-avatar{box-shadow:0 0 0 1.5px var(--panel)}
  .fk-assignpick .row .fk-avatar{width:24px;height:24px;font-size:10px;flex:none}
  /* the order box's lower half: brief, files, notes — set apart from the customer and the lines above */
  /* a sunk strip: 18% black reads as a shade on a dark drawer and as a GREY SLAB on Marine's light one (owner
     2026-09-29), so the fill is each theme's --fk-sunk — a faint tint in the light block, the old shade on the dark */
  .fk-orderhalf{background:var(--fk-sunk,rgba(0,0,0,.18));border-top:1px solid var(--line2);padding:6px 18px 4px}
  .fk-orderhalf .oh-l{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);padding:10px 0 6px}
  .fk-orderhalf .oh-row{display:grid;grid-template-columns:150px 1fr;gap:12px;align-items:start;padding:12px 0 14px;border-top:1px solid var(--line)}
  .fk-orderhalf .oh-row:first-of-type{border-top:0}
  .fk-orderhalf .k{font-size:12.5px;color:var(--dim);font-weight:600;padding-top:1px}
  .fk-orderhalf .k small{display:block;font-weight:500;color:var(--faint);font-size:11.5px;margin-top:2px}
  .fk-orderhalf .v{font-size:13.5px;color:var(--text);line-height:1.5;min-width:0}
  .fk-orderhalf .v.pre{white-space:pre-line}
  .fk-orderhalf textarea.fk-brief{margin:0;min-height:44px}
  .fk-orderhalf .oh-up{margin-top:8px}
  .fk-orderhalf .fk-thumbgrid{margin:0}
  @media (max-width:760px){
    .fk-dsgrid{grid-template-columns:minmax(0,1fr)}
    .fk-dsgrid::before{display:none}
    .fk-orderhalf .oh-row{grid-template-columns:minmax(0,1fr);gap:4px}
  }
  /* ═══ CUSTOMER SUPPLIED CHECK + UPLOAD ROWS (owner 2026-10-08; mock docs/prototype/fk-supplied-check/index.html — the mock is the contract) ═══
     Every class here is .fk-sc-* (the box on the Design panel, public/fksupplied.js) or .fk-up-* (the rows every drawer upload button draws, public/fkupload.js).
     The mock's own bare .box .tag .fact .up .spin .bar .ck .who .link .sec are NOT reused: suite.css already owns .who and others unscoped, and a bare class
     is how the Job Board broke while 3,495 tests stayed green (CLAUDE.md, "Things that bite"). Theme tokens only. Inputs get margin:0 against the global
     input{margin-bottom:16px}. */
  .fk-obx.fk-sc-mid{padding:0}
  .fk-sc-sec{padding:16px 20px;min-width:0}
  .fk-sc-sec + .fk-sc-sec{border-top:1px solid var(--line2)}
  .fk-sc-head{display:flex;align-items:center;gap:10px;margin:0 0 12px}
  .fk-sc-head h5{margin:0;font-size:12px;letter-spacing:.07em;text-transform:uppercase;color:var(--faint);font-weight:700}
  .fk-sc-r{margin-left:auto;display:flex;gap:6px}
  .fk-btn.sm.fk-sc-ghost{background:none;border-color:transparent;color:var(--dim);padding:0 6px}
  .fk-btn.sm.fk-sc-ghost:hover{color:var(--white)}
  .fk-sc-count{font-size:12px;font-weight:700;color:var(--warn)}
  .fk-sc-count.all{color:var(--ok)}
  .fk-sc-optag{font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--faint);border:1px solid var(--line2);border-radius:5px;padding:2px 7px}
  /* the customer's files, one card each */
  .fk-sc-card{display:grid;grid-template-columns:96px minmax(0,1fr) auto;gap:16px;align-items:center;padding:12px 14px;border:1px solid var(--line2);border-radius:10px;background:var(--panel)}
  .fk-sc-card + .fk-sc-card{margin-top:8px}
  .fk-sc-card.main{border-color:color-mix(in srgb,var(--accent) 55%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 25%,transparent) inset;background:linear-gradient(0deg,color-mix(in srgb,var(--accent) 5%,transparent),color-mix(in srgb,var(--accent) 5%,transparent)),var(--panel)}
  .fk-sc-card.off{opacity:.78}
  .fk-sc-card .fk-sc-thumb{width:96px;height:68px;border-radius:7px}
  .fk-sc-meta{min-width:0}
  .fk-sc-n{color:var(--white);font-weight:700;font-size:13.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .fk-sc-s{color:var(--faint);font-size:12px;margin-top:2px}
  .fk-sc-star{display:inline-grid;place-items:center;width:18px;height:18px;border-radius:50%;background:var(--accent);color:var(--on-accent);font-size:11px;font-weight:900;margin-right:6px;vertical-align:-3px}
  .fk-sc-facts{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
  .fk-sc-fact{display:inline-flex;align-items:center;gap:5px;min-height:22px;padding:0 8px;border-radius:6px;font-size:11.5px;font-weight:600;background:var(--panel3);color:var(--text)}
  .fk-sc-fact.ok{color:var(--ok-ink,var(--ok));background:color-mix(in srgb,var(--ok) 10%,transparent)}
  .fk-sc-fact.warn{color:var(--warn);background:color-mix(in srgb,var(--warn) 11%,transparent)}
  .fk-sc-fact.unknown{color:var(--dim)}
  .fk-sc-meta .fk-chk{margin-top:8px}
  .fk-sc-side{display:flex;flex-direction:column;align-items:flex-end;gap:8px}
  .fk-sc-tag{font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;padding:3px 8px;border-radius:5px;background:color-mix(in srgb,var(--accent) 16%,transparent);color:var(--accent-ink,var(--accent))}
  .fk-sc-mk{display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 12px;border-radius:7px;border:1px dashed color-mix(in srgb,var(--accent) 55%,transparent);background:none;color:var(--accent-ink,var(--accent));font-family:inherit;font-size:12px;font-weight:700;cursor:pointer;white-space:nowrap}
  .fk-sc-mk:hover{background:var(--accent-soft,color-mix(in srgb,var(--accent) 13%,transparent))}
  .fk-sc-unmk{background:none;border:0;padding:0;color:var(--faint);font-family:inherit;font-size:11.5px;font-weight:600;cursor:pointer;text-decoration:underline;text-underline-offset:3px}
  .fk-sc-unmk:hover{color:var(--white)}
  .fk-sc-for{display:inline-flex;align-items:center;gap:6px;height:28px;padding:0 10px;border:1px solid var(--line2);border-radius:7px;background:var(--panel2);color:var(--text);font-family:inherit;font-size:12px;cursor:pointer;max-width:240px;overflow:hidden;white-space:nowrap}
  .fk-sc-for b{color:var(--white);font-weight:600;overflow:hidden;text-overflow:ellipsis}
  .fk-sc-for:not([disabled])::after{content:"▾";color:var(--faint);font-size:10px}
  .fk-sc-for[disabled]{cursor:default}
  .fk-sc-ibs{display:flex;gap:4px}
  .fk-sc-ib{width:30px;height:30px;display:grid;place-items:center;border-radius:7px;border:1px solid var(--line2);background:var(--panel2);color:var(--dim);font-size:13px;text-decoration:none}
  .fk-sc-ib:hover{color:var(--white);border-color:var(--accent)}
  .fk-sc-replaces{color:var(--dim)}
  .fk-sc-empty{display:block;width:100%;padding:18px;border:1.5px dashed var(--line2);border-radius:10px;background:none;color:var(--dim);font-family:inherit;font-size:13px;font-weight:600;cursor:pointer;text-align:center}
  .fk-sc-empty:hover{border-color:var(--accent);color:var(--white)}
  /* the checks, as big rows */
  .fk-sc-ckgrid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .fk-sc-ck{display:flex;align-items:center;gap:12px;padding:12px 14px;border:1px solid var(--line2);border-radius:10px;background:var(--panel);color:var(--text);font-weight:600;cursor:pointer;min-width:0}
  .fk-sc-ck.on{border-color:color-mix(in srgb,var(--ok) 45%,transparent);background:color-mix(in srgb,var(--ok) 7%,transparent);color:var(--white)}
  .fk-sc-ck small{display:block;color:var(--faint);font-weight:500;font-size:11.5px;margin-top:1px}
  .fk-sc-ck input.fk-pfck{appearance:none;-webkit-appearance:none;flex:none;width:20px;height:20px;border-radius:5px;border:2px solid var(--faint);background:transparent;margin:0;display:grid;place-items:center;cursor:pointer}
  .fk-sc-ck input.fk-pfck:checked{background:var(--ok);border-color:var(--ok)}
  .fk-sc-ck input.fk-pfck:checked::after{content:"✓";color:#04241a;font-size:13px;font-weight:900;line-height:1}
  .fk-sc-ck input.fk-pfck:disabled{cursor:default}
  /* the customer proof */
  .fk-sc-popts{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .fk-sc-popts .fk-sc-pfile{grid-column:1/-1}
  .fk-sc-popt{display:flex;align-items:center;gap:12px;padding:12px 14px;border:1px solid var(--line2);border-radius:10px;background:var(--panel);color:var(--white);font-family:inherit;font-size:13px;font-weight:700;text-align:left;cursor:pointer}
  .fk-sc-popt:hover{border-color:var(--accent)}
  .fk-sc-popt small{display:block;color:var(--faint);font-weight:500;font-size:11.5px;margin-top:1px}
  .fk-sc-pic{flex:none;width:32px;height:32px;border-radius:8px;background:var(--panel3);display:grid;place-items:center;font-size:15px}
  .fk-sc-pstate{display:flex;align-items:center;gap:12px;padding:12px 14px;border-radius:10px;border:1px solid var(--line2);background:var(--panel)}
  .fk-sc-pstate + .fk-sc-pstate,.fk-sc-popts + .fk-sc-pstate,.fk-sc-pstate + .fk-sc-popts,.fk-sc-popts + .fk-sc-popts{margin-top:8px}
  .fk-sc-pm{min-width:0}
  .fk-sc-pm b{color:var(--white)}
  .fk-sc-pfile{color:var(--faint);font-size:11.5px;font-weight:700;margin-bottom:2px}
  .fk-sc-ps{color:var(--dim);font-size:12px;margin-top:1px}
  .fk-sc-pstate.ok{border-color:color-mix(in srgb,var(--ok) 45%,transparent);background:color-mix(in srgb,var(--ok) 6%,transparent)}
  .fk-sc-pstate.ok .fk-sc-pic{background:color-mix(in srgb,var(--ok) 15%,transparent)}
  .fk-sc-pstate.chg{border-color:color-mix(in srgb,var(--warn) 45%,transparent);background:color-mix(in srgb,var(--warn) 6%,transparent)}
  .fk-sc-pstate.chg .fk-sc-pic{background:color-mix(in srgb,var(--warn) 14%,transparent)}
  .fk-sc-pr{margin-left:auto;display:flex;gap:8px;flex:none}
  /* the quieter "other ways" row */
  .fk-sc-sec.fk-sc-quiet{padding-top:12px;padding-bottom:12px}
  .fk-sc-alt{display:flex;flex-wrap:wrap;align-items:center;gap:8px 18px;color:var(--dim);font-size:12.5px}
  .fk-sc-sep{width:1px;height:16px;background:var(--line2)}
  .fk-sc-link{background:none;border:0;color:var(--text);text-decoration:underline;text-decoration-color:var(--faint);text-underline-offset:3px;font:inherit;font-family:inherit;cursor:pointer;padding:0}
  .fk-sc-link:hover{color:var(--white)}
  .fk-sc-missing{color:var(--warn)}
  .fk-obfoot.fk-sc-warn .q{color:var(--warn)}
  /* the dialogs (in #fk-modal) */
  .fk-sc-dlg h3{margin:0 0 8px}
  .fk-sc-dlg p{margin:0 0 6px;color:var(--text);font-size:13px}
  .fk-sc-dmeta{color:var(--faint);font-size:12px;margin:10px 0 16px}
  .fk-sc-dlg .actions{display:flex;justify-content:flex-end;gap:8px;flex-wrap:wrap}
  .fk-btn.fk-sc-warnb{background:var(--warn);border-color:var(--warn);color:#2a1a00;font-weight:700}
  .fk-sc-items{display:flex;flex-direction:column;gap:8px;margin-bottom:6px}
  .fk-sc-itemopt{display:block;text-align:left;padding:11px 14px;border:1px solid var(--line2);border-radius:10px;background:var(--panel);color:var(--text);font-family:inherit;font-size:13px;cursor:pointer}
  .fk-sc-itemopt:hover{border-color:var(--accent)}
  .fk-sc-itemopt b{color:var(--white);font-weight:700}
  .fk-sc-itemopt small{display:block;color:var(--faint);font-size:11.5px;margin-top:1px}
  /* UPLOAD ROWS — every upload button in the order drawer (public/fkupload.js) */
  .fk-up-host:empty{display:none}
  .fk-up-host{margin:0 0 10px}
  .fk-up-row{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:12px;align-items:center;padding:12px 14px;border:1px solid color-mix(in srgb,var(--accent) 40%,transparent);border-radius:10px;background:color-mix(in srgb,var(--accent) 5%,transparent);transition:opacity .35s}
  .fk-up-row + .fk-up-row{margin-top:8px}
  .fk-up-row.wait{border-color:var(--line2);background:var(--panel2)}
  .fk-up-row.done{border-color:color-mix(in srgb,var(--ok) 45%,transparent);background:color-mix(in srgb,var(--ok) 6%,transparent)}
  .fk-up-row.bad{border-color:color-mix(in srgb,var(--danger) 50%,transparent);background:color-mix(in srgb,var(--danger) 7%,transparent)}
  .fk-up-row.fade{opacity:0}
  .fk-up-n{color:var(--white);font-weight:600;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .fk-up-s{color:var(--dim);font-size:12px;margin-top:1px}
  .fk-up-row.bad .fk-up-s{color:var(--danger-ink,var(--danger))}
  .fk-up-bar{height:5px;border-radius:3px;background:var(--panel3);margin-top:8px;overflow:hidden}
  .fk-up-bar i{display:block;height:100%;background:var(--accent);border-radius:3px;transition:width .2s}
  .fk-up-pc{color:var(--accent-ink,var(--accent));font-weight:800;font-variant-numeric:tabular-nums;font-size:13px}
  .fk-up-pc.ok{color:var(--ok)}
  .fk-up-pc.dim{color:var(--faint)}
  .fk-up-spin{flex:none;width:20px;height:20px;border-radius:50%;border:2.5px solid color-mix(in srgb,var(--accent) 25%,transparent);border-top-color:var(--accent);animation:fk-up-spin .8s linear infinite}
  .fk-up-spin.still{animation:none;border-color:var(--line2)}
  .fk-up-spin.sm{display:inline-block;width:14px;height:14px;border-width:2px;vertical-align:-2px}
  .fk-up-okic,.fk-up-badic{width:20px;height:20px;border-radius:50%;display:grid;place-items:center;font-weight:900;font-size:12px}
  .fk-up-okic{background:var(--ok);color:#04241a}
  .fk-up-badic{background:var(--danger);color:#2a0806}
  .fk-up-acts{display:flex;align-items:center;gap:6px}
  .fk-up-x{width:26px;height:26px;border-radius:6px;border:0;background:none;color:var(--dim);cursor:pointer;font-size:13px;padding:0}
  .fk-up-x:hover{color:var(--white);background:var(--panel3)}
  .fk-btn.sm.fk-sc-ghost.fk-up-busy,.fk-btn.fk-up-busy{color:var(--accent-ink,var(--accent));border-color:color-mix(in srgb,var(--accent) 45%,transparent);opacity:1}   /* busy is disabled too: .fk-btn:disabled must not fade it */
  @keyframes fk-up-spin{to{transform:rotate(360deg)}}
  @media (prefers-reduced-motion: reduce){ .fk-up-spin{animation-duration:2.4s} .fk-up-row{transition:none} }
  @media (max-width:900px){
    .fk-sc-ckgrid,.fk-sc-popts{grid-template-columns:1fr}
    .fk-sc-card{grid-template-columns:72px minmax(0,1fr)}
    .fk-sc-card .fk-sc-thumb{width:72px;height:52px}
    .fk-sc-side{grid-column:1/-1;flex-direction:row;justify-content:space-between;align-items:center;flex-wrap:wrap}
    .fk-sc-pstate{flex-wrap:wrap}
    .fk-sc-pr{margin-left:0}
  }
