/* =============================================================================
   THE ARENA: THE SYSTEM
   One stylesheet, loaded by every page. Tokens, base, the component kit, the
   app shell, and the Client-First v2 utility layer.

   HOUSE TYPE: Schibsted Grotesk, one family separated by weight, with Azeret
   Mono only for what a machine produced (an ID, a sha, a code, a column of
   figures). Set by the Type Styling rules (rules/type-styling.md): 15 to read,
   13 the floor, labels in sentence case. Load it in the page head:

     <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=
       Schibsted+Grotesk:wght@400;500;600;700;800&family=Azeret+Mono:wght@400;500;600&family=Roboto+Condensed:wght@400..700&display=swap">
     <link rel="stylesheet" href="elevance.css">

   MATERIAL: one black body, every control cut from it. Raised = a hairline top
   edge, a tight cast, a faint bounce. Sunken = the same light inverted. Never
   both on one element. Colour is spent on: the seafoam mark and primary action,
   one destination diamond, Chat, Advise, and the readout. Nothing else.

   NAMING: custom classes are component_element-descriptor; variants always
   combine and never stand alone; utilities do one job and carry no underscore;
   @layer decides override order, never source order or a specificity fight.
   ============================================================================= */
@layer tokens, base, components, utilities;

/* CROSS-DOCUMENT VIEW TRANSITIONS. Every navigation is a real page load, so
   without this the whole frame is thrown away and redrawn — the jitter. Naming
   the rail, the head and the blueprint tells the browser they are the SAME
   elements either side of the navigation, so they hold still while the body
   crossfades. */
/* NO VIEW TRANSITIONS.
   They were added to stop the frame flickering between page loads. They did not
   fix that — the flicker was the blueprint restarting, which the negative
   animation-delay below actually fixes — and they introduced a worse one: a
   cross-document transition cross-fades the two pages, so BOTH are briefly
   semi-transparent. That is the translucency on every click.
   Removing them costs nothing. The rail and the head are identical either side
   of a navigation, and the browser only paints the new page once it is ready,
   so the frame does not move; the grid keeps its phase through the delay. If
   they come back one day, they come back with every default animation disabled
   and tested on a slow connection, not on localhost. */

@property --advise-sweep { syntax:'<angle>'; initial-value:0turn; inherits:false; }
@keyframes adviseSweep { to { --advise-sweep:1turn; } }
/* The grounds' motions. A drift moves a whole number of its tile (512px leather, the
   120px heavy grid), so it lands on itself; the light's first and last frames match,
   and the sweep and the sway go there and back. Every loop, at every speed, divides the 720s phase clock in
   Shell.tsx. Transform, not background-position: composited, so none costs a
   repaint or can stutter. */
@keyframes blueprintDrift { to { transform: translate3d(-512px, 512px, 0); } }
@keyframes blueprintGrid  { to { transform: translate3d(-360px, 240px, 0); } }
@keyframes blueprintLight {
  0%,100% { transform: translate3d(-18%, -12%, 0); }
  33%     { transform: translate3d(16%, -14%, 0); }
  66%     { transform: translate3d(14%, 14%, 0); }
}
@keyframes blueprintSweep { from { transform: translate3d(-38%, 0, 0); } to { transform: translate3d(38%, 0, 0); } }
@keyframes blueprintSway {
  from { transform: translate3d(-2.5%, -1.5%, 0) rotate(-1.2deg); }
  to   { transform: translate3d(2.5%, 1.5%, 0) rotate(1.2deg); }
}

/* the HIS logo's own face, for The Arena's name on the rail (quote.css loads the same file) */
@font-face { font-family: 'HIS Montserrat'; src: url('/fonts/his-montserrat.woff2') format('woff2'); font-weight: 500 900; font-display: swap; }

/* ============================== TOKENS ============================== */
@layer tokens {
  :root{
    /* ground — console finish, the house finish */
    /* surfaces sit visibly above the field: near-black on black lost its edges on dim screens.
       Lifted again 2026-10-12, by tone and not by line: on a laptop or a showroom screen, room
       light on the glass lifts black, and steps of 3 to 18% (a well on the ground, a card on the
       ground, a tile on a card) ran together into one grey. Every step is now 12 to 40% under that
       light, the same hue. The well (--cut) sits between the ground and the card, not below the
       ground: nothing is darker than the ground, so a well set straight on it vanished. */
    --field:#04080A; --body:#162024; --face:#222E32; --face-2:#2A383C; --face-3:#334247; --cut:#0B1214;

    /* ink — raised deliberately: medium grey body text on dark is both a
       contrast failure and one of the generated-design tells */
    --ink:#F1F5F4; --ink-2:#D3DBD9; --ink-3:#AAB5B3; --ink-label:#B0BBB8;

    /* hue: the Arena's palette */
    --mint:#00FFA3;     /* the brand mark and the one loud action */
    --his-seafoam:#66BB9A; /* STRATEGIES in the HIS logo, and The Arena's line under it */
    --lime:#A3E635;     /* Chat, positive */
    --cobalt:#4C7DFF;   /* the knowledge faculty, and the light on Advise */
    --sapphire:#0F52BA; /* Advise's fill — cobalt at full pill size reads periwinkle */
    --amber:#FFA300;    /* Quote, warning */
    --cyan:#00DCFF;     /* Board, in progress */
    --violet:#A300FF;   /* Marketing */
    --pink:#FF005C;     /* wrong: overdue, blocked, failed */
    --slate:#8494A3;    /* utility pages, which get no hue */

    /* the bevel */
    /* every raised and sunk surface carries a hairline ring (--line), so a box keeps its
       outline on any screen instead of relying on a shadow the dark swallows. It went in
       at .12, which read as a drawn border and flattened the material — the boxes looked
       outlined rather than cut from the body. A quarter of that still holds the edge on a
       dim screen and lets the bevel do the work again. Raise it and the finish goes flat. */
    --line: rgba(255,255,255,.03);
    --edge: inset 0 0 0 1px var(--line), inset 0 1px 0 rgba(255,255,255,.06), inset 0 -1px 0 rgba(0,0,0,.6);
    --up:   var(--edge), 3px 5px 14px rgba(0,0,0,.7), -1px -1px 5px rgba(255,255,255,.014);
    --up-lg:var(--edge), 6px 9px 26px rgba(0,0,0,.8), -2px -2px 9px rgba(255,255,255,.016);
    --in:   inset 0 0 0 1px var(--line), inset 3px 5px 12px rgba(0,0,0,.75), inset -1px -1px 3px rgba(255,255,255,.03);
    --press:inset 0 0 0 1px var(--line), inset 3px 5px 13px rgba(0,0,0,.8), inset -1px -1px 3px rgba(255,255,255,.02);

    --radius:12px; --radius-small:8px; --radius-key:9px; --radius-round:100px;

    /* type */
    --font-display:'Schibsted Grotesk',ui-sans-serif,system-ui,sans-serif;
    --font-ui:'Schibsted Grotesk',ui-sans-serif,system-ui,sans-serif;
    --font-mono:'Azeret Mono','IBM Plex Mono',ui-monospace,monospace;
    --mono-tight:-.02em;
    /* the small secondary line (.meta): condensed and tight, so an address and a date sit on one clean line */
    /* the secondary line and a task's title read in the UI face: condensed to fit was a squeeze (Type Styling, rule 5) */
    --font-meta:var(--font-ui);
    --font-task:var(--font-ui);
    --t-task:15px; --w-task:560;   /* a task title reads at body size, a weight above the line under it */

    /* the scale (Admin > Branding > The Arena > Type Styling, 2026-10-19): anything read is 15, 13 is the floor,
       controls 14. --t-small reads at body size now; --t-meta and --t-label are the 13px floor, in sentence case */
    --t-display:44px; --t-page:28px; --t-stat:30px; --t-title:19px;
    --t-body:15px; --t-small:15px; --t-control:14px; --t-meta:13px; --t-label:13px;
    --lead-tight:1.12; --lead-body:1.55;
    --track-display:-.035em; --track-page:-.025em; --track-title:0em; --track-label:0em;

    /* Client-First spacing ladder, retuned for a dense tool (CF medium is 2rem) */
    --space-0:0px;        --space-tiny:2px;    --space-xxsmall:4px; --space-xsmall:8px;
    --space-small:12px;   --space-medium:22px; --space-large:34px;  --space-xlarge:52px;
    --space-xxlarge:72px; --space-huge:96px;   --space-xhuge:128px;
    --container-large:1160px; --container-medium:880px; --container-small:600px;
    --padding-global:22px;

    /* frame */
    --rail-width:212px; --ctl:34px;
    --hue:var(--mint);  /* the destination you are standing in */
  }
  :root[data-rail="icons"]{ --rail-width:66px; }
  /* THE DESTINATION HUE COMES FROM THE SERVER.
     <html data-hue="pink"> is printed in the response, so the hue is correct in
     the first painted frame. The demo set this with JavaScript after load, which
     server-rendered would flash the wrong colour for a frame. It is the door's own
     hue from the manifest, the same one its rail icon wears, or a super admin's
     colour for it (shell/tweaks.ts), so the page and its rail row always agree. */
  :root[data-hue="mint"]{--hue:var(--mint)} :root[data-hue="amber"]{--hue:var(--amber)} :root[data-hue="pink"]{--hue:var(--pink)}
  :root[data-hue="cyan"]{--hue:var(--cyan)} :root[data-hue="violet"]{--hue:var(--violet)} :root[data-hue="lime"]{--hue:var(--lime)}
  :root[data-hue="cobalt"]{--hue:var(--cobalt)} :root[data-hue="slate"]{--hue:var(--slate)}

  /* the four alternates, kept so the specimen page can compare them */
  :root[data-type="cabinet"]{--font-display:'Cabinet Grotesk',sans-serif;--font-ui:'General Sans',sans-serif;--font-mono:'Martian Mono',monospace;--mono-tight:-.04em}
  :root[data-type="clash"]{--font-display:'Clash Grotesk',sans-serif;--font-ui:'Switzer',sans-serif;--font-mono:'Spline Sans Mono',monospace;--mono-tight:0em}
  :root[data-type="familjen"]{--font-display:'Familjen Grotesk',sans-serif;--font-ui:'Chivo',sans-serif;--font-mono:'IBM Plex Mono',monospace;--mono-tight:0em}
  :root[data-type="geologica"]{--font-display:'Geologica',sans-serif;--font-ui:'Supreme',sans-serif;--font-mono:'Martian Mono',monospace;--mono-tight:-.04em}

  /* LIGHT (Appearance in Settings, 2026-10-16): the same ladder in pale grey-green, the same
     hue as the dark one. Not white: a card is a soft grey, a tile lighter, a key the only white.
     Each step clears 12% under room light (lint:tone-steps reads this block too). Going up the
     ladder is lighter, so a key's hover (--face-3) steps back down. The hues deepen so they read
     as text on a pale card; a fill that carried dark text carries white instead (LIGHT, below). */
  :root{color-scheme:dark}
  /* Paper is never dark: a dark scheme paints a sheet's margins #121212, a black frame round every white page of a PDF. */
  @media print{:root{color-scheme:light}}
  :root[data-theme="light"]{color-scheme:light;
    --field:#AEB9B6; --body:#D9E0DE; --face:#EBF0EE; --face-2:#FFFFFF; --face-3:#E6ECEA; --cut:#C3CCC9;
    --ink:#0C1513; --ink-2:#25322F; --ink-3:#4A5854; --ink-label:#4E5C58;
    --mint:#007A52; --his-seafoam:#267A5B; --lime:#4D7C0F; --cobalt:#2F5FE0; --sapphire:#0F52BA;
    --amber:#A35F00; --cyan:#00768F; --violet:#8A00D6; --pink:#D6004C; --slate:#5B6B7A;
    --line: rgba(0,0,0,.05);
    --edge: inset 0 0 0 1px var(--line), inset 0 1px 0 rgba(255,255,255,.7), inset 0 -1px 0 rgba(0,0,0,.08);
    --up:   var(--edge), 2px 4px 10px rgba(20,40,34,.16), -1px -1px 4px rgba(255,255,255,.4);
    --up-lg:var(--edge), 4px 8px 22px rgba(20,40,34,.2), -2px -2px 8px rgba(255,255,255,.4);
    --in:   inset 0 0 0 1px var(--line), inset 2px 3px 7px rgba(20,40,34,.18), inset -1px -1px 2px rgba(255,255,255,.6);
    --press:inset 0 0 0 1px var(--line), inset 2px 3px 8px rgba(20,40,34,.22), inset -1px -1px 2px rgba(255,255,255,.5)}
}

/* =============================== BASE =============================== */
@layer base {
  *,*::before,*::after{box-sizing:border-box}
  html,body{height:100%}
  body{margin:0;background:var(--field);color:var(--ink);
       font:400 var(--t-body)/var(--lead-body) var(--font-ui);-webkit-font-smoothing:antialiased}
  h1,h2,h3,h4{margin:0;font-family:var(--font-display);font-weight:700;line-height:var(--lead-tight);text-wrap:balance}
  p{margin:0}
  a{color:inherit;text-decoration:none}
  button{font:inherit;color:inherit;border:0;background:none;cursor:pointer}
  input,select,textarea{font:inherit;color:inherit}
  svg{display:block}
  :focus-visible{outline:1.5px solid var(--mint);outline-offset:3px;border-radius:3px}
  ::selection{background:color-mix(in srgb,var(--mint) 22%,transparent)}
  /* A popover is display:none until it is open, and that rule lives in the UA
     sheet — which ANY author `display:` on the same element silently beats. That
     is how a panel ends up painted at 0,0 forever, looking like a menu that will
     not close. Restate it here, in the author sheet, where it wins. */
  [popover]{margin:0;border:0;padding:0;background:none;color:inherit;overflow:visible}
  [popover]:not(:popover-open){display:none}
}

/* ============================ COMPONENTS ============================ */
@layer components {

  /* ---------------- buttons ---------------- */
  .button{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-xsmall);
    height:var(--ctl);padding:0 14px;border-radius:var(--radius-key);
    background:var(--face);box-shadow:var(--up);
    font:600 var(--t-control)/1 var(--font-ui);color:var(--ink-2);white-space:nowrap;
    transition:color .12s,box-shadow .12s,background-color .12s}
  .button:hover{color:var(--ink);background-color:var(--face-2)}
  /* a key on a raised card (a board card, an API row, an issue) stands a step above the card it is on */
  :where(.board_card,.api_row,.strategy_issue) .button:not(.is-chat,.is-advise,.is-text){background-color:var(--face-2)}
  :where(.board_card,.api_row,.strategy_issue) .button:not(.is-chat,.is-advise,.is-text):hover{background-color:var(--face-3)}
  .button:active,.button.is-active{box-shadow:var(--press);color:var(--ink)}
  .button:disabled{opacity:.4;cursor:not-allowed;box-shadow:var(--in)}
  .button.is-small{height:30px;padding:0 11px;font-size:var(--t-meta)}
  .button.is-large{height:40px;padding:0 18px;font-size:var(--t-body)}
  .button.is-icon{width:var(--ctl);padding:0}
  .button.is-text{box-shadow:none}
  .button.is-text:hover{box-shadow:var(--up)}
  .button.is-danger{color:var(--pink)}
  .button.is-secondary{color:var(--ink-3)}
  .button.is-secondary:hover{color:var(--ink-2)}
  .button.is-primary{color:var(--mint)}
  .button.is-primary::before{content:"";width:5px;height:5px;transform:rotate(45deg);background:var(--mint)}
  .button_ico{width:15px;height:15px;flex:none}

  /* Chat and Advise are the two LIT keys on an otherwise black deck: a flat
     100%-saturated fill on something small, never a gradient, never a tint. */
  .button.is-chat{background:var(--lime);color:#0D1B02;
    box-shadow:inset 0 1px 0 rgba(255,255,255,.38),inset 0 -1px 0 rgba(0,0,0,.34),0 2px 8px rgba(0,0,0,.55)}
  .button.is-chat:hover{background:#B5F04B;color:#0D1B02}
  .button.is-handled{background:var(--mint);color:#03150D;
    box-shadow:inset 0 1px 0 rgba(255,255,255,.35),inset 0 -1px 0 rgba(0,0,0,.35),0 2px 8px rgba(0,0,0,.5)}
  .button.is-handled:hover{background:#4DFFC0;color:#03150D}
  /* Advise keeps Ask's sweep: the one thing in this stylesheet allowed to run
     when idle, paused on hover, gone under prefers-reduced-motion. */
  .button.is-advise{position:relative;background:var(--sapphire);color:#fff;
    box-shadow:inset 0 1px 0 rgba(255,255,255,.22),inset 0 -1px 0 rgba(0,0,0,.4),
               0 0 0 1px color-mix(in srgb,var(--cobalt) 62%,var(--sapphire)),0 1px 3px rgba(0,0,0,.4)}
  .button.is-advise::before{content:'';position:absolute;z-index:-1;inset:-3px;border-radius:calc(var(--radius-key) + 3px);
    background:conic-gradient(from var(--advise-sweep),transparent 0turn,transparent .30turn,
      color-mix(in srgb,var(--cobalt) 70%,transparent) .42turn,#A8CBFF .50turn,
      color-mix(in srgb,var(--cobalt) 70%,transparent) .58turn,transparent .70turn,transparent 1turn);
    filter:blur(6px);animation:adviseSweep 5s linear infinite;transition:opacity .16s ease}
  .button.is-advise:hover,.button.is-advise:focus-visible{background:color-mix(in srgb,#fff 15%,var(--sapphire));
    box-shadow:0 0 0 3px color-mix(in srgb,var(--cobalt) 45%,transparent),0 1px 3px rgba(0,0,0,.4)}
  .button.is-advise:hover::before{opacity:0;animation-play-state:paused}

  /* ---------------- small parts ---------------- */
  /* a label is plain words in sentence case: 13px, the UI face, no capitals tracked wide (Type Styling, rule 3) */
  .label{font:600 var(--t-label)/1.3 var(--font-ui);color:var(--ink-label)}
  .meta{font:400 var(--t-meta)/1.45 var(--font-meta);color:var(--ink-2)}
  .mono{font-family:var(--font-mono);font-variant-numeric:tabular-nums;letter-spacing:var(--mono-tight)}
  .diamond{width:6px;height:6px;flex:none;transform:rotate(45deg);background:var(--hue-local,var(--ink-3));display:inline-block}
  .ticks{display:flex;gap:4px;align-items:center;flex:none}
  .ticks i{width:2px;height:2px;border-radius:50%;background:rgba(255,255,255,.13)}
  .ticks i:nth-child(3n){background:rgba(255,255,255,.26)}
  /* a state is a dot and the whole word, never a pill of capitals and never clipped (Type Styling, rule 9) */
  .chip{font:600 var(--t-label)/1.3 var(--font-ui);color:var(--ink-2);white-space:nowrap;display:inline-flex;align-items:center;gap:7px}
  .chip::before{content:"";width:7px;height:7px;flex:none;border-radius:50%;background:currentColor}
  .chip:has(> i,> svg,> .diamond)::before{display:none}
  .chip.is-mint{color:var(--mint)}   .chip.is-amber{color:var(--amber)} .chip.is-pink{color:var(--pink)}
  .chip.is-cyan{color:var(--cyan)}   .chip.is-violet{color:var(--violet)} .chip.is-lime{color:var(--lime)}
  .chip.is-cobalt{color:var(--cobalt)} .chip.is-slate{color:var(--slate)}
  .switch{width:28px;height:17px;border-radius:var(--radius-round);background:var(--cut);box-shadow:var(--in);
    display:inline-flex;align-items:center;padding:2px}
  .switch i{width:13px;height:13px;border-radius:50%;background:var(--ink-3);box-shadow:var(--up);transition:transform .14s,background .14s}
  .switch.is-on{background:color-mix(in srgb,var(--mint) 22%,var(--cut))}
  .switch.is-on i{transform:translateX(11px);background:var(--mint)}
  .bar{height:6px;border-radius:3px;background:var(--cut);box-shadow:var(--in);overflow:hidden;display:block}
  .bar i{display:block;height:100%;background:var(--hue-local,var(--mint))}
  .divider{height:1px;background:rgba(255,255,255,.055);border:0;margin:0}

  /* ---------------- fields ---------------- */
  .field{display:flex;flex-direction:column;gap:6px}
  .field.is-mark{width:96px}
  .field_input,.field_select,.field_note{background:var(--cut);box-shadow:var(--in);border:0;border-radius:var(--radius-small);
    color:var(--ink);outline:0;color-scheme:dark;font:400 var(--t-small)/1 var(--font-ui);padding:0 12px;height:36px;width:100%}
  .field_note{height:auto;min-height:82px;padding:11px 12px;line-height:1.55;resize:vertical}
  /* A sentence's box, as tall as its words (Scott, 2026-11-06: a one-line box cut the proposal's words off, their end out
     of reach): one line while they are, a line more for each they wrap to. Without field-sizing, its rows and a handle. */
  .field_note.is-fit{min-height:36px;padding:8px 12px;line-height:1.45;resize:vertical}
  @supports (field-sizing:content){.field_note.is-fit{field-sizing:content;resize:none}}
  .field_input::placeholder,.field_note::placeholder{color:var(--ink-3)}
  .field_input:focus,.field_note:focus,.field_select:focus{box-shadow:var(--in),0 0 0 1px color-mix(in srgb,var(--mint) 50%,transparent)}
  .field_input.is-error{box-shadow:var(--in),0 0 0 1px color-mix(in srgb,var(--pink) 62%,transparent)}
  /* A SAMPLE SAYS SO (rules/samples-say-example.md; Scott, 2026-11-06: an estimator read a box's sample as words already
     written). A box whose placeholder is made-up content wears data-example: while it is empty its words are faint and
     italic, its edge dashed, and an Example tag sits in its corner until the first letter is typed. The tag is the box's
     own background, so no script draws it and a box a script adds later has it too. In a box that speaks, the tag keeps
     clear of the sparkle and mic: above them in a tall box, beside them in a one-line one. */
  :root{--example-tag:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='60' height='18'><rect width='60' height='18' rx='9' fill='%23FFA300' fill-opacity='.17'/><text x='30' y='12.6' text-anchor='middle' font-family='system-ui,sans-serif' font-size='10.5' font-weight='600' fill='%23FFB833' textLength='44' lengthAdjust='spacingAndGlyphs'>Example</text></svg>")}
  :root[data-theme="light"]{--example-tag:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='60' height='18'><rect width='60' height='18' rx='9' fill='%23A35F00' fill-opacity='.14'/><text x='30' y='12.6' text-anchor='middle' font-family='system-ui,sans-serif' font-size='10.5' font-weight='600' fill='%23663B00' textLength='44' lengthAdjust='spacingAndGlyphs'>Example</text></svg>")}
  [data-example]:placeholder-shown{background-image:var(--example-tag) !important;background-repeat:no-repeat !important;
    background-size:60px 18px !important;background-position:right 8px center !important;padding-right:76px !important}
  textarea[data-example]:placeholder-shown{background-position:right 10px top 8px !important;padding-right:80px !important}
  :is(input.speak-room,textarea.is-fit)[data-example]:placeholder-shown{background-position:right 80px top 50% !important;padding-right:148px !important}
  textarea.is-fit[data-example]:placeholder-shown{background-position:right 80px top 9px !important}
  [data-example]:placeholder-shown:not(:focus,.composer_in){outline:2px dashed color-mix(in srgb,var(--ink-3) 50%,transparent) !important;outline-offset:-2px}
  [data-example]::placeholder{font-style:italic !important;color:color-mix(in srgb,var(--ink-3) 78%,transparent) !important}
  @media print{[data-example]{background-image:none !important;outline:0 !important}}
  /* The name above a field. Text, not a surface: .field_note is the textarea,
     and borrowing it for a label draws an 82px inset box above every input. */
  .field_label{font:600 var(--t-label)/1 var(--font-ui);color:var(--ink-label)}
  .field_label small{font-size:inherit;font-weight:400;color:var(--ink-3)}   /* a note beside a label is the same size, quieter by weight and ink */
  .field_check{display:inline-flex;align-items:center;gap:9px;font-size:var(--t-small);color:var(--ink-2);cursor:pointer}
  /* a checkbox is an action: a bright edge that stands off the dark, mint when it is on */
  .field_check input{appearance:none;width:18px;height:18px;border-radius:5px;background:transparent;border:2px solid var(--ink-2);display:grid;place-items:center;cursor:pointer;flex:none}
  .field_check input:hover{border-color:var(--mint)}
  .field_check input[type=radio]{border-radius:50%}
  .field_check input:checked{background:var(--mint);border-color:var(--mint)}
  .field_check input:checked::after{content:"";width:6px;height:6px;background:#03150D;border-radius:1px}
  .field_check input[type=radio]:checked::after{border-radius:50%}
  .field_search{display:flex;align-items:center;gap:9px;height:36px;padding:0 11px;border-radius:var(--radius-small);
    background:var(--cut);box-shadow:var(--in);color:var(--ink-3);font-size:var(--t-small);min-width:0}
  .field_search input{border:0;background:none;color:var(--ink);font:400 var(--t-small)/1 var(--font-ui);width:100%;min-width:0;outline:0;color-scheme:dark}
  .field_search input::-webkit-search-decoration,.field_search input::-webkit-search-cancel-button{-webkit-appearance:none;display:none}
  .field_search kbd{margin-left:auto;font:500 var(--t-label)/1 var(--font-mono);color:var(--ink-3);padding:4px 5px;border-radius:3px;background:var(--face);box-shadow:var(--up);white-space:nowrap}

  /* the header's search (shell/Search.tsx, client/search.ts): the box in the head, what matches dropped under it */
  .omni{position:relative;min-width:0}
  .omni_box:focus-within{box-shadow:var(--in),0 0 0 1px color-mix(in srgb,var(--cyan) 55%,transparent)}
  .omni[aria-busy="true"] .omni_box svg{color:var(--cyan)}
  .head_search{flex:1 10 360px;max-width:520px;min-width:180px;margin-inline:auto}   /* shrinks ten times faster than the title, so it gives way first */
  .head_search + .head_end{margin-left:0}
  .omni_list{position:absolute;z-index:25;top:calc(100% + 6px);left:0;right:0;min-width:320px;max-height:min(70vh,520px);overflow:auto;
    padding:6px;border-radius:var(--radius-small);background:var(--face);box-shadow:var(--up),0 18px 40px rgba(0,0,0,.6)}
  .omni_list[hidden]{display:none}
  .omni_group + .omni_group{margin-top:6px;padding-top:6px;box-shadow:0 -1px 0 var(--cut)}
  .omni_group-label{padding:6px 9px 4px;font:500 var(--t-label)/1 var(--font-ui);color:var(--ink-3)}
  .omni_hit{display:flex;align-items:center;gap:10px;padding:8px 9px;border-radius:6px;color:var(--ink);text-decoration:none}
  .omni_hit[aria-selected="true"]{background:var(--cut);box-shadow:var(--in)}
  .omni_hit-text{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}
  .omni_hit-title{font-size:var(--t-small);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .omni_hit-sub{font:400 var(--t-meta)/1.25 var(--font-meta);color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .omni_hit-tag{flex:none}
  .omni_more{display:block;padding:7px 9px;font-size:var(--t-meta);color:var(--cyan);text-decoration:none;border-radius:6px}
  .omni_more:hover{background:var(--cut)}
  .omni_empty{padding:10px 9px;font-size:var(--t-meta);color:var(--ink-3)}
  .omni_mic{display:grid;place-items:center;flex:none;width:26px;height:26px;margin-left:auto;border-radius:50%;color:var(--ink-3)}
  .omni_mic[hidden]{display:none}
  .omni_mic:hover{color:var(--ink);background:var(--face)}
  .omni_mic + kbd{margin-left:0}
  .omni.is-listening .omni_mic{color:var(--pink);background:color-mix(in srgb,var(--pink) 16%,transparent);animation:omni-listen 1.2s ease-in-out infinite}
  @keyframes omni-listen{50%{box-shadow:0 0 0 5px color-mix(in srgb,var(--pink) 18%,transparent)}}
  @media (prefers-reduced-motion:reduce){.omni.is-listening .omni_mic{animation:none}}
  /* the same records as Ask lists them (client/ask-links.ts): a diamond where a file row has its page */
  .ask_ref.is-row.is-go::before{width:7px;height:7px;border:0;border-radius:0;transform:rotate(45deg);background:currentColor;opacity:.6}
  /* a change Ask proposed, waiting for the person's Confirm (client/ask-links.ts, ask/propose.ts) */
  .ask_confirm{display:flex;flex-direction:column;gap:8px;padding:12px;margin:8px 0;border-radius:var(--radius);background:var(--face-2)}
  .ask_confirm_title{font-size:var(--t-body);color:var(--ink)}
  .ask_confirm_actions{display:flex;gap:8px;flex-wrap:wrap}
  .ask_confirm_actions .button{font-size:var(--t-control)}
  .ask_confirm_done{font-size:var(--t-body);color:var(--ink-2)}
  .ask_confirm_done.is-failed{color:var(--pink)}
  .ask_undo{display:flex;align-items:center;gap:8px;margin:6px 0}
  .ask_undo_title{flex:1;min-width:0;font-size:var(--t-meta);color:var(--ink-2)}
  .ask_undo .button{font-size:var(--t-control)}
  .ask_confirm_all{display:flex;justify-content:flex-end;margin:4px 0 8px}
  .ask_confirm_all .button{font-size:var(--t-control)}

  /* ---------------- cards ---------------- */
  .card{padding:var(--space-medium);border-radius:var(--radius);background:var(--body);box-shadow:var(--up);
    display:flex;flex-direction:column;gap:16px;min-width:0}
  .card.is-sunk{background:var(--cut);box-shadow:var(--in)}
  .card_head{display:flex;flex-wrap:wrap;align-items:center;gap:4px 12px}
  /* a sentence about a card (.card_hint) sits under its title, not jammed beside it; a count stays on the title line (Type Styling, rule 6) */
  .card_head > .card_hint{flex:1 0 100%;order:2}
  .card_title{font-family:var(--font-display);font-size:var(--t-title);font-weight:700;letter-spacing:var(--track-title)}
  .card_head .label,.card_head .chip,.card_head .button{margin-left:auto}

  .task-card{display:flex;align-items:center;gap:11px;padding:11px 12px;border-radius:var(--radius-small);background:var(--face);box-shadow:var(--up)}
  .task-card_text{min-width:0;display:flex;flex-direction:column;gap:2px}
  .task-card_title{font-size:var(--t-small);font-weight:600}
  .task-card_meta{font:400 var(--t-meta)/1.4 var(--font-ui);color:var(--ink-3)}
  .task-card .button,.task-card .chip{margin-left:auto}

  .empty-state{padding:26px;border-radius:var(--radius);background:var(--body);box-shadow:var(--up);
    display:flex;flex-direction:column;gap:10px;align-items:flex-start}
  :where(.card) .empty-state{background:var(--face)}   /* inside a card, a step above it */
  .toast{display:flex;align-items:center;gap:10px;padding:12px 14px;border-radius:var(--radius);background:var(--body);box-shadow:var(--up-lg);font-size:var(--t-small)}
  .notice_component{display:flex;gap:11px;align-items:flex-start;padding:12px 14px;border-radius:var(--radius);
    background:var(--cut);box-shadow:var(--in);font-size:var(--t-small);color:var(--ink-2);line-height:1.5}
  .notice_component b{color:var(--ink)}
  .notice_component a{color:var(--cobalt);text-decoration:underline;text-underline-offset:2px}

  /* ---------------- tables ---------------- */
  /* positioned, so a visually hidden label inside a wide table is clipped here and never widens the page */
  .table_wrap{overflow-x:auto;position:relative}
  .table_component{width:100%;min-width:520px;font-size:var(--t-small);border-spacing:0 7px;border-collapse:separate}
  .table_component th{text-align:left;padding:0 12px 6px;font:500 var(--t-label)/1 var(--font-ui);color:var(--ink-label);white-space:nowrap}
  .table_component td{padding:11px 12px;color:var(--ink-2);background:var(--face)}
  .table_component tbody tr{box-shadow:var(--up)}
  .table_component tbody td:first-child{border-radius:var(--radius-small) 0 0 var(--radius-small);color:var(--ink);font-weight:600}
  .table_component tbody td:last-child{border-radius:0 var(--radius-small) var(--radius-small) 0;text-align:right}
  .table_component td.is-num{font-family:var(--font-mono);font-variant-numeric:tabular-nums;letter-spacing:var(--mono-tight);color:var(--ink)}

  /* ============================ THE SHELL ============================ */
  .app{display:grid;grid-template-columns:var(--rail-width) minmax(0,1fr);min-height:100vh;position:relative}
  /* THE BLUEPRINT SURVIVES THE NAVIGATION.
     --bp-delay (a negative animation-delay, computed before first paint from a
     start time in localStorage) begins the drift and the light where the last
     page left them. The delay lives INSIDE the animation shorthand on purpose: as
     a separate animation-delay line the shorthand below would reset it to 0,
     which is exactly why this kept restarting.
     THE GROUND IS EACH PERSON'S OWN (2026-09-28): a ground, a darkness and moving or
     still, printed on <html> by the shell (kernel/ground.ts, picked in Settings). The
     texture is ::before, one tile larger than the box on every side so a drift never
     shows an edge; a light, if the ground has one, is ::after. Darker is a brightness
     filter over the lot, so the texture, its relief and its light dim together.
     With no attributes (the sign-in page) it is the house default: the debossed grid,
     50% darker. The leather tiles are drawn by scripts/ground.mjs. */
  .blueprint{position:fixed;inset:-25%;z-index:0;pointer-events:none;overflow:hidden;background:#151819;
    filter:brightness(calc(var(--bp-b,.5)*var(--bp-c,1))) sepia(var(--bp-s,0)) saturate(var(--bp-sat,1)) hue-rotate(var(--bp-h,0deg));
    -webkit-mask-image:radial-gradient(60% 55% at 50% 45%,#000 55%,rgba(0,0,0,.5) 100%);
    mask-image:radial-gradient(60% 55% at 50% 45%,#000 55%,rgba(0,0,0,.5) 100%)}
  .blueprint::before,.blueprint::after{content:"";position:absolute;will-change:transform}
  .blueprint::before{inset:-512px;background:url(/assets/deboss.webp) 0 0/512px 512px repeat;
    animation:blueprintDrift calc(180s*var(--bp-k,1)) linear infinite var(--bp-delay,0s)}
  .blueprint::after{inset:0;
    background:radial-gradient(36% 43% at 50% 50%,rgba(170,220,205,.06),transparent 70%);
    animation:blueprintLight calc(90s*var(--bp-k,1)) ease-in-out infinite var(--bp-delay,0s)}
  /* the original blueprint: green lines on the field, drifting down and to the left */
  :root[data-ground="grid"] .blueprint{background:none;
    -webkit-mask-image:radial-gradient(120% 100% at 70% 0%,#000 30%,rgba(0,0,0,.35) 100%);
    mask-image:radial-gradient(120% 100% at 70% 0%,#000 30%,rgba(0,0,0,.35) 100%)}
  :root[data-ground="grid"] .blueprint::before{
    background:
      linear-gradient(rgba(0,255,163,.06) 1px,transparent 1px) 0 0/24px 24px,
      linear-gradient(90deg,rgba(0,255,163,.06) 1px,transparent 1px) 0 0/24px 24px,
      linear-gradient(rgba(0,255,163,.1) 1px,transparent 1px) 0 0/120px 120px,
      linear-gradient(90deg,rgba(0,255,163,.1) 1px,transparent 1px) 0 0/120px 120px;
    animation:blueprintGrid calc(90s*var(--bp-k,1)) linear infinite var(--bp-delay,0s)}
  :root[data-ground="grid"] .blueprint::after{content:none}
  /* graphite pebble: the leather holds still, a cool light circles over it */
  :root[data-ground="pebble"] .blueprint{background:#17191C}
  :root[data-ground="pebble"] .blueprint::before{background-image:url(/assets/pebble.webp);animation:none}
  :root[data-ground="pebble"] .blueprint::after{background:radial-gradient(36% 43% at 50% 50%,rgba(170,185,205,.11),transparent 70%)}
  /* midnight suede: the nap holds still, a wide soft band brushes back and forth */
  :root[data-ground="suede"] .blueprint{background:#141B2C}
  :root[data-ground="suede"] .blueprint::before{background-image:url(/assets/suede.webp);animation:none}
  :root[data-ground="suede"] .blueprint::after{
    background:linear-gradient(100deg,transparent 38%,rgba(140,165,230,.075) 50%,transparent 62%);
    animation:blueprintSweep calc(30s*var(--bp-k,1)) ease-in-out infinite alternate var(--bp-delay,0s)}
  /* charcoal waves: textured paper holds still; the waves, one drawing the size of
     the box with translucent bands so the grain shows through, sway a little */
  :root[data-ground="waves"] .blueprint{background:#232324}
  :root[data-ground="waves"] .blueprint::before{background-image:url(/assets/paper.webp);animation:none}
  :root[data-ground="waves"] .blueprint::after{background:url(/assets/waves.svg) 50% 50%/cover no-repeat;
    animation:blueprintSway calc(45s*var(--bp-k,1)) ease-in-out infinite alternate var(--bp-delay,0s)}
  /* black granite: the stone holds still, a plain light circles over it */
  :root[data-ground="granite"] .blueprint{background:#262626}
  :root[data-ground="granite"] .blueprint::before{background-image:url(/assets/stone.webp);animation:none}
  :root[data-ground="granite"] .blueprint::after{background:radial-gradient(36% 43% at 50% 50%,rgba(215,215,215,.12),transparent 70%)}
  /* bronze geometry: a navy field; the planes and hairlines are one drawing, like the waves, and sway */
  :root[data-ground="shapes"] .blueprint{background:#0B1622}
  :root[data-ground="shapes"] .blueprint::before{inset:0;background:linear-gradient(115deg,#0A1830,#0B1A24 55%,#07181A);animation:none}
  :root[data-ground="shapes"] .blueprint::after{background:url(/assets/shapes.svg) 50% 50%/cover no-repeat;
    animation:blueprintSway calc(45s*var(--bp-k,1)) ease-in-out infinite alternate var(--bp-delay,0s)}
  /* stitched leather: the box itself is the wood; ::before is the hide, a panel inset from
     both sides (the box is half again as wide as the screen, so 29.5% and 21% clear the rail and leave a plank's
     width showing at each edge) with its stitching drawn as dashes down each side; the
     light circles over the lot */
  :root[data-ground="stitch"] .blueprint{background:#1B1916 url(/assets/wood.webp) 0 0/512px 512px repeat}
  :root[data-ground="stitch"] .blueprint::before{inset:0 21% 0 29.5%;animation:none;
    box-shadow:0 0 0 1px rgba(0,0,0,.55),0 0 46px 10px rgba(0,0,0,.75),inset 0 0 60px rgba(0,0,0,.35);
    background:
      repeating-linear-gradient(180deg,rgba(176,190,184,.34) 0 8px,transparent 8px 14px) 18px 0/1.5px 100% no-repeat,
      repeating-linear-gradient(180deg,rgba(176,190,184,.34) 0 8px,transparent 8px 14px) calc(100% - 18px) 0/1.5px 100% no-repeat,
      repeating-linear-gradient(180deg,rgba(176,190,184,.34) 0 8px,transparent 8px 14px) calc(100% - 46px) 0/1.5px 100% no-repeat,
      #1A2223 url(/assets/hide.webp) 0 0/512px 512px repeat}
  :root[data-ground="stitch"] .blueprint::after{background:radial-gradient(36% 43% at 50% 50%,rgba(180,215,210,.08),transparent 70%)}
  /* darkness: the slider's stops, as the brightness the one filter above uses (50 is its
     fallback, so the sign-in page has it too) */
  :root[data-ground-dim="0"]{--bp-b:1} :root[data-ground-dim="10"]{--bp-b:.9} :root[data-ground-dim="20"]{--bp-b:.8} :root[data-ground-dim="30"]{--bp-b:.7} :root[data-ground-dim="40"]{--bp-b:.6}
  :root[data-ground-dim="60"]{--bp-b:.4} :root[data-ground-dim="70"]{--bp-b:.3} :root[data-ground-dim="80"]{--bp-b:.2} :root[data-ground-dim="90"]{--bp-b:.1}
  /* two stops from before the slider, still drawn for whoever saved one */
  :root[data-ground-dim="25"]{--bp-b:.75} :root[data-ground-dim="75"]{--bp-b:.25}
  /* tint: a colour wash over whichever ground is picked. sepia() gives a grey its warmth
     (amber, about 40 degrees round the wheel), hue-rotate() turns that to the colour asked
     for, and --bp-c takes back the lift sepia adds, so Darkness means the same with a tint
     as without. The twelve stops are the turn from amber (kernel/ground.ts names them). */
  :root[data-ground-tint]{--bp-s:1;--bp-sat:3;--bp-c:.82}
  :root[data-ground-tint="1"]{--bp-h:-40deg} :root[data-ground-tint="2"]{--bp-h:-15deg} :root[data-ground-tint="3"]{--bp-h:0deg} :root[data-ground-tint="4"]{--bp-h:20deg} :root[data-ground-tint="5"]{--bp-h:80deg} :root[data-ground-tint="6"]{--bp-h:130deg}
  :root[data-ground-tint="7"]{--bp-h:150deg} :root[data-ground-tint="8"]{--bp-h:180deg} :root[data-ground-tint="9"]{--bp-h:210deg} :root[data-ground-tint="10"]{--bp-h:235deg} :root[data-ground-tint="11"]{--bp-h:270deg} :root[data-ground-tint="12"]{--bp-h:300deg}
  /* motion: five speeds, each double or half the last; 3 is the speed each ground was drawn at.
     --bp-k stretches every loop by the same factor, so the longest (the debossed drift at its
     slowest, 720s) is a whole number of all the others and the phase clock holds at any speed. */
  :root[data-ground-speed="1"]{--bp-k:4}
  :root[data-ground-speed="2"]{--bp-k:2}
  :root[data-ground-speed="4"]{--bp-k:.5}
  :root[data-ground-speed="5"]{--bp-k:.25}
  :root[data-ground-still] .blueprint::before,:root[data-ground-still] .blueprint::after{animation:none}
  /* THE LIGHT TWINS (data-theme="light"): each ground on its pale tile (scripts/ground.mjs,
     <name>-light.webp), the drawings over a pale field. Darkness bites half as hard, so even
     90% leaves dark ink readable on the ground; a tint is washed in at about half strength. */
  :root[data-theme="light"] .blueprint{background:#D6DCDA;
    filter:brightness(calc((1 - (1 - var(--bp-b,.5)) * .5) * var(--bp-c,1))) sepia(var(--bp-s,0)) saturate(var(--bp-sat,1)) hue-rotate(var(--bp-h,0deg))}
  :root[data-theme="light"][data-ground-tint]{--bp-s:.55;--bp-sat:1.25;--bp-c:.97}
  :root[data-theme="light"] .blueprint::before{background-image:url(/assets/deboss-light.webp)}
  :root[data-theme="light"] .blueprint::after{background:radial-gradient(36% 43% at 50% 50%,rgba(255,255,255,.35),transparent 70%)}
  :root[data-theme="light"][data-ground="grid"] .blueprint{background:#E3E9E6}
  :root[data-theme="light"][data-ground="grid"] .blueprint::before{
    background:
      linear-gradient(rgba(0,122,82,.09) 1px,transparent 1px) 0 0/24px 24px,
      linear-gradient(90deg,rgba(0,122,82,.09) 1px,transparent 1px) 0 0/24px 24px,
      linear-gradient(rgba(0,122,82,.17) 1px,transparent 1px) 0 0/120px 120px,
      linear-gradient(90deg,rgba(0,122,82,.17) 1px,transparent 1px) 0 0/120px 120px}
  :root[data-theme="light"][data-ground="pebble"] .blueprint{background:#D4D7DB}
  :root[data-theme="light"][data-ground="pebble"] .blueprint::before{background-image:url(/assets/pebble-light.webp)}
  :root[data-theme="light"][data-ground="suede"] .blueprint{background:#C8D2E5}
  :root[data-theme="light"][data-ground="suede"] .blueprint::before{background-image:url(/assets/suede-light.webp)}
  :root[data-theme="light"][data-ground="suede"] .blueprint::after{background:linear-gradient(100deg,transparent 38%,rgba(255,255,255,.3) 50%,transparent 62%)}
  :root[data-theme="light"][data-ground="waves"] .blueprint{background:#DEDEDB}
  :root[data-theme="light"][data-ground="waves"] .blueprint::before{background-image:url(/assets/paper-light.webp)}
  :root[data-theme="light"][data-ground="waves"] .blueprint::after{background:url(/assets/waves.svg) 50% 50%/cover no-repeat;opacity:.4}
  :root[data-theme="light"][data-ground="granite"] .blueprint{background:#E0E0DE}
  :root[data-theme="light"][data-ground="granite"] .blueprint::before{background-image:url(/assets/stone-light.webp)}
  :root[data-theme="light"][data-ground="shapes"] .blueprint{background:#DCE4EC}
  :root[data-theme="light"][data-ground="shapes"] .blueprint::before{background:linear-gradient(115deg,#D5E0EE,#DCE5EA 55%,#D3E2E0)}
  :root[data-theme="light"][data-ground="shapes"] .blueprint::after{background:url(/assets/shapes.svg) 50% 50%/cover no-repeat;opacity:.4}
  :root[data-theme="light"][data-ground="stitch"] .blueprint{background:#C4B092 url(/assets/wood-light.webp) 0 0/512px 512px repeat}
  :root[data-theme="light"][data-ground="stitch"] .blueprint::before{
    box-shadow:0 0 0 1px rgba(60,40,20,.35),0 0 36px 6px rgba(60,40,20,.3),inset 0 0 50px rgba(60,40,20,.12);
    background:
      repeating-linear-gradient(180deg,rgba(60,74,70,.45) 0 8px,transparent 8px 14px) 18px 0/1.5px 100% no-repeat,
      repeating-linear-gradient(180deg,rgba(60,74,70,.45) 0 8px,transparent 8px 14px) calc(100% - 18px) 0/1.5px 100% no-repeat,
      repeating-linear-gradient(180deg,rgba(60,74,70,.45) 0 8px,transparent 8px 14px) calc(100% - 46px) 0/1.5px 100% no-repeat,
      #C4D6D3 url(/assets/hide-light.webp) 0 0/512px 512px repeat}
  .rail,.main{position:relative;z-index:1}

  /* The rail is the frame, so it sits under a card (--body) but well above the ground. At 45% body
     on black it was 7% off the ground under room light and only 5% off its own wells (the plate, the
     current door, the company and account rows), so on a laptop or a showroom screen it read as the
     ground and the wells vanished. Lifted 2026-10-16, by tone, same hue: 27% off the ground, 13% off
     its wells, 11% under a card. Light theme sets its own --rail-bg further down. */
  .rail{--rail-bg:color-mix(in srgb,var(--body) 60%,var(--cut));position:sticky;top:0;height:100vh;display:flex;flex-direction:column;gap:var(--space-medium);
    padding:var(--space-medium) 12px;background:var(--rail-bg);box-shadow:var(--up-lg);z-index:4}
  .rail_brand{display:block;padding:2px 0 0;min-width:0}
  .rail_brand-lockup{display:block;width:100%;height:auto}
  .rail_brand-icon{display:none;width:100%;height:auto;max-width:44px;margin-inline:auto}
  .rail_arena{position:relative;display:flex;align-items:center;gap:9px;padding:10px;border-radius:10px;
    background:var(--cut);box-shadow:var(--in)}
  .rail_arena-ico{width:40px;height:40px;flex:none;display:grid;place-items:center;border-radius:9px;color:var(--mint);
    background:color-mix(in srgb,var(--mint) 9%,var(--body));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--mint) 22%,transparent)}
  .rail_arena-text{min-width:0;display:flex;flex-direction:column;gap:5px;padding-top:8px}
  .rail_arena-name{font:900 18px/1 'HIS Montserrat','Montserrat',var(--font-display);letter-spacing:-.01em;
    text-transform:uppercase;color:var(--ink);white-space:nowrap}
  .rail_arena-line{font:600 9px/1 var(--font-ui);letter-spacing:.1em;text-transform:uppercase;color:var(--his-seafoam);white-space:nowrap}
  .rail_arena-live{position:absolute;top:8px;right:9px;display:flex;align-items:center;gap:4px;
    font:600 8.5px/1 var(--font-ui);letter-spacing:.1em;text-transform:uppercase;color:var(--mint)}
  .rail_arena-live i{width:6px;height:6px;border-radius:50%;background:var(--mint)}
  /* the list scrolls on a short screen; the brand above and the account below stay put */
  .rail_brand,.rail_arena,.rail_foot{flex:none}
  .rail_nav{display:flex;flex-direction:column;gap:2px;flex:0 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;
    scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--ink-3) 40%,transparent) transparent;
    /* more doors below or above: the list fades at that edge, and only while there is more to scroll to */
    background:linear-gradient(var(--rail-bg) 40%,transparent) top/100% 26px,linear-gradient(transparent,var(--rail-bg) 60%) bottom/100% 26px,
      linear-gradient(color-mix(in srgb,var(--ink-3) 22%,transparent),transparent) top/100% 14px,linear-gradient(transparent,color-mix(in srgb,var(--ink-3) 22%,transparent)) bottom/100% 14px;
    background-repeat:no-repeat;background-attachment:local,local,scroll,scroll}
  /* a short window (a laptop, or any screen zoomed in): the rail tightens and drops its second badge so more doors show */
  @media (max-height:820px) and (min-width:981px){
    .rail{gap:12px;padding-block:14px}
    .rail_link{padding-block:6px}
  }
  @media (max-height:660px) and (min-width:981px){ .rail_arena{display:none} }
  .rail_link{display:flex;align-items:center;gap:11px;padding:8px 10px;border-radius:var(--radius-small);
    color:var(--ink-2);font-size:var(--t-control);font-weight:500;cursor:pointer;width:100%;text-align:left}
  .rail_link:hover{color:var(--ink);background:rgba(255,255,255,.045)}
  .rail_link[aria-current="page"]{background:var(--cut);box-shadow:var(--in);color:var(--ink)}
  /* Icons at full strength, the brand hue exactly: at 90% pink, cobalt and slate fell to about 3:1 on a
     showroom screen, and every light-theme hue sat near or under it. Violet is the darkest brand hue,
     so on the dark rail alone its icon carries a sixth of ink: 3.4:1 becomes 3.9:1 (3:1 under room light). */
  .rail_link-ico{width:17px;height:17px;flex:none;color:var(--hue-local,var(--ink-3))}
  :root:not([data-theme="light"]) .rail_link.hue-violet .rail_link-ico{color:color-mix(in srgb,var(--violet) 84%,var(--ink))}
  .rail_link[aria-current="page"] .rail_link-ico{filter:drop-shadow(0 0 6px color-mix(in srgb,var(--hue-local,var(--mint)) 45%,transparent))}
  .rail_rule{flex:none;height:1px;margin:7px 10px;background:var(--ink-3);opacity:.35}
  .rail_link-count{margin-left:auto;font:400 var(--t-label)/1 var(--font-ui);color:var(--ink-3);font-variant-numeric:tabular-nums}
  .rail_foot{margin-top:auto;display:flex;flex-direction:column;gap:7px}
  .rail_company{display:flex;align-items:center;gap:9px;min-height:38px;padding:7px 9px;border-radius:var(--radius-small);
    background:var(--cut);box-shadow:var(--in);min-width:0;width:100%}
  .rail_company-mark{width:20px;height:20px;border-radius:5px;background:var(--face);box-shadow:var(--up);display:grid;place-items:center;flex:none}
  .rail_company-mark i{width:7px;height:7px;transform:rotate(45deg);background:var(--mint)}
  .rail_company-name{min-width:0;display:flex;flex-direction:column;gap:2px;text-align:left;flex:1}
  .rail_company-name b{font:600 var(--t-meta)/1.25 var(--font-ui);overflow-wrap:anywhere}   /* a name wraps, it is never cut */
  .rail_company-swap{color:var(--ink-3);flex:none}
  .rail_company:hover .rail_company-swap{color:var(--mint)}
  /* three fixed-width objects, so nothing in this row can ever be too long */
  .rail_account{display:flex;align-items:center;gap:6px;padding:6px;border-radius:var(--radius-small);background:var(--cut);box-shadow:var(--in)}
  .rail_account-face{width:30px;height:30px;border-radius:var(--radius-round);background:var(--face);box-shadow:var(--up);
    display:grid;place-items:center;font:700 var(--t-label)/1 var(--font-ui);color:var(--mint);flex:none}
  .rail_account-face:hover{box-shadow:var(--up),0 0 0 1px rgba(0,255,163,.25)}
  .rail_account-spacer{flex:1}
  .rail_account-btn{width:30px;height:30px;border-radius:var(--radius-small);background:var(--face);box-shadow:var(--up);
    display:grid;place-items:center;color:var(--ink-3);position:relative}
  .rail_account-btn:hover{color:var(--ink-2)}
  /* the bell's count: cyan, because a nudge is news, not a fault */
  .rail_account-badge{position:absolute;top:-3px;right:-3px;min-width:14px;height:14px;padding:0 3px;border-radius:7px;
    background:var(--cyan);color:#04161B;font:700 11px/14px var(--font-ui);text-align:center}

  /* under the bell (shell/Alerts.tsx): unread first, each one a form that opens its task */
  .alerts_head{display:flex;align-items:baseline;gap:var(--space-xsmall)}
  .alerts_head .label{margin:0}
  .alerts_clear{margin-left:auto;background:none;border:0;padding:0;cursor:pointer}
  .alerts_list{display:flex;flex-direction:column;gap:4px;max-height:60vh;overflow:auto}
  .alerts_item{display:flex;flex-direction:column;gap:2px;width:100%;text-align:left;padding:9px 10px;border:0;
    border-radius:var(--radius-small);background:var(--face);box-shadow:var(--up);cursor:pointer;color:var(--ink-3)}
  .alerts_item:hover{color:var(--ink-2)}
  .alerts_item[data-unread]{box-shadow:var(--up),inset 3px 0 0 var(--cyan)}
  .alerts_what{display:flex;align-items:baseline;gap:8px;font-size:var(--t-small)}
  .alerts_what b{color:var(--ink);font-weight:700}
  .alerts_when{margin-left:auto;font:400 var(--t-meta)/1 var(--font-ui);color:var(--ink-3);white-space:nowrap}
  .alerts_title{font-size:var(--t-small);color:var(--ink-2)}
  .alerts_body{font-size:var(--t-meta);color:var(--ink-3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  #alerts [hidden]{display:none!important}
  /* a row: the notice, and its cross that dismisses it (cleared, never deleted) */
  .alerts_row{display:flex;align-items:flex-start;gap:2px;border-radius:var(--radius-small)}
  .alerts_row > form:first-child{flex:1;min-width:0}
  .alerts_x{flex:none;display:grid;place-items:center;width:26px;height:26px;margin-top:6px;border:0;border-radius:var(--radius-small);
    background:none;color:var(--ink-3);cursor:pointer;opacity:.5;transition:opacity .15s,background .15s,color .15s}
  .alerts_row:is(:hover,:focus-within) .alerts_x{opacity:1}
  .alerts_x:hover{background:var(--face-2);color:var(--ink)}
  @media (hover:none){.alerts_x{opacity:1}}
  /* the bar: Show cleared, then Mark all read and Clear all; with Show cleared on, the search under it */
  .alerts_bar{display:flex;align-items:center;gap:8px;min-height:28px}
  .alerts_acts{display:flex;align-items:center;gap:12px;margin-left:auto}
  .alerts_acts .alerts_clear{margin-left:0}
  .alerts_shelf{display:inline-flex;align-items:center;gap:8px;padding:2px 0;border:0;background:none;color:var(--ink-3);
    font:500 var(--t-meta)/1 var(--font-ui);white-space:nowrap;cursor:pointer;transition:color .15s}
  .alerts_shelf:hover,.alerts_shelf[aria-checked="true"]{color:var(--ink)}
  .alerts_track{position:relative;flex:none;width:28px;height:16px;border-radius:8px;background:var(--cut);box-shadow:var(--in);transition:background .2s}
  .alerts_thumb{position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:var(--ink-3);
    transition:transform .24s cubic-bezier(.2,.8,.2,1),background .2s}
  .alerts_shelf[aria-checked="true"] .alerts_track{background:color-mix(in srgb,var(--cyan) 28%,var(--cut))}
  .alerts_shelf[aria-checked="true"] .alerts_thumb{transform:translateX(12px);background:var(--cyan)}
  .alerts_find{display:flex;align-items:center;gap:8px;min-height:34px;padding:0 10px;border-radius:var(--radius-small);
    background:var(--cut);box-shadow:var(--in);color:var(--ink-3)}
  .alerts_find:focus-within{box-shadow:var(--in),0 0 0 2px color-mix(in srgb,var(--cyan) 50%,transparent)}
  .alerts_find input{flex:1;min-width:0;border:0;background:none;color:var(--ink);font:400 var(--t-small)/1.2 var(--font-ui);outline:none}
  .alerts_past .alerts_item{opacity:.8}
  .alerts_past .alerts_item:hover{opacity:1}
  .alerts_past{transition:opacity .15s}
  .alerts_past[data-loading]{opacity:.5}
  .alerts_more{align-self:center;margin:4px 0;padding:6px 12px;border:0;border-radius:var(--radius-small);background:none;
    color:var(--ink-3);font:600 var(--t-meta)/1 var(--font-ui);cursor:pointer}
  .alerts_more:hover{background:var(--face);color:var(--ink)}
  .alerts_past-none{margin:0;padding:18px 8px;text-align:center;font-size:var(--t-small);color:var(--ink-3)}
  @media (prefers-reduced-motion:reduce){.alerts_x,.alerts_shelf,.alerts_track,.alerts_thumb,.alerts_past{transition:none}}

  /* THE DRAWER (shell/Drawer.tsx), classed .tray because the carried chat sheet owns .drawer_*: what is still new for you, at the foot of every page, folded to its head when
     asked (html[data-drawer=min], set before the first paint); client/notices.ts drops live ones in, raised a rung */
  .tray{position:fixed;right:var(--space-small);bottom:var(--space-small);z-index:35;width:min(340px,calc(100vw - 24px));
    display:flex;flex-direction:column;gap:6px;padding:8px;border-radius:var(--radius);background:var(--body);box-shadow:var(--up),0 14px 40px rgba(0,0,0,.6)}
  .tray[hidden]{display:none}
  .tray_head{display:flex;align-items:center;gap:6px}
  .tray_toggle{display:flex;align-items:center;gap:7px;flex:1;min-width:0;padding:4px 6px;border:0;background:none;color:var(--ink);cursor:pointer;
    font:700 var(--t-small)/1.2 var(--font-meta);text-align:left}
  .tray_toggle svg{flex:none;color:var(--cyan)}
  .tray_title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .tray_count{min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--cyan);color:#04161B;font:700 11px/18px var(--font-ui);text-align:center}
  .tray_caret{margin-left:auto;display:flex;color:var(--ink-3);transform:rotate(180deg);transition:transform .15s}
  html[data-drawer=min] .tray_caret{transform:none}
  .tray_sound{flex:none;padding:3px 5px;border:0;border-radius:var(--radius-small);background:none;cursor:pointer;
    font:500 var(--t-label)/1 var(--font-ui);color:var(--ink-2)}
  .tray_sound[aria-pressed="false"]{color:var(--ink-3);text-decoration:line-through}
  .tray_sound:hover{background:var(--face)}
  .tray_clear{flex:none;padding:0 4px;border:0;background:none;cursor:pointer;font-size:var(--t-meta)}
  .tray_list{display:flex;flex-direction:column;gap:5px;margin:0;padding:0;list-style:none;max-height:min(46vh,420px);overflow:auto}
  html[data-drawer=min] .tray_list,html[data-drawer=min] .tray_more{display:none}
  .tray_item{display:flex;align-items:flex-start;gap:2px;border-radius:var(--radius-small);background:var(--face);
    box-shadow:var(--up),inset 3px 0 0 var(--cyan)}
  .tray_item>form:first-child{flex:1;min-width:0}
  .tray_open{display:flex;flex-direction:column;gap:2px;width:100%;padding:9px 4px 9px 12px;border:0;background:none;cursor:pointer;text-align:left;color:var(--ink-3)}
  .tray_open:hover .tray_name{color:var(--ink)}
  .tray_what{display:flex;align-items:baseline;gap:8px;min-width:0;font-size:var(--t-small)}
  .tray_what b{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink);font-weight:700}
  .tray_when{margin-left:auto;font:400 var(--t-meta)/1 var(--font-ui);color:var(--ink-3);white-space:nowrap}
  .tray_name{font-size:var(--t-small);color:var(--ink-2);overflow-wrap:anywhere}
  .tray_body{font-size:var(--t-meta);color:var(--ink-3);overflow-wrap:anywhere;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .tray_body[hidden]{display:none}
  .tray_x{flex:none;display:grid;place-items:center;width:26px;height:26px;margin:6px 6px 0 0;border:0;border-radius:var(--radius-small);
    background:none;color:var(--ink-3);cursor:pointer}
  .tray_x:hover{background:var(--face-2);color:var(--ink)}
  .tray_item.is-new{background:var(--face-2);animation:tray-in .38s cubic-bezier(.2,.8,.2,1)}
  .tray_more{margin:0;padding:0 6px 2px;font-size:var(--t-meta);color:var(--ink-3)}
  @keyframes tray-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
  @media (prefers-reduced-motion:reduce){.tray_item.is-new{animation:none}.tray_caret{transition:none}}
  @media (max-width:860px){.tray{left:8px;right:8px;width:auto;bottom:calc(76px + env(safe-area-inset-bottom,0px))}}
  @media print{.tray{display:none}}

  /* POP-UPS (client/alerts/toast.ts): a card at the top right for each notice as it lands, over whatever is open and
     clear of Chat docked beside the page; a press opens it, its cross or ten seconds put it away */
  .notepop_stack{position:fixed;top:72px;right:var(--space-small);z-index:70;width:min(360px,calc(100vw - 24px));
    display:flex;flex-direction:column;gap:8px;pointer-events:none}
  .notepop{display:flex;align-items:flex-start;pointer-events:auto;border-radius:var(--radius);background:var(--body);
    box-shadow:var(--up),inset 3px 0 0 var(--cyan),0 14px 40px rgba(0,0,0,.55);animation:notepop-in .22s cubic-bezier(.2,.8,.2,1)}
  .notepop.is-leaving{opacity:0;transform:translateX(16px);transition:opacity .2s,transform .2s}
  @keyframes notepop-in{from{opacity:0;transform:translateY(-8px)}}
  .notepop_form{flex:1;min-width:0}
  .notepop_open{display:flex;flex-direction:column;gap:3px;width:100%;padding:11px 6px 11px 15px;border:0;background:none;color:var(--ink);text-align:left;cursor:pointer}
  .notepop_line{font:700 var(--t-small)/1.25 var(--font-ui);color:var(--ink)}
  .notepop_title{font:500 var(--t-small)/1.3 var(--font-ui);color:var(--ink-2)}
  .notepop_body{font:400 var(--t-meta)/1.35 var(--font-ui);color:var(--ink-3);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .notepop_open:hover .notepop_line{color:var(--cyan)}
  .notepop_x{flex:none;width:32px;height:32px;margin:6px 6px 0 0;border:0;border-radius:50%;background:none;color:var(--ink-3);cursor:pointer;font-size:13px}
  .notepop_x:hover{background:var(--face);color:var(--ink)}
  @media (min-width:1360px){html[data-chat-open] .notepop_stack{right:calc(var(--chat-dock,520px) + var(--space-small))}}
  @media (max-width:860px){.notepop_stack{top:calc(8px + env(safe-area-inset-top,0px));left:8px;right:8px;width:auto}}
  @media (prefers-reduced-motion:reduce){.notepop{animation:none}.notepop.is-leaving{transition:none}}
  @media print{.notepop_stack{display:none}}

  .rooms_label{padding:6px 10px 8px}
  .settings_component.is-wide{width:286px}
  .settings_component{position:fixed;width:252px;padding:11px;border-radius:var(--radius);background:var(--body);
    box-shadow:var(--up-lg),0 0 0 1px rgba(0,0,0,.7);flex-direction:column;gap:10px;
    max-height:calc(100vh - 16px);overflow-y:auto}
  .settings_component:popover-open{display:flex}
  .settings_profile{display:flex;gap:10px;align-items:center;padding:9px;border-radius:var(--radius-small);background:var(--cut);box-shadow:var(--in);min-width:0}
  .settings_profile-face{width:34px;height:34px;border-radius:var(--radius-round);background:var(--face);box-shadow:var(--up);
    display:grid;place-items:center;font:700 var(--t-small)/1 var(--font-mono);color:var(--mint);flex:none}
  .settings_profile-text{min-width:0;display:flex;flex-direction:column;gap:3px}
  .settings_profile-name{font-size:var(--t-small);font-weight:700;line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .settings_profile-line{font:400 var(--t-label)/1.3 var(--font-ui);color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .settings_dials{display:grid;grid-template-columns:1fr 1fr;gap:6px}
  /* the rail's order (shell/RailPicker.tsx): a row like the dials, its dropdown at the end */
  .settings_rail{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:6px;min-height:50px;padding:6px 8px 6px 14px;
    border-radius:16px;background:var(--pl-well,var(--cut));box-shadow:var(--in)}
  .settings_rail-label{font:500 var(--t-body)/1.2 var(--font-ui);color:var(--ink)}
  .settings_rail-pick{width:auto;min-width:170px;min-height:36px;padding:0 10px;font:600 var(--t-control)/1 var(--font-ui);color:var(--ink)}
  .settings_dial{display:flex;flex-direction:column;gap:6px;padding:9px;border-radius:var(--radius-small);background:var(--face);box-shadow:var(--up);text-align:left}
  .settings_dial:hover{background:var(--face-2)}
  .settings_dial:active{box-shadow:var(--press)}
  .settings_dial-state{display:flex;align-items:center;gap:6px;font:600 var(--t-small)/1 var(--font-ui);color:var(--ink)}
  .settings_dial-state svg{color:var(--mint);flex:none}
  .settings_rows{display:flex;flex-direction:column;gap:4px}
  .settings_row{display:flex;align-items:center;gap:9px;padding:9px 10px;border-radius:var(--radius-small);
    color:var(--ink-2);font:500 var(--t-small)/1 var(--font-ui);width:100%}
  .settings_row:hover{background:var(--face);box-shadow:var(--up);color:var(--ink)}
  .settings_row svg{color:var(--ink-3);flex:none}
  .settings_row.is-danger:hover,.settings_row.is-danger:hover svg{color:var(--pink)}
  /* the pencil's panel: Edit This Page (shell/Tweak.tsx) */
  .tweak_panel{width:min(340px,calc(100vw - 16px));max-height:calc(100vh - 80px);overflow:auto}
  .tweak_form{display:flex;flex-direction:column;gap:11px}
  .tweak_hues{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px 10px;border:0;padding:0;margin:0}
  .tweak_hues legend{grid-column:1/-1;margin-bottom:8px}
  .tweak_hues .field_check{text-transform:capitalize}
  .tweak_note{font-size:var(--t-label);color:var(--ink-3);line-height:1.45;margin:0}
  .tweak_actions{display:flex;gap:8px;justify-content:flex-end}
  /* words in place (shell/say.tsx, client/say.ts): outlined while a super admin is editing them */
  .is-saying [data-say]{outline:1px dashed color-mix(in srgb,var(--mint) 55%,transparent);outline-offset:2px;border-radius:2px;cursor:text}
  .is-saying [data-say]:hover{background:color-mix(in srgb,var(--mint) 10%,transparent)}
  [data-say][contenteditable]:not([contenteditable="false"]){outline:1px solid var(--mint);background:var(--cut)}
  [data-say].is-failed{outline-color:var(--pink)}
  .tweak_words[aria-pressed="true"]{box-shadow:var(--press);color:var(--mint)}
  /* boxes in place (shell/part.tsx, client/parts.ts): a preset width, a place among the boxes
     beside it, hidden. Important, because a door's own sheet is unlayered and would win. */
  .part-w-narrow{max-width:var(--container-small)!important;width:100%} .part-w-medium{max-width:var(--container-medium)!important;width:100%}
  .part-w-wide{max-width:var(--container-large)!important;width:100%} .part-w-full{max-width:none!important;width:100%;grid-column:1/-1}
  .part-o-1{order:1!important} .part-o-2{order:2!important} .part-o-3{order:3!important} .part-o-4{order:4!important} .part-o-5{order:5!important} .part-o-6{order:6!important} .part-o-7{order:7!important} .part-o-8{order:8!important} .part-o-9{order:9!important} .part-o-10{order:10!important}
  .part-o-11{order:11!important} .part-o-12{order:12!important} .part-o-13{order:13!important} .part-o-14{order:14!important} .part-o-15{order:15!important} .part-o-16{order:16!important} .part-o-17{order:17!important} .part-o-18{order:18!important} .part-o-19{order:19!important} .part-o-20{order:20!important}
  .part-o-21{order:21!important} .part-o-22{order:22!important} .part-o-23{order:23!important} .part-o-24{order:24!important} .part-o-25{order:25!important} .part-o-26{order:26!important} .part-o-27{order:27!important} .part-o-28{order:28!important} .part-o-29{order:29!important} .part-o-30{order:30!important}
  :root:not(.is-shaping) .part-is-hidden{display:none!important}
  .is-shaping .part-is-hidden{opacity:.45}
  .part_bar{display:none}
  /* while arranging, each box makes room above itself for its bar, so the bar never covers a thin row's buttons */
  .is-shaping [data-part]{position:relative;margin-top:26px;outline:1px dashed color-mix(in srgb,var(--cyan) 60%,transparent);outline-offset:3px}
  .is-shaping .part_bar{display:flex;position:absolute;top:-29px;right:0;z-index:6;gap:2px;padding:2px;border-radius:6px;background:var(--face);box-shadow:var(--up)}
  .part_bar button{font:600 var(--t-label)/1 var(--font-ui);padding:5px 6px;border-radius:4px;color:var(--ink-3)}
  .part_bar button:hover{color:var(--ink);background:var(--face-2)}
  .part_bar button[aria-pressed="true"]{color:var(--cyan);box-shadow:var(--in)}
  [data-part].is-failed{outline-color:var(--pink)}
  .part-is-fixed > .part_bar [data-part-act="move"]{display:none}
  /* arranging never reaches paper: no bars, no outlines, no room made above a box */
  @media print{.part_bar{display:none!important} .is-shaping [data-part]{position:static;margin-top:0;outline:0}}

  .main{display:flex;flex-direction:column;min-width:0}
  .hue-line{height:2px;background:var(--hue);opacity:.9}
  .head{display:flex;align-items:center;gap:13px;min-height:56px;padding:9px var(--space-medium);
    background:var(--body);box-shadow:var(--up);position:relative;z-index:3}
  .head_title{font-family:var(--font-display);font-size:var(--t-title);font-weight:800;letter-spacing:var(--track-title);white-space:nowrap;
    min-width:0;overflow:hidden;text-overflow:ellipsis}
  .head_job{flex:none}
  .head_end{margin-left:auto;display:flex;align-items:center;gap:var(--space-xsmall);flex:none}
  /* why this page exists (shell/intent.tsx): a quiet "i", its card under it on a point or a tab */
  .head_why{position:relative;display:flex;flex:none}
  .head_why-key{display:grid;place-items:center;width:30px;height:30px;padding:0;border:0;border-radius:50%;
    background:none;color:var(--ink-3);opacity:.7;cursor:help;transition:opacity .15s,color .15s}
  .head_why:is(:hover,:focus-within) .head_why-key{opacity:1;color:var(--ink)}
  .head_why-tip{position:absolute;top:calc(100% + 8px);right:0;z-index:20;width:min(320px,calc(100vw - 32px));
    display:flex;flex-direction:column;gap:10px;padding:12px 14px;border-radius:12px;background:var(--face);box-shadow:var(--up);
    opacity:0;visibility:hidden;transform:translateY(-4px);transition:opacity .15s,transform .15s,visibility 0s .15s;pointer-events:none}
  .head_why-tip::before{content:"";position:absolute;left:0;right:0;bottom:100%;height:10px}  /* the pointer crosses the gap to the Walkthrough key without the note closing */
  .head_why:is(:hover,:focus-within) .head_why-tip{opacity:1;visibility:visible;transform:none;transition-delay:.12s,.12s,0s;pointer-events:auto}
  .head_why-say{display:flex;flex-direction:column;gap:4px}
  .head_why-title{font:600 var(--t-label)/1.3 var(--font-ui);color:var(--ink-2)}
  .head_why-text{font:400 var(--t-meta)/1.45 var(--font-ui);color:var(--ink-3)}
  @media (max-width:860px){ .head_why{display:none} }
  /* a laptop zoomed in: the head gives up its extras before the title gives up its words, and Chat and Advise never leave the screen */
  @media (max-width:1240px) and (min-width:861px){
    .head{gap:10px}
    .head_door-count,.head_search kbd{display:none}
    .head_search{min-width:130px}
  }
  @media (max-width:1120px) and (min-width:861px){ .chatpop_open-t,.button.is-advise span{display:none} }
  /* the door: cut into the body, the label engraved, only the caret standing proud */
  .head_door{display:flex;align-items:center;gap:9px;height:34px;padding:0 6px 0 13px;border-radius:var(--radius-round);
    background:var(--cut);box-shadow:var(--in);font:600 var(--t-small)/1 var(--font-ui);color:var(--ink-2);
    white-space:nowrap;text-shadow:0 1px 0 rgba(0,0,0,.7);flex:none}
  .head_door:hover{color:var(--ink)}
  .head_door-count{font:500 var(--t-label)/1 var(--font-ui);color:var(--ink-3);padding-left:9px;
    border-left:1px solid rgba(0,0,0,.55);box-shadow:-1px 0 0 rgba(255,255,255,.04)}
  .head_door-caret{width:22px;height:22px;border-radius:50%;background:var(--face);box-shadow:var(--up);display:grid;place-items:center;color:var(--ink-2);flex:none}
  .rooms_component{position:fixed;width:216px;padding:7px;border-radius:var(--radius);background:var(--body);
    box-shadow:var(--up-lg),0 0 0 1px rgba(0,0,0,.7);flex-direction:column;gap:2px}
  .rooms_component:popover-open{display:flex}
  .rooms_link{display:flex;align-items:center;gap:9px;padding:9px 10px;border-radius:var(--radius-small);
    font:500 var(--t-small)/1 var(--font-ui);color:var(--ink-2);width:100%;text-align:left}
  .rooms_link:hover{background:var(--face);box-shadow:var(--up);color:var(--ink)}
  .rooms_link[aria-current="page"]{background:var(--cut);box-shadow:var(--in);color:var(--ink)}

  /* THE COMPANY SWITCHER (shell/Companies.tsx). The house rides on top in its own tile, a rung up;
     the clients sit under it in a list that scrolls by itself, so the panel never outgrows the
     screen however many clients there are. Past seven a find box leads the list (client/companies.ts). */
  .co_panel{width:320px;max-height:min(640px,calc(100vh - 120px));padding:8px}
  .co{display:flex;flex-direction:column;gap:6px;min-height:0;flex:1}
  .co_house{padding:4px;border-radius:var(--radius);background:var(--face);box-shadow:var(--up)}
  .co_bar{display:flex;align-items:baseline;gap:8px;padding:10px 10px 0}
  .co_count{font:600 var(--t-label)/1 var(--font-ui);color:var(--ink-3)}
  .co_house,.co_bar,.co_find{flex:none}
  .co_find{width:100%}
  .co_list{display:flex;flex-direction:column;gap:2px;min-height:0;flex:1;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin}
  .co_row{display:flex;align-items:center;gap:11px;width:100%;min-height:50px;padding:7px 10px;border-radius:var(--radius-small);
    text-align:left;color:var(--ink-2)}
  .co_row:hover,.co_row:focus-visible{background:var(--face);box-shadow:var(--up);color:var(--ink)}
  .co_house .co_row:hover,.co_house .co_row:focus-visible{background:var(--face-2)}
  .co_row[aria-current="page"]{background:var(--cut);box-shadow:var(--in);color:var(--ink)}
  .co_tile{width:34px;height:34px;flex:none;border-radius:var(--radius-small);display:grid;place-items:center;
    background:var(--face);box-shadow:var(--up);color:var(--hue-local);font:700 var(--t-label)/1 var(--font-ui)}
  .co_house .co_tile{width:40px;height:40px;background:var(--face-2)}
  .co_text{display:flex;flex-direction:column;gap:5px;min-width:0;flex:1}
  .co_text b{font:600 var(--t-small)/1.25 var(--font-ui);color:inherit;overflow-wrap:anywhere}
  .co_line{display:flex;align-items:center;gap:12px;font:400 var(--t-meta)/1 var(--font-ui);color:var(--ink-3)}
  .co_row[data-closed] .co_line{color:var(--amber)}
  .co_here{display:inline-flex;align-items:center;gap:7px;font-weight:600;color:var(--ink-2)}
  .co_here::before{content:"";width:6px;height:6px;transform:rotate(45deg);background:var(--mint)}
  .co_none{margin:0;padding:12px 10px;font:400 var(--t-meta)/1.4 var(--font-ui);color:var(--ink-3)}

  .subbar{display:flex;align-items:center;gap:10px;min-height:48px;padding:7px var(--space-medium);background:var(--field);
    box-shadow:inset 0 1px 0 rgba(255,255,255,.03),0 6px 14px -6px rgba(0,0,0,.85);position:relative;z-index:2;flex-wrap:wrap}
  .subbar_end{margin-left:auto;display:flex;align-items:center;gap:var(--space-xsmall)}
  .view-tabs_component{display:inline-flex;gap:3px;padding:3px;border-radius:var(--radius-key);background:var(--cut);box-shadow:var(--in)}
  .view-tabs_link{height:32px;padding:0 14px;border-radius:4px;display:inline-flex;align-items:center;
    font:600 var(--t-small)/1 var(--font-ui);color:var(--ink-3)}
  .view-tabs_link:hover{color:var(--ink-2)}
  .view-tabs_link[aria-current="page"]{background:var(--face);box-shadow:var(--up);color:var(--hue)}
  .app_body{padding:var(--space-medium) var(--space-medium) var(--space-xxlarge);display:flex;flex-direction:column;gap:var(--space-medium);min-width:0}

  /* ---------------- board ---------------- */
  .board_component{display:flex;gap:var(--space-small);overflow-x:auto;padding-bottom:6px;align-items:flex-start}
  /* min-width:0 holds every column to its flex width: a card's nowrap line (its services) ellipsizes instead of stretching the board */
  .board_column{flex:0 0 252px;min-width:0;display:flex;flex-direction:column;gap:9px;padding:11px;border-radius:var(--radius);background:var(--cut);box-shadow:var(--in)}
  .board_column-header{display:flex;align-items:center;gap:8px}
  .board_column-header .label{color:var(--hue-local,var(--ink-label))}
  .board_column-header .count{margin-left:auto;font:500 var(--t-label)/1 var(--font-ui);color:var(--ink-3)}
  .board_card{padding:11px;border:1px solid var(--line);border-radius:var(--radius-small);transition:border-color .12s;background:var(--face);box-shadow:var(--up);display:flex;flex-direction:column;gap:8px;cursor:grab}
  .board_card-title{font-size:var(--t-small);font-weight:600;line-height:1.35}

  /* A task opened, wherever it shows (the planner, the board, My tasks): its title is
     the button (.task-open), the task a dialog over the page (.task-dialog) — the
     browser's own popover. Save comes first in the foot so Enter saves; the foot is
     reversed so it still sits on the right. */
  .task-open{padding:0;margin:0;font:inherit;color:inherit;text-align:left;min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:inherit}
  .task-title{font-family:var(--font-task);font-size:var(--t-task);font-weight:var(--w-task)}   /* a task title where no module sets one */
  .task-open:hover{text-decoration:underline;text-decoration-color:var(--mint);text-underline-offset:3px}
  /* a done task's title is struck in the utilities layer below, so no view's sheet can take it off */
  /* A card or a row that opens its task wherever it is clicked (.is-openable): the title's button stretches its hit
     area over the whole of it, and whatever else in it acts (a check box, a move button, a link, a fold, a mark with a
     tooltip, a block's grip) sits above. A form or fold drawn display:contents has no box to raise: raise what holds it
     (Franklin's .pf-keys). Where the title is only words (a teammate's planner) nothing opens, and no pointer says so.
     Zero-specificity :where, so a module that places the card itself (a planner block is absolute) keeps its place. */
  :where(.is-openable){position:relative}
  .is-openable:has(.task-open){cursor:pointer}
  .is-openable .task-open::after{content:'';position:absolute;inset:0}
  :where(.is-openable) :where(form,a,select,input,textarea,details,.task-signal,.task-stall){position:relative;z-index:1}
  :where(.is-openable) :where([data-cal-grip]){z-index:1}
  .task-dialog{position:fixed;inset:0;margin:auto;width:min(520px,calc(100vw - 32px));height:fit-content;max-height:calc(100vh - 32px);overflow:auto;
    box-shadow:var(--up),inset 3px 0 0 var(--hue-card,var(--line))}
  .task-dialog:not(:popover-open){display:none}
  .task-dialog::backdrop{background:rgba(0,0,0,.5)}
  .task-dialog .card_title{margin:0}
  .task-dialog .card_head .label,.task-dialog .card_head .text-link{margin-left:auto}
  .task-dialog_text{margin:0;white-space:pre-wrap;font-size:var(--t-small);line-height:1.5;color:var(--ink-2)}
  .task-dialog_made{margin-right:auto;align-self:center;font-size:var(--t-small);color:var(--ink-3)}   /* Created, last in the reversed foot: shell/stamps.tsx */
  /* A task's due signal and stalled mark (modules/board/signals.ts), on the Tasks overview and the planner.
     The signal grows a step at a time — a ring, a dot, a glow, a slow breath — and never turns pink:
     pink is Blocked's, and this is a nudge, not a scolding. */
  :root{--signal-soon:var(--cobalt);--signal-late:var(--amber);--signal-far:color-mix(in srgb,var(--amber) 60%,var(--pink));
        --signal-stall:color-mix(in srgb,var(--violet) 35%,var(--ink))}
  .task-signal{display:inline-block;flex:none;width:10px;height:10px;border-radius:var(--radius-round);vertical-align:-1px}
  .task-signal[data-sev="1"]{box-shadow:inset 0 0 0 2px var(--signal-soon)}
  .task-signal[data-sev="2"]{background:var(--signal-late)}
  .task-signal[data-sev="3"]{background:var(--signal-late);
    box-shadow:0 0 0 3px color-mix(in srgb,var(--signal-late) 22%,transparent),0 0 10px color-mix(in srgb,var(--signal-late) 50%,transparent)}
  .task-signal[data-sev="4"]{background:var(--signal-far);animation:task-breathe 3.2s ease-in-out infinite;
    box-shadow:0 0 0 4px color-mix(in srgb,var(--signal-far) 28%,transparent),0 0 14px color-mix(in srgb,var(--signal-far) 55%,transparent)}
  @keyframes task-breathe{50%{box-shadow:0 0 0 7px color-mix(in srgb,var(--signal-far) 10%,transparent),0 0 20px color-mix(in srgb,var(--signal-far) 35%,transparent)}}
  @media (prefers-reduced-motion:reduce){.task-signal[data-sev="4"]{animation:none}}
  .task-stall{display:inline-flex;flex:none;color:var(--signal-stall);vertical-align:-2px}
  .task-due{white-space:nowrap;color:var(--ink-3)}
  .task-due[data-sev="1"]{color:color-mix(in srgb,var(--signal-soon) 55%,var(--ink))}
  .task-due[data-sev="2"]{color:color-mix(in srgb,var(--signal-late) 70%,var(--ink))}
  .task-due[data-sev="3"]{color:var(--signal-late);font-weight:600}
  .task-due[data-sev="4"]{color:var(--signal-far);font-weight:600}
  /* A task's priority (shell/priority.tsx): a mark before its title, and the picker in its dialog. */
  .priority-mark{display:inline-flex;flex:none;vertical-align:-2px;margin-right:6px;color:var(--hue-local)}
  .priority-pick{border:0;margin:0;padding:0;min-width:0}
  .priority-pick legend{padding:0;margin-bottom:6px}
  .priority-pick_row{display:flex;flex-wrap:wrap;gap:6px}
  .priority-pick_option{position:relative;display:inline-flex;align-items:center;gap:6px;padding:7px 11px;border-radius:var(--radius-small);
    background:var(--cut);box-shadow:var(--in);cursor:pointer;font:600 var(--t-small)/1 var(--font-ui);color:var(--ink-2)}
  .priority-pick_option svg{color:var(--hue-local)}
  .priority-pick_option input{position:absolute;opacity:0;pointer-events:none}
  .priority-pick_option:has(input:checked){color:var(--ink);box-shadow:var(--in),0 0 0 1.5px var(--hue-local)}
  .priority-pick_option:has(input:focus-visible){outline:1.5px solid var(--mint);outline-offset:2px}
  .priority-filter{display:flex;flex-wrap:wrap;gap:6px}
  .priority-filter_link{display:inline-flex;align-items:center;gap:6px;padding:7px 12px;border-radius:var(--radius-small);
    font:600 var(--t-control)/1 var(--font-ui);color:var(--ink-2)}
  .priority-filter_link svg{color:var(--hue-local)}
  .priority-filter_link:hover{color:var(--ink)}
  .priority-filter_link[aria-current]{background:var(--cut);box-shadow:var(--in),0 0 0 1px var(--hue-local);color:var(--ink)}
  /* A search box that suggests as you type (client/combo.ts, and a <select data-search>: client/shapes/search-pick.ts): the list drops under the box. */
  .combo{position:relative;min-width:0}
  .combo .field_input{width:100%}
  .combo_list{position:absolute;z-index:20;top:calc(100% + 4px);left:0;right:0;min-width:240px;max-height:280px;overflow:auto;
    margin:0;padding:4px;list-style:none;border-radius:var(--radius-small);background:var(--face-2);box-shadow:var(--up),0 0 0 1px var(--line)}
  .combo_list li{display:flex;flex-direction:column;gap:2px;padding:7px 9px;border-radius:6px;cursor:pointer}
  .combo_list li b{font-size:var(--t-small);font-weight:600;color:var(--ink)}
  .combo_list li span{font:400 var(--t-meta)/1.2 var(--font-meta);color:var(--ink-3)}
  .combo_list li[aria-selected="true"],.combo_list li:hover{background:var(--cut)}
  .combo_list .combo_empty{cursor:default;font-size:var(--t-meta);color:var(--ink-3)}
  /* @ in a note (client/mention.ts): the company's people, dropped at the caret. */
  .mention{position:relative;display:block;min-width:0}
  .mention > .field_note,.mention > .field_input{width:100%}
  .mention:has(> .flex-1){flex:1}
  .mention_list{position:absolute;z-index:30;width:240px;max-height:240px;overflow:auto;margin:0;padding:4px;list-style:none;
    border-radius:var(--radius-small);background:var(--face-2);box-shadow:var(--up),0 0 0 1px var(--line)}
  .mention_list li{display:flex;align-items:baseline;justify-content:space-between;gap:8px;padding:7px 9px;border-radius:6px;cursor:pointer}
  .mention_list li b{font-size:var(--t-small);font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .mention_list li span{font:400 var(--t-meta)/1.2 var(--font-meta);color:var(--mint)}
  .mention_list li[aria-selected="true"],.mention_list li:hover{background:var(--cut)}
  /* A task done, celebrated (client/confetti.ts): a layer over the page for a second, its pieces flying from the check box. */
  .confetti{position:fixed;inset:0;z-index:200;overflow:hidden;pointer-events:none}
  .confetti > span{position:absolute;display:block;will-change:transform,opacity}
  .confetti_bit{border-radius:2px}
  .confetti_spark{width:2px;height:13px;border-radius:2px}
  .confetti_star{line-height:1}
  .confetti_ring{width:30px;height:30px;border:2px solid var(--mint);border-radius:50%}
  .confetti_word{font:800 16px/1 var(--font-display);letter-spacing:-.01em;white-space:nowrap;text-shadow:0 2px 10px rgba(0,0,0,.7)}
  .form-stack_foot.task-dialog_foot{flex-direction:row-reverse;justify-content:flex-start}   /* beats .form-stack_foot, which comes later */
  .board_card-foot{display:flex;align-items:center;gap:7px}
  .board_card-foot .who{margin-left:auto;width:20px;height:20px;border-radius:var(--radius-round);background:var(--cut);
    box-shadow:var(--in);display:grid;place-items:center;font:700 11px/1 var(--font-ui);color:var(--ink-2)}
  /* a card's head (title and initials) and its readouts (shell/shapes/pace.ts): what the job
     is, then time in phase, last touch and tasks — amber when slow, pink when stalled */
  .board_card-head{align-items:flex-start}
  .board_card-type{display:flex;align-items:center;gap:5px;min-width:0;font:500 calc(var(--t-meta) + 1px)/1.3 var(--font-meta);color:var(--ink-2);
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .board_card-type svg{flex:none;color:var(--ink-3)}
  /* its quotes, one a line: the amount, then where it stands. Signed is mint, a draft is quiet, a lost one struck through */
  .board_card-quotes{display:flex;flex-direction:column;gap:3px;margin:0;padding:0;list-style:none}
  .board_card-quote{display:flex;align-items:center;gap:5px;font:500 var(--t-meta)/1.3 var(--font-meta);color:var(--ink-3);white-space:nowrap}
  .board_card-quote b{font:700 var(--t-small)/1.3 var(--font-meta);color:var(--ink)}
  .board_card-quote svg{flex:none;color:var(--ink-3)}
  .board_card-quote.is-signed b,.board_card-quote.is-signed svg{color:var(--mint)}
  .board_card-quote.is-draft b{color:var(--ink-2);font-weight:500}
  .board_card-quote.is-lost b{color:var(--ink-3);font-weight:500;text-decoration:line-through}
  /* past three, how many more: lined up under the amounts, a link to the Quotes tab on The Track */
  .board_card-more{padding-left:17px;font:500 var(--t-meta)/1.3 var(--font-meta);color:var(--ink-3)}
  .board_card-more a{color:var(--ink-2)}
  .board_card-more a:hover{color:var(--ink);text-decoration:underline;text-underline-offset:3px}
  .board_card-test{padding:1px 5px;border-radius:var(--radius-small);background:var(--cut);box-shadow:var(--in);
    font:700 13px/1.3 var(--font-ui);color:var(--amber)}
  .board_card-readouts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;padding-top:7px;border-top:1px solid var(--line)}
  .board_card-readout{display:flex;flex-direction:column;gap:4px;min-width:0}
  .board_card-readout b{display:flex;align-items:center;gap:4px;font:600 var(--t-small)/1 var(--font-meta);color:var(--ink);white-space:nowrap}
  .board_card-readout b svg{flex:none;color:var(--ink-3)}
  .board_card-readout small{font:500 var(--t-meta)/1 var(--font-meta);color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .board_card-readout.is-slow b,.board_card-readout.is-slow b svg{color:var(--amber)}
  .board_card-readout.is-stalled b,.board_card-readout.is-stalled b svg{color:var(--pink)}
  .board_card-readout.is-done b,.board_card-readout.is-done b svg{color:var(--mint)}
  .board_card.is-stalled{box-shadow:var(--up),inset 3px 0 0 var(--pink)}
  /* a card dragged to another column (client/cards.ts): the card lifts, a ghost follows, the column lights */
  .board_card[data-card-move]{cursor:grab}
  .board_card[data-card-move]:hover{border-color:rgba(255,255,255,.28)}   /* every card outlined; brighter under the pointer where it drags */
  .board_card.is-lifted{opacity:.35}
  .board_card.is-ghost{position:fixed;left:0;top:0;z-index:90;pointer-events:none;box-shadow:var(--up-lg),0 0 0 1px var(--line)}
  .board_column.is-over{box-shadow:var(--in),0 0 0 2px var(--hue-local,var(--mint))}
  html.is-dragging,html.is-dragging *{cursor:grabbing!important;user-select:none}
  .gantt_row{display:grid;grid-template-columns:150px minmax(0,1fr);gap:11px;align-items:center}

  /* ---------------- intake ---------------- */
  .intake_component{display:grid;grid-template-columns:336px minmax(0,1fr);gap:var(--space-small);align-items:start}
  .intake_list-head{display:flex;align-items:center;gap:8px}
  .intake_list-head h3{font-size:var(--t-title);font-weight:700}
  .call-card_name{font-size:var(--t-small);font-weight:700}
  .call-card_foot{display:flex;align-items:center;gap:7px;flex-wrap:wrap;font:500 var(--t-label)/1 var(--font-ui);color:var(--ink-3)}
  .call-card_foot .ok{color:var(--mint)}

  /* ---------------- verdict + share (SEO) ---------------- */
  .verdict_component{display:flex;gap:13px;align-items:flex-start;padding:14px 16px;border-radius:var(--radius);background:var(--body);box-shadow:var(--up)}
  .verdict_flag{font:700 var(--t-label)/1 var(--font-ui);color:var(--mint);padding-top:4px;white-space:nowrap}
  .verdict_text{font-size:var(--t-small);line-height:1.55;color:var(--ink-2)}
  .verdict_text b{color:var(--ink);font-weight:600}   /* emphasis is weight in the same face (rule 10) */
  .verdict_text .up{color:var(--mint);font-weight:700} .verdict_text .down{color:var(--pink);font-weight:700}
  .section_head{display:flex;align-items:baseline;gap:11px;flex-wrap:wrap}
  .section_head h2{font-size:var(--t-page);font-weight:800;letter-spacing:var(--track-page)}
  .section_head p{font-size:var(--t-small);color:var(--ink-3)}
  .share_note{margin-top:9px;font-size:var(--t-small);color:var(--ink-3);line-height:1.55}
  .move_row{display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:var(--radius-small)}
  .move_row:nth-child(odd){background:rgba(255,255,255,.03)}
  .move_row .k{font-size:var(--t-small);color:var(--ink-2)}
  .move_row .v{margin-left:auto;font:700 var(--t-small)/1 var(--font-mono);letter-spacing:var(--mono-tight);font-variant-numeric:tabular-nums}
  .move_row .d{width:44px;text-align:right;font:500 var(--t-meta)/1 var(--font-mono)}
  .move_row .d.up{color:var(--mint)} .move_row .d.down{color:var(--pink)} .move_row .d.flat{color:var(--ink-3)}

  /* ---------------- library ---------------- */
  .file-row_ico{width:26px;height:26px;border-radius:5px;background:var(--cut);box-shadow:var(--in);display:grid;place-items:center;
    font:700 11px/1 var(--font-ui);color:var(--hue-local,var(--ink-3));flex:none}
  .file-row_text{min-width:0;display:flex;flex-direction:column;gap:2px}
  .file-row_text b{font-size:var(--t-small);font-weight:600}

  /* ---------------- written text (shell/prose.tsx): lines, paragraphs and bullets as typed ---------------- */
  .prose{display:block}
  .prose_p{display:block;margin:0}
  .prose_ul{display:block;margin:0;padding-left:1.25em;list-style:disc}
  .prose_li{display:list-item;margin:0}
  .prose_li::marker{color:var(--hue-card,var(--ink-3))}
  .prose > * + *{margin-top:.5em}
  .prose_li + .prose_li{margin-top:.15em}

  /* ---------------- LIGHT: what the tokens cannot reach (data-theme="light") ---------------- */
  /* a hue fill that carried near-black text carries white on the deeper light hues */
  :root[data-theme="light"] :is(.button.is-chat,.button.is-handled,.rail_account-badge,.tray_count,.gantt_bar,.u-skip-link:focus){color:#fff}
  :root[data-theme="light"] .button.is-chat:hover{background:color-mix(in srgb,var(--lime) 85%,#000);color:#fff}
  :root[data-theme="light"] .button.is-handled:hover{background:color-mix(in srgb,var(--mint) 85%,#000);color:#fff}
  :root[data-theme="light"] .field_check input:checked::after{background:#fff}
  :root[data-theme="light"] :is(.field_input,.field_select,.field_note,.field_search input){color-scheme:light}
  :root[data-theme="light"] input.field_search{border:0}   /* Quote's search is the input itself, and the UA's inset border drew dark */
  /* the rail sits a shade under the card, not under black */
  :root[data-theme="light"] .rail{--rail-bg:color-mix(in srgb,var(--body) 55%,var(--cut))}
  :root[data-theme="light"] :is(.rail_link,.shelf_folder):hover{background:rgba(0,0,0,.05)}
  :root[data-theme="light"] .head_door{text-shadow:none}
  :root[data-theme="light"] .head_door-count{border-left-color:rgba(0,0,0,.14);box-shadow:none}
  /* hairlines and ticks drawn in white turn to ink */
  :root[data-theme="light"] .divider{background:rgba(0,0,0,.1)}
  :root[data-theme="light"] .ticks i{background:rgba(0,0,0,.16)}
  :root[data-theme="light"] .ticks i:nth-child(3n){background:rgba(0,0,0,.3)}
  :root[data-theme="light"] .board_card[data-card-move]:hover{border-color:rgba(0,0,0,.28)}
  :root[data-theme="light"] .data-table td{border-top-color:rgba(0,0,0,.08)}
  :root[data-theme="light"] .swap_ring-track{stroke:rgba(0,0,0,.1)}
  .settings_dial-form{display:contents}
  /* SETTINGS' TABS (shell/Chrome.tsx): General and Notifications, a pair of keys in a well, a pane each
     (client/alerts/settings.ts); Notifications' notes and its device rows (shell/AlertSettings.tsx) */
  .settings_tabs{display:grid;grid-template-columns:1fr 1fr;gap:4px;padding:4px;border-radius:var(--radius-small);background:var(--pl-well,var(--cut));box-shadow:var(--in)}
  .settings_tab{min-height:34px;padding:0 10px;border:0;border-radius:var(--radius-small);background:none;color:var(--ink-3);cursor:pointer;font:600 var(--t-small)/1 var(--font-ui)}
  .settings_tab:hover{color:var(--ink)}
  .settings_tab[aria-selected="true"]{background:var(--face);box-shadow:var(--up);color:var(--ink)}
  .settings_pane{display:flex;flex-direction:column;gap:inherit;flex:1 0 auto}
  .settings_pane[hidden]{display:none}
  .settings_note{margin:0;font:400 var(--t-meta)/1.45 var(--font-ui);color:var(--ink-3)}
  .settings_dials .settings_note{grid-column:1/-1;padding:4px 8px}
  .settings_dial[aria-pressed="false"] .settings_dial-state{color:var(--ink-3)}
  .settings_dial[disabled]{cursor:default}
  .settings_test{display:flex;flex-direction:column;gap:6px}
  /* the logo in the theme's ink (shell/Brand.tsx) */
  :root:not([data-theme="light"]) .is-on-light,:root[data-theme="light"] .is-on-dark{display:none!important}
}

/* ====================== UTILITIES · CLIENT-FIRST v2 ====================== */
@layer utilities {
  /* A TASK OR APPOINTMENT DONE: its title struck through wherever it shows (bugs/done-tasks-not-struck-through.md).
     Said on the title itself, because a button does not take the line its parent draws, and said here in the
     last layer, because a view's own sheet styles the title in components (the new look's drawer link took the
     line off with text-decoration:none, bugs/done-struck-new-look-flow.md), and a later layer outranks any of it. */
  .is-done .task-open,.is-done .task-open:hover{color:var(--ink-3);text-decoration:line-through;text-decoration-color:currentColor}
  /* ======================= THE PHONE SHAPE =======================
     Under 860px the rail is the wrong object: it is a desktop column. The app
     becomes what the old Ops became on a phone — a bottom bar you can reach with
     a thumb, and a full-screen menu that lists every door with a line saying what
     it is for. Nothing is hidden behind a hamburger that only says "menu". */
  .bottombar{display:none}
  .menu_sheet{display:none}
  /* THE FRAME NEVER PRINTS (bugs/gc-office-print-chrome.md). A letter sheet is narrower than 860px, so a print takes the phone
     shape below, and its bottom bar and the frame round a client being visited (shell/Away.tsx) are fixed: they printed over every
     sheet of a proposal printed from its desk. The page's own padding goes too, so a paper starts at the top of its sheet. */
  @media print{.bottombar,.menu_sheet,.away{display:none!important}.app_body{padding:0!important}}

  @media (max-width:860px){
    .app{grid-template-columns:minmax(0,1fr)}
    .rail{display:none}                       /* the sheet replaces it entirely */
    .app_body{padding-bottom:calc(68px + env(safe-area-inset-bottom,0px) + var(--space-large))}
    .head{padding-inline:var(--space-small)}
    .subbar{padding-inline:var(--space-small);gap:7px}
    .head_title{font-size:var(--t-body)}

    /* the bar: four thumb targets, 44px minimum, always on screen */
    .bottombar{display:grid;grid-template-columns:repeat(4,1fr);position:fixed;left:0;right:0;bottom:0;z-index:30;
      padding:6px 6px calc(6px + env(safe-area-inset-bottom,0px));background:var(--body);box-shadow:0 -8px 24px rgba(0,0,0,.75),var(--edge)}
    .bottombar_tab{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;
      min-height:52px;border-radius:var(--radius-small);color:var(--ink-3);
      font:500 var(--t-label)/1 var(--font-ui);}
    .bottombar_tab svg{width:19px;height:19px}
    .bottombar_tab[aria-current="page"],.bottombar_tab.is-open{box-shadow:var(--in);background:var(--cut);color:var(--hue)}
    .bottombar_tab.is-chat{color:var(--lime)} .bottombar_tab.is-advise{color:var(--cobalt)}

    /* the sheet: a full screen of doors, each with the line that says what it is */
    .menu_sheet{display:flex;position:fixed;inset:0;z-index:40;flex-direction:column;gap:var(--space-small);
      padding:var(--space-small) var(--space-small) calc(76px + env(safe-area-inset-bottom,0px));
      background:var(--field);overflow-y:auto}
    .menu_sheet[hidden]{display:none}
    .head_search,.menu_search kbd{display:none}
    .head_search + .head_end{margin-left:auto}
    .menu_search .omni_list{position:static;min-width:0;max-height:none;margin-top:6px}
    .menu_sheet_head{display:flex;align-items:center;gap:var(--space-small);padding:4px 2px}
    .menu_sheet_head .rail_brand-lockup{width:150px}
    .menu_sheet_head .button{margin-left:auto}
    .menu_company{border-radius:var(--radius);background:var(--face);box-shadow:var(--up)}
    .menu_company > summary{list-style:none;cursor:pointer;min-height:52px;padding:10px 12px}
    .menu_company > summary::-webkit-details-marker{display:none}
    .menu_company_list{display:flex;flex-direction:column;padding:6px}
    .menu_company_list .co_list{max-height:52vh}
    .menu_company_list .co_house{background:var(--face-2)}
    .menu_company_list .co_house .co_tile,.menu_company_list .co_house .co_row:hover{background:var(--face-3)}
    .menu_filters{display:flex;gap:7px;flex-wrap:wrap}
    .menu_filter{height:36px;padding:0 15px;border-radius:var(--radius-round);background:var(--face);box-shadow:var(--up);
      font:600 var(--t-small)/1 var(--font-ui);color:var(--ink-2);display:inline-flex;align-items:center}
    .menu_filter[aria-pressed="true"]{box-shadow:var(--press);color:var(--hue)}
    .menu_list{display:flex;flex-direction:column;gap:7px}
    .menu_row{display:grid;grid-template-columns:46px minmax(0,1fr) auto;gap:var(--space-small);align-items:center;
      padding:12px;border-radius:var(--radius);background:var(--face);box-shadow:var(--up);min-height:64px;text-align:left}
    .menu_row[aria-current="page"]{box-shadow:var(--press);background:var(--cut)}
    .menu_row_ico{width:46px;height:46px;border-radius:var(--radius-round);display:grid;place-items:center;
      background:var(--cut);box-shadow:var(--in);color:var(--hue-local,var(--ink-3))}
    .menu_row_ico svg{width:21px;height:21px}
    .menu_row_text{min-width:0;display:flex;flex-direction:column;gap:3px}
    .menu_row_text b{font-size:var(--t-body);font-weight:700;letter-spacing:var(--track-title)}
    .menu_row_text span{font-size:var(--t-small);color:var(--ink-3)}
    .menu_row[aria-current="page"] .menu_row_text span{color:var(--ink-2)}
    .menu_row_count{font:500 var(--t-meta)/1 var(--font-ui);color:var(--ink-3);font-variant-numeric:tabular-nums}

    /* the frame's own bits that do not belong on a phone */
    .ticks,.head_door-count{display:none}
    .button.is-chat span,.button.is-advise span{display:none}
    .intake_component,.split,.grid-2,.grid-3,.grid-4{grid-template-columns:minmax(0,1fr)}
  }
  @media (min-width:861px){ .menu_sheet{display:none!important} }

  /* structure: page-wrapper > main-wrapper > section_[name] > padding-global >
     container-[size] > padding-section-[size] > the page's own component */
  .page-wrapper{display:flex;flex-direction:column;min-height:100%}
  .main-wrapper{flex:1}
  .padding-global{padding-inline:var(--padding-global)}
  .container-large{width:100%;max-width:var(--container-large);margin-inline:auto}
  .container-medium{width:100%;max-width:var(--container-medium);margin-inline:auto}
  .container-small{width:100%;max-width:var(--container-small);margin-inline:auto}
  .padding-section-small{padding-block:var(--space-large)}
  .padding-section-medium{padding-block:var(--space-xlarge)}
  .padding-section-large{padding-block:var(--space-xxlarge)}

  /* space blocks — siblings that hold a gap. Between STATIC things only; a
     conditional thing takes a margin block, which disappears with its content. */
  .spacer-tiny{height:var(--space-tiny)}
  .spacer-xsmall{height:var(--space-xsmall)}  .spacer-small{height:var(--space-small)}
  .spacer-medium{height:var(--space-medium)}  .spacer-large{height:var(--space-large)}
  .spacer-huge{height:var(--space-huge)}

  /* margin + padding blocks — direction zeroes every side and opens one */
  .margin-top{margin:0;margin-top:var(--_size)} .margin-bottom{margin:0;margin-bottom:var(--_size)}
  .margin-left{margin:0;margin-left:var(--_size)} .margin-right{margin:0;margin-right:var(--_size)}
  .padding-top{padding:0;padding-top:var(--_size)} .padding-bottom{padding:0;padding-bottom:var(--_size)}
  .margin-0{--_size:0px} .margin-small{--_size:var(--space-small)}
  .margin-medium{--_size:var(--space-medium)} .margin-large{--_size:var(--space-large)}
  .padding-0{--_size:0px}

  /* layout */
  .row{display:flex;flex-direction:row;align-items:center;gap:var(--_gap,var(--space-xsmall));flex-wrap:wrap}
  .row.is-top{align-items:flex-start} .row.is-baseline{align-items:baseline} .row.is-nowrap{flex-wrap:nowrap}
  .column{display:flex;flex-direction:column;gap:var(--_gap,var(--space-small))}
  .spread{display:flex;align-items:center;justify-content:space-between;gap:var(--_gap,var(--space-small));flex-wrap:wrap}
  .grid-2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--_gap,var(--space-small))}
  .grid-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--_gap,var(--space-small))}
  .grid-4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--_gap,var(--space-small))}
  /* a reading column beside a narrower one — the shape most ops pages take */
  .split{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);gap:var(--_gap,var(--space-small));align-items:start}
  .flex-1{flex:1;min-width:0}

  /* text + colour */
  .heading-style-h2{font:800 var(--t-page)/1.15 var(--font-display);letter-spacing:var(--track-page)}
  .heading-style-h3{font:700 var(--t-title)/1.3 var(--font-display);letter-spacing:var(--track-title)}
  .heading-style-h4{font:600 var(--t-body)/1.4 var(--font-display)}
  .text-size-small{font-size:var(--t-small)}
  .text-style-mono{font-family:var(--font-mono);font-variant-numeric:tabular-nums;letter-spacing:var(--mono-tight)}
  .text-style-nowrap{white-space:nowrap}
  .text-align-left{text-align:left} .text-align-center{text-align:center} .text-color-ink-2{color:var(--ink-2)} .text-color-ink-3{color:var(--ink-3)}
  .text-color-label{color:var(--ink-label)} .text-color-pink{color:var(--pink)}
  .background-color-body{background:var(--body)} .background-color-cut{background:var(--cut)}
  .max-width-small{max-width:36ch} .max-width-large{max-width:64ch}

  .u-visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .u-skip-link{position:absolute;left:-9999px;z-index:80}
  .u-skip-link:focus{left:12px;top:12px;padding:9px 13px;border-radius:var(--radius-small);background:var(--mint);color:#04110B;font-weight:700}
  .hide{display:none!important}

  /* a hue handed to a component by class — never by a style attribute */
  .hue-mint{--hue-local:var(--mint)} .hue-amber{--hue-local:var(--amber)} .hue-pink{--hue-local:var(--pink)}
  .hue-cyan{--hue-local:var(--cyan)} .hue-violet{--hue-local:var(--violet)} .hue-lime{--hue-local:var(--lime)}
  .hue-cobalt{--hue-local:var(--cobalt)} .hue-slate{--hue-local:var(--slate)}
  .max-width-form{max-width:var(--container-medium)} .max-width-wide{max-width:1080px}
  .margin-left-auto{margin-left:auto} .align-self-end{align-self:end}

  /* the collapsed rail: icons only, the lockup becomes the mark */
  [data-rail="icons"] .rail{padding-inline:9px;align-items:center}
  [data-rail="icons"] .rail_brand-lockup,[data-rail="icons"] .rail_link-label,[data-rail="icons"] .rail_link-count,
  [data-rail="icons"] .rail_company-name,[data-rail="icons"] .rail_company-swap,[data-rail="icons"] .rail_account-spacer{display:none}
  [data-rail="icons"] .rail_brand-icon{display:block}
  [data-rail="icons"] .rail_arena-text,[data-rail="icons"] .rail_arena-live{display:none}
  [data-rail="icons"] .rail_arena{padding:0;background:none;box-shadow:none}
  [data-rail="icons"] .rail_link{justify-content:center;padding:9px 0;width:44px}
  [data-rail="icons"] .rail_nav{align-items:center}
  [data-rail="icons"] .rail_rule{width:28px;margin-inline:0}
  [data-rail="icons"] .rail_company{justify-content:center;padding:0;width:44px;margin-inline:auto}
  [data-rail="icons"] .rail_account{flex-direction:column;gap:5px;padding:5px;width:44px;margin-inline:auto}

  @media (max-width:980px){
    .app{grid-template-columns:minmax(0,1fr)}
    .rail{position:sticky;height:auto;flex-direction:row;align-items:center;gap:10px;overflow-x:auto;padding:10px 14px}
    .rail_nav{flex-direction:row;gap:4px;overflow:visible}
    .rail_foot,.rail_brand,.rail_arena{display:none}
    .rail_link{white-space:nowrap;width:auto}
    .rail_rule{width:1px;height:20px;margin:0 4px}
    .split,.grid-2,.grid-3,.grid-4,.intake_component{grid-template-columns:minmax(0,1fr)}
    .app_body,.head,.subbar{padding-inline:14px}
  }
  @media (prefers-reduced-motion:reduce){
    *{transition:none!important}
    .blueprint::before,.blueprint::after,.button.is-advise::before{animation:none!important}
  }
}

/* ============================== THE FRONT DOOR ==============================
   One card, centred, on the same field as the app. It is the first thing anyone
   sees of this platform, so it is the frame's material at its quietest: no rail,
   no chrome, one loud action. */
@layer components {
  .login_body{margin:0;min-height:100vh;display:grid;place-items:center;background:var(--field)}
  .login{position:relative;z-index:1;width:min(420px,92vw);display:flex;flex-direction:column;gap:var(--space-medium);padding:var(--space-medium)}
  .login_card{padding:var(--space-large) var(--space-medium);border-radius:var(--radius);background:var(--body);
    box-shadow:var(--up-lg);display:flex;flex-direction:column;gap:var(--space-small)}
  .login_brand{width:220px;margin-bottom:var(--space-xsmall)}
  .login_brand img{display:block;width:100%;height:auto}
  .login_title{font-size:var(--t-page);font-weight:800;letter-spacing:var(--track-page)}
  .login_lede{font-size:var(--t-small);color:var(--ink-2);line-height:1.6}
  .login_lede b{color:var(--ink);font-weight:600}
  .login_form{display:flex;flex-direction:column;gap:9px;margin-top:var(--space-xsmall)}
  .login_form .button{margin-top:var(--space-xxsmall);justify-content:center}
  .login_code{font:600 var(--t-page)/1 var(--font-mono);letter-spacing:.34em;text-align:center;height:52px}
  .login_error{font-size:var(--t-small);color:var(--pink)}
  .login_note{font:400 var(--t-meta)/1.5 var(--font-mono);letter-spacing:var(--mono-tight);color:var(--mint);
    padding:9px 11px;border-radius:var(--radius-small);background:var(--cut);box-shadow:var(--in)}
  .login_back{font-size:var(--t-small);color:var(--ink-3);align-self:flex-start;margin-top:var(--space-xsmall)}
  .login_back:hover{color:var(--ink-2)}
  .login_foot{font:400 var(--t-meta)/1.6 var(--font-mono);letter-spacing:var(--mono-tight);color:var(--ink-3);text-align:center}
}

/* ========================= THE HOUSE, AND THE KIT IT GREW =========================
   HIS's own seat. It wears the same material as a client's shell on
   purpose — it is the same platform. The house_ classes below are things only
   the house ever sees (the console, the roster, the client page).

   The kit pieces the house grew first and every destination now uses carry kit
   names instead: stat-grid / stat-tile, data-table, tab-row, form-stack,
   toggle-list, action-list, fact-list, pill-list, chip-row, split-grid,
   page-stack, text-link. Use those anywhere; never borrow a house_ class. */
@layer components {
  /* The kit's card head puts a TRAILING .label on the right (margin-left:auto).
     Every house card leads with the label instead, so that rule would shove the
     whole head to the right edge. Inside .house the head simply spreads. */
  .house .card_head{justify-content:space-between}
  .house .card_head .label{margin-left:0}

  /* ---- the console ------------------------------------------------- */
  .house{display:flex;flex-direction:column;gap:var(--space-medium);min-width:0}
  .page-stack{display:flex;flex-direction:column;gap:var(--space-large);min-width:0}   /* sections stand apart: 34px between, so a card's own 16px reads as inside */
  .text-link{font:600 var(--t-small)/1 var(--font-ui);color:var(--ink-3);white-space:nowrap}
  .text-link:hover{color:var(--mint)}
  .house_note{margin:0;font-size:var(--t-small);line-height:1.7;color:var(--ink-3);max-width:78ch}
  /* Team on a phone: the name and email take the line, the seats and badge go under */

  /* the band of numbers. Every one is read out of something real. */
  .stat-grid{display:grid;gap:var(--space-xsmall);
    grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
  .stat-tile{display:flex;flex-direction:column;gap:6px;padding:16px 18px;border-radius:var(--radius);
    background:var(--face);box-shadow:var(--up)}
  .stat-tile_value{font:700 var(--t-stat)/1 var(--font-display);letter-spacing:var(--track-page);color:var(--ink)}
  .stat-tile > .stat-tile_value{order:-1}   /* the figure leads, whatever order the markup wrote (Type Styling, rule 8) */
  /* a narrow tile (a zoomed-in laptop) shrinks its figure to fit, so $657,850 never runs into the next tile */
  .stat-grid > .stat-tile{container-type:inline-size}
  .stat-grid .stat-tile_value{font-size:min(var(--t-stat),18cqi)}
  .stat-tile_label{font:400 var(--t-body)/1.35 var(--font-ui);color:var(--ink)}   /* plain words under the figure, quieter than it (rule 8) */
  .stat-tile_note{font-size:var(--t-meta);line-height:1.45;color:var(--ink-2)}

  .split-grid{display:grid;gap:var(--space-medium);grid-template-columns:minmax(0,5fr) minmax(0,7fr);align-items:start}
  .split-grid.is-even{grid-template-columns:repeat(2,minmax(0,1fr))}
  @media (max-width:1000px){.split-grid,.split-grid.is-even{grid-template-columns:minmax(0,1fr)}}

  /* needs you: a thing to do, and the door to do it behind */
  .action-list{display:flex;flex-direction:column;gap:6px}
  .action-list_row{display:grid;grid-template-columns:8px minmax(0,1fr) auto auto;gap:11px;align-items:center;
    padding:10px 12px;border-radius:var(--radius-small);background:var(--face);box-shadow:var(--up)}
  .action-list_dot{width:8px;height:8px;transform:rotate(45deg);background:var(--slate)}
  .action-list_dot.is-bad{background:var(--pink)}
  .action-list_dot.is-warn{background:var(--amber)}
  .action-list_dot.is-ok{background:var(--lime)}
  .action-list_text{min-width:0;display:flex;flex-direction:column;gap:2px}
  .action-list_text b{font-size:var(--t-small);font-weight:700;color:var(--ink)}
  .action-list_text span{font-size:var(--t-meta);color:var(--ink-3)}
  .action-list_when{font:400 var(--t-meta)/1 var(--font-ui);
    color:var(--ink-3);white-space:nowrap}
  .action-list_when.is-bad{color:var(--pink)}
  .action-list_when.is-warn{color:var(--amber)}

  /* the roster table */
  .data-table{width:100%;border-collapse:collapse;font-size:var(--t-small)}
  .data-table th{text-align:left;padding:0 14px 12px;font:600 var(--t-label)/1 var(--font-ui);color:var(--ink-label);white-space:nowrap}
  .data-table td{padding:14px;border-top:1px solid rgba(255,255,255,.04);vertical-align:middle;color:var(--ink-2)}
  .data-table .is-num{text-align:right;font-family:var(--font-mono);letter-spacing:var(--mono-tight)}
  .data-table th.is-num{font-family:var(--font-ui);letter-spacing:0}   /* a header is a word, even over figures */
  /* the first column names the row, so it gets room before the short columns do (Type Styling, rule 5) */
  .data-table td:first-child:has(b,strong,a,.meta){min-width:11em}   /* a first column that names its row, not a signal, a tick or an icon */
  .data-table td b{display:block;color:var(--ink);font-weight:700}
  .data-table td .meta{display:block;margin-top:3px}   /* the meta under the name, on a line of its own */

  .house_mark{width:34px;height:34px;flex:none;border-radius:var(--radius-small);background:var(--cut);
    box-shadow:var(--in);display:grid;place-items:center;color:var(--c,var(--ink-2));
    font:700 var(--t-meta)/1 var(--font-ui);}
  .house_mark.is-big{width:46px;height:46px;font-size:var(--t-small)}
  .house_event-what b{color:var(--ink);font-weight:600}

  /* ---- clients ------------------------------------------------------- */
  .tab-row{display:flex;gap:4px;flex-wrap:wrap}
  .tab-row_link{padding:8px 14px;border-radius:var(--radius-small);font:600 var(--t-control)/1 var(--font-ui);
    color:var(--ink-3);background:var(--face);box-shadow:var(--up)}
  .tab-row_link:hover{color:var(--ink-2)}
  .tab-row_link.is-active{color:var(--ink);background:var(--cut);box-shadow:var(--press)}
  .tab-row_count{font-family:var(--font-ui);font-size:var(--t-meta);color:var(--ink-3);margin-left:4px}
  .house_client{display:flex;flex-direction:column;gap:var(--space-small)}
  .house_client.is-closed{opacity:.62}
  .house_client-top{display:flex;align-items:center;gap:12px;min-width:0}
  .chip-row{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
  .house_client-foot{display:flex;align-items:center;gap:9px;margin-top:auto;padding-top:var(--space-xsmall);
    border-top:1px solid rgba(255,255,255,.045)}

  /* ---- one client ---------------------------------------------------- */
  .house_chead-top{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
  .house_rung-how{font:400 var(--t-meta)/1 var(--font-ui);
    color:var(--amber);white-space:nowrap}

  .fact-list{display:flex;flex-direction:column}
  .fact-list_row{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-small);
    padding:9px 0;border-bottom:1px solid rgba(255,255,255,.04);font-size:var(--t-small)}
  .fact-list_row:last-child{border-bottom:0}
  .fact-list_key{color:var(--ink-3);white-space:nowrap}
  .fact-list_value{color:var(--ink);text-align:right;min-width:0;overflow-wrap:anywhere}

  /* ---- the forms behind the tabs ------------------------------------- */
  .form-stack{display:flex;flex-direction:column;gap:var(--space-small)}
  .form-stack_row{display:flex;gap:var(--space-small);flex-wrap:wrap}
  .form-stack_row .field{min-width:150px}
  .form-stack_row .field.is-grow{flex:1}
  .form-stack_foot{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-small);
    flex-wrap:wrap;padding-top:var(--space-xsmall)}
  .form-stack_foot .meta{margin-right:auto}

  /* Speak (shell/Speak.tsx): a note's mic, what it is doing, and Undo tidy; under a box or beside its Save */
  /* every other box's (client/speak.ts, shell/InBox.tsx): the sparkle and the mic as round icons in a row right under
     the box, at its right edge, never over the words (Andrew, 2026-10-27: "I can't see ... if what I typed is correct");
     what they are doing, and Undo, on the left of that same row */
  .speak-on{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:6px 10px;margin-top:6px}
  .speak-tools{order:2;display:flex;gap:6px}
  .speak-say{order:1;flex:1 1 auto;min-width:0}
  .speak-on.is-slot{display:inline-flex;flex-wrap:nowrap;gap:8px;margin-top:0}
  .speak-icon{flex:none;display:grid;place-items:center;width:32px;height:32px;padding:0;border:1px solid var(--line);border-radius:999px;cursor:pointer;
    background:var(--face);color:var(--ink-3);box-shadow:var(--up, none)}
  .speak-icon[hidden]{display:none}
  .speak-icon:hover{color:var(--ink)}
  .speak-icon:focus-visible{outline:2px solid color-mix(in srgb,var(--hue,var(--mint)) 60%,transparent);outline-offset:2px}
  .speak-icon.is-live,.speak-icon[aria-pressed="true"]{background:var(--pink);border-color:transparent;color:#fff}
  .speak-icon.is-on{color:var(--hue,var(--mint));animation:speak-think 1.2s ease-in-out infinite}
  @keyframes speak-think{50%{opacity:.45}}
  .speak-say{display:flex;align-items:baseline;gap:10px;font:400 var(--t-meta)/1.4 var(--font-ui);color:var(--ink-3)}
  .speak-undo{padding:0;border:0;background:none;color:var(--ink-2);font:600 var(--t-meta)/1.4 var(--font-ui);text-decoration:underline;cursor:pointer}
  .speak-undo[hidden]{display:none}
  /* INSIDE THE BOX, the standard (Alex, 2026-10-27, of Chat's composer: "Use this as a standard"): the sparkle and the
     mic sit inside the box at its right edge, flat, the way Chat's box holds them (client/voice/inside.ts seats them,
     .is-in). The box keeps a gutter down its right side as wide as the two, so the words wrap before them and never run
     under them, scrolled or not (Andrew's ask above). A one-line box holds them in its middle. What they are doing, Undo
     and talk back stay on the line under the box. Where the browser has CSS anchors they hang off the box
     (.is-anchored); where it has none, the same spot is measured and pinned (.is-pinned), so every browser sees one look. */
  .speak-room{padding-right:80px !important}   /* every box's own padding gives way to the gutter, or words run under */
  .speak-on.is-in{display:block;position:static;margin-top:0}
  .speak-on.is-in,.talkback{grid-column:1/-1}   /* a box in a grid: its line and talk back take a row of their own (voice/inside.ts place) */
  .speak-on.is-in > .speak-tools{position:absolute;gap:2px;z-index:1}
  .speak-on.is-anchored > .speak-tools{right:calc(anchor(right) + 12px);bottom:calc(anchor(bottom) + 6px)}
  .speak-on.is-anchored.is-line > .speak-tools{bottom:auto;top:calc(anchor(center) - 15px)}
  .speak-on.is-pinned{position:relative}
  .speak-on.is-pinned > .speak-tools{right:calc(var(--speak-x, 0px) + 12px);top:calc(var(--speak-y, 0px) - 36px)}
  .speak-on.is-pinned.is-line > .speak-tools{top:calc(var(--speak-mid, 0px) - 15px)}
  .speak-on.is-in > .speak-tools .speak-icon{width:30px;height:30px;border-color:transparent;background:none;box-shadow:none}
  .speak-on.is-in > .speak-tools .speak-icon:hover{background:var(--face);color:var(--ink)}
  .speak-on.is-in > .speak-tools .speak-icon:is(.is-live,[aria-pressed="true"]){background:var(--pink);color:#fff}
  .speak-on.is-in > .speak-say:has([data-voice-status]:not(:empty), .speak-undo:not([hidden])){margin-top:6px}
  @media (prefers-reduced-motion:reduce){.speak-icon.is-on{animation:none}}
  /* Talk back (shell/InBox.tsx <TalkBack>, client/voice/talkback.ts): under a tidied job note, one line to tell Claude
     what to change, three quick asks, and the three versions to pick from */
  .talkback{display:grid;grid-template-columns:minmax(0,1fr);gap:8px;margin-top:10px;min-width:0}
  .talkback[hidden]{display:none}
  .talkback_pill{display:flex;align-items:center;gap:6px;padding:4px;border:1px solid var(--line);border-radius:999px;background:var(--face)}
  .talkback_pill:focus-within{border-color:color-mix(in srgb,var(--hue,var(--mint)) 45%,transparent)}
  .talkback_in{flex:1;min-width:0;height:32px;padding:0 6px;border:0;background:none;color:var(--ink);font:400 var(--t-body)/1.4 var(--font-ui)}
  .talkback_in:focus{outline:0}
  .talkback_in::placeholder{color:var(--ink-3)}
  .speak-icon.is-send{border:0;background:var(--hue,var(--mint));color:#141006}
  /* the talk back's mic is the main way in, so it reads as a button: the door's colour, not a quiet grey icon */
  .talkback_pill .speak-icon[data-voice]{width:34px;height:34px;border-color:color-mix(in srgb,var(--hue,var(--mint)) 55%,transparent);
    background:color-mix(in srgb,var(--hue,var(--mint)) 16%,transparent);color:var(--hue,var(--mint))}
  .talkback_pill .speak-icon[data-voice]:hover{background:color-mix(in srgb,var(--hue,var(--mint)) 28%,transparent)}
  .talkback_pill .speak-icon[data-voice][aria-pressed="true"]{background:var(--pink);border-color:transparent;color:#fff}
  .talkback_asks{display:flex;flex-wrap:wrap;gap:6px}
  .talkback_ask{padding:5px 12px;border:1px solid var(--line);border-radius:999px;background:none;color:var(--ink-2);cursor:pointer;
    font:600 var(--t-meta)/1.3 var(--font-ui)}
  .talkback_ask:hover{color:var(--ink);border-color:color-mix(in srgb,var(--hue,var(--mint)) 45%,transparent)}
  .talkback.is-busy{opacity:.6}
  .talkback.is-busy .talkback_pill{animation:speak-think 1.2s ease-in-out infinite}
  .talkback_say{font:400 var(--t-meta)/1.4 var(--font-ui);color:var(--ink-3)}
  .talkback_say:empty{display:none}
  .talkback_picks{display:grid;gap:8px}
  .talkback_picks[hidden]{display:none}
  .talkback_pick{padding:10px 12px;border:1px solid var(--line);border-radius:12px;background:var(--face);color:var(--ink);text-align:left;
    white-space:pre-wrap;cursor:pointer;font:400 var(--t-meta)/1.45 var(--font-ui)}
  .talkback_pick:hover,.talkback_pick:focus-visible{border-color:var(--hue,var(--mint))}
  @media (prefers-reduced-motion:reduce){.talkback.is-busy .talkback_pill{animation:none}}
  @media print{.speak,.speak-on,.talkback{display:none}.speak-room{padding-right:12px !important}}

  /* Working (client/panels.ts, data-working): a slow button's press was taken, and it is still going */
  .button.is-working{box-shadow:var(--in),0 0 0 1px var(--mint);cursor:progress}
  .working{display:inline-flex;align-items:center;gap:8px;font:600 var(--t-small)/1.4 var(--font-ui);color:var(--mint)}
  .working::before{content:"";flex:none;width:14px;height:14px;border-radius:50%;
    border:2px solid color-mix(in srgb,var(--mint) 25%,transparent);border-top-color:var(--mint);animation:working-spin .8s linear infinite}
  @keyframes working-spin{to{transform:rotate(1turn)}}
  @media (prefers-reduced-motion:reduce){.working::before{animation-duration:2.4s}}

  .toggle-list{display:flex;flex-direction:column;gap:5px}
  .toggle-list_row{display:grid;grid-template-columns:10px minmax(0,1fr) auto;gap:12px;align-items:center;
    padding:11px 13px;border-radius:var(--radius-small);background:var(--face);box-shadow:var(--up);margin:0}
  .toggle-list_text{min-width:0;display:flex;flex-direction:column;gap:2px}
  .toggle-list_text b{font-size:var(--t-small);font-weight:600;color:var(--ink)}

  .pill-list{display:flex;flex-wrap:wrap;gap:5px;min-width:0}

  /* the house adds the neutral tone and the dot the status chips carry */
  .chip.is-slate{color:var(--ink-3)}
  .chip_dot{width:6px;height:6px;transform:rotate(45deg);background:currentColor;flex:none}
  .toggle-list_row input[type=checkbox]{width:17px;height:17px;accent-color:var(--mint);cursor:pointer}
  .toggle-list_row:has(input:checked){box-shadow:var(--up),inset 0 0 0 1px color-mix(in srgb,var(--mint) 26%,transparent)}

  /* ---- changing shells ---- */
  /* ---- CHANGING SHELLS ------------------------------------------------
     Block name is `swap`, deliberately not `switch`: `.switch` above is the
     toggle, and a <main class="switch"> inherits its pill and inset shadow. */
  /* One 1.35s moment. Timeline: the grid dives in and a beam of the
     destination's colour crosses (0–1.1s); the mark lands and its ring counts
     the wait (0–1.35s); the name rises (.15s); at the end the whole stage
     punches toward you, so the redirect feels like passing through it.
     Only transform, opacity and one 120px stroke move. */
  .swap_body{margin:0;min-height:100svh;display:grid;place-items:center;overflow:hidden;
    background:var(--field);padding-inline:var(--space-medium)}
  .swap_zoom{position:fixed;inset:0;z-index:0;pointer-events:none;
    animation:swapDive 1.35s cubic-bezier(.16,1,.3,1) both}
  .swap_beam{position:fixed;top:0;bottom:0;left:0;width:45vw;z-index:1;pointer-events:none;opacity:0;
    background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--to) 10%,transparent) 42%,
      color-mix(in srgb,var(--to) 55%,transparent) 49.6%,var(--to) 50%,color-mix(in srgb,var(--to) 55%,transparent) 50.4%,
      color-mix(in srgb,var(--to) 10%,transparent) 58%,transparent);
    animation:swapBeam 1.1s cubic-bezier(.45,0,.2,1) .08s both}

  .swap{position:relative;z-index:2;display:flex;flex-direction:column;align-items:center;text-align:center;
    gap:var(--space-xsmall);animation:swapPunch .2s ease-in 1.15s forwards}
  .swap_mark{position:relative;width:120px;height:120px;display:grid;place-items:center;margin-bottom:var(--space-small);
    border-radius:50%;box-shadow:0 0 60px color-mix(in srgb,var(--to) 22%,transparent)}
  .swap_ring{position:absolute;inset:0;width:100%;height:100%;transform:rotate(-90deg)}
  .swap_ring circle{fill:none;stroke-width:2.5}
  .swap_ring-track{stroke:rgba(255,255,255,.06)}
  .swap_ring-run{stroke:var(--to);stroke-linecap:round;stroke-dasharray:352;stroke-dashoffset:352;
    animation:swapRing 1.35s cubic-bezier(.35,0,.25,1) forwards}
  .swap_letters{width:84px;height:84px;display:grid;place-items:center;border-radius:50%;
    background:var(--face);box-shadow:var(--up-lg);color:var(--to);
    font:700 22px/1 var(--font-mono);letter-spacing:var(--mono-tight);
    animation:swapLand .5s cubic-bezier(.34,1.56,.64,1) both}

  .swap_from{margin:0;font:400 var(--t-meta)/1 var(--font-ui);color:var(--ink-3);
    animation:swapFade .4s ease-out .1s both}
  .swap_title{margin:0;font:800 var(--t-display)/var(--lead-tight) var(--font-display);
    letter-spacing:var(--track-display);color:var(--ink);animation:swapRise .55s cubic-bezier(.16,1,.3,1) .15s both}
  .swap_note{margin:0;font:600 var(--t-label)/1 var(--font-ui);color:var(--to);animation:swapFade .4s ease-out .3s both}
  .swap_skip{position:fixed;bottom:var(--space-medium);left:50%;transform:translateX(-50%);z-index:2;
    font:400 var(--t-meta)/1 var(--font-ui);color:var(--ink-3);opacity:.55}
  .swap_skip:hover,.swap_skip:focus-visible{opacity:1;color:var(--ink)}

  @keyframes swapDive{from{transform:scale(1.18);opacity:.25}to{transform:none;opacity:1}}
  @keyframes swapBeam{0%{transform:translateX(-50vw);opacity:0}15%{opacity:1}85%{opacity:1}100%{transform:translateX(150vw);opacity:0}}
  @keyframes swapRing{to{stroke-dashoffset:0}}
  @keyframes swapLand{from{transform:scale(.55);opacity:0}to{transform:none;opacity:1}}
  @keyframes swapRise{from{transform:translateY(16px);opacity:0}to{transform:none;opacity:1}}
  @keyframes swapFade{from{opacity:0}to{opacity:1}}
  @keyframes swapPunch{to{transform:scale(1.08);opacity:0}}
  @media (prefers-reduced-motion:reduce){
    .swap_zoom,.swap_beam,.swap,.swap_letters,.swap_from,.swap_title,.swap_note{animation:none}
    .swap_beam{display:none}
    .swap_ring-run{animation:none;stroke-dashoffset:0}
  }
}

/* VIEW ONLY. The key gate refuses a write from somebody who may only look
   (403); this makes the page agree, so a form they cannot use is not drawn.
   !important on purpose: in a layer, an important declaration beats every
   normal one, layered or not, so a form that is also
   a .page-stack (utilities, display:flex) or a door's unlayered sheet can no
   longer draw it back (it did, 2026-10-21). A form whose every control is
   disabled is a readout, not a write (the Workshop's items, a crew's week, read
   only), so it stays. Two things in main decide for themselves: a drawer or
   pop-up (#side, #pop) is another door's fragment, gated by that door's own
   key, and Send it to HIS (POST /his/ask) needs only the door open
   (test/view-only.test.ts). A form posting where this person MAY write (another
   door they edit: a tick, a quick add, a note) carries data-may-write, set by
   the server from the same key the gate reads (shell/may-write.ts). */
@layer components {
  main[data-access="view"] form[method="post"]:has(:is(button,input:not([type="hidden"]),select,textarea):enabled):not(#side form,#pop form,[action="/his/ask"],[data-may-write]){display:none !important}
  .head_view{margin-left:4px}
  .login_back{justify-content:center;margin-top:12px}
}

/* CLOSED. A public link of an archived or trashed company (kernel/pages/Closed.tsx): one calm card,
   the company's name and how to reach them. Not an error, so no red. */
@layer components {
  .closed_body{margin:0;min-height:100vh;display:grid;place-items:center;background:var(--field)}
  .closed{width:min(460px,92vw);padding:16px}
  .closed_card{padding:var(--space-large) var(--space-medium);border-radius:var(--radius);background:var(--body);
    display:flex;flex-direction:column;gap:16px}
  .closed_title{margin:0;font-size:var(--t-page);font-weight:700;line-height:1.2;color:var(--ink)}
  .closed_lede{margin:0;font-size:var(--t-body);color:var(--ink-2);line-height:1.6}
  .closed_contact{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:8px;font-size:var(--t-body)}
  .closed_contact a{color:var(--ink)}
}

/* SAVED WHILE YOU WERE EDITING (shell/Conflict.tsx): the saved version beside the person's own,
   side by side on a desk, stacked on a phone. */
@layer components {
  .conflict_pair{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr));gap:var(--space-medium);align-items:start}
  .conflict_card{display:flex;flex-direction:column;gap:16px}
  .conflict_list{margin:0;display:flex;flex-direction:column;gap:16px}
  .conflict_row{display:flex;flex-direction:column;gap:4px}
  .conflict_value{margin:0;font-size:var(--t-body);color:var(--ink);line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}
}

/* THE VIEWER (modules/library/rooms/Viewer.tsx): a PDF or a photo shown in the app, by the
   Library and by a job's Documents tab, so it lives here and not in one door's sheet. */
@layer components {
  .viewer_bar{display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;gap:var(--space-xsmall)}
  .viewer_name{flex:1 1 200px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .viewer_tools{display:flex;align-items:center;gap:6px}
  .viewer_tools[hidden]{display:none}
  .viewer_pdf{overflow-x:auto}
  .viewer_page{width:calc(var(--viewer-zoom, 1) * 100%);margin:0 auto var(--space-xsmall)}
  .viewer_page canvas{display:block;width:100%;height:auto;background:#fff;border-radius:2px}
  .viewer_image{display:block;max-width:100%;height:auto;margin:0 auto}
  .viewer_note{padding:var(--space-large) 0;text-align:center}
}
