/* Lemma — workload, capacity & deadline planner. The APP layer: it loads AFTER suite-kit.css (the
   shared suite design system — tokens, shell components, Geist fonts) and carries Lemma's accent +
   edition overrides, app-specific tokens (planner grid, utilisation ramp) and the domain views.
   Type is self-hosted: Geist + Geist Mono, variable woff2, OFL/MIT. */
/* @font-face (Geist + Geist Mono) → suite-kit.css, served from /static/kit/fonts/ */
:root{
  /* App-only tokens. The shared palette + semantic aliases, type stacks, surfaces, shadows, motion,
     brass and the --brand → --nav-ink/--sh1..4 chrome-shade derivation all come from suite-kit.css
     (linked before this sheet). What stays here is Lemma's own: the utilisation-heatmap ramp and the
     planner grid metrics. The Lab-edition accent override lives below (html[data-edition="lab"]). */
  --u0:#ECF0F7; --uok:#6F97D8; --ugood:#1E9E78; --uwarn:#E9A23B; --uover:#E72D3F;
  --card:#fff;          /* what `var(--card,#fff)` has always MEANT here; see the dark block */
  /* Same story as --card: used only as `var(--ink-2,#3D5A85)`, never defined, so both themes got
     the literal. These values ARE the light literals, so light is unchanged; dark now has a real one. */
  --ink-2:#3D5A85; --ink-3:#8595AB;
  --grid-line:#f0f3f8;
  --holiday:#eef1f6;
  --colw:88px; --namew:252px; --rowh:64px;
  /* An ERROR, in either edition. --red is the brand accent, and the Lab maps it to plum — the colour
     of its headings and body text — so a refusal under a field ("The name must match your account")
     and an invalid field's border read as more of the page, not as something wrong. The Company value,
     so that edition is unchanged. Dark: see the dark block. */
  --danger:#E72D3F;
}
*{box-sizing:border-box}
[hidden]{display:none!important}
html,body{margin:0}
/* Keep the viewport width constant whether or not a page is tall enough to scroll, so switching from a
   scrolling page to a short one doesn't nudge the sticky top bar / centred content sideways. Use
   overflow-y:scroll (NOT scrollbar-gutter:stable): a short page then draws a normal disabled scrollbar
   track instead of reserving an EMPTY gutter, which showed the page background as a gap beside the navy
   top bar & footer. No-op on overlay-scrollbar systems (0 width, auto-hiding). */
html{overflow-y:scroll}
/* sticky footer: body fills at least the viewport and main grows to take the slack, so short pages
   (Clients, Contracts…) push the footer to the bottom instead of letting it ride up mid-screen —
   the footer then sits in the same place whatever page you're on, no jump when swapping. */
body{font-family:var(--font);color:var(--ink);background:var(--bg);font-size:15px;line-height:1.6;-webkit-font-smoothing:antialiased;display:flex;flex-direction:column;min-height:100vh}
h1,h2,h3{letter-spacing:-.015em}
.mono{font-family:var(--mono)}
.loading{font-family:var(--font);font-weight:600;font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);padding:18px 0}

/* topbar shell (.topbar, .lab-badge, .topnav, .navbtn, .navhome, .topbar-right) → suite-kit.css.
   Lemma keeps only its own brand/logo cluster: */
.brand{display:flex;align-items:center;gap:12px;cursor:pointer}
.brand:hover{opacity:.92}
.brand-logo svg{height:26px;width:auto;display:block}
.brand-logo svg path[fill="#0D2D4B"]{fill:#fff}
.brand-logo .lemmamark{height:28px;width:28px;fill:#fff}   /* neutral Lemma aperture mark (lab/product) */
.brand-text{font-weight:600;color:#fff;font-size:15px;letter-spacing:-.01em;line-height:1.1}
.brand-text small{display:none}   /* quiet chrome: the tagline lives in the hero, not the nav bar */
/* order the top-right cluster: notifications · help · | · account avatar (rightmost, account convention) */
#notifWrap{order:1}.topbar-right .helpbtn{order:2}#acctWrap{order:3}#navToggle{order:4}
/* account menu (.acctwrap / .acctbtn / .acct-panel / .acct-item / .helpbtn) → suite-kit.css */

/* nav dropdown groups (.navdrop / .navdrop-panel / .navdrop-item / .nd-ic / .nd-tx), the main
   content container (1280px / 30px gutters), .panel switching + fade, and .loadveil → suite-kit.css */
.loadveil .spin{width:28px;height:28px;border:3px solid var(--rule,#e5e7eb);border-top-color:var(--red,#870052);border-radius:50%;animation:lvspin .7s linear infinite}
@keyframes lvspin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion: reduce){.loadveil .spin{animation:none;border-top-color:var(--rule,#e5e7eb)}}
/* focus — one consistent keyboard-only ring on controls that were missing one (inputs keep their own
   box-shadow ring). --focus-ring, NOT --blue: the kit retuned the ring token (bd12911) because --blue
   measures 2.72:1 on --bg — under the 3:1 non-text floor — and this zero-specificity rule loads after
   suite-kit.css, so keeping --blue here silently overrode the kit's fix app-wide. :where() = 0 specificity. */
:where(a,button,[tabindex="0"],.seg button,.navbtn,.navhome,.acct-item,.navdrop-item,.acctbtn,.helpbtn,.jbtn,.backbtn,.todo-row,.mw-act):focus-visible{outline:2px solid var(--focus-ring,var(--blue));outline-offset:2px}
/* smooth the hovers the audit found snapping with no transition */
.todo-row,.gs-x,.drift-dismiss,.mw-undo,.mw-act,.brand,.jbtn,.wknav button,.backbtn{transition:background var(--t1) var(--ease),color var(--t1) var(--ease),border-color var(--t1) var(--ease),opacity var(--t1) var(--ease)}
/* global reduced-motion (near-instant everything) → suite-kit.css */

/* ---- proposal writing surface: a page, not a form box ------------------------------------- */
/* Notes — a two-pane notebook: the rail is what you have, the right pane is the one you are in.
   No dialog. A note IS the content, so a modal around it would be a frame around a frame — and the
   writing surface is .prop-page unchanged, because that is already this app's answer to "a long
   piece of text somebody is typing", down to the 78ch measure and the styled backdrop. */
/* A wider rail, because a card needs width to be a card. 264px held a single column of near-bare
   rows; 300px lets a note show its title, its preview and its footer without any of them truncating
   to one word. */
.noteswrap{display:grid;grid-template-columns:300px minmax(0,1fr);gap:20px;align-items:start}
/* Two-up on a large display. The reading column keeps its 78ch either way, so the space a wide
   monitor adds is spent on finding notes rather than on stretching the one being written. 240px
   minimum + 8px gap means the second column appears exactly when the rail passes ~500px. */
@media (min-width:1500px){ .noteswrap{grid-template-columns:520px minmax(0,1fr)} }
/* ⚠ A GRID, not a flex column — this is what makes the rail WRAP. auto-fill + minmax means the rail
   lays out one column at 300px and two the moment it is given room (the 2-up rail below 1440px), and
   a card keeps its own height instead of being stretched by its neighbour. */
.noterail{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:8px;
  align-content:start;max-height:72vh;overflow:auto;padding:2px 4px 2px 2px}
/* The row is a CARD now: a surface of its own, a hairline, a soft lift on hover. It was a borderless
   strip that only differed from its neighbours by 2px of gap, which is most of why the section read
   as dated. */
.noterow{display:grid;gap:4px;text-align:left;padding:11px 12px;border:1px solid var(--rule,#E7ECF3);
  border-radius:12px;background:var(--panel);cursor:pointer;font:inherit;color:inherit;
  box-shadow:0 1px 1px rgba(21,45,73,.03);
  transition:box-shadow var(--t1,.15s) var(--ease,ease),border-color var(--t1,.15s) var(--ease,ease),
             transform var(--t1,.15s) var(--ease,ease)}
.noterow:hover{background:var(--panel);border-color:var(--rule-blue);
  box-shadow:0 2px 8px rgba(21,45,73,.07);transform:translateY(-1px)}
/* ⚠ The selected accent is var(--blue), NOT var(--brand). --brand is the NAVY here, which against
   the dark theme's panel is very nearly the panel itself — a selected card would have been
   indistinguishable from an unselected one in dark. */
.noterow.on{background:var(--blue-soft);border-color:var(--blue,#2C4360);
  box-shadow:0 2px 10px rgba(21,45,73,.10)}
.noterow.on>b{color:var(--navy)}
/* Two lines, then clamp. A one-line ellipsis turned most titles into three words and a dot; the
   card has the room, and a note is found by its title. */
.noterow>b{font-size:13.5px;font-weight:600;line-height:1.3;color:var(--navy);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.noterow>.lmuted{font-size:12px;line-height:1.45;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.noterow .notewhen{font-size:11px;font-variant-numeric:tabular-nums}
.notehead{display:flex;gap:10px;align-items:center;max-width:78ch;margin:0 auto}
/* The title is a heading that happens to be editable — no box, no label. The rule appears on focus
   so the field is discoverable without drawing a form around a page of prose. */
.notetitle{flex:1;min-width:0;font-family:var(--font);font-size:19px;font-weight:600;color:var(--navy);
  background:none;border:0;border-bottom:1px solid transparent;padding:5px 0}
.notetitle:focus{outline:none;border-bottom-color:var(--rule-blue)}
.notesaved{font-size:11.5px;min-width:56px;text-align:right}
.noteseg{margin-bottom:8px;
  /* The rail is a column flexbox, whose default align-items:stretch pulled this segmented control
     to the rail's full 260px while its two buttons measure 101 — a bordered box two thirds empty,
     sitting above the notes it filters. .seg is inline-flex precisely so it hugs its buttons; in a
     stretch context that intent is overridden, so say it here. */
  align-self:flex-start;
  /* ⚠⚠ AND IT MUST NOT SHRINK. The Archived button VANISHED once you had enough notes to make the
     rail scroll, which is flexbox automatic minimum size doing exactly what it is specified to do:
     an item's min-height:auto resolves to its content height ONLY while its overflow is visible.
     The kit gives every .seg `overflow:hidden` (suite-kit.css), so THIS item's automatic minimum is
     0 and it is infinitely shrinkable — while .noterow declares no overflow, so every row's minimum
     equals its content and rows cannot give up a pixel. The rail's whole negative free space
     therefore lands on the one flexible item, which collapses to zero height and hides its own
     overflow. The control was still in the DOM, still clickable in principle, and 0px tall.
     ⚠ Do NOT "fix" the mobile rule (max-width:860px) the same way — there the rail is a ROW and
     .noterow{min-width:190px}, so it is a different overflow with a different answer. */
  flex:none;
  /* ⚠ AND THE GRID EQUIVALENT. The rail is a wrapping grid now, where `flex:none` is inert — the
     control would instead be laid into the first 150px track like a card and sit beside a note.
     Spanning every column keeps it a full-width header; justify-self keeps it hugging its buttons
     rather than stretching, which is what align-self:flex-start did under flex. */
  grid-column:1/-1;justify-self:start}
/* The note body and its heading are a centred 78ch reading column, so the formatting bar has to sit
   in the same column or it hangs 75px to the left of the note it formats — which is where it was.
   A wrapper rather than a rule on .mdbar itself: the other seven bars live directly above their own
   textarea in a dialog and must keep hugging it. */
.notebar{max-width:78ch;margin:0 auto}

.noteseg button{font-size:11.5px;padding:4px 9px}
.noterowfoot{display:flex;align-items:center;justify-content:space-between;gap:6px;min-height:18px}
.noterowfoot .pill{font-size:8.5px}

/* A pill that navigates. Inherits the pill's look so the row does not gain a second visual language;
   the affordance is the pointer and the hover, not a different shape. */
.pill-link{font:inherit;border:0;cursor:pointer;text-decoration:none}
.pill-link:hover{background:color-mix(in srgb,var(--brand) 12%,transparent);color:var(--navy)}
.pill-link:focus-visible{outline:2px solid var(--navy);outline-offset:1px}
/* Who shared it, said once above the text rather than as a badge beside every line. A note somebody
   else wrote should read as theirs before you start typing in it. */
.notefrom{max-width:78ch;margin:0 auto 2px;font-size:12px}
.asg-chip.noteshare{gap:4px}
/* The three share rungs have to be told apart at a glance — "can edit" is a real grant and looked
   identical to "can read" until now. `.on` already inverts to brand for shared-at-all; can-edit
   adds a ring so the stronger grant is the stronger mark. */
.asg-chip.noteshare.can-edit{box-shadow:0 0 0 2px var(--blue-soft) inset;font-weight:600}
.asg-chip.noteshare.on .lmuted{color:rgba(255,255,255,.82)}   /* .on inverts to brand; keep the tail legible */
@media (max-width:860px){
  .noteswrap{grid-template-columns:1fr}
  .noterail{max-height:210px;flex-direction:row;overflow-x:auto}
  .noterow{min-width:190px}
  .noterow>.lmuted,.noterow .notewhen{display:none}   /* a phone rail is a switcher, not a preview */
}

.prop-page{background:var(--surface);border:1px solid var(--rule,#e5e7eb);border-radius:14px;box-shadow:0 1px 2px rgba(21,45,73,.04),0 6px 22px rgba(21,45,73,.05);padding:40px 48px;max-width:78ch;margin:14px auto 0}
@media(max-width:820px){.prop-page{padding:22px 20px}}
/* ⚠ THE READING MARGIN BELONGS TO THE FIELD, NOT TO THE CARD AROUND IT. `.prop-page` carries 48px
   of padding, so the strip you naturally begin a sweep in — a few pixels left of the first character
   — was OUTSIDE the textarea. The drag then selected the BACKDROP's shadow copy instead: a highlight
   appeared, the field itself never got the selection, and you could not type over what looked
   selected. Reported as "can't highlight some text", and measured in a browser before this.
   The wrap pulls back across that margin and pads itself by the same amount, so nothing moves on
   screen and the hit area now reaches the edge of the card.
   ⚠⚠ `.prop-ta` MUST CARRY THE SAME PADDING. It is `position:absolute;inset:0`, so its containing
   block is the wrap's PADDING box, while the backdrop is an in-flow child living in the CONTENT box.
   Padding one and not the other separates the two layers by exactly that much — the register bug
   this file exists to avoid. */
.prop-ta-wrap{position:relative;min-height:44vh;margin:0 -48px;padding:0 48px}
.prop-backdrop,.prop-ta{font-family:inherit;font-size:15.5px;line-height:1.75;letter-spacing:.005em;white-space:pre-wrap;overflow-wrap:break-word;word-break:break-word}
.prop-backdrop{color:var(--navy,#152D49);pointer-events:none;min-height:44vh}
.prop-backdrop .prop-hl{font-weight:700;color:var(--red,#870052)}
.prop-backdrop .prop-over{background:rgba(231,45,63,.10);color:#b03030;border-radius:2px}
/* markdown-ish emphasis — METRICS-SAFE styles only (the backdrop must mirror the textarea exactly):
   faux-bold via text-shadow (no advance-width change) + synthesized oblique (sheared glyphs, same widths) */
.prop-backdrop .prop-b{text-shadow:.6px 0 0 currentColor}
.prop-backdrop .prop-i{font-style:italic}
.prop-backdrop .prop-bi{text-shadow:.6px 0 0 currentColor;font-style:italic}
.prop-backdrop .prop-mk{opacity:.32}
.prop-ta{position:absolute;inset:0;width:100%;height:100%;background:transparent;color:transparent;caret-color:var(--navy,#152D49);border:0;outline:0;resize:none;overflow:hidden;padding:0 48px;margin:0;box-shadow:none}
/* ⚠ AFTER the two rules it overrides, not beside `.prop-page`'s own breakpoint. A media query adds
   no specificity, so an override written earlier in the file simply loses to the base rule and does
   nothing at any width. */
@media(max-width:820px){.prop-ta-wrap{margin:0 -20px;padding:0 20px}.prop-ta{padding:0 20px}}
.prop-ta::placeholder{color:var(--faint,#9aa4b2)}
.prop-ta:focus{border:0;outline:0;box-shadow:none}
/* limit meter — a hairline that fills toward the limit */
.prop-meter{height:3px;border-radius:2px;background:var(--panel,#eef1f5);overflow:hidden;flex:1;min-width:140px}
.prop-meter i{display:block;height:100%;border-radius:2px;background:var(--red,#870052);transition:width .25s ease,background .25s ease}
.prop-meter i.warn{background:#d98e04}.prop-meter i.over{background:#c0392b}
/* rail mini progress */
.prop-minibar{display:block;height:2px;border-radius:1px;background:var(--panel,#eef1f5);margin-top:5px;overflow:hidden}
.prop-minibar i{display:block;height:100%;background:var(--red,#870052);opacity:.75}
.prop-minibar i.warn{background:#d98e04}.prop-minibar i.over{background:#c0392b}
/* focus (zen) mode — hide the rail + comments, centre the page */
.prop-zen .prop-railcol{display:none}
.prop-zen .prop-grid{grid-template-columns:1fr !important}
/* ⚠ THE DRAFT TAB NEVER COLLAPSED, and the damage was not the grid. `250px 1fr` is an INLINE style
   (app.js builds it), so it held at every width and gave the page ~534px of content in a 375px
   viewport. On mobile the LAYOUT VIEWPORT widens to the overflow, which is the containing block for
   `position:fixed` — so #modal, sized `inset:0`, became 534px wide and centred every dialog in the
   app 80px off the right edge of the screen. The tab looked merely cramped; what it actually did
   was put every modal opened from it out of reach. Found by measuring the document, not the card.
   `!important` because the declaration it overrides is inline — the same reason the zen rule above
   needs it. */
@media(max-width:700px){
  .prop-grid{grid-template-columns:1fr !important}
  .prop-railcol{max-height:220px;overflow:auto}
}
.prop-zen .prop-page{max-width:72ch}
.prop-zen .prop-comments,.prop-zen .prop-fillpanel{display:none}
/* per-section comments */
.prop-comments{max-width:78ch;margin:14px auto 0}
.prop-comment{display:flex;gap:10px;align-items:flex-start;padding:8px 2px;border-top:1px solid var(--rule,#e5e7eb)}
.prop-comment.resolved{opacity:.5}
.prop-comment .pc-body{flex:1;min-width:0;font-size:13px;color:var(--navy);white-space:pre-wrap;overflow-wrap:break-word}
.prop-comment .pc-meta{font-size:11px}
.prop-comment .pc-act{cursor:pointer;font-size:12px;border:0;background:none;color:var(--muted,#5C6B80);padding:2px 4px}
.prop-comment .pc-act:hover{color:var(--navy)}

.pagehead{position:relative;padding-top:26px;margin-bottom:20px}
.pagehead::before{content:"";display:none;position:absolute;top:-30px;right:0;width:250px;height:300px;z-index:0;
  opacity:.5;transform:rotate(-7deg);
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64' fill='%23E9E2EE'%3E%3Cpath fill-rule='evenodd' d='M5,32 a27,27 0 1,0 54,0 a27,27 0 1,0 -54,0 Z M9,32 a23,23 0 1,0 46,0 a23,23 0 1,0 -46,0 Z M32,17 L45,24.5 L45,39.5 L32,47 L19,39.5 L19,24.5 Z M32,21 L41.5,26.5 L41.5,37.5 L32,43 L22.5,37.5 L22.5,26.5 Z'/%3E%3C/svg%3E") no-repeat center/contain}
.pagehead>*{position:relative;z-index:1}
.eyebrow{font-family:var(--mono);font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.1em;color:var(--faint);margin-bottom:8px}
.pagehead h1{font-size:34px;font-weight:500;letter-spacing:-.022em;line-height:1.05;margin:0;color:var(--navy)}
.pagehead h1 .a{color:var(--red)}
.deck{font-size:17px;color:var(--soft);line-height:1.5;max-width:680px;margin:12px 0 0}

/* ---------------- brand elements (door-mark motif) ---------------- */
@keyframes dmPulse{0%,100%{opacity:.5;transform:scale(.96)}50%{opacity:1;transform:scale(1)}}
/* boot splash — red door-mark on navy, matching the app icon */
#boot{position:fixed;inset:0;z-index:200;background:var(--brand);display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:20px;transition:opacity .45s ease;opacity:1}
#boot.gone{opacity:0;pointer-events:none}
#boot .boot-door{width:122px;height:122px;animation:dmPulse 1.4s ease-in-out infinite}
/* Duotone, and only at THIS size. The mark is one aperture — a ring around a hex core — and the
   two elements can carry the two editions: Company red around Lab teal. It is legible at 122px
   and MEASURED NOT TO BE at the 26px the sign-in card uses, which is why the gate solves the
   same problem with its ground instead of its mark. */
#boot .boot-door .bd-ring{fill:var(--red)}
#boot .boot-door .bd-hex{fill:#4DB5BC}
#boot .boot-word{font-family:var(--font);font-weight:700;font-size:46px;color:#fff;letter-spacing:.005em;line-height:1}
#boot .boot-sub{font-family:var(--mono);font-size:10px;text-transform:uppercase;letter-spacing:.22em;color:#7E93B2}
/* Lab edition (set on <html> by the server from default_mode, or echoed from localStorage on a
   return visit): paints the BOOT SPLASH in the KI plum brand. It no longer reaches the sign-in gate —
   see #gate below, which is deliberately edition-neutral because it renders before we know who is
   signing in. These set the --rda-* override
   layer so the gate is themed before applyBrand() runs (which only fires once an org is loaded); for
   a signed-in org, applyBrand's inline vars take precedence and recolour per the org's edition. */
html[data-edition="lab"]{--rda-navy:#870052;--rda-red:#4F0433;--rda-blue:#4DB5BC}
html[data-edition="lab"] #boot{background:#870052}
html[data-edition="lab"] #boot .boot-door .bd-ring,
html[data-edition="lab"] #boot .boot-door .bd-hex{fill:#4DB5BC}
html[data-edition="lab"] #boot .boot-sub{color:#D58FB9}
/* first-run gate — sign-in / onboarding overlay (auth-enabled deployments only) */
/* EDITION-NEUTRAL BY CONSTRUCTION. This screen renders before we know who is signing in, so it
   cannot wear their edition's brand — and it used to wear the DEPLOYMENT's, which meant a first-time
   visitor to a Company workspace was met with the Lab edition's KI plum front door. The house canvas
   belongs to neither edition, so neither reads as wrong: near-white ground, navy ink, one red accent,
   and the rotated-square motif the marketing site uses. The --rda-* reset is what makes it neutral —
   without it the Lab override upstream still recolours the button and the wordmark. Once an org is
   known, applyBrand recolours everything inside the app exactly as before. */
#gate{position:fixed;inset:0;z-index:210;display:flex;align-items:center;justify-content:center;
  padding:24px;overflow:auto;background:#EEF2F9;
  /* PIN THE HOUSE SCALE, don't just re-declare --rda-*. The semantic tokens (--navy, --red, --blue…)
     are derived from --rda-* in suite-kit.css AT :root, so their computed values inherit down and a
     lower re-declaration of --rda-* never reaches them — the ground went neutral while the wordmark,
     the mark and the button stayed KI plum. Same technique the dark-mode rule below already uses to
     hold a light card on a dark page. */
  --rda-navy:#152D49;--rda-red:#E72D3F;--rda-blue:#6F97D8;
  --ink:#152D49;--navy:#152D49;--soft:#2C4360;--muted:#5A6A82;--faint:#7D8A9E;--ghost:#A7AFBE;
  --red:#E72D3F;--blue:#6F97D8;--rule:#E7ECF3;--rule-blue:#C8D2E3;--field:#fff;--field-line:#C8D2E3;
  --panel:#F6F8FC;--blue-soft:#ECF0F7;
  /* --brand and --red-fill are the two that were still leaking KI plum after the ink scale was
     pinned: the button reads --red-fill, NOT --red (a deliberate split), and --brand is the chrome
     ground. Values read off a Company render rather than guessed. */
  --brand:#152D49;--red-fill:#E72D3F;--red-fill-dark:#C4002A}
/* The marketing site's one signature motif: a large soft-blue rounded square rotated -12deg, bled
   off the top-right at low opacity. Sized and offset so only a corner is in frame — it should read
   as a quiet wash behind the card, not as a shape competing with it. */
#gate::before{content:"";position:absolute;top:-300px;right:-260px;width:820px;height:820px;
  border-radius:96px;background:#DBE3F0;opacity:.4;transform:rotate(-12deg);pointer-events:none}
.gate-card{position:relative;background:#fff;border:1px solid #E7ECF3;border-top:4px solid #E72D3F;
  border-radius:14px;padding:28px 32px 34px;width:440px;max-width:94vw;
  box-shadow:0 18px 50px rgba(21,45,73,.16)}
.gate-brand{display:flex;align-items:center;gap:10px;margin-bottom:22px}
.gate-brand .lemmamark{width:30px;height:30px;fill:var(--red)}
.gate-brand span{font-family:var(--font);font-weight:700;font-size:22px;color:var(--navy);letter-spacing:.005em}
.gate-card h2{margin:0 0 4px;font-size:24px;font-weight:500;letter-spacing:-.02em;color:var(--navy)}
.gate-sub{margin:0 0 20px;color:var(--muted);font-size:14px}
.gate-card label{display:block;font-weight:600;font-size:10px;text-transform:uppercase;
  letter-spacing:.07em;color:var(--faint);margin:14px 0 5px}
.gate-card input{width:100%;font-family:var(--font);font-size:14px;padding:9px 11px;
  border:1px solid var(--rule-blue);border-radius:6px;color:var(--ink);box-sizing:border-box}
.gate-card input:focus{outline:none;border-color:var(--blue)}
.gate-opt{font-family:var(--font);text-transform:none;letter-spacing:0;color:var(--ghost);font-weight:400}
.gate-go{width:100%;margin-top:22px;padding:12px;font-size:13px}
.gate-ms{width:100%;padding:12px;font-size:13px}
.gate-rule{display:flex;align-items:center;gap:12px;margin:22px 0 4px;color:var(--ghost);
  font-family:var(--mono);font-size:9.5px;text-transform:uppercase;letter-spacing:.16em}
.gate-rule::before,.gate-rule::after{content:"";flex:1;height:1px;background:var(--rule-blue)}
.gate-editions{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.gate-ed{text-align:left;padding:12px 13px;border:1.5px solid var(--rule-blue);border-radius:9px;
  background:#fff;cursor:pointer;display:flex;flex-direction:column;gap:3px;transition:border-color .12s,background .12s}
.gate-ed b{font-family:var(--font);font-size:14px;color:var(--navy)}
.gate-ed span{font-size:11.5px;color:var(--muted);line-height:1.35}
.gate-ed:hover{border-color:var(--blue)}
.gate-ed.on{border-color:var(--red);background:var(--blue-soft)}
.gate-inv{display:flex;gap:8px;margin-bottom:8px}
.gate-inv input{flex:1}
.gate-inv select{font-family:var(--font);font-size:13px;padding:0 8px;border:1px solid var(--field-line,var(--rule-blue));
  border-radius:6px;color:var(--ink);background:var(--field,#fff)}
.gate-inv .gate-invx{flex:0 0 auto;width:34px;border:1px solid var(--field-line,var(--rule-blue));border-radius:6px;
  background:var(--field,#fff);color:var(--faint);cursor:pointer;font-size:15px}
.gate-inv .gate-invx:hover{border-color:var(--red);color:var(--red)}
.gate-addinv{background:none;border:none;color:var(--red);font-family:var(--font);font-weight:700;
  font-size:12.5px;cursor:pointer;padding:2px 0}
.gate-addinv:hover{color:var(--red-dark)}
.gate-err{margin-top:12px;color:var(--red);font-size:13px}
/* in-app door loader — small pulsing door + label */
.doorload{display:flex;align-items:center;gap:11px;padding:20px 0;color:var(--faint);
  font-weight:600;font-size:10.5px;text-transform:uppercase;letter-spacing:.06em}
.doorload .dm{width:22px;height:28px;fill:var(--blue);animation:dmPulse 1.3s ease-in-out infinite}
.profpage>.doorload{justify-content:center;padding:52px 0}
/* skeleton loaders — content-shaped shimmer placeholders shown while data loads (calmer than a spinner,
   and the layout doesn't jump when content lands). Theme-adaptive; the sweep stills under reduced-motion. */
.skel-wrap{animation:fade var(--t2) var(--ease)}
.skel{position:relative;overflow:hidden;border-radius:7px;background:color-mix(in srgb,var(--rule,#E7ECF3) 62%,var(--surface,#fff))}
.skel::after{content:"";position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--surface,#fff) 72%,transparent),transparent);animation:skelShimmer 1.35s ease-in-out infinite}
@keyframes skelShimmer{100%{transform:translateX(100%)}}
.skel-row{display:flex;align-items:center;gap:14px;padding:13px 6px;border-bottom:1px solid var(--rule,#E7ECF3)}
.skel-row .skel{height:13px}
.skel-card{border:1px solid var(--rule,#E7ECF3);border-radius:12px;padding:15px 16px}
@media (prefers-reduced-motion: reduce){.skel::after{animation:none;opacity:0}.skel-wrap{animation:none}}
/* branded empty state (.empty / .empty-mini + the .dm glyph fill) → suite-kit.css */
/* .btn.btn-sm → suite-kit.css */
/* first-run "Get started" checklist (home, admins, new org) */
.getstarted{background:var(--surface);border:1px solid var(--card-line);border-radius:16px;padding:16px 18px;margin:0 0 22px;box-shadow:var(--shadow-card)}
/* the collapsed form of the above: one quiet line naming the next step, once setup is under way */
.gs-mini{display:flex;align-items:center;gap:10px;margin:0 0 16px;padding:8px 12px;border-radius:10px;
  background:var(--panel);border:1px solid var(--rule);font-size:12.5px;color:var(--muted)}
.gs-mini-prog{font-family:var(--mono);font-size:11px;font-weight:700;color:var(--brand);
  background:var(--surface);border:1px solid var(--rule);border-radius:999px;padding:1px 8px}
.gs-mini-txt{flex:1 1 auto;min-width:0}
.gs-mini-txt b{color:var(--navy);font-weight:600}
.gs-mini .gs-x{margin-left:0}
.gs-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
.gs-title{font-weight:700;color:var(--navy);font-size:15px}
.gs-prog{font-family:var(--mono);font-size:11px;color:var(--muted);margin-left:10px;font-weight:500}
.gs-x{background:none;border:none;color:var(--faint);font-size:20px;line-height:1;cursor:pointer;padding:0 4px}
.gs-x:hover{color:var(--navy)}
.gs-steps{display:flex;flex-direction:column;gap:8px}
.gs-step{display:flex;align-items:center;gap:12px;padding:10px 12px;border:1px solid var(--rule);border-radius:9px}
.gs-step.done{background:var(--panel)}
.gs-check{flex:none;width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;background:var(--brand);color:#fff}
.gs-step.done .gs-check{background:var(--green)}
.gs-text{flex:1;display:flex;flex-direction:column;gap:1px;min-width:0}
.gs-text b{color:var(--navy);font-size:13.5px}
.gs-text span{color:var(--muted);font-size:11.5px}
.gs-done{font-size:11px;color:var(--green);font-weight:600;font-family:var(--mono)}
/* planner staffing-response banner: declined (urgent/red) or awaiting-acceptance counts */
.staffalert{display:flex;align-items:center;gap:11px;background:var(--panel);border:1px solid var(--rule);border-left:3px solid var(--blue);border-radius:10px;padding:11px 16px;margin:0 0 16px}
.staffalert.urgent{background:rgba(231,45,63,.05);border-color:color-mix(in srgb,var(--red) 30%,#fff);border-left-color:var(--red)}
@supports not (color:color-mix(in srgb,red 50%,blue)){.staffalert.urgent{border-color:var(--rule-blue)}}
.sa-ic{font-size:15px;line-height:1;color:var(--blue)}
.staffalert.urgent .sa-ic{color:var(--red)}
.sa-txt{flex:1;min-width:0;font-size:13px;color:var(--soft)}
.sa-dec{color:var(--red);font-weight:700}
.sa-awa{color:var(--muted)}
.sa-link{font-size:12.5px;font-weight:600;color:var(--navy);cursor:pointer;white-space:nowrap}
.sa-link:hover{text-decoration:underline}
/* "My work" home panel (signed-in members) — boxed to match the home cards (soft blue-tinted
   border, 14px radius, light lift) so it reads as part of the home, not a bare table. */
.mywork{background:var(--surface);border:1px solid var(--card-line);border-radius:16px;padding:20px 22px;margin:0 0 18px;box-shadow:var(--shadow-card)}
.mw-head{margin-bottom:15px}
/* section header band — a tinted strip that bleeds to the card's top + side edges so each section
   (This week, Workload radar, My work…) reads as a bold full-width header (theme/edition-aware via --panel) */
.mywork > .mw-head:first-child{margin:-20px -22px 16px;padding:13px 22px 12px;background:var(--panel);border-bottom:1px solid var(--rule,#E7ECF3);border-radius:16px 16px 0 0}
.mw-head.brief-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px}
.brief-acts{display:flex;gap:6px;flex:0 0 auto}
.mw-title{font-weight:700;color:var(--navy);font-size:15px;letter-spacing:-.01em}
.mw-subtitle{color:var(--muted);font-size:12.5px;margin-top:1px}
.mw-notify{display:inline-flex;align-items:center;gap:6px;margin-top:8px;color:var(--muted);font-size:12px;cursor:pointer}
.mw-notify input{accent-color:var(--navy);cursor:pointer}
.mw-cols{display:grid;grid-template-columns:1fr 1fr;gap:24px}
.mw-h{font-weight:600;color:var(--faint);font-size:10.5px;margin-bottom:6px;text-transform:uppercase;letter-spacing:.06em}
.mw-row{display:flex;align-items:center;gap:10px;padding:7px 0;border-top:1px solid var(--rule)}
.mw-col .mw-row:first-of-type{border-top:none}
.mw-main{flex:1;display:flex;flex-direction:column;gap:1px;min-width:0}
.mw-main b{color:var(--navy);font-size:13px}
.mw-sub{color:var(--muted);font-size:11px}
/* assignment accept/decline response control */
.mw-resp{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-top:5px}
.mw-resp:empty{display:none}
.mw-act{font:600 11px/1 var(--font);border-radius:7px;padding:4px 11px;cursor:pointer;border:1px solid}
.mw-act.ok{color:var(--green);border-color:color-mix(in srgb,var(--green) 42%,#fff);background:rgba(30,158,120,.06)}
.mw-act.ok:hover{background:rgba(30,158,120,.15)}
.mw-act.no{color:var(--red);border-color:color-mix(in srgb,var(--red) 42%,#fff);background:rgba(231,45,63,.05)}
.mw-act.no:hover{background:rgba(231,45,63,.13)}
.mw-pill{font-family:var(--mono);font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;border-radius:8px;padding:2px 8px}
.mw-pill.ok{color:var(--green);background:rgba(30,158,120,.12)}
.mw-pill.no{color:var(--red);background:rgba(231,45,63,.1)}
.mw-undo{font-size:11px;color:var(--faint);cursor:pointer;text-decoration:underline}
.mw-undo:hover{color:var(--navy)}
.mw-when{font-size:11px;color:var(--faint);font-variant-numeric:tabular-nums;white-space:nowrap}
.mw-when.soon{color:var(--amber)}.mw-when.over{color:var(--red)}
/* first-run welcome banner — shown once on an invited member's first sign-in */
.mw-welcome{position:relative;background:color-mix(in srgb,var(--brand) 5%,var(--surface));border:1px solid var(--card-line);border-left:3px solid var(--brand);border-radius:12px;padding:15px 18px;margin:0 0 16px}
.mw-welcome-title{font-weight:700;color:var(--navy);font-size:15.5px;letter-spacing:-.01em}
.mw-welcome-lede{color:var(--muted);font-size:12.5px;line-height:1.5;margin:6px 0 12px;max-width:64ch}
.mw-welcome-x{position:absolute;top:9px;right:11px;background:none;border:none;color:var(--faint);font-size:14px;line-height:1;cursor:pointer;padding:2px}
.mw-welcome-x:hover{color:var(--navy)}
.mw-welcome-fte label{display:block;font-weight:600;color:var(--faint);font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;margin-bottom:6px}
.mw-welcome-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.mw-welcome-row input{width:74px;padding:6px 8px;border:1px solid var(--card-line);border-radius:8px;font:600 13px/1 var(--font);color:var(--navy);background:var(--surface)}
.mw-welcome-row>span{color:var(--muted);font-size:12.5px}
.mw-welcome-actions{margin-top:14px}
/* Workload Radar — drift rows (Company home panel) */
.drift-list{margin-top:4px}
.drift-item{display:flex;align-items:center;gap:13px;padding:11px 0;border-top:1px solid var(--rule)}
.drift-item:first-child{border-top:none}
.drift-bar{flex:0 0 auto;width:3px;align-self:stretch;min-height:30px;border-radius:3px;background:var(--faint)}
.drift-body{flex:1 1 auto;min-width:0}
.drift-l1{display:flex;align-items:center;gap:9px;flex-wrap:wrap;line-height:1.15}
.drift-proj{font-weight:600;color:var(--navy);font-size:13.5px;letter-spacing:-.005em}
.drift-tag{font:600 8.5px/1 var(--mono);text-transform:uppercase;letter-spacing:.08em;border-radius:999px;padding:3px 9px;white-space:nowrap}
.drift-note{color:var(--muted);font-size:12px;margin-top:3px;line-height:1.3}
.drift-stat{color:var(--navy);font-weight:600}
.drift-acts{display:flex;align-items:center;gap:10px;flex:0 0 auto}
.drift-acts .btn-sm{white-space:nowrap}
.drift-dismiss{font:500 12px/1 var(--font);color:var(--faint);cursor:pointer;background:none;border:0;padding:4px 2px}
.drift-dismiss:hover{color:var(--navy)}
.drift-item.over-running .drift-bar{background:var(--red)}
.drift-item.over-running .drift-tag{color:var(--red);background:rgba(231,45,63,.09)}
.drift-item.stalled .drift-bar{background:var(--amber)}
.drift-item.stalled .drift-tag{color:var(--amber);background:rgba(233,162,59,.16)}
.drift-item.under-running .drift-bar{background:var(--blue)}
.drift-item.under-running .drift-tag{color:var(--blue);background:rgba(111,151,216,.15)}
.drift-item.unplanned .drift-bar{background:var(--navy-soft)}
.drift-item.unplanned .drift-tag{color:var(--navy-soft);background:var(--panel)}
.drift-item.slipping .drift-bar{background:var(--amber)}
.drift-item.slipping .drift-tag{color:var(--amber);background:rgba(233,162,59,.16)}
.drift-sub{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--faint);font-weight:600;margin:12px 2px 2px}
@media (max-width:720px){
  .drift-item{flex-wrap:wrap}
  .drift-acts{width:100%;justify-content:flex-end;padding-left:16px}
}
.mw-section{margin-top:18px;padding-top:16px;border-top:1px solid var(--rule)}
.mw-empty{color:var(--muted);font-size:13px;padding:4px 0}
/* general to-dos (task manager) — a flat list row, on the To-dos page and the My-work panel */
.todo-row{display:flex;align-items:center;gap:12px;padding:11px 14px;border:1px solid var(--rule,#E7ECF3);border-radius:10px;margin-bottom:8px;background:var(--panel);cursor:pointer}
/* A derived to-do — a controlled document you owe a review. Read-only by construction, so it must
   not LOOK like the rows beside it that you can tick and drag. */
.td-derived{cursor:pointer;background:var(--blue-soft)}
.td-derived .todo-main b{font-weight:600}
.td-derived-ico{display:flex;align-items:center;justify-content:center;opacity:.5}
.tbcard.td-derived{cursor:pointer}
.todo-row:hover{border-color:var(--blue,#6F97D8)}
.todo-check{display:flex;align-items:center;cursor:pointer;flex:0 0 auto}
.todo-check input{width:17px;height:17px;cursor:pointer;accent-color:var(--blue,#6F97D8)}
.todo-main{flex:1;min-width:0;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.todo-who{font-size:12px;color:var(--navy-soft);background:var(--blue-soft);padding:1px 9px;border-radius:999px}
.todo-proj{font-size:11.5px;color:var(--muted,#5C6B80);border:1px solid var(--rule,#E7ECF3);padding:0 8px;border-radius:999px;max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tbc-proj{margin-top:3px}
.todo-sub{font-size:10.5px;color:var(--faint);text-transform:uppercase;letter-spacing:.05em}
.todo-when{font-size:12px;color:var(--muted);white-space:nowrap;flex:0 0 auto}
.todo-off{opacity:.55}
.todo-off .todo-main b{text-decoration:line-through}
/* to-dos month calendar (v0.295) — chips on due days; click a day to add one there */
.tdc-head{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.tdc-head h2{margin:0;font-size:18px;color:var(--navy);letter-spacing:-.01em;min-width:150px;text-align:center}
.tdcal{display:grid;grid-template-columns:repeat(7,1fr);border:1px solid var(--rule,#E7ECF3);border-radius:12px;overflow:hidden;background:var(--surface)}
.tdc-dow{font-family:var(--mono);font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);padding:7px 10px;border-bottom:1px solid var(--rule,#E7ECF3);background:var(--panel,#F2F5FA)}
.tdc-day{min-height:96px;padding:6px 7px;border-bottom:1px solid var(--rule,#E7ECF3);border-right:1px solid var(--rule,#E7ECF3);cursor:pointer;display:flex;flex-direction:column;gap:3px;min-width:0}
.tdc-day:nth-child(7n+1){border-right:0}
.tdc-day:hover{background:var(--panel,#F2F5FA)}
.tdc-day.out{background:color-mix(in srgb,var(--panel,#F2F5FA) 45%,var(--surface));opacity:.6}
.tdc-day.today{box-shadow:inset 0 0 0 2px var(--blue,#6F97D8)}
.tdc-num{font-family:var(--mono);font-size:10.5px;color:var(--faint)}
.tdc-day.today .tdc-num{color:var(--blue,#6F97D8);font-weight:700}
.tdc-chip{font-size:11px;line-height:1.25;padding:3px 7px;border-radius:6px;background:var(--blue-soft);color:var(--navy-soft);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}
.tdc-chip:hover{filter:brightness(.96)}
.tdc-chip.over{background:rgba(231,45,63,.1);color:var(--red)}
.tdc-chip.done{background:var(--panel,#F2F5FA);color:var(--faint);text-decoration:line-through}
/* to-do due-date urgency — a coloured left edge on list rows + board cards (over→red, ≤7d/today→amber, ≤28d→blue) */
.todo-row.td-sev-over{border-left:4px solid var(--red)}
.todo-row.td-sev-urgent{border-left:4px solid var(--amber)}
.todo-row.td-sev-soon{border-left:4px solid var(--blue,#6F97D8)}
.todo-row.td-sev-later{border-left:4px solid var(--rule,#E7ECF3)}
/* to-do kanban board — reuses .board/.bcol; cards are draggable between status columns */
.todo-board{margin-top:4px}
.tbcard{background:var(--surface);border:1px solid var(--rule,#E7ECF3);border-left:4px solid var(--rule,#E7ECF3);border-radius:9px;padding:9px 11px;margin-bottom:8px;cursor:grab;box-shadow:0 1px 2px rgba(16,32,64,.05)}
.tbcard:hover{border-color:var(--blue,#6F97D8)}
.tbcard.td-sev-over{border-left-color:var(--red)}
.tbcard.td-sev-urgent{border-left-color:var(--amber)}
.tbcard.td-sev-soon{border-left-color:var(--blue,#6F97D8)}
.tbcard.drag{opacity:.45;cursor:grabbing}
.tbc-title{font-size:13px;font-weight:600;color:var(--ink)}
.tbc-who{font-size:11.5px;color:var(--muted);margin-top:3px}
.tbc-when{font-size:11px;color:var(--muted);margin-top:4px}
.tbc-when.over{color:var(--red);font-weight:600}.tbc-when.soon{color:var(--amber)}
.tb-empty{font-size:11.5px;color:var(--faint);text-align:center;padding:14px 0;border:1px dashed var(--rule,#E7ECF3);border-radius:8px}
html[data-theme=dark] .tdc-day.out{opacity:.45}
html[data-theme=dark] .tdc-chip.done{background:rgba(255,255,255,.05)}
/* "Was July roughly as planned?" — the plan-confirmation prompt in My work. A tinted panel rather
   than another table row: it is a question, asked once for a month, not a field. */
.mw-confirm{background:var(--accent-tint,rgba(231,45,63,.06));border:1px solid var(--rule);border-radius:8px;padding:12px 14px;margin:8px 0 4px}   /* fallback: --accent-tint is only DEFINED in dark scope, so the "tinted" panel rendered transparent in light */
.mw-confirm-q{font-size:13.5px;color:var(--ink);line-height:1.35}
.mw-confirm-d{font-size:11.5px;color:var(--faint);line-height:1.45;margin-top:5px}
.mw-confirm-a{display:flex;gap:8px;margin-top:10px;flex-wrap:wrap}
.mw-toh{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:4px}
.mw-bal{margin-left:8px;font-family:var(--mono);font-size:11px;font-weight:600;color:var(--muted);background:var(--panel);border-radius:10px;padding:2px 8px;letter-spacing:0;text-transform:none}
.mw-bal.low{color:var(--red);background:rgba(231,45,63,.08)}
.mw-badge{font-family:var(--mono);font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;border-radius:9px;padding:2px 8px;white-space:nowrap}
.mw-badge.pend{color:var(--amber);background:rgba(233,162,59,.14)}
.mw-badge.ok{color:var(--green);background:rgba(30,158,120,.12)}
@media(max-width:760px){.mw-cols{grid-template-columns:1fr;gap:16px}}

.controls{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin:20px 0 18px}
.ctl-label{font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:.07em;color:var(--faint);margin-right:2px}
/* .seg segmented control → suite-kit.css */
/* ---- Search field (the list pages' type-to-filter box) ----
   Sized to the .seg it stands beside so a toolbar reads as one row of controls, wearing the app's
   own field skin instead of the browser's default input. The magnifier marks it as search without
   spending a placeholder word on it; the ✕ appears only once there's something to clear. */
/* The WRAPPER is the field — icon, input and ✕ live inside one border, so hover and focus light the
   whole control rather than a rectangle floating next to an icon. */
.searchbox{display:inline-flex;align-items:center;flex:0 1 230px;min-width:148px;height:32px;box-sizing:border-box;
  padding:0 4px 0 10px;border:1px solid var(--rule-blue);border-radius:8px;background:var(--field);
  transition:border-color var(--t1) var(--ease),box-shadow var(--t1) var(--ease)}
.searchbox:hover{border-color:color-mix(in srgb,var(--navy,#152D49) 25%,var(--rule-blue))}
.searchbox:focus-within{border-color:var(--navy,#152D49);box-shadow:0 0 0 3px color-mix(in srgb,var(--navy,#152D49) 12%,transparent)}
.searchbox>svg{width:14px;height:14px;flex:none;color:var(--faint);pointer-events:none;transition:color var(--t1) var(--ease)}
.searchbox:focus-within>svg{color:var(--navy,#152D49)}
.searchbox input{flex:1;min-width:0;height:100%;border:none;background:none;outline:none;color:var(--ink);
  font-family:var(--font);font-size:12.5px;letter-spacing:-.003em;padding:0 4px 0 8px}
.searchbox input::placeholder{color:var(--faint)}
.searchbox input::-webkit-search-cancel-button{display:none}   /* ours is better placed */
.sb-x{width:19px;height:19px;flex:none;display:none;align-items:center;justify-content:center;padding:0;
  border:none;border-radius:50%;background:none;color:var(--faint);font-size:10px;line-height:1;cursor:pointer;
  transition:color var(--t1) var(--ease),background var(--t1) var(--ease)}
.searchbox.has-q .sb-x{display:inline-flex}
.sb-x:hover{color:var(--navy,#152D49);background:color-mix(in srgb,var(--navy,#152D49) 8%,transparent)}
@media (max-width:680px){.searchbox{flex:1 1 100%}}

/* status filter tabs on the Work list pages — the homepage underline-tab look (not a pill seg) */
.filttabs{display:inline-flex;align-items:center;gap:20px}
.filttabs button{font-family:var(--font);font-weight:700;font-size:14px;letter-spacing:-.01em;color:var(--faint);background:none;border:none;border-bottom:2px solid transparent;padding:5px 1px 4px;cursor:pointer;transition:color var(--t1) var(--ease),border-color var(--t1) var(--ease)}
.filttabs button:hover{color:var(--soft)}
.filttabs button.on{color:var(--navy);border-bottom-color:var(--brand)}
.filttabs button:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
/* status tabs on their own row, sitting on the table's top edge like a header of the table */
.list-tabbar{display:flex;align-items:flex-end;border-bottom:1px solid var(--rule,#E7ECF3);margin:2px 0 0}
/* a search box may ride in the tab row (the QMS register, whose toolbar is above it) — right-aligned
   and lifted off the rule so it doesn't sit on the underline */
.list-tabbar>.searchbox{margin:0 2px 6px auto;flex:0 1 230px}
.list-tabbar .filttabs{gap:2px}
.list-tabbar .filttabs button{font-size:12.5px;font-weight:600;color:var(--muted);padding:8px 15px 9px;margin-bottom:-1px;border-bottom:2px solid transparent;border-top-left-radius:8px;border-top-right-radius:8px}
.list-tabbar .filttabs button:hover{color:var(--navy);background:color-mix(in srgb,var(--navy,#152D49) 3%,transparent)}
.list-tabbar .filttabs button.on{color:var(--navy);border-bottom-color:var(--brand);background:color-mix(in srgb,var(--navy,#152D49) 4%,transparent)}
/* the list table sits flush under the tab bar — no gap between the header rule and the column heads */
#projList>table,#clientList>table,#contractList>table,#projList .ptable,#clientList .ptable,#contractList .ptable{margin-top:0}
/* buttons (.btn / -red / -ghost / -sm) + .spacer → suite-kit.css. App-specific button variants
   (.btn-ghost.on, .btn.pj-reset, …) stay in this sheet. */
a.arrow{font-family:var(--font);font-size:13px;font-weight:700;color:var(--red);text-decoration:none;white-space:nowrap}
a.arrow::after{content:" →"}a.arrow:hover{color:var(--red-dark)}
.wknav{display:inline-flex;align-items:center;gap:8px;font-family:var(--mono);font-size:11px;color:var(--muted)}
.wknav button{border:1px solid transparent;background:rgba(28,34,51,.05);color:var(--navy);width:30px;height:30px;border-radius:8px;cursor:pointer;font-size:14px;transition:border-color .15s,background .15s}.wknav button:hover{background:rgba(28,34,51,.09)}

/* the home hero + its frosted in-hero .statband tiles now live in suite-kit.css (.home-hero .statband);
   Lemma's static hero markup + renderHomeStats() consume them. Nothing home-hero-related stays app-side. */
.dashwin{font-size:11.5px;color:var(--muted);margin:2px 0 14px;letter-spacing:.01em;font-variant-numeric:tabular-nums}
/* Dashboard scorecard — the top row reads as defined, liftable cards (not bare columns like the rest
   of the app's stat bands). Uniform-height, subtle surface, money cards carry a flush accent strip. */
#dashStats{gap:14px;align-items:stretch}
#dashStats .stat{position:relative;overflow:hidden;display:flex;flex-direction:column;padding:15px 17px;
  border-radius:13px;background:var(--panel);border:1px solid var(--rule,#E7ECF3);
  transition:border-color .15s,box-shadow .15s,transform .15s}
#dashStats .stat:hover{border-color:var(--rule-blue);box-shadow:0 6px 20px rgba(20,45,73,.08);transform:translateY(-1px)}
#dashStats .stat .meta{margin-top:auto;padding-top:5px}   /* pin the sub-label to the card floor so rows align */
#dashStats .stat.fincard{padding-left:19px}
#dashStats .stat.fincard::before{top:0;bottom:0;left:0;border-radius:0}   /* accent flush to the rounded card edge */

/* grid */
.gridcard{border:1px solid var(--card-line);border-radius:16px;box-shadow:var(--shadow-card);overflow:hidden;background:var(--surface)}
.gridwrap{overflow-x:auto;overscroll-behavior-x:contain}
.grid{min-width:max-content}
.ghead{display:flex;position:sticky;top:0;z-index:6}
.namehead{width:var(--namew);flex:0 0 var(--namew);background:var(--panel);border-bottom:1px solid var(--rule);border-right:1px solid var(--rule);position:sticky;left:0;z-index:7;display:flex;align-items:flex-end;padding:0 16px 8px;font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:.07em;color:var(--faint)}
.whead{flex:0 0 var(--colw);width:var(--colw);background:var(--panel);border-bottom:1px solid var(--rule);border-right:1px solid var(--rule);padding:8px 6px 7px;text-align:center}
.whead .m{font-family:var(--mono);font-size:9.5px;text-transform:uppercase;letter-spacing:.08em;color:var(--ghost);height:12px}
.whead .wk{font-family:var(--mono);font-size:12px;font-weight:500;color:var(--navy)}
.whead .dt{font-family:var(--mono);font-size:9.5px;color:var(--faint);margin-top:1px}
.whead.holiday{background:var(--holiday)}.whead.holiday .wk{color:var(--muted)}
.whead .hol{display:block;font-size:8.5px;color:var(--red);font-weight:600;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;line-height:1.1}
.whead.over .wk{color:var(--red)}
/* the time axis reads as a calibrated ruler — a fine brass graduation tick at each week boundary */
.whead{position:relative}
.whead::before{content:"";position:absolute;left:0;bottom:0;width:1px;height:7px;background:var(--brass);opacity:.65}

.lane{display:flex;border-bottom:1px solid var(--rule);position:relative}
.lane:last-child{border-bottom:none}
.namecell{width:var(--namew);flex:0 0 var(--namew);position:sticky;left:0;z-index:5;background:var(--surface);border-right:1px solid var(--rule);display:flex;align-items:center;gap:11px;padding:0 14px}
.namecell.leave{background:var(--surface-2)}
.av{width:32px;height:32px;flex:0 0 32px;border-radius:50%;background:var(--brand);color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:600}
.av.partner{background:var(--surface);color:var(--navy);border:1.5px dashed var(--rule-blue)}
.av.incoming{background:var(--blue-soft);color:var(--blue);border:1.5px dashed var(--blue)}
.av.ph{background:var(--surface);color:var(--blue);border:1.5px dashed var(--blue)}
.nm{min-width:0}
.nm .n{font-size:13.5px;font-weight:600;color:var(--navy);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}
.nm .r{font-size:9.5px;font-weight:500;text-transform:uppercase;letter-spacing:.05em;color:var(--faint);margin-top:2px;line-height:1.3;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}   /* clamp a long job title to 2 lines so it can't overflow the row and squeeze against the edges */
.nm .r .ft{color:var(--blue);font-weight:500}

.track{position:relative;height:var(--rowh);flex:1}
/* "Split rows by role": a thin role heading strip sits above each band's lanes (its own 15px band,
   so it never overlaps the blocks below it) */
.track .rbtag{position:absolute;left:6px;font-family:var(--mono);font-size:8px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--ghost);z-index:3;pointer-events:none;line-height:1}
.track.dropok{background:rgba(111,151,216,.12)}                                  /* valid drop target */
.track.dropover{background:rgba(231,45,63,.16);box-shadow:inset 0 0 0 2px rgba(231,45,63,.5)}  /* drop would push >100% */
.cellgrid{position:absolute;inset:0;display:flex;pointer-events:none}
.cellgrid .c{flex:0 0 var(--colw);width:var(--colw);border-right:1px solid var(--grid-line)}
.cellgrid .c.overweek{background:rgba(231,45,63,.07)}
.unavail{position:absolute;top:0;bottom:0;z-index:1;pointer-events:none;background:repeating-linear-gradient(135deg,#eceff4,#eceff4 5px,#f5f7fa 5px,#f5f7fa 10px)}
.unavail.holiday{background:repeating-linear-gradient(135deg,#e7ebf1,#e7ebf1 5px,#eef1f6 5px,#eef1f6 10px)}
.unavail.notyet{background:repeating-linear-gradient(135deg,#fafbfc,#fafbfc 6px,#fff 6px,#fff 12px)}
.unavail .ul{position:absolute;top:3px;left:5px;font-family:var(--mono);font-size:8.5px;letter-spacing:.04em;color:var(--ghost);text-transform:uppercase}
/* leave label floated ABOVE the blocks (z>blk) so a booking scheduled over the leave can't hide it.
   Kept short (top:1px, tight line) so it sits in the block's top border band, clear of the title text. */
.ultag{position:absolute;top:1px;z-index:4;pointer-events:none;font-family:var(--mono);font-size:8px;
  letter-spacing:.03em;text-transform:uppercase;color:#fff;background:var(--amber);padding:0 3px;border-radius:3px;
  line-height:1.35;box-shadow:0 1px 2px rgba(21,45,73,.25)}

.blk{position:absolute;border-radius:6px;z-index:3;cursor:grab;overflow:hidden;color:#fff;padding:5px 8px;user-select:none;touch-action:none;box-shadow:0 1px 2px rgba(21,45,73,.12)}
.blk:active{cursor:grabbing}
.blk .blk-txt{position:relative;z-index:1;display:inline-block;max-width:100%}   /* the label wrapper — inline-block so it's sized to the text (not the whole block); JS slides it to stay visible while a wide block scrolls */
.blk .pj{font-size:11.5px;font-weight:600;line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.blk .pj .pj-code{font-family:var(--mono);font-size:9.5px;font-weight:700;letter-spacing:.02em;opacity:.72;margin-right:4px}   /* project code, mono, leading the name on a timeline block */
.blk .rl{font-family:var(--mono);font-size:9px;text-transform:uppercase;letter-spacing:.05em;opacity:.92;margin-top:1px}
.blk .rl .blkpct{font-family:var(--mono);font-weight:600;letter-spacing:0;opacity:.95}   /* the % (or logged/planned), inline in the label so it pins to the left with the name */
.blk.dark{color:var(--navy)}
.blk.ph{background:var(--surface)!important;border:1.5px dashed var(--blue);color:var(--navy)}
.blk.ph .rl{color:var(--blue)}
/* plan-vs-actual fill on a block (Both mode): a thin logged÷planned bar along the bottom edge */
.blk-log{position:absolute;left:0;bottom:0;height:4px;border-radius:0 0 4px 4px;pointer-events:none;opacity:.92}
.blk-log.under{background:#F59A00}.blk-log.ok{background:#54B986}.blk-log.over{background:#E72D3F}
/* timeline 'Log' mode: planned blocks recede so the logged-hours bars read; bars sit in the bottom band */
.lane.logmode .blk{opacity:.32;cursor:default}
.lane.logmode .blk .blk-log{display:none}
.loghbar{position:absolute;bottom:3px;z-index:4;border-radius:2px;pointer-events:auto;box-shadow:inset 0 0 0 1px rgba(255,255,255,.28)}
/* per-person logged÷planned roll-up on the name cell (Logged/Both mode) */
.lvtot{font-family:var(--mono);font-size:10px;font-weight:700;text-transform:none}   /* "7h 30m", as every duration reads — not "7H 30M" from the uppercase line it sits on */
.lvtot.under{color:var(--amber)}.lvtot.ok{color:var(--green)}.lvtot.over{color:var(--red)}
.blk .rz{position:absolute;top:0;right:0;width:9px;height:100%;cursor:ew-resize}
.blk.dragging{z-index:30;opacity:.92;box-shadow:0 10px 24px rgba(21,45,73,.28)}
/* QC marker: a red inline chip at the start of the role line (not an absolute badge — so it pins with
   the label and never overlaps the % / slides out of view on a wide scrolled block) */
.blk .rl .qctag{display:inline-block;background:var(--red);color:#fff;font-family:var(--mono);font-size:8.5px;font-weight:600;line-height:1.35;padding:0 3px;border-radius:3px;letter-spacing:.02em;vertical-align:baseline}
/* a booking that overlaps the person's leave: amber left edge (the floating 'leave' tag carries the word) */
.blk.onleave::after{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--amber);border-radius:6px 0 0 6px;pointer-events:none}
/* protected / reserved capacity (R&D, retainer, teaching): hatched overlay + lock glyph */
.blk.protected{box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.55)}
.blk.protected::before{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:repeating-linear-gradient(135deg,rgba(255,255,255,.16),rgba(255,255,255,.16) 4px,transparent 4px,transparent 9px)}
.protflag{position:absolute;right:6px;bottom:3px;font-size:10px;line-height:1;opacity:.85}
/* assignee accept/decline response on a grid block: declined gets a dashed red outline; a small
   contrast badge top-right carries the ✓ / ✕ so it reads on any block colour */
.blk.declined{outline:2px dashed var(--red);outline-offset:-2px}
/* a booking the window cuts off carries on past that edge: square on the cut side, not rounded */
.blk.runs-on{border-top-right-radius:0;border-bottom-right-radius:0}
.blk.ran-in,.blk.ran-in.onleave::after{border-top-left-radius:0;border-bottom-left-radius:0}
/* inline accept/decline tick in the block label (see respFlag) — inherits the block's text colour for contrast */
.blk .rl .blktick{margin-left:5px;font-weight:800;letter-spacing:0}
.blk .rl .blktick.no{opacity:.9}
.sw.prot{background:#6F97D8;box-shadow:inset 0 0 0 1px #fff;background-image:repeating-linear-gradient(135deg,rgba(255,255,255,.5),rgba(255,255,255,.5) 2px,transparent 2px,transparent 4px)}
.heat{position:absolute;top:5px;bottom:5px;border-radius:5px;display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:11px;font-weight:500;z-index:2}   /* fill the row (top/bottom insets) so it tracks the taller capacity-row height */

.hint{font-size:12px;color:var(--muted);margin:8px 0 0;font-style:italic}
.below{display:grid;grid-template-columns:1.1fr 1fr;gap:22px;margin-top:24px}
/* .card (+ h3 / .sub) → suite-kit.css */
/* .legend/.lg/.sw* — the chart legend primitives moved to suite-kit.css: the marks are shared
   chart vocabulary now that the kit owns the --ch-* series tokens they colour. */
.sw.hatch{background:repeating-linear-gradient(135deg,#e7ebf1,#e7ebf1 3px,#eef1f6 3px,#eef1f6 6px)}
.ins{display:flex;gap:11px;padding:11px 0;border-top:1px solid var(--rule)}
.ins:first-of-type{border-top:none}
.ins .dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto;margin-top:5px}
.ins .tx{font-size:13px;color:var(--soft);line-height:1.45}.ins .tx b{color:var(--navy);font-weight:600}
.ins .tag{display:inline-block;font-family:var(--mono);font-size:8.5px;text-transform:uppercase;letter-spacing:.06em;padding:1px 6px;border-radius:3px;margin-left:4px;vertical-align:1px}
.tag.red{background:rgba(231,45,63,.12);color:var(--red-dark)}
.tag.amber{background:rgba(233,162,59,.16);color:#8A5E0F}
.tag.navy{background:var(--blue-soft);color:var(--navy-soft)}
.tag.blue{background:var(--blue-soft);color:var(--navy-soft)}

/* tables (table / th / td / .num) + .pill status chips → suite-kit.css */
tr.depd b{color:var(--navy-soft)!important}tr.depd .av{opacity:.55}tr.depd td{color:var(--muted)}
/* .cardgrid → suite-kit.css */
.pcard{border:1px solid var(--card-line);border-left:4px solid var(--blue);border-radius:12px;padding:14px 16px;background:var(--surface);box-shadow:var(--shadow-card)}
.pcard h4{margin:0 0 6px;font-size:15px;font-weight:600;color:var(--navy)}
.pcard .meta{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--faint)}
.ubar{display:flex;align-items:center;gap:12px;margin:9px 0}
.ubar .nm2{width:150px;flex:0 0 150px;font-size:13px;color:var(--soft)}
.ubar .track2{flex:1;height:18px;background:var(--panel);border-radius:4px;overflow:hidden;position:relative}
.ubar .fill{height:100%;border-radius:4px}
.ubar .v{flex:0 0 auto;min-width:46px;padding-left:8px;text-align:right;font-family:var(--mono);font-size:12px;color:var(--navy);white-space:nowrap}
.ubar .v .vsub{color:var(--faint);font-size:10.5px}
.ubar .track2 .actmark{position:absolute;top:0;bottom:0;width:3px;background:var(--ink);z-index:3;box-shadow:0 0 0 1px rgba(255,255,255,.6)}
.sw.actsw{background:var(--ink);width:3px}

.milestone{display:flex;align-items:center;gap:14px;background:var(--panel);border-left:2px solid var(--red);padding:14px 18px;margin-bottom:24px}
.milestone .dot{width:9px;height:9px;border-radius:999px;background:var(--red);flex:0 0 auto}
.milestone .txt{font-size:14px;color:var(--soft);line-height:1.5}.milestone .txt b{color:var(--navy);font-weight:600}

/* toast */
/* #toast (centre-bottom navy toast) → suite-kit.css */

/* modal */
/* backdrop-filter re-blurs the whole viewport every frame while the modal animates — the biggest cost of
   opening a "window". A 3px blur keeps the frosted look at roughly half the paint cost of 6px; saturate dropped. */
/* Overlay behaviour shared by the app's single #modal AND the standalone list-overlays (.lm-overlay).
   Enter AND exit are driven by transitions (not from-0 keyframes) so the resting shown state is always the
   cascaded opacity:1 — a modal can never be left invisible if an animation is throttled/paused — while the
   veil fades and the card lifts on the way in, and both ease back out when .show is removed (no hard cut). */
#modal,.lm-overlay{position:fixed;inset:0;background:var(--modal-veil);display:flex;align-items:center;justify-content:center;z-index:90;backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);opacity:0;visibility:hidden;pointer-events:none;transition:opacity var(--t2) var(--ease),visibility 0s linear var(--t2)}
.lm-overlay{z-index:95}
#modal.show,.lm-overlay.show{opacity:1;visibility:visible;pointer-events:auto;transition:opacity var(--t2) var(--ease),visibility 0s}
@keyframes mfade{from{opacity:0}to{opacity:1}}
@keyframes mpop{from{opacity:0;transform:translateY(12px) scale(.985)}to{opacity:1;transform:none}}
#modal .modal-card,.lm-overlay .modal-card{opacity:0;transform:translateY(12px) scale(.985);transition:opacity var(--t3) var(--ease),transform var(--t3) var(--ease)}
#modal.show .modal-card,.lm-overlay.show .modal-card{opacity:1;transform:none}
/* ⚠ 420px WAS TOO NARROW AND THE CODEBASE HAD BEEN SAYING SO 78 TIMES. That many dialogs set
   their own width rather than take this one, and the values they reach for cluster at
   440-560px — so the default was not a considered size, it was a floor everything stepped
   over. The dialogs still on it were the squashed ones: labels wrapping mid-phrase, hint
   text in four lines, and an action row that pushed a button outside the card.
   480px is the middle of what the overrides already chose. `max-width:94vw` is unchanged, so
   nothing grows on a phone. */
.modal-card{background:var(--surface);border-radius:20px;padding:26px 28px;width:480px;max-width:94vw;max-height:92vh;overflow:auto;box-shadow:0 1px 3px rgba(21,45,73,.07),0 24px 60px -12px rgba(21,45,73,.32);border:1px solid color-mix(in srgb,var(--rule) 60%,transparent)}
.modal-card h3{margin:0 0 16px;font-size:19px;font-weight:700;letter-spacing:-.015em;color:var(--navy)}
.modal-card h3+.msub{margin-top:-12px}
.msub{margin:0 0 8px;font-size:12.5px;color:var(--muted);line-height:1.45}
/* section divider inside a sleek form */
.msec{display:flex;align-items:center;gap:10px;margin:20px 0 10px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--faint)}
.msec::after{content:"";flex:1;height:1px;background:var(--rule)}
.msec:first-of-type{margin-top:8px}
/* responsive field grid (holds 2/3-up until genuinely narrow, then stacks) */
.mgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 14px}
/* The ISO echo under a native date input. A native control draws its date in the BROWSER's
   locale — 03/04/2026 on a US machine, 2026-04-03 on a Swedish one — and cannot be forced from
   the page, so the value is restated unambiguously beside it. min-height reserves the line so a
   row does not grow the first time a blank field is filled. */
.dhint{font-size:11px;color:var(--faint,#8A93A6);line-height:14px;min-height:14px;margin-top:2px;font-variant-numeric:tabular-nums}
.mgrid.c3{grid-template-columns:repeat(3,minmax(0,1fr))}
.mgrid .full{grid-column:1/-1}
.mgrid>div{min-width:0}
.mgrid label,.mgrid.c3 label{margin-top:10px}
@media(max-width:540px){.mgrid,.mgrid.c3{grid-template-columns:1fr}}
/* per-project Team rates table (in the project editor) */
.perates-tbl{width:100%;border-collapse:collapse}
.perates-tbl th{text-align:left;font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);font-weight:600;padding:2px 8px 6px}
.perates-tbl th.num,.perates-tbl td.num{text-align:right}
.perates-tbl td{padding:5px 8px;border-top:1px solid var(--rule,#E7ECF3);font-size:13px;vertical-align:middle}
.perates-tbl input.pe-rate{width:120px;height:34px;text-align:right;font-family:var(--mono);font-size:13px;padding:0 10px;margin:0}
.pe-sched{font-size:10.5px;color:var(--faint);text-align:right;margin-top:2px;white-space:nowrap}
.pe-apply{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:10px}
.pe-apply-lbl{font-size:10px;text-transform:uppercase;letter-spacing:.07em;color:var(--faint);font-weight:600}
.pe-apply .pe-effdate{width:auto;height:34px;margin:0;font-size:13px}
/* Clients list — in-place edits (colour / code / sector / contact) */
.cl-colcell{width:1%;white-space:nowrap}
.cl-colour-btn{width:26px;height:26px;padding:0;border:1px solid var(--rule-blue,#C8D2E3);border-radius:6px;cursor:pointer;vertical-align:middle;box-shadow:0 0 0 1px var(--rule,#E7ECF3) inset;transition:transform .1s}
.cl-colour-btn:hover{transform:scale(1.08)}
.cl-colour-btn.unset{background:transparent!important;border-style:dashed;opacity:.6;box-shadow:none}
.cl-colpop{position:absolute;z-index:1200;background:var(--card,#fff);border:1px solid var(--rule-blue,#C8D2E3);border-radius:12px;padding:10px;box-shadow:0 10px 30px rgba(21,45,73,.20)}
.cl-colpop .swatchgrid{max-width:206px;margin:0}
.cl-inline{height:30px;font-family:var(--font);font-size:12.5px;padding:0 8px;border:1px solid transparent;border-radius:6px;background:transparent;color:var(--ink);width:100%;box-sizing:border-box;transition:border-color .12s,background .12s}
.cl-inline:hover{border-color:var(--rule-blue,#C8D2E3)}
.cl-inline:focus{border-color:var(--blue);background:var(--field);outline:none}
select.cl-inline{cursor:pointer}
/* Contact cell = bold name + muted email subline, mirroring the client name/address column.
   Still inline-editable (borderless until hover/focus), just tighter + typographically matched. */
.cl-contact{display:flex;flex-direction:column;gap:0}
.cl-contact .cl-inline{height:auto;padding:2px 4px}
.cl-contact .cl-cname{font-weight:700;color:var(--navy)}
.cl-contact .cl-cemail{font-size:11px;color:var(--muted);line-height:1.3}
.cl-addr{font-size:11px;color:var(--muted);margin-top:1px;line-height:1.3}
.cl-notecell{min-width:150px}
#clientList th[data-col="contact"]{min-width:150px}   /* roomier default so the contact name doesn't truncate on first load */
.cl-note{font-style:italic}
.cl-note::placeholder{font-style:normal}
.fin-invaddr{font-size:11px;color:var(--muted);margin:1px 0 4px;padding-left:2px}
/* Contracts list — read-only client-colour swatch (first column) */
.ct-colcell{width:1%;white-space:nowrap}
.ct-colour{width:22px;height:22px;border-radius:6px;display:inline-block;vertical-align:middle;box-shadow:0 0 0 1px var(--rule,#E7ECF3) inset}
.ct-colour.unset{box-shadow:none;border:1px dashed var(--rule-blue,#C8D2E3);opacity:.55}
/* Contracts term as a progress pill — fill = elapsed portion of the term */
.ct-term{position:relative;display:inline-flex;align-items:center;min-width:158px;height:23px;padding:0 9px;border-radius:6px;border:1px solid var(--rule-blue,#C8D2E3);background:var(--field,#F6F8FC);overflow:hidden}
.ct-term-fill{position:absolute;left:0;top:0;bottom:0;z-index:0;background:color-mix(in srgb,var(--blue,#6F97D8) 26%,transparent);transition:width .3s ease}
.ct-term.warn .ct-term-fill{background:color-mix(in srgb,#E0A100 32%,transparent)}   /* nearing the end */
.ct-term.over .ct-term-fill{background:color-mix(in srgb,var(--red,#E72D3F) 24%,transparent)}   /* term fully elapsed */
.ct-term-lbl{position:relative;z-index:1;font-size:12px;font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--ink)}
/* Term, Duration and Expires were three columns describing the same two dates, and together they
   pushed the register to 1461px inside a shell that caps at 1280 — so it scrolled sideways at EVERY
   window size, not just narrow ones. The two derived columns now sit as a line under the term pill:
   same information, same row, and the table finally fits its own page. */
.ct-term-sub{display:none}
#contractList [data-col=duration],#contractList [data-col=expires]{display:none}
#contractList .ct-term-sub{display:block;margin-top:3px;font-size:11px;color:var(--muted,#5C6B80);font-variant-numeric:tabular-nums}
#contractList .ct-term{min-width:0}
.modal-card label,.appform label,.settings-page label{display:block;font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:.07em;color:var(--faint);margin:12px 0 5px}
.modal-card input,.modal-card select,.profedit-fields input,.profedit-fields select,.appform input,.appform select,.settings-page input,.settings-page select{width:100%;box-sizing:border-box;height:41px;font-family:var(--font);font-size:14px;padding:0 12px;border:1px solid var(--field-line,var(--rule-blue));border-radius:10px;color:var(--ink);background:var(--field);transition:border-color .15s,box-shadow .15s}   /* --field-line: the kit minted it (b620154) because --rule-blue is 1.52:1 on the field fill — these pre-kit rules kept the failing border on every dialog field */
.modal-card input[type=file]{height:auto}   /* hidden photo picker — never a fixed-height field */
/* A tick box is not a text field. The rule above sizes EVERY input in a dialog as one (width:100%,
   height:41px), which renders a checkbox as a ~210×41 slab and wrings its label into a column of
   single words. Checkbox rows have been re-fixing this one at a time (label.pfcheck, label.mtg-flag,
   and each one that quietly lived with it); reset it once, here, where it is caused. */
.modal-card input[type=checkbox],.modal-card input[type=radio],
.appform input[type=checkbox],.appform input[type=radio],
.settings-page input[type=checkbox],.settings-page input[type=radio]{width:16px;height:16px;padding:0}   /* 16px, not auto: auto re-shrank them to the ~13px browser default the kit's sizing rule exists to fix */
/* Prose, not code. Nearly every textarea in this app holds writing a person will read back — meeting
   narratives, policy text, what happened and why — and monospace made all of it look like terminal
   output. The kit already draws this distinction (.in is the UI font, .in.mono is opt-in); this rule
   was quietly overriding it for every dialog. Add `mono` to the few that hold pasted data or markup. */
.modal-card textarea,.appform textarea,.settings-page textarea{width:100%;font-family:var(--font);font-size:13px;line-height:1.5;padding:9px 11px;border:1px solid var(--field-line,var(--rule-blue));border-radius:9px;color:var(--ink);background:var(--field);resize:vertical;transition:border-color .15s,box-shadow .15s}
.modal-card textarea.mono,.appform textarea.mono,.settings-page textarea.mono{font-family:var(--mono);font-size:12px;line-height:1.45}
.modal-card input:focus,.modal-card select:focus,.modal-card textarea:focus,.profedit-fields input:focus,.profedit-fields select:focus,.appform input:focus,.appform select:focus,.appform textarea:focus,.settings-page input:focus,.settings-page select:focus{outline:none;border-color:var(--navy);box-shadow:0 0 0 3px color-mix(in srgb,var(--navy) 13%,transparent)}
.modal-card input[type=file]{font-size:12px;color:var(--muted)}
/* The field a validation toast is about. The toast says WHAT is wrong; this says WHERE, on the one
   screen where the reader is already looking. Mirrors the focus rule exactly, in red instead of navy,
   so a marked field reads as the same object in a different state rather than as new furniture.
   ⚠ COLOUR ONLY, NO LAYOUT — a mark that appears and clears as somebody types must not reflow the
   dialog under them. And --red, which is defined in both themes.
   The mark clears on the next keystroke in that field (see _markInvalid): a stale red border on a
   field the reader has already corrected is a lie that outlives its message. */
.is-invalid,
.modal-card input.is-invalid,.modal-card select.is-invalid,.modal-card textarea.is-invalid{
  border-color:var(--danger) !important;box-shadow:0 0 0 3px color-mix(in srgb,var(--danger) 13%,transparent)}
.row2{display:flex;gap:12px;align-items:flex-end}.row2>div{flex:1;min-width:0}
.fxrow{display:flex;align-items:center;gap:10px;margin-top:8px}
.fxrow .fxlbl{flex:0 0 84px;font-size:13px;color:var(--soft);text-align:right}
.fxrow input.fxrate{width:150px;flex:0 0 150px}
.fxrow .fxsuffix{font-size:13px;color:var(--faint)}
.impgrid .row2{align-items:center;margin-bottom:6px}
.impgrid .row2>div:first-child{flex:0 0 150px;font-size:12px;color:var(--soft)}
.modal-card .hint{margin:0 0 10px;font-style:normal;color:var(--muted)}
table.prev{font-size:11px;border-collapse:collapse;width:auto}
table.prev th,table.prev td{border:1px solid var(--rule);padding:3px 7px;text-align:left;white-space:nowrap;color:var(--soft)}
table.prev th{font-family:var(--mono);font-size:9px;color:var(--faint)}
/* weekly timesheet grid (My work) */
.ts-nav{display:flex;align-items:center;gap:8px 10px;margin:2px 0 12px;flex-wrap:wrap}
.ts-nav .btn,.ts-nav .ts-wk{white-space:nowrap}   /* a phone wrapped "‹ Prev" into two lines; wrap the row, not the words */
.ts-nav .ts-wk{font-weight:600;color:var(--navy);font-size:13px}
table.tsgrid{border-collapse:collapse;width:100%;font-size:12.5px}
table.tsgrid th,table.tsgrid td{border:1px solid var(--rule);padding:4px 6px;text-align:center}
table.tsgrid th{font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--faint);font-weight:600}
table.tsgrid th.ts-fut{color:var(--ghost)}
table.tsgrid th .ts-dnum{display:block;font-size:12px;color:var(--muted);font-weight:400}
table.tsgrid .ts-proj{text-align:left;white-space:nowrap;color:var(--navy);max-width:220px;overflow:hidden;text-overflow:ellipsis}
table.tsgrid .ts-proj .cdot{margin-right:6px}
.ts-plan{margin-left:6px;font-size:11px;color:var(--faint)}
/* the grid's planned pill sits on a line of its own under the name, so a long name's ellipsis never
   swallows it (two of three Lab rows lost theirs, and every row on a phone) */
table.tsgrid .ts-proj .ts-pname{display:block;overflow:hidden;text-overflow:ellipsis}
table.tsgrid .ts-proj .ts-plan{display:block;margin:1px 0 0 14px;font-variant-numeric:tabular-nums}
/* hours logged that day in calendar blocks or against a task: counted in the totals, edited elsewhere */
table.tsgrid .ts-other{display:block;margin-top:2px;font-size:10px;line-height:1.2;color:var(--muted);white-space:nowrap;font-variant-numeric:tabular-nums}
table.tsgrid .ts-other-pad{visibility:hidden}   /* keeps the row's inputs on one line (see cell() in app.js) */
/* two-line timesheet ENTRY label: code on top, project name beneath (opt-in via the code+name toggle) */
.tsp-n{display:block;font-weight:400;font-size:.85em;opacity:.72;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
table.tsgrid .ts-proj .tsp-n{padding-left:14px}
/* hours as the app writes them (L-30): "12h 45m" is 50px of text at this size, "12 h 45 min" 67px */
table.tsgrid .ts-cell{width:58px;text-align:center;padding:4px 2px;border:1px solid var(--rule-blue,#C8D2E3);border-radius:6px;background:var(--panel,#F6F8FC);color:var(--navy);font-size:12.5px;transition:border-color .12s,box-shadow .12s}
html[lang=sv] table.tsgrid .ts-cell{width:74px}
/* the weekly timesheet's card: seven 87px Swedish day columns + the project and total columns measured
   883px of table, so Swedish gets the width that holds them without a scrollbar */
.modal-card.ts-card{width:min(860px,94vw)}
html[lang=sv] .modal-card.ts-card{width:min(944px,94vw)}
table.tsgrid .ts-cell:hover:not(:disabled){border-color:var(--blue,#6F97D8)}
table.tsgrid .ts-cell:disabled{background:transparent;color:var(--ghost);border-color:transparent}
table.tsgrid .ts-cell:focus{outline:none;border-color:var(--blue,#6F97D8);box-shadow:0 0 0 2px var(--blue-soft,#ECF0F7)}
table.tsgrid th.ts-today{color:var(--blue,#6F97D8);background:var(--blue-soft,#ECF0F7)}
table.tsgrid td.ts-today{background:var(--blue-soft,#ECF0F7)}
table.tsgrid td.ts-today .ts-cell:not(:disabled){background:var(--field,#fff)}
table.tsgrid tfoot td,table.tsgrid .ts-rowtot{font-weight:600;color:var(--navy);background:var(--panel)}

/* ---- week-view calendar time-logger (Company · #timesheet) ---- */
.cal-top{display:flex;align-items:center;gap:12px;margin:0 0 16px;flex-wrap:wrap}
.cal-top .rng{font-weight:600;font-size:14px;min-width:132px;text-align:center;color:var(--navy)}
/* month-end close status bar (above the week calendar) */
/* reserve the bar's vertical box even while empty, so the async close-status fill (a fetch after the
   calendar paints) drops in place instead of shoving the whole calendar down — that reflow read as a
   flicker/jerk on opening the Timesheet tab. */
/* Inline page notice (org-continuity nudge on People). Amber tint, left accent, matches close-bar rounding. */
.banner{display:flex;align-items:center;gap:12px;margin:0 0 14px;padding:11px 14px;border-radius:12px;box-sizing:border-box}
.banner-amber{background:color-mix(in srgb,var(--amber) 10%,var(--panel));border:1px solid color-mix(in srgb,var(--amber) 38%,var(--rule,#E7ECF3));border-left:3px solid var(--amber)}
.banner .bn-body{flex:1;font-size:13px;line-height:1.5;color:var(--soft)}
.banner .bn-body b{color:var(--navy)}
.banner .bn-x{flex:none;white-space:nowrap}
.close-bar{min-height:50px;margin:0 0 14px;box-sizing:border-box}
.close-bar:not(:empty){display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:9px 14px;background:var(--panel);border:1px solid var(--rule,#E7ECF3);border-radius:12px}
.close-bar .cb-month{font-weight:600;font-size:13px;color:var(--navy)}
.close-bar .cb-lock{font-weight:600;font-size:13px;color:var(--muted)}
.close-bar .cb-badge{font-size:10.5px;font-weight:600;padding:2px 9px;border-radius:999px;letter-spacing:.02em}
.close-bar .cb-badge.sub{background:color-mix(in srgb,var(--amber) 16%,transparent);color:#8a5a12}
.close-bar .cb-badge.ok{background:color-mix(in srgb,var(--green) 14%,transparent);color:color-mix(in srgb,var(--green) 72%,#0a3a24)}
html[data-theme=dark] .close-bar .cb-badge.ok{color:var(--green)}
.cal-top .cal-hint{font-family:var(--mono);font-size:10.5px;color:var(--faint);margin-left:auto;letter-spacing:.02em}
.cal-top .cal-person{font:inherit;font-size:12.5px;font-weight:600;color:var(--navy);background:var(--panel);border:1px solid var(--rule);border-radius:8px;padding:5px 9px;cursor:pointer;max-width:200px}
.cal-card{background:var(--surface);border:1px solid var(--card-line);border-radius:16px;box-shadow:var(--shadow-card);overflow:hidden}
.cal-head{display:flex;padding-left:56px;border-bottom:1px solid var(--rule,#E7ECF3);background:var(--surface)}
.cal-dh{flex:1;min-width:96px;padding:9px 12px 8px;border-left:1px solid var(--grid-line,#f0f3f8)}
.cal-dh .dow{font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--faint);font-weight:600}
.cal-dh .dnum{font-size:15px;font-weight:600;color:var(--soft);line-height:1.1}
.cal-dh.today .dnum,.cal-dh.today .dow{color:var(--blue)}   /* the only "today" cue — a blue header, no column wash */
.cal-dh .cal-tot{float:right;font-family:var(--mono);font-size:11px;color:var(--faint);margin-top:2px}
.cal-dh .cal-tot b{color:var(--soft);font-weight:600}
.cal-grid{position:relative;display:flex;overflow-y:auto;overflow-x:hidden;max-height:66vh}
.cal-gutter{width:56px;flex:0 0 56px;position:relative}
.cal-gutter .cal-hr{position:absolute;right:8px;font-family:var(--mono);font-size:10px;color:var(--ghost);transform:translateY(-6px)}
.cal-cols{flex:1;position:relative;display:flex}
.cal-col{flex:1;min-width:96px;position:relative;border-left:1px solid var(--grid-line,#f0f3f8)}
/* Full-day column shading: weekends get a neutral grey wash; TODAY gets a distinct blue wash (listed
   after .weekend so today wins when today falls on a weekend). Both span the whole day (the column). */
/* weekend = a neutral slate wash (clearly an off-day); today = a cool blue wash + blue header text —
   kept distinct in hue AND weight so a Saturday never reads like "today". today wins on the overlap. */
.cal-col.weekend{background:rgba(148,163,184,.22)}
.cal-col.today{background:rgba(111,151,216,.15)}
.cal-dh.weekend{background:rgba(148,163,184,.22)}
/* time off (leave / public holiday) on the timesheet: a soft amber wash + a small label so you don't
   log against a day you're off (the plan draft suggests no work there either) */
.cal-col.off{background:rgba(245,158,11,.13)}
.cal-col.off.holiday{background:rgba(111,151,216,.14)}
.cal-col.off.pending{background:repeating-linear-gradient(135deg,rgba(245,158,11,.13),rgba(245,158,11,.13) 7px,transparent 7px,transparent 14px)}
.cal-dh.off .dnum,.cal-dh.off .dow{color:var(--amber,#B8791A)}
.cal-dh.off.holiday .dnum,.cal-dh.off.holiday .dow{color:var(--blue)}
.cal-offlabel{font-family:var(--mono);font-size:8.5px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--amber,#B8791A);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cal-dh.off.holiday .cal-offlabel{color:var(--blue)}
.cal-offband{position:absolute;top:6px;left:6px;right:6px;z-index:1;pointer-events:none;font-family:var(--mono);font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--amber,#B8791A);text-align:center;opacity:.75}
.cal-col.off.holiday .cal-offband{color:var(--blue)}
.cal-hrline{position:absolute;left:0;right:0;height:1px;background:var(--grid-line,#f0f3f8)}
.cal-lunch{position:absolute;left:2px;right:2px;z-index:1;pointer-events:none;border-radius:5px;
  background:repeating-linear-gradient(-45deg,transparent 0 5px,color-mix(in srgb,var(--navy,#152D49) 6%,transparent) 5px 10px);
  border:1px dashed var(--rule-blue,#C8D2E3);display:flex;align-items:center;justify-content:center;
  font-family:var(--mono);font-size:9px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--faint,#8595AB)}
html[data-theme=dark] .cal-lunch{background:repeating-linear-gradient(-45deg,transparent 0 5px,rgba(255,255,255,.05) 5px 10px)}
/* --- the 1:1 page: the context band that sets the screen (load, work, rhythm) --- */
.ooo-ctx{display:flex;gap:12px;align-items:stretch;flex-wrap:wrap;margin:0 0 12px}
.ooo-stat{background:var(--surface);border:1px solid var(--rule,#E7ECF3);border-radius:12px;padding:10px 16px;display:flex;flex-direction:column;justify-content:center;min-width:104px}
.ooo-stat b{font-size:21px;color:var(--navy);font-variant-numeric:tabular-nums;line-height:1.1}
.ooo-stat span{font-family:var(--mono);font-size:9.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--faint,#8595AB);margin-top:3px}
.ooo-weeks{background:var(--surface);border:1px solid var(--rule,#E7ECF3);border-radius:12px;padding:10px 14px;display:flex;gap:4px;align-items:center}
.ooo-wk{width:36px;height:34px;border-radius:6px;color:#fff;display:flex;flex-direction:column;align-items:center;justify-content:center;font-family:var(--mono)}
.ooo-wk b{font-size:11px;font-weight:700;line-height:1}
.ooo-wk small{font-size:8px;opacity:.85;margin-top:2px}
.ooo-weeks-lbl{font-family:var(--mono);font-size:9.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--faint,#8595AB);margin-left:8px;max-width:52px;line-height:1.4}
.ooo-pcs{display:flex;gap:10px;flex-wrap:wrap;margin:0 0 14px}
.ooo-pc{background:var(--surface);border:1px solid var(--rule,#E7ECF3);border-radius:10px;padding:8px 12px;font-size:12.5px;max-width:250px;transition:box-shadow .15s ease,transform .15s ease}
.ooo-pc:hover{box-shadow:0 3px 10px rgba(21,45,73,.08);transform:translateY(-1px)}
.ooo-pc>b{color:var(--navy);margin-right:6px}
.ooo-pc-upd{font-size:11px;margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:226px}
/* the roles a person holds on a project, beside its name in the 1:1 — muted and secondary to
   the title, because the title is what you scan and the role is what you check. */
.ooo-role{font-size:11.5px;color:var(--muted,#6B7A90);white-space:nowrap}
/* Projects the person is still on that the timeline does not show — deliberately quieter than the
   current ones: this is a prompt to consider, not a list of today's work. */
/* a contract reading as expired because its term ran out, not because anybody said so */
.ct-lapsed{border-style:dashed}
/* The project's Team tab — a row per person: who, what they are on it as, the booked window, flags. */
.pt-wrap{display:flex;flex-direction:column}
.pt-row{display:grid;grid-template-columns:minmax(180px,1.6fr) minmax(120px,1fr) minmax(150px,1fr) auto;
  gap:10px;align-items:center;padding:9px 0;border-bottom:1px solid var(--rule,#E7ECF3)}
.pt-row.is-gone{opacity:.62}
.pt-who{display:flex;align-items:center;gap:9px;min-width:0}
.pt-name{background:none;border:0;padding:0;font:inherit;font-weight:600;color:var(--navy);cursor:pointer;text-align:left}
.pt-name:hover{text-decoration:underline}
.pt-name.is-plain{cursor:default}
.pt-name.is-plain:hover{text-decoration:none}
.pt-title{font-size:11.5px}
.pt-roles{display:flex;flex-wrap:wrap;gap:4px}
.pt-win{font-size:12px}
.pt-flags{display:flex;flex-wrap:wrap;gap:4px;justify-content:flex-end}
.pt-wait{border-style:dashed}
.pt-sec{font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted,#6B7A90);margin:14px 0 6px}
.pt-ph{display:flex;flex-wrap:wrap;gap:5px}
.pt-acct{font-size:12.5px}
.pt-note{font-size:12.5px;margin-top:12px;padding:7px 11px;border-radius:8px;background:var(--surface);
  border:1px solid var(--rule,#E7ECF3)}
.pt-note.warn{border-color:var(--amber);color:#8a5a12;
  background:color-mix(in srgb,var(--amber) 10%,transparent)}   /* matches .hpill.h-amber */
.pt-note.ok{color:var(--muted,#6B7A90)}
/* the formatting bar inside a 1:1 row — tighter than the standalone one, and it must not
   push the note away from the row it belongs to */
.ooo-row .mdbar{margin:2px 0 2px;padding:2px}
.ooo-row .mdbar button{padding:1px 6px;font-size:11px}
/* Timeline grouped over client: the group row, its disclosure, and the union bar. The bar is
   deliberately flat and unlabelled — it says WHEN this client has work, not how much (see
   _tlClientGroups: the three booking kinds are not addable). */
.clientlane .namecell{font-weight:600}
.clientlane .namecell b{color:var(--navy)}
.tl-chev{border:0;background:none;cursor:pointer;color:var(--muted,#6B7A90);font-size:11px;padding:0 6px 0 0}
.blk.clientblk{background:color-mix(in srgb,var(--rule-blue,#C8D2E3) 55%,transparent);
  border:1px solid var(--rule-blue,#C8D2E3);border-radius:5px;height:16px;top:7px;
  /* the summed FTE-percentage rides IN the bar: padding/line-height override .blk's 5px 8px, which
     was sized for a two-line project label and would push a one-line figure out of a 16px bar */
  padding:0 5px;color:var(--navy);font-family:var(--mono);font-size:9.5px;font-weight:700;
  line-height:14px;letter-spacing:.02em;white-space:nowrap;cursor:default;box-shadow:none}
.lane.tl-child .namecell{padding-left:22px}
.ooo-dorm{display:flex;flex-wrap:wrap;gap:6px;padding:4px 0 2px}
.ooo-dormbtn{border:1px dashed var(--rule,#E7ECF3);background:transparent;border-radius:999px;
  padding:3px 10px;font-size:11.5px;color:var(--navy);cursor:pointer}
.ooo-dormbtn:hover{border-style:solid;background:var(--surface)}
.wn-dormrow{display:flex;align-items:flex-start;gap:8px;margin-top:8px;
  padding-top:8px;border-top:1px dashed var(--rule,#E7ECF3)}
.wn-dormlbl{font-size:11px;white-space:nowrap;padding-top:4px}
.wn-proj.wn-dorm{border-style:dashed;opacity:.82}

html[data-theme=dark] .ooo-stat b,html[data-theme=dark] .ooo-pc>b{color:#E8EEF7}
/* 1:1 page header + composer sections (v0.295 sleek pass) */
.ooo-head{display:flex;gap:16px;align-items:center;margin:0 0 16px}
.ooo-head .ooo-av{width:52px;height:52px;border-radius:50%;flex:none;font-size:17px}
.ooo-sec{display:flex;align-items:baseline;gap:8px;margin:18px 0 8px;padding-top:12px;border-top:1px solid var(--rule,#E7ECF3);font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--navy-soft);font-family:var(--mono)}
.ooo-sec:first-child{margin-top:0;padding-top:0;border-top:0}
.ooo-sec span{font-family:var(--font);font-weight:500;text-transform:none;letter-spacing:0;font-size:11px;color:var(--faint)}
html[data-theme=dark] .ooo-sec{color:#B9C6DA}
/* --- Finance HQ --- */
.fin-chain{display:flex;gap:5px;flex-wrap:wrap;align-items:center}
.fin-chip{font-family:var(--mono);font-size:10px;padding:2px 8px;border-radius:9px;background:var(--panel,#F2F5FA);color:var(--muted)}
.fin-chip.ok{background:rgba(30,158,120,.13);color:#0f6e56}
.fin-chip.warn{background:rgba(233,162,59,.16);color:#8A5E0F}
.fin-warn{font-size:12px;color:#8A5E0F;background:rgba(233,162,59,.1);border-radius:7px;padding:5px 10px;margin:3px 0}
.fin-ok{font-size:12px;color:#0f6e56;background:rgba(30,158,120,.1);border-radius:7px;padding:5px 10px}
.fin-client{margin:10px 0 4px}
.fin-client-hd{display:flex;align-items:center;gap:8px;padding:5px 0;border-bottom:1px solid var(--rule,#E7ECF3)}
.fin-client-hd b{color:var(--navy)}
/* sent/settled marking (P2): a per-client billing-state row under the client header */
.fin-mark{display:flex;align-items:center;gap:6px;padding:5px 0 4px 2px;flex-wrap:wrap}
.fin-state{font-size:11px;font-weight:600;padding:2px 9px;border-radius:999px;letter-spacing:.01em;white-space:nowrap}
.fin-state.sent{color:#8a5a12;background:color-mix(in srgb,var(--amber) 16%,transparent)}
.fin-state.settled{color:#0f6e56;background:color-mix(in srgb,var(--green) 15%,transparent)}
html[data-theme=dark] .fin-state.settled{color:var(--green)}
.fin-mk-x{border:none;background:none;color:var(--faint);cursor:pointer;font-size:12px;line-height:1;padding:2px 4px;border-radius:6px}
.fin-mk-x:hover{color:var(--red);background:color-mix(in srgb,var(--red) 10%,transparent)}
.fin-client.is-marked{opacity:.92}
.fin-line{display:flex;align-items:center;gap:8px;padding:3px 0 3px 12px;font-size:12.5px}
.fin-line-p{font-weight:600;color:var(--navy);max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fin-amt,.fin-amt-b{font-variant-numeric:tabular-nums;white-space:nowrap;font-size:12.5px}
.fin-amt-b{font-weight:700;color:var(--navy)}
.fin-row{display:flex;align-items:center;gap:10px;padding:7px 0;border-bottom:1px solid var(--rule,#E7ECF3)}
.fin-name{flex:0 0 118px;font-weight:600;font-size:12.5px;color:var(--navy);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fin-bars{flex:1;display:flex;flex-direction:column;gap:2px;min-width:56px}
.fin-bar{display:block;height:7px;border-radius:4px;min-width:2px}
.fin-bar.proj{background:var(--panel,#E9EEF6);border:1px solid var(--rule-blue,#C8D2E3)}
.fin-bar.real{background:var(--blue,#6F97D8)}
.fin-util{flex:0 0 54px;text-align:right;font-family:var(--mono);font-size:10.5px;color:#8A5E0F}
.fin-util.ok{color:#0f6e56}
.fin-earn-amt{flex:0 0 138px;text-align:right;font-size:11.5px}
html[data-theme=dark] .fin-name,html[data-theme=dark] .fin-client-hd b,html[data-theme=dark] .fin-line-p,html[data-theme=dark] .fin-amt-b{color:#E8EEF7}
/* Dark inks for the local pill/chip clones. The kit's 08-06 pill fix documented the failure —
   "#0f6e56 sat on a translucent green wash over a dark surface and measured 2.08:1" — and minted
   --pill-ok/--pill-warn as the measured dark replacements; these classes are the same construction
   built before the kit owned pills, so they ride the same tokens rather than re-deriving values. */
html[data-theme=dark] .fin-chip.ok,html[data-theme=dark] .fin-ok,html[data-theme=dark] .fin-util.ok,html[data-theme=dark] .fin-state.settled,html[data-theme=dark] .lvstat.approved,html[data-theme=dark] .cbt-delta.up{color:var(--pill-ok)}
html[data-theme=dark] .fin-chip.warn,html[data-theme=dark] .fin-warn,html[data-theme=dark] .fin-util,html[data-theme=dark] .dl-when.urgent,html[data-theme=dark] .dlcal-ev.urgent,html[data-theme=dark] .lvstat.requested,html[data-theme=dark] .tag.amber,html[data-theme=dark] .topend h4,html[data-theme=dark] #scenBanner .scn b{color:var(--pill-warn)}
/* Finance HQ (v0.294): topline tiles + 6-month realised spark + the month bar + deep-views grid */
.fin-today-eyebrow{font-family:var(--mono);font-size:10px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--faint);margin:0 0 7px}
.fin-tiles{display:grid;grid-template-columns:repeat(5,1fr) 1.4fr;gap:10px;margin-bottom:18px}
.fin-tile{background:var(--surface);border:1px solid var(--card-line);border-radius:12px;padding:12px 14px;display:flex;flex-direction:column;gap:3px;min-width:0}
.fin-tile .ft-l{font-size:10px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fin-tile b{font-size:21px;font-weight:750;color:var(--navy);font-variant-numeric:tabular-nums;letter-spacing:-.01em;line-height:1.15}
.fin-tile .ft-m{font-size:10.5px;color:var(--faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fin-spark{flex:1;display:flex;align-items:flex-end;gap:6px;min-height:46px;margin-top:2px}
.fs-col{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:2px;height:100%;min-width:0}
.fs-col i{display:block;width:100%;max-width:26px;background:var(--rule-blue,#C8D2E3);border-radius:3px 3px 0 0}
.fs-col i.cur{background:var(--blue,#6F97D8)}
.fs-col span{font-size:9px;color:var(--faint);letter-spacing:.02em}
.fin-monthbar{display:flex;align-items:center;flex-wrap:wrap;gap:14px;margin:0 0 12px;padding-top:16px;border-top:1px solid var(--rule,#E7ECF3)}   /* wrap: the granularity seg + hint must never clip on narrow panes */
.fin-monthbar h2{margin:0;font-size:18px;color:var(--navy);letter-spacing:-.01em;min-width:150px}
.fin-mnav{display:flex;gap:6px;align-items:center}
.fin-mnav input{font-size:12.5px}
/* Finance period granularity (Month/Quarter/Year) + the quarter/year summary card */
.fin-granseg{margin-left:2px}
.fin-summary{margin-bottom:16px}
.fin-sum-tiles{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:4px 0 12px}
.fin-bm{display:flex;align-items:flex-end;gap:8px;min-height:96px;padding:6px 2px 0}
.fin-bm-col{flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;min-width:0}
.fin-bm-stack{flex:1;display:flex;align-items:flex-end;gap:3px;width:100%;justify-content:center;height:80px}
.fin-bm-stack i{display:block;width:100%;max-width:16px;border-radius:3px 3px 0 0}
.fin-bm-stack i.proj{background:var(--rule-blue,#C8D2E3)}
.fin-bm-stack i.real{background:var(--blue,#6F97D8)}
.fin-bm-l{font-size:9.5px;color:var(--faint);letter-spacing:.02em}
.fin-deephead{display:flex;align-items:baseline;gap:12px;margin:26px 0 12px;padding-top:16px;border-top:1px solid var(--rule,#E7ECF3)}
.fin-deephead h2{margin:0;font-size:18px;color:var(--navy);letter-spacing:-.01em}
.fin-deep{display:grid;grid-template-columns:1fr 1fr;gap:16px;align-items:start}
#finance .fin-deep .card{margin:0}
html[data-theme=dark] .fin-tile b,html[data-theme=dark] .fin-monthbar h2,html[data-theme=dark] .fin-deephead h2{color:#E8EEF7}
@media (max-width:1100px){.fin-tiles{grid-template-columns:repeat(3,1fr)}.fin-tile.fin-trend{grid-column:span 3}.fin-tiles .fin-tile:nth-child(5){grid-column:span 2}.fin-deep{grid-template-columns:1fr}}   /* 5 stat tiles in a 3-col grid leave a hole — Cash on hand spans the rest of its row */
@media (max-width:640px){.fin-tiles{grid-template-columns:1fr 1fr}.fin-tile.fin-trend{grid-column:span 2}.fin-tiles .fin-tile:nth-child(5){grid-column:span 2}}
/* keep the hour grid faintly visible THROUGH the day washes — the default #f0f3f8 line vanishes on
   the leave/holiday/weekend/today tints; a translucent ink line composes over any of them */
.cal-col.off .cal-hrline,.cal-col.weekend .cal-hrline,.cal-col.today .cal-hrline{background:rgba(21,45,73,.09)}
html[data-theme=dark] .cal-col.off .cal-hrline,html[data-theme=dark] .cal-col.weekend .cal-hrline,
html[data-theme=dark] .cal-col.today .cal-hrline{background:rgba(255,255,255,.07)}
.cal-blk{position:absolute;left:5px;right:5px;border-radius:7px;padding:4px 8px;overflow:hidden;font-size:11.5px;line-height:1.22;color:#fff;box-shadow:0 1px 2px rgba(21,45,73,.18);z-index:3}
.cal-blk::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:rgba(255,255,255,.55)}
.cal-blk .bt{font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cal-blk .bm{font-family:var(--mono);font-size:9.5px;opacity:.92;margin-top:1px}
.cal-blk.nonbill{background-image:repeating-linear-gradient(135deg,rgba(255,255,255,.16) 0 6px,transparent 6px 12px)}
/* an entry that ran past midnight: the two halves meet at the day boundary, so the edges that touch it
   are square and the continuation is faded — one entry reading across two columns, not two entries */
.cal-blk.spans{border-bottom-left-radius:0;border-bottom-right-radius:0}
.cal-blk.cont{border-top-left-radius:0;border-top-right-radius:0;opacity:.9;border-top:1.5px dashed rgba(255,255,255,.75)}
.cal-ghost{position:absolute;left:5px;right:5px;border:1.5px dashed;border-radius:8px;padding:4px 8px;overflow:hidden;font-size:11.5px;line-height:1.18;z-index:2}
.cal-ghost .bt{font-weight:600;opacity:.92;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cal-ghost .bm{font-family:var(--mono);font-size:9px;opacity:.72;margin-top:1px}
.cal-now{position:absolute;left:0;right:0;height:0;border-top:2px solid var(--red);z-index:6;pointer-events:none}
.cal-now::before{content:"";position:absolute;left:-4px;top:-4px;width:8px;height:8px;border-radius:50%;background:var(--red)}
.cal-empty{padding:44px 20px;text-align:center;color:var(--faint);font-size:14px}
/* calendar interactions: drag-to-create · project picker · undo */
.cal-col{cursor:cell}
.cal-blk,.cal-ghost{cursor:pointer}
.cal-prov{position:absolute;left:5px;right:5px;border-radius:7px;background:rgba(111,151,216,.22);border:2px solid var(--blue);z-index:7;pointer-events:none}
.cal-chip{position:absolute;left:6px;z-index:9;background:var(--navy);color:#fff;font-family:var(--mono);font-size:10px;font-weight:600;padding:3px 7px;border-radius:6px;white-space:nowrap;pointer-events:none;box-shadow:0 4px 12px rgba(21,45,73,.3)}
.cal-pop{position:fixed;z-index:200;width:312px;background:var(--surface);border:1px solid var(--rule-blue,#C8D2E3);border-radius:12px;box-shadow:0 10px 26px rgba(21,45,73,.18),0 24px 60px rgba(21,45,73,.16);overflow:hidden}
.cal-pop-hd{padding:9px 13px;border-bottom:1px solid var(--rule,#E7ECF3);font-family:var(--mono);font-size:11px;color:var(--muted);font-weight:600}
.cal-pop-list{max-height:280px;overflow:auto}
.cal-pop-search{padding:8px 10px;border-bottom:1px solid var(--rule,#E7ECF3)}
.cal-pop-search input{width:100%;box-sizing:border-box;font:inherit;font-size:12.5px;padding:6px 9px;border:1px solid var(--rule-blue,#C8D2E3);border-radius:8px;background:var(--field,#fff);color:var(--ink)}
.cal-pop-search input:focus{outline:none;border-color:var(--navy);box-shadow:0 0 0 3px color-mix(in srgb,var(--navy) 12%,transparent)}
.cal-fav{flex:0 0 auto;margin-left:auto;color:var(--ghost,#C6D0DF);font-size:13px;padding:0 3px;border-radius:4px;cursor:pointer;line-height:1}
.cal-fav.on{color:#E9A23B}
.cal-fav:hover{color:#E9A23B;background:var(--panel,#F2F5FA)}
/* the entry form's searchable combobox */
.cf-combo{position:relative}
.cf-combo-list{position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:30;max-height:240px;overflow:auto;background:var(--surface);border:1px solid var(--rule-blue,#C8D2E3);border-radius:10px;box-shadow:0 10px 26px rgba(21,45,73,.18)}
.cf-copt{display:flex;align-items:center;gap:8px;width:100%;padding:8px 11px;background:none;border:none;font:inherit;font-size:13px;color:var(--ink);text-align:left;cursor:pointer;text-transform:none;letter-spacing:0}
.cf-copt:hover{background:var(--panel,#F2F5FA)}
.cf-copt .opn{flex:1;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cf-copt .odot{flex:0 0 auto;width:9px;height:9px;border-radius:50%}
.cal-opt{display:flex;align-items:center;gap:9px;width:100%;padding:8px 12px;border:none;background:none;cursor:pointer;font:inherit;font-size:13px;text-align:left;color:var(--ink)}
.cal-opt:hover{background:var(--blue-soft)}
.cal-opt .onum{width:18px;height:18px;flex:0 0 auto;border-radius:5px;background:var(--panel);border:1px solid var(--rule-blue,#C8D2E3);font-family:var(--mono);font-size:10px;font-weight:700;color:var(--muted);display:flex;align-items:center;justify-content:center}
.cal-opt .odot{width:10px;height:10px;border-radius:3px;flex:0 0 auto}
.cal-opt .opn{flex:1;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cal-opt .otag{font-family:var(--mono);font-size:8.5px;letter-spacing:.03em;padding:2px 6px;border-radius:5px;background:rgba(111,151,216,.16);color:var(--navy)}
.cal-opt .otag.nb{background:rgba(135,146,166,.18);color:var(--muted)}
.cal-pop-empty{padding:16px;text-align:center;color:var(--faint);font-size:12.5px}
/* The plan moved under you (wave 4). Same physics as .cal-snack — centre-bottom, navy, slides up —
   because it belongs to the same family of "something happened, here's what you can do about it"
   bars, and a second visual language for the same idea is how a UI starts to feel assembled rather
   than designed. Sits ABOVE the mobile bar so it never covers navigation. */
/* L-31: the form builder's working-copy bars — an offer to resume, and a save that met a newer one */
.fb-wcbar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;background:var(--panel);border:1px solid var(--rule);
  border-radius:9px;padding:8px 12px;margin:0 0 12px;font-size:13px;color:var(--ink)}
.fb-wcbar>span{flex:1;min-width:200px}
.fb-wcbar[hidden]{display:none}
.fb-wcbar.fb-stale{border-color:var(--amber,#E9A23B)}
.plan-stale{position:fixed;left:50%;bottom:calc(78px + env(safe-area-inset-bottom,0px));transform:translateX(-50%) translateY(12px);z-index:301;
  display:flex;align-items:center;gap:13px;background:var(--navy);color:#fff;border-radius:11px;
  padding:11px 16px;font-size:13px;box-shadow:0 10px 30px rgba(21,45,73,.34);opacity:0;
  pointer-events:none;transition:opacity .18s,transform .18s;max-width:calc(100vw - 32px)}
.plan-stale.show{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
.plan-stale button{background:none;border:none;border-left:1px solid rgba(255,255,255,.22);
  padding-left:13px;color:#9DBBEC;font-weight:600;cursor:pointer;font:inherit;font-size:13px}
.plan-stale button:hover{opacity:.8}
/* Above the toast's own slot (26px) rather than on top of it — they can be on screen together,
   and a confirmation hidden behind this bar is a worse bug than the staleness. */
@media (max-width:820px){ .plan-stale{bottom:calc(128px + env(safe-area-inset-bottom,0px))} }
.cal-snack{position:fixed;left:50%;bottom:26px;transform:translateX(-50%) translateY(12px);z-index:300;display:flex;align-items:center;gap:13px;background:var(--navy);color:#fff;border-radius:11px;padding:11px 16px;font-size:13px;box-shadow:0 10px 30px rgba(21,45,73,.34);opacity:0;pointer-events:none;transition:opacity .18s,transform .18s}
.cal-snack.show{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
.cal-snack .cs-chk{width:18px;height:18px;border-radius:50%;background:var(--green);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px}
.cal-snack .cs-undo{background:none;border:none;border-left:1px solid rgba(255,255,255,.22);padding-left:13px;color:#9DBBEC;font-weight:600;cursor:pointer;font:inherit;font-size:13px}
/* L-37: the undo snackbar sat at bottom:26px, ON the ≤820px bottom bar (~58px tall) — measured at
   800×600 it spanned y 541–586 over To-dos and Alerts for its five seconds. #toast and .plan-stale
   were lifted for exactly this and the snackbar was missed; it takes the toast's slot, as on desktop.
   ⚠ AFTER the base .cal-snack rule: same specificity, so the later one wins — placed above it, this
   lift was measured doing nothing. */
@media (max-width:820px){ .cal-snack{bottom:calc(70px + env(safe-area-inset-bottom,0px))} }
/* ⚠ INVERSE INK, NOT NAVY AND WHITE. --navy turns near-white in dark (#E8EAF2), so a navy bar with
   white text and a light-blue Undo read at about 1.2:1 there — after a drag on the Schedule tab this
   bar is the only confirmation and the only Undo. --ink on --surface is the pair that inverts with
   the theme (as .pjs-dtip does); in light it is the same navy and white as before. */
.cal-snack,.plan-stale{background:var(--ink);color:var(--surface)}
.cal-snack .cs-undo,.plan-stale button{color:inherit;text-decoration:underline;text-underline-offset:2px;
  border-left-color:color-mix(in srgb,currentColor 30%,transparent)}
/* live plan-vs-actual variance rail */
.cal-var{margin-top:16px;background:var(--surface);border:1px solid var(--card-line);border-radius:14px;box-shadow:var(--shadow-card);padding:15px 18px}
.cal-var-hd{font-family:var(--mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--faint);font-weight:600;margin-bottom:11px}
.cal-var-rows{display:flex;flex-direction:column;gap:9px}
.cal-var-row{display:flex;align-items:center;gap:10px;font-size:13px}
.cal-var-row .vdot{width:10px;height:10px;border-radius:3px;flex:0 0 auto}
.cal-var-row .vname{flex:0 0 190px;font-weight:600;color:var(--soft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cal-var-row .vbar{flex:1;height:6px;border-radius:3px;background:var(--rule,#E7ECF3);overflow:hidden}
.cal-var-row .vfill{display:block;height:100%;border-radius:3px;background:var(--blue)}
.cal-var-row .vfill.ok{background:var(--green)}.cal-var-row .vfill.under{background:var(--amber)}.cal-var-row .vfill.over{background:var(--red)}
.cal-var-row .vnum{flex:0 0 auto;font-family:var(--mono);font-size:11.5px;font-weight:600;color:var(--muted);min-width:74px;text-align:right;white-space:nowrap}
.cal-var-row .vnum.over{color:var(--red)}.cal-var-row .vnum.under{color:var(--amber)}.cal-var-row .vnum.ok{color:var(--green)}
/* the rail's heading carries the week's total on its right */
.cal-var-hd{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.cal-var-tot{margin-left:auto;letter-spacing:.04em;text-transform:none;font-size:11px;color:var(--muted)}
.cal-var-tot b{color:var(--navy);font-weight:700}
/* THE WEEK'S TOTAL (calendar + the weekly grid): "Week 39 · 32h 30m logged · of 40h planned", a bar, a %.
   Bands follow the rail's: within 85–110% of plan is on track. Wraps to two lines on a phone. */
.cal-week{display:flex;align-items:center;gap:6px 14px;flex-wrap:wrap;margin:0 0 14px;padding:11px 16px;background:var(--surface);border:1px solid var(--card-line);border-radius:14px;box-shadow:var(--shadow-card)}
.cal-week .cw-wk{font-family:var(--mono);font-size:10.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--faint)}
.cal-week .cw-num{font-size:13.5px;color:var(--soft)}
.cal-week .cw-num b{font-size:21px;font-weight:700;color:var(--navy);font-variant-numeric:tabular-nums;margin-right:2px}
.cal-week .cw-of{font-size:13.5px;color:var(--muted)}
.cal-week .cw-bar{flex:1 1 140px;min-width:90px;height:8px;border-radius:4px;background:var(--rule,#E7ECF3);overflow:hidden}
.cal-week .cw-fill{display:block;height:100%;border-radius:4px;background:var(--blue)}
.cal-week .cw-fill.ok{background:var(--green)}.cal-week .cw-fill.under{background:var(--amber)}.cal-week .cw-fill.over{background:var(--red)}
.cal-week .cw-pct{font-family:var(--mono);font-size:12px;font-weight:700;color:var(--muted);min-width:38px;text-align:right}
.cal-week .cw-pct.ok{color:var(--green)}.cal-week .cw-pct.under{color:var(--amber)}.cal-week .cw-pct.over{color:var(--red)}
/* in the weekly-grid dialog it sits flat, between the week navigation and the table */
.modal-card .cal-week.ts-week{box-shadow:none;background:var(--panel);margin:0 0 12px;padding:9px 14px}
/* HOURS LOGGED WITHOUT CLOCK TIMES (the weekly grid), in a row of their own under each day's heading —
   they add up with the blocks to that heading's total. Tiles the heading's columns exactly. */
.cal-daylogs{display:flex;position:relative;padding-left:56px;border-bottom:1px solid var(--rule,#E7ECF3);background:var(--surface)}
.cal-daylogs .cdl-lbl{position:absolute;left:0;top:0;bottom:0;width:56px;display:flex;align-items:center;justify-content:flex-end;padding:0 7px 0 4px;box-sizing:border-box;text-align:right;line-height:1.3;font-family:var(--mono);font-size:8.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--muted)}
.cal-daylogs .cdl-col{flex:1;min-width:96px;padding:5px 6px;border-left:1px solid var(--grid-line,#f0f3f8);display:flex;flex-direction:column;gap:4px;min-height:14px;box-sizing:border-box}
.cal-daylogs .cdl-col.weekend{background:rgba(148,163,184,.22)}
.cal-daylogs .cdl-col.today{background:rgba(111,151,216,.15)}
.cdl-chip{display:flex;align-items:center;gap:6px;width:100%;box-sizing:border-box;font:inherit;font-size:11px;line-height:1.25;text-align:left;padding:3px 7px;border-radius:6px;border:1px solid color-mix(in srgb,var(--cdl,#6F97D8) 55%,transparent);border-left:3px solid var(--cdl,#6F97D8);background:color-mix(in srgb,var(--cdl,#6F97D8) 12%,var(--surface));color:var(--soft)}
.cdl-chip .cdl-p{flex:1;min-width:0;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cdl-chip b{flex:0 0 auto;font-family:var(--mono);font-size:10.5px;font-weight:700;color:var(--navy)}
/* dark: a navy project colour vanishes into the ground, so the chip's edge is lifted toward white */
html[data-theme=dark] .cdl-chip{border-color:color-mix(in srgb,color-mix(in srgb,var(--cdl,#6F97D8) 60%,#fff) 45%,transparent);border-left-color:color-mix(in srgb,var(--cdl,#6F97D8) 60%,#fff);background:color-mix(in srgb,var(--cdl,#6F97D8) 22%,var(--surface))}
button.cdl-chip{cursor:pointer}
/* booked, not drafted (L-19): planned, not logged — the ghosts' dashed edge, not a logged chip's fill */
.cdl-chip.cdl-undrafted,html[data-theme=dark] .cdl-chip.cdl-undrafted{border-style:dashed;background:transparent}
.cdl-chip .cdl-t{font-weight:400;opacity:.8}
button.cdl-chip:hover{background:color-mix(in srgb,var(--cdl,#6F97D8) 20%,var(--surface))}
button.cdl-chip:focus-visible{outline:2px solid var(--blue);outline-offset:1px}
/* the grid's totals are durations now ("19h 45m"): one line each, never broken after the hours */
table.tsgrid .ts-rowtot,table.tsgrid .ts-daytot,table.tsgrid .ts-grand{white-space:nowrap}
@media (max-width:640px){
  .cal-week{padding:10px 14px}
  .cal-week .cw-bar{flex:1 1 calc(100% - 64px);order:5}   /* a row of its own, with the % beside it */
  .cal-week .cw-pct{order:6}
  /* the rail's bar on a line of its own under the name and figures: beside "7 h 30 min / 7 h 16 min"
     it shrank to a stub, and the name to "Biostatistics …" */
  .cal-var-row{flex-wrap:wrap;row-gap:5px}
  .cal-var-row .vname{flex:1 1 0}
  .cal-var-row .vbar{order:5;flex:1 1 calc(100% - 20px);margin-left:20px}
  table.tsgrid .ts-proj{max-width:118px}   /* the grid scrolls sideways on a phone: give the days the room */
  /* an Untimed chip's name above its duration: side by side, a Lab project name (no code) read "Tu…".
     The whole name, wrapped at spaces and hyphenated inside a long word at the soft hyphens app.js
     _softHyphens puts there: hyphens stays MANUAL because a project name is in no known language
     (auto broke English names by Swedish rules, "cour-se", and skipped capitalised English words).
     It was clamped at two lines, and a phone has no hover to read the rest in the title. break-word
     stays only as the last resort for a token with no syllable to break at. */
  .cdl-chip{flex-wrap:wrap;gap:1px 6px}
  .cdl-chip .cdl-p{flex-basis:100%;white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:break-word;-webkit-hyphens:manual;hyphens:manual}
}
/* keyboard / ARIA: screen-reader live region, focus rings, accessible entry form */
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.cal-blk:focus-visible,.cal-ghost:focus-visible{outline:2px solid var(--navy);outline-offset:2px;z-index:8}
.cal-form-back{position:fixed;inset:0;z-index:400;background:var(--modal-veil,rgba(21,45,73,.42));display:flex;align-items:center;justify-content:center;padding:20px}
.cal-form{width:440px;max-width:100%;background:var(--surface);border-radius:16px;box-shadow:0 20px 60px rgba(21,45,73,.32);padding:20px 22px;display:flex;flex-direction:column;gap:12px}
.cal-form .cf-hd{font-weight:700;font-size:17px;color:var(--navy)}
.cal-form .cf-l{display:flex;flex-direction:column;gap:5px;font-size:11px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;color:var(--faint);font-family:var(--mono)}
.cal-form .cf-l select,.cal-form .cf-l input,.cal-form .cf-l textarea{font:inherit;font-size:14px;text-transform:none;letter-spacing:0;color:var(--ink);padding:9px 11px;border:1px solid var(--rule-blue,#C8D2E3);border-radius:9px;background:var(--field,#fff);width:100%;box-sizing:border-box}
.cal-form .cf-l textarea{resize:vertical;min-height:38px;font-family:var(--font)}
.cal-form .cf-l select:focus,.cal-form .cf-l input:focus,.cal-form .cf-l textarea:focus{outline:none;border-color:var(--navy);box-shadow:0 0 0 3px color-mix(in srgb,var(--navy) 13%,transparent)}
.cal-form .cf-row{display:flex;gap:12px}.cal-form .cf-row .cf-l{flex:1}
.cal-form .cf-act{display:flex;align-items:center;justify-content:space-between;margin-top:4px}
.cal-form .cf-over{font-size:12px;color:var(--blue,#6F97D8);font-weight:600;margin:-2px 0 2px}
.cal-form .cf-bill-row{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--soft);margin:2px 0 8px;cursor:pointer}
.cal-form .cf-bill-row input{width:15px;height:15px;accent-color:var(--blue,#6F97D8);cursor:pointer}
.cal-form .cf-r{display:flex;gap:8px}
/* Clockify timesheet import — dry-run summary + options */
.imp-summary{margin:12px 0 0;background:var(--panel);border:1px solid var(--rule,#E7ECF3);border-radius:10px;padding:12px 14px;font-size:13.5px;color:var(--soft);line-height:1.5}
.imp-summary b{color:var(--navy)}
.imp-note{margin-top:6px;font-size:12.5px;color:var(--blue)}
.imp-warn{margin-top:6px;font-size:12.5px;color:#9a6a10;background:rgba(233,162,59,.12);border-radius:7px;padding:6px 9px}
.ts-hint{font-size:11.5px}
/* a popup subsection = a boxed card (subtle panel over the modal surface) with a tinted header bar,
   so sections read as distinct blocks rather than run-together text. Applies everywhere .psec is used. */
.psec{margin-top:14px;background:var(--panel);border:1px solid var(--rule,#E7ECF3);border-radius:12px;padding:14px;overflow:hidden}
.psec h4,.seclabel{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
/* the header bleeds to the box edges with a subtle EDITION-brand tint (navy · plum in Lab) */
.psec>h4{margin:-14px -14px 14px;padding:10px 14px;background:color-mix(in srgb,var(--brand) 9%,var(--surface));
  border-bottom:1px solid color-mix(in srgb,var(--brand) 14%,var(--rule,#E7ECF3));border-radius:12px 12px 0 0;color:var(--soft);letter-spacing:.07em}
/* dark: chrome goes neutral (a brand-tinted bar fights the dark canvas) — a plain lifted header */
html[data-theme=dark] .psec>h4{background:rgba(255,255,255,.05);border-bottom-color:var(--rule,#2A2E3B)}
/* tame native date inputs so the "fill in the date" fields sit with the sleek text fields */
.modal-card input[type=date]{min-height:38px}
.modal-card input[type=date]::-webkit-calendar-picker-indicator{opacity:.45;cursor:pointer;transition:opacity .15s}
.modal-card input[type=date]:hover::-webkit-calendar-picker-indicator,
.modal-card input[type=date]:focus::-webkit-calendar-picker-indicator{opacity:.85}
.lrow{display:flex;justify-content:space-between;align-items:center;font-size:12.5px;color:var(--soft);padding:5px 2px;border-bottom:1px solid var(--rule);border-radius:6px;transition:background .12s}
.lrow:hover{background:rgba(23,20,40,.03)}
.lrow .del{cursor:pointer;color:var(--faint);font-size:13px;padding:0 4px}
.lrow.msedit{cursor:pointer}
.lrow .del:hover{color:var(--red)}
.lmuted{font-size:12px;color:var(--faint);font-style:italic;padding:4px 0}
/* Deadlines — list view urgency grading: coloured section headers + row dots + tinted when-chips
   (over=red · next-7-days=amber · next-4-weeks=blue · later/no-date=neutral). */
.dl-sect{display:flex;align-items:center;gap:8px;font-family:var(--mono);font-size:10px;font-weight:600;
  text-transform:uppercase;letter-spacing:.1em;color:var(--muted);padding:14px 2px 6px}
.dl-sect:first-child{padding-top:2px}
.dl-sect .dl-count{font-weight:600;color:var(--faint);letter-spacing:0}
.dl-sect.over{color:var(--red)}
.dl-main{display:inline-flex;align-items:center;gap:8px;min-width:0}
.dl-dot{width:7px;height:7px;border-radius:50%;flex:0 0 auto}
.dl-dot.over{background:var(--red)} .dl-dot.urgent{background:var(--amber)}
.dl-dot.soon{background:var(--blue)} .dl-dot.later,.dl-dot.nodate{background:var(--ghost)}
.dl-dot.done{background:var(--green)}
.dl-when{font-family:var(--mono);font-size:11px;font-variant-numeric:tabular-nums;white-space:nowrap;
  padding:3px 9px;border-radius:8px;color:var(--muted);background:var(--panel)}
.dl-when.over{color:var(--red);background:rgba(231,45,63,.1)}
.dl-when.urgent{color:#8A5E0F;background:rgba(233,162,59,.16)}
.dl-when.soon{color:var(--navy-soft);background:var(--blue-soft)}
.dl-when.done{color:var(--green);background:rgba(30,158,120,.12)}
html[data-theme=dark] .dl-when.urgent{color:#E2B564}
html[data-theme=dark] .dl-when.soon{color:var(--blue)}
/* Deadlines — month calendar view (List ↔ Calendar toggle). Monday-start; chips coloured by urgency. */
.dlcal{margin-top:14px}
.dlcal-head{display:flex;align-items:center;gap:8px;margin-bottom:10px}
.dlcal-title{flex:1;font-weight:700;color:var(--navy);font-size:15px;display:flex;align-items:baseline;gap:10px}
.dlcal-count{font-weight:500;font-size:12px;color:var(--muted)}
.dlcal-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:1px;background:var(--rule,#E7ECF3);border:1px solid var(--rule,#E7ECF3);border-radius:12px;overflow:hidden}
.dlcal-dow{background:var(--panel);color:var(--faint);font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;text-align:center;padding:7px 0}
.dlcal-cell{background:var(--surface);min-height:96px;min-width:0;overflow:hidden;padding:5px 5px 6px;display:flex;flex-direction:column;gap:3px}
.dlcal-cell.other{background:var(--panel)}
.dlcal-cell.other .dlcal-day{color:var(--ghost)}
.dlcal-cell.addable{cursor:pointer}
.dlcal-cell.addable:hover{background:rgba(111,151,216,.07)}
.dlcal-day{font-size:11.5px;font-weight:600;color:var(--muted);align-self:flex-end;line-height:1.4;min-width:18px;text-align:center}
.dlcal-cell.today{box-shadow:inset 0 0 0 2px var(--blue)}
.dlcal-cell.today .dlcal-day{background:var(--blue);color:#fff;border-radius:999px}
/* chip urgency — the SAME graded palette as the list view (.dl-when): over=red · urgent ≤7d=amber ·
   soon ≤28d=blue · later=neutral. Default (no class) = later. */
.dlcal-ev{font-size:11px;line-height:1.35;padding:2px 6px;border-radius:5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;background:var(--panel);color:var(--muted)}
.dlcal-ev[data-edit]{cursor:pointer}
.dlcal-ev[data-edit]:hover{filter:brightness(.97)}
.dlcal-ev.soon{background:var(--blue-soft);color:var(--navy-soft)}
.dlcal-ev.urgent{background:rgba(233,162,59,.16);color:#8A5E0F}
.dlcal-ev.over{background:rgba(231,45,63,.12);color:var(--red)}
.dlcal-ev.done{background:rgba(30,158,120,.12);color:var(--green)}
/* supervision loop: the agenda block in the supervision log + the "raise at next meeting" flag */
.supAgenda{margin-top:10px;padding:10px 12px;background:var(--panel);border:1px solid var(--rule,#E7ECF3);border-radius:10px}
.supAgRow{font-size:12.5px;color:var(--soft);padding:2px 0}
/* The supervision record: one meeting per card, its items listed underneath. What was agreed and
   whether it happened is the whole value of the record, so an action's state is on the row itself. */
.sup-open{margin-top:10px;padding:10px 12px;background:var(--panel);border:1px solid var(--rule,#E7ECF3);border-radius:10px}
.sup-eyebrow{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);margin-bottom:5px}
.sup-row{padding:11px 12px;border:1px solid var(--rule,#E7ECF3);border-radius:10px;margin-bottom:8px;background:var(--card,#fff)}
.sup-row-h{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--navy)}
.sup-row-h b{flex:none}
.sup-sum{font-size:12.5px;color:var(--soft);margin-top:5px;line-height:1.45}
.sup-items{margin-top:7px;display:flex;flex-direction:column;gap:4px}
.sup-item{display:flex;align-items:center;gap:7px;flex-wrap:wrap;font-size:12px}
.sup-item-t{color:var(--navy)}
.sup-item-t.is-done{text-decoration:line-through;color:var(--faint)}
.sup-state{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:1px 6px;border-radius:999px;
  background:color-mix(in srgb,var(--brass,#A9772A) 16%,transparent);color:var(--brass,#A9772A)}
.sup-state.is-done{background:color-mix(in srgb,var(--green,#1E9E78) 16%,transparent);color:var(--green,#1E9E78)}
/* The 1:1 composer is a page, not a dialog, so it never matched .modal-card textarea — and with
   nothing else styling them its boxes fell through to the browser's own default, which is monospace.
   Same "minutes look like terminal output" problem as the dialogs had, arrived at from the other side. */
#oooSched,#oooAob,.oooNote,.oooTNote,.oooDNote{font-family:var(--font);font-size:12.5px;line-height:1.5;
  color:var(--ink);background:var(--field);border:1px solid var(--rule-blue);border-radius:8px;
  padding:7px 9px;box-sizing:border-box;resize:vertical;transition:border-color .15s,box-shadow .15s}
#oooSched:focus,#oooAob:focus,.oooNote:focus,.oooTNote:focus,.oooDNote:focus{outline:none;
  border-color:var(--navy);box-shadow:0 0 0 3px color-mix(in srgb,var(--navy) 13%,transparent)}

/* pull a colleague into the attendees field without retyping their name */
.mtg-att-add{display:flex;gap:8px;align-items:center;margin-top:6px}
.mtg-att-add input{flex:1;min-width:0}
.mtg-att-add .btn{flex:none}
/* "still open from last time" — the panel a recurring meeting opens on, in the project-meeting editor */
.mtg-carry{margin-top:12px;padding:10px 12px;border:1px solid var(--rule,#E7ECF3);border-radius:10px;background:var(--panel)}
.mtg-carry-h{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);margin-bottom:5px}
label.mtg-carry-r{font-size:12px;padding:2px 0}
/* the item-kind chip, shared by every minutes read view */
.mtg-kchip{flex:none;font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:2px 6px;border-radius:4px;
  background:color-mix(in srgb,var(--faint) 18%,transparent);color:var(--soft)}
.mtg-kchip.k-decision{background:color-mix(in srgb,var(--rda-blue) 15%,transparent);color:var(--rda-blue)}
.mtg-kchip.k-action{background:color-mix(in srgb,var(--brass,#A9772A) 18%,transparent);color:var(--brass,#A9772A)}
.tflag{color:var(--brass,#A9772A);font-size:12px}
.dlcal-more{font-size:10.5px;color:var(--faint);padding:0 4px}
html[data-theme=dark] .dlcal-ev.urgent{color:#E2B564}
html[data-theme=dark] .dlcal-ev.soon{color:var(--blue)}
.namecell.clickable{cursor:pointer}.namecell.clickable:hover{background:var(--panel)}
tr.clickrow{cursor:pointer}
#scenBanner{display:flex;align-items:center;gap:14px;background:#fff7ec;border:1px solid #f0d8a8;border-left:3px solid var(--amber);border-radius:8px;padding:10px 16px;margin-bottom:14px}
#scenBanner .scn{font-size:13.5px;color:var(--soft)}#scenBanner .scn b{color:#8A5E0F}
#scenBanner .sp{margin-left:auto;display:flex;gap:8px;align-items:center}
.btn.tiny{padding:6px 11px;font-size:11px}
footer{background:var(--nav-ink);color:rgba(255,255,255,.52);font-size:12px;padding:16px 30px;margin-top:48px;display:flex;align-items:center;justify-content:space-between;flex-shrink:0}   /* .52, the kit's measured footer alpha (.4 was 3.3:1 on the bar) — Lemma's footer predates .appfoot, so the kit's contrast fix never reached these rules */
#encState{display:none!important}
/* -3.6px sits the wordmark's glyph baseline (167.9 of the 225.5 viewBox) on the footer text
   baseline, so "Lemma · by Red Door Analytics" reads as one line (was -5px → 1.4px too low) */
.rda-wm{height:14px;width:auto;color:#fff;display:inline-block;vertical-align:-3.6px;margin:0 2px}
.rda-link{display:inline;cursor:pointer;text-decoration:none;transition:opacity .15s}
.rda-link:hover .rda-wm{opacity:.7}
.footbrand{color:#fff;font-weight:700}
.footright{display:inline-flex;gap:16px;align-items:center}
.footver{background:none;border:none;font:inherit;font-size:11px;color:rgba(255,255,255,.52);cursor:pointer;padding:0;letter-spacing:.02em}
.footver:hover{color:rgba(255,255,255,.75)}
/* SC 2.5.8 hit areas, the kit's .appfoot technique verbatim: enlarge the TARGET, not the box —
   an absolutely-positioned ::after grows what responds to a pointer without moving the footer's
   baseline. The version button rendered 14×13; the links ~40×15. */
.footver,.footlink{position:relative}
.footver::after,.footlink::after{content:"";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);min-width:24px;width:100%;height:24px}
.clh{font-weight:700;color:var(--navy);font-size:14px;margin:16px 0 6px}.clh:first-child{margin-top:0}
.clsub{font-weight:600;color:var(--red);font-size:11px;text-transform:uppercase;letter-spacing:.08em;margin:12px 0 4px}
.clp{font-size:12.5px;color:var(--soft);margin:6px 0}
.cllist{margin:4px 0 4px;padding-left:18px}.cllist li{font-size:12.5px;color:var(--soft);margin:3px 0}
.clmore{margin:14px 0 2px;padding-top:12px;border-top:1px solid var(--rule,#E7ECF3);text-align:center}
/* The release's user-facing summary — one file, two audiences. Directly under the heading,
   it carries the whole story for someone who does not build Lemma; the bullets below it are
   free to be as specific as they like. A callout on purpose: a release MISSING one should
   look wrong at a glance in the popover, not just in the file. */
.clsum{margin:6px 0 8px;padding:8px 12px;border-left:3px solid var(--red);
  background:var(--panel,rgba(0,0,0,.03));border-radius:0 8px 8px 0;
  font-size:13px;line-height:1.5;color:var(--navy)}
.clsum b{font-weight:600}
.lrow.avno{opacity:.5}   /* availability finder: below the requested hours threshold */
/* grant command center: funded-vs-committed per person */
.grant-tot{font-size:13px;color:var(--soft);background:var(--blue-soft);border-radius:8px;padding:8px 12px}
.grow{display:grid;grid-template-columns:1fr 64px 78px 116px 22px;align-items:center;gap:8px;font-size:12.5px;color:var(--soft);padding:6px 2px;border-bottom:1px solid var(--rule)}
.grow.ghead{color:var(--faint);font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:.06em;border-bottom:1px solid var(--rule-blue)}
.grow .gname{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--navy)}
.grow .gnum{text-align:right;font-family:var(--mono);font-variant-numeric:tabular-nums}
.grow .gdel{text-align:right}
.grow .del{cursor:pointer;color:var(--faint);font-size:13px;padding:0 4px}
.grow .del:hover{color:var(--red)}
.gchip{font-family:var(--mono);font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.02em;border-radius:8px;padding:2px 7px;white-space:nowrap}
.gchip.ok{color:var(--green);background:rgba(30,158,120,.12)}
.gchip.over{color:var(--red);background:rgba(231,45,63,.1)}
.gchip.under{color:#9a6a00;background:rgba(233,162,59,.16)}
.gchip.muted{color:var(--faint);background:var(--panel)}
/* Grants command center (lab) — landing tab */
.gsections{display:grid;grid-template-columns:1.15fr 1fr;gap:22px;margin-top:22px;align-items:start}
.gleft{display:flex;flex-direction:column;gap:22px;min-width:0}
.gcol-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin-bottom:10px}
section.gcol + section.gcol .gcol-head{margin-top:28px}   /* breathing room between stacked sections (In flight → Decided) */
.gcol-head h2{font-size:15px;margin:0;color:var(--navy)}
/* supervision-load balancing (lab): a load pill + attention signals per supervisor */
.gch-right{display:flex;align-items:baseline;gap:8px;flex-shrink:0}
.sup-load{font-size:11px;font-weight:700;color:var(--soft);background:var(--panel);border:1px solid var(--rule,#E7ECF3);border-radius:999px;padding:2px 9px;white-space:nowrap}
.sup-load.over{background:color-mix(in srgb,var(--amber) 18%,var(--surface));border-color:color-mix(in srgb,var(--amber) 32%,var(--rule,#E7ECF3))}
.sup-signals{font-size:11px;color:var(--muted);margin:-6px 0 9px}
.sup-signals .warn{color:var(--red);font-weight:600}
.gcard{background:var(--surface);border:1px solid var(--card-line);border-radius:16px;padding:14px 16px;box-shadow:var(--shadow-card)}
/* salary split / kontering table */
.k-controls{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.k-range{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);font-weight:600;display:flex;align-items:center;gap:6px}
.k-range input{font-family:var(--font);font-size:13px;padding:5px 8px;border:1px solid var(--rule-blue);border-radius:8px;color:var(--ink);background:var(--field);text-transform:none;letter-spacing:0}
.k-scroll{overflow-x:auto;padding:6px 10px}
.ktable{width:100%;border-collapse:collapse;font-size:13px;font-variant-numeric:tabular-nums}
.ktable th{text-align:right;font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--faint);font-weight:600;padding:6px 10px;border-bottom:1.5px solid var(--rule-blue);white-space:nowrap}
.ktable th:first-child{text-align:left}
.ktable td{padding:6px 10px;text-align:right;border-bottom:1px solid var(--card-line);white-space:nowrap}
.ktable td.k-mon{text-align:left;color:var(--muted);font-variant-numeric:tabular-nums}
.ktable tr.k-band td{text-align:left;font-weight:600;color:var(--navy);background:var(--blue-soft);border-bottom:none;padding-top:9px;padding-bottom:7px}
.k-cell{font-weight:600;color:var(--ink)}
.k-empty{color:var(--faint)}
.k-base{color:var(--muted)}
.k-cost{color:var(--navy);font-weight:600}
.ktable td.k-over{color:var(--red)}
.ktable td.k-under,.ktable td.k-unb{color:var(--amber)}
.ktable td.k-tos{color:var(--muted)}
.repdf{margin-left:8px;font-size:11px;color:var(--navy);text-decoration:none;white-space:nowrap;border-bottom:1px dotted var(--rule-blue)}
.repdf:hover{color:var(--red);border-bottom-color:var(--red)}
/* People page: email + inline role select */
td.pemail{color:var(--soft);font-size:12.5px;max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.prole .rolesel{font-family:var(--font);font-size:12px;padding:3px 7px;border:1px solid var(--rule-blue);border-radius:7px;background:var(--field);color:var(--ink);text-transform:capitalize;cursor:pointer}
.prole .rolesel:hover{border-color:var(--navy)}
/* People -> Account. A person WITH an account now carries the control that moves it onto a new
   sign-in, so this cell can hold a pill and a button together; before, the button appeared only
   for a person with none. Keep the label whole: the column is user-resizable, and "Move account"
   broken across two lines reads as two controls. Same treatment as .drift-acts .btn-sm. */
.pacct .btn-sm{white-space:nowrap;vertical-align:middle}
.pacct .pill{vertical-align:middle}
/* quick-budget personnel row */
.qbp-row{display:flex;gap:6px;align-items:center;margin-top:6px}
.qbp-row input{margin:0}
.qbp-row .qbp-role,.qbp-row .qbp-sal{flex:1.3;min-width:0}
.qbp-row .qbp-fte{flex:0 0 56px}
.qbp-row .qbp-mo{flex:0 0 74px}
.qbp-del{flex:0 0 auto;border:none;background:none;color:var(--red);cursor:pointer;font-size:14px;padding:2px 5px}
.gclick{cursor:pointer;border-radius:8px;margin-left:-8px;margin-right:-8px;padding-left:8px;padding-right:8px}
.gclick:hover{background:var(--blue-soft)}
.gclick:focus-visible{outline:2px solid var(--blue);outline-offset:1px}
.gbadge{font-family:var(--mono);font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;border-radius:8px;padding:3px 8px;white-space:nowrap}
.gbadge.over{color:var(--red);background:rgba(231,45,63,.1)}
.gbadge.ok{color:var(--green);background:rgba(30,158,120,.12)}
.ocrow{padding:9px 0;border-bottom:1px solid var(--rule)}
.ocrow:last-child{border-bottom:none}
.ocrow.over{border-left:3px solid var(--red);background:rgba(231,45,63,.04);margin:0 -16px;padding:9px 16px 9px 13px}
.oc-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.oc-name{font-size:13px;color:var(--navy);font-weight:600}
.oc-fte{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:12px;color:var(--soft);white-space:nowrap}
.oc-fte.over{color:var(--red);font-weight:700}
.oc-fte.tight{color:#9a6a00}
.oc-grants{display:flex;flex-wrap:wrap;gap:5px;margin-top:6px}
.gpill{font-size:10.5px;color:var(--soft);background:var(--panel);border-left:3px solid var(--gc,var(--blue));border-radius:4px;padding:2px 7px;white-space:nowrap}
.gpill b{font-family:var(--mono);color:var(--navy)}
/* a single funding-runway chip (grant · FTE · end date) can be wider than a phone; let it wrap
   its text on small screens so the grants page doesn't scroll sideways. */
@media(max-width:600px){.gpill{white-space:normal}}
.ghint{font-size:10.5px;margin:8px 2px 0;line-height:1.45}
.gtotal{font-size:20px;font-weight:700;color:var(--navy);margin-bottom:10px}
.gtotal .lmuted{font-size:12px;font-weight:400}
.bidrow{padding:8px 0;border-bottom:1px solid var(--rule)}
.bidrow:last-child{border-bottom:none}
.bid-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.bid-sen{font-size:12.5px;color:var(--navy);text-transform:capitalize}
.bid-fte{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:13px;font-weight:700;color:var(--green)}
.bid-who{font-size:11px;margin-top:3px}
.bid-who b{font-family:var(--mono);color:var(--soft)}
.ginput{font:inherit;font-size:12px;border:1px solid var(--rule);border-radius:8px;padding:4px 8px;background:var(--field);color:var(--navy)}
.gscenbar{display:flex;align-items:center;gap:10px;margin-top:18px;flex-wrap:wrap}
.gscenbar label{font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--faint)}
.gscentag{font-family:var(--mono);font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;color:#9a6a00;background:rgba(233,162,59,.16);border-radius:8px;padding:3px 8px}
h3 .gscentag{margin-left:6px;vertical-align:middle}
.gverdict{display:flex;align-items:flex-start;gap:10px;margin-top:12px;padding:11px 14px;border-radius:12px;font-size:13px;line-height:1.45;border:1px solid var(--rule)}
.gverdict.ok{background:rgba(30,158,120,.09);border-color:rgba(30,158,120,.35);color:var(--navy)}
.gverdict.tight{background:rgba(231,45,63,.06);border-color:rgba(231,45,63,.35);color:var(--navy)}
.gv-icon{flex:none;width:20px;height:20px;border-radius:50%;display:grid;place-items:center;font-size:12px;font-weight:700;color:#fff}
.gverdict.ok .gv-icon{background:var(--green)}
.gverdict.tight .gv-icon{background:var(--red)}
.gv-text b{color:var(--navy)}
.gv-free{font-family:var(--mono);font-size:11px;color:var(--soft);white-space:nowrap;margin-left:4px}
@media(max-width:860px){.gsections{grid-template-columns:1fr}.gsections .gcol:first-child{grid-row:auto}}
/* PhD / researcher progression card (lab person panel) */
.progsec .pstages{display:flex;align-items:center;flex-wrap:wrap;gap:4px;margin:2px 0 10px}
.pstage{font-size:11px;color:var(--faint);background:var(--panel);border:1px solid var(--rule);border-radius:20px;padding:3px 11px;white-space:nowrap}
.pstage.hit{color:#fff;background:var(--rda-navy,var(--blue));border-color:var(--rda-navy,var(--blue));font-weight:600}
.parrow{color:var(--ghost);font-size:13px}
.pstage.overdue{color:var(--red);background:rgba(231,45,63,.08);border-color:rgba(231,45,63,.45);font-weight:600}
.progmeta{font-size:11.5px;margin:0 0 8px}
.progmeta .povr{color:var(--red);font-weight:600}
.pdone{color:var(--green);font-weight:700}
/* Doctoral development plan (ISP/TSP/IDP/TNA) — credit-ledger progress bar + activity status pills */
.docbar{position:relative;height:8px;border-radius:20px;background:var(--panel);border:1px solid var(--rule);overflow:hidden;margin:2px 0 6px}
.docbar.big{height:10px;margin:2px 0 8px}
.docbar-fill{position:absolute;left:0;top:0;height:100%;background:var(--rda-navy,var(--blue));border-radius:20px;transition:width .3s ease;z-index:1}
.docbar-plan{position:absolute;left:0;top:0;height:100%;border-radius:20px;background:#dbe4f0;background:color-mix(in srgb,var(--rda-navy,var(--blue)) 20%,#fff)}
.docbar-legend{font-size:11.5px;color:var(--soft);margin:0 0 4px}
.docbar-legend b{color:var(--navy)}
.docstat{display:inline-block;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:1px 7px;border-radius:20px;margin-left:6px;vertical-align:middle}
.docstat.ok{color:#fff;background:var(--green)}
.docstat.wip{color:var(--navy);background:#eaf3fb;background:color-mix(in srgb,var(--blue) 20%,#fff)}
.docstat.plan{color:var(--soft);background:var(--panel);border:1px solid var(--rule)}
.docrow .docedit,.docrow .docdel{opacity:.5;font-size:13px;padding:0 2px}
.docrow:hover .docedit,.docrow:hover .docdel{opacity:1}
/* Research group / supervision pipeline (lab Group tab) */
/* org chart / supervision — masonry of manager cards, richer person rows */
.gpgrid{columns:2;column-gap:16px}
.gpgrid.single{columns:1}                                      /* one manager → span full width… */
.gpgrid.single .gcard{columns:2;column-gap:28px}              /* …and flow the people into two columns */
/* mobile LAST so it beats the single-group two-column rule (equal specificity → source order won;
   this block used to sit above it, so phones with ONE manager still got two squashed columns) */
@media(max-width:900px){.gpgrid,.gpgrid.single .gcard{columns:1}}
.gpgroup{break-inside:avoid;-webkit-column-break-inside:avoid;margin:0 0 16px;width:100%}
.gpgroup .gcard{padding:6px 16px}
.gprow{display:flex;gap:12px;align-items:flex-start;padding:12px 11px;border-bottom:1px solid var(--rule);break-inside:avoid;-webkit-column-break-inside:avoid;border-radius:10px}
.gprow.gclick{margin-left:-11px;margin-right:-11px}         /* hover highlight keeps ~11px boundary round the content + sits inset from the card edge */
.gprow:last-child{border-bottom:none}
.gprow .av.sm{flex:0 0 auto;margin-top:1px}
.gp-body{flex:1;min-width:0}
.gp-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.gp-name{font-size:13.5px;color:var(--navy);font-weight:600}
.gp-badges{display:inline-flex;gap:6px;align-items:center;flex-shrink:0}
.gp-role{font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:2px 7px;border-radius:8px;color:var(--soft);background:var(--panel);white-space:nowrap}
.gp-role.r-admin{color:var(--red);background:rgba(231,45,63,.1)}
.gp-role.r-mgr{color:var(--navy);background:var(--blue-soft)}
.gp-stage{font-family:var(--mono);font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;color:var(--blue);background:var(--blue-soft);border-radius:8px;padding:2px 8px;white-space:nowrap}
.gp-stage.overdue{color:var(--red);background:rgba(231,45,63,.1)}
.gp-meta{font-size:11.5px;margin-top:3px}
.gp-meta .warn{color:#9a6a00;font-weight:600}
.gp-projs{display:flex;flex-wrap:wrap;gap:5px;margin-top:6px}
.gp-projs .cchip{font-size:10.5px;padding:2px 8px}
.footlink{background:none;border:none;font:inherit;color:rgba(255,255,255,.7);font-weight:600;cursor:pointer;padding:0}
.footlink:hover{color:#fff}
.encstate{display:inline-flex;align-items:center;gap:6px;margin-left:10px}
.encstate::before{content:"";width:8px;height:8px;border-radius:50%;background:var(--ghost);display:inline-block}
.encstate.ok::before{background:var(--green)}.encstate.warn::before{background:var(--amber)}
/* minmax(0,1fr) not 1fr: a card whose content has a wide min-content (util bars, mono figures) would
   otherwise force its 1fr track past the container and scroll the page sideways on mobile. */
.grid2dash{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:22px;margin-top:22px}
@media(max-width:960px){.grid2dash{grid-template-columns:minmax(0,1fr)}}
/* dashboard: full-width cards stacked directly in the panel had no inter-card margin (they touched);
   give consecutive standalone cards / a card after the 2-col section the same 22px rhythm as elsewhere */
#dashboards > .card + .card,

/* Dashboards is tabbed: the cards now sit inside a [data-dashtab] wrapper, so the direct-child
   spacing selector above no longer matches them. Kept as well as, not instead of — the wrapper is a
   layout container and the originals stay correct if a card is ever hoisted back out. */
#dashboards .dashtab > .card + .card,
#dashboards .dashtab > .grid2dash + .card,
#dashboards .dashtab > .card + .grid2dash{margin-top:22px}
.dashproj-tw{overflow-x:auto}
#dashboards > .grid2dash + .card{margin-top:22px}
svg.chart{display:block;width:100%;height:auto;overflow:visible;margin-top:6px}
.chart-tx{font-family:var(--mono);font-size:10px;fill:var(--faint)}
.ubar .track2{position:relative}.ubar .seg{height:100%;float:left}
/* A pencilled booking — on the utilisation bar AND on the legend swatch that explains it, from ONE
   rule, so the key cannot drift from the mark it names. Hatched in the placeholder's blue rather
   than given a solid colour of its own, because it makes the same claim `.blk.ph` makes with its
   dash: the time is held, nobody has committed to it. */
.seg-soft{background:repeating-linear-gradient(135deg,var(--blue) 0 3px,transparent 3px 7px)}
.ubar .target{position:absolute;top:0;bottom:0;width:2px;background:var(--red);z-index:2}
.prow{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 0;border-bottom:1px solid var(--rule)}
.prow:last-child{border-bottom:none}
.prow .pn{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--navy);min-width:0}
.prow .pn .cdot{width:9px;height:9px;border-radius:2px;flex:0 0 auto}
.prow .pn .ptag{font-family:var(--mono);font-size:9px;text-transform:uppercase;letter-spacing:.05em;color:var(--faint);flex:0 0 auto}
.roles{display:flex;gap:5px;flex:0 0 auto}
.rdot{width:20px;height:20px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:9px;font-weight:600;border:1.5px solid var(--rule-blue);color:var(--ghost);background:var(--surface)}
.rdot.on{background:var(--brand);border-color:var(--brand);color:#fff}
.rdot.gap{border-color:var(--red);color:var(--red);border-style:dashed}
.rdot.waived{border-color:var(--rule-blue);color:var(--faint);border-style:dashed;background:var(--surface)}   /* QC deliberately waived — muted, not a red gap */
/* Pencilled in: the seat has a name but no commitment. Dashed in the placeholder's blue, the same
   language `.blk.ph` speaks on the timeline — NOT the filled `.on`, which claims cover. Ranked
   after `.gap` so a soft QC on a billable project still shows red: the gap is the true statement. */
.rdot.soft{border-color:var(--blue);color:var(--blue);border-style:dashed;background:var(--surface)}
/* QC-waiver control in the project editor */
.qcwaive{margin:8px 0 2px;padding:9px 11px;border:1px solid var(--rule,#E7ECF3);border-radius:9px;background:var(--panel)}
.qcwaive #peQcReason{margin-top:8px}
.qcwaive .qcwmeta{margin-top:6px;font-size:11px}
.numin{width:60px;font-family:var(--font);font-size:13px;padding:5px 8px;border:1px solid var(--rule-blue);border-radius:8px;
  color:var(--ink);background:var(--field);
  transition:border-color var(--t1) var(--ease),box-shadow var(--t1) var(--ease)}
.navbadge{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:15px;padding:0 4px;margin-left:6px;font-family:var(--mono);font-size:9.5px;font-weight:500;border-radius:999px;background:var(--red);color:#fff}
.navbadge[hidden]{display:none}

/* in-app notification bell + dropdown */
.notifwrap{position:relative;display:flex;align-items:center}
.notifwrap[hidden]{display:none}
.bellbtn{position:relative}
.bellico{width:18px;height:18px}
.bellbadge{position:absolute;top:1px;right:1px;min-width:14px;height:14px;padding:0 3px;margin-left:0;font-size:9px}
.notif-panel{position:absolute;top:calc(100% + 6px);right:0;width:330px;max-height:62vh;overflow-y:auto;
  background:var(--surface);color:var(--navy);border-radius:14px;box-shadow:0 14px 36px rgba(21,45,73,.24);
  border:1px solid var(--card-line);z-index:120}
.notif-panel[hidden]{display:none}
.notif-head{display:flex;align-items:center;justify-content:space-between;padding:11px 14px;
  border-bottom:1px solid var(--rule);position:sticky;top:0;background:var(--surface);border-radius:12px 12px 0 0}
.notif-head b{font-size:13px}
.notif-allread{font-size:11.5px;color:var(--blue);cursor:pointer;background:none;border:none;padding:0;font-family:inherit;margin-left:12px}
.notif-x{flex:0 0 auto;margin-left:auto;align-self:center;color:var(--ghost,#B8C4D6);font-size:11px;line-height:1;padding:3px 5px;border-radius:5px;opacity:0;transition:opacity .12s}
.notif-item:hover .notif-x,.notif-item:focus-within .notif-x{opacity:1}
.notif-x:hover{color:var(--red);background:var(--panel,#F2F5FA)}
.notif-allread:hover{text-decoration:underline}
.notif-list{display:flex;flex-direction:column}
.notif-item{display:flex;gap:9px;align-items:flex-start;text-align:left;width:100%;padding:10px 14px;
  background:none;border:none;border-bottom:1px solid var(--rule);cursor:pointer;font-family:inherit}
.notif-item:last-child{border-bottom:none}
.notif-item:hover{background:var(--panel)}
.notif-item.unread{background:var(--blue-soft)}
.notif-dot{flex:0 0 7px;width:7px;height:7px;border-radius:50%;margin-top:4px;background:transparent}
.notif-item.unread .notif-dot{background:var(--blue)}
.notif-b{display:flex;flex-direction:column;gap:2px;min-width:0}
.notif-title{font-size:12.5px;line-height:1.32;color:var(--navy)}
.notif-time{font-family:var(--mono);font-size:10px;color:var(--muted)}
.notif-empty{padding:20px 14px;color:var(--muted);font-size:12.5px;text-align:center}
@media (max-width:560px){ .notif-panel{position:fixed;left:8px;right:8px;width:auto;top:54px} }
.lvstat{font-family:var(--mono);font-size:8px;text-transform:uppercase;letter-spacing:.04em;padding:1px 5px;border-radius:3px;margin-left:5px}
.lvstat.approved{background:rgba(30,158,120,.14);color:#0f6e56}
.lvstat.requested{background:rgba(233,162,59,.16);color:#8A5E0F}
.txtlink2{color:var(--blue);font-weight:600;cursor:pointer;font-size:11px;margin-right:8px}.txtlink2:hover{color:var(--navy)}
/* del ✕ + Approve are <button>s (keyboard-operable); strip native chrome so they read as the old span/link */
button.del,button.txtlink2{appearance:none;-webkit-appearance:none;background:none;border:none;font-family:inherit;line-height:normal;vertical-align:baseline}

/* (1) the decorative pagehead motif must never intercept clicks; keep controls above it.
   z-index:35 also lifts the toolbar (and its dropdown popovers) above the grid's sticky header
   (.ghead z-index:6) + blocks, so the More/Settings menus aren't clipped by the grid below.
   Kept under the sticky topbar (z-index:40) so it never paints over the nav on scroll. */
.pagehead::before{pointer-events:none}
.controls{position:relative;z-index:35}
.btn-ghost.on{border-color:var(--red);color:var(--red);background:var(--accent-tint,rgba(231,45,63,.06))}

/* (3) collapse chevron in the name cell */
.lanechev{flex:0 0 auto;width:18px;height:18px;border:none;background:none;color:var(--ghost);cursor:pointer;font-size:11px;line-height:1;padding:0;border-radius:4px}
.lanechev:hover{color:var(--red);background:var(--panel)}

/* (4) hover tooltip on blocks */
#blkTip{position:fixed;z-index:120;max-width:240px;max-height:60vh;overflow-y:auto;background:var(--brand);color:#fff;border-radius:8px;padding:9px 12px;
  font-size:12px;line-height:1.45;box-shadow:0 10px 30px rgba(21,45,73,.35);pointer-events:none;opacity:0;transition:opacity .12s}
#blkTip.show{opacity:1}
/* a pale project colour as the card's background → flip the whole type ramp to navy for contrast */
#blkTip.tip-dark{color:#152D49}
#blkTip.tip-dark .tt{color:#152D49}
#blkTip.tip-dark .tsub{color:rgba(21,45,73,.75)}
#blkTip.tip-dark .tc{color:rgba(21,45,73,.6);border-bottom-color:rgba(21,45,73,.18)}
#blkTip.tip-dark .tl .tk{color:rgba(21,45,73,.55)}
#blkTip .tt{font-weight:600;font-size:12.5px;line-height:1.2;color:#fff}   /* override the generic .tt (navy) — the tooltip bg is navy, so the project name was invisible */
#blkTip .tsub{font-size:11.5px;color:#dfe7f2;margin-top:1px}   /* who (by-project grid) — the row is the project, so name the person */
/* header meta line doubles as a divider so the project name reads as the card's heading */
#blkTip .tc{font-family:var(--mono);font-size:9.5px;text-transform:uppercase;letter-spacing:.05em;color:#9fb2cc;margin:2px 0 6px;padding-bottom:6px;border-bottom:1px solid rgba(159,178,204,.2)}
/* detail rows: fixed tag column + flexible value → tags and values line up cleanly even when many
   deadlines with differently-sized labels are present (value wraps with a hanging indent) */
#blkTip .tl{display:grid;grid-template-columns:78px 1fr;column-gap:8px;align-items:baseline;margin-top:4px}
#blkTip .tl .tk{min-width:0;font-family:var(--mono);font-size:9px;text-transform:uppercase;letter-spacing:.05em;color:#7E93B2;line-height:1.3;overflow-wrap:anywhere}
#blkTip .tl .tv{min-width:0;overflow-wrap:anywhere}
#blkTip .tl .tv .td{display:block;color:#9fb2cc;font-size:10px;margin-top:1px}   /* a deadline's date/when on its own aligned line under the title */
#blkTip .tl .tv .tw.over{color:#ff9b9b}   /* overdue */
#blkTip .tl .tv .tw.soon{color:#ffcf8f}   /* soon / today */
#blkTip .tl .tk.lv{color:#ffcf8f}   /* leave overlapping the hovered block — amber accent */
#blkTip .tl .tk.dl{color:#8fd3ff}   /* a deadline falling within the hovered block — blue accent */

/* (5) projects detail cards */
.pcard-lg{display:flex;flex-direction:column}
.pteam{margin-top:10px;border-top:1px solid var(--rule);padding-top:9px}
.prow2{display:flex;gap:8px;font-size:12.5px;color:var(--soft);padding:2px 0}
.prow2 .rk{flex:0 0 70px;font-weight:600;font-size:9px;text-transform:uppercase;letter-spacing:.05em;color:var(--faint);padding-top:2px}
.prow2 .rv{flex:1;min-width:0}

/* (6) home landing cards */
.listcap{font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);margin:8px 0 14px}

/* (6) instructions guide */
.guide{max-width:820px}
.gsec{margin-bottom:22px;border-top:1px solid var(--rule);padding-top:16px}
.gsec:first-child{border-top:none;padding-top:0}
.gsec h3{margin:0 0 8px;font-size:17px;font-weight:600;color:var(--navy)}
.gsec p{font-size:14px;color:var(--soft);line-height:1.6;margin:0 0 8px;max-width:760px}
.gsec ul{margin:6px 0 0;padding-left:18px}
.gsec li{font-size:14px;color:var(--soft);line-height:1.6;margin:4px 0}
.gsec b{color:var(--navy);font-weight:600}.gsec i{color:var(--muted);font-style:normal;font-weight:500}

/* (1) settable date window */
/* Date pickers wear the kit's field treatment (background, radius, focus) at a compact size, rather
   than a bare bordered box. Without --field they fell back to the UA's own white, which is why they
   were the most obviously unfinished control in the app on a dark ground. */
.datein{font-family:var(--mono);font-size:11px;padding:5px 8px;border:1px solid var(--rule-blue);border-radius:8px;
  color:var(--ink);background:var(--field);width:118px;
  transition:border-color var(--t1) var(--ease),box-shadow var(--t1) var(--ease)}
.datein:focus-visible,.numin:focus-visible{outline:none;border-color:var(--brand);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--brand) 22%,transparent)}
.wknav .rdash{color:var(--faint)}
.jbtn{font-family:var(--font);font-size:11px;font-weight:600;color:var(--muted);background:rgba(28,34,51,.04);border:1px solid transparent;border-radius:6px;padding:5px 9px;cursor:pointer;white-space:nowrap;flex-shrink:0}
.jbtn:hover{border-color:var(--red);color:var(--red)}

/* timeline toolbar (single row): zone divider, overflow/settings popovers, range dropdown */
.tldiv{display:inline-block;width:0;height:22px;border-left:1px solid var(--rule-blue);margin:0 2px}
.tlbar .caret{font-size:11px;color:var(--faint);margin-left:1px}
.iconbtn{padding:7px 9px;font-size:15px;line-height:1}
.tlmenu{position:relative;display:inline-flex;align-items:center}
.tlmenu-trig.on,.tlmenu.open .tlmenu-trig{border-color:var(--red);color:var(--red)}
.tlmenu-pop{display:none;position:absolute;top:calc(100% + 6px);left:0;z-index:50;min-width:184px;
  background:var(--surface);border:1px solid var(--rule-blue);border-radius:9px;box-shadow:0 12px 32px rgba(21,45,73,.17);
  padding:6px;flex-direction:column;gap:1px}
.tlmenu-pop-r{left:auto;right:0}
.tlmenu.open .tlmenu-pop{display:flex}
.tlmenu-sec{font-size:9.5px;font-weight:600;text-transform:uppercase;letter-spacing:.07em;
  color:var(--faint);padding:8px 10px 4px}
.tlmenu-sec:first-child{padding-top:4px}
.tlmenu-item,.tlmenu-pop .jbtn{display:flex;align-items:center;gap:7px;width:100%;text-align:left;
  font-family:var(--font);font-size:13px;font-weight:500;color:var(--soft);background:none;border:none;
  border-radius:6px;padding:8px 11px;cursor:pointer;white-space:nowrap;text-decoration:none}
.tlmenu-item:hover,.tlmenu-pop .jbtn:hover{background:var(--panel);color:var(--navy)}
.tlmenu-item[role=menuitemcheckbox]::before,.tlmenu-item[role=menuitemradio]::before{content:"";display:inline-block;width:14px;color:var(--red);font-weight:700}
.tlmenu-item[role=menuitemcheckbox].on::before,.tlmenu-item[role=menuitemradio].on::before{content:"✓"}
.tlmenu-item[role=menuitemcheckbox].on,.tlmenu-item[role=menuitemradio].on{color:var(--navy)}
/* (2) project cards: clickable, manager, grouping */
.pcard.clickable{cursor:pointer;transition:border-color .15s,box-shadow .15s}
.pcard.clickable:hover{border-color:var(--rule-blue);box-shadow:0 8px 28px rgba(21,45,73,.07)}
.pmgr{display:flex;gap:8px;font-size:12.5px;color:var(--navy);font-weight:500;margin-top:8px}
.pmgr .rk{flex:0 0 70px;font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--faint);padding-top:1px}
.pgroup{margin-bottom:10px}
.pgroup .listcap{margin:6px 0 10px}
/* (4) current-date line */
#gbody{position:relative}
.todayline{position:absolute;top:0;bottom:0;width:2px;background:var(--red);opacity:.65;z-index:4;pointer-events:none}
.todayline::before{content:"";position:absolute;top:0;left:-3px;width:8px;height:8px;border-radius:50%;background:var(--red)}
/* (2) forecast tooltip rows: aligned label + value */
#blkTip .ftl{display:flex;justify-content:space-between;gap:18px;margin-top:2px}
#blkTip .ftl .tk{min-width:62px;font-family:var(--mono);font-size:9px;text-transform:uppercase;letter-spacing:.05em;color:#7E93B2}
#blkTip .ftl .tv{font-family:var(--mono);font-size:11px;white-space:nowrap}
#blkTip .ftl .tv.over{color:#ff9b9b}
/* (6) project colour swatch grid */
.swatchgrid{display:flex;flex-wrap:wrap;gap:7px;margin-top:5px;align-items:center}
/* `.swatchgrid .swatch` (not bare `.swatch`) so the margin reset outranks the modal's `label` margin —
   the "pick any colour" chip is a <label>, and an inherited label margin was pushing it out of line. */
.swatchgrid .swatch{flex:0 0 auto;box-sizing:border-box;width:26px;height:26px;border-radius:6px;border:2px solid transparent;cursor:pointer;padding:0;margin:0;line-height:0;vertical-align:middle;box-shadow:0 0 0 1px var(--rule,#E7ECF3) inset}
.swatch.on{border-color:var(--navy)}.swatch:hover{transform:scale(1.08)}
/* "no colour" chip — clients may have none; a muted ∅ on the surface */
.swatch-none{background:var(--surface);color:var(--muted,#5C6B80);font-size:13px;line-height:1;display:inline-flex;align-items:center;justify-content:center}
/* "pick any colour" chip — a rainbow hint until a custom colour is chosen (then its inline bg wins) */
.swatch-custom{position:relative;overflow:hidden;display:inline-block;background:conic-gradient(from 0deg,#f43f5e,#f59e0b,#22c55e,#3b82f6,#a855f7,#f43f5e)}
.swatch-custom input[type=color]{position:absolute;inset:0;width:100%;height:100%;opacity:0;border:0;padding:0;margin:0;cursor:pointer}
/* (4) photo avatars */
.av.photo{padding:0;overflow:hidden}
.av.photo img{width:100%;height:100%;object-fit:cover;object-position:center 8%;display:block}
.av.sm{width:30px;height:30px;flex:0 0 30px;font-size:11px}
.pcell{display:flex;align-items:center;gap:11px}
/* (3) projects list/table view */
.ptable .cdot{display:inline-block;width:9px;height:9px;border-radius:2px;vertical-align:-1px;margin-right:8px;flex:none}
.ptable td,.ptable th{white-space:nowrap}
.ptable th{font-family:var(--mono);letter-spacing:.06em}      /* technical column headers */
/* the staffing triad (design review P4): three fixed slots, so an unfilled role is a visible hole
   rather than an em dash. `off` is a dashed ring — deliberately drawn, not blank, because the absence
   IS the information. `gap` is the one that costs money: billable work with no independent QC. */
.td-team{padding-top:6px;padding-bottom:6px}
.roles{display:inline-flex;gap:5px}
/* NOTE: these are scoped to .roles on purpose. `.rl` is also the timeline block's role LINE
   (.blk .rl, ~line 474) — an unrelated element that happens to share the class. Unscoped, the
   24px circle + flex centring below applied to it too, so a role line wider than 24px
   ("Senior · 60%") overflowed both sides of a 24px box and lost its first character to the
   block's overflow:hidden. Keep both selectors scoped. */
.roles .rl{width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  font-size:9.5px;font-weight:600;letter-spacing:.01em;flex:0 0 auto}
.roles .rl.on{background:var(--brand);color:#fff}
/* the unfilled slots are a DRAWN ring, not a dashed border. A CSS dashed border on a 24px circle gets
   ~12 chunky dashes of uneven length plus a visible seam where the path closes — at the size this
   actually ships it read as scratchy. An angular repeating-conic-gradient masked to a hairline ring
   puts 24 identical dashes at identical spacing, so the slot still reads unmistakably "unfilled"
   without the ragged edge. Colour is then the only thing separating a plain hole from a QC gap. */
.roles .rl.off{--rl-ring:var(--field-line,var(--rule-blue));position:relative;background:transparent;border:0;color:var(--ghost)}   /* --field-line: an unfilled slot is a meaningful boundary — --rule-blue's ~1.4:1 made the hole invisible */
.roles .rl.off::before{content:"";position:absolute;inset:0;border-radius:50%;
  background:repeating-conic-gradient(var(--rl-ring) 0 6deg,transparent 0 15deg);
  -webkit-mask:radial-gradient(closest-side,transparent calc(100% - 1.25px),#000 calc(100% - 1.25px));
          mask:radial-gradient(closest-side,transparent calc(100% - 1.25px),#000 calc(100% - 1.25px))}
.roles .rl.gap{--rl-ring:var(--red);color:var(--red);font-weight:700}
/* client portfolio mix — total, then a bar encoding the active and billable SUBSETS, so the
   relationship between the three numbers is visible instead of inferred. Chart tokens, not status
   colours: this is a composition, not a verdict. */
.climx{display:inline-flex;align-items:center;gap:8px;justify-content:flex-end}
.climx b{font-family:var(--mono);font-weight:600;font-variant-numeric:tabular-nums;color:var(--ink)}
.climx-bar{position:relative;display:block;width:56px;height:5px;border-radius:3px;background:var(--ch-1-soft);overflow:hidden}
.climx-bar i{position:absolute;inset:0 auto 0 0;background:var(--ch-1);border-radius:3px}
.climx-bar u{position:absolute;inset:0 auto 0 0;height:2px;margin-top:1.5px;background:var(--ch-2);border-radius:3px;text-decoration:none}
.climx s{font-size:11px;color:var(--faint);text-decoration:none;white-space:nowrap;min-width:58px;text-align:left}
.ptable td{font-variant-numeric:tabular-nums}                 /* figures line up */
/* the windowed revenue & margin table on the Projects tab: figures right-aligned, a ruled total row */
.ptable .num{text-align:right}
.ptable tr.total td{font-weight:700;border-top:2px solid var(--rule-blue,#C8D2E3)}
.ptable td.num.neg{color:var(--red)}   /* the same red a negative margin gets on the burn card */
/* zebra striping on the Work list tables — a subtle alternating row tint (group-header rows excluded);
   set on the ROW so the per-cell hover background (tr:hover td) still paints over it on hover */
#projList .ptable tbody tr:nth-child(even):not(.grouphead),
#clientList .ptable tbody tr:nth-child(even):not(.grouphead),
#contractList .ptable tbody tr:nth-child(even):not(.grouphead),
#peopleTable tbody tr:nth-child(even):not(.grouphead){background:color-mix(in srgb,var(--navy,#152D49) 4%,transparent)}
/* Phones: the list tables can't show 8–11 columns, so keep the essentials and let the row-click open the
   full record. Columns are hidden by their data-col (stamped on cells by _stampCols), so it's reorder-safe. */
@media (max-width:680px){
  /* CSS owns mobile: !important overrides the desktop fixed-layout + inline column widths from wireTableResize */
  #projList table,#clientList table,#contractList table,#peopleTable{width:100%!important;table-layout:auto!important}
  #projList th,#clientList th,#contractList th,#peopleTable th{width:auto!important}
  #projList .colgrip,#clientList .colgrip,#contractList .colgrip{display:none}   /* no resize grips on touch */
  #projList [data-col=code],#projList [data-col=category],#projList [data-col=client],#projList [data-col=bill],#projList [data-col=manager],#projList [data-col=lead],#projList [data-col=senior],#projList [data-col=qc]{display:none}   /* projects have long names + inline selects → name + status only on a phone */
  #clientList [data-col=colour],#clientList [data-col=code],#clientList [data-col=sector],#clientList [data-col=notes],#clientList [data-col=active],#clientList [data-col=billable]{display:none}
  #contractList [data-col=colour],#contractList [data-col=no],#contractList [data-col=contact],#contractList [data-col=term],#contractList [data-col=duration],#contractList [data-col=projects],#contractList [data-col=value],#contractList [data-col=expires]{display:none}
  #peopleTable [data-col=email],#peopleTable [data-col=title],#peopleTable [data-col=seniority],#peopleTable [data-col=role],#peopleTable [data-col=account]{display:none}   /* keep name/FTE/status — Role is an inline select, not roster-scanning info on a phone */
  #clientList th[data-col=contact]{min-width:0}   /* drop the desktop widen — a 3-column phone table needs the room */
  #projList .ptable td,#projList .ptable th,#clientList .ptable td,#clientList .ptable th,#contractList .ptable td,#contractList .ptable th,#peopleTable td,#peopleTable th{padding-left:6px;padding-right:6px}
  #contractList td[data-col=contract],#clientList td[data-col=client]{white-space:normal;word-break:break-word}   /* let the long text column wrap instead of forcing width */
  #peopleTable td[data-col=name],#peopleTable td[data-col=name] b{white-space:normal;word-break:break-word}
  #peopleTable td[data-col=name]{max-width:56vw}
  #projList td[data-col=name],#projList td[data-col=name] *{white-space:normal;word-break:break-word}   /* the project name wraps (it lives in an inner .pn-cell) */
  #projList td[data-col=name]{max-width:62vw}
  #projList td select{min-width:0;max-width:34vw;font-size:11.5px}   /* the inline category/status/client selects must shrink to fit */
}
/* v0.295 list polish: the Project column is user-resizable (sticky headers can't work inside the
   .tblscroll overflow-x wrapper — vertical stickiness pins to the scroll container, not the page) */
.ptable thead th{background:var(--surface);box-shadow:0 1px 0 var(--rule,#E7ECF3)}
/* ⚠ RAISING --pnw ALONE DOES NOTHING, AND THE REASON IS NOT THE TABLE ALGORITHM. wireTableResize
   measures each header ONCE, freezes it as an inline width and adds .resizable — after which
   `table.resizable .pn-cell{width:auto}` below disables these variables for the rest of the session.
   So the variable is consumed during the FIRST auto-layout pass and is invisible to any measurement
   taken afterwards, which is why a previous note here concluded it had no effect: the test was run
   against the frozen state. (Reproduce the pre-freeze state by clearing every th.style.width, the
   table's tableLayout/width, AND removing .resizable — then it moves exactly as written.)

   Raising it is still not enough on its own: the frozen widths summed to precisely the wrapper, so
   any increase pushed the total past it and bought a horizontal scrollbar instead of a truncation.
   Both halves ship together — this value, and the budget clamp in wireTableResize that shrinks the
   other columns back to the wrapper. Measured at 1440px on a seeded lab org: 364 gives 0 truncated
   project titles with no overflow (the dot takes 9px of the cell, so 340 of title needs 349+);
   260 truncated 4 of 5, and past ~380 funder names start truncating instead. */
.ptable{--pcw:90px;--pnw:364px;--pclw:150px}
.ptable .th-code{position:relative;width:var(--pcw);min-width:56px}
.ptable .th-name{position:relative;width:var(--pnw);min-width:120px}
.ptable .th-client{position:relative;width:var(--pclw);min-width:80px}
.ptable .pn-cell{display:flex;align-items:center;flex-wrap:wrap;width:var(--pnw);min-width:0}
/* ⚠ THE GRANT NUMBER WAS WINNING. It sat on the title's line as flex:none — never shrinking — so on
   a project with a grant number the title got whatever was left (measured: 123px of a 340px need)
   and ellipsed, while an untitled-by-comparison reference code sat beside it in full. It goes on its
   own line now: the title gets the whole column, nothing truncates, and the number is legible rather
   than crammed. Costs ~18px of row height on the rows that have one. */
/* ⚠ BASIS 0, NOT auto OR 100%. Flex wraps on each item's HYPOTHETICAL size, before it shrinks any
   of them: at `auto` the title's hypothetical size is its full text width, so it wraps to its own
   line and pushes the colour dot above it; at `100%` it claims the whole line by definition. Only a
   basis of 0 lets the dot and the title share line one while the number below keeps its own. */
.ptable .pn-cell b{color:var(--navy);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1 1 0;min-width:0}
.ptable .pn-cell span:not(.cdot){flex:0 0 100%;margin-left:0;font-size:11px}
.ptable .cl-cell{width:var(--pclw);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* generic resizable columns (wireTableResize): fixed layout, every header gripped, cells clip to width.
   Scoped to .resizable so it works on any list table (Projects/Clients/Contracts/People), not only .ptable. */
table.resizable th{position:relative}
table.resizable th, table.resizable td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
table.resizable .pn-cell, table.resizable .cl-cell, table.resizable .cd-cell{width:auto;min-width:0}   /* let the fixed td own the width, not the old CSS var */
.colgrip{position:absolute;top:0;right:-5px;width:11px;height:100%;cursor:col-resize;touch-action:none;z-index:3}
.colgrip::after{content:'';position:absolute;left:5px;top:22%;height:56%;width:2px;border-radius:1px;background:var(--rule,#E7ECF3)}
.colgrip:hover::after,.colgrip:active::after{background:var(--blue,#6F97D8)}
/* drag-to-reorder columns — grab the header body (the grip still resizes). The dragged column fades;
   the target header shows a coloured bar on its leading edge = where the column will land. */
table.resizable th[draggable="true"]{cursor:grab}
table.resizable th[draggable="true"]:active{cursor:grabbing}
table.resizable th.col-dragging{opacity:.45}
table.resizable th.col-dragover{box-shadow:inset 3px 0 0 var(--brand,#C8102E)}
/* "Reset plan" — a mild-danger ghost action (muted red) sitting apart from the neutral plan buttons */
.btn.pj-reset{color:var(--red,#E72D3F);border-color:color-mix(in srgb,var(--red,#E72D3F) 35%,transparent)}
.btn.pj-reset:hover{background:color-mix(in srgb,var(--red,#E72D3F) 8%,transparent);border-color:var(--red,#E72D3F)}
/* the Code column — mono tag, first thing you read on a row; editable in place for planners.
   the inner .cd-cell carries the explicit px width so table-layout:auto actually honours the grip
   (a bare td width is only a hint when the cell content is narrow — same trick as .pn-cell) */
.ptable .td-code{padding-right:4px}
.ptable .cd-cell{width:var(--pcw);min-width:0}
.rowcode{font-family:var(--mono);font-size:11.5px;font-weight:600;color:var(--navy-soft);letter-spacing:.02em;width:100%;box-sizing:border-box;border:1px solid transparent;background:transparent;border-radius:7px;padding:3px 7px;cursor:text}
.rowcode::placeholder{color:var(--faint);font-weight:400}
.rowcode:hover{border-color:var(--rule,#E7ECF3)}
.rowcode:focus{border-color:var(--rule-blue,#C8D2E3);background:var(--panel,#F2F5FA);outline:none}
.rowcode-r{font-family:var(--mono);font-size:11.5px;font-weight:600;color:var(--navy-soft);letter-spacing:.02em}
.pcode{font-family:var(--mono);font-size:11px;font-weight:700;color:var(--navy-soft);background:var(--blue-soft);border-radius:6px;padding:1px 7px;vertical-align:2px}
html[data-theme=dark] .rowcode,html[data-theme=dark] .rowcode-r{color:#B9C6DA}
html[data-theme=dark] .rowcode:focus{background:rgba(255,255,255,.06)}
/* in-place selects — read as text until you hover, then show the control */
.rowsel{appearance:none;-webkit-appearance:none;border:1px solid transparent;background:transparent;font:inherit;font-size:13px;color:var(--soft);padding:3px 20px 3px 7px;margin:-3px 0 -3px -7px;border-radius:8px;cursor:pointer;max-width:180px;overflow:hidden;text-overflow:ellipsis;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='%23A5B0C2'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 7px center}
.rowsel:hover,.rowsel:focus{border-color:var(--rule-blue,#C8D2E3);background-color:var(--panel,#F2F5FA)}
.rowsel.pstat{font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;font-weight:700;font-family:var(--mono);padding:3px 20px 3px 8px;margin:0;border-radius:10px}
html[data-theme=dark] .rowsel:hover,html[data-theme=dark] .rowsel:focus{background-color:rgba(255,255,255,.06)}
.ptable .pill{background:var(--blue-soft);color:var(--navy-soft)}
/* group-header row inside a grouped table — one table (not one per group) keeps every column aligned */
.ptable tr.grouphead,.ptable tr.grouphead td{cursor:default}
.ptable tr.grouphead td{padding:18px 10px 6px;font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);background:transparent;border:0}
.ptable tbody tr.grouphead:first-child td{padding-top:2px}
.ptable tr.grouphead:hover td{background:transparent}
/* clients page */
.crollup{font-size:12.5px;color:var(--soft);margin:8px 0 10px}
.cchips{display:flex;flex-wrap:wrap;gap:6px}
.cchip{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;color:var(--navy);background:var(--blue-soft);border-radius:999px;padding:3px 9px}
.cchip.muted{background:transparent;color:var(--faint)}
.cchip .cdot{width:8px;height:8px;border-radius:2px}
.lock{font-size:12px}
/* inline text icon — the replacement for the emoji that used to sit in running text. Sized in em so it
   scales with whatever it sits beside, inherits currentColor so it never fights the surrounding ink,
   and nudged down a fraction to sit on the text's optical baseline rather than its box. */
.tico{width:1em;height:1em;vertical-align:-.13em;flex:0 0 auto;stroke-width:2.1}
label.chk{display:flex!important;align-items:center;gap:7px;font-size:12px;color:var(--soft);text-transform:none;letter-spacing:0;font-family:var(--font);margin-top:5px;cursor:pointer}
label.chk input{width:auto!important}
/* time off page */
.topend{border:1px solid var(--amber);background:rgba(233,162,59,.07);border-radius:8px;padding:12px 16px;margin-bottom:18px}
.topend h4{margin:0 0 8px;font-size:13px;color:#8A5E0F}
.topend .lrow{border-bottom-color:rgba(233,162,59,.2)}
/* a list table with a long cell no longer runs off the page on the right — it scrolls within this wrapper */
.tblscroll{overflow-x:auto;overscroll-behavior-x:contain}
.totable tbody tr{cursor:pointer}
.totable .allowin{width:62px;padding:4px 6px;text-align:right;font-family:var(--mono);font-size:12.5px;border:1px solid var(--rule-blue);border-radius:5px}
.totable .lowbal{color:var(--red)}
/* money layer (finance-only) */
.stat .val.good{color:var(--green)}   /* COO scorecard: on/above target (e.g. GP margin) */
/* budget burn — planned effort vs budgeted hours, with a schedule-elapsed tick */
.burn-row{padding:9px 0;border-bottom:1px solid var(--rule)}.burn-row:last-child{border-bottom:none}
.burn-head{display:flex;justify-content:space-between;align-items:center;font-size:13px;margin-bottom:5px}
.burn-head .pn{display:flex;align-items:center;gap:7px;color:var(--ink);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.burn-num{font-family:var(--mono);font-size:12px;color:var(--soft);white-space:nowrap}
.burn-num.over{color:var(--red)}.burn-num.burning{color:var(--amber)}.burn-num.ok{color:var(--green)}.burn-num.under{color:var(--blue)}
.burn-bar{position:relative;height:8px;border-radius:5px;background:var(--u0);overflow:hidden}
.burn-fill{position:absolute;left:0;top:0;height:100%;border-radius:5px;background:var(--green)}
.burn-fill.burning{background:var(--amber)}.burn-fill.over{background:var(--red)}.burn-fill.under{background:var(--blue)}
.burn-tick{position:absolute;top:-2px;width:2px;height:12px;background:var(--brand);transform:translateX(-1px);border-radius:1px}
.burn-actual{position:absolute;top:50%;width:9px;height:9px;background:var(--ink);border:1.5px solid #fff;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 1px rgba(0,0,0,.15)}
.burn-act{color:var(--ink)}
.burn-bar{overflow:visible}
.burn-note{font-size:11px;color:var(--faint);margin-top:3px}
.burn-note.over{color:var(--red)}.burn-note.burning{color:#8A5E0F}.burn-note.under{color:var(--blue)}
.burn-margin{color:var(--soft);font-weight:600}.burn-margin.neg{color:var(--red)}
/* F5 project profitability retro */
.prof-row{padding:9px 0;border-bottom:1px solid var(--rule)}.prof-row:last-child{border-bottom:none}
.prof-head{display:flex;justify-content:space-between;align-items:baseline;gap:10px}
.prof-head .pn{font-size:13px;font-weight:600;color:var(--navy);display:flex;align-items:center;gap:7px;min-width:0}
.prof-margin{font-weight:700;font-size:12.5px;white-space:nowrap;color:var(--soft)}
.prof-margin.ok{color:color-mix(in srgb,var(--green) 72%,#0a3a24)}.prof-margin.warn{color:#8A5E0F}.prof-margin.neg{color:var(--red)}
html[data-theme=dark] .prof-margin.ok{color:var(--green)}
.prof-note{font-size:11px;color:var(--faint);margin-top:3px}
/* F2 forward money & cash */
.fwd-stats{display:flex;gap:22px;flex-wrap:wrap;margin-bottom:12px}
.fwd-stat b{display:block;font-size:19px;font-weight:700;color:var(--navy);font-variant-numeric:tabular-nums}
.fwd-stat span{font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--faint)}
/* Workload Radar L2 — staffing signal card (short = amber above the line · over-staffed = blue below) */
.stf-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:4px}
.stf-badge{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:3px 11px;border-radius:999px;color:var(--soft)}
.stf-badge.short{background:color-mix(in srgb,var(--amber) 16%,var(--surface))}
.stf-badge.over{background:color-mix(in srgb,var(--blue) 20%,var(--surface))}
.stf-badge.ok{background:color-mix(in srgb,var(--green) 16%,var(--surface))}
.stf-fte{font-size:22px;font-weight:700;color:var(--navy);font-variant-numeric:tabular-nums}
.stf-unit{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--faint)}
.stf-sub{font-size:12.5px;color:var(--muted)}
.stf-when{font-size:11.5px;color:var(--muted);margin-bottom:8px}
.stf-spark{width:100%;height:46px;display:block;margin:6px 0 12px}
.stf-zero{stroke:var(--rule-blue,#C8D2E3);stroke-width:.6}
.stf-bar.up{fill:var(--amber)}
.stf-bar.dn{fill:var(--blue)}
.stf-stats{display:flex;gap:22px;flex-wrap:wrap}
.stf-stat b{display:block;font-size:18px;font-weight:700;color:var(--navy);font-variant-numeric:tabular-nums}
.stf-stat span{font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--faint)}
/* client base & retention (company dashboard card) */
.cb-stats{display:flex;gap:26px;flex-wrap:wrap;margin-bottom:14px}
.cb-stat b{display:block;font-size:20px;font-weight:750;color:var(--navy);font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.cb-stat span{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--faint)}
.cb-h{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--faint);margin:0 0 6px;padding-top:12px;border-top:1px solid var(--rule,#E7ECF3)}
.cb-row{display:flex;align-items:center;gap:10px;padding:8px 6px;margin:0 -6px;border-radius:8px;cursor:pointer;transition:background var(--t1) var(--ease)}
.cb-row:hover{background:var(--panel,#E9EEF6)}
.cb-name{flex:0 0 34%;min-width:0;display:flex;align-items:center;gap:7px;font-size:13px;font-weight:600;color:var(--navy);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cb-name .cdot{width:9px;height:9px;border-radius:2px;flex:0 0 auto}
.cb-tags{display:flex;gap:4px;flex:0 0 auto}
.cb-tag{font-family:var(--mono);font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;padding:2px 6px;border-radius:5px;background:var(--blue-soft,#E4ECF7);color:var(--navy-soft,#3f567d)}
.cb-tag.warn{background:rgba(233,162,59,.16);color:#8A5E0F}
.cb-tag.red{background:rgba(231,45,63,.12);color:#c0293a}
.cb-meta{flex:1;min-width:0;font-size:11.5px;color:var(--faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cb-rev{flex:0 0 auto;font-family:var(--mono);font-size:12px;font-weight:600;color:var(--navy);font-variant-numeric:tabular-nums}
/* the logo trend (retention P3) — active-client bars over 12 months */
.cb-trend{margin:2px 0 6px;padding-top:11px;border-top:1px solid var(--rule,#E7ECF3)}
.cbt-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:7px}
.cbt-l{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--faint)}
.cbt-delta{font-family:var(--mono);font-size:11px;font-weight:600}
.cbt-delta.up{color:#0f6e56}.cbt-delta.dn{color:var(--red,#E72D3F)}
.cbt-bars{display:flex;align-items:flex-end;gap:3px;height:32px}
.cbt-col{flex:1;height:100%;display:flex;align-items:flex-end}
.cbt-col i{display:block;width:100%;border-radius:2px 2px 0 0;background:var(--blue-soft,#C8D6EC);transition:background var(--t1) var(--ease)}
.cbt-col:hover i{background:var(--blue,#6F97D8)}
.cbt-col i.cur{background:var(--brand)}
html[data-theme=dark] .cb-stat b,html[data-theme=dark] .cb-name{color:#E8EEF7}
/* client "relationship" strip on the client record (retention P2) */
.crel{display:flex;gap:24px;align-items:center;flex-wrap:wrap;background:var(--field,#F1F5FA);border:1px solid var(--card-line);border-radius:12px;padding:11px 16px;margin:12px 0 2px}
.crel-cell b{display:block;font-size:16px;font-weight:750;color:var(--navy);font-variant-numeric:tabular-nums;letter-spacing:-.01em;line-height:1.2}
.crel-cell b .crel-sub{font-size:11px;font-weight:600;color:var(--faint)}
.crel-cell span{font-size:9.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--faint)}
.crel-risk{margin-left:auto;display:flex;gap:5px}
.crel-new{font-size:12px;color:var(--faint);background:var(--field,#F1F5FA);border:1px solid var(--card-line);border-radius:10px;padding:11px 14px;margin:12px 0 2px}
html[data-theme=dark] .crel-cell b{color:#E8EEF7}
/* contract amendments — history rows + the inline apply form (contract editor) */
.amrow{display:flex;align-items:flex-start;gap:10px;padding:8px 0;border-bottom:1px solid var(--rule,#E7ECF3)}
.amrow:last-child{border-bottom:none}
.am-main{flex:1;min-width:0}
.am-main b{font-size:13px;color:var(--navy)}
.am-eff{font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--faint);margin-left:8px}
.am-ch{font-size:12px;color:var(--soft);font-variant-numeric:tabular-nums;margin-top:2px}
.am-note{font-size:11.5px;color:var(--faint);margin-top:2px}
.am-undo{flex:0 0 auto;font-family:var(--font);font-size:11px;font-weight:600;color:var(--red,#E72D3F);background:none;border:1px solid color-mix(in srgb,var(--red,#E72D3F) 35%,transparent);border-radius:7px;padding:4px 10px;cursor:pointer;transition:background var(--t1) var(--ease)}
.am-undo:hover{background:color-mix(in srgb,var(--red,#E72D3F) 8%,transparent)}
.amform{background:var(--field,#F1F5FA);border:1px solid var(--card-line);border-radius:12px;padding:12px 14px;margin:2px 0 10px}
html[data-theme=dark] .am-main b{color:#E8EEF7}
/* 'amended' badge on the Contracts list — signals a contract carries an amendment history */
.ct-amend{display:inline-block;font-family:var(--mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;vertical-align:1px;
  padding:1px 6px;border-radius:5px;background:rgba(233,162,59,.16);color:#8A5E0F;white-space:nowrap}
/* ↗ to the stored document, beside a contract's title. Quiet until hovered: it sits in a cell whose
   job is the title, and a row full of blue arrows would read as the point of the table. */
.ct-doc{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;
  margin-left:2px;vertical-align:middle;font-size:12px;line-height:1;text-decoration:none;
  color:var(--faint);border-radius:6px}
.ct-doc:hover{color:var(--red);background:color-mix(in srgb,var(--red) 10%,transparent)}
/* cash runway (L3) — reuses .stf-spark/.stf-stats; positive = green, negative = red */
.cash-bar.pos{fill:var(--green)}
.cash-bar.neg{fill:color-mix(in srgb,var(--red) 78%,#B23)}
.cash-hire{margin-top:12px;padding:9px 12px;border-radius:10px;font-size:12.5px;border:1px solid var(--rule,#E7ECF3)}
.cash-hire b{display:block;color:var(--navy);font-size:13px}
.cash-hire span{color:var(--muted)}
.cash-hire.ok{background:color-mix(in srgb,var(--green) 8%,var(--surface))}
.cash-hire.bad{background:color-mix(in srgb,var(--amber) 10%,var(--surface))}
.cash-cfg{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap;margin-top:12px}
.cash-cfg label{display:flex;flex-direction:column;gap:3px;font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--faint)}
.cash-cfg input{width:120px;padding:6px 9px;font-size:13px;border:1px solid var(--rule-blue,#C8D2E3);border-radius:8px;background:var(--field);color:var(--ink)}
.fwd-legend{display:flex;gap:14px;font-size:10.5px;color:var(--muted);margin-bottom:6px}
.fwd-key{display:inline-flex;align-items:center;gap:5px}
.fwd-key::before{content:"";width:10px;height:10px;border-radius:2px;display:inline-block}
.fwd-key.rev::before{background:var(--brand)}.fwd-key.cash::before{background:color-mix(in srgb,var(--green) 60%,transparent)}
.fwd-chart{display:flex;gap:8px;align-items:flex-end;height:96px;padding:4px 0 0}
.fwd-col{flex:1;display:flex;flex-direction:column;align-items:center;gap:4px;min-width:0}
.fwd-bars{flex:1;width:100%;display:flex;gap:3px;align-items:flex-end;justify-content:center}
.fwd-bars span{flex:1;max-width:16px;border-radius:3px 3px 0 0;min-height:2px}
.fwd-rev{background:var(--brand)}.fwd-cash{background:color-mix(in srgb,var(--green) 60%,transparent)}
.fwd-m{font-size:9.5px;color:var(--faint)}
.runout-idle{color:var(--red);font-weight:600;font-size:12px}.runout-soon{color:#8A5E0F;font-weight:600;font-size:12px}
/* F4 retainer banks */
.ret-row{padding:9px 0;border-bottom:1px solid var(--rule)}.ret-row:last-child{border-bottom:none}
.ret-head{display:flex;justify-content:space-between;align-items:baseline;gap:10px}
.ret-head .pn{font-size:13px;font-weight:600;color:var(--navy);display:flex;align-items:center;gap:7px;min-width:0}
.ret-num{font-weight:600;font-size:12px;white-space:nowrap;color:var(--soft)}
.ret-num.over{color:var(--red)}.ret-num.burning{color:#8A5E0F}
.ret-bar{height:7px;border-radius:4px;background:var(--rule);overflow:hidden;margin:5px 0 3px}
.ret-fill{display:block;height:100%;border-radius:4px;background:var(--brand)}
.ret-fill.burning{background:var(--amber)}.ret-fill.over{background:var(--red)}
.ret-note{font-size:11px;color:var(--faint)}.ret-over{color:var(--red);font-weight:600}
.mgrid.retbox{background:color-mix(in srgb,var(--brand) 5%,transparent);border:1px solid var(--rule-blue);border-radius:10px;padding:4px 12px 12px;margin-top:8px}
.mgrid.retbox label{margin-top:8px}
/* grant funded-vs-committed FTE shown inline on the grants list (lab) */
.grant-fte{font-size:11.5px;font-weight:600;margin:2px 0 1px}
.grant-fte.ok{color:var(--green)}.grant-fte.over{color:var(--red)}.grant-fte.under{color:var(--blue)}
.fte-over{color:var(--red);font-weight:600}.fte-under{color:var(--blue);font-weight:600}
/* deadline radar */
.rad-row{display:flex;align-items:center;gap:12px;padding:7px 0;border-bottom:1px solid var(--rule);font-size:13px}
.rad-row:last-child{border-bottom:none}
.rad-row .rad-date{flex:0 0 92px;font-family:var(--mono);font-size:11.5px;color:var(--soft)}
.rad-row .rad-main{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink)}
.rad-row .rad-when{flex:0 0 auto;font-size:11.5px;color:var(--faint);white-space:nowrap;display:flex;align-items:center;gap:6px}
.rad-row.soon .rad-date,.rad-row.soon .rad-when{color:#8A5E0F}
.rad-row.over .rad-date,.rad-row.over .rad-when{color:var(--red)}
.rad-row.over{background:rgba(231,45,63,.04)}
.rad-cluster{font-size:10px;font-weight:700;color:var(--red);background:rgba(231,45,63,.1);border-radius:3px;padding:1px 5px}
.mini-stats{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:10px}
.mini-stat{flex:1 1 90px;background:var(--u0);border-radius:8px;padding:8px 10px}
.mini-stat .ms-v{font-size:20px;font-weight:700;color:var(--navy);line-height:1.1;font-variant-numeric:tabular-nums}
.mini-stat .ms-l{font-size:11px;color:var(--muted);margin-top:2px}
/* Applications overview — sleek list matching the grants cards */
.apbar{display:flex;align-items:center;gap:8px;margin-bottom:14px}
.apbar .viewlbl{font-family:var(--mono);font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--faint);margin-right:8px}
.apstats{margin-bottom:18px}
.apstats .ms-v,.apphead .mini-stat .ms-v{font-family:var(--mono);font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.apstats .ms-l,.apphead .mini-stat .ms-l{font-family:var(--mono);letter-spacing:.06em;text-transform:uppercase;font-size:9.5px}
.gcard.aplist{padding:2px 16px}
/* pipeline reading: a slim funnel strip in the section head + stage sub-headers in the list */
.ap-funnel{display:inline-flex;align-items:center;gap:8px;font-family:var(--mono);font-size:11px;color:var(--muted);margin-left:14px}
.apf-step{white-space:nowrap;font-variant-numeric:tabular-nums}
.apf-step.won{color:var(--green);font-weight:600}
.apf-arrow{color:var(--ghost)}
.ap-stagehead{display:flex;align-items:center;gap:7px;font-family:var(--mono);font-size:10px;font-weight:600;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted);padding:13px 0 5px;border-bottom:1px solid var(--rule,#E7ECF3)}
.apsh-n{color:var(--faint);letter-spacing:0}
/* stat band — four surface cards; the numbers a PI plans by, mono per the readout rule */
.apstatband{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin:18px 0 22px}
.apstat{background:var(--surface);border:1px solid var(--card-line);border-radius:12px;box-shadow:var(--shadow-card);padding:13px 15px 11px}
.apstat .ms-v{font-family:var(--mono);font-size:21px;font-weight:700;color:var(--navy);line-height:1.1;font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.apstat .ms-v small{font-size:12px;font-weight:600;color:var(--muted);letter-spacing:0}
.apstat .ms-l{font-family:var(--mono);font-size:9.5px;font-weight:600;letter-spacing:.07em;text-transform:uppercase;color:var(--muted);margin-top:5px}
.apstat .ms-sub{font-size:11.5px;color:var(--faint);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.apstat.hot .ms-v{color:var(--amber-ink)}
.apstat.late .ms-v{color:var(--red)}
@media(max-width:960px){.apstatband{grid-template-columns:1fr 1fr}}
/* the stage board — in-flight proposals as Drafting → Submitted → Under review columns.
   Cards open the application (stage changes live THERE — the board is a reading, not a control). */
.apboard{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;align-items:start}
.apcol{background:color-mix(in srgb,var(--surface) 55%,var(--bg));border:1px solid var(--card-line);border-radius:14px;padding:10px 10px 12px;min-height:96px}
.apcol-head{display:flex;align-items:center;gap:7px;font-family:var(--mono);font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);padding:4px 6px 10px}
.apcol-head .bar{width:22px;height:3px;border-radius:2px;background:var(--ghost)}
.apcol.s-submitted .apcol-head .bar{background:var(--blue)}
.apcol.s-under_review .apcol-head .bar{background:var(--amber)}
.apcol-head .cnt{margin-left:auto;color:var(--faint)}
.apccard{display:flex;gap:12px;background:var(--surface);border:1px solid var(--card-line);border-radius:12px;box-shadow:var(--shadow-card);padding:12px 14px;margin-top:8px;cursor:pointer;transition:box-shadow var(--t2) var(--ease),transform var(--t2) var(--ease)}
.apccard:first-of-type{margin-top:0}
.apccard:hover{box-shadow:var(--shadow-card-hover);transform:translateY(-1px)}
.apccard:focus-visible{outline:2px solid var(--blue);outline-offset:1px}
.apc-main{flex:1;min-width:0}
.apc-title{font-size:13.5px;font-weight:600;color:var(--ink);line-height:1.35}
.apc-meta{font-size:12px;color:var(--muted);margin-top:3px}
.apc-ready{display:flex;align-items:center;gap:8px;margin-top:9px}
.apc-ready .rbar{flex:1}
.apc-rlbl{font-family:var(--mono);font-size:9.5px;color:var(--muted);white-space:nowrap}
.apc-foot{display:flex;align-items:baseline;gap:6px 10px;margin-top:8px;flex-wrap:wrap}
.apc-when{font-family:var(--mono);font-size:10.5px;color:var(--faint);white-space:nowrap}
.apc-when.soon{color:var(--amber-ink)}
.apc-when.later{color:var(--brass)}
.apc-when.over{color:var(--red)}
.apc-amt{font-family:var(--mono);font-size:11.5px;font-weight:600;color:var(--soft);white-space:nowrap;margin-left:auto}
.apc-empty{font-size:12px;color:var(--faint);padding:6px 6px 2px}
@media(max-width:960px){.apboard{grid-template-columns:1fr}}
/* the list rows keep the classic .aprow shell; the date leads there too */
.aprow .dblock{margin:2px 0}
/* decided — quiet rows with the one action each outcome affords */
.apdrow{display:flex;align-items:center;gap:14px;padding:12px 16px;margin:0 -16px;border-bottom:1px solid var(--rule);cursor:pointer;transition:background .12s}
.apdrow:last-child{border-bottom:none}
.apdrow:hover{background:var(--u0)}
.apdrow:focus-visible{outline:2px solid var(--blue);outline-offset:-2px}
.apd-main{flex:1;min-width:0}
.apd-title{font-size:13.5px;font-weight:600;color:var(--ink)}
.apd-meta{font-size:12px;color:var(--muted);margin-top:1px}
.apd-amt{font-family:var(--mono);font-size:11.5px;font-weight:600;color:var(--soft);white-space:nowrap}
.apd-act{font-size:12px;font-weight:600;color:var(--blue);white-space:nowrap;background:none;border:0;padding:0;cursor:pointer;font-family:inherit}
.apd-act:hover{text-decoration:underline}
/* first run — the empty state sells: start from a live call, sections + limits preloaded */
.apstarters{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:16px}
.apstart{background:var(--surface);border:1px solid var(--card-line);border-radius:14px;box-shadow:var(--shadow-card);padding:18px 20px;cursor:pointer;text-align:left;font-family:inherit;transition:box-shadow var(--t2) var(--ease),transform var(--t2) var(--ease)}
.apstart:hover{box-shadow:var(--shadow-card-hover);transform:translateY(-2px)}
.apstart:focus-visible{outline:2px solid var(--blue);outline-offset:1px}
.apstart .sf{font-family:var(--mono);font-size:9.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--brass)}
.apstart h3{margin:7px 0 3px;font-size:15.5px;color:var(--ink)}
.apstart .ss{font-size:12.5px;color:var(--muted);line-height:1.5}
.apstart .sd{display:inline-block;font-family:var(--mono);font-size:10.5px;color:var(--soft);background:var(--u0);border-radius:6px;padding:3px 9px;margin-top:12px}
.apstart .go{display:block;font-size:13px;font-weight:600;color:var(--blue);margin-top:12px}
.apquiet{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:14px}
.apqcard{background:var(--panel);border:1px dashed var(--rule-blue);border-radius:14px;padding:16px 20px;cursor:pointer;text-align:left;font-family:inherit}
.apqcard:hover{border-color:var(--blue)}
.apqcard:focus-visible{outline:2px solid var(--blue);outline-offset:1px}
.apqcard h3{margin:0 0 4px;font-size:14px;color:var(--ink)}
.apqcard p{margin:0;font-size:12.5px;color:var(--muted);line-height:1.5}
.apradar{font-size:12.5px;color:var(--faint);margin-top:18px}
.apradar b{color:var(--brass)}
@media(max-width:960px){.apstarters,.apquiet{grid-template-columns:1fr}}
/* lifecycle header: stage stepper + readiness chip + resubmission links + outcome menu */
.apstage-row{position:relative;display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:12px}
/* the lifecycle is a kit .steptrack (dots + line + dated sub-lines); the checks chip docks on the
   current drafting step. The old bordered-segment stepper retired in 0.441.0. */
.apstage-row .steptrack{margin-top:16px}
.apstage-row .apchip{margin-top:8px}
/* header actions overflow — destructive actions leave the front row */
.apovf-wrap{position:relative}
.apovf-menu{position:absolute;top:calc(100% + 6px);right:0;z-index:30;display:flex;flex-direction:column;min-width:200px;padding:6px;
  background:var(--surface);border:1px solid var(--card-line);border-radius:12px;box-shadow:var(--shadow-card-hover)}
.apovf-menu button{text-align:left;font-family:var(--font);font-size:13px;font-weight:500;color:var(--soft);background:none;border:none;
  border-radius:8px;padding:9px 11px;cursor:pointer;transition:background var(--t1) var(--ease),color var(--t1) var(--ease)}
.apovf-menu button:hover{background:var(--panel);color:var(--navy)}
.apovf-menu button.danger{color:var(--red)}
.apovf-menu button.danger:hover{background:rgba(231,45,63,.07)}
/* header tiles carry urgency as a tint, mono discipline unchanged */
.apphead .mini-stat.hot{background:rgba(233,162,59,.13)}
.apphead .mini-stat.hot .ms-v{color:var(--amber-ink)}
.apphead .mini-stat.late{background:rgba(231,45,63,.10)}
.apphead .mini-stat.late .ms-v{color:var(--red)}
/* Overview reads first — a facts grid + the team as chips; one Edit reveals the form */
.apfacts{display:grid;grid-template-columns:1fr 1fr;gap:13px 22px}
.apfact .fl{font-family:var(--mono);font-size:9.5px;font-weight:600;letter-spacing:.07em;text-transform:uppercase;color:var(--faint)}
.apfact .fv{font-size:13.5px;color:var(--ink);margin-top:3px;font-weight:500;overflow-wrap:break-word}
.apfact .fv .q{color:var(--faint);font-weight:400}
.apfact .fv a{color:var(--blue)}
.appeople{display:flex;gap:7px;flex-wrap:wrap;margin-top:4px}
.apperson{display:inline-flex;align-items:center;gap:7px;background:var(--u0);border-radius:999px;padding:3px 11px 3px 3px;font-size:12px;font-weight:600;color:var(--soft)}
.apperson .pa{width:20px;height:20px;border-radius:50%;background:var(--brand);color:#fff;display:grid;place-items:center;font-size:9px;font-weight:700;flex:0 0 auto}
.apperson small{font-weight:500;color:var(--faint)}
.apnotes{border-top:1px solid var(--rule);margin-top:16px;padding-top:12px;font-size:13px;color:var(--soft);white-space:pre-wrap;overflow-wrap:break-word}
@media(max-width:700px){.apfacts{grid-template-columns:1fr}}
/* the budget hero — full cost, then who pays what as one bar */
.apbig{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.apbig .v{font-family:var(--mono);font-size:24px;font-weight:700;color:var(--navy);font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.apbig .q{font-size:12px;color:var(--faint)}
.apsplit{display:flex;height:14px;border-radius:7px;overflow:hidden;margin:12px 0 8px;background:var(--u0)}
.apsplit .f{background:var(--brand)}
.apsplit .u{background:var(--brass-2)}
.apsplit-key{display:flex;gap:16px;font-size:12px;color:var(--soft);flex-wrap:wrap}
.apsplit-key i{display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:6px;vertical-align:-1px}
.apsplit-key .f i{background:var(--brand)}
.apsplit-key .u i{background:var(--brass-2)}
.apsplit-key b{font-family:var(--mono);font-weight:600}
.apsignoff{font-size:11.5px;color:var(--faint);border-top:1px dashed var(--rule);margin-top:11px;padding-top:9px}
/* the studio rail leads with the whole draft's progress; group headers carry their counts */
.prop-railprog{display:flex;align-items:center;gap:8px;padding:4px 2px 10px;border-bottom:1px solid var(--rule);margin-bottom:8px}
.prop-railprog .rbar{flex:1}
.prp-lbl{font-family:var(--mono);font-size:9.5px;color:var(--muted);white-space:nowrap}
.prp-gn{color:var(--faint);letter-spacing:0;text-transform:none;font-weight:500}
/* prefill, promoted from a footnote to a labelled panel — it is a headline feature */
.prop-fillpanel{background:var(--panel);border:1px solid var(--rule);border-radius:12px;padding:12px 14px;margin:12px auto 0;max-width:78ch}
.pfp-eyebrow{font-family:var(--mono);font-size:9.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--brass)}
.pfp-sub{font-size:12px;color:var(--muted);margin:4px 0 8px;line-height:1.5}
.pfp-btns{display:flex;gap:6px;flex-wrap:wrap}
/* The prospect queue — an operator surface inside Settings. Deliberately plain: it is a worklist,
   not a dashboard, and the one thing that must stand out is which requests have been let in. */
.ps-list{display:flex;flex-direction:column;gap:8px;margin-top:8px}
/* ⚠ `.setgrid` is CSS MULTI-COLUMN (`columns:2`), not a grid — so a card lands in a ~460px column
   whatever its content wants. A worklist row does not fit there: measured, `.ps-acts` took 322 of
   418px and left the prospect's name 12px, wrapping it one character per line. `column-span:all`
   is the multi-column way to take the full width, and the row wraps its actions underneath rather
   than squeezing the name to nothing. */
.settings-page .setgrid>.ps-card{column-span:all}
.ps-row{display:flex;flex-wrap:wrap;gap:10px;align-items:flex-start;border:1px solid var(--rule);border-radius:10px;padding:9px 11px}
.ps-who{flex:1 1 260px;min-width:0;font-size:13px;color:var(--navy)}
.ps-meta{font-size:11.5px;margin-top:2px;overflow-wrap:anywhere}
.ps-acts{display:flex;gap:6px;align-items:center;flex-wrap:wrap;flex:0 0 auto}
@media(max-width:700px){
  .ps-row{flex-wrap:wrap}
  .ps-who{flex:1 0 100%}
  .ps-acts{flex:1 0 100%;margin-top:4px}
}
/* The proposal assistant. It borrows .prop-fillpanel's shell on purpose — the deterministic pull-ins
   and the drafting assist are the same gesture at different confidence, and giving the AI one a
   louder box would say the opposite of what the feature is for. The brass accent (--brass) is the
   suite's existing AI signal; everything provisional is dashed. */
.prop-aipanel{background:var(--panel);border:1px solid var(--rule);border-left:2px solid var(--brass);border-radius:12px;padding:12px 14px;margin:12px auto 0;max-width:78ch}
.prop-zen .prop-aipanel{display:none}
.pa-card{width:min(760px,96vw)}
.pa-srclist{display:flex;flex-direction:column;gap:8px;margin:12px 0 0;max-height:44vh;overflow:auto}
.pa-src{border:1px dashed var(--rule);border-radius:10px;padding:8px 10px;background:transparent;transition:border-color .15s,background .15s}
.pa-src.on{border-style:solid;border-color:color-mix(in srgb,var(--brass) 45%,transparent);background:color-mix(in srgb,var(--brass) 5%,transparent)}
/* ⚠ `.modal-card label` (0,1,1) sets display:block, 10px, uppercase and faint on EVERY label in
   a modal — the house form-label look. A source header is a row of content that happens to be
   a <label> so clicking it toggles its checkbox, not a field caption, so it has to out-specify
   that rule rather than inherit it. `.pa-instr` deliberately does NOT: a field caption is
   exactly what that one is. */
.modal-card label.pa-srchd{display:flex;align-items:center;gap:8px;cursor:pointer;font-size:13px;text-transform:none;letter-spacing:0;font-weight:400;color:var(--navy);margin:0}
.pa-srchd input[type=checkbox]{flex:0 0 auto}
.pa-srclbl{font-weight:600;color:var(--navy)}
.pa-srcorigin{font-size:11.5px;color:var(--muted)}
.pa-srctext{margin:8px 0 0;padding:8px 10px;background:var(--surface,#fff);border:1px solid var(--rule);border-radius:8px;font-family:var(--mono);font-size:11.5px;line-height:1.55;white-space:pre-wrap;max-height:180px;overflow:auto;color:var(--navy)}
.pa-refs{margin-top:8px;display:flex;flex-direction:column;gap:4px;max-height:160px;overflow:auto}
.pa-ref{display:flex;gap:8px;align-items:center;font-size:12px;color:var(--navy)}
.pa-ref span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pa-writer .paWLabel{font-size:12.5px;padding:4px 7px;flex:1;min-width:0}
.pa-writer textarea{width:100%;margin-top:6px;font-size:12.5px}
.pa-add{align-self:flex-start}
.pa-instr{display:block;font-size:11.5px;color:var(--muted);margin:12px 0 0}
.pa-instr input{width:100%;margin-top:4px}
.pa-sendline{margin:10px 0 0;font-size:12px;font-variant-numeric:tabular-nums;color:var(--muted)}
.pa-working{display:flex;align-items:center;gap:10px;padding:26px 2px;font-size:13.5px;color:var(--navy)}
.pa-spin{width:15px;height:15px;border-radius:50%;border:2px solid color-mix(in srgb,var(--brass) 30%,transparent);border-top-color:var(--brass);animation:pa-spin .8s linear infinite}
@keyframes pa-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.pa-spin{animation-duration:2.4s}}
.pa-prov{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap;margin:10px 0 8px;font-size:12px}
.pa-gaps{border:1px dashed var(--amber,#B8860B);border-radius:10px;padding:9px 12px;margin:8px 0;font-size:12.5px;background:color-mix(in srgb,var(--amber,#B8860B) 7%,transparent)}
.pa-gaps ul{margin:5px 0 4px;padding-left:18px}
.pa-gaps .lmuted{font-size:11.5px}
.pa-paras{display:flex;flex-direction:column;gap:8px;max-height:46vh;overflow:auto;margin-top:6px}
.pa-para{display:flex;gap:10px;align-items:flex-start;border:1px solid var(--rule);border-radius:10px;padding:9px 11px}
.pa-para.gap{border-style:dashed;border-color:var(--amber,#B8860B);background:color-mix(in srgb,var(--amber,#B8860B) 5%,transparent)}
.pa-para.taken{opacity:.5}
.pa-para.taken .pa-ptext{text-decoration:none;color:var(--muted)}
.pa-ptext{flex:1;min-width:0;font-size:13px;line-height:1.6;color:var(--navy);white-space:pre-wrap}
.pa-para .btn{flex:0 0 auto}
.pa-gap{font-family:var(--mono);font-size:11.5px;color:var(--amber,#B8860B);border:1px dashed currentColor;border-radius:5px;padding:0 5px}
.pa-findings{display:flex;flex-direction:column;gap:7px;max-height:50vh;overflow:auto;margin-top:6px}
.pa-finding{display:flex;gap:9px;align-items:baseline;border:1px solid var(--rule);border-radius:10px;padding:8px 11px;font-size:13px;line-height:1.55}
.pa-fkind{flex:0 0 auto;font-family:var(--mono);font-size:9.5px;font-weight:700;letter-spacing:.07em;padding:2px 7px;border-radius:20px;border:1px solid currentColor}
.pa-finding.missing .pa-fkind,.pa-finding.unev .pa-fkind{color:var(--red)}
.pa-finding.unclear .pa-fkind,.pa-finding.length .pa-fkind{color:var(--amber,#B8860B)}
.pa-finding.ok .pa-fkind{color:var(--green)}
.pa-ftext{flex:1;min-width:0;color:var(--navy)}
@media(max-width:640px){
  .pa-para,.pa-finding{flex-wrap:wrap}
  .pa-ptext,.pa-ftext{flex:1 0 100%}
  .pa-srchd{flex-wrap:wrap}
}
/* the won moment */
.apwon-mark{width:44px;height:44px;border-radius:50%;background:rgba(30,158,120,.14);color:var(--green);display:grid;place-items:center;font-size:20px;font-weight:700}
/* readiness — the ring + its one primary action */
.apring{display:flex;align-items:center;gap:16px}
.apring svg{flex:0 0 auto}
.apring .rtx{font-size:12.5px;color:var(--soft);min-width:0}
.apring .rtx b{color:var(--ink)}
.apsubrow{margin-top:14px;display:flex;flex-direction:column;align-items:flex-start;gap:8px}
.apsubnote{font-size:11.5px;color:var(--faint)}
.apchip{font-family:var(--mono);font-size:10.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;cursor:pointer;
  color:#8A5E0F;background:rgba(233,162,59,.14);border:1px solid transparent;border-radius:8px;padding:6px 11px;white-space:nowrap;
  transition:filter var(--t1) var(--ease)}
.apchip.ok{color:var(--green);background:rgba(30,158,120,.12)}
.apchip:hover{filter:brightness(.96)}
.apout{position:absolute;top:calc(100% + 6px);z-index:30;display:flex;flex-direction:column;min-width:250px;padding:6px;
  background:var(--surface);border:1px solid var(--card-line);border-radius:12px;box-shadow:var(--shadow-card-hover)}
.apout button{text-align:left;font-family:var(--font);font-size:13px;font-weight:500;color:var(--soft);background:none;border:none;
  border-radius:8px;padding:9px 11px;cursor:pointer;transition:background var(--t1) var(--ease),color var(--t1) var(--ease)}
.apout button:hover{background:var(--panel);color:var(--navy)}
.apresub-row{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}
.apresub{font-size:12px;color:var(--soft);background:var(--panel);border:1px solid var(--rule,#E7ECF3);border-radius:8px;
  padding:4px 10px;cursor:pointer;max-width:420px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  transition:border-color var(--t1) var(--ease),color var(--t1) var(--ease)}
.apresub:hover{border-color:var(--brass);color:var(--navy)}
/* budget: the lump-sum personnel input gets the money treatment */
.apmoney{display:flex;align-items:center;gap:7px}
.apmoney input{flex:1;min-width:0;box-sizing:border-box;font-family:var(--mono);font-variant-numeric:tabular-nums}
.apmoney-cur{font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;color:var(--faint)}
html[data-theme=dark] .apchip{color:#E2B564}
.aprow{display:flex;justify-content:space-between;gap:16px;align-items:center;padding:12px 16px;margin:0 -16px;border-bottom:1px solid var(--rule);cursor:pointer;transition:background .12s}
.aprow:last-child{border-bottom:none}
.aprow:hover{background:var(--u0)}
.aprow:focus-visible{outline:2px solid var(--blue);outline-offset:-2px}
.ap-main{flex:1;min-width:0}
.ap-main .apc-ready{max-width:340px}
.ap-title{font-weight:600;color:var(--navy);display:flex;align-items:center;gap:8px;min-width:0}
.ap-title .apt-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ap-meta{font-size:12px;color:var(--muted);margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ap-right{flex:0 0 auto;text-align:right;font-size:12px;display:flex;flex-direction:column;gap:3px;align-items:flex-end}
.ap-when{color:var(--faint);white-space:nowrap}
.ap-when.soon{color:#8A5E0F}
.ap-when.over{color:var(--red);font-weight:600}
.ap-amt{color:var(--muted);font-variant-numeric:tabular-nums}
.apill{display:inline-block;padding:2px 9px;border-radius:999px;font-size:11px;font-weight:600;flex:0 0 auto;letter-spacing:.01em}
.apill.drafting{background:var(--u0);color:var(--muted)}
.apill.submitted{background:var(--blue-soft);color:var(--blue)}
.apill.under_review{background:rgba(230,160,20,.16);color:#8A5E0F}
.apill.awarded{background:rgba(30,158,120,.15);color:#1E9E78}
.apill.rejected{background:rgba(231,45,63,.10);color:var(--red)}
.apill.withdrawn{background:var(--u0);color:var(--faint)}
/* Application page — command header + in-page tab strip */
.apphead{background:var(--surface);border:1px solid var(--card-line);border-radius:16px;padding:16px 18px;box-shadow:var(--shadow-card)}
.apphead-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.apphead-title{margin:0;font-size:22px;color:var(--navy);min-width:0;overflow:hidden;text-overflow:ellipsis}
.apphead-meta{font-size:13px;margin-top:5px}
.apphead-acts{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.apptabs{display:flex;gap:2px;margin:16px 0 0;border-bottom:1px solid var(--rule);flex-wrap:wrap}
.apptab{background:transparent;border:0;border-bottom:2px solid transparent;border-radius:0;padding:9px 14px;font-family:inherit;font-size:14px;color:var(--muted);cursor:pointer}
.apptab:hover{color:var(--navy)}
.apptab.on{color:var(--navy);border-bottom-color:var(--brand)}
.chkrow{display:flex;align-items:center;gap:11px;padding:10px 0;border-bottom:1px solid var(--rule);font-size:13.5px}
.chkrow:last-of-type{border-bottom:none}
.chk-ico{flex:0 0 20px;width:20px;height:20px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:12px;font-weight:700}
.chk-ico.ok{background:rgba(30,158,120,.15);color:#1E7A46}
.chk-ico.no{background:var(--u0);color:var(--muted)}
.chk-lbl{flex:1;min-width:0;color:var(--ink)}
.chk-hint{font-size:12px;flex:0 0 auto;text-align:right}
.stat.fincard{position:relative;padding-left:14px}
.stat.fincard::before{content:"";position:absolute;left:0;top:8px;bottom:8px;width:3px;border-radius:2px;background:#1E9E78}
.row2.fin{background:rgba(30,158,120,.06);border:1px solid rgba(30,158,120,.18);border-radius:8px;padding:6px 10px 10px;margin-top:8px}
.mgrid.finbox{background:rgba(30,158,120,.06);border:1px solid rgba(30,158,120,.18);border-radius:10px;padding:4px 12px 12px;margin-top:8px}
.mgrid.finbox label{margin-top:8px}
/* project-categories editor: a compact "billable" toggle inline on each row */
.catrow .catbill{margin-top:0;flex:0 0 auto;white-space:nowrap;font-size:11px;color:var(--muted)}
.catrow .catbill input{margin:0}
/* ⚠⚠ THE ROW OVERFLOWED THE CARD AND CLIPPED A BUTTON OFF ITS LEFT EDGE. `justify-content:
   flex-end` with no wrap pushes the surplus out of the padding box, so the assignment
   editor's Delete sat half outside the dialog once 'Open project →' joined the row — and
   that button, having nowhere to go, wrapped its own label onto three lines and stood twice
   as tall as its neighbours. Wrapping keeps whole buttons inside the card; nowrap on the
   labels stops a single button becoming a paragraph. */
.modal-actions{display:flex;flex-wrap:wrap;gap:10px;justify-content:flex-end;margin-top:22px;align-items:center}
.modal-actions .btn{white-space:nowrap;min-width:92px;text-align:center}
/* ⚠ A PAIR SHOULD LOOK LIKE A PAIR. Cancel measured 78px beside Save's 65px — close enough
   to read as a mistake rather than a hierarchy, and every dialog in the app shows that pair.
   One minimum width makes them a set; the labels still size anything longer. `btn-sm` is
   exempt: the secondary row is deliberately lighter than the footer it sits above. */
.modal-actions .btn-sm{min-width:0}
/* Contextual actions that LEAVE this form — repeat it elsewhere, open the project behind it.
   Above the footer and visually lighter, so the footer can stay a straight answer to
   "save or not". Right-aligned to sit over the confirm pair rather than float free. */
.modal-subactions{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end;margin-top:18px}
.modal-subactions + .modal-actions{margin-top:10px}
.modal-subactions .btn{white-space:nowrap}
@media(max-width:960px){.below{grid-template-columns:1fr}}

/* ---------------- milestone markers on the timeline (lab mode) ---------------- */
/* markers coloured by urgency (same buckets as the Deadlines tab): future=brand, soon=amber, overdue=red */
.msmark{position:absolute;top:0;bottom:0;width:0;border-left:2px dashed var(--red);z-index:2;pointer-events:none}
.msmark.soon{border-left:2px solid #BA7517}
.msmark.over{border-left:2px solid #D64545}
.msmark .msflag{position:absolute;top:3px;left:-5px;width:9px;height:9px;background:var(--red);
  border:1.5px solid #fff;border-radius:1px;transform:rotate(45deg);pointer-events:auto;box-shadow:0 1px 2px rgba(0,0,0,.25)}
.msmark.soon .msflag{background:#BA7517}
.msmark.over .msflag{background:#D64545}
/* delivery axis on the timeline — one shape per type (all keep the urgency background colour):
   milestone = small diamond (default) · deliverable = larger diamond (the acceptance artifact) ·
   gate = upright square (go/no-go) · report = disc (funder/billing period) */
.msmark.t-deliverable .msflag{width:11px;height:11px;top:2px;left:-6px}
.msmark.t-gate .msflag{transform:none;border-radius:2px}
.msmark.t-report .msflag{transform:none;border-radius:50%}
/* A task is the smallest marker on the lane and the only hollow one: it is the WORK, not a
   commitment to a client, and it should read as lighter than the deliverable it feeds. */
.msmark.t-task .msflag{transform:none;border-radius:2px;width:6px;height:6px;background:transparent;border:1.5px solid currentColor;opacity:.75}
.msmark.t-task.reached .msflag{background:currentColor;opacity:.45}
/* reached (accepted/met/submitted) → a solid green marker, gently dimmed (it's behind you) */
.msmark.reached{border-left-color:var(--green);border-left-style:solid;opacity:.7}
.msmark.reached .msflag{background:var(--green)}

/* ---------------- home hero → suite-kit.css (.home-hero + .home-hero-* + the in-hero .statband) ----------------
   Promoted to the kit so Theorem/Proof/Lemma share one hero. Lemma's static hero markup (index.html) and
   renderHomeStats() feed it; the brass edition stamp + mono readouts are the kit's. Nothing stays here. */
/* ---------- home cockpit: fixed-height glance band + full-width sections below ---------- */
/* The top band = two glance cards side by side (attention wide · this-week narrow) with a FIXED height —
   content scrolls INSIDE the card, so however many items land in them the band never grows and nothing
   below shifts. Everything under the band (radar · my work · research) is full-width in a stable order;
   those can grow tall without moving anything beside them. :has() collapses the band when a card is
   empty/hidden (member view · no-auth demo), so there's never a dead column. */
.home-top{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px;align-items:stretch;margin:18px 0}
.home-top>div{min-width:0}
.home-top .mywork{height:332px;margin:0;display:flex;flex-direction:column;overflow:hidden}
.home-top .mw-head{flex:0 0 auto}
.home-top .attlist,.home-top .mw-body{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;padding-right:8px;margin-right:-8px}
.home-top .attlist::-webkit-scrollbar,.home-top .mw-body::-webkit-scrollbar{width:6px}
.home-top .attlist::-webkit-scrollbar-thumb,.home-top .mw-body::-webkit-scrollbar-thumb{background:var(--rule-blue,#C8D2E3);border-radius:3px}
.home-top #weeklyBrief .brief-head{flex-wrap:wrap;row-gap:8px}   /* actions wrap below the title instead of bleeding past the card edge */
.home-top #weeklyBrief .brief-acts .btn{padding:4px 9px;font-size:11px}
@media(max-width:760px){.home-top #weeklyBrief .mw-cols{grid-template-columns:1fr;gap:14px}}
/* tabbed panel under the band: ONE card whose tinted title band IS the tab bar — the tabs are the
   section titles (active = navy + brand underline), and the active section's own header keeps only
   its description line + action buttons (its title is the tab). Panel height follows the active card. */
.home-tabs{margin:0 0 18px;background:var(--surface);border:1px solid var(--card-line);border-radius:16px;
  padding:20px 22px;box-shadow:var(--shadow-card)}
.ht-bar{display:flex;align-items:baseline;gap:22px;flex-wrap:wrap;margin:-20px -22px 16px;padding:11px 22px 0;
  background:var(--panel);border-bottom:1px solid var(--rule,#E7ECF3);border-radius:16px 16px 0 0}
.ht-bar:empty{display:none}
.ht-bar button{font-family:var(--font);font-weight:700;font-size:15px;letter-spacing:-.01em;color:var(--faint);
  background:none;border:none;border-bottom:2px solid transparent;padding:2px 0 10px;cursor:pointer;
  transition:color var(--t1) var(--ease),border-color var(--t1) var(--ease)}
.ht-bar button:hover{color:var(--soft)}
.ht-bar button.on{color:var(--navy);border-bottom-color:var(--brand)}
.ht-bar button:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
/* inner section cards: the panel supplies the chrome; drop the duplicate title, keep subtitle+actions */
.home-tabs .ht-body .mywork{background:none;border:none;box-shadow:none;padding:0;margin:0}
.home-tabs .ht-body .mywork > .mw-head:first-child{margin:0 0 14px;padding:0;background:none;border-bottom:none;border-radius:0}
.home-tabs .ht-body .mw-head .mw-title{display:none}
@media(max-width:760px){.home-tabs{padding:18px 16px}.ht-bar{margin:-18px -16px 14px;padding:9px 16px 0;gap:16px}}
.home-top:not(:has(#weeklyBrief:not([hidden]))){grid-template-columns:1fr}
.home-top:not(:has(#homeAttention:not([hidden]))){grid-template-columns:1fr}
.home-top:not(:has(>div:not([hidden]))){display:none}
@media(max-width:900px){.home-top{grid-template-columns:1fr}}
.att-count{font-family:var(--mono);font-size:12px;color:var(--faint)}
.attlist{display:flex;flex-direction:column}
.att-row{display:grid;grid-template-columns:9px 1fr auto;gap:14px;align-items:center;padding:12px 2px;border-top:1px solid var(--rule,#E7ECF3)}
.att-row:first-child{border-top:none}
.att-dot{width:8px;height:8px;border-radius:50%}
.att-dot.red{background:var(--red)} .att-dot.amber{background:var(--amber)} .att-dot.blue{background:var(--blue)}
.att-tx{min-width:0}
.att-tx b{font-weight:600;font-size:14.5px;color:var(--navy)}
.att-tx small{display:block;color:var(--muted);font-size:12.5px;margin-top:2px}
.att-act{font-family:var(--mono);font-size:10.5px;letter-spacing:.05em;text-transform:uppercase;color:var(--brass);font-weight:600;
  border:1px solid var(--rule-blue);border-radius:8px;padding:6px 12px;background:var(--field);cursor:pointer;white-space:nowrap;
  transition:border-color var(--t1) var(--ease),background var(--t1) var(--ease),color var(--t1) var(--ease)}
.att-act:hover{border-color:var(--brass);background:var(--panel)}
/* Jump strip — brand-coloured chips (navy Company / plum Lab via --brand). The label sits in its own
   column and the chips wrap inside .hj-links, so a second line stays indented under the first chip
   (hanging indent) instead of wrapping back to the far left. */
.home-jump{display:flex;align-items:flex-start;gap:14px;padding:14px 18px;margin-top:20px;
  background:var(--surface);border:1px solid var(--card-line);border-radius:14px;box-shadow:var(--shadow-card)}
.hj-label{flex:0 0 auto;font-family:var(--mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--faint);padding-top:9px}
.hj-links{display:flex;flex-wrap:wrap;gap:8px;flex:1;min-width:0}
.hj-link{font-family:var(--mono);font-size:11.5px;color:rgba(255,255,255,.92);cursor:pointer;padding:6px 12px;line-height:1.2;
  background:var(--brand);border:1px solid transparent;border-radius:8px;white-space:nowrap;
  transition:filter var(--t1) var(--ease),color var(--t1) var(--ease)}
.hj-link:hover{filter:brightness(1.25);color:#fff}
.hj-link:focus-visible{outline:2px solid var(--blue);outline-offset:2px}

/* ---------------- mobile: collapsing menu + responsive panels ("all windows sync") ---------------- */
.navtoggle{display:none;background:none;border:none;color:#fff;font-size:23px;line-height:1;cursor:pointer;padding:4px 8px}
@media(max-width:820px){
  .topbar{padding:0 14px;gap:10px}
  .brand-logo{display:flex;align-items:center}
  /* stack the wordmark + edition badge on mobile, badge flush-left (drop the desktop indent) */
  .brand-text{display:flex;flex-direction:column;align-items:flex-start;line-height:1.15}
  .brand-text .lab-badge{margin-left:0;margin-top:2px}
  .navtoggle{display:block}
  .home-hero{padding:26px 18px 22px;margin:16px 0 20px;border-radius:14px}
  .home-hero-inner{gap:14px}
  .home-hero-mark{width:38px;height:38px;flex:0 0 38px}
  .home-hero-name{font-size:25px}
  .home-hero-edition{font-size:12px}
  .home-hero-desc{font-size:13.5px}
  /* the narrow hero-tile pairing (2×2) moved to suite-kit.css `.home-hero .statband` — #homeStats sits
     inside .home-hero, so the kit rule covers this element exactly. Removed rather than left as an
     identical duplicate: two copies of the same rule is how the kit quietly stops being the source. */
  .topnav{position:absolute;top:54px;left:0;right:0;display:none;flex-direction:column;align-items:stretch;
    height:auto;max-height:calc(100dvh - 54px);overflow-y:auto;-webkit-overflow-scrolling:touch;
    gap:0;padding:6px 0;background:var(--nav-ink);box-shadow:0 14px 28px rgba(0,0,0,.28);z-index:60}
  /* max-height + overflow: without them the open drawer ran to its natural height with NO way to
     scroll — on phone-height screens everything below the Team group (Timesheet included) was
     simply unreachable. Found live in the 2026-08-13 walkthrough. */
  .topnav.open{display:flex}
  .topnav .navbtn{height:auto;justify-content:flex-start;padding:13px 22px;font-size:13px;border-radius:0}
  .topnav .navbtn.on{background:rgba(255,255,255,.08)}
  /* dropdown groups flatten to inline lists in mobile nav */
  .navdrop{height:auto;display:flex;flex-direction:column;align-items:stretch}
  .navdrop-btn{pointer-events:none;opacity:.55;padding:10px 22px 4px!important;font-size:11px!important;letter-spacing:.12em}
  .navchev{display:none}
  .navdrop-panel{position:static;display:flex;transform:none;box-shadow:none;border-radius:0;border:none;background:transparent;padding:0;gap:0;min-width:0;max-width:none}
  /* drawer rows stay compact: no icon tiles or descriptions, title inherits the drawer's white.
     Re-pin the item colour — the desktop card-panel ink (var(--soft)) is unreadable on the dark drawer. */
  .navdrop-item{padding:11px 32px!important;font-size:13px!important;border-radius:0;color:rgba(255,255,255,.78)}
  .navdrop-item .nd-ic{display:none}
  .navdrop-item .nd-tx small{display:none}
  .navdrop-item .nd-tx b{color:inherit;font-weight:inherit;font-size:inherit}
  .navdrop-item:hover{background:rgba(255,255,255,.06);color:#fff}
  .navdrop-item.on{background:rgba(255,255,255,.08);color:#fff}
  main{padding:0 14px 56px}
  .pagehead{padding-top:22px;margin-bottom:14px}
  .pagehead h1{font-size:25px}
  .pagehead::before{display:none}           /* drop the big door watermark on small screens */
  .pagehead .deck{font-size:14px}
  .row2{flex-direction:column;align-items:stretch;gap:0}
  .modal-card{padding:20px 18px}
  .lrow{flex-wrap:wrap;gap:4px}
  /* My work: drop the date onto its own line instead of floating mid-right next to a tall block */
  .mw-row{flex-wrap:wrap;align-items:flex-start}
  .mw-main{flex:1 1 60%}
  .mw-when{width:100%;text-align:left;margin-top:3px}
  .mw-toh{flex-wrap:wrap}
  .mw-bal{white-space:nowrap}
  .mywork{padding:18px 16px}
  .mywork > .mw-head:first-child{margin:-18px -16px 14px;padding:11px 16px 10px}
  /* timeline: narrow the name column so the schedule grid gets more of the screen, and clamp the
     long title/role line to 2 lines so a verbose title can't make a lane tall on a phone. */
  :root{--namew:172px}
  .nm .r{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  /* timeline: tighten the (now single) toolbar and lift the grid above the fold by moving the
     KPI stat band BELOW the grid — the band's tall stacked tiles were the main thing in the way.
     MUST be scoped to .active: a bare #timeline (ID specificity) overrides .panel{display:none}
     and stacks the resourcing grid under EVERY page on narrow screens. */
  #timeline.active{display:flex;flex-direction:column}
  #timeline>.pagehead{order:0}
  #timeline>.controls{order:1}
  #timeline>.gridcard{order:2}
  #timeline>.hint{order:3}
  #timeline>#statband{order:4;margin:18px 0 0}
  #timeline>.below{order:5}
  .tlbar{gap:8px;margin:14px 0 12px}
  .tldiv{display:none}
  .tlmenu-pop{min-width:200px}
  /* footer: the desktop single row (brand · links · enc-state) crushes on a phone — stack it */
  footer{flex-direction:column;gap:10px;padding:16px 14px 18px;text-align:center;margin-top:28px}
  .footright{flex-wrap:wrap;justify-content:center;gap:10px 16px}
  .encstate{margin-left:0}
}
/* THE SAME DRAWER WHEN THE BAR IS TOO TIGHT FOR ITS NAV, at any width (L-33) — Lemma's twin of the kit's
   html.sk-nav-tight rules, for the bar rules this sheet sets itself (the group labels, the logo, the
   drawer rows' size). suite-kit-navfit.js sets the class; only the BAR is twinned, never the page's
   phone layout. ⚠ Keep these identical to their ≤820px originals above: tests/test_nav_fit_twin.py. */
html.sk-nav-tight .topbar{padding:0 14px;gap:10px}
html.sk-nav-tight .brand-logo{display:flex;align-items:center}
html.sk-nav-tight .brand-text{display:flex;flex-direction:column;align-items:flex-start;line-height:1.15}
html.sk-nav-tight .brand-text .lab-badge{margin-left:0;margin-top:2px}
html.sk-nav-tight .navtoggle{display:block}
html.sk-nav-tight .topnav{position:absolute;top:54px;left:0;right:0;display:none;flex-direction:column;align-items:stretch;
  height:auto;max-height:calc(100dvh - 54px);overflow-y:auto;-webkit-overflow-scrolling:touch;
  gap:0;padding:6px 0;background:var(--nav-ink);box-shadow:0 14px 28px rgba(0,0,0,.28);z-index:60}
html.sk-nav-tight .topnav.open{display:flex}
html.sk-nav-tight .topnav .navbtn{height:auto;justify-content:flex-start;padding:13px 22px;font-size:13px;border-radius:0}
html.sk-nav-tight .topnav .navbtn.on{background:rgba(255,255,255,.08)}
html.sk-nav-tight .navdrop{height:auto;display:flex;flex-direction:column;align-items:stretch}
html.sk-nav-tight .navdrop-btn{pointer-events:none;opacity:.55;padding:10px 22px 4px!important;font-size:11px!important;letter-spacing:.12em}
html.sk-nav-tight .navchev{display:none}
html.sk-nav-tight .navdrop-panel{position:static;display:flex;transform:none;box-shadow:none;border-radius:0;border:none;background:transparent;padding:0;gap:0;min-width:0;max-width:none}
html.sk-nav-tight .navdrop-item{padding:11px 32px!important;font-size:13px!important;border-radius:0;color:rgba(255,255,255,.78)}
html.sk-nav-tight .navdrop-item .nd-ic{display:none}
html.sk-nav-tight .navdrop-item .nd-tx small{display:none}
html.sk-nav-tight .navdrop-item .nd-tx b{color:inherit;font-weight:inherit;font-size:inherit}
html.sk-nav-tight .navdrop-item:hover{background:rgba(255,255,255,.06);color:#fff}
html.sk-nav-tight .navdrop-item.on{background:rgba(255,255,255,.08);color:#fff}
/* phones: one home card per row — two columns clip the titles and the 01/02 index */
@media(max-width:560px){
}

/* ---------------- profile page (a person's consolidated page) ---------------- */
.profpage{max-width:940px;margin:0 auto;padding:6px 2px 48px}
/* a proper, obvious back control (drill-in pages) — a ghost pill with an arrow that nudges on hover */
.backbtn{display:inline-flex;align-items:center;gap:7px;margin-bottom:16px;padding:7px 15px 7px 12px;border-radius:999px;background:rgba(28,34,51,.05);border:1px solid transparent;color:var(--soft);font-size:13px;font-weight:600;cursor:pointer;transition:background .15s,color .15s}
.backbtn:hover{background:rgba(28,34,51,.09);color:var(--navy)}
.backbtn .bk-arrow{font-size:16px;line-height:1;transition:transform .15s}
.backbtn:hover .bk-arrow{transform:translateX(-3px)}
.backbtn:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
html[data-theme=dark] .backbtn{background:rgba(255,255,255,.07)}html[data-theme=dark] .backbtn:hover{background:rgba(255,255,255,.12)}
.profhead{display:flex;gap:18px;align-items:center;margin-bottom:22px}
.profid{flex:1;min-width:0}
.profid h2{margin:0 0 5px;font-size:23px;letter-spacing:-.01em;color:var(--navy)}
.profmeta{color:var(--muted);font-size:14px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.profids{margin-top:7px;display:flex;gap:8px;align-items:center;flex-wrap:wrap;font-size:12.5px}
.profids .idlink{color:var(--soft);text-decoration:none;border-bottom:1px solid transparent}
.profids .idlink:hover{border-bottom-color:currentColor;color:var(--navy)}
.profmeta .dot,.profids .dot{color:var(--rule-blue)}
.profacts{display:flex;gap:8px;flex:0 0 auto;align-self:flex-start}
.orcidmark{display:inline-block;background:#A6CE39;color:#fff;font-weight:700;font-size:9px;border-radius:3px;padding:0 3px;line-height:15px;margin-right:5px;vertical-align:middle}
.pstat{font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;font-weight:700;padding:2px 8px;border-radius:10px;background:var(--panel);color:var(--muted);font-family:var(--mono)}
.pstat.active{background:color-mix(in srgb,var(--green) 14%,#fff);color:var(--green)}
.pstat.incoming,.pstat.on_leave{background:color-mix(in srgb,var(--amber) 16%,#fff);color:#8a5a00}
.pstat.departed{background:var(--panel);color:var(--faint)}
.profgrid{display:grid;grid-template-columns:1.6fr 1fr;gap:16px;align-items:start}
.profcol{display:flex;flex-direction:column;gap:16px;min-width:0}
.profcol-solo{max-width:640px}
.profcard{border:1px solid var(--card-line);border-radius:16px;padding:18px 20px;background:var(--surface);box-shadow:var(--shadow-card)}
.profcard>h3{margin:0 0 12px;font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
/* publications summary heading — match the uppercase card/section headings (home + profile) */
.pubhdr{font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
.pubhdr .lmuted{font-weight:400}
.profcard .lrow:last-child{border-bottom:none}
.profcard .mw-section:first-child{margin-top:0;padding-top:0;border-top:none}
/* calendar-feed card (profile, self): the once-shown secret URL + its actions */
.calfeed-url{display:flex;gap:6px;margin:8px 0 2px}
.calfeed-url input{flex:1;min-width:0;font-family:var(--mono);font-size:11px;color:var(--soft);background:var(--panel);border:1px solid var(--rule);border-radius:8px;padding:6px 8px}
.calfeed-acts{display:flex;gap:6px;margin-top:10px}
/* profile edit card (the inline "Edit" form) */
.profedit{max-width:560px;margin:0 auto;border:1px solid var(--card-line);border-radius:16px;padding:24px 26px;background:var(--surface);box-shadow:var(--shadow-card)}
.profedit-title{margin:0 0 20px;font-size:18px;letter-spacing:-.01em;color:var(--navy)}
.profedit-photo{display:flex;gap:14px;align-items:center;margin-bottom:20px}
.profedit-name{font-weight:700;font-size:15px;color:var(--navy);margin-bottom:7px}
.profedit-photobtns{display:flex;gap:8px}
.profedit-fields{display:flex;flex-direction:column;gap:14px}
.profedit-fields .row2{margin:0}
.profedit-fields .row2 label{display:block;font-weight:600;font-size:10px;text-transform:uppercase;letter-spacing:.07em;color:var(--faint);margin:0 0 5px}
/* label.pfcheck (not bare .pfcheck) so it ties .modal-card label's specificity and wins by source
   order — checkbox rows must escape the uppercase field-label treatment wherever they appear */
label.pfcheck{display:flex;align-items:center;gap:8px;font-weight:400;font-size:13px;color:var(--soft);cursor:pointer;text-transform:none;letter-spacing:0}
label.pfcheck .lmuted{font-style:normal}
/* height too, not just width: .modal-card input sets height:41px for text fields, and a checkbox that
   inherits it is 13px wide by 41px tall — it drags the row's height and floats off its own label. */
.pfcheck input{width:auto;height:auto;margin:0;accent-color:var(--navy)}
/* Settings page (account menu → Settings) — cards for personal prefs + org config */
/* masonry columns — cards of very different heights flow to fill gaps (no short-card-beside-tall-card dead space) */
.settings-page .setgrid{columns:2;column-gap:16px;margin-top:10px}
.settings-page .setgrid>.profcard{break-inside:avoid;-webkit-column-break-inside:avoid;width:100%;margin:0 0 16px}
@media(max-width:760px){.settings-page .setgrid{columns:1}}
.set-hint{font-size:12.5px;color:var(--muted);margin:0 0 12px;line-height:1.5}
.set-sub{font-weight:600;color:var(--faint);font-size:10px;text-transform:uppercase;letter-spacing:.08em;margin:16px 0 4px}
.set-actions{display:flex;justify-content:flex-end;margin-top:14px}
.set-btns{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}
/* org logo on exported PDFs — preview sits on a navy swatch that mimics the PDF header band */
.logo-row{display:flex;gap:16px;align-items:center;flex-wrap:wrap}
.logo-preview{flex:0 0 auto;width:190px;height:60px;border-radius:10px;background:var(--navy,#152D49);display:flex;align-items:center;justify-content:center;padding:8px 14px;box-shadow:inset 0 0 0 1px var(--rule,#E7ECF3)}
.logo-preview img{max-width:100%;max-height:100%;object-fit:contain;display:block}
.logo-preview .lmuted{color:#fff;font-weight:700;font-size:20px;opacity:.92}
label.pfcheck.setrow{align-items:flex-start;gap:10px;padding:7px 2px}
label.pfcheck.setrow input{margin-top:2px;flex:0 0 auto}
label.pfcheck.setrow>span{display:flex;flex-direction:column;min-width:0;gap:1px}
label.pfcheck.setrow>span b{color:var(--navy);font-size:13.5px;font-weight:600}
label.pfcheck.setrow>span .lmuted{font-size:12px}
@media(max-width:720px){.profgrid{grid-template-columns:1fr}.profhead{flex-wrap:wrap}.profacts{width:100%}}

/* ============================== dark mode ("dark lab") ==============================
   Real tokens, not a filter: [data-theme=dark] re-maps the surface + ink layer while
   --brand keeps each edition's hue for the chrome (topbar, hero, avatars, KPI tiles).
   The accent (--red) is brightened via color-mix so buttons and links keep contrast on
   dark panels — it tracks the org's brand automatically. Set from Settings → Appearance
   (person.ui_prefs.theme), mirrored to localStorage so first paint is already dark. */
html[data-theme=dark]{
  color-scheme:dark;
  --bg:#13151C; --surface:#1B1E28; --surface-2:#171A22; --field:#232734;
  /* --card is used 28 times as `var(--card,#fff)` and was never actually DEFINED anywhere, so every
     one of those fell through to the literal white — invisible in the light theme, and a glaring
     white slab in this one (most obviously the item rows in a meeting editor). Define it per theme
     and all 28 come right at once. */
  --card:#1B1E28; --ink-2:#9FB2CC; --ink-3:#7D8A9E;
  --danger:color-mix(in srgb,#E72D3F 45%,#FF9FC4);   /* the Company's dark --red, in both editions */
  --card-line:rgba(255,255,255,.055);
  --modal-veil:rgba(0,0,0,.6);
  --shadow-card:0 1px 2px rgba(0,0,0,.3),0 8px 28px rgba(0,0,0,.35);
  --shadow-card-hover:0 4px 10px rgba(0,0,0,.35),0 18px 44px rgba(0,0,0,.5);
  --brass:#CDA55C; --brass-2:#DEBC7E;   /* brass lifts in dark so it reads on the darker grounds */
  /* Chrome stays BRAND-TINTED in dark (reverted 2026-07-26 — it was neutral #101219 on the argument
     that a tinted bar fights the blue-grey canvas). The topbar, the mobile bottom bar and the footer
     all derive from --nav-ink, so they move together and keep reading as one block. Deliberately NOT
     a hard-coded navy: --nav-ink falls back to the kit's `color-mix(--brand 72%, #000)`, so the Lab
     edition keeps its plum chrome instead of being forced to Company navy. */
  --panel:#20242F; --rule:#2A2E3B; --rule-blue:#343A4C;
  --grid-line:#20242F; --holiday:#1D202B;
  --ink:#E8EAF2; --navy:#E8EAF2; --navy-soft:#C9CEDD; --soft:#C4CADA;
  --muted:#98A0B4; --faint:#7C8499; --ghost:#5C6376;
  --blue-soft:#232B3D; --blue-panel:#2A3348;
  --u0:#262B38;
  --red:color-mix(in srgb,var(--rda-red,#E72D3F) 45%,#FF9FC4);
  --red-dark:color-mix(in srgb,var(--rda-red,#E72D3F) 62%,#FF9FC4);
  --accent-tint:rgba(255,255,255,.07);
}
/* scrollbars: nested scrollers don't reliably pick up color-scheme, so style them —
   transparent tracks kill the phantom light bars on modals/grids, slim dark thumbs */
html[data-theme=dark]{scrollbar-color:#3A4052 transparent}
html[data-theme=dark] ::-webkit-scrollbar{width:10px;height:10px;background:transparent}
html[data-theme=dark] ::-webkit-scrollbar-track{background:transparent}
html[data-theme=dark] ::-webkit-scrollbar-corner{background:transparent}
html[data-theme=dark] ::-webkit-scrollbar-thumb{background:#333949;border-radius:8px;border:2px solid transparent;background-clip:padding-box}
html[data-theme=dark] ::-webkit-scrollbar-thumb:hover{background:#414A5E;background-clip:padding-box}
/* quiet ghost controls invert their tint */
html[data-theme=dark] .btn-ghost{background:rgba(255,255,255,.07)}
html[data-theme=dark] .btn-ghost:hover{background:rgba(255,255,255,.12);color:var(--ink)}
html[data-theme=dark] .wknav button{background:rgba(255,255,255,.07)}
html[data-theme=dark] .wknav button:hover{background:rgba(255,255,255,.12)}
html[data-theme=dark] .jbtn{background:rgba(255,255,255,.06)}
html[data-theme=dark] .lrow:hover{background:rgba(255,255,255,.04)}
html[data-theme=dark] .loadveil{background:rgba(19,21,28,.65)}
/* timeline overlays: hatch patterns rebuilt from dark greys */
html[data-theme=dark] .unavail{background:repeating-linear-gradient(135deg,#1A1D27,#1A1D27 5px,#20242F 5px,#20242F 10px)}
html[data-theme=dark] .unavail.holiday{background:repeating-linear-gradient(135deg,#191C26,#191C26 5px,#1D202B 5px,#1D202B 10px)}
html[data-theme=dark] .unavail.notyet{background:repeating-linear-gradient(135deg,#161923,#161923 6px,#13151C 6px,#13151C 12px)}
html[data-theme=dark] .sw.hatch{background:repeating-linear-gradient(135deg,#252938,#252938 3px,#1D2029 3px,#1D2029 6px)}
/* (the dark empty-state glyph is the KIT's now — it covers .empty-mini too, which this didn't) */
/* amber accents need a lighter shade on dark panels */
html[data-theme=dark] .topend h4,html[data-theme=dark] #scenBanner .scn b,
html[data-theme=dark] .gp-meta .warn,html[data-theme=dark] .gchip.under,
html[data-theme=dark] .gscentag,html[data-theme=dark] .pill.amber,
html[data-theme=dark] .tag.amber,html[data-theme=dark] .lvstat.requested,
html[data-theme=dark] .rad-row.soon .rad-date,html[data-theme=dark] .rad-row.soon .rad-when,
html[data-theme=dark] .ap-when.soon,html[data-theme=dark] .apill.under_review,
html[data-theme=dark] .thrs.over{color:#E2B564}
html[data-theme=dark] #scenBanner{background:rgba(233,162,59,.1);border-color:rgba(233,162,59,.3)}
html[data-theme=dark] .docstat.wip{background:#2A3348;color:var(--ink)}
html[data-theme=dark] .prop-backdrop .prop-over{color:#FF8F8F}
html[data-theme=dark] .pill.green,html[data-theme=dark] .lvstat.approved{color:#5ED4A9}
/* the pre-login gate keeps its light card on the brand backdrop — pin the light ink scale inside */
html[data-theme=dark] .gate-card{color-scheme:light;
  --ink:#152D49;--navy:#152D49;--soft:#2C4360;--muted:#5A6A82;--faint:#7D8A9E;--ghost:#A7AFBE;
  --rule:#E7ECF3;--rule-blue:#C8D2E3;--field:#fff;--panel:#F6F8FC;--blue-soft:#ECF0F7}

/* ============================== project delivery layer (board · workspace) ============================== */
/* Portfolio health board */
.board{display:flex;gap:14px;overflow-x:auto;padding:6px 2px 14px}
.bcol{flex:0 0 300px;background:var(--panel);border-radius:14px;padding:10px 10px 12px;display:flex;flex-direction:column;min-height:120px}
.bcol-head{display:flex;align-items:center;gap:8px;padding:4px 6px 10px}
/* A status nobody is in still gets a column — it answers the question and it is the drop target
   for moving a project INTO that status. Muted so an empty one never competes with a full one. */
.bcol-empty{opacity:.62}
.bcol-empty .bcol-head h3{color:var(--ghost)}
.bcol-empty .bcol-none{padding:10px 6px;font-size:11.5px;color:var(--ghost)}
.bcol-empty.dropok{opacity:1}
.bcol-head::before{content:"";width:8px;height:8px;border-radius:50%;background:var(--acc,var(--blue))}
.bcol-head h3{margin:0;flex:1;font-size:10.5px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--faint)}
.bcol-head .count{font-family:var(--mono);font-size:11px;color:var(--muted);background:var(--surface);border-radius:999px;padding:1px 8px}
.bcol-body{display:flex;flex-direction:column;gap:10px;overflow-y:auto;min-height:24px}
.bcard{background:var(--surface);border-radius:12px;padding:12px 13px;box-shadow:var(--shadow-card);border-left:3px solid var(--blue);cursor:pointer;transition:transform .15s,box-shadow .15s}
.bcard:hover{transform:translateY(-2px);box-shadow:var(--shadow-card-hover)}
.bc-top{display:flex;align-items:center;gap:10px}
.bc-top h4{margin:0;font-size:14px;font-weight:600;color:var(--navy);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bc-h{min-width:0}
.bc-meta{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--faint);margin-top:2px}
.bc-meta span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bc-next{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:9px 0 2px;font-size:12px;color:var(--soft)}
.bc-next .nt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bc-foot{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:8px;min-height:20px}
.bc-badges{display:flex;gap:5px;flex-wrap:wrap}
.pring{display:block;flex:0 0 auto}
.hdot{display:inline-block;width:8px;height:8px;border-radius:50%;flex:0 0 auto}
/* health pill */
.hpill{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;padding:3px 10px;border-radius:999px;background:var(--blue-soft);color:var(--navy-soft)}
.hpill.h-green{background:color-mix(in srgb,var(--green) 14%,transparent);color:var(--green)}
.hpill.h-amber{background:color-mix(in srgb,var(--amber) 18%,transparent);color:#8a5a12}
.hpill.h-red{background:color-mix(in srgb,var(--red) 12%,transparent);color:var(--red-dark)}
.hpill.h-on_hold,.hpill.h-none{background:var(--panel);color:var(--muted)}
/* avatar stack */
.avstack{display:inline-flex;flex-direction:row-reverse;align-items:center}
.avstack .av{margin-right:-9px;box-shadow:0 0 0 2px var(--surface)}
.avstack .av:first-child{margin-right:0}
.av-more{width:24px;height:24px;flex:0 0 24px;border-radius:50%;background:var(--u0);color:var(--muted);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:600;box-shadow:0 0 0 2px var(--surface);margin-right:-9px}
/* phase stepper */
.stepper{display:flex;list-style:none;margin:4px 0 2px;padding:0}
.step{flex:1;position:relative;display:flex;flex-direction:column;align-items:center;text-align:center;padding:0 4px}
.step::before{content:"";position:absolute;top:11px;left:-50%;width:100%;height:2px;background:var(--rule-blue);z-index:0}
.step:first-child::before{display:none}
.step.done::before,.step.cur::before{background:var(--green)}
.step .dot{position:relative;z-index:1;width:24px;height:24px;border-radius:50%;background:var(--surface);border:2px solid var(--rule-blue);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;color:var(--faint)}
.step.done .dot{background:var(--green);border-color:var(--green);color:#fff}
.step.cur .dot{border-color:var(--brand);color:var(--brand);box-shadow:0 0 0 4px color-mix(in srgb,var(--brand) 14%,transparent)}
.step.over .dot{border-color:var(--red);color:var(--red)}
.step .slabel{font-size:11.5px;font-weight:600;color:var(--navy);margin-top:7px}
.step .sdate{font-size:10.5px;color:var(--faint);margin-top:1px}
/* checkpoint rows */
/* ⚠ THREE columns, and the reorder handles share the first with the type badge (`.clead`). Adding
   `.ord` as a fourth child pushed the Sign off / Mark done button onto its own line — the same
   mistake the task row had, fixed there and missed here. */
.crow{display:grid;grid-template-columns:100px minmax(0,1fr) auto;align-items:center;column-gap:10px;padding:9px 4px;border-bottom:1px solid var(--rule)}
.crow:last-child{border-bottom:none}
.cr-main{display:flex;align-items:center;gap:8px;min-width:0}
.cr-right{display:flex;align-items:center;gap:8px;justify-content:flex-end}   /* when · action · edit — right-aligned cluster */
.cr-title{font-size:13.5px;color:var(--navy);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.crow.done .cr-title{color:var(--muted)}
.mtype{font-size:8.5px;text-transform:uppercase;letter-spacing:.09em;font-weight:600;padding:3px 9px;border-radius:999px;background:color-mix(in srgb,var(--navy-soft) 9%,transparent);color:var(--navy-soft);flex:0 0 auto;line-height:1;justify-self:start}
.mtype.mt-deliverable{background:color-mix(in srgb,var(--brand) 9%,transparent);color:var(--brand)}
.mtype.mt-gate{background:color-mix(in srgb,var(--amber) 15%,transparent);color:#8a5a12}
.mtype.mt-report{background:var(--panel);color:var(--muted)}
.signoff-chip{font-size:11px;font-weight:600;color:var(--green);white-space:nowrap}
/* billing trigger: a chargeable checkpoint (company). muted = billable, green = accepted → ready to invoice */
.bill-chip{font-size:10px;font-weight:600;letter-spacing:.02em;padding:3px 8px;border-radius:999px;background:color-mix(in srgb,var(--navy-soft) 8%,transparent);color:var(--muted);white-space:nowrap;flex:0 0 auto;line-height:1}
.bill-chip.ready{background:color-mix(in srgb,var(--green) 14%,transparent);color:color-mix(in srgb,var(--green) 72%,#0a3a24)}
html[data-theme=dark] .bill-chip.ready{color:var(--green)}
.cr-edit{background:none;border:none;color:var(--faint);cursor:pointer;font-size:12px;padding:2px 5px;border-radius:6px;opacity:0;transition:opacity .12s,color .12s;flex:0 0 auto}
.crow:hover .cr-edit{opacity:1}
.cr-edit:hover{color:var(--brand);background:color-mix(in srgb,var(--brand) 8%,transparent)}
.tag.bill{background:color-mix(in srgb,var(--green) 14%,transparent);color:color-mix(in srgb,var(--green) 70%,#0a3a24)}
html[data-theme=dark] .tag.bill{color:var(--green)}
.pf-stat.bill b{color:color-mix(in srgb,var(--green) 72%,#0a3a24)}
html[data-theme=dark] .pf-stat.bill b{color:var(--green)}
.pf-stat.bill .pf-amt{font-size:13px;font-weight:600}
.cp-bill{margin-top:4px;padding-top:12px;border-top:1px solid var(--rule)}
/* Deliverable file: the picker is a kit button wrapping a hidden input — clicking the label opens the
   native dialog, so nothing here reimplements file selection, it only stops it looking foreign. */
/* Full-width and centred on purpose, matching the stacked chips above it (evidence, billable) rather
   than sitting as a lone shrink-wrapped button in a column of full-width controls. */
.cpf-pick{display:block;text-align:center;cursor:pointer}
/* Vouching for a reference — one dialog, shared by the checker and the library. */
.rv-card{width:min(520px,94vw)}
/* --panel, not a literal: it is redefined for dark mode, and a hardcoded pale fill would have
   stayed pale there with --navy text on top of it. */
.rv-card .rv-ref{font-weight:600;color:var(--navy);line-height:1.4;margin:10px 0 2px;
  padding:9px 11px;border:1px solid var(--rule);border-radius:9px;background:var(--panel)}
.rv-card .rv-warn{margin:4px 0 0;color:var(--red,#870052)}
/* Who vouched, under the reference it answers for — a vouch is somebody's name against a work, so
   the name travels with it rather than living only in the audit log. */
.rl-att{font-size:12px;margin-top:3px;font-style:italic}
/* Earlier status updates, under the current one. Muted so the newest stays the subject of the card. */
.upd-hist{margin-top:10px}
.upd-hist>summary{cursor:pointer;font-size:12px;color:var(--muted);padding:2px 0;list-style:none}
.upd-hist>summary::-webkit-details-marker{display:none}
.upd-hist>summary::before{content:'▸ ';color:var(--faint)}
.upd-hist[open]>summary::before{content:'▾ '}
.upd-hist>summary:hover{color:var(--navy)}
.upd-card.upd-old{opacity:.78;margin-top:8px}
.cpf-pick.is-busy{pointer-events:none;opacity:.65}
/* The attached file, shaped like the evidence rows above it — one row, name taking the slack and
   ellipsised rather than wrapping into a two-character column when the filename is long. */
.cpf-row{display:flex;align-items:center;gap:10px;margin-top:6px;padding:8px 11px;
  border:1px solid var(--rule);border-radius:8px;background:var(--surface-2)}
.cpf-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:12.5px;font-weight:600;text-decoration:none;color:var(--rda-blue)}
.cpf-name:hover{text-decoration:underline}
.cpf-size{flex:none;font-size:11px;color:var(--muted)}
/* Rides label.pfcheck for the escape from .modal-card label's uppercase field treatment (that class
   exists for exactly this); label.cpf-share ties its specificity to trim the size for a compact row. */
label.cpf-share{flex:none;gap:6px;white-space:nowrap;font-size:11.5px;color:var(--muted)}

/* L2 evidence gate. Two classes of row, laid out identically on purpose: ATTACHED evidence is solid
   and filled (a record), work merely UNDER WAY is dashed and hollow (a promise). Same shape, so the
   only thing that reads as different is the thing that IS different. */
.cp-evlist{margin-top:8px;display:flex;flex-direction:column;gap:6px}
.cp-item{padding:8px 11px;border:1px solid var(--rule);border-radius:8px;background:var(--surface-2)}
.cp-item.cp-wip{border-style:dashed;background:none}
.cp-item-h{display:flex;align-items:center;gap:8px;font-size:12.5px;min-width:0}
.cp-item-h b,.cp-item-h code{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cp-item-h code{font-size:11.5px;color:var(--muted)}
.cp-item-h a{flex:none;font-size:11.5px;font-weight:600;text-decoration:none;color:var(--rda-blue)}
.cp-item-h a:hover{text-decoration:underline}
.cp-item-m{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin-top:5px;font-size:11px;color:var(--muted)}
.cp-mark{width:8px;height:8px;border-radius:50%;flex:none;background:var(--rda-blue)}
.cp-mark.wip{background:none;border:2px solid var(--brass)}
.cp-chip{text-transform:uppercase;letter-spacing:.05em;font-size:9.5px;font-weight:700;padding:2px 6px;
  border-radius:4px;background:color-mix(in srgb,var(--muted) 15%,transparent)}
.cp-app{text-transform:capitalize}       /* apps arrive as machine keys: "theorem" → "Theorem" */
.cp-stage{font-size:10.5px;font-weight:600;padding:2px 8px;border-radius:999px}
.cp-stage.wk-att{background:color-mix(in srgb,var(--green) 16%,transparent);color:color-mix(in srgb,var(--green) 72%,#0a3a24)}
html[data-theme=dark] .cp-stage.wk-att{color:var(--green)}
.cp-stage.wk-draft{background:color-mix(in srgb,var(--muted) 15%,transparent)}
.cp-stage.wk-rev{background:color-mix(in srgb,var(--brass) 20%,transparent);color:var(--brass-2)}
.cp-stage.wk-done{background:color-mix(in srgb,var(--rda-blue) 14%,transparent);color:var(--rda-blue)}
.cp-evnote,.cp-evempty{font-size:11.5px;line-height:1.45;color:var(--muted)}
.cp-evempty{margin-top:6px}
.cp-evstart{margin-top:8px;display:flex;flex-wrap:wrap;gap:8px}
.cp-evstart a{font-size:12px;font-weight:600;text-decoration:none;padding:6px 11px;border:1px solid var(--rule);border-radius:999px;color:var(--rda-blue)}
.cp-evstart a:hover{background:color-mix(in srgb,var(--rda-blue) 8%,transparent)}
/* task rows */
/* ⚠ STILL THREE COLUMNS. The reorder handles share the first one with the checkbox (`.tlead`)
   rather than becoming a fourth child — the three-column rule is what stopped every row sizing its
   own grid and landing the avatars, hours and buttons at a different x on every line. */
.trow{display:grid;grid-template-columns:38px minmax(0,1fr) auto;align-items:center;gap:12px;padding:9px 4px;border-bottom:1px solid var(--rule);cursor:pointer}
/* the right-hand cluster: FIXED-width slots, always present, so avatars / hours / buttons / date / status
   line up down the list. Widths (not `auto`) because each row is its own grid container — `auto` sizes
   to that row's own content, which is what made the list ragged. */
.tright{display:flex;align-items:center;gap:8px;justify-content:flex-end}
.tright > span{flex:0 0 auto;display:flex;align-items:center;justify-content:flex-end;min-width:0;overflow:hidden}
/* ⚠ Sized for the WIDEST thing each slot holds, because a slot clips (overflow:hidden) from the left
   (flex-end): at 66px the hours chip showed "n/12h 30m" — the logged figure itself cut off — once it
   read "3h 15m/12h 30m" instead of "3.25h/12.5h"; "41h 30m/37h 45m" is 114px. Three avatars are 72px,
   "5d overdue" 81px. */
.t-av{width:76px}
.t-hrs{width:120px}
.t-act{width:118px;gap:6px}
.t-when{width:88px}
.t-st{width:88px}
.t-av .lmuted{padding-right:2px}   /* the italic "Unassigned" overhangs its box; the slot clipped its "d" */
.t-when .ap-when,.t-st .pill{white-space:nowrap}
.tright{min-height:30px}
/* progress meetings: draft → submitted → approved */
.ooo-state{font-size:11.5px;font-weight:600;border-radius:8px;padding:5px 9px;margin:0 0 8px}
.ooo-state.draft{background:var(--blue-soft,#EEF2F9);color:var(--ink-2,#3D5A85)}
.ooo-state.sub{background:rgba(233,162,59,.16);color:#8A5E0F}
.ooo-state.ok{background:rgba(46,139,87,.13);color:#1F6B44}
.ooo-revbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12.5px;color:var(--navy);background:var(--blue-soft,#EEF2F9);border-radius:10px;padding:9px 11px;margin-top:10px}
.ooo-drow{display:grid;grid-template-columns:1fr auto;gap:6px;padding:7px 0;border-bottom:1px solid var(--rule,#E7ECF3)}
.ooo-drow textarea{grid-column:1/-1;width:100%;font-size:12.5px;resize:vertical}
/* management meetings: the category chip, the filter strip, the to-do control and the comparison */
.mtg-cat{display:inline-block;font-size:10px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-2,#3D5A85);background:var(--blue-soft,#EEF2F9);border-radius:20px;padding:2px 8px;margin-right:8px;vertical-align:middle}
.mgmt-filter{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 12px}
.fchip{border:1px solid var(--rule-blue,#C8D2E3);background:var(--surface);color:var(--soft);font-size:11.5px;font-weight:600;padding:3px 11px;border-radius:999px;cursor:pointer}
.fchip:hover{border-color:var(--brand)}
.fchip.on{background:var(--navy);border-color:var(--navy);color:#fff}
/* The per-item "done" tick had no rule of its own, so .modal-card's block-label treatment applied
   and the box stacked on top of its word in a 31px column. Same shape as .mtg-todo beside it. */
.mtg-done{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--soft);white-space:nowrap;cursor:pointer;flex:0 0 auto;text-transform:none;letter-spacing:0;font-weight:400;margin:0}
.mtg-done input{margin:0;flex:0 0 auto}
.mtg-todo{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--soft);white-space:nowrap;cursor:pointer}
.mtg-todo input{margin:0}
.mtg-todo.has{background:var(--blue-soft,#EEF2F9);color:var(--ink-2,#3D5A85);border-radius:20px;padding:2px 9px;font-weight:600;cursor:default}
.mtg-todo.has.ok{background:rgba(46,139,87,.14);color:#1F6B44}
.mdiff-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px 20px;margin-top:6px}
.mdiff-rows{display:flex;flex-direction:column;gap:5px}
.mdiff-row{display:flex;gap:8px;align-items:flex-start;font-size:12.5px;color:var(--navy);line-height:1.35}
.mdiff-dot{width:7px;height:7px;border-radius:50%;flex:0 0 auto;margin-top:5px;background:var(--rule-blue,#C8D2E3)}
.mdiff-row.ok .mdiff-dot{background:var(--green,#2E8B57)}
.mdiff-row.open .mdiff-dot{background:var(--amber,#E9A23B)}
.mdiff-row.new .mdiff-dot{background:var(--blue,#6F97D8)}
.mdiff-row.dec .mdiff-dot{background:var(--navy)}
.mdiff-sums{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:16px}
/* pre-wrap is gone: the summary is rendered into real paragraphs and lists now, and pre-wrap on
   top of that would double every blank line. */
.mdiff-sum{font-size:12.5px;color:var(--soft);line-height:1.5}
@media(max-width:640px){.mdiff-grid,.mdiff-sums{grid-template-columns:1fr}}
/* the log-time dialog's optional task picker + the admin-only billable row */
.tt-bill{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--navy);cursor:pointer}
.tt-bill input{margin:0}   /* the sm avatar's height — so a row without one is the same height as a row with */
@media(max-width:900px){.t-av,.t-hrs,.t-when,.t-st{width:auto}.t-act{width:auto}}
/* ⚠ A PHONE HAS NO ROOM FOR THE CLUSTER BESIDE THE NAME. The `auto` third column took the cluster's
   whole width — avatars, "41h 30m/37h 45m", + Time, → Book, the date, the status: ~450px at 390 —
   squeezed the name to nothing and pushed the row, and the page with it, past the screen's edge.
   On a phone the cluster is a second line under the name: left-aligned, wrapping, and the slots
   with nothing to say collapse so their gaps do not leave holes. */
@media(max-width:640px){
  .trow{grid-template-columns:38px minmax(0,1fr);row-gap:6px}
  .tright{grid-column:2;justify-content:flex-start;flex-wrap:wrap;row-gap:6px;min-height:0}
  .tright > span:empty{display:none}
}
.trow:last-child{border-bottom:none}
.trow:hover{background:color-mix(in srgb,var(--brand) 3%,transparent)}
/* "Book" — turn a task estimate into a capacity booking (confirm-don't-construct) */
.tbook{border:1px solid var(--rule-blue,#C8D2E3);background:var(--surface);color:var(--soft);font-size:10.5px;font-weight:700;letter-spacing:.02em;padding:2px 8px;border-radius:999px;cursor:pointer;white-space:nowrap}

/* Logged-vs-estimated on a task row. Amber past the estimate, never red: overrunning an estimate is
   information, and this row already spends red on dates that have actually slipped. */
.thrs{font-size:11px;font-weight:600;color:var(--ink-2,#3D5A85);background:var(--blue-soft,#EEF2F9);border-radius:20px;padding:2px 8px;white-space:nowrap;flex:0 0 auto}
.thrs.over{background:rgba(233,162,59,.16);color:#8A5E0F}
.tbook:hover{background:color-mix(in srgb,var(--brand) 9%,var(--surface));border-color:var(--brand)}
.tcheck{width:18px;height:18px;border-radius:6px;border:1.5px solid var(--rule-blue);background:var(--surface);cursor:pointer;position:relative;flex:0 0 auto}
.trow.done .tcheck{background:var(--green);border-color:var(--green)}
.trow.done .tcheck::after{content:"✓";color:#fff;font-size:12px;position:absolute;inset:0;display:flex;align-items:center;justify-content:center;animation:tpop .18s ease}
@keyframes tpop{from{transform:scale(.5);opacity:0}to{transform:scale(1);opacity:1}}
.tmain{min-width:0;display:flex;flex-direction:column}
.tt{font-size:13.5px;color:var(--navy);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.trow.done .tt{text-decoration:line-through;color:var(--muted)}
.tlink{font-size:10.5px;color:var(--faint)}
/* "not done because" — the second line under a blocked/cancelled task's title. Amber, matching the
   `blocked` pill on the same row; clamped to one line because a paragraph here would make the list
   ragged and the whole text is in the tooltip. */
.twhy{font-size:11px;color:var(--amber);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:1px}
/* rebalance panel: a week strip that states a figure per week (never one average across the run),
   then the moves as ticked rows so a planner drops the ones they disagree with */
.rb-card{width:min(620px,94vw)}
.rb-lead{font-weight:600;color:var(--navy);margin:2px 0 10px}
.rb-strip{display:flex;gap:4px;margin:6px 0 12px;overflow-x:auto}
.rb-wk{flex:1 0 62px;border:1px solid var(--rule,#E7ECF3);border-radius:6px;padding:5px 6px;
  display:flex;flex-direction:column;gap:1px;background:var(--surface)}
.rb-wk .rb-lbl{font-size:9.5px;letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}
.rb-wk .rb-util{font-family:var(--mono);font-size:13px;font-weight:700;color:var(--navy)}
.rb-wk .rb-over{font-family:var(--mono);font-size:10px;color:var(--red);min-height:12px}
.rb-wk.rb-hot{border-color:var(--red);background:color-mix(in srgb,var(--red) 6%,transparent)}
.rb-wk.rb-un{opacity:.45}
.todo-der{display:inline-flex;align-items:center;justify-content:center;opacity:.5}
/* A seven-column table cannot live in half a page. The other deep cards are charts and lists that
   read fine at 1fr; this one spans the grid so the numeric columns keep their own line. */
#peopleCostCard{grid-column:1 / -1}
.fin-drift{display:inline-block;margin-left:9px;font-size:11.5px;font-family:var(--mono);
  color:var(--amber);white-space:nowrap}
.ec-band{margin:2px 0 14px}
.ec-name{display:block}
.ec-title{display:block;font-size:11.5px;color:var(--muted);margin-top:1px}
.ec-note{font-size:12px;color:var(--amber);margin:0 0 10px}
.ec-table{width:100%;border-collapse:collapse;font-size:13px}
.ec-table th{text-align:left;font-size:10px;letter-spacing:.05em;text-transform:uppercase;
  color:var(--muted);font-weight:600;padding:0 8px 6px;border-bottom:1px solid var(--rule,#E7ECF3)}
.ec-table td{padding:7px 8px;border-bottom:1px solid var(--rule,#E7ECF3)}
.ec-table .num{text-align:right;font-family:var(--mono);font-variant-numeric:tabular-nums}
.ec-table tr:last-child td{border-bottom:0}
.ec-basis{font-size:10.5px;letter-spacing:.03em;text-transform:uppercase;padding:2px 6px;border-radius:4px;
  background:color-mix(in srgb,var(--navy) 7%,transparent);color:var(--muted)}
.ec-unpriced td{opacity:.62}
.ec-unpriced .ec-basis{background:color-mix(in srgb,var(--amber) 16%,transparent);color:var(--amber)}
.ec-foot{font-size:11.5px;color:var(--muted);margin:10px 0 0}
.rb-who{display:flex;flex-wrap:wrap;gap:5px;margin:0 0 10px}
.rb-chip{font:inherit;font-size:12px;line-height:1;padding:5px 9px;border-radius:999px;
  border:1px solid var(--rule,#E7ECF3);background:var(--surface,#fff);color:var(--muted);cursor:pointer}
.rb-chip:hover{border-color:var(--navy);color:var(--navy)}
.rb-chip.on{background:var(--navy);border-color:var(--navy);color:#fff;cursor:default;font-weight:600}
.rb-tasks{font-size:12px;color:var(--amber);margin:0 0 10px}
.rb-moves{display:flex;flex-direction:column;gap:6px;margin-bottom:10px}
.rb-move{display:flex;gap:9px;align-items:flex-start;border:1px solid var(--rule,#E7ECF3);
  border-radius:8px;padding:8px 10px;font-size:12.5px;cursor:pointer}
.rb-move:hover{background:var(--surface)}
.rb-change{font-family:var(--mono);font-weight:700;color:var(--navy)}
.rb-affects{font-size:11px;color:var(--muted)}
.rb-after{font-size:12.5px;color:var(--navy);font-weight:600;margin:0 0 4px}
.rb-none{font-size:12.5px;color:var(--muted)}
/* reorder handles on a plan/task row — quiet until the row is hovered, so a list you are reading
   does not look like a control panel */
.tlead{display:flex;align-items:center;gap:2px;min-width:0}
.ord{display:inline-flex;flex-direction:column;gap:1px;opacity:0;transition:opacity .12s}
.clead{display:flex;align-items:center;gap:4px;min-width:0}
.crow .ord{margin-right:0}
.crow:hover .ord,.trow:hover .ord,.ord:focus-within{opacity:1}
.ordbtn{border:0;background:transparent;color:var(--muted);font-size:8px;line-height:1;padding:1px 2px;cursor:pointer}
.ordbtn:hover{color:var(--navy)}
/* where you were: the row you just signed off or ticked, so a repaint does not lose your place */
@keyframes rowtouch{from{background:color-mix(in srgb,var(--brand) 14%,transparent)}to{background:transparent}}
.row-touched{animation:rowtouch 1.2s ease-out}
/* "Will not apply" — the scenario diff's refusals, above the three change sections rather than
   among them: these rows are what the commit WON'T do, and reading them as changes is the defect */
.rb-willnot{border:1px solid var(--red);border-radius:8px;padding:8px 10px;margin-bottom:10px;
  background:color-mix(in srgb,var(--red) 5%,transparent)}
.rb-willnot h4{margin:0 0 2px}
.trow.done .twhy{color:var(--muted)}
/* workspace header + overview */
.ah-title{flex:1;min-width:0}
.ah-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.projbody{margin-top:6px}
.pc-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:2px}
.pc-head h3{white-space:nowrap}
.upd-card{border:1px solid var(--rule);border-radius:10px;padding:12px 14px;margin-top:8px;background:var(--panel)}
.upd-top{display:flex;align-items:center;justify-content:space-between;gap:8px}
.upd-by{font-size:11px;color:var(--faint)}
.upd-reason{font-size:12.5px;color:var(--navy);font-weight:600;margin-top:8px}
.upd-body{font-size:13px;color:var(--soft);margin:6px 0 0;white-space:pre-wrap}
.sug-hint{font-size:11.5px;color:var(--muted);background:var(--panel);border-radius:8px;padding:8px 10px;margin-top:10px;display:flex;gap:6px;align-items:baseline}
.radlist{margin-top:6px}
.rad-sub{font-size:10.5px;color:var(--faint)}
/* activity feed */
.feed{margin-top:6px}
.feed-row{display:flex;gap:10px;padding:7px 0}
.feed-dot{width:8px;height:8px;border-radius:50%;background:var(--rule-blue);margin-top:5px;flex:0 0 auto}
.feed-dot.ok{background:var(--green)}.feed-dot.bad{background:var(--red)}
.feed-body{font-size:12.5px;color:var(--soft)}
.feed-body b{color:var(--navy)}
.feed-when{display:block;font-size:10.5px;color:var(--faint);margin-top:1px}
/* modals: form labels, assignee chips, RAG picker, template list */
.fl{display:block;font-size:11px;font-weight:600;color:var(--soft);margin:10px 0 4px}
.asg-grid{display:flex;flex-wrap:wrap;gap:6px;max-height:170px;overflow:auto}
.asg-chip{display:inline-flex;align-items:center;gap:5px;font-size:12px;padding:5px 9px;border-radius:999px;border:1px solid var(--rule-blue);cursor:pointer;color:var(--soft)}
.asg-chip.on{background:var(--brand);color:#fff;border-color:var(--brand)}
.asg-chip input{display:none}
/* A former colleague, on the two pickers that record what HAPPENED. Dashed rather than a second
   colour: the chip still has to read as selectable, and .on already owns the filled brand state. */
.asg-former{border-style:dashed;opacity:.85}
.asg-former.on{opacity:1}
.asg-more{display:inline-block;margin-top:6px;width:100%}
.asg-more>summary{font-size:12px;color:var(--soft);cursor:pointer;list-style:none;padding:4px 0}
.asg-more>summary::-webkit-details-marker{display:none}
.asg-more>summary::before{content:'▸ ';font-size:10px}
.asg-more[open]>summary::before{content:'▾ '}
.asg-more[open]{display:flex;flex-wrap:wrap;gap:6px}
.asg-more[open]>summary{width:100%}
.rag-row{display:flex;gap:8px;flex-wrap:wrap}
.rag-opt{flex:1;min-width:68px;text-align:center;font-size:12px;font-weight:600;padding:8px;border-radius:9px;border:1.5px solid var(--rule-blue);cursor:pointer;color:var(--soft)}
.rag-opt input{display:none}
.rag-opt.on.rag-green{border-color:var(--green);color:var(--green);background:color-mix(in srgb,var(--green) 10%,transparent)}
.rag-opt.on.rag-amber{border-color:var(--amber);color:#8a5a12;background:color-mix(in srgb,var(--amber) 14%,transparent)}
.rag-opt.on.rag-red{border-color:var(--red);color:var(--red-dark);background:color-mix(in srgb,var(--red) 10%,transparent)}
.rag-opt.on.rag-on_hold{border-color:var(--muted);color:var(--muted);background:var(--panel)}
.tpl-list{display:flex;flex-direction:column;gap:6px;max-height:320px;overflow:auto;margin-top:8px}
/* ⚠ label.tpl-opt, not bare .tpl-opt: `.modal-card label` (0,1,1) turns every label in a dialog into the
   house field caption, a 10px uppercase block, and the bare class (0,1,0) lost to it. So every picker
   built from these rows (Apply a template, Link a publication, New document, Archive project) drew its
   radio on a line of its own above an option name in spaced capitals. Tying the specificity wins by
   source order, as label.pfcheck does, and the resets undo what the caption rule sets. */
label.tpl-opt{display:flex;gap:10px;align-items:flex-start;padding:10px;border:1px solid var(--rule);border-radius:9px;cursor:pointer;
  margin:0;font-size:13px;font-weight:400;text-transform:none;letter-spacing:0;color:var(--navy)}
label.tpl-opt:hover{border-color:var(--rule-blue)}
label.tpl-opt input[type=radio]{flex:0 0 auto;margin:1px 0 0}
.tpl-name{font-size:13px;font-weight:600;color:var(--navy)}
.tpl-sub{font-size:11px;color:var(--faint);margin-top:2px}
/* dark: keep amber legible on dark surfaces (mirrors the existing amber-lift) */
html[data-theme=dark] .hpill.h-amber,html[data-theme=dark] .mtype.mt-gate,html[data-theme=dark] .rag-opt.on.rag-amber{color:var(--amber)}
html[data-theme=dark] .step.done .dot,html[data-theme=dark] .trow.done .tcheck::after{color:#0d1a2b}
/* workspace header: keep the big title from colliding with the ring/actions (esp. mobile) */
#projectPage .apphead-top{align-items:center;flex-wrap:wrap;row-gap:10px}
#projectPage .ah-title{flex:1 1 200px;min-width:0}
#projectPage .ah-title h1{font-size:23px;line-height:1.2;margin:0}
.ah-code{font-family:var(--mono);font-size:12px;font-weight:600;color:var(--muted,#5C6B80);background:var(--panel,#F2F5FA);border-radius:6px;padding:2px 8px;vertical-align:middle;margin-left:8px;letter-spacing:.02em}
@media(max-width:640px){ #projectPage .ah-actions{width:100%} #projectPage .board,.board{scroll-snap-type:x proximity} }
/* compact portfolio stat strip (board) — replaces the tall statband */
.pf-stats{display:flex;gap:26px;flex-wrap:wrap;align-items:baseline;padding:2px 2px 14px;border-bottom:1px solid var(--rule);margin-bottom:14px}
.pf-stat{display:flex;align-items:baseline;gap:7px}
.pf-stat b{font-size:19px;font-weight:700;color:var(--navy);font-variant-numeric:tabular-nums}
.pf-stat span{font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--faint)}
.pf-stat.warn b{color:var(--red)}
/* template manager + builder */
.modal-wide{width:min(680px,94vw)!important;max-width:94vw}
.tm-list{display:flex;flex-direction:column;gap:6px;max-height:340px;overflow:auto;margin-top:6px}
.tm-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 10px;border:1px solid var(--rule);border-radius:9px}
.tm-acts{display:flex;gap:6px;flex:0 0 auto}
.tb-head,.tb-row{display:grid;grid-template-columns:16px 104px 96px 1fr 58px 34px 72px 64px 22px;gap:6px;align-items:center}
.tb-grip{cursor:grab;color:var(--faint);font-size:13px;line-height:1;text-align:center;user-select:none;touch-action:none}
.tb-grip:active{cursor:grabbing}
.tb-row.tb-dragging{opacity:.45}
.tb-head{padding:10px 0 4px;font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--faint)}
.tb-head span:last-child{width:22px}
.tb-list{display:flex;flex-direction:column;gap:6px;max-height:300px;overflow:auto}
.tb-docs{display:flex;flex-wrap:wrap;gap:6px;min-height:8px}
.tb-docchip{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;color:var(--navy);background:color-mix(in srgb,var(--brand,#6F97D8) 12%,var(--panel));border:1px solid var(--rule,#E7ECF3);border-radius:999px;padding:3px 6px 3px 10px}
.tb-docrm{cursor:pointer;color:var(--faint);font-size:11px;line-height:1;padding:1px 3px;border-radius:5px}
.tb-docrm:hover{color:var(--red);background:color-mix(in srgb,var(--red) 10%,transparent)}
.tb-row input,.tb-row select{padding:5px 7px!important;font-size:12px!important;margin:0!important;width:100%}
.tb-sign{display:flex;justify-content:center;align-items:center}
.tb-del{background:none;border:none;color:var(--faint);cursor:pointer;font-size:14px;padding:0}
.tb-del:hover{color:var(--red)}
/* board drag-to-restatus */
.bcard[draggable=true]{cursor:grab}
.bcard.drag{opacity:.45;cursor:grabbing;box-shadow:var(--shadow-card-hover)}
.bcol.dropok{outline:2px dashed var(--rule-blue);outline-offset:-4px;background:color-mix(in srgb,var(--brand) 5%,var(--panel))}
/* smooth workspace tab switches: only #projBody repaints, and it fades in */
#projBody{opacity:0;transform:translateY(3px);transition:opacity .17s ease,transform .17s ease;will-change:opacity,transform}
#projBody.tab-in{opacity:1;transform:none}
.apptab{transition:color .15s ease,border-color .15s ease}
/* ---- delivery layer: mobile alignment + polish ---- */
.stepper{overflow-x:auto;padding:5px 0 7px;scrollbar-width:thin}
.step{flex:1 0 82px}
@media (max-width:600px){
  #projects .controls .ctl-label{display:none}          /* orphaned VIEW / GROUP BY labels on narrow screens */
  .crow{grid-template-columns:76px minmax(0,1fr);row-gap:4px}   /* narrow: badge + title on top, the right cluster wraps below */
  .crow .cr-right{grid-column:1/-1;justify-content:flex-start}
  .cr-edit{opacity:.55}                                 /* no hover on touch → keep the edit affordance visible */
  #projectPage .mini-stat{flex-basis:calc(50% - 5px)}   /* 2×2 tiles instead of a lonely 3+1 */
}
/* ---- workspace header: breathing room around the actions + tiles ---- */
#projectPage .ah-actions{margin-left:auto}
#projectPage .mini-stats{margin-top:14px}
/* smooth loading veil: fades out to reveal content instead of a hard swap */
.loadveil{transition:opacity .24s ease}
.loadveil.hiding{opacity:0;pointer-events:none}
/* board badges → the same sleek pill system as the type tags */
.bc-badges .tag{display:inline-block;font-size:9px;font-weight:600;letter-spacing:.02em;padding:2.5px 8px;border-radius:999px;line-height:1;white-space:nowrap}
/* status pills: a touch tighter/lighter so every tag in Projects reads as one system */
.pill{font-size:8.5px;letter-spacing:.08em;padding:3px 8px}
/* change requests (scope control) */
.chg-list{display:flex;flex-direction:column;gap:10px}
.chg-card{border:1px solid var(--rule);border-radius:12px;padding:13px 15px;background:var(--surface)}
.chg-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.chg-title{font-size:14px;font-weight:600;color:var(--navy)}
.chg-by{font-size:11px;color:var(--faint);margin-left:auto}
.chg-detail{font-size:13px;color:var(--soft);margin-top:8px;white-space:pre-wrap}
.chg-impact{font-size:11.5px;color:var(--muted);margin-top:6px}
.chg-decided{font-size:11.5px;color:var(--muted);margin-top:8px;font-weight:600}
.chg-acts{display:flex;gap:8px;margin-top:12px}
/* publications on a project (lab) */
.pub-list{display:flex;flex-direction:column}
.pub-row{display:flex;align-items:center;gap:12px;padding:10px 4px;border-bottom:1px solid var(--rule)}
.pub-row:last-child{border-bottom:none}
.pub-main{flex:1;min-width:0}
.pub-title{font-size:13.5px;font-weight:500;color:var(--navy)}
.pub-meta{font-size:11.5px;color:var(--faint);margin-top:2px}
.pub-doi{font-size:11px;color:var(--blue);white-space:nowrap;text-decoration:none}
.pub-doi:hover{text-decoration:underline}

/* documents & forms on a project (P1b) */
/* "Operates under" — QMS controlled documents governing a project (delivery ↔ quality link) */
.ctrl-docs{margin:0 0 14px;padding:11px 12px;border:1px solid var(--rule,#E7ECF3);border-radius:10px;background:var(--panel,#F6F8FC)}
.ctrl-docs .cd-h{font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);margin:0 0 8px}
.ctrl-docs .cd-h .lmuted{text-transform:none;letter-spacing:0;font-weight:500}
.cd-chips{display:flex;flex-wrap:wrap;gap:7px}
.ctrl-chip{display:inline-flex;align-items:center;gap:7px;max-width:100%;padding:5px 9px;border:1px solid var(--rule,#E7ECF3);border-radius:999px;background:var(--card,#fff);font:inherit;cursor:pointer;transition:border-color .12s ease,background .12s ease,transform .12s ease}
button.ctrl-chip:hover{border-color:var(--ink);transform:translateY(-1px)}
.ctrl-chip .cc-code{font-size:11px;font-weight:600;color:var(--ink);letter-spacing:.02em;white-space:nowrap}
.ctrl-chip .cc-title{font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ctrl-chip.cc-unreg{cursor:default;border-style:dashed;border-color:#c99a00}
.ctrl-chip.cc-unreg .cc-code{color:#8A5E0F}
.doc-list{display:flex;flex-direction:column}
.doc-row{display:flex;align-items:center;gap:12px;padding:11px 6px;border-bottom:1px solid var(--rule,#E7ECF3);cursor:pointer;border-radius:8px;transition:background .12s ease}
.doc-row:last-child{border-bottom:none}
.doc-row:hover{background:var(--panel,#F6F8FC)}
.doc-main{flex:1;min-width:0}
.doc-title{font-size:13.5px;font-weight:600;color:var(--ink)}
.doc-sub{font-size:11.5px;color:var(--faint);margin-top:2px}
.doc-prog{height:3px;border-radius:2px;background:var(--rule,#E7ECF3);margin-top:6px;max-width:220px;overflow:hidden}
.doc-prog i{display:block;height:100%;background:var(--ink);opacity:.55;border-radius:2px}
.doc-acts{display:flex;align-items:center;gap:6px;flex-shrink:0}
.iconbtn{padding:4px 8px}
/* project meeting minutes — list + composer */
.mtg-list{display:flex;flex-direction:column}
.mtg-row{display:flex;align-items:flex-start;gap:12px;padding:12px 6px;border-bottom:1px solid var(--rule,#E7ECF3);cursor:pointer;border-radius:8px;transition:background .12s ease}
.mtg-row:last-child{border-bottom:none}
.mtg-row:hover{background:var(--panel,#F6F8FC)}
.mtg-main{flex:1;min-width:0}
.mtg-title{font-size:13.5px;font-weight:600;color:var(--ink)}
.mtg-shared{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ugood);margin-left:6px}
.mtg-sub{font-size:11.5px;color:var(--faint);margin-top:2px}
.mtg-summary{font-size:12px;color:var(--muted);margin-top:5px;line-height:1.45}
.mtg-acts{display:flex;align-items:center;gap:6px;flex-shrink:0}
.mtg-item{border:1px solid var(--rule,#E7ECF3);border-radius:10px;padding:10px 11px;margin:8px 0;background:var(--card,#fff)}
.mtg-item-top{display:flex;gap:8px;align-items:center}
/* owner · due · to-do on ONE line. It had no rule at all, so the three controls stacked into three
   full-width rows and the row grew taller than the item it belongs to. */
.mtg-item-bot{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:7px}
.mtg-item-bot > select{flex:0 1 200px;min-width:0}
.mtg-item-bot > input[type=date]{flex:0 0 auto;width:auto}
.mtg-item-bot .mtg-todo{margin-left:auto}
.mtg-kind{flex:0 0 110px;height:34px}
.mtg-it-title{flex:1;height:34px}
/* ↑ / ↓ on a minute item — the form builder's move-button shape, reused so the two reorder controls
   in the app look and behave the same. */
/* The archived marker on a client row — quiet, because it states a fact rather than raising an alarm. */
.cl-arch{display:inline-block;margin-left:6px;padding:1px 6px;border-radius:999px;background:var(--panel,#F0F4FA);color:var(--muted);font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;vertical-align:middle}
.mtg-move{display:flex;align-items:center;gap:2px;flex:0 0 auto}
.mtg-move button{appearance:none;border:0;background:none;color:var(--muted);cursor:pointer;font-size:13px;line-height:1;padding:3px 5px;border-radius:5px}
.mtg-move button:hover:not(:disabled){background:var(--surface);color:var(--ink)}
.mtg-move button:disabled{opacity:.3;cursor:default}
/* The formatting strip over a plain-text box. Deliberately quiet: the text is still plain text and
   the markers stay visible in the box, so the bar is a shortcut, not a promise of a word processor. */
/* The formatting strip. Quiet by design — the text underneath is still plain text and the markers
   stay visible in the box — but it has to read as a toolbar rather than as four stray letters, so it
   gets a tray, a separator between the character marks and the list marks, and real button targets. */
.mdbar{display:inline-flex;align-items:center;gap:2px;margin:0 0 5px;padding:3px;border:1px solid var(--rule-blue,#C8D2E3);border-radius:8px;background:var(--panel,#F6F8FC)}
.mdbar button{appearance:none;border:0;background:none;color:var(--soft);cursor:pointer;font-size:13px;line-height:1;height:26px;min-width:30px;padding:0 8px;border-radius:6px;font-family:inherit;display:inline-flex;align-items:center;justify-content:center;transition:background .12s ease,color .12s ease}
.mdbar button b{font-weight:700}
.mdbar button i{font-style:italic;font-family:Georgia,'Times New Roman',serif}   /* an unmistakable I */
.mdbar button:hover{background:var(--surface);color:var(--ink);box-shadow:0 1px 2px rgba(21,45,73,.08)}
.mdbar button:active{background:var(--blue-soft,#DBE3F0);color:var(--navy)}
.mdbar button:focus-visible{outline:2px solid var(--blue,#6F97D8);outline-offset:-2px}
.mdbar-sep{width:1px;height:16px;margin:0 3px;background:var(--rule-blue,#C8D2E3);flex:0 0 auto}
/* Rendered minutes and notes. Tight margins: these sit inside cards that already carry their own
   padding, and a first/last child must not add a second gap. */
.md>p{margin:0 0 8px}
.md>ol,.md>ul{margin:0 0 8px;padding-left:22px}
.md>ol li,.md>ul li{margin:0 0 2px}
.md>*:last-child{margin-bottom:0}
.mtg-it-x{appearance:none;background:none;border:0;color:var(--muted);cursor:pointer;font-size:14px;flex:0 0 auto;line-height:1}
.mtg-it-x:hover{color:var(--red)}
.mtg-item textarea.mtg-it-note{margin-top:7px}
.mtg-action-x{display:flex;gap:8px;align-items:center;margin-top:7px;flex-wrap:wrap}
.mtg-action-x .mtg-it-owner{flex:1;min-width:120px;height:34px}
.mtg-action-x .mtg-it-due{flex:0 0 148px;height:34px}
/* .modal-card label styles labels block+uppercase — override for these inline checkbox labels */
.modal-card label.mtg-flag{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--navy);cursor:pointer;text-transform:none;letter-spacing:0;font-weight:500;margin:0}
.mtg-flag input{flex:0 0 auto;margin:0}
.mtg-internal{margin-top:8px}
.modal-card label.mtg-share-toggle{display:flex;align-items:center;gap:9px;margin:16px 0 0;padding:11px 13px;border:1px solid var(--rule,#E7ECF3);border-radius:10px;background:var(--panel);font-size:13px;color:var(--navy);cursor:pointer;text-transform:none;letter-spacing:0;font-weight:500}
.mtg-share-toggle input{flex:0 0 auto;margin:0}
/* fill-in view */
.ff-wrap{margin-top:2px}
.ff-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0 0 14px}
.ff-title{flex:1;min-width:0;display:flex;flex-direction:column}
.ff-title b{font-size:15px;color:var(--ink)}
.ff-code{font-size:11px;color:var(--faint);letter-spacing:.02em;margin-top:1px}
.ff-right{display:flex;align-items:center;gap:10px}
.ff-prog{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums}
.ff-signed{color:#1E874B;font-weight:600}
.doc-signed{font-size:10.5px;font-weight:600;color:#1E874B;background:color-mix(in srgb,#1E874B 12%,transparent);padding:1px 6px;border-radius:6px;margin-left:6px;vertical-align:middle}
.ff-needs{background:color-mix(in srgb,var(--red) 7%,transparent);border:1px solid color-mix(in srgb,var(--red) 22%,transparent);color:var(--soft);border-radius:9px;padding:8px 11px;margin:0 0 12px;font-size:12.5px}
.ff-saved{font-size:11.5px;color:var(--muted);min-width:74px;text-align:right;transition:opacity .3s ease;opacity:0}
/* The fields the .ff-needs banner above is naming. The banner, the disabled Sign button's tooltip
   ("Fill the highlighted fields first"), the client's refusal and the server's 422 all said
   "highlighted" while nothing on the page was — so a reader had to match a list of labels against a
   long document by eye. Marked from the SAME placeholder rule the server counts with, so the banner
   and the marks can never disagree about which field is which.
   ⚠ Border and a tint only — no layout. A document view is a reading surface; adding a line or a
   margin here would reflow the page as answers are typed, which is exactly when somebody is reading
   it. And --red (not --red-fill, which has no dark-theme definition). */
.ff-needs-you > .ff-box, .ff-needs-you > .ff-in,
input.ff-in.ff-needs-you{border-color:color-mix(in srgb,var(--red) 55%,transparent);background:color-mix(in srgb,var(--red) 4%,transparent)}
.ff-needs-you > .ff-label{color:var(--red)}
.ff-choice.ff-needs-you > .ff-opts{box-shadow:inset 2px 0 0 color-mix(in srgb,var(--red) 55%,transparent)}   /* inset shadow, NOT a border: a border is part of the box and shifts the tick boxes off
      the measured 23px indent that test_form_layout pins. A shadow paints and nothing else. */
/* One rhythm knob for the whole document view. Every vertical gap below is a multiple of it, so the
   form breathes as one thing rather than as seven constants that drift apart. Defined here (not only
   set from JS) so the token guard can see it. */
.ff-wrap{--ff-rhythm:1}
.ff-sec{margin-bottom:calc(var(--ff-rhythm)*18px)}
.ff-sec h3{margin:0 0 calc(var(--ff-rhythm)*13px)}
.profcard.ff-sec{padding:calc(var(--ff-rhythm)*22px) 24px}
/* A question needs more air beneath it than its own label has above its control, or the reader
   cannot tell where one question ends and the next begins — at 14px against a 5px label gap they
   read as one block. */
.ff-field{margin:0 0 calc(var(--ff-rhythm)*22px)}
.ff-field:last-child{margin-bottom:2px}
/* An unlabelled write-in box answering the choice group above it: no label of its own means nothing
   separates the last tick box from the top of the box, so it reads as one more option. */
.ff-field.ff-afterchoice{margin-top:calc(var(--ff-rhythm)*14px)}
.ff-label{font-size:12.5px;color:var(--soft);margin:0 0 calc(var(--ff-rhythm)*7px);font-weight:500}
.ff-box,.ff-in{width:100%;font:inherit;font-size:13px;color:var(--ink);background:var(--surface);border:1px solid var(--rule-blue,#C8D2E3);border-radius:9px;padding:8px 10px;box-sizing:border-box}
.ff-box{resize:vertical;min-height:52px;line-height:1.5}
.ff-box:focus,.ff-in:focus{outline:none;border-color:var(--ink);box-shadow:0 0 0 3px color-mix(in srgb,var(--ink) 10%,transparent)}
.ff-box:disabled,.ff-in:disabled{background:var(--panel,#F6F8FC);color:var(--muted)}
/* Indented by one box-plus-gap (15+8), so a tick box now begins exactly where its own option text
   used to — the options read as answers BELONGING to the question above rather than as a second
   column of questions sharing its left rail. */
.ff-opts{display:flex;flex-direction:column;gap:calc(var(--ff-rhythm)*8px);padding-left:23px}
/* flex-start, not center: `center` aligns the box against the WHOLE wrapped label, so a two-line
   option drops the box into the gap between its lines. The margin puts it back on the first line —
   (line-height − box) / 2 — which reproduces the single-line look exactly. */
.ff-opt{display:flex;align-items:flex-start;gap:8px;font-size:13px;line-height:1.6;color:var(--ink);cursor:pointer}
.ff-opt input{accent-color:var(--ink);width:15px;height:15px;flex-shrink:0;margin-top:2.9px}
.ff-meta{display:flex;flex-direction:column;gap:calc(var(--ff-rhythm)*10px)}
.ff-mrow{display:flex;align-items:center;gap:10px}
.ff-mlab{flex:0 0 200px;font-size:12.5px;color:var(--muted)}
.ff-mcell{flex:1}
/* ---- Form template builder (P3): manager list + field editor (Settings → Documents & forms) */
.ftlist{display:flex;flex-direction:column;margin:6px 0 4px}
.ftrow{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 2px;border-bottom:1px solid var(--rule,#E7ECF3)}
.ftrow:last-child{border-bottom:0}
.ftacts{display:flex;align-items:center;gap:6px;flex-shrink:0}
.ft-code{display:inline-block;font-family:var(--mono);font-size:10.5px;font-weight:600;letter-spacing:.02em;color:var(--navy);background:color-mix(in srgb,var(--brand,#6F97D8) 14%,var(--panel));border:1px solid var(--rule,#E7ECF3);border-radius:6px;padding:1px 6px;margin-left:2px}
.ft-code.retired{color:#8a2e2e;background:color-mix(in srgb,var(--red) 12%,var(--panel));text-decoration:line-through}
.ftrow.is-retired>div:first-child b{opacity:.6}
/* the template builder at width = a two-pane editor: template settings as a left rail, the
   field list owning the full height. Areas by class, so the optional jump strip just collapses. */
.fb-card{height:92vh;max-height:92vh;overflow:hidden;display:grid;column-gap:26px;
  grid-template-columns:290px minmax(0,1fr);
  grid-template-rows:auto auto auto minmax(0,1fr) auto auto;
  grid-template-areas:"head head" "meta sec" "meta jump" "meta fields" "meta addbar" "actions actions"}
.fb-card>h3{grid-area:head}
.fb-card>.mgrid{grid-area:meta;grid-template-columns:minmax(0,1fr);align-content:start;overflow-y:auto;min-height:0;padding-right:4px}
.fb-card>.msec{grid-area:sec;margin-top:0}
.fb-card>.fb-jump{grid-area:jump}
.fb-card>.fb-fields{grid-area:fields}
.fb-card>.fb-addbar{grid-area:addbar}
.fb-card>.modal-actions{grid-area:actions}
@media (max-width:900px){
  .fb-card{display:flex;flex-direction:column;height:auto}
  .fb-card>.mgrid{overflow:visible}
}
.fb-jump{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin:0 0 8px}
.fb-jumpchip{font-size:11px;font-weight:600;padding:3px 10px;border-radius:20px;border:1px solid var(--rule,#E7ECF3);background:var(--panel,#fff);cursor:pointer;color:var(--ink-2,#3D5A85)}
.fb-jumpchip:hover{border-color:color-mix(in srgb,var(--brass,#A9772A) 45%,transparent)}
.fb-prevwrap{position:fixed;inset:0;z-index:96;background:var(--modal-veil,rgba(21,45,73,.45));display:flex;align-items:center;justify-content:center;backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
.fb-prevcard{width:min(920px,96vw);height:94vh;background:var(--surface,#fff);border-radius:14px;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 24px 60px -12px rgba(21,45,73,.4)}
.fb-prevbar{display:flex;align-items:center;gap:10px;padding:9px 10px 9px 16px;border-bottom:1px solid var(--rule,#E7ECF3)}
.fb-prevbar b{font-size:13.5px;color:var(--navy,#152D49);white-space:nowrap}
.fb-prevbar .lmuted{flex:1;min-width:0;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fb-previf{flex:1;border:0;width:100%;background:#525659}
.ai-draftwrap{position:fixed;inset:0;z-index:96;background:var(--modal-veil,rgba(21,45,73,.45));display:flex;align-items:center;justify-content:center;backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
/* A sub-panel opened from inside a dialog, on its own layer above it — so the dialog underneath
   survives instead of being overwritten with "unsaved edits here are lost. Continue?".
   ⚠ ONE FIXED VALUE, NOT A LADDER. 97 clears #modal (90), .lm-overlay (95) and the two fixed-96
   wraps above. A "parent + 2" scheme would collide with those 96s the first time a sub-panel opened
   from an .lm-overlay dialog, and z-index bugs of that kind are invisible until the one combination
   that triggers them. It shares the veil and the card animation with #modal so a reader cannot tell
   the two hosts apart — which is the point: it is the same kind of surface, one layer up. */
.sub-modal{position:fixed;inset:0;background:var(--modal-veil);display:flex;align-items:center;justify-content:center;z-index:97;backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px)}
.sub-modal .modal-card{animation:mpop var(--t3) var(--ease) both}
.ai-draftcard{width:min(620px,94vw);background:var(--surface,#fff);border-radius:14px;padding:16px 18px;box-shadow:0 24px 60px -12px rgba(21,45,73,.4);border:1px solid color-mix(in srgb,var(--rule,#E7ECF3) 60%,transparent)}
.ai-drafthd{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.ai-drafthd b{font-size:14.5px;color:var(--navy,#152D49);white-space:nowrap}
.ai-drafthd .lmuted{flex:1;min-width:0;font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ai-drafttx{width:100%;box-sizing:border-box;font-family:var(--font);font-size:13.5px;line-height:1.5;padding:11px 12px;border:1px solid var(--rule-blue,#C8D2E3);border-radius:10px;color:var(--ink);background:var(--field);resize:vertical}
.ai-draftft{display:flex;align-items:center;gap:8px;margin-top:10px}
.ai-drafttag{font-size:12px;color:var(--muted,#5C6B80)}
.ai-flag{display:inline-block;font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--brass,#A9772A);border:1px solid color-mix(in srgb,var(--brass,#A9772A) 40%,transparent);border-radius:20px;padding:1px 7px;margin-right:4px}
.ai-draftnarr{cursor:pointer;background:none;border:0;font:inherit;color:var(--brass,#A9772A)}
.ai-inline{margin:4px 0 18px;border:1px solid color-mix(in srgb,var(--brass,#A9772A) 22%,transparent);background:color-mix(in srgb,var(--brass,#A9772A) 5%,var(--surface,#fff));border-radius:12px;padding:10px 13px}
.ai-inline-hd{display:flex;align-items:center;gap:6px;font-size:11.5px;color:var(--muted,#5C6B80);margin-bottom:6px}
.ai-inline-body{font-size:13.5px;line-height:1.55;color:var(--ink);white-space:pre-wrap}
.ai-inline-btn{border:0;background:none;cursor:pointer;color:var(--muted,#5C6B80);font-size:13px;line-height:1;padding:3px 5px;border-radius:6px}
.ai-inline-btn:hover{background:color-mix(in srgb,var(--brass,#A9772A) 14%,transparent);color:var(--navy,#152D49)}
.ai-readcard{width:min(640px,94vw);background:var(--surface,#fff);border-radius:14px;padding:16px 18px;box-shadow:0 24px 60px -12px rgba(21,45,73,.4);border:1px solid color-mix(in srgb,var(--rule,#E7ECF3) 60%,transparent)}
.ai-readbody{font-size:14px;line-height:1.6;color:var(--ink);white-space:pre-wrap;max-height:60vh;overflow:auto;margin:6px 0 2px}
.ai-readft{display:flex;align-items:center;gap:8px;margin-top:12px}
.ai-askcard{width:min(640px,94vw);background:var(--surface,#fff);border-radius:14px;padding:16px 18px;box-shadow:0 24px 60px -12px rgba(21,45,73,.4);border:1px solid color-mix(in srgb,var(--rule,#E7ECF3) 60%,transparent)}
.ai-askrow{display:flex;gap:8px;margin:6px 0 10px}
.ai-askin{flex:1;min-width:0;height:38px;box-sizing:border-box;font-family:var(--font);font-size:14px;padding:0 12px;border:1px solid var(--rule-blue,#C8D2E3);border-radius:10px;background:var(--field);color:var(--ink)}
.ai-askin:focus{outline:none;border-color:var(--navy,#152D49);box-shadow:0 0 0 3px color-mix(in srgb,var(--navy,#152D49) 13%,transparent)}
.ai-askans{min-height:56px}
.ai-askhd{font-size:11.5px;color:var(--muted,#5C6B80)}
.ai-asktext{font-size:14px;line-height:1.6;color:var(--ink);white-space:pre-wrap;margin-top:4px;max-height:52vh;overflow:auto}
.ai-srcs{margin-top:12px;display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.ai-src{font-size:11.5px;border:1px solid var(--rule-blue,#C8D2E3);border-radius:20px;padding:2px 9px;color:var(--ink-2,#3D5A85)}
.ai-chips{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 12px}
.ai-chip{font-size:12px;border:1px solid var(--rule-blue,#C8D2E3);border-radius:20px;padding:4px 11px;background:var(--panel,#fff);color:var(--ink-2,#3D5A85);cursor:pointer;text-align:left}
.ai-chip:hover{border-color:color-mix(in srgb,var(--brass,#A9772A) 45%,transparent);color:var(--navy,#152D49)}
.ai-usedtools{margin-top:12px;font-size:11.5px}
/* Ask Lemma dock — bottom-right; a Lemma-marked bubble that expands upward into a chat feed.
   Rests at bottom:20px but lifts to ride above the footer once it scrolls into view. The lift is set
   in JS on the `translate` property (NOT `transform` — the bubble's entrance/hover animations own
   that), so it composes with every breakpoint's own `bottom` value and never fights them. */
.ask-dock{position:fixed;right:20px;bottom:20px;z-index:70;display:flex;flex-direction:column;align-items:flex-end;transition:translate .18s var(--ease,ease)}
@media (prefers-reduced-motion:reduce){.ask-dock{transition:none}}
.ask-dock.is-open .ask-bubble{display:none}
/* collapsed bubble */
.ask-bubble{position:relative;display:inline-flex;align-items:center;gap:8px;height:44px;padding:0 8px 0 15px;border-radius:24px;border:1px solid color-mix(in srgb,var(--brass,#A9772A) 40%,transparent);background:var(--surface,#fff);color:var(--navy,#152D49);font-family:var(--font);font-size:13.5px;font-weight:600;box-shadow:0 6px 20px -6px rgba(21,45,73,.28);cursor:pointer;transition:border-color .15s,box-shadow .15s}
.ask-bubble:hover{border-color:var(--brass,#A9772A);box-shadow:0 9px 26px -6px rgba(21,45,73,.34)}
.ask-bubble-mark{display:inline-flex}
.ask-bubble-mark .lemmamark{width:24px;height:24px;fill:var(--brass,#A9772A)}
.ask-bubble-lbl{white-space:nowrap}
/* A DOT, not a counter — it used to carry the risk-radar number, which on a chat bubble reads as
   unread messages and promises something to read that does not exist. Same attention, no claim. */
.ask-bubble-badge{display:inline-flex;width:9px;height:9px;padding:0;border-radius:50%;background:var(--brass,#A9772A)}
.ask-bubble-x{width:24px;height:24px;border-radius:50%;border:1px solid var(--rule-blue,#C8D2E3);background:var(--surface,#fff);color:var(--muted,#5C6B80);font-size:10px;line-height:1;cursor:pointer;opacity:0;transition:opacity .12s;flex:none}
.ask-bubble:hover .ask-bubble-x{opacity:1}
.ask-bubble-x:hover{color:var(--navy,#152D49);border-color:var(--muted,#5C6B80)}
/* expanded chat panel — anchored bottom-right, grows upward */
.ask-panel{width:min(380px,calc(100vw - 32px));height:min(600px,calc(100vh - 132px));display:flex;flex-direction:column;background:var(--surface,#fff);border:1px solid color-mix(in srgb,var(--rule,#E7ECF3) 70%,transparent);border-radius:16px;box-shadow:0 26px 64px -14px rgba(21,45,73,.42);overflow:hidden;transform-origin:bottom right;animation:askPop .18s cubic-bezier(.2,.8,.25,1)}
@keyframes askPop{from{opacity:0;transform:translateY(10px) scale(.96)}to{opacity:1;transform:none}}
.ask-phd{display:flex;align-items:center;gap:9px;padding:11px 12px 11px 14px;border-bottom:1px solid var(--rule,#E7ECF3)}
.ask-phd-mark{display:inline-flex}
.ask-phd-mark .lemmamark{width:22px;height:22px;fill:var(--brass,#A9772A)}
.ask-phd-t{display:flex;flex-direction:column;line-height:1.15;flex:1;min-width:0}
.ask-phd-t b{font-size:14px;color:var(--navy,#152D49)}
.ask-phd-t span{font-size:11px;color:var(--muted,#5C6B80)}
.ask-icon{width:28px;height:28px;border-radius:8px;border:1px solid transparent;background:transparent;color:var(--muted,#5C6B80);font-size:14px;line-height:1;cursor:pointer;flex:none;transition:background .12s,color .12s}
.ask-icon:hover{background:var(--panel,#F4F7FB);color:var(--navy,#152D49)}
.ask-feed{flex:1;min-height:0;overflow-y:auto;padding:14px 14px 6px;display:flex;flex-direction:column;gap:12px}
.ask-greet{display:flex;flex-direction:column;align-items:center;text-align:center;gap:9px;padding:14px 8px 4px;color:var(--muted,#5C6B80)}
.ask-greet .lemmamark{width:34px;height:34px;fill:color-mix(in srgb,var(--brass,#A9772A) 78%,transparent)}
/* the greet mark gained a wrapper so a character can be targeted there; the aperture
   fallback still sizes off .lemmamark above, and the character sizes itself. */
.ask-greet-mark{display:inline-flex;line-height:0}
.ask-greet p{margin:0;font-size:12.5px;line-height:1.5;max-width:280px}
.ask-chips{display:flex;flex-direction:column;gap:7px;padding:2px 2px 8px}
.ask-chip{font-size:12.5px;border:1px solid var(--rule-blue,#C8D2E3);border-radius:10px;padding:8px 11px;background:var(--panel,#fff);color:var(--ink-2,#3D5A85);cursor:pointer;text-align:left;transition:border-color .12s,color .12s}
.ask-chip:hover{border-color:color-mix(in srgb,var(--brass,#A9772A) 45%,transparent);color:var(--navy,#152D49)}
.ask-msg{display:flex;gap:8px;max-width:100%}
.ask-msg.ask-me{justify-content:flex-end}
.ask-msg.ask-ai{align-items:flex-start}
.ask-msg-mark{display:inline-flex;margin-top:2px;flex:none}
.ask-msg-mark .lemmamark{width:20px;height:20px;fill:var(--brass,#A9772A)}
.ask-bub{font-size:13.5px;line-height:1.55;border-radius:13px;padding:9px 12px;max-width:82%}
.ask-me .ask-bub{background:var(--navy,#152D49);color:#fff;border-bottom-right-radius:5px}
.ask-ai .ask-bub{background:var(--panel,#F4F7FB);color:var(--ink,#152D49);border:1px solid var(--rule,#E7ECF3);border-bottom-left-radius:5px}
.ask-flag{display:inline-block;font-size:9.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--brass,#A9772A);margin-bottom:3px}
.ask-bub.ask-err{background:color-mix(in srgb,var(--red,#9E2A2B) 6%,var(--panel,#F4F7FB));border:1px solid color-mix(in srgb,var(--red,#9E2A2B) 22%,transparent);color:var(--ink-2,#3D5A85)}
.ask-retry{display:block;margin-top:7px;font-size:12px;font-weight:600;color:var(--navy,#152D49);background:none;border:none;padding:0;cursor:pointer;text-decoration:underline}
.ask-retry:hover{color:var(--red,#9E2A2B)}
.ask-atext{white-space:pre-wrap}
#askStreamText::after{content:"▋";margin-left:1px;color:var(--brass,#A9772A);animation:askCaret 1s steps(2,start) infinite}
@keyframes askCaret{50%{opacity:0}}
.ask-tools{margin-top:6px;font-size:11px;color:var(--muted,#5C6B80)}
/* persona C — the aperture "thinking" state */
.ask-msg-think{padding:2px 0 4px 2px}
.ask-thinking{display:inline-flex}
.ask-thinking svg{width:30px;height:30px}
.ask-thinking .atr{fill:none;stroke:var(--brass,#A9772A);stroke-width:3;opacity:.45}
.ask-thinking .atr2{opacity:.26;stroke-width:2.5}
.ask-thinking .ath{fill:none;stroke:var(--brass,#A9772A);stroke-width:3;transform-box:fill-box;transform-origin:center}
.ask-thinking .athi{fill:none;stroke:var(--brass,#A9772A);stroke-width:2;opacity:.7;transform-box:fill-box;transform-origin:center}
@media(prefers-reduced-motion:no-preference){
  .ask-thinking .atr{animation:askPulse 2.6s ease-in-out infinite}
  .ask-thinking .ath{animation:askSpin 8s linear infinite}
  .ask-thinking .athi{animation:askSpin 8s linear infinite reverse}
}
@keyframes askPulse{0%,100%{opacity:.24}50%{opacity:.66}}
@keyframes askSpin{to{transform:rotate(360deg)}}
/* Tier 0 — "show the figures" grounding evidence */
.ask-ev{margin-top:9px;font-size:12px}
.ask-ev>summary{cursor:pointer;color:var(--muted,#5C6B80);font-weight:600;list-style:none;display:inline-flex;align-items:center;gap:6px;user-select:none}
.ask-ev>summary::-webkit-details-marker{display:none}
.ask-ev>summary::before{content:"\25B8";color:var(--brass,#A9772A);font-size:10px;transition:transform .12s}
.ask-ev[open]>summary::before{transform:rotate(90deg)}
.ask-ev>summary:hover{color:var(--navy,#152D49)}
.ask-ev-item{margin-top:9px;padding-top:9px;border-top:1px solid var(--rule,#E7ECF3)}
.ask-ev-item:first-of-type{border-top:none}
.ask-ev-name{font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--brass,#A9772A);font-weight:700;margin-bottom:5px;display:flex;align-items:baseline;gap:8px}
.ask-ev-at{margin-left:auto;font-family:var(--mono);font-size:9.5px;font-weight:400;letter-spacing:0;text-transform:none;color:var(--muted,#5C6B80)}
/* L0 — the grounding strip: the deterministic gate's verdict, printed under the answer */
.ask-ground{margin-top:9px;font-size:11.5px;color:var(--muted,#5C6B80);display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.ask-ground.ok{color:var(--green,#1E9E78)}
.ask-ground.warn{color:#8a5a12;background:color-mix(in srgb,var(--amber,#E9A23B) 12%,transparent);border:1px solid color-mix(in srgb,var(--amber,#E9A23B) 38%,transparent);border-radius:7px;padding:5px 8px}
html[data-theme=dark] .ask-ground.warn{color:var(--amber,#E9A23B)}
.ask-vpath{font-family:var(--mono);font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--green,#1E9E78);font-weight:600}
.ask-vpath.off{color:var(--muted,#5C6B80)}
/* verified-question chips carry a quiet tick — the claim behind it is tested, not decorative */
.ask-chip-v,.ai-chip .ask-chip-v{color:var(--green,#1E9E78);font-weight:700;margin-right:5px}
.ask-ev-kv{display:flex;flex-direction:column;gap:2px}
.ask-ev-row{display:flex;gap:8px;justify-content:space-between;align-items:baseline}
.ask-ev-row.ask-ev-nest{flex-direction:column;gap:3px;align-items:stretch}
.ask-ev-k{color:var(--muted,#5C6B80)}
.ask-ev-v{color:var(--ink,#152D49);text-align:right;font-variant-numeric:tabular-nums}
.ask-ev-nest .ask-ev-v{text-align:left}
.ask-ev-nil{color:var(--muted,#5C6B80);opacity:.7}
.ask-ev-tags{display:flex;flex-wrap:wrap;gap:4px}
.ask-ev-tag{background:var(--panel,#F4F7FB);border:1px solid var(--rule,#E7ECF3);border-radius:6px;padding:2px 7px;font-size:11px;color:var(--ink-2,#3D5A85)}
.ask-ev-tw{overflow-x:auto;margin-top:2px}
.ask-ev-table{border-collapse:collapse;font-size:11.5px;width:100%}
.ask-ev-table th{text-align:left;color:var(--muted,#5C6B80);font-weight:600;padding:2px 12px 4px 0;text-transform:capitalize;white-space:nowrap}
.ask-ev-table td{padding:2px 12px 2px 0;color:var(--ink,#152D49);font-variant-numeric:tabular-nums;white-space:nowrap;border-top:1px solid var(--rule,#E7ECF3)}
.ask-ev-more{font-size:11px;color:var(--muted,#5C6B80);margin-top:3px}
/* Tier 1 — chart as the answer */
.ask-ch{margin-top:10px;display:flex;flex-direction:column;gap:5px}
.ask-ch-row{display:grid;grid-template-columns:minmax(64px,34%) 1fr auto;gap:9px;align-items:center;font-size:11.5px}
.ask-ch-lab{color:var(--ink-2,#3D5A85);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ask-ch-bar{height:8px;background:var(--panel,#F4F7FB);border:1px solid var(--rule,#E7ECF3);border-radius:5px;overflow:hidden}
.ask-ch-fill{display:block;height:100%;background:var(--brass,#A9772A);border-radius:5px;min-width:3px}
.ask-ch-val{color:var(--ink,#152D49);font-variant-numeric:tabular-nums;font-weight:600;text-align:right;min-width:32px}
/* Tier 3 — draft->act proposal cards */
.ask-prop{margin-top:11px;border:1px solid color-mix(in srgb,var(--brass,#A9772A) 35%,transparent);border-radius:12px;padding:11px 13px;background:color-mix(in srgb,var(--brass,#A9772A) 8%,var(--panel,#F4F7FB))}
.ask-prop-hd{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--brass,#A9772A);font-weight:700;margin-bottom:4px}
.ask-prop-title{font-size:13.5px;font-weight:600;color:var(--navy,#152D49)}
.ask-prop-detail{font-size:12px;color:var(--ink-2,#3D5A85);margin-top:3px;line-height:1.45}
.ask-prop-meta{font-size:11px;color:var(--muted,#5C6B80);margin-top:5px}
.ask-prop-acts{display:flex;gap:8px;margin-top:10px}
.ask-prop-add{font-size:12.5px;font-weight:600;border:none;border-radius:8px;padding:6px 14px;background:var(--brass,#A9772A);color:#fff;cursor:pointer}
.ask-prop-add:hover{filter:brightness(1.06)}
.ask-prop-add:disabled{opacity:.55;cursor:default}
.ask-prop-x{font-size:12.5px;font-weight:600;border:1px solid var(--rule-blue,#C8D2E3);border-radius:8px;padding:6px 12px;background:transparent;color:var(--muted,#5C6B80);cursor:pointer}
.ask-prop-x:hover{color:var(--navy,#152D49);border-color:var(--muted,#5C6B80)}
.ask-prop.done{border-color:color-mix(in srgb,var(--brass,#A9772A) 25%,transparent);color:var(--ink-2,#3D5A85);font-size:12.5px;font-weight:600}
.ask-prop-tick{color:var(--brass,#A9772A);font-weight:700}
.ask-prop-rag{display:inline-block;margin-left:5px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:1px 7px;border-radius:20px;vertical-align:middle}
.ask-prop-rag.rag-green{color:var(--green,#1F9D57);background:color-mix(in srgb,var(--green,#1F9D57) 14%,transparent)}
.ask-prop-rag.rag-amber{color:#8a5a12;background:color-mix(in srgb,var(--amber,#E0A106) 20%,transparent)}
.ask-prop-rag.rag-red{color:var(--red-dark,#B3261E);background:color-mix(in srgb,var(--red,#D64545) 14%,transparent)}
.ask-prop-rag.rag-on_hold{color:var(--muted,#5C6B80);background:color-mix(in srgb,var(--muted,#5C6B80) 14%,transparent)}
html[data-theme=dark] .ask-prop-rag.rag-amber{color:var(--amber,#E0A106)}
/* Tier 1 — follow-up drill-down chips */
.ask-fu{margin-top:12px;display:flex;flex-wrap:wrap;gap:6px}
.ask-fu-chip{font-size:12px;border:1px solid var(--rule-blue,#C8D2E3);border-radius:20px;padding:4px 11px;background:transparent;color:var(--ink-2,#3D5A85);cursor:pointer;text-align:left;transition:border-color .12s,color .12s}
.ask-fu-chip::before{content:"\21B3 ";color:var(--brass,#A9772A)}
.ask-fu-chip:hover{border-color:color-mix(in srgb,var(--brass,#A9772A) 45%,transparent);color:var(--navy,#152D49)}
/* Tier 2 — watch a question, and the watched-question list in the empty state */
.ask-watch{margin-top:11px;font-size:11.5px;background:none;border:none;padding:0;cursor:pointer;color:var(--muted,#5C6B80);font-weight:600;display:inline-block}
.ask-watch:hover,.ask-watch.on{color:var(--brass,#A9772A)}
/* Tier 4 — answer actions row (copy a composed deliverable; watch sits alongside) */
.ask-acts{display:flex;align-items:center;gap:14px;margin-top:11px;flex-wrap:wrap}
.ask-acts .ask-watch{margin-top:0}
.ask-copy,.ask-dl{font-size:11.5px;background:none;border:none;padding:0;cursor:pointer;color:var(--muted,#5C6B80);font-weight:600}
.ask-copy:hover,.ask-dl:hover{color:var(--brass,#A9772A)}
.ask-watch-list{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}
.ask-watch-hd{font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--brass,#A9772A);font-weight:700;margin-bottom:1px}
.ask-watch-item{position:relative;background:var(--panel,#F4F7FB);border:1px solid var(--rule,#E7ECF3);border-radius:11px;padding:9px 30px 9px 12px;cursor:pointer;transition:border-color .12s}
.ask-watch-item:hover{border-color:color-mix(in srgb,var(--brass,#A9772A) 40%,transparent)}
.ask-watch-q{font-size:12.5px;font-weight:600;color:var(--navy,#152D49)}
.ask-watch-a{font-size:11.5px;color:var(--muted,#5C6B80);margin-top:2px;line-height:1.4}
.ask-watch-x{position:absolute;top:7px;right:7px;width:20px;height:20px;border-radius:50%;border:none;background:none;color:var(--muted,#5C6B80);font-size:10px;line-height:1;cursor:pointer;opacity:0;transition:opacity .12s}
.ask-watch-item:hover .ask-watch-x{opacity:1}
.ask-watch-x:hover{color:var(--red,#9E2A2B)}
.ask-inrow{display:flex;gap:8px;align-items:center;padding:10px 12px;border-top:1px solid var(--rule,#E7ECF3)}
.ask-in{flex:1;min-width:0;height:38px;box-sizing:border-box;font-family:var(--font);font-size:13.5px;padding:0 12px;border:1px solid var(--rule-blue,#C8D2E3);border-radius:20px;background:var(--field);color:var(--ink)}
.ask-in:focus{outline:none;border-color:var(--navy,#152D49);box-shadow:0 0 0 3px color-mix(in srgb,var(--navy,#152D49) 12%,transparent)}
.ask-send{width:38px;height:38px;flex:none;border-radius:50%;border:none;background:var(--red,#9E2A2B);color:#fff;font-size:16px;line-height:1;cursor:pointer;transition:opacity .12s,filter .12s}
.ask-send:hover{filter:brightness(1.06)}
.ask-send:disabled{opacity:.5;cursor:default}
@media(max-width:640px){.ask-dock{right:12px;bottom:12px;left:12px;align-items:flex-end}.ask-panel{width:calc(100vw - 24px);height:min(560px,calc(100vh - 96px))}}
@media(prefers-reduced-motion:reduce){.ask-panel{animation:none}}
.fb-card>.fb-fields{overflow-y:auto}
.fb-fields{display:flex;flex-direction:column;gap:10px;margin:4px 0 12px;flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:2px;scroll-padding-top:6px}
.fb-field{border:1px solid var(--rule-blue,#C8D2E3);border-radius:11px;padding:11px 12px;background:var(--panel,#F6F8FC)}
.fb-gap{position:relative;height:14px;margin:-10px 0;flex:0 0 auto}
.fb-gap.on{height:auto;margin:0}
.fb-insbtn{position:absolute;inset:0;width:100%;border:0;background:transparent;cursor:pointer;display:flex;align-items:center;gap:8px;padding:0;opacity:0;transition:opacity .12s}
.fb-insbtn i{flex:1;height:1px;background:color-mix(in srgb,var(--brass,#A9772A) 50%,transparent)}
.fb-insbtn span{font-size:10.5px;font-weight:600;color:var(--brass,#A9772A);letter-spacing:.04em;white-space:nowrap}
.fb-gap:hover .fb-insbtn,.fb-insbtn:focus-visible{opacity:1}
@media (hover:none){.fb-insbtn{opacity:.5}}
.fb-instypes{display:flex;flex-wrap:wrap;gap:6px;align-items:center;padding:9px 10px;border:1px dashed color-mix(in srgb,var(--brass,#A9772A) 45%,transparent);border-radius:11px;background:color-mix(in srgb,var(--brass,#A9772A) 5%,var(--surface,#fff))}
.fb-fhead{display:flex;align-items:center;gap:9px;margin-bottom:9px}
.fb-sec{flex:1;font:inherit;font-size:12.5px;font-weight:600;color:var(--ink);background:transparent;border:0;border-bottom:1px dashed var(--rule-blue,#C8D2E3);padding:3px 1px;box-sizing:border-box}
.fb-sec:focus{outline:none;border-bottom-color:var(--ink)}
.fb-sec::placeholder{font-weight:400;color:var(--faint)}
.fb-type{flex-shrink:0;font-size:10px;letter-spacing:.03em;text-transform:uppercase;color:var(--muted);background:var(--surface);border:1px solid var(--rule,#E7ECF3);border-radius:5px;padding:2px 7px}
.fb-fmove{display:flex;align-items:center;gap:2px;flex-shrink:0}
.fb-fmove button{border:0;background:none;color:var(--muted);cursor:pointer;font-size:13px;line-height:1;padding:3px 6px;border-radius:5px}
.fb-fmove button:hover:not(:disabled){background:var(--surface);color:var(--ink)}
.fb-fmove button:disabled{opacity:.3;cursor:default}
.fb-fmove .fb-del:hover{color:var(--red)}
.fb-fbody{display:flex;flex-direction:column;gap:7px}
.fb-in{width:100%;font:inherit;font-size:12.5px;color:var(--ink);background:var(--surface);border:1px solid var(--rule-blue,#C8D2E3);border-radius:8px;padding:6px 9px;box-sizing:border-box}
.fb-in:focus{outline:none;border-color:var(--ink);box-shadow:0 0 0 3px color-mix(in srgb,var(--ink) 9%,transparent)}
textarea.fb-in{resize:vertical;line-height:1.5}
/* `.modal-card select` (0,1,1) BEATS a bare `.fb-narrow` (0,1,0) and forces width:100%, so this
   select's flex-basis resolved to the whole row and the prompt input beside it — flex:1, basis 0 —
   collapsed to a ~15px sliver. The fill-in box looked like it had no description field at all.
   `.fb-in.fb-narrow` is (0,2,0), which wins; `flex:0 0 auto` then stops it growing, the way
   `.fb-bind` already does for the binding picker. */
.fb-in.fb-narrow{width:auto;flex:0 0 auto;min-width:140px}
.fb-grid{display:flex;gap:8px;align-items:center}
.fb-grid .fb-in:first-child{flex:1}
.fb-bind{flex:0 0 auto;max-width:230px}
.fb-opts,.fb-mrows,.fb-prows{display:flex;flex-direction:column;gap:6px}
.fb-opt,.fb-mrow,.fb-prow{display:flex;align-items:center;gap:8px}
.fb-olab,.fb-mlab,.fb-plab{flex:1}
.fb-chk{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;color:var(--muted);white-space:nowrap;flex-shrink:0}
.fb-chk input{accent-color:var(--ink);width:14px;height:14px;margin:0}
.fb-orm{flex-shrink:0;color:var(--muted);cursor:pointer;font-size:12px;line-height:1;padding:3px 5px;border-radius:5px}
.fb-orm:hover{background:var(--surface);color:var(--red)}
.fb-addopt,.fb-addrow,.fb-addparty{align-self:flex-start}
.fb-addbar{display:flex;align-items:center;gap:8px;margin-bottom:4px}
.fb-addbar select{font:inherit;font-size:12.5px;color:var(--ink);background:var(--surface);border:1px solid var(--rule-blue,#C8D2E3);border-radius:8px;padding:6px 9px}
/* ethics/compliance go/no-go gate toggle (grant panel) */
.cblk{display:inline-flex;align-items:center;gap:4px;font-size:11px;color:var(--muted);cursor:pointer;white-space:nowrap}
.cblk input{margin:0}
/* Itemised budget cost-lines editor — grant panel + application budget (Travel & subsistence etc.) */
.cllist{margin-top:6px}
.clrow{display:flex;align-items:center;gap:8px;padding:5px 0;border-bottom:1px solid var(--rule,#E7ECF3)}
.clrow:last-child{border-bottom:0}
.cltag{flex:0 0 auto;font-size:10px;letter-spacing:.03em;text-transform:uppercase;color:var(--muted,#5C6B80);background:var(--panel,#F2F5FA);border-radius:5px;padding:2px 7px;white-space:nowrap}
.cllabel{flex:1;min-width:0;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.clamt{flex:0 0 auto;font-weight:600;font-size:13px;white-space:nowrap}
.cldel{border:0;background:none;color:var(--red);cursor:pointer;font-size:13px;line-height:1;padding:2px 5px;border-radius:5px}
.cldel:hover{background:var(--panel,#F2F5FA)}
.clsubs{display:flex;flex-wrap:wrap;gap:14px;margin-top:6px;font-size:12px}
.clsub b{margin-left:2px}
.cladd{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px;align-items:center}

/* ---- Thesis Map — trajectory chips (docs/thesis-map-scope.md). Status ramp: muted → blue
   (data/analysis/submitted) → amber (drafting/revision) → green (accepted); parked = struck. */
.tmap{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}
.tstudy{display:flex;flex-direction:column;align-items:flex-start;gap:3px;padding:8px 11px;max-width:250px;
  border:1px solid var(--rule,#E7ECF3);border-radius:10px;background:var(--field,#fff);cursor:pointer;text-align:left;
  transition:border-color var(--t2) var(--ease),box-shadow var(--t2) var(--ease)}
.tstudy:hover{border-color:var(--blue);box-shadow:0 1px 6px rgba(21,45,73,.08)}
.tstudy.ro{cursor:default}
.tstudy.ro:hover{border-color:var(--rule,#E7ECF3);box-shadow:none}
.ts-top{font-size:12.5px;font-weight:600;color:var(--navy);max-width:226px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ts-bot{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.tstat{font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;padding:1px 7px;border-radius:999px;background:var(--panel,#F2F5FA);color:var(--muted)}
.st-data .tstat,.st-analysis .tstat,.st-submitted .tstat{background:#EDF3FC;color:#2C4E80}
.st-drafting .tstat,.st-in_revision .tstat{background:#FFF4E0;color:#8A5A00}
.st-accepted .tstat{background:#E7F6EF;color:#1E9E78}
.st-parked{opacity:.62}
.st-parked .ts-top{text-decoration:line-through}
.tsub2{font-size:11px;color:var(--muted);max-width:210px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tstall{font-size:10.5px;color:#8A5A00;white-space:nowrap}
.tready{margin-top:8px;font-size:12px;color:var(--muted)}
.tready.ok{color:#1E9E78;font-weight:600}
html[data-theme=dark] .tstudy{background:transparent}
html[data-theme=dark] .st-data .tstat,html[data-theme=dark] .st-analysis .tstat,html[data-theme=dark] .st-submitted .tstat{background:rgba(111,151,216,.16);color:#9FC0F0}
html[data-theme=dark] .st-drafting .tstat,html[data-theme=dark] .st-in_revision .tstat{background:rgba(255,190,90,.14);color:#E8B45A}
html[data-theme=dark] .st-accepted .tstat{background:rgba(48,190,140,.15);color:#4ED0A0}
html[data-theme=dark] .tstall{color:#E8B45A}
html[data-theme=dark] .tready.ok{color:#4ED0A0}

/* Thesis-Map mini-strip on the Group page — one dot per study, ramp matches the .tstat colours */
.tdots{display:inline-flex;align-items:center;gap:3px;margin-right:2px}
.tdot{width:7px;height:7px;border-radius:50%;background:#C9D4E4}
.tdot.td-data,.tdot.td-analysis,.tdot.td-submitted{background:#6F97D8}
.tdot.td-drafting,.tdot.td-in_revision{background:#E8A33D}
.tdot.td-accepted{background:#1E9E78}
.tdot.td-parked{background:transparent;border:1px solid #C9D4E4}
.tdready{font-size:10px;color:#1E9E78;font-weight:700;margin-left:2px}
html[data-theme=dark] .tdot{background:rgba(255,255,255,.22)}
html[data-theme=dark] .tdot.td-data,html[data-theme=dark] .tdot.td-analysis,html[data-theme=dark] .tdot.td-submitted{background:#6F97D8}
html[data-theme=dark] .tdot.td-drafting,html[data-theme=dark] .tdot.td-in_revision{background:#E8B45A}
html[data-theme=dark] .tdot.td-accepted{background:#4ED0A0}
html[data-theme=dark] .tdot.td-parked{background:transparent;border-color:rgba(255,255,255,.3)}

/* "What's left" — degree requirements as facts: green tick when met, hollow dot when pending */
.reqtick{color:#1E9E78;font-weight:700;margin-right:2px}
.reqdot{color:var(--muted);margin-right:2px}
html[data-theme=dark] .reqtick{color:#4ED0A0}

/* My-work assignment rows link into the project workspace (members get the read-only view) */
.mw-link{cursor:pointer;text-decoration:underline;text-decoration-color:transparent;transition:text-decoration-color var(--t2) var(--ease)}
.mw-link:hover{text-decoration-color:var(--blue)}

/* Project Notes card — the standing facts; multi-line text kept verbatim */
.pj-note{white-space:pre-wrap;font-size:13px;color:var(--navy);line-height:1.55;margin:2px 0 0;overflow-wrap:break-word}

/* Timeline capacity strip — total per-bucket utilisation above a person's Schedule blocks.
   pointer-events off so create-click and block drag pass through; same ramp as Capacity mode. */
.capstrip{position:absolute;top:3px;height:11px;border-radius:6px;z-index:2;pointer-events:none;
  font:600 8.5px/11px var(--mono);color:#fff;text-align:center;overflow:hidden;letter-spacing:.02em}
.capstrip.idle{color:transparent}
.capstrip.over{box-shadow:inset 0 0 0 1px rgba(255,255,255,.55)}
/* name-cell window summary — the numbers behind the strip (avg booked · free hours · projects) */
.nsum{font-size:11px;color:var(--muted);margin-top:3px;font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nsum b{color:var(--navy);font-weight:700}
.nsum b.overload{color:var(--red)}
.namecell .nm{min-width:0}
html[data-theme=dark] .nsum b{color:#E8EEF7}

/* ===================== QMS / Quality hub ===================== */
/* Header uses the standard .pagehead (eyebrow + h1 + deck); the coverage ring sits beside it. */
#qms .qms-headrow{display:flex;justify-content:space-between;align-items:flex-start;gap:24px;flex-wrap:wrap}
#qms .qms-headrow .pagehead{flex:1 1 320px;min-width:0}
.qms-cov{display:flex;align-items:center;gap:12px;flex-shrink:0;padding-top:30px}
.qms-ring{--pct:0;width:60px;height:60px;border-radius:50%;display:grid;place-items:center;
  background:conic-gradient(var(--green) calc(var(--pct)*1%), var(--rule,#E7ECF3) 0);position:relative}
.qms-ring::after{content:"";position:absolute;inset:7px;border-radius:50%;background:var(--surface,#fff)}
.qms-ring span{position:relative;font-weight:700;font-size:14px;color:var(--navy)}
.qms-cov-tx{font-size:13px;color:var(--navy);line-height:1.35}
/* Page tabs use the standard .apptabs/.apptab — a single row that scrolls on narrow screens (never wraps
   under, and never shares its row with action buttons). */
.qms-apptabs,.dash-apptabs{margin:10px 0 18px;flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;mask-image:linear-gradient(90deg,#000 90%,transparent);-webkit-mask-image:linear-gradient(90deg,#000 90%,transparent)}
.qms-apptabs::-webkit-scrollbar,.dash-apptabs::-webkit-scrollbar{height:0}
.qms-apptabs .apptab,.dash-apptabs .apptab{white-space:nowrap;flex:0 0 auto}
.qms-pill-n{display:inline-grid;place-items:center;min-width:18px;height:18px;padding:0 5px;border-radius:9px;
  background:var(--red);color:#fff;font-size:11px;font-weight:700;margin-left:4px;vertical-align:middle}
/* Context actions live in their own toolbar inside the tab body — not in the tab row. */
.qms-toolbar{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 14px}
/* The register's filter row (All/Draft/…) is a secondary level: smaller, seated on the table's top edge —
   visually distinct from the page tabs above it. Single-line chips that scroll on narrow screens. */
#qms .list-tabbar{margin-top:2px;overflow-x:auto}
#qms .list-tabbar::-webkit-scrollbar{height:0}
#qms .list-tabbar .filttabs button{white-space:nowrap}
.qmono{font-family:var(--mono,ui-monospace,SFMono-Regular,Menlo,monospace);font-size:12px;color:var(--muted);letter-spacing:.02em}
.q-bad{color:var(--red-dark,#C4002A)}
.q-badge{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;
  padding:1px 6px;border-radius:5px;background:var(--panel);color:var(--muted);vertical-align:middle}
.q-badge.ok{background:color-mix(in srgb,var(--green) 15%,var(--panel));color:var(--green)}
.q-badge.bad{background:color-mix(in srgb,var(--red) 15%,var(--panel));color:var(--red-dark,#C4002A)}
.q-badge.muted{opacity:.7;text-decoration:line-through}
/* My reading cards */
.qms-sec-h{font-size:12px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--muted);margin:0 0 10px}
.qms-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px}
.qms-card{border:1px solid var(--rule,#E7ECF3);border-radius:12px;padding:14px;background:var(--surface,#fff);
  display:flex;flex-direction:column;gap:6px;transition:box-shadow var(--t1,.12s) var(--ease,ease),transform var(--t1,.12s) var(--ease,ease)}
.qms-card:hover{box-shadow:0 6px 18px rgba(21,45,73,.08);transform:translateY(-1px)}
.qms-card.is-overdue{border-color:color-mix(in srgb,var(--red) 40%,var(--rule,#E7ECF3))}
.qms-card-top{display:flex;justify-content:space-between;align-items:center}
.qms-card-title{font-weight:700;color:var(--navy);font-size:15px}
.qms-card-sum{color:var(--muted);font-size:13px;flex:1;min-height:18px}
.qms-card .qms-read{margin-top:4px;align-self:flex-start}
.qms-allclear{padding:26px;text-align:center;color:var(--green);font-weight:600;background:var(--panel);border-radius:12px}
/* tables */
.qtbl{width:100%;border-collapse:collapse;font-size:13.5px}
.qtbl th{text-align:left;font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);
  font-weight:700;padding:8px 10px;border-bottom:1.5px solid var(--rule,#E7ECF3)}
.qtbl td{padding:9px 10px;border-bottom:1px solid var(--rule,#E7ECF3);color:var(--navy);vertical-align:top}
.qtbl.qmini td{padding:5px 8px;font-size:12.5px;border-bottom:0}
.qreg .qrow{cursor:pointer;transition:background var(--t1,.12s) var(--ease,ease)}
.qreg .qrow:hover td{background:var(--panel)}
.qreg .qrow.is-ret td{opacity:.6}
.qreg .qgo{color:var(--ghost,#A7AFBE);text-align:right;font-size:18px}
.qcov{font-weight:700;font-variant-numeric:tabular-nums}
.qcov.ok{color:var(--green)} .qcov.bad{color:var(--red-dark,#C4002A)}
.qrev{font-variant-numeric:tabular-nums}
.qrev.overdue{color:var(--red-dark,#C4002A);font-weight:700}
.qrev.soon{color:var(--amber,#B7791F);font-weight:600}
/* reader + detail modals */
.qms-reader,.qms-detail,.qms-editor{width:min(720px,94vw);max-height:88vh;display:flex;flex-direction:column}
/* the detail card's action row holds up to nine buttons; at 720px Swedish "Förhandsgranska" left Close alone on a
   second row */
.qms-detail{width:min(780px,94vw)}
.qms-detail .modal-actions{row-gap:8px}
.qms-reader-h{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;border-bottom:1px solid var(--rule,#E7ECF3);padding-bottom:12px;margin-bottom:12px}
.qms-reader-h h3{margin:2px 0 0}
.modal-x{appearance:none;background:none;border:0;font-size:18px;color:var(--muted);cursor:pointer;line-height:1}
.qms-reader-body{overflow:auto;flex:1;padding:2px 2px 8px}
.qms-doc-body{color:var(--navy);line-height:1.6;font-size:14.5px}
.qms-doc-body h1,.qms-doc-body h2,.qms-doc-body h3{color:var(--navy)}
.qms-doc-body ul,.qms-doc-body ol{padding-left:22px}
.qms-file{padding:16px;background:var(--panel);border-radius:10px;text-align:center}
.qms-attest{border-top:1px solid var(--rule,#E7ECF3);padding-top:12px;margin-top:8px;display:flex;flex-direction:column;gap:8px}
.qms-check{display:flex;gap:9px;align-items:flex-start;font-size:13.5px;color:var(--navy);cursor:pointer}
.qms-check input{margin-top:2px;flex-shrink:0}
.qms-check input:disabled{cursor:not-allowed}
.qms-gate{font-size:12px;display:flex;align-items:center;gap:6px;color:var(--muted)}
.qms-gate::before{content:"↑";font-weight:700;color:var(--red)}
.qms-typed{max-width:320px}
/* Under a typed-name signature field (the sign ceremony, Quality read & sign): what the name must be,
   the moment it isn't. Reserves one line so the dialog doesn't jump as it appears. */
.sign-namehint{font-size:12px;line-height:1.4;min-height:17px;margin-top:5px;color:var(--muted)}
.qms-attest .sign-namehint{margin-top:-4px}
.sign-namehint.ok{color:var(--green)}
.sign-namehint.bad{color:var(--danger)}
.sign-namehint b{font-weight:600;color:inherit;white-space:nowrap}
/* a Sign button waiting for the tick and the right name has to LOOK unavailable — the app has no general
   disabled style, so it read as pressable and did nothing (the portal's sign card already fades) */
#scGo:disabled,#qrSign:disabled,#qdPublish:disabled{opacity:.45;cursor:not-allowed}
/* a reading view's title or a followed section takes the focus when the view replaces the dialog the focus
   was in (so a screen reader starts there); they are not controls, so no ring */
.qms-reader-h h3[tabindex="-1"]:focus,.qms-doc-body [tabindex="-1"]:focus{outline:none}
.qms-detail-grid{display:grid;grid-template-columns:1fr 1fr;gap:22px;overflow:auto}
@media(max-width:640px){.qms-detail-grid{grid-template-columns:1fr}}
.qms-aud{display:flex;flex-wrap:wrap;gap:6px}
.qaud{display:inline-flex;align-items:center;gap:5px;font-size:12.5px;background:var(--blue-soft,#ECF0F7);
  color:var(--navy);padding:3px 9px;border-radius:14px}
.qaud a{color:var(--muted);cursor:pointer;text-decoration:none;font-weight:700}
.qaud a:hover{color:var(--red)}
.qdanger{color:var(--red-dark,#C4002A)}
.qms-bk{display:flex;gap:16px;margin:4px 0 8px;font-size:13px;color:var(--navy)}
.qms-bk label{display:flex;gap:5px;align-items:center;cursor:pointer}
/* ---- authored controlled documents: section numbers + cross-references (reader, view, editor) ---- */
.qms-doc-body .secno{color:var(--muted);font-weight:600;font-variant-numeric:tabular-nums;margin-right:.45em}
.qms-doc-body h1,.qms-doc-body h2,.qms-doc-body h3,.qms-doc-body h4{scroll-margin-top:12px;border-radius:6px;transition:background-color .6s ease}
.qms-doc-body .qd-flash{background:color-mix(in srgb,var(--amber,#B7791F) 18%,transparent);
  box-shadow:0 0 0 6px color-mix(in srgb,var(--amber,#B7791F) 18%,transparent)}
.qms-doc-body a:not(.xref){color:var(--ink-2,#3D5A85);text-decoration:underline;text-underline-offset:2px}
.xref{color:var(--ink-2,#3D5A85);font-weight:600;text-decoration:underline;text-decoration-thickness:1px;
  text-underline-offset:3px;text-decoration-color:color-mix(in srgb,currentColor 45%,transparent);
  -webkit-box-decoration-break:clone;box-decoration-break:clone}
a.xref[data-xkey]{cursor:pointer}
a.xref[data-xkey]:hover{text-decoration-color:currentColor}
.xref.is-broken{color:var(--red-dark,#C4002A);text-decoration-style:wavy;text-decoration-color:var(--red,#E72D3F)}
.xref.is-warn{text-decoration-style:dashed}
.xref[data-flag]::after{content:attr(data-flag);display:inline-block;margin-left:5px;padding:0 6px;border-radius:5px;font-size:10.5px;
  font-weight:700;letter-spacing:.02em;line-height:1.6;vertical-align:1px;text-decoration:none;
  background:color-mix(in srgb,var(--amber,#B7791F) 16%,var(--panel));color:var(--amber,#B7791F)}
.xref.is-broken[data-flag]::after{background:color-mix(in srgb,var(--red) 14%,var(--panel));color:var(--red-dark,#C4002A)}
html[data-theme=dark] .xref,html[data-theme=dark] .qms-doc-body a:not(.xref){color:#9DB8E6}
html[data-theme=dark] .xref.is-broken{color:#FF8A95}
html[data-theme=dark] .xref.is-broken[data-flag]::after{color:#FF8A95}
/* Lab: the document is plum, so its links are a plum too (they were Company navy on plum text) —
   6.2:1 on white, 9.6:1 on the dark card. Scoped to the document surfaces; --ink-2 stays for chips. */
html[data-edition=lab] :is(.qms-doc-body,.qed-surface) :is(.xref:not(.is-broken),a:not(.xref)){color:#B0247A}
html[data-theme=dark][data-edition=lab] :is(.qms-doc-body,.qed-surface) :is(.xref:not(.is-broken),a:not(.xref)){color:#F0B3D6}
/* a typed {POL-099 §3} that names nothing, flagged in the editor as it is typed (a CSS highlight) */
::highlight(qed-broken){color:var(--red-dark,#C4002A);text-decoration:underline wavy var(--red,#E72D3F)}
html[data-theme=dark] ::highlight(qed-broken){color:#FF8A95}
.qd-edited{color:var(--amber-ink,#8A5E0F);font-weight:600}
.q-untitled{color:var(--muted);font-style:italic}
.qd-outline{list-style:none;margin:0;padding:0;font-size:13px;line-height:1.5}
.qd-outline li{--d:0;padding:2px 0 2px calc(var(--d,0) * 16px)}
.qd-outline a{color:var(--navy);cursor:pointer;text-decoration:none}
.qd-outline a:hover{text-decoration:underline}
.qd-outline .secno{color:var(--muted);font-weight:600;font-variant-numeric:tabular-nums;margin-right:.35em}
.qd-broken{margin-top:10px;padding:9px 12px;border-radius:9px;font-size:12.5px;color:var(--red-dark,#C4002A);
  background:color-mix(in srgb,var(--red) 8%,var(--panel));border:1px solid color-mix(in srgb,var(--red) 25%,transparent)}
.qd-broken ul{margin:4px 0 0;padding-left:18px}
html[data-theme=dark] .qd-broken{color:#FF8A95}
.qd-broken.qd-warn{color:var(--ink);background:color-mix(in srgb,var(--amber,#B7791F) 11%,var(--panel));
  border-color:color-mix(in srgb,var(--amber,#B7791F) 30%,transparent)}
html[data-theme=dark] .qd-broken.qd-warn{color:var(--ink)}
/* the editor: near full-screen, the text grows with what is written and the dialog scrolls */
#modal .qed-card{width:min(1120px,96vw);max-height:94vh;padding:0 0 0;display:block;overflow:auto;overscroll-behavior:contain}
.qed-card>*{margin-left:28px;margin-right:28px}
.qed-head{display:flex;align-items:center;gap:12px;padding-top:22px}
.qed-head h3{margin:0;flex:1}
.qed-note{margin-top:10px;margin-bottom:0;padding:9px 12px;border-radius:9px;font-size:12.5px;line-height:1.45;color:var(--ink);
  background:color-mix(in srgb,var(--amber,#B7791F) 11%,var(--panel));border:1px solid color-mix(in srgb,var(--amber,#B7791F) 30%,transparent)}
.qed-meta{display:grid;grid-template-columns:minmax(0,2.3fr) minmax(88px,.55fr) minmax(0,1.25fr) minmax(0,1.25fr);column-gap:12px}
.qed-f-sum{grid-column:1/-1}
.modal-card textarea.qed-sum{resize:none;overflow:hidden;min-height:41px;font-size:14px;line-height:1.45;padding:10px 12px}
.qed-kind{display:flex;flex-wrap:wrap;gap:6px 18px;margin-top:14px;margin-bottom:10px}
.modal-card label.qed-radio,.modal-card label.qed-num{display:inline-flex;align-items:center;gap:7px;margin:0;font-size:13px;font-weight:500;
  letter-spacing:0;text-transform:none;color:var(--ink);cursor:pointer}
.qed{border:1px solid var(--field-line,var(--rule-blue));border-radius:12px;background:var(--field);position:relative}
.qed:focus-within{border-color:var(--navy);box-shadow:0 0 0 3px color-mix(in srgb,var(--navy) 11%,transparent)}
.qed-bar{position:sticky;top:0;z-index:3;display:flex;flex-wrap:wrap;align-items:center;gap:3px;padding:6px 8px;
  background:var(--field);border-bottom:1px solid var(--rule);border-radius:12px 12px 0 0}
.qed-bar .spacer{flex:1}
.qed-sep{width:1px;height:20px;background:var(--rule);margin:0 5px}
.qed-btn{appearance:none;display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:32px;padding:0 7px;border:0;
  border-radius:7px;background:transparent;color:var(--ink);font:inherit;font-size:14.5px;cursor:pointer;
  transition:background-color var(--t1,.12s) var(--ease,ease)}
.qed-btn svg{width:18px;height:18px}
.qed-btn:hover{background:var(--panel)}
.qed-btn.on{background:color-mix(in srgb,var(--navy) 12%,transparent);color:var(--navy)}
.qed-btn b,.qed-btn i{font-family:var(--font);line-height:1}
.qed-brace{font-family:var(--mono);font-size:12.5px;font-weight:600;letter-spacing:-.02em}
.modal-card select.qed-block{width:auto;height:32px;font-size:13px;padding:0 28px 0 9px;border-radius:7px;border-color:transparent;background-color:transparent}
.modal-card select.qed-block:hover{background-color:var(--panel)}
.qed-bar.is-source .qed-btn:not([data-cmd="source"]),.qed-bar.is-source .qed-block,.qed-bar.is-source .qed-num{opacity:.35;pointer-events:none}
.qed-num{margin-right:4px !important}
.qed-surface{min-height:min(46vh,420px);padding:18px 26px 30px;outline:none;position:relative;background:var(--surface);border-radius:0 0 12px 12px;
  overflow-wrap:anywhere;caret-color:var(--navy)}
.qed-surface>:first-child{margin-top:0}
.qed-surface.is-empty::before{content:attr(data-ph);position:absolute;left:26px;top:18px;right:26px;color:var(--faint);pointer-events:none}
.qed-surface.is-numbered [data-secno]::before{content:attr(data-secno);color:var(--muted);font-weight:600;
  font-variant-numeric:tabular-nums;margin-right:.45em}
.qed-surface a.xref{background:color-mix(in srgb,var(--ink-2,#3D5A85) 9%,transparent);border-radius:5px;padding:0 3px;cursor:default;user-select:all;
  -webkit-box-decoration-break:slice;box-decoration-break:slice}
.xref[data-flag]::after{white-space:nowrap}
/* a Word table's cells carry paragraphs; their margins made every row about 60px tall */
.qed-surface td>p,.qed-surface th>p,.qms-doc-body td>p,.qms-doc-body th>p{margin:0}
.qed-surface table,.qms-doc-body table{border-collapse:collapse;margin:8px 0}
.qed-surface td,.qed-surface th,.qms-doc-body td,.qms-doc-body th{border:1px solid var(--rule);padding:5px 8px;vertical-align:top}
/* the author's own table header, not the app's column-label style (uppercase 10px) that th picks up */
.qms-doc-body th{text-align:left;text-transform:none;letter-spacing:normal;font-size:inherit;font-weight:700;color:var(--navy);background:var(--panel)}
.qms-doc-body blockquote{margin:8px 0;padding:2px 0 2px 14px;border-left:3px solid var(--rule);color:var(--muted)}
.modal-card textarea.qed-source{display:block;width:100%;min-height:min(46vh,420px);border:0;border-radius:0 0 12px 12px;resize:none;
  font-size:12px;line-height:1.55;padding:16px 20px;background:var(--surface)}
.modal-card textarea.qed-source:focus{box-shadow:none}
.qed-file{padding:6px 0 4px;display:flex;flex-direction:column;gap:6px}
.qed-foot{position:sticky;bottom:0;z-index:3;margin:14px 0 0 !important;padding:12px 28px 16px;background:var(--surface);
  border-top:1px solid var(--rule)}
.qed-status{font-size:12.5px;color:var(--muted);font-variant-numeric:tabular-nums}
.qed-status[data-state=failed],.qed-status[data-state=stuck]{color:var(--red-dark,#C4002A);font-weight:600}
html[data-theme=dark] .qed-status[data-state=failed],html[data-theme=dark] .qed-status[data-state=stuck]{color:#FF8A95}
.qed-ac{position:fixed;z-index:120;width:min(420px,92vw);max-height:min(320px,50vh);overflow:auto;padding:5px;
  background:var(--surface);border:1px solid var(--rule-blue,#C8D2E3);border-radius:11px;font-size:13px;
  box-shadow:0 12px 34px -8px rgba(21,45,73,.35)}
.qed-ac-h{padding:7px 9px 3px;font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--faint)}
.qed-ac-i{display:flex;align-items:baseline;gap:6px;padding:6px 9px;border-radius:7px;color:var(--ink);cursor:pointer}
.qed-ac-i .qmono{flex:none;font-size:11.5px}
.qed-ac-i:hover{background:var(--panel)}
/* the option Enter will pick: a bar in the ink colour (13.9:1 in both themes), not only a wash that was
   1.1:1 against the menu */
.qed-ac-i.on{background:var(--blue-soft);box-shadow:inset 3px 0 0 var(--navy)}
.qed-ac-more{margin-left:auto;color:var(--faint);font-weight:700}
.qed-ac-empty{padding:9px;color:var(--muted)}
@media (max-width:760px){
  .qed-card>*{margin-left:16px;margin-right:16px}
  .qed-foot{padding-left:16px;padding-right:16px}
  .qed-meta{grid-template-columns:minmax(0,1fr) 92px}
  .qed-meta .qed-f:nth-child(3),.qed-meta .qed-f:nth-child(4){grid-column:1/-1}
  .qed-surface{padding:14px 14px 24px}
  .qed-surface.is-empty::before{left:14px;top:14px}
}
/* on a phone the toolbar wraps, and a separator left at the end of a row read as a stray mark */
@media (max-width:480px){.qed-sep{display:none}}
/* matrix */
.qms-matrix-wrap{overflow-x:auto;border:1px solid var(--rule,#E7ECF3);border-radius:10px}
.qmatrix{border-collapse:collapse;font-size:12.5px;min-width:100%}
.qmatrix th,.qmatrix td{border:1px solid var(--rule,#E7ECF3);padding:6px 8px;text-align:center}
.qmatrix th{background:var(--panel);position:sticky;top:0}
.qm{display:inline-block;font-weight:700}
.qm.ok{color:var(--green)} .qm.bad{color:var(--red-dark,#C4002A)} .qm.pend{color:var(--amber,#B7791F)} .qm.na{color:var(--ghost,#C3CAD6)}
.qms-legend{margin-top:10px;font-size:12.5px;color:var(--muted)}
.qms-legend .qm{margin:0 2px}
/* transposed training matrix — documents as rows (sticky code+description), people as rotated columns */
.qmatrix-t .qm-doc{text-align:left;position:sticky;left:0;background:var(--surface,#fff);white-space:nowrap;min-width:172px}
.qmatrix-t thead .qm-doc{background:var(--panel);z-index:2}
.qmatrix-t .qm-doc .qmono{display:block;font-size:11px;color:var(--muted)}
.qmatrix-t .qm-doc .qm-doc-t{display:block;font-weight:600;color:var(--navy);font-size:12px;max-width:250px;overflow:hidden;text-overflow:ellipsis}
.qmatrix-t th.qm-person{vertical-align:bottom;padding:8px 6px;min-width:58px;max-width:84px}
.qmatrix-t th.qm-person span{display:block;line-height:1.22;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.qmatrix-t th.qm-person .qmp-f{font-weight:600;font-size:11px;color:var(--navy)}
.qmatrix-t th.qm-person .qmp-l{font-weight:500;font-size:11px;color:var(--muted)}
.qmatrix-t .qmx-grp .qm-doc{background:var(--panel);font-weight:700;font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
.qmatrix-t .qmx-grp td{background:var(--panel)}
.qmatrix-t .qmx-row{cursor:pointer}
.qmatrix-t .qmx-row:hover td{background:color-mix(in srgb,var(--panel) 55%,transparent)}
.qmatrix-t .qmx-row:hover .qm-doc{background:color-mix(in srgb,var(--panel) 55%,var(--surface,#fff))}
.qmatrix-t .qm-cov{color:var(--muted);font-size:11.5px;white-space:nowrap;font-variant-numeric:tabular-nums}
.qmx-ctl{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;color:var(--muted)}
.qmx-ctl select{height:30px;border:1px solid var(--rule-blue);border-radius:8px;background:var(--field);font-family:var(--font);font-size:12.5px;padding:0 8px;color:var(--ink)}
/* new-document kind chooser */
.qms-choose{display:flex;flex-direction:column;gap:10px}
.qms-choice{display:flex;flex-direction:column;gap:3px;text-align:left;padding:14px 16px;border:1px solid var(--rule,#E7ECF3);border-radius:12px;background:var(--card,#fff);cursor:pointer;font:inherit;transition:border-color .12s ease,transform .12s ease}
.qms-choice:hover{border-color:var(--navy);transform:translateY(-1px)}
.qms-choice b{font-size:14px;color:var(--navy)}
.qms-choice span{font-size:12px;color:var(--muted);line-height:1.4}

/* QMS P3/P4: scheduled badge + team-overview training pill */
.q-badge.sched{background:color-mix(in srgb,var(--amber,#B7791F) 15%,var(--panel));color:var(--amber,#B7791F)}
.qtrain{display:inline-block;font-size:11.5px;font-weight:600;padding:2px 8px;border-radius:12px;white-space:nowrap}
.qtrain.ok{color:var(--green);background:color-mix(in srgb,var(--green) 12%,transparent)}
.qtrain.pend{color:var(--amber,#B7791F);background:color-mix(in srgb,var(--amber,#B7791F) 14%,transparent)}
.qtrain.bad{color:var(--red-dark,#C4002A);background:color-mix(in srgb,var(--red) 14%,transparent)}

/* ---- ⌘K command palette — a top-aligned modal variant + its own compact list chrome ---- */
#modal.modal-top{align-items:flex-start;padding-top:12vh}
.cmdk-card{width:560px;max-width:92vw;padding:0!important;overflow:hidden}
.cmdk-in{width:100%;border:0;border-bottom:1px solid var(--rule,#E7ECF3);border-radius:0;padding:15px 18px;font-size:14.5px;background:transparent;outline:none}
.cmdk-list{max-height:min(46vh,420px);overflow-y:auto;padding:6px 6px 8px}
.cmdk-sec{font-size:10px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3,#8595AB);padding:10px 12px 4px}
.cmdk-item{padding:8px 12px;border-radius:8px;font-size:13.5px;cursor:pointer;display:flex;align-items:baseline;gap:8px}
.cmdk-item.on{background:color-mix(in srgb,var(--red) 8%,var(--panel,#fff))}
.cmdk-hint{font-size:11.5px;color:var(--ink-3,#8595AB);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cmdk-ask{color:var(--navy,#152D49);font-weight:600}
.cmdk-ask-mk{display:inline-flex;align-self:center;flex:none}
.cmdk-ask-mk .lemmamark{width:15px;height:15px;fill:var(--brass,#A9772A)}
.cmdk-foot{display:flex;gap:16px;padding:9px 16px;border-top:1px solid var(--rule,#E7ECF3);font-size:10.5px;color:var(--ink-3,#8595AB)}

/* ---- Profile hero (design review 2026-07-16): photo-forward, human, self-updatable ---- */
.pf-av{position:relative;border:0;padding:0;background:none;border-radius:50%;flex:0 0 auto;cursor:default}
button.pf-av{cursor:pointer}
.pf-av-hint{position:absolute;inset:auto 0 -4px 0;text-align:center;font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:#fff;background:rgba(21,45,73,.72);border-radius:20px;padding:2px 0;opacity:0;transition:opacity var(--t1) var(--ease)}
.pf-av:hover .pf-av-hint{opacity:1}
.pf-av-hint.always{opacity:.92;background:var(--brass,#A9772A)}
.pf-pronouns{font-size:12.5px;font-weight:500;color:var(--ink-3,#8595AB);margin-left:6px}
.pf-bio{font-size:13.5px;color:var(--ink-2,#3D5A85);margin:5px 0 2px;max-width:640px}
.pf-chips{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin-top:8px}
.pf-chips-lbl{font-size:9.5px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--brass,#A9772A);margin-right:2px}
.pf-chip{font-size:11.5px;font-weight:600;padding:2.5px 10px;border-radius:20px;background:color-mix(in srgb,var(--brass,#A9772A) 9%,var(--panel,#fff));color:#7a5a22;border:1px solid color-mix(in srgb,var(--brass,#A9772A) 25%,transparent)}
.pf-chip-add{background:transparent;border-style:dashed;color:var(--ink-3,#8595AB);cursor:pointer}
.pf-hint{display:flex;gap:10px;align-items:center;font-size:12.5px;color:var(--ink-2,#3D5A85);background:color-mix(in srgb,var(--brass,#A9772A) 7%,var(--panel,#fff));border:1px solid color-mix(in srgb,var(--brass,#A9772A) 22%,transparent);border-radius:10px;padding:8px 12px;margin:0 0 14px}
.wn-card{margin:0 0 16px}
.wn-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.wn-head h3{margin:0}
.wn-next{font-size:12px;color:var(--ink-3,#8595AB);margin-left:auto}
.wn-body{display:flex;gap:18px;align-items:flex-start;flex-wrap:wrap}
.wn-projs{display:flex;gap:8px;flex-wrap:wrap;flex:1;min-width:260px}
.wn-proj{display:flex;flex-direction:column;gap:2px;align-items:flex-start;border:1px solid var(--rule,#E7ECF3);background:var(--panel,#fff);border-radius:10px;padding:8px 12px;font-size:12.5px;cursor:pointer;text-align:left;transition:border-color var(--t1) var(--ease),background var(--t1) var(--ease)}
.wn-proj:hover{border-color:color-mix(in srgb,var(--brass,#A9772A) 45%,transparent);background:color-mix(in srgb,var(--brass,#A9772A) 4%,var(--panel,#fff))}
.wn-top{display:flex;gap:8px;align-items:center;min-width:0;max-width:100%}
.wn-sub{font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}

/* ---- People directory cards ---- */
.dir-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:12px;margin-top:12px}
.dir-card{display:flex;flex-direction:column;align-items:center;text-align:center;gap:3px;border:1px solid var(--card-line,#E7ECF3);background:var(--panel,#fff);border-radius:14px;padding:20px 14px 16px;cursor:pointer;transition:transform var(--t1) var(--ease),box-shadow var(--t1) var(--ease)}
.dir-card:hover{transform:translateY(-2px);box-shadow:0 6px 18px rgba(21,45,73,.10)}
.dir-av{width:64px;height:64px;border-radius:50%;object-fit:cover;margin-bottom:6px}
.dir-name{font-weight:700;font-size:14px}
.dir-title{font-size:12px;color:var(--ink-3,#8595AB);min-height:15px}
.dir-bio{font-size:11.5px;color:var(--ink-2,#3D5A85);margin-top:4px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.dir-chips{display:flex;gap:4px;flex-wrap:wrap;justify-content:center;margin-top:7px}
.dir-chips .pf-chip{font-size:10.5px;padding:1.5px 8px}
.dir-foot{font-size:11px;color:var(--ink-3,#8595AB);margin-top:8px}

/* Finance tighten (2026-07-16): tile lift, the clickable Awaiting tile, the aging strip */
.fin-tile{transition:transform var(--t1) var(--ease),box-shadow var(--t1) var(--ease)}
.fin-tile:hover{transform:translateY(-1px)}
.fin-tile-link{cursor:pointer}
.fin-tile-link:hover{box-shadow:0 4px 14px rgba(21,45,73,.09)}
.fin-aging{background:var(--surface);border:1px solid var(--card-line);border-radius:12px;padding:12px 14px;margin:-6px 0 18px;transition:box-shadow var(--t2) var(--ease)}
.fin-aging.flash{box-shadow:0 0 0 2px var(--brass,#A9772A)}
.fin-aging-hd{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:6px}
.fin-aging-row{display:flex;gap:12px;align-items:center;padding:7px 2px;border-top:1px solid var(--rule,#E7ECF3);font-size:12.5px}
.fin-aging-row b{min-width:140px}
.fin-aging-row .fa-amt{font-variant-numeric:tabular-nums;font-weight:650;margin-left:auto}
.fin-aging-row .fa-age{font-size:11.5px;color:var(--muted);min-width:170px;text-align:right}
.fin-aging-row.over .fa-age{color:var(--red-dark,#C4002A)}
.fin-aging-row.over b::after{content:" •";color:var(--red)}

/* ---- Quality on mobile (2026-07-16): wide tables scroll INSIDE their card — the page never
   scrolls sideways. The tab row already scrolls (.qms-apptabs). ---- */
@media (max-width:700px){
  .qtbl{display:block;overflow-x:auto;-webkit-overflow-scrolling:touch;white-space:nowrap}
  .qtbl td{white-space:normal;min-width:90px}
  .qtbl td:first-child{white-space:nowrap}
  .qms-headrow{flex-wrap:wrap}
  .qms-toolbar .spacer{flex:1 1 100%!important}
  #qmsBody input[placeholder^="Search"]{max-width:100%!important;flex:1 1 100%}
}

/* ---- Group tables on mobile (2026-07-16): the 8-column overview/metrics tables become stacked
   cards under 700px — same rows, same click-through, no sideways squinting. ---- */
.gm-cards{display:none}
.gm-card{border:1px solid var(--rule,#E7ECF3);border-radius:10px;padding:10px 12px;display:flex;flex-direction:column;gap:5px;cursor:pointer;background:var(--surface,#fff)}
@media (max-width:700px){
  .gm-tblwrap{display:none}
  .gm-cards{display:flex;flex-direction:column;gap:8px}
}

/* group pages ≤700px: the 1:1 queue and member rows wrap instead of squeezing */
@media (max-width:700px){
  .gprow .gp-top{flex-wrap:wrap}
  .gp-projs{max-width:100%}
  .gp-projs .cchip{max-width:100%;overflow:hidden;text-overflow:ellipsis}
}

/* ---- The Friday wrap + the time-off month export ---- */
.fri-wrap{display:flex;gap:12px;align-items:center;flex-wrap:wrap;background:color-mix(in srgb,var(--brass,#A9772A) 6%,var(--surface,#fff));border:1px solid color-mix(in srgb,var(--brass,#A9772A) 22%,transparent);border-radius:12px;padding:10px 14px;margin:0 0 16px;font-size:13px}
.fw-eyebrow{font-size:10px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--brass,#A9772A);white-space:nowrap}
.fw-items{display:flex;flex-wrap:wrap;gap:6px 8px;flex:1;min-width:0;align-items:center;color:var(--navy,#152D49)}
.fw-item{display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background:var(--surface,#fff);border:1px solid color-mix(in srgb,var(--brass,#A9772A) 20%,transparent);border-radius:999px;padding:3px 11px;line-height:1.5}
.fw-note{flex-basis:100%;font-size:12px;padding-left:2px}
@media (max-width:700px){
  .fri-wrap{row-gap:8px}
  .fw-eyebrow{flex:1}
  .fw-items{flex-basis:100%;order:3}
  .fw-note{order:4}
  .fw-item{white-space:normal;overflow:visible;text-overflow:clip;border-radius:11px}
}
.fri-wrap b{font-variant-numeric:tabular-nums}

/* the Friday wrap is a one-line strip — span the whole home-top grid row instead of pairing as a
   column with the (tall) attention card, which left a dead gap beneath it */
#fridayWrap{grid-column:1/-1}
#fridayWrap .fri-wrap{margin:0}

/* ---- Time off month timeline: people × days ---- */
.tom-head{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:10px}
.tom-scroll{overflow-x:auto;flex:1;min-width:0}
.tom-grid{display:grid;gap:1px;align-items:stretch;min-width:640px}
.tom-d{font-size:9.5px;text-align:center;color:var(--ink-3,#8595AB);padding:2px 0;line-height:1.15;font-variant-numeric:tabular-nums}
.tom-d small{display:block;font-size:8px;letter-spacing:.03em}
.tom-wrap{display:flex;align-items:flex-start}
.tom-names{flex:0 0 150px;min-width:0;padding-right:8px;border-right:1px solid var(--rule,#E7ECF3);margin-right:6px}
.tom-hd{height:31px}
.tom-name{font-size:12px;font-weight:600;color:var(--navy,#152D49);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:23px;line-height:22px}
.tom-d{height:30px;box-sizing:border-box}
.tom-c{height:22px;border-radius:3px;background:color-mix(in srgb,var(--rule,#E7ECF3) 45%,var(--surface,#fff));position:relative}
.tom-c.we,.tom-d.we{background:color-mix(in srgb,var(--rule,#E7ECF3) 85%,var(--surface,#fff))}
.tom-c.hol{background:color-mix(in srgb,var(--brass,#A9772A) 14%,var(--surface,#fff))}
.tom-d.hol{color:var(--brass,#A9772A);font-weight:700}
.tom-c i{position:absolute;inset:2px;border-radius:2px;background:var(--lc,#6F97D8)}
.tom-c.pend i{opacity:.45;border:1px dashed var(--lc,#6F97D8);background:color-mix(in srgb,var(--lc,#6F97D8) 30%,transparent)}
.tom-legend{display:flex;gap:14px;flex-wrap:wrap;margin-top:10px;font-size:11.5px;color:var(--ink-2,#3D5A85)}
/* L-01: a project's pass-through costs */
.pj-cost{display:flex;gap:12px;align-items:baseline}
.pj-cost .pjc-date{flex:none;width:92px;font-variant-numeric:tabular-nums;color:var(--muted)}
.pj-cost .pjc-what{flex:1;min-width:0}
.pj-cost .pjc-ref{flex:none;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pj-cost .pjc-amt{flex:none;font-variant-numeric:tabular-nums}
@media (max-width:620px){.pj-cost{flex-wrap:wrap}.pj-cost .pjc-ref{max-width:none}}
/* L-02: the payroll hand-off panel — what is ready, and every gap by name */
.ph-ok,.ph-gap{background:var(--panel);border:1px solid var(--rule);border-radius:9px;padding:9px 12px;margin:0 0 10px;font-size:13px;color:var(--ink)}
.ph-gap{border-color:var(--amber,#E9A23B)}
.ph-gap ul{margin:6px 0 4px 18px;padding:0}
.ph-gap li{margin:2px 0}
.ph-last{font-size:12.5px;margin:4px 0 0}
.tom-lg{display:inline-flex;gap:5px;align-items:center}
.tom-lg i{width:10px;height:10px;border-radius:2px;display:inline-block}

/* Right-now chips stay chip-sized with many/long projects; the sticky timeline name column gets
   a covering edge so day columns disappear cleanly under it instead of peeking through */
.wn-projs{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr))}
.wn-proj{max-width:none;justify-content:flex-start;min-width:0}
.wn-nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;text-align:left}
.wn-extra{display:none}
.wn-more{color:var(--ink-3,#8595AB);border-style:dashed}

/* profile fact cards: long values (e.g. a long job title on Capacity & employment) wrap
   right-aligned instead of overflowing the card */
.profcard .lrow b{min-width:0;max-width:68%;text-align:right;overflow-wrap:anywhere}

/* today, marked in brass on the month view — the app's today-marker motif */
.tom-d.td{color:var(--brass,#A9772A)}
.tom-d.td span{display:inline-block;min-width:15px;line-height:15px;border-radius:8px;background:var(--brass,#A9772A);color:#fff;font-weight:700}
.tom-c.td{box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--brass,#A9772A) 50%,transparent)}

/* editable time-off category cells: hover affordance + the adjustment dot */
.tocell{cursor:pointer}
.tocell:hover{background:color-mix(in srgb,var(--brass,#A9772A) 8%,transparent);border-radius:6px}
.toadj{color:var(--brass,#A9772A);font-weight:700;margin-left:2px}

/* ---------------- mobile bottom bar (≤820px) — thumb-reach primary nav; edition chrome via --nav-ink ---------------- */
.mbar{display:none}
@media(max-width:820px){
  .mbar{position:fixed;left:0;right:0;bottom:0;z-index:39;display:flex;align-items:stretch;justify-content:space-around;
    background:var(--nav-ink,#152D49);padding:3px 6px calc(3px + env(safe-area-inset-bottom));
    box-shadow:0 -1px 0 rgba(255,255,255,.07),0 -8px 24px rgba(10,12,24,.20)}
  /* the kit lifts #toast at ≤700px for ITS bar; Lemma's bar shows at ≤820px, so between 701 and
     820px the toast landed exactly on the nav — the defect the kit's own lift comment describes */
  #toast{bottom:calc(70px + env(safe-area-inset-bottom,0px))}
  .mbar-btn{flex:1;max-width:96px;display:flex;flex-direction:column;align-items:center;gap:3px;border:0;background:none;cursor:pointer;
    color:rgba(255,255,255,.62);font-family:var(--font);font-size:9.5px;font-weight:600;letter-spacing:.04em;padding:8px 2px 5px;position:relative;border-radius:10px}
  .mbar-btn svg{width:21px;height:21px}
  .mbar-btn.on{color:#fff}
  .mbar-btn.on::before{content:"";position:absolute;top:0;left:30%;right:30%;height:2px;border-radius:2px;background:var(--brass,#A9772A)}
  .mbar-badge{position:absolute;top:4px;right:calc(50% - 19px);min-width:15px;height:15px;border-radius:8px;background:var(--red,#e72d3f);color:#fff;
    font-size:9px;font-weight:700;font-style:normal;display:flex;align-items:center;justify-content:center;padding:0 4px}
  /* The footer (same --nav-ink chrome) carries the bar clearance itself — its navy extends UNDER the
     fixed bar, so footer + bar always read as ONE chrome block with no light gap, regardless of the
     bar's exact height, safe-area inset, or font scaling. Body padding would only match by luck. */
  body{padding-bottom:0}
  footer{padding-bottom:calc(18px + 58px + env(safe-area-inset-bottom));margin-top:32px}
  .ask-dock{bottom:calc(64px + env(safe-area-inset-bottom))}
  .ask-panel{height:min(560px,calc(100vh - 150px))}
  /* On a phone the bubble collapses to the mark alone — a round FAB above the bottom bar, so it
     never crowds a narrow screen. The ✕ goes with it: it only ever appeared on hover, which a
     touch screen has no equivalent for, and Settings → Preferences is the real off switch. */
  .ask-bubble{width:48px;height:48px;padding:0;gap:0;justify-content:center;border-radius:50%}
  .ask-bubble-lbl,.ask-bubble-x{display:none}
  .ask-bubble-mark .lemmamark{width:27px;height:27px}
  .ask-bubble-badge{position:absolute;top:-3px;right:-3px;border:2px solid var(--surface,#fff)}
}

/* ---------------- settings page — tabbed groups (v0.414) ---------------- */
.settings-tabs{margin:2px 0 16px}
.setgroup[hidden]{display:none}

/* ---------------- projects toolbar pairs + list health dot (v0.415) ---------------- */
.ctl-pair{display:inline-flex;align-items:center;gap:8px;white-space:nowrap}
.ptable .pn-cell .hdot{margin-left:6px}
.pcard h4 .hdot{margin-left:2px;vertical-align:middle}

/* Connected apps (L2 service principals) — Settings → Organisation */
.sp-list{display:flex;flex-direction:column;gap:8px;margin-top:4px}
.sp-row{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;border:1px solid var(--rule);border-radius:10px;background:var(--card)}
.sp-row.is-dead{opacity:.55}
.sp-main{flex:1;min-width:0}
.sp-name{font-size:13px;font-weight:600;color:var(--navy)}
.sp-dead{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--red);
  background:color-mix(in srgb,var(--red) 12%,transparent);padding:1px 6px;border-radius:999px;margin-left:4px}
.sp-meta{font-size:11.5px;color:var(--muted);margin-top:2px}
.sp-meta code{font-size:11px}
.sp-scopes{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px}
.sp-scope{font-size:10px;font-family:var(--mono);padding:1px 6px;border-radius:4px;
  background:color-mix(in srgb,var(--muted) 14%,transparent);color:var(--muted)}
.sp-scopelist{display:flex;flex-direction:column;gap:2px;max-height:230px;overflow:auto;
  border:1px solid var(--rule);border-radius:9px;padding:8px 10px;margin-top:4px}
label.sp-scopechk{font-size:12px;padding:2px 0}
.sp-scopechk code{font-size:11.5px}
/* the show-once secret */
.sp-warn{font-size:12.5px;line-height:1.5;padding:10px 12px;border-radius:9px;margin:2px 0 12px;
  border:1px solid color-mix(in srgb,var(--red) 35%,transparent);
  background:color-mix(in srgb,var(--red) 7%,transparent);color:var(--ink)}
.sp-copy{display:flex;align-items:center;gap:8px;padding:8px 10px;border:1px solid var(--rule);
  border-radius:9px;background:var(--field)}
.sp-copy code{flex:1;min-width:0;font-size:12px;word-break:break-all}
.sp-copy .btn{flex:none}

/* minutes from a transcript — the review list, where a proposal becomes a record.
   The row is a <label> so the whole thing is a hit target, which puts it in reach of the form-label
   rule above (10px, uppercase, faint). That styling is for the caption over a field, not for the
   content of a row, so it is turned off here — and specifically enough to win. */
.modal-card label.tr-row{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:9px 11px;
  margin:6px 0 0;border:1px solid var(--rule);border-radius:9px;background:var(--card);
  font-size:12.5px;font-weight:400;text-transform:none;letter-spacing:normal;color:var(--ink);
  cursor:pointer}
.tr-row:hover{border-color:var(--rule-blue)}
.tr-row input[type=checkbox]{margin:0;accent-color:var(--navy);flex:none}
.tr-t{flex:1;min-width:0;color:var(--navy);font-weight:600;font-size:13px}
/* the detail the row carries into the editor — reviewable only if it is visible */
.tr-n{flex-basis:100%;min-width:0;margin-left:26px;color:var(--muted);font-size:12px;line-height:1.45}
/* who spoke: chips, because a name is short and a room is a set, not a list */
.tr-who{display:flex;flex-wrap:wrap;gap:6px;margin:2px 0 4px}
.modal-card label.tr-chip{display:inline-flex;align-items:center;gap:7px;padding:5px 10px 5px 8px;
  border:1px solid var(--rule);border-radius:999px;background:var(--card);margin:0;
  font-size:12.5px;font-weight:400;text-transform:none;letter-spacing:normal;color:var(--ink);
  cursor:pointer;max-width:100%}
.tr-chip:hover{border-color:var(--rule-blue)}
.tr-chip input[type=checkbox]{margin:0;accent-color:var(--navy);flex:none}
.tr-chip:has(input:not(:checked)){opacity:.5}
.tr-cn{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tr-turns{flex:none;font-size:10.5px;font-family:var(--mono);color:var(--muted);
  background:color-mix(in srgb,var(--muted) 13%,transparent);border-radius:999px;padding:1px 6px}
/* the paste screen's footer: the file picker, and what it is about to read */
.tr-foot{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;margin-top:8px}
.tr-foot .lmuted{font-size:12px}
.tr-cost{font-size:11.5px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ============ polish pass (2026-07-31): dark-mode fidelity + rhythm ============ */
/* the weekly brief: the when-label belongs to the ITEM — top-aligned with its first line, not
   floating mid-paragraph when a title wraps to two */
.mw-row{align-items:flex-start}
.mw-when{padding-top:2px}
/* attention actions keep their outline-pill character in dark (they were solid grey slabs) */
html[data-theme=dark] .att-act{background:transparent;border-color:color-mix(in srgb,var(--brass) 45%,transparent);color:var(--brass-2,#DEBC7E)}
html[data-theme=dark] .att-act:hover{background:rgba(255,255,255,.05);border-color:var(--brass)}
/* status pills derive their tint from the SURFACE in dark, not from white — the pale slabs go */
html[data-theme=dark] .pstat.active{background:color-mix(in srgb,var(--green) 22%,var(--surface));color:color-mix(in srgb,var(--green) 72%,#fff)}
html[data-theme=dark] .pstat.incoming,html[data-theme=dark] .pstat.on_leave{background:color-mix(in srgb,var(--amber) 24%,var(--surface));color:var(--amber-ink,#E2B564)}
/* reduced motion is a preference, honoured wholesale — every animation and transition collapses
   to instant. Individual guards above stay (they also fix colour endpoints); this is the net. */
@media (prefers-reduced-motion: reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}

/* --- Demand: catalogue + pricing guardrail (docs/demand-module-scope.md D1) ------------------- */
/* The verdict strip is the module's argument on screen, so it is coloured by MEANING and not by
   mood: green only when a quote clears the target, amber when it clears the floor but not the
   target, red when it is below the floor, and a neutral grey when the guardrail has nothing to
   judge with. A floor-exempt offer is deliberately NOT red — it is priced low on purpose, and
   colouring it as a breach is what teaches people to ignore the colour. */
.setgrid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:14px}
/* .full spans the settings grid the way it already does inside a dialog's .mgrid — the
   segment-rate row carries four controls (sector, currency, rate, remove) and truncates the
   sector to two characters in a 190px column. */
.setgrid2>.full{grid-column:1/-1}
.dm-rate,.dm-seg{display:flex;gap:6px;align-items:center;margin-bottom:6px}
/* .setrow is NOT a layout class — its only selectors are label.pfcheck.setrow, so a <div>
   carrying it matches nothing. .dm-rate has always supplied its own flex; .dm-seg needs the
   same or its select, currency, rate and remove button stack down the card. */
.dm-verdict{margin-top:10px;padding:10px 13px;border-radius:10px;border:1px solid var(--rule);
  font-size:13px;line-height:1.5;background:var(--surface)}
.dm-verdict b{font-family:var(--mono);font-size:15px}
.dm-ok{color:var(--green);border-color:color-mix(in srgb,var(--green) 42%,#fff);background:rgba(30,158,120,.06)}
.dm-warn{color:var(--amber-ink,var(--amber));border-color:color-mix(in srgb,var(--amber) 42%,#fff);background:color-mix(in srgb,var(--amber) 8%,transparent)}
.dm-bad{color:var(--red);border-color:color-mix(in srgb,var(--red) 45%,#fff);background:rgba(231,45,63,.07)}
.dm-exempt{color:var(--muted);border-color:var(--rule);background:var(--bg)}
.dm-none{color:var(--muted)}
.dm-offer{border:1px solid var(--rule);border-radius:12px;padding:12px 14px;margin-bottom:10px;background:var(--surface)}
.dm-offer-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:8px}
.dm-offer-head .dm-exempt{font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;
  padding:2px 7px;border-radius:99px;border:1px solid var(--rule);background:var(--bg)}
.dm-tiers{width:100%;border-collapse:collapse;font-size:13px}
.dm-tiers td{padding:4px 6px;border-top:1px solid var(--grid-line,var(--rule))}
.dm-tiers td.num{font-family:var(--mono);text-align:right;white-space:nowrap}
.dm-newtier{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px}

/* --- Demand: the pipeline board (D2) --------------------------------------------------------- */
/* The no-next-action stat is shown even at zero, and only turns amber when it is NOT zero: a
   discipline metric that vanishes when healthy cannot be watched, and one that is always amber
   stops being read. */
.dm-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:12px;margin:0 0 18px}
.dm-stat{border:1px solid var(--rule);border-radius:12px;padding:12px 16px;background:var(--surface)}
.dm-stat b{display:block;font-family:var(--mono);font-size:21px;line-height:1.1;color:var(--ink)}
.dm-stat span{display:block;font-family:var(--mono);font-size:9.5px;font-weight:600;text-transform:uppercase;letter-spacing:.07em;color:var(--muted);margin-top:5px}
.dm-stat-warn{border-color:color-mix(in srgb,var(--amber) 45%,#fff);background:color-mix(in srgb,var(--amber) 7%,transparent)}
.dm-stat-warn b{color:var(--amber-ink,var(--amber))}
/* The board rides on .ptable now: one table for every stage, with a grouphead row per stage, so the
   columns line up down the page. That inherits the zebra striping, the tabular figures and the
   grouphead type scale, and leaves only what is genuinely Demand's here. .dm-stage and the
   standalone .dm-pipe table/td rules went with the per-stage tables that used to need them. */
.dm-pipe td{vertical-align:top}
.dm-pipe td .lmuted{white-space:normal}   /* .ptable td is nowrap; the sub-line under a title wraps */
.dm-overdue{color:var(--red)}
.dm-due{color:var(--amber-ink,var(--amber))}
.dm-noaction .lmuted{color:var(--amber-ink,var(--amber));font-style:italic}
/* A pipeline row is a doorway to the deal editor. Modelled on .gclick but not reusing it — its
   negative margins are for card list rows, not table cells. */
/* In dark these four mixed toward #fff and washed out to nothing on the dark surface: a pale
   pastel outline round a card with no fill. The house rule 30 lines up (.pstat.active) mixes the
   hue into the SURFACE instead, which is what reads on both grounds. */
html[data-theme=dark] .dm-ok{border-color:color-mix(in srgb,var(--green) 34%,var(--surface));background:color-mix(in srgb,var(--green) 22%,var(--surface))}
html[data-theme=dark] .dm-warn{border-color:color-mix(in srgb,var(--amber) 34%,var(--surface));background:color-mix(in srgb,var(--amber) 24%,var(--surface))}
html[data-theme=dark] .dm-bad{border-color:color-mix(in srgb,var(--red) 34%,var(--surface));background:color-mix(in srgb,var(--red) 22%,var(--surface))}
html[data-theme=dark] .dm-stat-warn{border-color:color-mix(in srgb,var(--amber) 34%,var(--surface));background:color-mix(in srgb,var(--amber) 24%,var(--surface))}
.dm-pipe tr.dm-click{cursor:pointer}
.dm-pipe tr.dm-click:hover td{background:var(--blue-soft)}
.dm-pipe tr.dm-click:focus-visible{outline:2px solid var(--focus-ring,var(--blue));outline-offset:-2px}

/* Demand · the signal payload a triager opens to see why the producer fired */
.dm-sig-payload { margin-top: 6px; }
.dm-sig-payload > summary { cursor: pointer; color: var(--muted); font-size: 12px; }
.dm-sig-payload > pre {
  margin: 6px 0 0; padding: 8px 10px; max-height: 260px; overflow: auto;
  background: var(--bg); border: 1px solid var(--card-line); border-radius: 6px;
  font-size: 12px; line-height: 1.45; white-space: pre-wrap; word-break: break-word;
}

/* A retired catalogue entry: kept because deals reference it, but not on offer. */
.dm-retired{font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);
  border:1px solid var(--rule);border-radius:999px;padding:1px 7px}

/* The touch log inside the deal editor. */
.dm-touches{width:100%;border-collapse:collapse;font-size:12.5px;margin-bottom:8px}
.dm-touches td{padding:4px 8px 4px 0;border-top:1px solid var(--grid-line,var(--rule));vertical-align:top}
.dm-touches td.num{font-family:var(--mono);white-space:nowrap;width:1%}
.dm-kind{font-family:var(--mono);font-size:10px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);border:1px solid var(--rule);border-radius:999px;padding:1px 6px}
.dm-newtouch{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
/* min-width:0 is the load-bearing half. A flex item's default min-width is auto, so an <input>
   refuses to shrink past its intrinsic size: the summary field collapsed to a few pixels while the
   select and the date input kept theirs, and the button wrapped to two lines. */
.dm-newtouch .dmTSummary{flex:1 1 160px;min-width:0}
.dm-newtouch .dmTKind{flex:0 0 auto;max-width:120px}
.dm-newtouch .dmTWhen{flex:0 0 auto}
.dm-newtouch .dmTAdd{flex:0 0 auto;white-space:nowrap}

/* The per-deal floor override, set apart from the deal's own facts: it is a decision ABOUT the
   price rather than part of it. */
.dm-override{border-top:1px solid var(--rule);padding-top:10px;margin-top:4px}

/* Documents generated from a deal, inside the deal editor. */
.dm-docs{width:100%;border-collapse:collapse;font-size:12.5px;margin-bottom:8px}
.dm-docs td{padding:4px 8px 4px 0;border-top:1px solid var(--grid-line,var(--rule))}
.dm-newdoc{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.dm-newdoc .dmDocTpl{flex:1 1 180px;min-width:0}
.dm-newdoc .dmGenDoc{flex:0 0 auto;white-space:nowrap}

/* A deal's facts shown to someone who may not change them. Plain text, not a disabled input —
   a greyed-out field invites a click that does nothing (the clients table sets this precedent). */
.dm-ro{font-size:13.5px;color:var(--ink);padding:2px 0 4px}

/* A prefilled code that nobody has confirmed yet. Legible, not shouty — it is a suggestion the user
   is expected to keep, and it drops back to a normal field the moment they type. */
/* ⚠⚠ SPECIFICITY, AND GETTING IT WRONG PAINTS NOTHING AT ALL. `.cal-form .cf-l textarea` (0,2,1)
   sets `font:inherit` — a SHORTHAND, so it resets font-style to normal — and `color:var(--ink)`,
   and a one-class rule cannot beat it. The suggestion classes were on the element, a source test
   would have passed, and the field looked exactly like ordinary typed text. Only opening the page
   found it, so every host that dresses its own fields is named here. */
input.suggested,textarea.suggested,
.cal-form .cf-l textarea.suggested,.cal-form .cf-l input.suggested{
  color:var(--ink-2,#3D5A85);background:color-mix(in srgb,var(--brand) 4%,var(--field,#fff))}
/* A suggested NOTE is italic as well as muted; a suggested code is not. "Working on QC" is a
   sentence somebody may keep as it stands, and italic says "these are not your words yet" — but
   italicising a code like MSA-116 would just make it look wrong. */
textarea.sug-note,input.sug-note,
.cal-form .cf-l textarea.sug-note,.cal-form .cf-l input.sug-note{font-style:italic}
/* The alternatives, under the field. Quiet enough that the field stays the subject, and big enough
   to hit: these are the whole point for somebody logging a week in one sitting. */
.sug-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
.sug-chip{font:inherit;font-size:12px;font-style:italic;line-height:1.2;padding:5px 10px;border-radius:999px;
  border:1px solid var(--rule-blue,#C8D2E3);background:transparent;color:var(--ink-2,#3D5A85);cursor:pointer;
  text-align:left;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sug-chip:hover{border-color:var(--navy);color:var(--navy)}
.sug-chip:focus-visible{outline:2px solid var(--navy);outline-offset:1px}

/* Reference check — the three verdicts must be distinguishable at a glance AND without colour, because
   "could not check" being mistaken for either a pass or a fail is the whole failure mode. Colour
   carries the mood; the WORD carries the meaning, and the dashed border marks unchecked as a third
   thing rather than a weak version of one of the other two. */
.rc-tbl td{vertical-align:top;padding:7px 8px;border-bottom:1px solid var(--rule,#E7ECF3)}
.rc-tbl code{font-size:12px;word-break:break-all}
.rc-badge{white-space:nowrap;width:1%}
.rc-pill{display:inline-block;font-size:11px;font-weight:600;padding:2px 8px;border-radius:999px;border:1px solid transparent}
.rc-pill.rc-ok{background:var(--blue-soft);color:var(--navy);border-color:var(--rule-blue)}
.rc-pill.rc-no{background:color-mix(in srgb,var(--red) 12%,transparent);color:var(--red);border-color:var(--red)}
.rc-pill.rc-unk{background:transparent;color:var(--soft);border-style:dashed;border-color:var(--soft)}
/* Vouched-for: solid like a pass, but its OWN colour and word — a person said so, an index did not.
   Never the same pill as `found`, because a disclosure statement has to tell the two apart. */
.rc-pill.rc-att{background:color-mix(in srgb,var(--amber,#B8860B) 14%,transparent);color:var(--navy);border-color:var(--amber,#B8860B)}
.rc-sum{margin-top:10px;font-size:12.5px;font-variant-numeric:tabular-nums;color:var(--soft)}
/* The one line that answers the question the modal was opened to ask. `nothing_outstanding`,
   not `all_resolved` — a vouched-for reference counts (app/citations.py says why). */
.rc-verdict{margin-top:8px;padding:9px 11px;border-radius:8px;border:1px solid transparent;font-size:13px}
.rc-verdict b{font-size:13.5px}
.rc-verdict .lmuted{margin-top:2px;font-size:12px}
.rc-verdict.rc-ok{background:var(--blue-soft);border-color:var(--rule-blue);color:var(--navy)}
.rc-verdict.rc-no{background:color-mix(in srgb,var(--red) 8%,transparent);border-color:var(--red);color:var(--navy)}
/* A partly-checked file gets the same dashed, deliberately unfinished treatment as an
   unchecked ROW — it is the absence of a verdict, not a bad one. */
.rc-verdict.rc-unk{background:transparent;border-style:dashed;border-color:var(--soft);color:var(--navy)}
.rc-file{display:flex;align-items:center;gap:10px;margin:8px 0 2px;flex-wrap:wrap}
.rc-file .lmuted{font-size:12px}
.rc-zot{margin:8px 0;padding:10px 12px;border:1px solid var(--rule,#E7ECF3);border-radius:8px;background:var(--blue-soft)}
.rc-zotrow{display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap}
.rc-zotrow label{display:flex;flex-direction:column;gap:3px;font-size:12px;color:var(--soft)}
.rc-zotrow input,.rc-zotrow select{font-size:13px;padding:5px 7px}
.rc-zotrow .rc-zotid{width:11ch}
.rc-zot .msub{margin:8px 0 0;font-size:11.5px}
/* The master reference library — the list, its filters, the import drawer, and a proposal's own
   cited list. Shares the checker's verdict pills (.rc-pill above) on purpose: one reference must
   not read as "Found" on one screen and something else on another. */
.rl-card{width:min(880px,96vw)}
.rl-bar{display:flex;gap:8px;align-items:center;margin:10px 0 0;flex-wrap:wrap}
.rl-q{flex:1;min-width:180px}
.rl-add{margin:10px 0 0;padding:10px 12px;border:1px solid var(--rule,#E7ECF3);border-radius:8px}
.rl-add textarea{width:100%;margin-top:8px}
.rl-addacts{display:flex;justify-content:flex-end;margin-top:8px}
.rl-filts{display:flex;gap:6px;flex-wrap:wrap;margin:10px 0 0}
.rl-chip{font-size:11.5px;padding:3px 9px;border-radius:999px;border:1px solid var(--rule,#E7ECF3);background:transparent;color:var(--soft);cursor:pointer}
.rl-chip.on{border-color:var(--navy);color:var(--navy);font-weight:600}
.rl-chip .rl-n{margin-left:6px;font-variant-numeric:tabular-nums;opacity:.7}
.rl-list{max-height:46vh;overflow:auto;margin-top:10px}
.rl-empty{padding:18px 2px}
.rl-title{color:var(--navy);font-weight:600;font-size:13px;line-height:1.35}
.rl-meta{font-size:12px;margin-top:2px}
.rl-doi{display:inline-block;margin-top:3px;font-family:var(--mono);font-size:11.5px;color:var(--soft);word-break:break-all}
.rl-uses{margin-top:5px;display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.rl-use{font-size:11.5px;padding:2px 8px;border-radius:999px;border:1px solid var(--rule-blue);background:var(--blue-soft);color:var(--navy);cursor:pointer;max-width:26ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rl-when{font-weight:400;opacity:.75}
.rl-verdict{white-space:nowrap;width:1%}
.rl-acts{white-space:nowrap;width:1%;text-align:right}
.rl-acts .btn{margin-right:6px}
.aprefrow{display:flex;gap:10px;align-items:flex-start;padding:9px 0;border-bottom:1px solid var(--rule,#E7ECF3)}
.aprefmain{flex:1;min-width:0}
/* ⚠ STACKED, NOT SCROLLED. As a table the row is ~445px inside a ~315px phone dialog, which put
   Remove (and Cite) beyond a horizontal scroll nobody would find — the page itself did not overflow,
   so every width check passed while the controls were unreachable. Rows become blocks below 640px. */
@media(max-width:640px){
  .rl-list table,.rl-list tbody,.rl-row,.rl-row td{display:block;width:auto}
  .rl-row{border-bottom:1px solid var(--rule,#E7ECF3);padding:9px 0}
  .rl-row td{border-bottom:0;padding:2px 0}
  .rl-verdict,.rl-acts{text-align:left;white-space:normal}
  .rl-acts{display:flex;gap:14px;align-items:center;margin-top:7px}
  .rl-acts .btn{margin-right:0}
  .aprefrow{flex-wrap:wrap}
  .aprefmain{flex:1 0 100%}
}
/* Your data — the in-product privacy notice. Sections rather than one wall of prose, because
   a rights notice nobody reads is the same as no notice. */
.yd-sec{margin:14px 0 0;padding-top:12px;border-top:1px solid var(--rule,#E7ECF3)}
.yd-sec:first-of-type{border-top:0;padding-top:0}
.yd-sec h4{margin:0 0 4px;font-size:13.5px}
.yd-sec .msub{margin:0 0 8px}
.yd-tbl td{padding:5px 8px;vertical-align:top;border-bottom:1px solid var(--rule,#E7ECF3);font-size:12.5px}
.yd-tbl td:first-child{width:34%;white-space:nowrap}
/* Start a project — a guided flow, so each step ARRIVES rather than replacing the last. The slide
   is small and fast on purpose: it says "same page, next question", and anything longer becomes a
   thing to sit through on the fourth proposal of the week. */
.wz-dots{display:flex;gap:6px;margin:2px 0 14px}
.wz-dot{width:22px;height:3px;border-radius:2px;background:var(--rule,#E7ECF3);transition:background .18s ease}
.wz-dot.on{background:var(--red)}
.wz-body{min-height:190px}
@keyframes wzInFwd{from{opacity:0;transform:translateX(14px)}to{opacity:1;transform:none}}
@keyframes wzInBack{from{opacity:0;transform:translateX(-14px)}to{opacity:1;transform:none}}
.wz-body.wz-fwd{animation:wzInFwd .2s ease}
.wz-body.wz-back{animation:wzInBack .2s ease}
/* ⚠ Honour the OS setting: an animation is a nicety and motion sensitivity is not. */
@media (prefers-reduced-motion: reduce){.wz-body.wz-fwd,.wz-body.wz-back{animation:none}}
.wz-q{display:block;font-size:15px;font-weight:600;margin:0 0 10px;color:var(--navy)}
.wz-in{width:100%;font-size:15px;padding:9px 11px}
.wz-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(184px,1fr));gap:8px;max-height:44vh;overflow:auto}
.wz-card{display:flex;flex-direction:column;gap:2px;text-align:left;padding:9px 11px;border:1px solid var(--rule,#E7ECF3);border-radius:8px;background:var(--surface,#fff);cursor:pointer;transition:border-color .14s ease,background .14s ease}
.wz-card:hover{border-color:var(--rule-blue)}
.wz-card.on{border-color:var(--red);background:color-mix(in srgb,var(--red) 6%,transparent)}
.wz-card b{font-size:13.5px;color:var(--navy)}
.wz-card .lmuted{font-size:11.5px;line-height:1.3}
.wz-meta{font-size:11px;color:var(--soft)}
.wz-tbl td{padding:6px 8px;border-bottom:1px solid var(--rule,#E7ECF3);font-size:13px}
.wz-tbl td:first-child{width:38%;white-space:nowrap}

/* --- comparing two published versions of a controlled document -------------------------------- */
/* The units are the document's own: a heading stays a heading, a paragraph stays a paragraph. An
   added block and a removed one must be tellable apart WITHOUT colour — this is evidence in an
   audit, it gets printed, and a reader may not see green and red as different. So each carries a
   gutter mark and a rule, and colour is the third signal rather than the only one. */
.dd-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:10px 0;border-bottom:1px solid var(--rule)}
.dd-bar label{font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin:0}
.dd-bar select{width:auto;min-width:150px;margin:0}
.dd-arrow{color:var(--muted)}
.dd-sum{margin-left:auto;font-family:var(--mono);font-size:11px;color:var(--muted)}
.dd-body{max-height:56vh;overflow:auto;padding:12px 0}
.dd-prose .dd-row{position:relative;padding:3px 0 3px 22px;line-height:1.55;font-size:13px}
.dd-prose h2.dd-row,.dd-prose h3.dd-row,.dd-prose h4.dd-row{font-size:14px;font-weight:600;margin:12px 0 2px}
.dd-row::before{position:absolute;left:4px;top:3px;font-family:var(--mono);font-size:11px;color:var(--muted)}
.dd-same{color:var(--muted)}
.dd-add{background:rgba(30,158,120,.08);border-left:2px solid var(--green,#1E9E78)}
.dd-add::before{content:"+";color:var(--green,#1E9E78)}
.dd-del{background:rgba(231,45,63,.07);border-left:2px solid var(--red)}
.dd-del::before{content:"−";color:var(--red)}
.dd-chg{background:rgba(111,151,216,.08);border-left:2px solid var(--blue)}
.dd-chg::before{content:"~";color:var(--blue)}
.dd-body ins{text-decoration:none;background:rgba(30,158,120,.22);border-radius:2px}
.dd-body del{background:rgba(231,45,63,.16);border-radius:2px}
.dd-tbl td{vertical-align:top;font-size:12px}
.dd-tbl .dd-op{width:18px;font-family:var(--mono);font-weight:700}
.dd-tbl tr.dd-add .dd-op{color:var(--green,#1E9E78)}
.dd-tbl tr.dd-del .dd-op{color:var(--red)}
.dd-tbl tr.dd-change .dd-op{color:var(--blue)}
.dd-note{padding:10px 12px;margin:8px 0;background:var(--panel);border-left:2px solid var(--rule-blue);font-size:12.5px;line-height:1.55;color:var(--ink)}

/* --- a project's own schedule (the Schedule tab) ----------------------------------------------- */
/* Geometry is PERCENTAGE-based on purpose: this view shares none of the timeline's singletons —
   not `--colw`, not laneRefs, not pinLabels — so it reads correctly at any panel width and cannot
   fight the main grid over a zoom level. */
/* The chart scrolls sideways inside the card on a narrow screen; the editing bar and the key above
   and below it do not, so the hint and "+ Add booking" stay in view while the lanes scroll. */
.pjs-scroll{overflow-x:auto}
.pjs-head,.pjs-row{display:flex;align-items:stretch;gap:10px;min-width:560px}
/* The names stay put while the lanes scroll under them (a phone scrolls this chart sideways); the
   shadow paints the row gap too, so a block passing beneath never shows through it. */
.pjs-nm{flex:0 0 172px;min-width:0;display:flex;flex-direction:column;justify-content:center;padding:5px 0;
  position:sticky;left:0;z-index:4;background:var(--surface);box-shadow:10px 0 0 var(--surface)}
@media (max-width:640px){
  .pjs-head,.pjs-row{min-width:720px}
  .pjs-nm{flex-basis:124px}
}
.pjs-nm b{font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pjs-nm .lmuted{font-size:10.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pjs-months{flex:1 1 0;display:flex;border-bottom:1px solid var(--rule)}
.pjs-m{flex:1 1 0;text-align:center;padding:2px 0 5px;font-family:var(--mono);font-size:10px;color:var(--muted);border-left:1px solid var(--rule)}
.pjs-m:first-child{border-left:none}
.pjs-m b{display:block;font-weight:600;color:var(--navy)}
.pjs-row{border-bottom:1px solid var(--rule)}
.pjs-row:last-child{border-bottom:none}
/* ⚠ THE GRIDLINE SPACING FOLLOWS THE DATA. This was written as `calc(100% / 7)` and looked perfect
   — on the seven-month project it was tested against. `--pjs-cols` is set from the month count, so a
   three-month project and a three-year one both line up with their own headers. */
.pjs-track{flex:1 1 0;position:relative;min-height:34px;margin:5px 0;--pjs-cols:12;
  background:repeating-linear-gradient(to right,transparent 0,transparent calc(100% / var(--pjs-cols) - 1px),var(--rule) calc(100% / var(--pjs-cols) - 1px),var(--rule) calc(100% / var(--pjs-cols)))}
/* the person's OTHER commitments — a muted ground, so an empty month on THIS project is not read
   as a free month */
.pjs-oth{position:absolute;top:0;bottom:0;background:var(--navy-soft);pointer-events:auto}
/* a lane that holds a role with no time booked — sticks beside the names while the chart scrolls */
.pjs-none{position:sticky;left:182px;display:inline-block;margin:7px 0 0 8px;padding:2px 6px;border-radius:4px;
  background:var(--surface);font-size:10.5px;font-style:italic;color:var(--muted);white-space:nowrap;pointer-events:none}
@media (max-width:640px){ .pjs-none{left:134px} }
/* ⚠ THE LABEL IS INK, NOT WHITE. White on the light booking blue measured 3:1 (2.4:1 on the Lab
   teal), and white on the dark theme's near-white --navy-soft 1.6:1 — on labels that are now the
   controls a planner clicks. Ink on the blue fill; the fill that turns light in dark mode gets the
   surface colour there. Pencilled and unstaffed blocks keep their own colours below. */
.pjs-blk{position:absolute;top:3px;bottom:3px;border-radius:4px;background:var(--blue);color:var(--ink);
  display:flex;align-items:center;padding:0 6px;font-size:10.5px;font-weight:600;overflow:hidden;white-space:nowrap}
.pjs-blk.internal{background:var(--navy-soft);color:var(--surface)}
html[data-theme=dark] .pjs-blk:not(.soft):not(.hole){color:var(--surface)}
.pjs-blk.soft{background:var(--surface);color:var(--navy);border:1.5px dashed var(--blue)}
.pjs-blk.hole{background:var(--surface);color:var(--red);border:1.5px dashed var(--red)}
.pjs-notes{margin:6px 0 0;padding-left:18px;font-size:12.5px;line-height:1.7}
.pjs-notes b{font-weight:600}
/* the key for the muted ground — an unexplained shade is not information */
.pjs-key{display:flex;gap:14px;flex-wrap:wrap;align-items:center;padding:8px 0 0;font-size:10.5px;color:var(--muted)}
.pjs-key i{display:inline-block;width:12px;height:9px;border-radius:2px;margin-right:5px;vertical-align:middle}
.pjs-key .k-this{background:var(--blue)}
.pjs-key .k-oth{background:var(--navy-soft);opacity:.45}
.pjs-key .k-soft{background:var(--surface);border:1.5px dashed var(--blue)}
.pjs-key .k-hole{background:var(--surface);border:1.5px dashed var(--red)}
/* editing (plan_write only — the class is never set for a member, so a read-only chart keeps the
   default cursor and no grips) */
.pjs-bar{display:flex;align-items:center;gap:10px 14px;flex-wrap:wrap;margin:0 0 12px}
.pjs-hint{flex:1 1 280px;font-size:12px;line-height:1.45;color:var(--muted)}
.pjs-track.can-add{cursor:pointer}
.pjs-blk.ed{cursor:grab;transition:box-shadow var(--t1) var(--ease),filter var(--t1) var(--ease)}
.pjs-blk.ed:hover{box-shadow:0 0 0 2px var(--rule-blue);filter:brightness(1.04)}
.pjs-blk.ed:focus-visible{outline:2px solid var(--focus-ring,var(--blue));outline-offset:1px}
.pjs-blk.dragging{cursor:grabbing;z-index:3;box-shadow:0 0 0 2px var(--focus-ring,var(--blue)),0 6px 18px rgba(21,45,73,.22)}
.pjs-rz{position:absolute;top:0;bottom:0;width:8px;cursor:ew-resize;z-index:1}
.pjs-rz.l{left:0}.pjs-rz.r{right:0}
.pjs-blk.ed:hover .pjs-rz::after{content:"";position:absolute;top:28%;bottom:28%;left:3px;width:2px;border-radius:1px;background:currentColor;opacity:.5}
/* what a click on an empty stretch would book — three weeks from the Monday under the pointer */
.pjs-ghost{position:absolute;top:3px;bottom:3px;border-radius:4px;border:1.5px dashed var(--rule-blue);
  background:color-mix(in srgb,var(--blue) 8%,transparent);color:var(--muted);display:flex;align-items:center;
  justify-content:center;font-size:14px;font-weight:600;pointer-events:none}
/* the dates a drag will write, live beside the pointer — inverse ink, so it reads in both themes */
.pjs-dtip{position:fixed;z-index:400;pointer-events:none;background:var(--ink);color:var(--surface);
  font-family:var(--mono);font-size:11.5px;font-weight:600;line-height:1;padding:7px 9px;border-radius:7px;
  white-space:nowrap;box-shadow:0 6px 18px rgba(21,45,73,.25)}

/* --- a project's hours: logged against planned over four windows (the project header) ----------- */
.pj-hours{margin-top:14px;padding-top:12px;border-top:1px solid var(--rule)}
.pjh-cap{font-family:var(--mono);font-size:9.5px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--faint);margin-bottom:8px}
.pjh-cells{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));column-gap:22px;row-gap:0;margin-bottom:-12px}
/* ⚠ LABEL, FIGURE AND BAR EACH SIT ON A ROW THE CELLS SHARE (subgrid). A column with only the bar
   pushed to its foot kept the bars level, but a label that wrapped in one cell ("Senaste 5
   arbetsdagarna" on a phone) dropped that cell's figure 16 px below its neighbour's. The gap between
   rows of cells is the cell's own margin, so the three rows inside a cell stay tight. */
.pjh-cell{min-width:0;display:grid;grid-row:span 3;grid-template-rows:subgrid;row-gap:0;margin-bottom:12px}
.pjh-cell .pjh-bar{align-self:end}
.pjh-empty{font-size:12.5px;color:var(--muted)}
/* what "≈" and the tick mean — in the tooltips on a desktop, and here where there is no hover */
.pjh-key{display:none}
/* on a phone the two rolling windows wait behind a toggle, so the tabs are not pushed off the first screen */
.pjh-more{display:none}
@media (max-width:640px){
  .pjh-key{display:block;margin-top:8px;font-size:11px;line-height:1.4;color:var(--muted)}
  .pj-hours:not(.all) .pjh-cell.rolling{display:none}
  .pjh-cap{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
  .pjh-more{display:inline-block;padding:0;background:none;border:0;font-family:var(--font,inherit);font-size:12px;
    font-weight:600;letter-spacing:0;text-transform:none;color:var(--ink);text-decoration:underline;
    text-underline-offset:2px;cursor:pointer}
}
.pjh-l{display:flex;align-items:baseline;gap:6px;font-size:11.5px;line-height:1.35;color:var(--muted);min-width:0}
.pjh-l > span:first-child{min-width:0}
.pjh-v{display:flex;align-items:baseline;flex-wrap:wrap;column-gap:6px;min-width:0;margin:1px 0 6px}
.pjh-v b{font-family:var(--mono);font-size:15px;font-weight:700;color:var(--navy);letter-spacing:-.01em;font-variant-numeric:tabular-nums;white-space:nowrap}
.pjh-of{font-size:11.5px;color:var(--muted);white-space:nowrap}
.pjh-pct{margin-left:auto;flex:0 0 auto;font-family:var(--mono);font-size:11px;font-weight:600;color:var(--muted);font-variant-numeric:tabular-nums}
.pjh-bar{position:relative;height:5px;border-radius:3px;background:var(--rule)}
.pjh-bar i{position:absolute;left:0;top:0;bottom:0;border-radius:3px;background:var(--blue)}
/* where the plan stands today, in a window still running */
.pjh-tick{position:absolute;top:-3px;bottom:-3px;width:2px;margin-left:-1px;border-radius:1px;background:var(--ink);opacity:.5}
/* the colour follows the number (see _pjHoursBand): the timesheet's own bands */
.pjh-cell.ok .pjh-bar i{background:var(--green)}
.pjh-cell.under .pjh-bar i{background:var(--amber)}
.pjh-cell.over .pjh-bar i{background:var(--red)}
.pjh-cell.under .pjh-pct{color:var(--amber-ink)}
.pjh-cell.over .pjh-pct{color:var(--red)}
.pjh-cell.none .pjh-v b{color:var(--faint)}
@media (max-width:760px){ .pjh-cells{grid-template-columns:repeat(2,minmax(0,1fr));column-gap:18px} }

/* --- the project page's tab strip: one row, counts as quiet badges, the overflow behind "More" -- */
.pj-tabbar{display:flex;align-items:stretch;margin:16px 0 0;border-bottom:1px solid var(--rule);position:relative}
.pj-tabbar .pj-tabs{margin:0;border-bottom:0;flex:1 1 auto;min-width:0;flex-wrap:nowrap;overflow:hidden}
.pj-tabs .apptab{flex:0 0 auto;white-space:nowrap;display:inline-flex;align-items:center;gap:6px;padding:9px 13px}
/* the strip clips (overflow:hidden is what the fitting measures against), so the focus ring goes
   inside the tab — an outset ring lost its top, bottom and left edges */
.pj-tabs .apptab:focus-visible{outline-offset:-2px}
.apptab-n{display:inline-grid;place-items:center;min-width:18px;height:17px;padding:0 5px;border-radius:9px;
  background:var(--panel);border:1px solid var(--rule);color:var(--muted);font-family:var(--mono);font-size:10px;
  font-weight:600;line-height:1;font-variant-numeric:tabular-nums}
.apptab.on .apptab-n{color:var(--navy);border-color:var(--rule-blue)}
.pj-tabmore{position:relative;flex:0 0 auto;display:flex}
.pj-morebtn{display:inline-flex;align-items:center;gap:6px;background:transparent;border:0;border-bottom:2px solid transparent;
  border-radius:0;padding:9px 12px;font-family:inherit;font-size:14px;color:var(--muted);cursor:pointer;white-space:nowrap;
  transition:color .15s ease,border-color .15s ease}
.pj-morebtn:hover{color:var(--navy)}
.pj-morebtn.on{color:var(--navy);border-bottom-color:var(--brand)}
.pj-caret{font-size:10px;line-height:1}
.pj-moremenu{position:absolute;right:0;top:calc(100% + 6px);z-index:60;min-width:200px;display:flex;flex-direction:column;
  background:var(--surface);border:1px solid var(--card-line);border-radius:12px;padding:6px;
  box-shadow:0 1px 3px rgba(21,45,73,.08),0 16px 44px rgba(21,45,73,.2)}
.pj-mi{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;text-align:left;background:transparent;
  border:0;border-radius:8px;padding:8px 10px;font-family:inherit;font-size:14px;color:var(--ink);cursor:pointer}
.pj-mi:hover,.pj-mi:focus-visible{background:var(--panel)}
.pj-mi.on{background:var(--panel);color:var(--navy);font-weight:600}
@media (max-width:640px){ .pj-tabs .apptab,.pj-morebtn{padding:9px 10px;font-size:13.5px} }

/* --- building a controlled document from one the org already wrote ------------------------------ */
.di-card{width:min(1000px,96vw)}
.di-drop{display:flex;align-items:center;gap:10px;padding:14px;margin:10px 0;
  border:1.5px dashed var(--rule-blue);border-radius:8px;background:var(--panel)}
.di-scroll{max-height:52vh;overflow:auto;margin-top:10px;border:1px solid var(--rule);border-radius:6px}
.di-tbl{width:100%}
.di-tbl th{position:sticky;top:0;background:var(--surface);z-index:1}
.di-tbl td{vertical-align:top;border-bottom:1px solid var(--rule)}
.di-src{width:58%}
/* The reader's own words. Monospace and pre-wrap because the question this column answers is "did
   Lemma read this correctly", and a proportional font that reflows the source makes that harder. */
.di-src pre{margin:2px 0 0;font-family:var(--mono);font-size:11px;line-height:1.5;
  white-space:pre-wrap;word-break:break-word;color:var(--navy)}
.di-sec{font-size:9.5px;text-transform:uppercase;letter-spacing:.04em;color:var(--muted)}
.di-map{width:42%;padding-left:10px}
.di-map select{width:100%;margin:0 0 4px}
.di-map .lmuted{font-size:11px;line-height:1.45}
.di-warn{margin-top:4px;padding:5px 7px;border-left:2px solid var(--uwarn);background:rgba(233,162,59,.09);
  font-size:11px;line-height:1.45;color:var(--navy)}
.di-row.di-merged .di-src pre{opacity:.55}
.di-row.di-merged .di-map{opacity:.75}
