/* SPDX-License-Identifier: AGPL-3.0-only */
/*
 * The interface's three families (MP-1-2; TOKENS.md DS-TOK-28 to DS-TOK-30),
 * from pinned OFL-1.1 packages, Latin faces only: Funnel Display 400 to 700
 * in exactly the weights the tokens use, and Funnel Sans (300 to 800) and
 * Chivo Mono (100 to 900) as the variable faces the mockup draws, declared
 * here under the tokens' family names, since the packages name them
 * '<family> Variable'. The static instances of both drew the same weights a
 * shade differently from the mockup. No italic is drawn anywhere, so none is
 * loaded. Each face uses `font-display: swap`, so text shows in the fallback
 * stack until it arrives. The licence texts and the record are in
 * packages/ui/assets.
 */
/* funnel-display-latin-400-normal */
@font-face {
  font-family: 'Funnel Display';
  font-style: normal;
  font-display: swap;
  font-weight: 400;
  src: url(/assets/funnel-display-latin-400-normal-CzanjfVo.woff2) format('woff2'), url(/assets/funnel-display-latin-400-normal-YfsDShO0.woff) format('woff');
}
/* funnel-display-latin-500-normal */
@font-face {
  font-family: 'Funnel Display';
  font-style: normal;
  font-display: swap;
  font-weight: 500;
  src: url(/assets/funnel-display-latin-500-normal-CfaoK8W9.woff2) format('woff2'), url(/assets/funnel-display-latin-500-normal-NE_OKJDc.woff) format('woff');
}
/* funnel-display-latin-600-normal */
@font-face {
  font-family: 'Funnel Display';
  font-style: normal;
  font-display: swap;
  font-weight: 600;
  src: url(/assets/funnel-display-latin-600-normal-Mgf2EgkJ.woff2) format('woff2'), url(/assets/funnel-display-latin-600-normal-DTDKxDdc.woff) format('woff');
}
/* funnel-display-latin-700-normal */
@font-face {
  font-family: 'Funnel Display';
  font-style: normal;
  font-display: swap;
  font-weight: 700;
  src: url(/assets/funnel-display-latin-700-normal-CLO_L4Ou.woff2) format('woff2'), url(/assets/funnel-display-latin-700-normal-CWqFwraO.woff) format('woff');
}
@font-face {
  font-family: 'Funnel Sans';
  font-style: normal;
  font-display: swap;
  font-weight: 300 800;
  src: url('/assets/funnel-sans-latin-wght-normal-zzU05adE.woff2')
    format('woff2-variations');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Chivo Mono';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url('/assets/chivo-mono-latin-wght-normal-DXNvimoL.woff2')
    format('woff2-variations');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329,
    U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* SPDX-License-Identifier: AGPL-3.0-only
   ============================================================================
   Layer 1 of 3. THE LOAD ORDER IS THE CONTRACT and it is not negotiable:

       1-tokens.css  ->  2-primitives.css  ->  3-surfaces.css

   which is the pinned estate's own order (tokens -> hub-ds -> app.css), later
   wins, and preserving intentional cascade order is a standing rule
   [ui-reference CONTRACT.md:145]. `main.tsx` imports the three in this order
   and nothing else imports a stylesheet, so there is one place to read it.

   WHERE THESE VALUES COME FROM. The four token files the ticket names were
   disposed per-file in [ui-reference CONTRACT.md:157] and all four resolve to
   "take the Hub's version": across the four, not one changes a value or a rule
   the mockup renders. So the primitives, the semantic layer, radius, spacing
   and typography below are the Hub's own `src/design/tokens/` at the pinned
   revision 2c82bee, and the dark PRIMITIVE bridge at the foot is the mockup's
   `assets/tokens.css`, which the Hub serves from its application entry instead.

   FOUR STANDING RULES COME WITH THE SET, not optional:
     - tokens only for colour, never a literal
     - color-mix() for overlays, never raw rgba()
     - status is an OUTLINE, a NUMBER or a LINE, never a fill
     - radius is 0 except pills and circles

   NO @import. The mockup pulls Funnel Sans/Display, Chivo Mono and the
   Flaticon rounded icon set from two content-delivery networks. Neither route
   establishes redistribution rights, and the candidate's asset-rights rule
   says no unresolved asset ships by implication [ui-reference CONTRACT.md:196,
   issue #32]. So the families are NAMED with real fallbacks and no font file
   or icon is vendored. Every control that carries an icon in the mockup
   carries a word or an aria-label here instead, and the icon slot is left.
   ============================================================================ */

:root {
  /* -- Grounds and ink. OKLCH, editorial monochrome. ---------------------- */
  --paper: oklch(1 0 0);
  --paper-cream: oklch(0.945 0.006 70);
  --ink: oklch(0 0 0);
  --ink-muted: oklch(0.505 0.014 62); /* AA about 4.9:1 on paper */
  --ink-faint: oklch(0.62 0.012 62);
  --void: oklch(0.145 0.006 285);
  --void-deep: oklch(0.09 0.004 285);
  --on-dark: oklch(0.98 0 0);
  --on-dark-muted: color-mix(in oklch, var(--on-dark) 72%, transparent);
  --rule: oklch(0 0 0);
  --rule-faint: oklch(0 0 0 / 0.12);

  /* -- The one interactive signal. Swapping it is a one-line edit. -------- */
  --accent: oklch(0.58 0.21 285);
  --accent-ink: oklch(0.98 0 0);
  --accent-ring: color-mix(in oklch, var(--accent) 35%, transparent);
  --brand: var(--accent);
  /* The only accent tint: a selected row, an armed drop zone, today. */
  --accent-wash: color-mix(in oklch, var(--accent) 8%, transparent);
  /* The backdrop behind the off-canvas rail and a modal sheet. */
  --scrim: oklch(0 0 0 / 0.4);
  /* Chart paint beside ink and the accent (the mockup's PAINT): the donut's
     third and fourth slices. The same in both themes, as the mockup has them. */
  --lilac: oklch(0.78 0.088 305);
  --lilac-deep: oklch(0.52 0.125 300);

  /* -- Chrome that is dark in both themes. The app strip lifts off the void
        in dark; the client face paints it with the client's brand. The cover
        photo's fallback gradient never flips. ----------------------------- */
  --app-chrome: var(--void);
  --client-brand: oklch(0.33 0.058 192);
  --hero-paint: linear-gradient(135deg, #0e7c7b 0%, #17555a 42%, #14243b 100%);

  /* -- The mock-data mark, shown only where a demo install shows mock data.
        Its hue stays clear of the accent and it mixes in oklab. ------------ */
  --mock-pink: oklch(0.7 0.19 350);
  --mock-tint: color-mix(in oklab, var(--mock-pink) 9%, transparent);
  --mock-edge: color-mix(in oklab, var(--mock-pink) 34%, transparent);

  /* -- Semantic neutrals. Feature code reads these, never the primitives. - */
  --bg: var(--paper);
  --surface: var(--paper);
  --surface-2: color-mix(in oklch, var(--ink) 4%, var(--paper));
  --surface-3: color-mix(in oklch, var(--ink) 8%, var(--paper));
  --border: var(--rule-faint);
  --border-strong: color-mix(in oklch, var(--ink) 32%, transparent);
  --text: var(--ink);
  --text-2: var(--ink-muted);
  --text-muted: var(--ink-faint);
  --text-dim: color-mix(in oklch, var(--ink-faint) 60%, var(--paper));
  --scheme: light;

  /* -- Buttons. Ink at rest, accent on hover. ---------------------------- */
  --btn-fill: var(--ink);
  --btn-text: var(--paper);
  --btn-hover: var(--accent);
  --btn-hover-text: var(--accent-ink);
  --btn-outline: var(--text);
  --hover-accent: var(--accent);

  /* -- Status. MEANING ONLY: border, text or line. The -soft fills are
        transparent because a status colour never fills a box. The four light
        inks are pinned separately so a surface inside a dark scope has a token
        to reach for rather than re-minting the hex. -------------------------- */
  --info-light: #009dea;
  --success-light: #10b981;
  --warning-light: #f59e0b;
  --danger-light: #e84a5f;
  --info: var(--info-light);
  --success: var(--success-light);
  --warning: var(--warning-light);
  --danger: var(--danger-light);
  --info-soft: transparent;
  --success-soft: transparent;
  --warning-soft: transparent;
  --danger-soft: transparent;

  /* -- Radius. Sharp. The legacy names are kept so primitives cascade. ---- */
  --radius-none: 0;
  --radius-pill: 999px;
  --radius-round: 50%;
  --radius-xs: var(--radius-none);
  --radius-sm: var(--radius-none);
  --radius-md: var(--radius-none);
  --radius-lg: var(--radius-none);

  /* -- Elevation. Shadow is earned: it means an element is lifted. -------- */
  --shadow-sm: 0 1px 2px rgb(15 18 24 / 5%);
  --shadow: 0 1px 3px rgb(15 18 24 / 8%), 0 14px 32px -20px rgb(15 18 24 / 24%);
  --shadow-lg: 0 2px 8px rgb(15 18 24 / 10%), 0 24px 64px -30px rgb(15 18 24 / 32%);
  --shadow-overlay: 0 24px 60px oklch(0 0 0 / 45%);
  /* The shade on a sticky column's edge. It follows the text, so it flips. */
  --shadow-edge: -10px 0 10px -10px color-mix(in srgb, var(--text) 30%, transparent);
  /* Focus is a SHADOW token rather than an outline, which is why the visual
     acceptance set captures focus-visible in both themes [13.4]. */
  --focus-ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent);

  /* -- Motion. One ease. prefers-reduced-motion is honoured below. -------- */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 0.12s;
  --dur: 0.18s;
  --dur-1: 220ms;
  --dur-2: 420ms;
  /* The locate flash only. */
  --dur-flash: 1.5s;

  /* -- Spacing. The 8px rhythm at 4px granularity. ----------------------- */
  --s-0-5: 2px;
  --s-1: 0.25rem;
  --s-1-5: 6px;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;
  --s-9: 6rem;
  /* The page gutter. */
  --pad-x: clamp(20px, 3.2vw, 32px);

  /* -- Type. Three families, loaded by 0-fonts.css. ----------------------- */
  --font-display: 'Funnel Display', ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-sans: 'Funnel Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'Chivo Mono', ui-monospace, SFMono-Regular, monospace;

  --text-h1: 24px;
  --text-h2: 20px;
  --text-h3: 16px;
  --text-body: 14px;
  --text-sm: 13px;
  --text-label: 12px;
  --text-overline: 11px;
  --fs-mono-sm: 0.75rem;
  --fs-mono: 0.875rem;
  --fs-title: clamp(1.5rem, 2.4vw, 1.75rem);

  --leading-snug: 1.35;
  --leading-normal: 1.55;
  --lh-title: 1.1;
  --tracking-tight: -0.01em;
  --tracking-label: 0.02em;
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  /* The rest of the scale's parts (DS-TOK-31, 35, 40, 45 to 49, 51, 53, 56). */
  --text-display: clamp(28px, 4vw, 44px);
  --text-num-lg: 34px;
  --text-num-md: 26px;
  --text-num-sm: 22px;
  --text-body-lg: 15px;
  --text-micro: 10px;
  --leading-none: 1;
  --lh-body: 1.4;
  --weight-light: 300;
  --tracking-display: -0.03em;
  --tracking-caps: 0.06em;

  /* -- The 23 text styles (DS-TOK-107 to 129, MP-1-4). A rule sets text by
        one style and only that way: `font: var(--type-x)` with
        `letter-spacing: var(--type-x-tracking)` and
        `text-transform: var(--type-x-case)` beside it, so nothing leaks in
        from a parent. `scripts/type-census.mjs` refuses any other size,
        weight, family, line height, tracking or case. The three figure
        sizes (`--type-num-*`) are kept apart from body text so a stat
        never reflows. ------------------------------------------------------ */
  --type-display: var(--weight-medium) var(--text-display)/var(--lh-title) var(--font-display);
  --type-display-tracking: var(--tracking-display);
  --type-display-case: none;
  --type-section: var(--weight-medium) var(--fs-title)/var(--lh-title) var(--font-display);
  --type-section-tracking: var(--tracking-tight);
  --type-section-case: none;
  --type-title: var(--weight-medium) var(--text-h1)/var(--lh-title) var(--font-display);
  --type-title-tracking: var(--tracking-tight);
  --type-title-case: none;
  --type-heading: var(--weight-medium) var(--text-h2)/var(--lh-title) var(--font-display);
  --type-heading-tracking: var(--tracking-tight);
  --type-heading-case: none;
  --type-subheading: var(--weight-medium) var(--text-h3)/var(--lh-title) var(--font-display);
  --type-subheading-tracking: var(--tracking-tight);
  --type-subheading-case: none;
  --type-rail-label: var(--weight-medium) var(--text-sm)/var(--lh-title) var(--font-display);
  --type-rail-label-tracking: var(--tracking-label);
  --type-rail-label-case: uppercase;
  --type-num-lg: var(--weight-medium) var(--text-num-lg)/var(--leading-none) var(--font-display);
  --type-num-lg-tracking: var(--tracking-display);
  --type-num-lg-case: none;
  --type-num-md: var(--weight-regular) var(--text-num-md)/var(--leading-none) var(--font-display);
  --type-num-md-tracking: 0.01em;
  --type-num-md-case: none;
  --type-num-sm: var(--weight-regular) var(--text-num-sm)/var(--leading-none) var(--font-display);
  --type-num-sm-tracking: 0.01em;
  --type-num-sm-case: none;
  --type-body-lg: var(--weight-regular) var(--text-body-lg)/var(--leading-normal) var(--font-sans);
  --type-body-lg-tracking: 0;
  --type-body-lg-case: none;
  --type-body: var(--weight-regular) var(--text-body)/var(--leading-normal) var(--font-sans);
  --type-body-tracking: 0;
  --type-body-case: none;
  --type-body-strong: var(--weight-medium) var(--text-body)/var(--leading-normal) var(--font-sans);
  --type-body-strong-tracking: 0;
  --type-body-strong-case: none;
  --type-card-title: var(--weight-semibold) var(--text-body-lg)/var(--lh-title) var(--font-sans);
  --type-card-title-tracking: 0;
  --type-card-title-case: none;
  --type-small: var(--weight-regular) var(--text-sm)/var(--leading-normal) var(--font-sans);
  --type-small-tracking: 0;
  --type-small-case: none;
  --type-small-strong: var(--weight-medium) var(--text-sm)/var(--leading-normal) var(--font-sans);
  --type-small-strong-tracking: 0;
  --type-small-strong-case: none;
  --type-caption: var(--weight-regular) var(--text-label)/var(--leading-normal) var(--font-sans);
  --type-caption-tracking: 0;
  --type-caption-case: none;
  --type-button: var(--weight-medium) var(--text-label)/var(--leading-none) var(--font-sans);
  --type-button-tracking: var(--tracking-tight);
  --type-button-case: none;
  --type-data: var(--weight-regular) var(--text-label)/var(--leading-normal) var(--font-mono);
  --type-data-tracking: 0;
  --type-data-case: none;
  --type-mono: var(--weight-regular) var(--text-body)/var(--leading-normal) var(--font-mono);
  --type-mono-tracking: 0;
  --type-mono-case: none;
  --type-eyebrow: var(--weight-light) var(--text-label)/var(--lh-body) var(--font-mono);
  --type-eyebrow-tracking: var(--tracking-label);
  --type-eyebrow-case: uppercase;
  --type-tag: var(--weight-light) var(--text-body)/var(--leading-normal) var(--font-mono);
  --type-tag-tracking: var(--tracking-label);
  --type-tag-case: uppercase;
  --type-chip: var(--weight-regular) var(--text-overline)/var(--leading-none) var(--font-mono);
  --type-chip-tracking: var(--tracking-caps);
  --type-chip-case: uppercase;
  --type-badge: var(--weight-regular) var(--text-micro)/var(--leading-none) var(--font-mono);
  --type-badge-tracking: 0;
  --type-badge-case: none;

  /* -- Icon sizes (DS-TOK-102 to DS-TOK-106). A door mark is sized from
        its host's text. ------------------------------------------------------ */
  --icon-xs: 8px;
  --icon-sm: 12px;
  --icon-md: 16px;
  --icon-lg: 24px;
  --icon-door: 0.85em;

  /* -- Layout. The rail's own ground is a quiet step off the page so the
        sidebar reads as furniture rather than paper. ---------------------- */
  --rail-w: 224px;
  --rail-bg: #f7f7f7;
  /* The dock's width is written by the shell, and it is the only writer. One
     number, one place, no second opinion. */
  --dock-w: 40px;
  --aip-dock: 380px;
  /* 224 rail + 836 measured content floor + 380 panel = 1440. The threshold is
     arithmetic and not taste [app.css:1226]; it is not a fifth breakpoint. */
  --content-floor: 836px;
}

/* -- Dark. THE PRIMITIVE BRIDGE, and it is not decoration ----------------
   Flipping only the semantic aliases would leave --ink literally black, which
   silently kills anything painted with var(--ink) against the void ground:
   invisible in review, obvious to a client. So the primitives flip and every
   alias cascades from them. A custom property's var() references substitute
   where the property is DECLARED, so the semantic names are re-declared here
   to re-resolve against the flipped primitives above.

   The attribute sits on <html>. The step in `apps/web/index.html` sets it
   before first paint, from a handed preference or else the system.

   Three primitives take the ruled value rather than their own: secondary
   ink is one value (--text-2's 72%), faint ink folds into --text-muted's
   55%, and the faint rule is the border. */
[data-theme='dark'] {
  --paper: oklch(0.145 0.006 285);
  --paper-cream: oklch(0.19 0.008 285);
  --ink: oklch(0.98 0 0);
  --ink-muted: var(--on-dark-muted);
  --ink-faint: color-mix(in oklch, var(--on-dark) 55%, transparent);
  --rule: oklch(1 0 0 / 0.24);
  --rule-faint: color-mix(in oklch, var(--on-dark) 10%, transparent);

  --bg: var(--void);
  --surface: color-mix(in oklch, var(--on-dark) 3%, var(--void));
  --surface-2: color-mix(in oklch, var(--on-dark) 7%, var(--void));
  --surface-3: color-mix(in oklch, var(--on-dark) 11%, var(--void));
  --border: color-mix(in oklch, var(--on-dark) 10%, transparent);
  --border-strong: color-mix(in oklch, var(--on-dark) 20%, transparent);
  --text: var(--on-dark);
  --text-2: var(--on-dark-muted);
  --text-muted: color-mix(in oklch, var(--on-dark) 55%, transparent);
  --text-dim: color-mix(in oklch, var(--on-dark) 36%, transparent);
  --scheme: dark;

  --btn-fill: var(--on-dark);
  --btn-text: var(--void);
  --btn-outline: color-mix(in oklch, var(--on-dark) 55%, transparent);
  /* Outline controls go monochrome on hover in the dark: accent-on-dark
     contrast is too low. The solid button keeps the accent, on a light fill. */
  --hover-accent: var(--text);
  --accent-ring: color-mix(in oklch, var(--accent) 55%, transparent);

  --info: #38b6f1;
  --success: #34d399;
  --warning: #fbbf24;
  --danger: #f87171;

  --shadow-sm: 0 1px 2px rgb(0 0 0 / 45%);
  --shadow: 0 1px 3px rgb(0 0 0 / 50%), 0 18px 42px -24px rgb(0 0 0 / 70%);
  --shadow-lg: 0 2px 8px rgb(0 0 0 / 50%), 0 30px 80px -34px rgb(0 0 0 / 85%);
  --focus-ring: 0 0 0 2px var(--void), 0 0 0 4px var(--accent);
  --rail-bg: var(--bg);

  --app-chrome: oklch(0.255 0.007 285);
  /* The hue shifts so it never reads as the accent over the void. */
  --mock-pink: oklch(0.78 0.2 358);
  --mock-tint: color-mix(in oklab, var(--mock-pink) 20%, transparent);
  --mock-edge: color-mix(in oklab, var(--mock-pink) 48%, transparent);
}

/* The resets the Hub serves from its application entry rather than from a
   stylesheet, carried here because this package has no other entry. */
*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  color-scheme: var(--scheme);
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
  /* The mockup's base rendering: without it every glyph draws a shade heavier. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
/* Faux bold: no 700 face is loaded, so strong text is the medium weight. */
b,
strong {
  /* type-exception DS-TOK-118: strong keeps its host's size at the medium weight */
  font-weight: var(--weight-medium);
}
img,
canvas,
svg {
  display: block;
  max-width: 100%;
}
:where(a) {
  color: inherit;
}
:where(button) {
  font: inherit;
  color: inherit;
}
/* Inline code in running text: the mono style, never the browser's monospace. */
:where(code, kbd, samp) {
  font: var(--type-mono);
  letter-spacing: var(--type-mono-tracking);
  text-transform: var(--type-mono-case);
}
:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
/* SPDX-License-Identifier: AGPL-3.0-only
   ============================================================================
   Layer 2 of 3, first half: the component kit's controls and marks (MP-1-3):
   actions, fields, the segmented control, tabs, containers, status, marks,
   the three absence voices and the icon (the banner is in the second half,
   beside the blocks). The second half,
   2-primitives.css, loads straight after it (packages/ui/src/index.ts), so
   the two read as one sheet in this order; its header holds the rules for
   the whole layer.
   ============================================================================ */

/* -- Actions (DS-PRIM-1, DS-PRIM-2, MP-1-3). ----------------------------
   One focus ring, the global one (DR-1): nothing here draws an outline. A bare
   `.btn` is the secondary button, so an unmarked button is never invisible;
   its border is the mockup's outline strength, --btn-outline (full ink on
   light, on-dark at 55% in dark).
   `sm` is the house size and the base; `md` pairs with a 38 input (DR-21). */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6.6px;
  height: 27px;
  padding: 0 11.4px;
  border: 1px solid var(--btn-outline);
  border-radius: 0;
  background: transparent;
  color: var(--text);
  font: var(--type-button);
  letter-spacing: var(--type-button-tracking);
  text-transform: var(--type-button-case);
  white-space: nowrap;
  cursor: pointer;
  transition:
    background var(--dur-1) var(--ease),
    color var(--dur-1) var(--ease),
    border-color var(--dur-1) var(--ease),
    transform var(--dur-1) var(--ease);
}
.btn:active:not(:disabled) {
  transform: translateY(1px);
}
.btn:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}
.btn--sm {
  height: 27px;
  padding: 0 11.4px;
}
.btn--md {
  height: 38px;
  padding: 0 14px;
  /* type-exception DS-TOK-123: the 13 px size variant of the button label */
  font-size: var(--text-sm);
}
.btn--lg {
  height: 43px;
  padding: 12.75px 22.5px;
  /* type-exception DS-TOK-123: the 15 px size variant of the button label (R53) */
  font-size: var(--text-body-lg);
}
.btn--primary {
  border-color: transparent;
  background: var(--text);
  color: var(--bg);
}
.btn--primary:hover:not(:disabled) {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--accent-ink);
}
/* DR-22: a disabled primary is an outline, never a grey fill. */
.btn--primary:disabled {
  border-color: var(--border);
  background: transparent;
  color: var(--text-muted);
  opacity: 1;
}
.btn--secondary:hover:not(:disabled) {
  border-color: var(--text);
  background: var(--text);
  color: var(--bg);
}
/* The filter-preset toggle, pressed (DR-20). */
.btn[aria-pressed='true'] {
  background: var(--text);
  color: var(--bg);
}
.btn--ghost {
  border-color: transparent;
  color: var(--text-2);
}
.btn--ghost:hover:not(:disabled) {
  color: var(--accent);
}
.btn--text {
  height: auto;
  padding: 0;
  border-color: transparent;
  color: var(--text-2);
}
.btn--text:hover:not(:disabled) {
  text-decoration: underline;
}

.ibtn {
  display: inline-grid;
  place-items: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}
.ibtn:hover:not(:disabled) {
  color: var(--text);
}
.ibtn:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}
.ibtn--compact {
  width: 22px;
  height: 22px;
}
.ibtn--danger:hover:not(:disabled) {
  color: var(--danger);
}
.ibtn--accent {
  transition:
    color var(--dur-fast) var(--ease),
    transform var(--dur-fast) var(--ease);
}
.ibtn--accent:hover:not(:disabled) {
  color: var(--accent);
  transform: scale(1.12);
}
/* DR-24: row tools wait for the row's hover above 900, and always show on
   focus and on touch-width screens. */
.ibtn--reveal {
  opacity: 0;
}
:hover > .ibtn--reveal,
.ibtn--reveal:focus-visible {
  opacity: 1;
}
@media (width <= 900px) {
  .ibtn--reveal {
    opacity: 1;
  }
}
.disclosure .icon {
  transition: transform var(--dur-fast) var(--ease);
}
.disclosure[aria-expanded='true'] .icon {
  transform: rotate(90deg);
}

/* -- Fields (DS-PRIM-3 to DS-PRIM-7, DS-PRIM-9, DS-PRIM-19). -------------
   One paper field ground on both faces (DR-25). Focus moves the border to the
   accent; the global ring still shows for the keyboard. */
.field {
  display: grid;
  gap: var(--s-1-5);
  min-width: 0;
}
.field__label {
  color: var(--text-muted);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
.tf,
.ta {
  width: 100%;
  min-width: 0;
  padding: 7.2px 12px;
  border: 1px solid var(--border);
  border-radius: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}
.tf {
  height: 38px;
}
.ta {
  min-height: 6rem;
  resize: vertical;
}
.tf::placeholder,
.ta::placeholder,
.search__in::placeholder {
  color: var(--text-muted);
}
.tf:focus,
.ta:focus,
.sel__btn:focus,
.sel__btn[aria-expanded='true'] {
  border-color: var(--accent);
}
.tf:disabled,
.ta:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}
/* A secret's value (C31): drawn masked, but no password field, so no password manager saves or fills it. */
.tf--sealed {
  -webkit-text-security: disc;
}
.tf--inline {
  height: auto;
  padding: 0;
  border: 0;
  border-bottom: 1px solid transparent;
  background: transparent;
  font: inherit;
}
.tf--inline:focus {
  border-bottom-color: var(--accent);
}
.sel {
  position: relative;
}
.sel__btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  width: 100%;
  height: 37px;
  padding: 8.8px 12px;
  border: 1px solid var(--border);
  border-radius: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
  text-align: left;
  cursor: pointer;
}
.sel__btn:hover:not(:disabled) {
  border-color: var(--border-strong);
}
.sel__btn:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}
.sel__caret {
  width: 0;
  height: 0;
  border-top: 5px solid currentColor;
  border-right: 4px solid transparent;
  border-left: 4px solid transparent;
}
.menu {
  position: absolute;
  z-index: 30;
  top: calc(100% + 4px);
  left: 0;
  min-width: 100%;
  margin: 0;
  padding: var(--s-1) 0;
  list-style: none;
  border: 1px solid var(--accent);
  background: var(--bg);
  box-shadow: var(--shadow-overlay);
}
.menu__opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding: 6px 12px;
  color: var(--text-2);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  cursor: pointer;
}
.menu__opt:hover,
.menu__opt.is-active {
  background: var(--surface-2);
  color: var(--text);
}
.menu__opt[aria-selected='true'] {
  color: var(--accent);
}
.search {
  display: flex;
  align-items: center;
  gap: 7.2px;
  height: 34px;
  padding: 4.8px 8.8px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text-muted);
}
.search:focus-within {
  border-color: var(--accent);
}
.search__in {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--text);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
  outline: none;
}
.keycap {
  padding: 0 4px;
  border: 1px solid var(--border-strong);
  color: var(--text-muted);
  font: var(--type-chip);
  letter-spacing: var(--type-chip-tracking);
  text-transform: var(--type-chip-case);
}
.check {
  display: inline-grid;
  place-items: center;
  width: 18px;
  height: 18px;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: 0;
  background: var(--bg);
  color: var(--accent);
  cursor: pointer;
}
.check:hover:not(:disabled) {
  border-color: var(--accent);
}
.check[aria-checked='true'] {
  border-color: var(--accent);
}
.switch {
  display: inline-flex;
  align-items: center;
  width: 42px;
  height: 20px;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: 0;
  background: var(--surface);
  cursor: pointer;
}
.switch:hover:not(:disabled) {
  border-color: var(--border-strong);
}
.switch:focus-visible {
  border-color: var(--accent);
}
.switch:disabled {
  border-style: dashed;
  cursor: not-allowed;
}
.switch__knob {
  width: 14px;
  height: 14px;
  border: 1px solid var(--border-strong);
  transition: transform var(--dur-fast) var(--ease);
}
.switch[aria-checked='true'] {
  border-color: var(--success);
}
.switch[aria-checked='true'] .switch__knob {
  border-color: var(--success);
  background: var(--success);
  transform: translateX(20px);
}

/* -- Segmented control and facet (DS-PRIM-10). Both have a hover rule (SHELL
      I8). Pressed segmented is an ink fill; a pressed facet is an accent
      outline and no fill. -- */
.segmented {
  display: inline-flex;
  border: 1px solid var(--border-strong);
}
.segmented__opt {
  height: 30px;
  padding: 5.6px 11.2px;
  border: 0;
  border-right: 1px solid var(--border);
  background: transparent;
  color: var(--text-2);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease);
}
.segmented__opt:last-child {
  border-right: 0;
}
.segmented__opt:hover:not([aria-pressed='true']) {
  color: var(--text);
}
.segmented__opt[aria-pressed='true'] {
  background: var(--text);
  color: var(--bg);
}
.segmented__opt:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}
.facets {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}
.facet {
  display: inline-flex;
  align-items: center;
  gap: 7.2px;
  height: 34px;
  padding: 5.6px 11.2px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-2);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  cursor: pointer;
  transition:
    color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.facet:hover {
  border-color: var(--border-strong);
  color: var(--text);
}
.facet[aria-pressed='true'] {
  border-color: var(--accent);
  color: var(--text);
}
.facet__num {
  color: var(--text-muted);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

/* -- Tabs. Anchors and buttons wear the same dress, so a tab can be opened
      in a new tab with a modifier click and pick up no browser link dress. -- */
.tabs {
  position: relative;
  display: flex;
  gap: var(--s-5);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
.tab {
  display: inline-flex;
  align-items: baseline;
  gap: var(--s-2);
  padding: 0 0 0.65rem;
  margin-bottom: -1px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--text-muted);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    color var(--dur) var(--ease),
    border-color var(--dur) var(--ease);
}
.tab:hover {
  color: var(--text);
}
.tab[aria-selected='true'] {
  color: var(--text);
  border-bottom-color: var(--accent);
  font: var(--type-body-strong);
  letter-spacing: var(--type-body-strong-tracking);
  text-transform: var(--type-body-strong-case);
}

/* -- Containers ---------------------------------------------------------- */
.card__body {
  color: var(--text-2);
}
.sec {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}
.sec__head {
  margin: 0;
  font: var(--type-section);
  letter-spacing: var(--type-section-tracking);
  text-transform: var(--type-section-case);
}
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}
.grid {
  display: grid;
  gap: var(--s-4);
}
.g3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (width <= 640px) {
  .g3 {
    grid-template-columns: minmax(0, 1fr);
  }
}
/* -- Status. An outline, a number or a line, never a fill. ---------------- */
/* The pinned mockup has NO base .spill rule: it is five colour declarations
   and nothing else, which is the anti-fill law drawn rather than described. */
.spill[data-tone='wait'] {
  color: var(--text-muted);
}
.spill[data-tone='run'] {
  color: var(--info);
}
.spill[data-tone='gate'] {
  color: var(--warning);
}
.spill[data-tone='done'] {
  color: var(--success);
}
.spill[data-tone='bad'] {
  color: var(--danger);
}
/* -- Marks (DS-PRIM-11 to DS-PRIM-18, DS-PRIM-25 to DS-PRIM-27, MP-1-3). */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 5.5px;
  padding: 3.3px 8.25px;
  border: 1px solid var(--text-2);
  border-radius: var(--radius-pill);
  background: color-mix(in oklch, var(--surface-2) 50%, var(--bg));
  color: var(--text-2);
  font: var(--type-chip);
  letter-spacing: var(--type-chip-tracking);
  text-transform: var(--type-chip-case);
  white-space: nowrap;
}
.chip--soft {
  border-color: var(--border);
  color: var(--text);
}
.chip.is-ok,
.smark.is-ok {
  border-color: var(--success);
  color: var(--success);
}
.chip.is-warn,
.smark.is-warn {
  border-color: var(--warning);
  color: var(--warning);
}
.chip.is-bad,
.smark.is-bad {
  border-color: var(--danger);
  color: var(--danger);
}
.chip.is-info,
.smark.is-info {
  border-color: var(--info);
  color: var(--info);
}
.chip.is-idle,
.smark.is-idle {
  border-color: var(--text-muted);
  color: var(--text-muted);
}
.chip--filter {
  border-color: var(--accent);
  color: var(--text);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.chip__key {
  color: var(--text-muted);
}
.chip__x {
  display: inline-grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-muted);
  cursor: pointer;
}
.chip__x:hover {
  color: var(--text);
}
.chip--suggestion {
  border-color: var(--border);
  color: var(--text-2);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  cursor: pointer;
  transition:
    color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.chip--suggestion:hover {
  border-color: var(--accent);
  color: var(--text);
}
.smark {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}
.sline {
  display: inline-block;
  width: 2px;
  height: 11px;
  background: currentColor;
}
.snode {
  display: inline-block;
  width: 9px;
  height: 9px;
  border: 1px solid currentColor;
}
.sline.is-ok,
.snode.is-ok {
  color: var(--success);
}
.sline.is-warn,
.snode.is-warn {
  color: var(--warning);
}
.sline.is-bad,
.snode.is-bad {
  color: var(--danger);
}
.sline.is-info,
.snode.is-info {
  color: var(--info);
}
.sline.is-idle,
.snode.is-idle {
  color: var(--text-muted);
}
.av {
  display: inline-grid;
  place-items: center;
  flex: none;
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
}
.av--person {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: color-mix(in oklch, var(--text) 12%, transparent);
  color: var(--text);
}
.av--person-large {
  width: 36px;
  height: 36px;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text);
  font: var(--type-chip);
  letter-spacing: var(--type-chip-tracking);
  text-transform: var(--type-chip-case);
}
.av--person-large.is-on {
  border-color: var(--accent);
}
.av--person-large.is-away {
  border-style: dashed;
}
.av--client {
  width: 26px;
  height: 26px;
  border: 1px solid var(--border-strong);
  background: var(--bg);
  color: var(--text-2);
}
.avstack {
  display: inline-flex;
}
.avstack .av + .av {
  margin-left: -0.18rem;
}
.avstack .av {
  box-shadow: 0 0 0 1px var(--bg);
}
.avstack .av.is-here {
  box-shadow: 0 0 0 1px var(--accent);
}
.door {
  display: inline-flex;
  margin-left: 0.25em;
  opacity: 0.62;
}
.door .icon {
  width: var(--icon-door);
  height: var(--icon-door);
}
/* The explained word and its bubble. Shown on hover and on keyboard focus. */
.term {
  position: relative;
  border-bottom: 1px dotted var(--text-muted);
  cursor: help;
}
.term__tip {
  position: absolute;
  z-index: 40;
  top: calc(100% + 7px);
  left: 0;
  display: none;
  width: max-content;
  max-width: 260px;
  padding: 0.5rem 0.7rem;
  background: var(--void);
  color: var(--on-dark);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.term:hover .term__tip,
.term:focus-visible .term__tip {
  display: block;
}
.term--end .term__tip {
  right: 0;
  left: auto;
}
.marker {
  font: var(--type-tag);
  letter-spacing: var(--type-tag-tracking);
  text-transform: var(--type-tag-case);
}
.u-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  color: var(--text);
}
.u-tag::before {
  width: 6px;
  height: 6px;
  background: currentColor;
  content: '';
}
.keytag {
  color: var(--text-muted);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
.kind {
  display: inline-flex;
  align-items: center;
  gap: 7.2px;
  color: var(--accent);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
.kind__glyph {
  width: 6px;
  height: 6px;
  border: 1px solid currentColor;
  transform: rotate(45deg);
}
.index {
  color: var(--text-muted);
  font: var(--type-mono);
  letter-spacing: var(--type-mono-tracking);
  text-transform: var(--type-mono-case);
}
.index__k {
  color: var(--text);
}
.ttl {
  color: var(--text-muted);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.ttl.is-soon,
.ttl.is-expired {
  color: var(--warning);
}
.chlink {
  border-bottom: 1px dotted var(--text-muted);
  color: var(--text-muted);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  text-decoration: none;
}
.chlink:hover,
.chlink:focus-visible {
  border-bottom-color: var(--accent);
  color: var(--accent);
}
.plink {
  color: inherit;
  text-decoration-color: var(--accent);
}
.plink:hover,
.plink:focus-visible {
  color: var(--accent);
}
.doorlink {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  color: var(--text-muted);
}
.doorlink:hover,
.doorlink:focus-visible {
  color: var(--accent);
}
.rule {
  width: 100%;
  height: 0;
  margin: 0;
  border: 0;
  border-top: 1px solid var(--border);
}
.rule--section {
  border-top-color: var(--rule);
}
.vdiv {
  display: inline-block;
  width: 1px;
  height: 20px;
  background: var(--border);
}
.u-mono {
  font: var(--type-tag);
  letter-spacing: var(--type-tag-tracking);
  text-transform: var(--type-tag-case);
}
/* The count badge is absence-honest at its call site: zero renders nothing at
   all rather than a zero, because a badge saying 0 is a badge saying look. */
.cbadge {
  display: inline-grid;
  place-items: center;
  min-width: 1rem;
  height: 1rem;
  padding: 0 0.15rem;
  background: var(--accent);
  color: var(--accent-ink);
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
}
.cbadge--plain {
  background: none;
  color: inherit;
}
.cbadge--corner {
  position: absolute;
  top: -4px;
  right: -4px;
}
:hover > .cbadge--corner,
:focus-visible > .cbadge--corner {
  background: var(--text);
  color: var(--bg);
}
.cbadge--numeral {
  width: 17px;
  height: 17px;
  background: var(--text);
  color: var(--bg);
}
.cbadge--inline {
  background: none;
  color: var(--text-muted);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
/* -- Voice one: no rows. ------------------------------------------------- */
/* -- Voice two: this input is wrong. Red is legitimate status here, because
      the field IS in an error state. ------------------------------------- */
/* DS-PRIM-30's field error (adopted at build-ready). */
[aria-invalid='true'] {
  border-color: var(--danger);
}
.field__error {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  color: var(--danger);
}
.field__hint {
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  color: var(--text-muted);
}

/* -- Voice three: the product has not built this yet. --------------------
   ZERO SPECIFICITY ON PURPOSE. :where() makes this a DEFAULT rather than a
   fight, so a surface that already owns an absence voice keeps it with a plain
   class and only a surface with no voice of its own falls back to here. The
   token is --text-2 rather than --text-dim: --text-dim is documented as
   non-essential metadata only and measures about 2.07:1 on paper, which fails
   WCAG 1.4.3 outright, and a low-vision reader would see a blank cell, the
   broken reading this voice exists to prevent. No colour, no decoration: it
   states a fact about the product, it is not a status. */
:where(.in-dev) {
  color: var(--text-2);
}
.empty--in-dev .empty__title {
  color: var(--text-2);
}

/* The icon (DS-PRIM-17, MP-1-2). Stroked glyphs in the text's colour, sized by
   the icon tokens, sitting on the text's middle. */
.icon {
  display: inline-block;
  flex: none;
  width: var(--icon-md);
  height: var(--icon-md);
  vertical-align: middle;
  color: inherit;
}
.icon--xs {
  width: var(--icon-xs);
  height: var(--icon-xs);
}
.icon--sm {
  width: var(--icon-sm);
  height: var(--icon-sm);
}
.icon--lg {
  width: var(--icon-lg);
  height: var(--icon-lg);
}
/* DS-PRIM-32: sample data only. The edge is inset so the mark never moves
   layout, and a marked region inside another keeps only its edge. */
.is-mock {
  position: relative;
  background: var(--mock-tint);
  box-shadow: inset 0 0 0 1px var(--mock-edge);
}
.is-mock--nested,
.is-mock .is-mock {
  background: none;
}
.mocktag {
  padding: 0 0.3rem;
  border: 1px solid var(--border);
  color: var(--text-muted);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
/* The one shared mock label: the region's top-right corner, taking no layout. */
.is-mock > .mocktag {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 1;
  background: var(--bg);
}
/* SPDX-License-Identifier: AGPL-3.0-only
   ============================================================================
   Layer 2 of 3: the component kit (MP-1-3), built once from the catalogue
   (`docs/design-system/catalogue/PRIMITIVES.md` in the roadmap) and shown on
   the component gallery. Values are the catalogue's measurements; where the
   mockup drew one thing several ways, the catalogue's ruling (a DR id) picks
   the one built here. The chip is `.chip` (DS-PRIM-11), and a bare `.btn` is
   the secondary button (DS-PRIM-1).

   THREE ABSENCE VOICES, and they must stay distinct. `.empty` says no rows;
   `[aria-invalid]` plus `.field__error` says this input is wrong; `.in-dev`
   says the product has not built this yet. The third is a HUB-ONLY idiom —
   the string `in-dev` does not occur anywhere in the pinned mockup, which
   ships populated demonstration data — so it is adopted as the starting point
   for new work with its own acceptance, not as an inherited authority
   [ui-reference CONTRACT.md:176].

   The layer is two sheets, loaded in this order: 2-controls-and-marks.css
   (actions to the icon), then this one (blocks, the MP-1-6 treatments, the
   charts and the gallery page).
   ============================================================================ */

/* -- Blocks (DS-PRIM-20, DS-PRIM-21, DS-PRIM-23, DS-PRIM-24, DS-PRIM-28 to
      DS-PRIM-33, DS-COMP-7, DS-COMP-8, DS-COMP-13, DS-COMP-26; MP-1-3). -- */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.tablewrap {
  display: grid;
  gap: var(--s-2);
  overflow-x: auto;
}
.table__tools {
  display: flex;
  justify-content: flex-end;
}
.table {
  width: 100%;
  border-collapse: collapse;
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}
/* The one table head style: the mockup's two dialects become this. */
.table th {
  position: relative;
  padding: 8.8px 16px;
  border-bottom: 1px solid var(--rule);
  color: var(--text-muted);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  text-align: left;
  white-space: nowrap;
}
.table td {
  padding: 0.65rem 16px;
  border-bottom: 1px solid var(--border);
  color: var(--text-2);
}
.table tbody tr {
  transition: background var(--dur-fast) var(--ease);
}
.table tbody tr:hover {
  background: var(--surface-2);
}
.table--dense td {
  padding: 0.4rem 16px;
}
.table .r {
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.table .c {
  text-align: center;
}
.table__sort {
  display: inline-flex;
  gap: var(--s-1);
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
}
.table__sort:hover {
  color: var(--text);
  text-decoration: underline;
}
.table th[aria-sort='ascending'],
.table th[aria-sort='descending'] {
  color: var(--text);
}
.table th[aria-sort='ascending'] .table__arrow,
.table th[aria-sort='descending'] .table__arrow {
  color: var(--accent);
}
@media (width <= 640px) {
  .table {
    min-width: 44rem;
  }
}
.card {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  min-width: 0;
  padding: var(--s-5);
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  transition: border-color var(--dur-1) var(--ease);
}
.card > * {
  min-width: 0;
}
.card--flush {
  padding: 0;
}
.card--current {
  border-color: var(--accent);
  box-shadow: inset 3px 0 0 var(--accent);
}
.card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
}
.card--flush .card__head {
  padding: var(--s-5) var(--s-5) 0;
}
.card__title {
  margin: 0;
  font: var(--type-card-title);
  letter-spacing: var(--type-card-title-tracking);
  text-transform: var(--type-card-title-case);
}
.card__sub {
  margin: 0;
  color: var(--text-muted);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.doorcard {
  display: grid;
  gap: var(--s-1);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  text-decoration: none;
  transition:
    border-color var(--dur-1) var(--ease),
    background var(--dur-fast) var(--ease);
}
.doorcard--card {
  padding: var(--s-5);
}
.doorcard--card:hover {
  border-color: var(--accent);
}
.doorcard--row {
  padding: 16px 24px;
  border-width: 1px 0 0;
  background: transparent;
}
.doorcard--row:hover {
  background: var(--surface-2);
}
.doorcard--cta {
  padding: var(--s-4) var(--s-5);
  box-shadow: inset 3px 0 0 var(--accent);
}
.doorcard--cta:hover {
  border-color: var(--accent);
}
.doorcard__title {
  font: var(--type-card-title);
  letter-spacing: var(--type-card-title-tracking);
  text-transform: var(--type-card-title-case);
}
.doorcard__sub {
  color: var(--text-muted);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.lrow {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 16px 24px;
  border-top: 1px solid var(--border);
  list-style: none;
  transition: background var(--dur-fast) var(--ease);
}
.lrow:hover {
  background: var(--surface-2);
}
.lrow__lead:empty {
  display: none;
}
/* A row with no lead slot gives the lead's column (and its gap) to the main one. */
.lrow:not(:has(> .lrow__lead)) {
  grid-template-columns: minmax(0, 1fr) auto;
}
.lrow:not(:has(> .lrow__lead)) > * {
  grid-column: auto;
}
.lrow__main {
  display: grid;
  min-width: 0;
  grid-column: 2;
}
.lrow__title {
  color: var(--text);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}
.lrow__meta {
  color: var(--text-muted);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.lrow__trail {
  grid-column: 3;
}
.lrow--panel {
  padding: 9px 20px;
}
.lrow--notice {
  box-shadow: inset 2px 0 0 var(--accent);
}
.lrow--record {
  grid-template-columns: minmax(8rem, 1fr) minmax(0, 2fr);
}
.lrow[data-state='selected'] {
  background: var(--surface-2);
}
.lrow[data-state='done'] .lrow__title {
  color: var(--text-muted);
  text-decoration: line-through;
}
.lrow[data-state='archived'] .lrow__title {
  color: var(--text-2);
}
@media (width <= 390px) {
  .lrow[data-state='gate'] .lrow__trail {
    grid-column: 1 / -1;
  }
}
.form {
  display: grid;
  gap: var(--s-4);
  padding: var(--s-4);
  background: var(--surface-2);
}
.form__grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--s-4);
}
.form__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--s-2);
}
@media (width <= 1279px) {
  .form__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}
@media (width <= 900px) {
  .form__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (width <= 640px) {
  .form__grid {
    grid-template-columns: minmax(0, 1fr);
  }
}
/* -- Banner and tip (DS-PRIM-22). `--hint` is the agent's aside (DR-5): no
   box, a 1px accent rule on the one wash (DR-11). ------------------------ */
.banner {
  display: flex;
  align-items: flex-start;
  gap: var(--s-4);
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-left: 2px solid var(--warning);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}
.banner__body {
  flex: 1;
  margin: 0;
}
.banner--bad {
  border-left-color: var(--danger);
}
.banner--info {
  border-left-color: var(--info);
}
.banner--hint {
  gap: var(--s-2);
  padding: var(--s-2) var(--s-3);
  border: 0;
  border-left: 1px solid var(--accent);
  background: var(--accent-wash);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  color: var(--text-2);
}
.banner__mark {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  color: var(--accent);
}
@media print {
  .banner--info {
    display: none;
  }
}
.meter {
  position: relative;
  display: block;
  width: 100%;
  height: 6px;
  background: var(--surface-3);
}
.meter__fill {
  display: block;
  height: 100%;
  background: var(--text);
}
.meter.is-ok .meter__fill {
  background: var(--success);
}
.meter.is-warn .meter__fill {
  background: var(--warning);
}
.meter.is-bad .meter__fill,
.meter.is-over .meter__fill {
  background: var(--danger);
}
.meter.is-info .meter__fill {
  background: var(--info);
}
.meter.is-idle .meter__fill {
  background: var(--text-muted);
}
.meter--stat {
  height: 3px;
  background: var(--border);
}
.meter--stat .meter__fill,
.meter--time .meter__fill {
  background: var(--accent);
}
.meter--time {
  height: 4px;
  background: var(--border);
}
.meter__target {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 1px;
  background: var(--text);
}
.stat {
  display: grid;
  gap: 8px;
  padding: 16px 24px 16px 0;
}
.stat__label {
  color: var(--text-muted);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
.stat__num {
  font: var(--type-num-lg);
  letter-spacing: var(--type-num-lg-tracking);
  text-transform: var(--type-num-lg-case);
  font-variant-numeric: tabular-nums;
}
.stat__of {
  color: var(--text-muted);
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
}
.stat__foot {
  color: var(--text-muted);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
/* The tile in a stat row (DS-COMP-6): the row's padding, and the number a
   step down at 640 and under. */
.stat--row {
  padding: var(--s-4) var(--s-5) var(--s-4) 0;
}
@media (width <= 640px) {
  .stat--row .stat__num {
    font: var(--type-num-md);
    letter-spacing: var(--type-num-md-tracking);
    text-transform: var(--type-num-md-case);
  }
}
/* DS-PRIM-29 (DR-37): a skeleton at the size of what it stands for. A slow
   pulse, and none at all under reduced motion. */
.skel {
  display: block;
  background: var(--surface-2);
  animation: skel-pulse var(--dur-2) ease-in-out infinite alternate;
}
.skel--field {
  width: 100%;
  height: 38px;
}
.skel--line {
  width: 60%;
  height: 0.9em;
}
.skel--tile {
  width: 10rem;
  height: 5rem;
}
@keyframes skel-pulse {
  to {
    opacity: 0.55;
  }
}
@media (prefers-reduced-motion: reduce) {
  .skel {
    animation: none;
  }
}
.rownote {
  margin: 0;
  color: var(--text-2);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
/* DS-PRIM-33: one accent ring pulse where a link landed. */
.flash-target {
  animation: locate-flash var(--dur-flash) var(--ease) 1;
}
@keyframes locate-flash {
  from {
    box-shadow: 0 0 0 3px color-mix(in oklch, var(--accent) 75%, transparent);
  }
  to {
    box-shadow: 0 0 0 3px transparent;
  }
}
@media (prefers-reduced-motion: reduce) {
  .flash-target {
    animation: none;
    box-shadow: 0 0 0 3px color-mix(in oklch, var(--accent) 75%, transparent);
  }
}
.popover {
  position: absolute;
  z-index: 30;
  top: calc(100% + 4px);
  right: 0;
  display: grid;
  gap: 12px;
  width: 352px;
  max-width: calc(100vw - 32px);
  padding: 12px;
  border: 1px solid var(--border-strong);
  background: var(--bg);
  box-shadow: var(--shadow-overlay);
}

/* -- Not connected, unavailable and freshness (MP-1-6). No hatch and no pink
      here: pink is for sample data on a demo install only (R56). -- */
.notconn {
  display: grid;
  gap: var(--s-2);
  padding: var(--s-5);
  border: 1px dashed var(--border-strong);
  color: var(--text-2);
}
.notconn > p {
  margin: 0;
}
.notconn__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s-3);
}
.notconn__word {
  color: var(--text);
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
}
.notconn__source {
  color: var(--text-muted);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
.notconn__reason {
  max-width: 60ch;
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.unavail {
  display: inline-flex;
  border-bottom: 0;
  cursor: not-allowed;
}
.freshrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
}
/* An indicator: the bordered mono look in its one state, no hover, no press. */
.fresh {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1-5);
  padding: 4px 8px;
  border: 1px solid var(--border);
  color: var(--text-muted);
  font: var(--type-chip);
  letter-spacing: var(--type-chip-tracking);
  text-transform: var(--type-chip-case);
  cursor: default;
}
.fresh__live {
  width: 6px;
  height: 6px;
  border: 1px solid var(--success);
}
.fresh--offline,
.fresh--source-behind {
  color: var(--warning);
}

/* -- The stamp (DS-PRIM-25): a timestamp or provenance line. ------------- */
.stamp {
  color: var(--text-muted);
  font: var(--type-chip);
  letter-spacing: var(--type-chip-tracking);
  text-transform: var(--type-chip-case);
}

/* -- Charts (MP-1-5: DS-COMP-27, 28, 29 and 40). Hand-drawn SVG. Colour
      comes from a tone through currentColor, so no chart names a colour and
      every one follows the theme; text is set by the type scale. ---------- */
.chart {
  min-width: 0;
  margin: 0;
  color: var(--text);
}
.chart__frame {
  position: relative;
  width: 100%;
}
.chart--radial .chart__frame {
  width: max-content;
}
.chart svg,
.spark {
  display: block;
  overflow: visible;
}
[data-tone='accent'] {
  color: var(--accent);
}
[data-tone='ink'] {
  color: var(--text);
}
[data-tone='muted'] {
  color: var(--text-muted);
}
[data-tone='info'] {
  color: var(--info);
}
[data-tone='ok'] {
  color: var(--success);
}
[data-tone='warn'] {
  color: var(--warning);
}
[data-tone='bad'] {
  color: var(--danger);
}
.chart__plot {
  fill: none;
}
.chart__grid {
  stroke: currentColor;
  opacity: 0.09;
}
/* Axis labels in mono 10 at 45%. */
.chart__axis {
  fill: currentColor;
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
  opacity: 0.45;
}
.chart__axis-title {
  fill: currentColor;
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
  opacity: 0.7;
}
.chart__line {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.spark .chart__line {
  stroke-width: 1.5;
}
.chart__area {
  fill: currentColor;
  opacity: 0.1;
}
.spark .chart__area {
  opacity: 0.09;
}
.chart__dot,
.chart__end {
  fill: currentColor;
}
.chart__bar {
  fill: currentColor;
  opacity: 0.9;
}
.is-active > .chart__bar {
  opacity: 1;
}
.chart__cursor {
  stroke: currentColor;
  stroke-dasharray: 2 3;
  opacity: 0.35;
}
/* The hover and focus targets: invisible, with a ring when the keyboard is on one. */
.chart__hit {
  fill: transparent;
  outline: none;
}
/* The keyboard's ring is the cursor line, drawn solid while a point has focus. */
.chart__frame:has(.chart__hit:focus-visible) .chart__cursor {
  stroke: var(--accent);
  stroke-dasharray: none;
  stroke-width: 1.5;
  opacity: 1;
}
/* The donut's slices by index, in the mockup's chart paint order. */
[data-paint='ink'] {
  color: var(--ink);
}
[data-paint='accent'] {
  color: var(--accent);
}
[data-paint='lilac'] {
  color: var(--lilac);
}
[data-paint='deep'] {
  color: var(--lilac-deep);
}
[data-paint='muted'] {
  color: var(--ink-muted);
}
[data-paint='faint'] {
  color: var(--ink-faint);
}
.chart__slice {
  fill: currentColor;
  opacity: 0.92;
  outline: none;
}
.chart__slice:hover,
.chart__slice:focus-visible {
  opacity: 1;
  stroke: var(--text);
  stroke-width: 1.5;
}
.chart__tip {
  position: absolute;
  z-index: 40;
  display: grid;
  gap: 2px;
  width: max-content;
  max-width: 260px;
  padding: 0.5rem 0.7rem;
  transform: translate(-50%, calc(-100% - 8px));
  background: var(--void);
  color: var(--on-dark);
  pointer-events: none;
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.chart__tip-title {
  color: var(--on-dark-muted);
}
.chart__tip-value {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.chart__centre {
  fill: currentColor;
  font: var(--type-heading);
  letter-spacing: var(--type-heading-tracking);
  text-transform: var(--type-heading-case);
}
.chart__centre-label {
  fill: currentColor;
  opacity: 0.5;
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
}
.chart__track {
  fill: none;
  stroke: currentColor;
  stroke-width: 9;
  opacity: 0.12;
}
.chart__arc {
  fill: none;
  stroke: currentColor;
  stroke-width: 9;
}
.chart__target {
  stroke: currentColor;
  stroke-width: 1.5;
}
.chart__value {
  fill: currentColor;
  font: var(--type-heading);
  letter-spacing: var(--type-heading-tracking);
  text-transform: var(--type-heading-case);
}
.dials {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-5) var(--s-6);
}
/* The score dial: the ring takes the band's colour (0 to 49, 50 to 89, 90 up). */
.dial {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45rem;
}
.dial.is-ok {
  color: var(--success);
}
.dial.is-warn {
  color: var(--warning);
}
.dial.is-bad {
  color: var(--danger);
}
.dial .chart__track {
  stroke-width: 6;
  opacity: 0.15;
}
.chart__ring {
  fill: none;
  stroke: currentColor;
  stroke-width: 6;
}
.dial__score {
  fill: currentColor;
  font: var(--type-num-md);
  letter-spacing: var(--type-num-md-tracking);
  text-transform: var(--type-num-md-case);
  /* type-exception DS-COMP-28: the score dial's number at the medium weight, as the mockup's scoreDial draws it */
  font-weight: var(--weight-medium);
}
.dial__label {
  color: var(--text-muted);
  text-align: center;
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
/* The funnel (DS-COMP-40), to true scale: each stage as wide as its count. */
.funnel {
  display: grid;
}
.funnel__step {
  display: grid;
  grid-template-columns: 8.5rem minmax(0, 1fr) 16rem;
  gap: var(--s-4);
  align-items: center;
  min-height: 3rem;
  padding: 0 var(--s-4);
}
.funnel__label {
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
}
.funnel__shape {
  align-self: stretch;
  display: flex;
}
.funnel__bg {
  width: var(--w);
  background: var(--accent);
  opacity: var(--depth);
}
/* The shape look fuses the stages: a centred trapezoid from this width to the next. */
.funnel--shape .funnel__bg {
  width: 100%;
  clip-path: polygon(
    calc(50% - var(--w) / 2) 0,
    calc(50% + var(--w) / 2) 0,
    calc(50% + var(--next) / 2) 100%,
    calc(50% - var(--next) / 2) 100%
  );
}
.funnel__val {
  display: flex;
  gap: var(--s-3);
  align-items: baseline;
  font-variant-numeric: tabular-nums;
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}
.funnel__pct,
.funnel__foot {
  color: var(--text-muted);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.funnel__foot {
  margin: var(--s-3) 0 0;
  padding: 0 var(--s-4);
}
/* At phone width a stage takes two rows: its label and value, then its
   true-scale shape across the full width, never hidden. */
@media (width <= 640px) {
  .funnel__step {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      'label val'
      'shape shape';
    row-gap: var(--s-1);
    padding-block: var(--s-2);
  }
  .funnel__label {
    grid-area: label;
  }
  .funnel__val {
    grid-area: val;
  }
  .funnel__shape {
    grid-area: shape;
    min-height: 1.5rem;
  }
}

/* -- The component gallery page (MP-1-3). -------------------------------- */
.gallery {
  display: grid;
  gap: var(--s-6);
  padding: var(--s-5) var(--pad-x);
}
.gallery__title {
  margin: 0;
  font: var(--type-title);
  letter-spacing: var(--type-title-tracking);
  text-transform: var(--type-title-case);
}
.gallery__entry {
  display: grid;
  gap: var(--s-3);
  padding-top: var(--s-3);
  border-top: 1px solid var(--rule);
}
.gallery__name {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  margin: 0;
  font: var(--type-card-title);
  letter-spacing: var(--type-card-title-tracking);
  text-transform: var(--type-card-title-case);
}
.gallery__states {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--s-4) var(--s-5);
  /* A wide table or chart scrolls or fits inside its state; it never widens the page. */
  min-width: 0;
}
/* A state lays its component out in flow, as a page does: an inline control
   (a button, a chip) keeps its own width and a block fills the state. */
.gallery__state {
  display: flow-root;
  min-width: 0;
  max-width: 100%;
  margin: 0;
}
.gallery__state > figcaption {
  margin-bottom: var(--s-2);
}
/* An axis chart or the funnel takes its width from its host and has none of
   its own, so its state is given a basis rather than shrinking to fit. */
.gallery__state:has(> .chart:not(.chart--radial), > .funnel) {
  flex: 1 1 min(100%, 36rem);
}
.gallery__host {
  position: relative;
  display: inline-flex;
}
.gallery__icons {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  max-width: 40rem;
}
.gallery__host--popover {
  min-height: 9rem;
  min-width: min(352px, 100%);
}
.gallery__list {
  margin: 0;
  padding: 0;
  min-width: min(30rem, 100%);
}
.gallery__stack,
.gallery__flash {
  display: grid;
  gap: var(--s-3);
}
/* SPDX-License-Identifier: AGPL-3.0-only
   Layer 2, the kit's one empty state. Its own sheet because 2-primitives.css
   is at the product-source line limit; loads straight after it. */

/* The one empty state (DS-PRIM-28): no icon, no fill, in three looks. */
.empty {
  display: grid;
  gap: 6px;
  color: var(--text-muted);
}
.empty > p {
  margin: 0;
}
.empty--block {
  display: block;
  padding: 48px 24px;
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
  text-align: center;
}
/* As the mockup's house empty state: every line at the block's own size, 1em apart. */
.empty.empty--block > * {
  max-width: none;
  margin: 1em 0;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
}
.empty--inline {
  max-width: 60ch;
  padding-block: 16px;
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.empty--row {
  padding: 0;
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.empty__title {
  color: var(--text-muted);
}
.empty__desc,
.empty__hint {
  max-width: 340px;
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.empty__action {
  margin-top: 8px;
}
/* SPDX-License-Identifier: AGPL-3.0-only
   Layer 2, the kit's form layouts beside `.form` (DS-COMP-26). Its own sheet
   because 2-primitives.css is at the product-source line limit. */

/* DS-COMP-26, the settings rows (AG-X20, AG-X21; mockup app.css:3250-3283):
   a label and one sentence beside the row's control, in one card capped at a
   readable measure rather than run to the grid. The derived line sits with
   the controls; it reports state, so it is mono. */
.set__card {
  max-width: 46rem;
}
.set {
  display: grid;
  margin-top: var(--s-3);
}
.setrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--s-4);
  align-items: start;
  padding: var(--s-4) 0;
  border-top: 1px solid var(--border);
}
.setrow:first-child {
  padding-top: 0;
  border-top: 0;
}
.setrow__k {
  margin: 0;
  color: var(--text);
  font: var(--type-body-strong);
  letter-spacing: var(--type-body-strong-tracking);
  text-transform: var(--type-body-strong-case);
}
.setrow__note {
  margin: 0.15rem 0 0;
  color: var(--text-2);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.setrow__ctl {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--s-2);
}
.setrow__state {
  margin: 0;
  color: var(--text-muted);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  text-align: right;
}
@media (width <= 640px) {
  .setrow {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-3);
  }
  .setrow__ctl {
    align-items: flex-start;
  }
  .setrow__state {
    text-align: left;
  }
}
/* SPDX-License-Identifier: AGPL-3.0-only
   ============================================================================
   Layer 3 of 4: the shell (S6). The Agent panel (S5) is `3-agent-panel.css`,
   loaded straight after this sheet.

   Ported from the pinned mockup's `assets/app.css` at 7066bad. Geometry is
   reproduced exactly; the class names are the mockup's so a visual comparison
   against the pinned reference has something to compare.

   THE COMPLEMENT FORM IS DELIBERATE AND LOAD-BEARING. Every desktop query is
   written `@media not all and (max-width: N)` rather than `min-width: N`,
   because at exactly N both forms match and the two layouts land on top of one
   another. The pinned sheet states this rule three times and banks a bug that
   blanked the estate for two rounds against it [app.css:4412]. It is carried
   here as written.

   THE CANONICAL BREAKPOINTS ARE 640 / 900 / 1279. 1440 is NOT a fifth
   breakpoint: no grid, type or spacing rule changes there. It is one condition
   governing whether one optional column appears, and the number is arithmetic
   rather than taste — 224 rail + 836 measured content floor + 380 panel.
   ============================================================================ */

.shell {
  display: grid;
  grid-template-columns: var(--rail-w) 1fr;
  min-height: 100vh;
}
/* The third track is the dock, and the shell is the only thing that writes
   --dock-w, so there is no second opinion about how wide the edge is. At rest
   the track is empty: the dock's rail floats over the page's right gutter, as
   the mockup's does, and the content runs to the window's edge. */
@media not all and (max-width: 900px) {
  .shell[data-face='agency'] {
    --dock-w: 0px;
    grid-template-columns: var(--rail-w) minmax(0, 1fr) var(--dock-w);
  }
}
@media (width <= 900px) {
  .shell {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* -- The rail ------------------------------------------------------------ */
.rail {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  padding: var(--s-5) 0;
  border-right: 1px solid var(--border);
  background: var(--rail-bg);
}
.rail__brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.4rem;
  padding: 0 var(--s-5);
}
/* The brand marks (MP-1-2): masks over the ink, so one file serves both
   themes. The wordmark is a ceiling rather than a fixed width, because the
   rail can be narrower than 176px; the aspect ratios are the SVGs' own. */
.brand {
  display: block;
  flex: none;
  background: currentColor;
}
.brand--wordmark {
  width: min(176px, 100%);
  aspect-ratio: 566.93 / 57.9;
  mask: url('/assets/wordmark-DSz2185k.svg') no-repeat left center / contain;
}
.brand--planet {
  width: 24px;
  aspect-ratio: 566.93 / 463.61;
  mask: url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20566.93%20463.61'%3e%3cpath%20d='M362.16,346.61c-45.62,42.76-92.16,78.86-135.78,106.61,18.25,4.69,37.38,7.19,57.1,7.19,126.26,0,228.62-102.36,228.62-228.62,0-19.06-2.37-37.56-6.76-55.26-32.75,53.11-82.09,112.81-143.17,170.07Z'/%3e%3cpath%20d='M353.58,322.37c66.1-51.17,120.58-105.94,157.55-155.48,46.94-62.9,65.66-117.38,44-145.35-22.58-29.16-84.06-23.04-161.12,10.13-32.77-18.13-70.43-28.49-110.53-28.49-126.26,0-228.62,102.36-228.62,228.62,0,19.64,2.48,38.69,7.14,56.88C10.58,354.96-10.76,412.94,11.82,442.11c8.15,10.53,21.41,16.41,38.59,18.13,64.45,6.49,184.71-46.17,303.17-137.87ZM471.14,53.37c.29.37.49.79.74,1.18,9.98,15.17-2.54,45.55-31.21,82.82,11.1-19.52,18-36.58,19.98-50.03-11.82-14.48-25.37-27.5-40.35-38.72,24.83-6.33,43.01-5.36,50.84,4.75ZM71.79,318.14c8.52,20.86,20.01,40.18,33.98,57.42-20.35,3.96-35.22,2.11-42.1-6.78-7.86-10.16-4.39-28.03,8.12-50.65Z'/%3e%3cpath%20d='M25.22,74.85c5.31,1.24,9.29,5.66,9.96,11.07l6.03,48.28c.13,1.03,1.63,1.03,1.75,0l5.98-48.28c.67-5.41,4.64-9.83,9.95-11.07l21.7-5.07c.91-.21.91-1.51,0-1.72l-21.71-5.08c-5.31-1.24-9.29-5.66-9.96-11.07L42.9,3.63c-.13-1.03-1.62-1.03-1.75,0l-5.98,48.28c-.67,5.41-4.64,9.83-9.95,11.07l-21.7,5.07c-.91.21-.91,1.51,0,1.72l21.7,5.07Z'/%3e%3c/svg%3e") no-repeat center / contain;
}
.rail__brand .brand {
  color: var(--text);
}
.rail__hub {
  font: var(--type-rail-label);
  letter-spacing: var(--type-rail-label-tracking);
  text-transform: var(--type-rail-label-case);
  color: var(--ink-faint);
}
.rail__build {
  margin: auto 0 0;
  padding: 0 var(--s-5);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  color: var(--ink-faint);
}
.rail__group {
  position: relative;
  display: flex;
  flex-direction: column;
}
/* One level, items 36 tall (MP-2-2). The railmark takes the place of a
   border: it is one element that slides, not a border per item that jumps. */
.rail__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  box-sizing: border-box;
  height: 36px;
  padding: 0 var(--s-5);
  color: var(--text-2);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
  text-decoration: none;
}
/* A section's own glyph (MP-2-2, T-R4): the expanded rail stays text; the
   folded rail (MP-2-3) displays it. */
.rail__icon {
  display: none;
}
.rail__item:hover {
  background: var(--surface-2);
  color: var(--text);
}
.rail__item:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.rail__item[data-lit] {
  color: var(--text);
  font: var(--type-body-strong);
  letter-spacing: var(--type-body-strong-tracking);
  text-transform: var(--type-body-strong-case);
}
/* The railmark: 2px of accent the height of the lit item. It snaps on load
   (`data-placing`) and slides over 220ms on in-app navigation. */
.railmark {
  position: absolute;
  top: 0;
  left: 0;
  width: 2px;
  height: var(--railmark-h);
  background: var(--accent);
  transform: translateY(var(--railmark-y));
  transition:
    transform var(--dur-1) var(--ease),
    height var(--dur-1) var(--ease);
  pointer-events: none;
}
.railmark[data-placing] {
  transition: none;
}
.railmark[hidden] {
  display: block;
  opacity: 0;
}
/* "Back to Clients" above a client's sections (MP-2-9). */
.rail__backrow {
  padding: 0 var(--s-5);
}
.rail__back {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  text-decoration: none;
}
/* The drawer's own close, drawn only while it is open. */
.navclose {
  display: none;
}
@media (width <= 900px) {
  .rail {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: 60;
    width: min(300px, 84vw);
    height: 100dvh;
    transform: translateX(-100%);
    visibility: hidden;
    transition:
      transform var(--dur-1) var(--ease),
      visibility 0s var(--dur-1);
  }
  .shell[data-nav='open'] .rail {
    transform: translateX(0);
    visibility: visible;
    box-shadow: var(--shadow-overlay);
    transition:
      transform var(--dur-1) var(--ease),
      visibility 0s;
  }
  .shell[data-nav='open'] .navclose {
    display: inline-flex;
  }
}
/* In the drawer's top corner, so the brand keeps its stack (DS-SIDE-12). */
.navclose {
  position: absolute;
  top: var(--s-5);
  right: var(--s-3);
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--border-strong);
  background: transparent;
  color: var(--text);
  cursor: pointer;
}
/* The drawer's backdrop: 40% black, fading in over 220ms (MP-2-8). */
.navbackdrop {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: var(--scrim);
  animation: navbackdrop-in var(--dur-1) var(--ease);
}
@keyframes navbackdrop-in {
  from {
    opacity: 0;
  }
}
@media not all and (max-width: 900px) {
  .navbackdrop {
    display: none;
  }
}
/* The hamburger: first in the page header, at 900 and below only. */
.navtoggle {
  display: none;
  order: -1;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--border-strong);
  background: transparent;
  color: var(--text);
  cursor: pointer;
}
.navtoggle span {
  display: block;
  width: 14px;
  height: 1.5px;
  background: currentColor;
}
@media (width <= 900px) {
  .navtoggle {
    display: inline-flex;
  }
}

/* -- The rail folds (MP-2-3). Above 900 it folds to a 56px strip of glyphs,
      each with its name on hover, and its right edge drags it from 170 to
      400. At 900 and below the rail is the drawer: no fold, no grip, and the
      strip's rules do not reach it. The shell writes --rail-w; the grid's
      transition runs once the shell is ready and never during a drag
      (the mockup's drag trailed the cursor, DS-SIDE-D4). */
/* On the label's line, 2px under the wordmark's foot: the mockup's touched
   it and overlapped the end of the word (DR-61). */
.railfold {
  position: absolute;
  top: calc(var(--s-5) + 20px);
  right: var(--s-3);
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition:
    color var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease);
}
.railfold:hover,
.railfold:focus-visible {
  color: var(--text);
  background: var(--surface);
}
.rail__glyph {
  display: none;
}
/* Right: 0 rather than straddling the border, because the rail scrolls and
   would clip or scroll sideways to show anything past its edge. */
.railgrip {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 5;
  width: 6px;
  cursor: col-resize;
  touch-action: none;
}
.railgrip:hover,
.railgrip:focus-visible,
.shell[data-rail-dragging] .railgrip {
  background: var(--accent-ring);
  outline: none;
}
.shell[data-rail-dragging],
.shell[data-rail-dragging] * {
  transition: none !important;
  cursor: col-resize;
  user-select: none;
}
@media not all and (max-width: 900px) {
  .shell[data-rail='collapsed'] .rail {
    padding-top: calc(var(--s-5) + 30px);
  }
  .shell[data-rail='collapsed'] .railfold {
    top: var(--s-5);
    right: 16px;
  }
  /* The strip keeps the brand as the planet mark, centred (DS-SIDE-12). */
  .shell[data-rail='collapsed'] .rail__brand {
    align-items: center;
    padding: 0;
  }
  .shell[data-rail='collapsed'] .rail__brand .brand--wordmark {
    width: 24px;
    aspect-ratio: 566.93 / 463.61;
    mask-image: url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20566.93%20463.61'%3e%3cpath%20d='M362.16,346.61c-45.62,42.76-92.16,78.86-135.78,106.61,18.25,4.69,37.38,7.19,57.1,7.19,126.26,0,228.62-102.36,228.62-228.62,0-19.06-2.37-37.56-6.76-55.26-32.75,53.11-82.09,112.81-143.17,170.07Z'/%3e%3cpath%20d='M353.58,322.37c66.1-51.17,120.58-105.94,157.55-155.48,46.94-62.9,65.66-117.38,44-145.35-22.58-29.16-84.06-23.04-161.12,10.13-32.77-18.13-70.43-28.49-110.53-28.49-126.26,0-228.62,102.36-228.62,228.62,0,19.64,2.48,38.69,7.14,56.88C10.58,354.96-10.76,412.94,11.82,442.11c8.15,10.53,21.41,16.41,38.59,18.13,64.45,6.49,184.71-46.17,303.17-137.87ZM471.14,53.37c.29.37.49.79.74,1.18,9.98,15.17-2.54,45.55-31.21,82.82,11.1-19.52,18-36.58,19.98-50.03-11.82-14.48-25.37-27.5-40.35-38.72,24.83-6.33,43.01-5.36,50.84,4.75ZM71.79,318.14c8.52,20.86,20.01,40.18,33.98,57.42-20.35,3.96-35.22,2.11-42.1-6.78-7.86-10.16-4.39-28.03,8.12-50.65Z'/%3e%3cpath%20d='M25.22,74.85c5.31,1.24,9.29,5.66,9.96,11.07l6.03,48.28c.13,1.03,1.63,1.03,1.75,0l5.98-48.28c.67-5.41,4.64-9.83,9.95-11.07l21.7-5.07c.91-.21.91-1.51,0-1.72l-21.71-5.08c-5.31-1.24-9.29-5.66-9.96-11.07L42.9,3.63c-.13-1.03-1.62-1.03-1.75,0l-5.98,48.28c-.67,5.41-4.64,9.83-9.95,11.07l-21.7,5.07c-.91.21-.91,1.51,0,1.72l21.7,5.07Z'/%3e%3c/svg%3e");
    mask-position: center;
  }
  .shell[data-rail='collapsed'] .rail__item {
    justify-content: center;
    padding-inline: 0;
  }
  .shell[data-rail='collapsed'] .rail__icon,
  .shell[data-rail='collapsed'] .rail__glyph {
    display: grid;
    place-items: center;
    width: 16px;
    height: 16px;
    font: var(--type-small-strong);
    letter-spacing: var(--type-small-strong-tracking);
    text-transform: var(--type-small-strong-case);
  }
  /* Hidden from sight only: each label stays its item's accessible name. */
  .shell[data-rail='collapsed'] .rail__hub,
  .shell[data-rail='collapsed'] .rail__build,
  .shell[data-rail='collapsed'] .rail__label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}
@media (width <= 900px) {
  .railfold,
  .railgrip {
    display: none;
  }
}

/* -- The page strip and the content column ------------------------------- */
.main {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
/* The chrome: the app strip, the tab row and the page header, one block,
   sticky above 900 and scrolling away at 900 and below (MP-2-7). */
.chrome {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--bg);
}
@media not all and (max-width: 900px) {
  .chrome {
    position: sticky;
    top: 0;
    z-index: 30;
  }
  /* A menu open in the chrome lifts it over the dock (DS-TOK-99), which
     would otherwise cover the menu's lower items (OW-127). The lift lands
     with the menu: reduced motion's reset would ease it in a frame late. */
  .chrome:has(.menu) {
    z-index: 65;
    transition-property: none;
  }
  .topbar__meta {
    min-height: 34px;
  }
}

/* -- The app strip (MP-2-5): dark chrome on the agency face, teal on the
      client face. Its ink is on-dark on either ground. ------ */
.appbar {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  /* A 32px row (search, the face switch) inside its padding, as the mockup's
     44.8: its controls centre on the same half pixel as the mockup's. */
  min-height: calc(32px + 0.8rem);
  box-sizing: border-box;
  padding: 0.4rem var(--s-4);
  background: var(--app-chrome);
  color: var(--on-dark);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.appbar[data-face='client'] {
  background: var(--client-brand);
}
/* Back and Forward: 26 square, faint until hovered, hidden at 640. */
.appbar__step {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  background: none;
  color: color-mix(in oklch, var(--on-dark) 55%, transparent);
  cursor: pointer;
}
.appbar__step:hover:not(:disabled) {
  background: color-mix(in oklch, var(--on-dark) 10%, transparent);
  color: var(--on-dark);
}
.appbar__step:disabled {
  opacity: 0.35;
  cursor: default;
}
.appbar__step + .appbar__step {
  margin-left: calc(var(--s-4) * -1 + 2px);
}
/* Search, drawn and disabled until it is built (R29): not focusable. */
.appbar__search {
  display: flex;
  flex: 1;
  align-items: center;
  gap: var(--s-2);
  min-width: 90px;
  height: 32px;
  box-sizing: border-box;
  padding: 0.3rem 0.6rem;
  border: 1px solid color-mix(in oklch, var(--on-dark) 12%, transparent);
  background: color-mix(in oklch, var(--on-dark) 7%, transparent);
  color: color-mix(in oklch, var(--on-dark) 50%, transparent);
  opacity: 0.55;
  cursor: not-allowed;
}
.appbar__key {
  margin-left: auto;
  padding: 0 0.25rem;
  border: 1px solid color-mix(in oklch, var(--on-dark) 20%, transparent);
  font: var(--type-chip);
  letter-spacing: var(--type-chip-tracking);
  text-transform: var(--type-chip-case);
}
.appbar__preview {
  flex: 1;
  color: color-mix(in oklch, var(--on-dark) 72%, transparent);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  text-align: right;
  white-space: nowrap;
}
/* The signed-in person (C23): the strip's last element, its circle in the
   strip's on-dark ink; the menu opens under it, flush right. */
.who {
  position: relative;
  flex: none;
  margin-left: auto;
}
.who__trigger {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  cursor: pointer;
}
.who__trigger .av {
  background: color-mix(in oklch, var(--on-dark) 16%, transparent);
  color: var(--on-dark);
}
.who__trigger:hover .av,
.who__trigger[aria-expanded='true'] .av {
  background: color-mix(in oklch, var(--on-dark) 28%, transparent);
}
.who__menu {
  /* Clear of the strip: the circle sits 7.5px above the strip's bottom edge. */
  top: calc(100% + 8px);
  right: 0;
  left: auto;
  min-width: 14rem;
}
.who__menu .menu__opt {
  width: 100%;
  box-sizing: border-box;
  border: 0;
  background: none;
  text-align: start;
  text-decoration: none;
}
.who__menu .menu__opt:hover,
.who__menu .menu__opt:focus-visible {
  background: var(--surface-2);
  color: var(--text);
}
.who__head {
  display: grid;
  gap: 2px;
  padding: 6px 12px var(--s-2);
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--s-1);
}
.who__name {
  color: var(--text);
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
}
.who__email {
  color: var(--text-muted);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  overflow-wrap: anywhere;
}

/* The face switch: the strip's dress of the segmented control. */
.facesw {
  display: inline-flex;
  flex: none;
  border: 1px solid color-mix(in oklch, var(--on-dark) 22%, transparent);
}
.facesw button {
  height: 30px;
  padding: 0 0.75rem;
  border: 0;
  background: none;
  color: color-mix(in oklch, var(--on-dark) 60%, transparent);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  cursor: pointer;
}
.facesw button[aria-pressed='true'] {
  background: var(--on-dark);
  color: var(--app-chrome);
  cursor: default;
}
.appbar__timer {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 0.35rem;
  height: 30px;
  padding: 0.25rem 0.6rem;
  border: 1px solid color-mix(in oklch, var(--on-dark) 22%, transparent);
  background: none;
  color: var(--on-dark);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  opacity: 0.55;
  cursor: not-allowed;
}
@media (width <= 900px) {
  .appbar {
    padding-inline: var(--s-3);
    gap: var(--s-3);
  }
  .appbar__search {
    display: none;
  }
}
@media (width <= 640px) {
  .appbar__step {
    display: none;
  }
  .appbar__timer .appbar__label {
    display: none;
  }
  .appbar__timer {
    padding-inline: 0.45rem;
  }
}
.clienthdr {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}
.clienthdr__mark {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 22px;
  height: 22px;
  background: var(--accent);
  color: var(--on-dark);
  font: var(--type-rail-label);
  letter-spacing: var(--type-rail-label-tracking);
  text-transform: var(--type-rail-label-case);
}
.appbar[data-face='client'] .clienthdr__mark {
  background: color-mix(in oklch, var(--on-dark) 20%, transparent);
}
.clienthdr__name {
  overflow: hidden;
  font: var(--type-subheading);
  letter-spacing: var(--type-subheading-tracking);
  text-transform: var(--type-subheading-case);
  white-space: nowrap;
  text-overflow: ellipsis;
}
.clienthdr__tag {
  color: color-mix(in oklch, var(--on-dark) 46%, transparent);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  white-space: nowrap;
}
@media (width <= 900px) {
  .clienthdr__tag {
    display: none;
  }
}

/* -- The tab row (MP-2-6): the section's pages, an underline that slides
      over 420ms, and overflow that scrolls with a fade and an arrow at each
      edge with more past it (R62). It never widens its column. ------------ */
.tabbar {
  position: relative;
  display: flex;
  min-width: 0;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}
.tabbar__scroll {
  position: relative;
  display: flex;
  flex: 1;
  gap: var(--s-6);
  min-width: 0;
  padding: 0 var(--s-6);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabbar__scroll::-webkit-scrollbar {
  display: none;
}
.tabbar[data-more='start'] .tabbar__scroll {
  mask-image: linear-gradient(to right, transparent, #000 3rem);
}
.tabbar[data-more='end'] .tabbar__scroll {
  mask-image: linear-gradient(to left, transparent, #000 3rem);
}
.tabbar[data-more='start end'] .tabbar__scroll {
  mask-image: linear-gradient(
    to right,
    transparent,
    #000 3rem,
    #000 calc(100% - 3rem),
    transparent
  );
}
.tabbar__t {
  flex: none;
  padding: 0.65rem 0 0.525rem;
  border-bottom: 2px solid transparent;
  color: var(--text-2);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
  text-decoration: none;
  white-space: nowrap;
}
.tabbar__t:hover {
  color: var(--text);
}
.tabbar__t[aria-current='page'] {
  color: var(--text);
  font: var(--type-body-strong);
  letter-spacing: var(--type-body-strong-tracking);
  text-transform: var(--type-body-strong-case);
}
.tabmark {
  position: absolute;
  bottom: 0;
  left: 0;
  width: var(--tabmark-w);
  height: 2px;
  background: var(--accent);
  transform: translateX(var(--tabmark-x));
  transition:
    transform var(--dur-2) var(--ease),
    width var(--dur-2) var(--ease);
  pointer-events: none;
}
.tabmark[data-placing] {
  transition: none;
}
.tabmark[hidden] {
  display: none;
}
.tabbar__arrow {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 2rem;
  padding: 0;
  border: 0;
  background: var(--bg);
  color: var(--text-2);
  cursor: pointer;
}
.tabbar__arrow:hover {
  color: var(--text);
}
.tabbar__arrow[data-edge='start'] {
  left: 0;
}
.tabbar__arrow[data-edge='end'] {
  right: 0;
}
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
  min-height: 2.9rem;
  padding: var(--s-3) var(--s-6);
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}
.topbar__title {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.topbar__title .t-title {
  margin: 0;
  font: var(--type-title);
  letter-spacing: var(--type-title-tracking);
  text-transform: var(--type-title-case);
}
.topbar__meta {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  flex-wrap: wrap;
}
.content {
  display: flex;
  flex-direction: column;
  gap: var(--s-6);
  flex: 1;
  padding: var(--s-6);
}
/* Above 900 the agency face's right gutter clears the dock's rail, which
   floats over it: 16px past the rail's 40 (the mockup's calc). */
@media not all and (max-width: 900px) {
  .shell[data-face='agency'] :is(.topbar, .content) {
    padding-right: calc(var(--s-4) + 40px);
  }
}
@media (width <= 900px) {
  .topbar {
    justify-content: flex-start;
  }
  .topbar__meta {
    margin-left: auto;
  }
  .content {
    padding: var(--s-4);
  }
}

/* -- Search (C1): a modal palette over a scrim, one field, the hits the
      scoped service answered. ------------------------------------------- */
button.appbar__search {
  font: inherit;
  text-align: left;
  opacity: 1;
  cursor: text;
}
button.appbar__search:hover {
  border-color: color-mix(in oklch, var(--on-dark) 22%, transparent);
}
.palette__scrim {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: var(--scrim);
}
.palette {
  position: fixed;
  top: 12vh;
  left: 50%;
  z-index: 91;
  display: flex;
  flex-direction: column;
  width: min(560px, calc(100vw - 2rem));
  max-height: 70vh;
  border: 1px solid var(--border-strong);
  background: var(--bg);
  box-shadow: var(--shadow-overlay);
  transform: translateX(-50%);
}
.palette__field {
  box-sizing: border-box;
  width: 100%;
  padding: var(--s-4);
  border: 0;
  border-bottom: 1px solid var(--border);
  background: transparent;
  color: var(--text);
  font: var(--type-body-lg);
  letter-spacing: var(--type-body-lg-tracking);
  text-transform: var(--type-body-lg-case);
}
.palette__field:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.palette__list {
  margin: 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
}
.palette__hit {
  display: flex;
  gap: var(--s-3);
  padding: 0.6rem var(--s-4);
  color: var(--text-2);
  cursor: pointer;
}
.palette__hit[aria-selected='true'],
.palette__hit:hover {
  background: var(--surface-2);
  color: var(--text);
}
.palette__key {
  flex: none;
  color: var(--ink-faint);
  font: var(--type-chip);
  letter-spacing: var(--type-chip-tracking);
  text-transform: var(--type-chip-case);
}
.palette__none {
  margin: 0;
  padding: var(--s-4);
  color: var(--text-2);
}
/* SPDX-License-Identifier: AGPL-3.0-only
   ============================================================================
   Layer 3 of 4, continued: the Agent panel (S5), moved whole from the end of
   `3-shell.css` to keep that sheet under the line limit. `packages/ui/src/index.ts`
   loads it straight after `3-shell.css`, so the cascade order is unchanged.
   ============================================================================ */

/* -- The Agent panel (S5) ------------------------------------------------
   Docked, it is a grid TRACK beside the rail and the content; below 1280 it is
   fixed and out of flow. Same parent in both forms, which is why it is a child
   of the shell rather than of the document body. */
.aipanel {
  position: fixed;
  inset: 0 0 0 auto;
  z-index: 70;
  display: flex;
  flex-direction: column;
  width: min(400px, 92vw);
  height: 100dvh;
  border-left: 1px solid var(--border);
  background: var(--rail-bg);
  box-shadow: var(--shadow-overlay);
}
.aipanel[hidden] {
  display: none;
}
@media not all and (max-width: 1439px) {
  .shell[data-dock='seated'] .aipanel {
    position: sticky;
    inset: 0 auto auto auto;
    width: var(--aip-dock);
    height: 100vh;
    box-shadow: none;
  }
}
/* In the dock (MP-7-11) the drawer is an `ai` panel's body: it takes the
   body's room and draws no frame of its own, which the dock's panel has. */
.dpanel .aipanel,
.shell[data-dock='seated'] .dpanel .aipanel {
  position: static;
  z-index: auto;
  flex: 1;
  width: auto;
  height: auto;
  min-height: 0;
  margin: calc(-1 * var(--s-4)) calc(-1 * var(--s-5));
  border-left: 0;
  box-shadow: none;
}
.aip__head {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--border);
}
.aip__id {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.aip__title {
  font: var(--type-subheading);
  letter-spacing: var(--type-subheading-tracking);
  text-transform: var(--type-subheading-case);
}
.aip__hmodel {
  margin-left: auto;
  min-width: 0;
}
/* The model picker is the head's quiet control (AI-02): the house select with
   no ground and no edge until it is hovered or focused. */
select.aip__hmodel {
  padding: 0.2rem 0.4rem;
  border: 1px solid transparent;
  background: none;
  color: var(--text-muted);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
select.aip__hmodel:hover:not(:disabled) {
  border-color: var(--border-strong);
}
.aip__acts {
  display: flex;
  align-items: center;
  align-self: center;
  gap: 0.15rem;
}
.aip__actdiv {
  flex: none;
  width: 1px;
  align-self: stretch;
  margin: 0.15rem 0.25rem;
  background: var(--border);
}
.aip__scroll {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
}
.aip__msg {
  max-width: 92%;
  padding: 0.6rem 0.8rem;
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}
.aip__msg--ai {
  align-self: flex-start;
  background: var(--surface-2);
  border: 1px solid var(--border);
}
.aip__msg--user {
  align-self: flex-end;
  background: var(--ink);
  color: var(--paper);
}
.aip__msg--note {
  background: transparent;
  border: 1px dashed var(--border);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  color: var(--text-muted);
}
.aip__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  padding: 0 var(--s-5) var(--s-3);
}
.aip__chip {
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text-2);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  cursor: pointer;
}
.aip__inputrow {
  display: flex;
  align-items: stretch;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-5) var(--s-4);
  border-top: 1px solid var(--border);
}
.aip__input {
  flex: 1;
  min-width: 0;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--border);
  background: var(--paper);
  color: var(--text);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}
/* Send stands as tall as the field beside it (AI-12), as the mockup's row does. */
.aip__inputrow .btn {
  height: auto;
}
.aip__input:focus {
  border-color: var(--accent);
}
.aip__chip:hover {
  border-color: var(--accent);
  color: var(--text);
}
.aip__tabs {
  padding: var(--s-3) var(--s-5) 0;
  border-bottom: 1px solid var(--border);
}
/* The conversation tab row's parts (AI-06 to AI-08). Each tab carries its own
   close, shown on the selected tab and on hover or focus, and always at phone
   width where there is no hover (DOCK D-10). */
.aip__tab {
  display: inline-flex;
  align-items: center;
}
.aip__tabx,
.aip__new,
.aip__act {
  display: inline-flex;
  align-items: center;
  border: 0;
  background: none;
  color: var(--text-dim);
  font: inherit;
  cursor: pointer;
}
/* The head's eye and close (AI-03, AI-05): muted, the close a 1.6rem square. */
.aip__act {
  padding: 0.25rem 0.35rem;
  color: var(--text-muted);
}
.aip__x {
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  padding: 0;
}
.aip__tabx {
  opacity: 0;
  padding: 0 0.2rem;
}
.aip__tab:hover .aip__tabx,
.aip__tab:focus-within .aip__tabx,
.aip__tab:has([aria-selected='true']) .aip__tabx {
  opacity: 1;
}
@media (max-width: 640px) {
  .aip__tabx {
    opacity: 1;
  }
}
.aip__new {
  margin-left: auto;
}
.aip__tabx:hover,
.aip__new:hover,
.aip__act:hover {
  color: var(--accent);
}
.cmtab--rename {
  max-width: 18ch;
  border: 1px solid var(--accent);
  background: var(--paper);
  color: var(--text);
}
/* Where the ask came from, and what each answer read (AI-11, AI-12). */
.aip__cited {
  margin: 0;
  padding: var(--s-2) var(--s-5) 0;
  color: var(--text-muted);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.aip__cites {
  margin: 0.4rem 0 0;
  padding-left: 1rem;
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.aip__msg--failed {
  border-color: var(--danger);
}
/* SPDX-License-Identifier: AGPL-3.0-only
   ============================================================================
   Layer 3 of 4, the shell's third track: the dock (MP-3-1), its sheet tier
   (MP-3-3) and its phone strip. Split from 3-shell.css, which draws the rail,
   the chrome and the content column; the shell's grid names this track.
   ============================================================================ */

/* -- The dock (MP-3-1). The right edge as a place: a 40px rail of permanent
      tabs floats centred on the right edge, and the open panels sit beside it,
      the rail riding their left edge. It is fixed, so the grid's third track
      (--dock-w) only keeps the rail off the content. Which panels are open and
      how wide they sit is MP-3-2's geometry; this is the frame.
      Below 900 the rail does not disappear: it ROTATES onto the bottom edge
      and stays on screen at rest (the mockup's D-1), because a phone holds one
      thing. The sheet tiers are MP-3-3's. ----------------------------------- */
.dock {
  position: fixed;
  /* Beside the page the dock starts at the app strip's foot (.appbar, 45px),
     and the rail centres on what is left of the edge (DS-SIDE-1, DS-SIDE-7). */
  top: 45px;
  right: 0;
  bottom: 0;
  z-index: 50;
  display: flex;
  pointer-events: none;
}
.dock > * {
  pointer-events: auto;
}
.dock__rail {
  position: absolute;
  top: 50%;
  right: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  width: 40px;
  padding: var(--s-2) 0;
  border: 1px solid var(--border);
  border-right: 0;
  background: var(--rail-bg);
  box-shadow: var(--shadow-sm);
  transform: translateY(-50%);
}
.dock:not([data-open='0']) .dock__rail {
  box-shadow: none;
}
.dock__tab {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink-faint);
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
  cursor: pointer;
  /* DS-SIDE-2: ink and ground move over 120 ms on the one ease. */
  transition:
    color var(--dur-fast) var(--ease),
    background-color var(--dur-fast) var(--ease);
}
/* The panel's count rides the tab's corner: the kit's `cbadge`, placed. */
.dock__count {
  position: absolute;
  top: -3px;
  right: -3px;
}
.dock__tab:hover {
  color: var(--text);
  background: var(--surface);
}
/* The count chip (DS-SIDE-4): square, never capped, the same in both themes. */
.dock__n {
  position: absolute;
  top: -3px;
  right: -3px;
  min-width: 17px;
  height: 16px;
  padding: 0 2.4px;
  background: var(--accent);
  color: var(--on-dark);
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
  display: grid;
  place-items: center;
}
/* Open is an OUTLINE and a rule, never a fill. */
.dock__tab[aria-expanded='true'] {
  color: var(--accent);
}
.dock__tab[aria-expanded='true']::before {
  content: '';
  position: absolute;
  left: -1px;
  top: 4px;
  bottom: 4px;
  width: 2px;
  background: var(--accent);
}
/* The callout: a dark chip to the tab's left, the side the panels open on.
   Display-gated, so it never widens the page or takes a click. In dark its
   ground is the page's own, so the edge is what shows where it ends; in light
   the edge sits on the dark chip and cannot be seen. The padding gives back
   the edge's pixel so the chip keeps its size. */
.dock__tablabel {
  display: none;
  position: absolute;
  top: 50%;
  right: calc(100% + 7px);
  z-index: 80;
  max-width: 14rem;
  padding: calc(0.35rem - 1px) calc(0.6rem - 1px);
  border: 1px solid var(--border-strong);
  background: var(--void);
  color: var(--on-dark);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  white-space: nowrap;
  transform: translateY(-50%);
  pointer-events: none;
}
.dock__tab:hover .dock__tablabel,
.dock__tab:focus-visible .dock__tablabel {
  display: block;
}
/* It opens to the right when the rail sits within 150px of the window's left
   edge (DK-03). */
.dock--tipflip .dock__tablabel {
  right: auto;
  left: calc(100% + 7px);
}
/* Close all (DK-06): last, behind its own hairline, only while something is open. */
.dock__closeall {
  margin-top: 0.35rem;
  border-top: 1px solid var(--border);
}
.dock__closeall:hover {
  color: var(--danger);
}
/* The higher-ranked panel takes the outer edge (DS-SIDE-7 stacked): the
   panels come in rank order, so the row runs from the edge inwards. */
.dock__panels {
  display: flex;
  flex-direction: row-reverse;
  height: 100%;
  box-shadow: var(--shadow-overlay);
}
.dpanel {
  display: flex;
  flex-direction: column;
  width: var(--dock-panel-w, 550px);
  min-width: 0;
  border-left: 1px solid var(--border);
  background: var(--rail-bg);
}
.dpanel__head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-4) var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--border);
}
.dpanel__name {
  flex: 1;
  min-width: 0;
  margin: 0;
  overflow: hidden;
  font: var(--type-subheading);
  letter-spacing: var(--type-subheading-tracking);
  text-transform: var(--type-subheading-case);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dpanel__acts {
  display: flex;
  align-items: center;
  gap: 0.15rem;
}
.dpanel__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 1px 6px;
  border: 0;
  background: none;
  color: var(--ink-faint);
  text-decoration: none;
  cursor: pointer;
}
.dpanel__btn:hover {
  color: var(--text);
}
.dpanel__btn[data-act='door']:hover {
  color: var(--accent);
}
/* Back and forward are disabled, never hidden (DK-11, DK-12). */
.dpanel__btn[aria-disabled='true'] {
  opacity: 0.4;
  cursor: not-allowed;
}
.dpanel__btn[aria-disabled='true']:hover {
  color: var(--ink-faint);
}
.dpanel__div {
  flex: none;
  width: 1px;
  height: 1.1em;
  margin: 0 0.25rem;
  background: var(--border);
}
.dpanel__body {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
}
/* Seated, the group is a grid track (the shell's --dock-w) and casts no
   shadow; floating, it lies over the page. The grip is a 6px strip over each
   panel's left edge, one width for them all (MP-3-2). */
.dock[data-mode='seated'] .dock__panels {
  box-shadow: none;
}
.dpanel {
  position: relative;
}
.dpanel__grip {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -3px;
  z-index: 2;
  width: 6px;
  cursor: col-resize;
  touch-action: none;
}
.dpanel__grip:hover,
.dpanel__grip:focus-visible,
.dock[data-dragging] .dpanel__grip {
  background: color-mix(in oklch, var(--accent) 35%, transparent);
  outline: none;
}
/* R39: one line saying which panel closed to make room. */
.dock__stamp {
  position: absolute;
  right: 0;
  bottom: var(--s-4);
  margin: 0;
  padding: 0.35rem 0.6rem;
  border: 1px solid var(--border-strong);
  background: var(--void);
  color: var(--on-dark);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
/* Nothing animates on the first layout: the shell and dock mark themselves
   ready two frames after it. A drag suspends every transition. */
.shell[data-dock-ready] {
  transition: grid-template-columns var(--dur-2) var(--ease);
}
.dock[data-ready] .dock__rail {
  transition: right var(--dur-2) var(--ease);
}
.dock[data-dragging] *,
.shell:has(.dock[data-dragging]) {
  transition: none !important;
}
@media (prefers-reduced-motion: reduce) {
  .shell[data-dock-ready],
  .dock[data-ready] .dock__rail {
    transition: none;
  }
}
/* -- The sheet tier (MP-3-3), 901 to 1279: the dock is in flow under the
      content, its tabs on the sheet's top edge; shift stacks panels in one
      shared height, dragged on the sheet's top edge within [220, window
      height - 140]. -------------------------------------------------------- */
.dock[data-mode='sheet'] {
  position: sticky;
  inset: auto 0 0;
  grid-column: 2;
  grid-row: 2;
  flex-direction: column;
  align-items: stretch;
}
.dock[data-mode='sheet'] .dock__rail {
  position: static;
  order: -1;
  flex-direction: row;
  align-self: center;
  width: auto;
  padding: var(--s-3) var(--s-3) 0;
  border-bottom: 0;
  border-right: 1px solid var(--border);
  box-shadow: none;
  transform: none;
}
.dock[data-mode='sheet'] .dock__panels {
  flex-direction: column-reverse;
  min-height: var(--dock-sheet-h);
  border-top: 1px solid var(--border);
  box-shadow: none;
}
.dock[data-mode='sheet'] .dpanel,
.dock[data-mode='phone'] .dpanel {
  flex: 1;
  min-height: 0;
  width: 100%;
  border-left: 0;
}
/* A stacked panel never shrinks below its head and its body's padding, so
   one panel's body never covers the next one's close: when the dragged
   height cannot seat every head, the sheet grows to seat them (OW-126). */
.dock[data-mode='sheet'] .dpanel {
  flex-basis: 0;
  min-height: auto;
}
.dock[data-mode='sheet'] .dpanel__body {
  contain: size;
}
/* Stacked from the bottom edge up, so the rule falls under the upper panel. */
.dock[data-mode='sheet'] .dpanel + .dpanel {
  border-bottom: 1px solid var(--border);
}
/* Close all closes the row behind a hairline on its left (DS-SIDE-6). */
.dock[data-mode='sheet'] .dock__closeall {
  margin: 0 0 0 0.35rem;
  border-top: 0;
  border-left: 1px solid var(--border);
}
.dock[data-mode='sheet'] .dpanel__grip,
.dock[data-mode='phone'] .dpanel__grip {
  top: -3px;
  right: 0;
  bottom: auto;
  left: 0;
  width: auto;
  height: 6px;
  cursor: row-resize;
}
.dock[data-mode='sheet'] .dock__tab[aria-expanded='true']::before {
  left: 4px;
  right: 4px;
  top: auto;
  bottom: -1px;
  width: auto;
  height: 2px;
}

/* -- The phone strip, 900 and below: the tabs along the bottom edge, on
      screen at rest (the mockup's D-1), one panel over them, and the page
      padded so nothing hides under either. Nothing is wider than the
      window. ---------------------------------------------------------------- */
@media (width <= 900px) {
  .dock {
    top: auto;
    right: 0;
    bottom: 0;
    left: 0;
    flex-direction: column;
    background: var(--rail-bg);
  }
  .dock__tablabel {
    top: auto;
    right: auto;
    bottom: calc(100% + 7px);
    left: 50%;
    transform: translateX(-50%);
  }
  .dock__rail {
    position: static;
    order: 2;
    flex-direction: row;
    justify-content: center;
    gap: var(--s-4);
    width: auto;
    height: 40px;
    padding: 0;
    border: 0;
    border-top: 1px solid var(--border);
    box-shadow: none;
    transform: none;
  }
  .dock__closeall {
    margin: 0;
    border-top: 0;
  }
  .dock__panels {
    height: var(--dock-sheet-h);
    max-height: calc(100dvh - 40px);
  }
  .dpanel {
    width: 100%;
  }
  .main {
    padding-bottom: 40px;
  }
  .shell:has(.dock[data-mode='phone']:not([data-open='0'])) .main {
    padding-bottom: calc(var(--dock-sheet-h) + 40px);
  }
  .dock__tab[aria-expanded='true']::before {
    left: 4px;
    right: 4px;
    top: -1px;
    bottom: auto;
    width: auto;
    height: 2px;
  }
}

/* Print leaves the dock out, and the shell unwinds to the page alone. */
@media print {
  .dock {
    display: none;
  }
  .shell {
    display: block;
  }
}
/* SPDX-License-Identifier: AGPL-3.0-only
   ============================================================================
   Layer 4 of 5: the board (S1).

   Ported from the pinned mockup's `assets/app.css` at 7066bad, geometry exact.
   ============================================================================ */

/* -- The board (S1). It is a table, not a card board. -------------------- */
.cbd {
  border: 1px solid var(--border);
  background: var(--paper);
}
.cbd__filters {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  flex-wrap: wrap;
  padding: var(--s-3) var(--s-5);
  border-bottom: 1px solid var(--border);
}
.cbd__flabel {
  margin-right: 0.3rem;
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  color: var(--ink-faint);
}
.cbd__tag {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0.5rem;
  border: 1px solid var(--accent);
  background: var(--surface);
  color: var(--text);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.cbd__tagk {
  color: var(--text-dim);
}
.cbd__tagx {
  border: 0;
  background: none;
  color: var(--text-muted);
  cursor: pointer;
  font: var(--type-button);
  letter-spacing: var(--type-button-tracking);
  text-transform: var(--type-button-case);
}
/* The quick-add field (B-01's field): a bordered box the input sits in
   borderless, so the box owns the focus state and the input draws nothing. */
.cbd__field {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  min-width: 10rem;
  padding: 0.3rem 0.55rem;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}
.cbd__field:focus-within {
  border-color: var(--accent);
}
.cbd__field .icon {
  flex: none;
  color: var(--ink-faint);
}
.cbd__field input {
  width: 100%;
  min-width: 3rem;
  padding: 1px 0;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--text);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.cbd__field input:focus-visible {
  outline: none;
  box-shadow: none;
}
.cbd__wrap {
  overflow-x: auto;
  max-width: 100%;
}
.cbd__tbl {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}
.cbd__thl {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cbd__tbl td {
  padding: 0.5rem var(--s-3);
  border-bottom: 1px solid var(--border);
  color: var(--text);
  vertical-align: middle;
  overflow: hidden;
}
.cbd__tbl tbody tr:not(.cbd__grp):nth-child(even) {
  background: color-mix(in oklch, var(--ink) 1.6%, var(--paper));
}
.cbd__tbl tbody tr:not(.cbd__grp):hover {
  background: var(--surface-2);
}
/* The group banner is a plain heading: no colour, no count. A board where
   every row shouts says nothing. A rule on the cell parts it from the group
   above; the first group sits tight under the heads with none (DS-COMP-17). */
.cbd__grp > td {
  padding: 0.85rem 0.5rem 0.35rem;
  border-top: 1px solid var(--border);
  border-bottom: 0;
  background: var(--paper);
}
.cbd__tbl tbody tr.cbd__grp:first-child > td {
  padding-top: 0.35rem;
  border-top: 0;
}
/* The heading and its wait reasons are two sizes on one line: baselines. */
.cbd__grpb {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  font: var(--type-subheading);
  letter-spacing: var(--type-subheading-tracking);
  text-transform: var(--type-subheading-case);
  color: var(--text);
}
.cbd__grpr {
  margin-left: 0.1rem;
  padding-left: 0.4rem;
  border-left: 1px solid var(--border);
  color: var(--text-muted);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.cbd__name {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-width: 0;
}
.cbd__nm {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* One name weight on every board, the Projects board's 400 (DR-48). */
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
  color: var(--text);
  text-decoration: none;
}
/* The task name is the row's link: ink, not link dress (the whole row reads as one). */
a.cbd__nm:hover {
  text-decoration: underline;
}
/* The assignee's name sits a step quieter than the task's. */
.av + .cbd__nm {
  color: var(--text-2);
}
.cbd__rank {
  color: var(--ink-faint);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.cbd__dim {
  color: var(--text-dim);
}
/* Stage and state: the board's outline cell chip. */
.cbd__chips {
  display: flex;
  gap: 0.25rem;
  min-width: 0;
}
.cbd__chip {
  max-width: 100%;
  overflow: hidden;
  padding: 0.1rem 0.35rem;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-2);
  font: var(--type-caption);
  font-size: var(--text-overline); /* type-exception DS-COMP-17: the 11 px board cell chip */
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The state's own tone stays on the task page; on the board the chip is neutral. */
.cbd__chip .spill {
  color: inherit;
}
.tl__due {
  white-space: nowrap;
  color: var(--text-2);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.tl__due.is-bad {
  color: var(--danger);
  /* type-exception DS-COMP-17: the overdue date carries the medium weight */
  font-weight: var(--weight-medium);
}
/* The reading line under the rows (B-22): how many the board holds. */
.cbd__read {
  margin: 0;
  padding: var(--s-2) var(--s-5);
  color: var(--text-muted);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}

/* The width model: below 1280 the estimate and actual columns go and the
   assignee is their avatar alone (the name stays for a reader); below 900 the
   stage column goes too. A column's `col` goes with it, so the rest take its
   share. */
@media (width < 1280px) {
  .cbd__tbl [data-hide-below='1280'] {
    display: none;
  }
  .cbd__tbl .av + .cbd__nm {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }
}
@media (width < 900px) {
  .cbd__tbl [data-hide-below='900'] {
    display: none;
  }
}
/* SPDX-License-Identifier: AGPL-3.0-only */

/* The board machine (U09): the command bar, the chip row, the reading line,
   the typeahead and the table's width model. Rules only the machine draws;
   the board's shared dialect stays in 4-board.css. */

.cbd__cmd {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.cbdm__search {
  position: relative;
  flex: 1 1 220px;
  min-width: 0;
}

.cbd__barq {
  width: 100%;
  font: inherit;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
}

.cbd__barq:focus {
  outline: none;
  border-color: var(--accent);
}

.cbd__ico {
  font: inherit;
  width: 32px;
  height: 32px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
}

.cbd__ico:disabled {
  opacity: 0.4;
  cursor: default;
}

.cbd__clear:disabled {
  opacity: 0.32;
  cursor: default;
}

.cbd__preset,
.cbd__mode {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: inherit;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
}

.cbd__preset:hover {
  border-color: var(--text);
}

.cbd__preset.is-on {
  background: var(--text);
  border-color: var(--text);
  color: var(--bg);
}

.cbd__mode.is-on {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
  color: var(--text);
}

.cbd__count {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

/* The viewer's own chip (P-11): an ink fill when on. */
.cbd__preset--viewer.is-on {
  background: var(--ink);
  border-color: var(--ink);
}

/* A category chip where a client or a mention waits (P-13): flagged, never counted. */
.cbd__preset--cat.is-flagged {
  border-color: var(--accent);
}

/* The Review chip's live count (P-10): a badge, its figure on the accent
   deepened toward the void, since --accent-ink on the plain accent is 4.4:1.
   The void never flips, so the badge holds about 5.9:1 in both themes. */
.cbd__count--accent {
  padding: 0 5px;
  border-radius: 999px;
  background: color-mix(in oklch, var(--accent) 85%, var(--void-deep));
  color: var(--accent-ink);
}

.cbd__read {
  margin: 0;
  color: var(--text-muted);
}

/* The typeahead: groups are presentation, options are the only stops. It
   opens over the sticky chip row (12) and heads (11), under the chrome (30). */
.cbdta {
  position: absolute;
  z-index: 13;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  margin: 0;
  padding: 4px 0;
  list-style: none;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
}

.cbdta__gh,
.cbdta__more {
  padding: 4px 10px;
  color: var(--text-muted);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}

.cbdta__opt {
  display: flex;
  justify-content: space-between;
  padding: 5px 10px;
  cursor: pointer;
}

.cbdta__opt[aria-selected='true'] {
  background: var(--surface-2);
}

.cbdta__k {
  color: var(--text-muted);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}

/* The width model: when the floors exceed the card the table takes their
   sum and scrolls here, inside the card; the page never scrolls sideways.
   The heads are the kit table's (`.table th`, MP-1-3); the width model, not
   the kit table's phone floor, sizes the table. */
.cbd__wrap {
  overflow-x: auto;
  max-width: 100%;
}

[data-board] .cbd__tbl {
  min-width: 0;
}

/* The resize grip (MP-5-6, B-17): an 8px handle on the head's right edge
   whose rule is 1px at rest and 2px accent on hover, focus and drag. */
.cbd__grip {
  position: absolute;
  top: 0;
  right: 0;
  width: 8px;
  height: 100%;
  cursor: col-resize;
  touch-action: none;
  z-index: 1;
}

.cbd__grip::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  width: 1px;
  height: 100%;
  background: var(--border);
}

.cbd__grip:hover::after,
.cbd__grip:focus-visible::after,
.cbd__grip.is-live::after {
  width: 2px;
  background: var(--accent);
}

.cbd__grip:focus-visible {
  outline: none;
}

.cbd__th {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  box-sizing: border-box;
  /* The head cell is the one table head (`.table th`, MP-1-3); the label
     button spans its padding edge to edge and carries the board's own
     (DS-COMP-17, B-15), so it clips at the cell's edge where the grip sits. */
  width: calc(100% + 32px);
  margin: -8.8px -16px;
  /* The head's icon box (1rem) holds its height where the icon is not drawn. */
  min-height: calc(1rem + 1.1rem);
  border: 0;
  padding: 0.55rem var(--s-3);
  overflow: hidden;
  background: none;
  color: var(--text-muted);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  text-align: inherit;
  white-space: nowrap;
  cursor: pointer;
}
.cbd__th:hover,
.cbd__hd[aria-sort='ascending'] .cbd__th,
.cbd__hd[aria-sort='descending'] .cbd__th {
  color: var(--text);
}
.cbd__tbl [data-align='end'] > .cbd__th {
  justify-content: flex-end;
}
.cbd__tbl [data-align='center'] > .cbd__th {
  justify-content: center;
}

.cbd__tbl [data-align='end'] {
  text-align: end;
}

.cbd__tbl [data-align='center'] {
  text-align: center;
}

.cbd__hd:not([data-tight]) .cbd__thi {
  display: none;
}

/* Tight: the head drops its words and centres its icon; the label stays the
   button's accessible name. */
.cbd__hd[data-tight] .cbd__thl {
  display: none;
}

/* Tight cells clip at the column's edge; they never shorten their text. */
td[data-tight] {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: clip;
}

/* The sort arrow sits centred on the head's bottom rule, so a sorted column
   is never wider than an unsorted one. */
.cbd__arrow {
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translate(-50%, 50%) scale(0.8);
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
  color: var(--text);
}

/* ── The command bar (MP-5-7, B-04, B-05, B-25, B-26, P-07) ─────────────── */

.cbd__funnelw {
  position: relative;
}

.cbd__funnel.is-on {
  background: var(--surface-2);
}

/* The corner badge: how many filters are on that no chip on the bar shows. */
.cbd__badge {
  position: absolute;
  top: -5px;
  right: -5px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--accent);
  color: var(--accent-ink);
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
  display: grid;
  place-content: center;
}

/* Display-gated by `hidden`, never moved out of view. */
.cbd__menu[hidden] {
  display: none;
}

.cbd__menu {
  position: absolute;
  z-index: 45;
  top: calc(100% + 4px);
  right: 0;
  width: min(22rem, calc(100vw - 32px));
  max-height: 70vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-3);
  background: var(--paper);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-overlay);
}

.cbd__menuq {
  display: flex;
  border: 1px solid var(--border);
  background: var(--surface);
  padding: 4px var(--s-3);
}

.cbd__menuq:focus-within {
  border-color: var(--accent);
}

.cbd__menuq input {
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  width: 100%;
  min-width: 0;
  padding: 0;
}

.cbd__menuq input:focus {
  outline: none;
}

.cbd__menugrp {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.cbd__menuk,
.cbd__flabel {
  flex: 0 0 100%;
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  color: var(--ink-faint);
}

.cbd__facet {
  font: inherit;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-2);
  cursor: pointer;
}

.cbd__facet[aria-pressed='true'] {
  background: var(--text);
  border-color: var(--text);
  color: var(--bg);
}

.cbd__lnk {
  align-self: flex-start;
  font: inherit;
  border: 0;
  padding: 0;
  background: none;
  color: var(--text-muted);
  text-decoration: underline;
  cursor: pointer;
}

/* At 390 the menu spans the whole bar, which sits inside the page's 16px
   gutter, instead of hanging off the funnel toward the screen's edge (D-22). */
@media (max-width: 480px) {
  .cbd__cmd {
    position: relative;
  }

  .cbd__funnelw {
    position: static;
  }

  .cbd__menu {
    left: 0;
    right: 0;
    width: auto;
  }
}

/* The freshness stamp (P-07): a stamp, not a control. The board stays live,
   so there is no Sync button; the short words are for narrow bars. */
.cbd__fresh {
  margin-left: auto;
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  color: var(--ink-faint);
  white-space: nowrap;
}

.cbd__freshs {
  display: none;
}

@media (max-width: 480px) {
  .cbd__freshl {
    display: none;
  }

  .cbd__freshs {
    display: inline;
  }
}

/* The chip row's ladder (B-25): full words, then each chip's words capped at
   96, 72, 56 and 44px (clipped, like every cell), then icons only; the chip
   keeps its name as its label. */
.cbd__presi {
  display: none;
}

.cbd__filters[data-tier]:not([data-tier='words'], [data-tier='icons']) .cbd__presetw {
  display: inline-block;
  max-width: var(--catw);
  overflow: hidden;
  text-overflow: clip;
  white-space: nowrap;
}

.cbd__filters[data-tier='icons'] .cbd__presetw {
  display: none;
}

.cbd__filters[data-tier='icons'] .cbd__presi {
  display: inline;
}

/* The sticky stack (B-26): the chip row under the chrome, the heads under the
   chip row. Each offset is measured by whoever draws the element: the shell
   publishes --chrome-h, the board --catbar-h. The grounds are opaque so rows
   never show through. Below 900 the chip row scrolls away. */
@media not all and (max-width: 900px) {
  .cbd__filters {
    position: sticky;
    top: var(--chrome-h, 0px);
    z-index: 12;
    background: var(--paper);
  }
}

/* Heads stick only where the table fits its card: a scroll container would
   pin them to itself, so the wrap clips instead of scrolling there. Below
   1279 the table can overflow and scrolls, and the heads do not stick. */
@media (min-width: 1279px) {
  .cbd__wrap {
    overflow-x: clip;
  }

  .cbd__tbl .cbd__hd {
    position: sticky;
    top: calc(var(--chrome-h, 0px) + var(--catbar-h, 0px));
    z-index: 11;
    background: var(--paper);
  }
}

/* The Projects board's cells (MP-5-8, BOARDS P-20 to P-28, P-36). */
.cbd__rank {
  color: var(--ink-faint);
}
/* The assignee's name beside the person avatar (DS-PRIM-16) is quieter than the task's. */
.cbd__tbl .av--person + .cbd__nm {
  color: var(--text-2);
}
/* The due date, in the dock's `.tl__due` dialect: overdue is the danger ink
   at the medium weight; due today keeps the plain date's ink. */
.cbd__tbl .tl__due {
  color: var(--text-2);
}
.cbd__tbl .tl__due.is-now:not(.is-bad) {
  color: var(--text-2);
}
.cbd__tbl .tl__due.is-bad {
  color: var(--danger);
}
/* 22 tall and top-aligned, so the chip sits inside the cell's line and the
   row keeps 39 (DS-COMP-17); the caption's line is taller than the box. */
.cbd__chip {
  display: inline-block;
  vertical-align: top;
  box-sizing: border-box;
  height: 22px;
  max-width: 100%;
  overflow: hidden;
  padding: 0.1rem 0.35rem;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-2);
  white-space: nowrap;
  /* Its type (the 11 px caption, DS-COMP-17) and its text overflow are the board
     chip's in 4-board.css. */
}
.cbd__tok {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.cbd__tokk {
  display: block;
  font: var(--type-chip);
  letter-spacing: var(--type-chip-tracking);
  text-transform: var(--type-chip-case);
  color: var(--ink-faint);
}
.cbd__cmt {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  color: var(--text-2);
  text-decoration: none;
}
.cbd__cmtg {
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.cbd__cmtn {
  position: absolute;
  top: -2px;
  right: -4px;
  min-width: 14px;
  padding: 0 3px;
  border-radius: 999px;
  /* The Review count's deepened accent: --accent-ink on the plain accent is 4.4:1. */
  background: color-mix(in oklch, var(--accent) 85%, var(--void-deep));
  color: var(--accent-ink);
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
  display: grid;
  place-content: center;
  height: 14px;
}
.cbd__cmt:hover,
.cbd__cmt:focus-visible {
  color: var(--accent);
}
/* Hover and focus invert the badge, as the on preset does: ink ground and
   paper figure in light, light ground and void figure in dark. */
.cbd__cmt:hover .cbd__cmtn,
.cbd__cmt:focus-visible .cbd__cmtn {
  background: var(--text);
  color: var(--bg);
}
.brn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: 100%;
}
.brn__bar {
  flex: 1 1 auto;
  min-width: 28px;
  height: 4px;
  border-radius: 2px;
  background: var(--border);
  overflow: hidden;
}
.brn__fill {
  display: block;
  height: 100%;
  background: var(--accent);
}
.brn__fig {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  color: var(--text-2);
}
.brn.is-over .brn__fill {
  background: var(--danger);
}
.brn.is-over .brn__fig {
  color: var(--danger);
}

/* The Projects row's controls (MP-5-9, P-30, P-32, P-33). The tick sits
   before the name; the rename input is sized to the cell so the row keeps
   its height; the hover box shows on row hover or focus, and at rest below
   900, where there is no hover. */
.cbd__tick {
  flex: none;
  margin: 0;
  accent-color: var(--accent);
}

.cbd__rename {
  flex: 1 1 auto;
  min-width: 0;
  height: 1.6em;
  padding: 0 4px;
  font: inherit;
}

.cbd__routes--pop {
  display: none;
  flex: none;
  gap: 2px;
  margin-left: auto;
}

tr:hover .cbd__routes--pop,
tr:focus-within .cbd__routes--pop {
  display: inline-flex;
}

@media (max-width: 900px) {
  .cbd__routes--pop {
    display: inline-flex;
  }
}

.cbd__route {
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text-2);
  font: var(--type-button);
  letter-spacing: var(--type-button-tracking);
  text-transform: var(--type-button-case);
  text-decoration: none;
  cursor: pointer;
}

.cbd__route:hover {
  border-color: var(--text);
  color: var(--text);
}

/* Inline cell editors (MP-5-10, P-37, DS-PRIM-5 inline, R47). The editor lies
   over its cell and the drawn value stays underneath, hidden, so the row keeps
   its height and the editor is the cell's size; the menu hangs below the cell,
   at least its width and never wider than 22rem. */
.cbd__cell {
  position: relative;
}

.cbd__edb {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: inherit;
  cursor: pointer;
}

.cbd__edb:hover {
  box-shadow: inset 0 -1px 0 var(--border-strong);
}

.cbd__cell.is-editing > .cbd__cellv {
  visibility: hidden;
}

.cbd__ed {
  position: absolute;
  inset: 0;
  z-index: 40;
}

.cbd__ed .sel,
.cbd__ed .sel__btn,
.cbd__ed .cbd__date {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
}

.cbd__ed .sel__btn,
.cbd__ed .cbd__date {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin: 0;
  padding: 0 6px;
  border: 1px solid var(--accent);
  border-radius: 0;
  background: var(--paper);
  color: var(--text);
  font: inherit;
  overflow: hidden;
  white-space: nowrap;
}

/* The caret: a border triangle, as the house select draws it. */
.cbd__ed .sel__btn::after {
  content: '';
  flex: none;
  border: 4px solid transparent;
  border-top-color: currentColor;
  margin-top: 4px;
}

.cbd__ed .sel__menu {
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 100%;
  width: max-content;
  max-width: 22rem;
  max-height: 16rem;
  overflow-y: auto;
  margin: 0;
  padding: 4px 0;
  list-style: none;
  background: var(--paper);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-overlay);
}

.cbd__ed .sel__menu:focus {
  outline: none;
}

.cbd__ed .sel__opt {
  padding: 6px 12px;
  white-space: nowrap;
  cursor: pointer;
}

.cbd__ed .sel__opt.is-active {
  background: var(--surface-2);
}

.cbd__ed .sel__opt[aria-selected='true'] {
  color: var(--accent);
}

/* The td lifts its clipping while an editor is open, or the menu would
   vanish into it. The wrap lifts only where the table fits its card: below
   1279 it scrolls, and lifting it would drop the scroll and spill the table
   across the page, so there the menu stays inside the wrap's scroll. */
.cbd__tbl td:has(.cbd__cell.is-editing) {
  overflow: visible;
}

@media (min-width: 1279px) {
  .cbd__wrap:has(.cbd__cell.is-editing) {
    overflow: visible;
  }
}

/* Made-up category chips (no catalogue yet) under the one mock label (DS-PRIM-32):
   the region is one item of the chip row, its chips in a row, room kept for the tag. */
.cbd__filters > .is-mock {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  padding: 0.15rem 2.9rem 0.15rem 0.15rem;
  border-radius: var(--radius-sm);
}
/* SPDX-License-Identifier: AGPL-3.0-only
   ============================================================================
   Layer 5 of 5: the task page and its tabs (S2, S3, S4), the run hero and the
   gate.

   Ported from the pinned mockup's `assets/app.css` at 7066bad, geometry exact.
   ============================================================================ */

/* -- The task page record header (S2; TASK-PAGE S5, DS-TASK-11) --------- */
.tpr {
  display: grid;
  gap: var(--s-3);
  margin-bottom: var(--s-4);
}
.tpr__crumb {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
  color: var(--text-muted);
}
/* TP-01: the door link, DS-TOK-124 (the mockup's 13 snaps to the data style),
   and the same door out of a gate or an empty page. */
.tpr__crumb .sb__addr,
.empty__action .sb__addr {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  color: var(--text);
  text-decoration: none;
}
.tpr__crumb .sb__addr:hover,
.tpr__crumb .sb__addr:focus-visible,
.empty__action .sb__addr:hover,
.empty__action .sb__addr:focus-visible {
  color: var(--accent);
}
/* TP-06: DS-TOK-107 --type-display (the mockup's 600 weight is drift). */
.tpr__title {
  margin: 0;
  font: var(--type-display);
  letter-spacing: var(--type-display-tracking);
  text-transform: var(--type-display-case);
  /* A long name wraps at 390 rather than clipping (MP-4-1). */
  overflow-wrap: anywhere;
}
/* Refresh sits outside the read (TaskDetail.tsx says why), at the page's end. */
.tpr__refresh {
  display: flex;
  justify-content: flex-end;
}
/* The dock panel's live ticks sit in a strip of their own (MP-4-10). */
.tpr__strip {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
}
.tpr__fact {
  display: grid;
  gap: 0.15rem;
}
/* The rank's calculation, under the fact strip (MP-4-2). */
.tpr__calc {
  margin: 0;
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  color: var(--ink-faint);
}
/* Inert on the task page: the strip's ticks say what the record says and do
   nothing, so the cursor is the default one, never the pointer (MP-4-2, D-08).
   They are the kit's tick box otherwise (`.mstrip .check` below). */
.tpr__mark {
  cursor: default;
}
/* The live ticks (MP-4-10, DP-16, DP-17): the dock panel's, which do turn. */
.tpr__tick {
  display: inline-grid;
  place-items: center;
  inline-size: 18px;
  block-size: 18px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--accent);
  cursor: pointer;
}
.tpr__tick:hover,
.tpr__tick[aria-checked='true'] {
  border-color: var(--accent);
}
.tpr__tick:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.tpr__tick[aria-disabled='true'] {
  cursor: progress;
}
/* TP-10: the read-only field grid, DS-COMP-26 inline form (5 / 2 / 1). */
.taskform {
  display: grid;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-5) var(--s-5);
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}
.tf__grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--s-3) var(--s-4);
  margin: 0;
}
@media (width <= 1279px) {
  .tf__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (width <= 640px) {
  .tf__grid {
    grid-template-columns: minmax(0, 1fr);
  }
}
.tf__row {
  display: grid;
  gap: 0.3rem;
  align-content: start;
  min-width: 0;
}
.tf__k {
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  color: var(--text-muted);
}
/* A field's value as words (TP-10): DS-TOK-117 in the secondary ink. */
.sb__state {
  margin: 0;
  padding: 0.45rem 0;
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
  color: var(--text-2);
  overflow-wrap: anywhere;
}

/* The dock task panel's field grid (DP-18 to DP-25, `.sb__grid`): label and
   control pairs, two to a line, one below 641; a field that is more than a
   pair (Assign to AI, the tags, a refusal) takes the whole line. */
.dtp__fields {
  display: grid;
  grid-template-columns: 4.4rem minmax(0, 1fr) 4.4rem minmax(0, 1fr);
  align-items: center;
  gap: 0.4rem var(--s-3);
}
@media (width <= 640px) {
  .dtp__fields {
    grid-template-columns: 4.4rem minmax(0, 1fr);
  }
}
.dtp__fields > :is(.field, .tf__tags, .field__error, p) {
  grid-column: 1 / -1;
}
/* DS-PRIM-5, the field select, on the panel and the page's Status: 37 tall. */
.dtp__fields select.input,
[data-task-status] select.input {
  box-sizing: border-box;
  block-size: 2.3125rem;
  padding: 0 var(--s-3);
  background: var(--paper);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}

/* The page's ruled sections (DS-COMP-22): a rule above, the 24 gutter. The
   Agent side column's sit closer under their rule (DS-TASK-15). */
[data-task] > .sb__sect,
[data-tp-pane] > .sb__sect,
.tpg__main > .sb__sect,
.tpg__side > .sb__sect {
  gap: var(--s-3);
  padding: var(--s-5);
  border-top: 1px solid var(--border);
}
.tpg__side > .sb__sect {
  padding-top: var(--s-2);
}

/* DS-TASK-1, read-only: the fact strip above the field grid. */
.mstrip {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--s-3) var(--s-6);
  margin: 0 0 var(--s-4);
  padding: 0 0 var(--s-4);
  border-bottom: 1px solid var(--border);
}
.mstrip__c {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-width: 0;
}
.mstrip__k {
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  color: var(--text-muted);
}
.mstrip__v {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  color: var(--text);
}
.mstrip__bucket {
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
}
.mstrip__rank {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  font-variant-numeric: tabular-nums;
}
.mstrip__v--none {
  font-style: italic;
  color: var(--text-muted);
}
/* A tick on the page is a picture of a state: nothing to press (D-08). */
.mstrip .check {
  cursor: default;
}
/* Its state rides on data-on, since a picture takes no aria-checked. */
.mstrip .check[data-on='yes'] {
  border-color: var(--accent);
}
/* "derived": the calculation-source word after a derived cell's label. */
.mcalc__src {
  color: var(--text-2);
}
.mcalc__src::before {
  content: '\00b7';
  margin: 0 0.35rem;
}

/* -- The sliding tab set (S3/S4 switch, and the panel's conversations) ---- */
.cmtabs {
  position: relative;
  display: flex;
  gap: var(--s-4);
}
.cmtab {
  display: inline-flex;
  align-items: baseline;
  gap: 0.3rem;
  padding: 0.3rem 0 0.45rem;
  border: 0;
  background: none;
  color: var(--text-muted);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  white-space: nowrap;
  cursor: pointer;
}
.cmtab:hover,
.cmtab[aria-selected='true'] {
  color: var(--text);
}
.cmtabs__mark {
  position: absolute;
  bottom: -1px;
  height: 2px;
  background: var(--accent);
  transition:
    left var(--dur-1) var(--ease),
    width var(--dur-1) var(--ease);
}
/* A tab's count is a plain mono number in the muted ink, not a badge. */
.cmtab .cbadge--plain {
  display: inline;
  min-width: 0;
  height: auto;
  padding: 0;
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  color: var(--text-muted);
}
.cmtabs.is-placing .cmtabs__mark {
  transition: none;
}
.cmtabs--set {
  align-items: center;
  gap: var(--s-3);
  min-width: 0;
}

/* -- The Agent tab's two columns (S4) ------------------------------------ */
.tpg {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-5);
  align-items: start;
}
.tpg__main,
.tpg__side {
  display: grid;
  gap: var(--s-5);
  min-width: 0;
}
@media not all and (max-width: 1278px) {
  .tpg {
    grid-template-columns: minmax(0, 1fr) 21rem;
  }
}
.sb__sect {
  display: grid;
  gap: var(--s-2);
}
.sb__sh {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
}
.sb__k,
.sb__meta,
.sb__steplist [data-step-count] {
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
.sb__k {
  color: var(--text-muted);
}
.sb__meta {
  color: var(--ink-faint);
}
.sbact__row {
  display: grid;
  gap: 0.15rem;
  padding: var(--s-2) 0;
  border-bottom: 1px solid var(--border);
}
/* A task key prints as typed (MP-4-14): the data style's case is none. */
.sbact__meta,
.tt__more {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.sbact__meta {
  color: var(--ink-faint);
}
/* The staged-output rows (DS-TASK-6): a lined box of label-over-value rows. */
.sout__box {
  display: grid;
  gap: var(--s-3);
  padding: var(--s-3);
  border: 1px solid var(--border);
}
.sout__row {
  display: grid;
  gap: 0.3rem;
  min-width: 0;
}
.sout__v {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  color: var(--text-2);
  overflow-wrap: anywhere;
}
.sout__t {
  margin: 0;
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  color: var(--text);
}

/* -- The run hero. Status is a border-left LINE plus a word. -------------- */
.tph {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  min-width: 0;
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
}
.tph[data-tone='gate'] {
  border-left-color: var(--warning);
}
.tph[data-tone='run'] {
  border-left-color: var(--accent);
}
.tph[data-tone='done'] {
  border-left-color: var(--success);
}
.tph[data-tone='bad'] {
  border-left-color: var(--danger);
}
.tph__lead {
  display: grid;
  gap: var(--s-2);
  align-content: start;
  min-width: 0;
  padding: var(--s-4);
}
.tph__top {
  display: flex;
  align-items: baseline;
  justify-content: flex-start;
  gap: var(--s-3);
  flex-wrap: wrap;
}
.tph__head {
  margin: 0;
  font: var(--type-card-title);
  letter-spacing: var(--type-card-title-tracking);
  text-transform: var(--type-card-title-case);
  color: var(--text);
}
/* The pinned sheet fixes two columns with nth-child border rules, so it assumes
   two cells or four. The port keeps the geometry and lets the column count
   follow the cells, because a three-cell hero is reachable here (the token
   figure is absent until a run is priced) and the pinned rules land its borders
   asymmetrically. Recorded in DECISIONS.tsv. */
.tph__stats {
  display: grid;
  grid-template-columns: repeat(var(--tph-cols, 2), minmax(7.5rem, auto));
  border-left: 1px solid var(--border);
}
.tph__stat {
  display: grid;
  gap: 0.2rem;
  align-content: center;
  padding: var(--s-3) var(--s-4);
  border-right: 1px solid var(--border);
}
.tph__stat:last-child {
  border-right: 0;
}
.tph__n {
  /* type-exception DR-6: the run hero's mono 20 number, the one mono figure */
  font: var(--type-mono);
  letter-spacing: var(--type-mono-tracking);
  text-transform: var(--type-mono-case);
  font-size: var(--text-h2);
  line-height: var(--leading-none);
  color: var(--text);
}
.tph__of {
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  color: var(--text-muted);
}
@media (width <= 640px) {
  .tph {
    grid-template-columns: minmax(0, 1fr);
  }
  .tph__stats {
    border-left: 0;
    border-top: 1px solid var(--border);
  }
}

/* -- The gate. The mark is the ONE place a fill is allowed, and only when
      armed. Everything else is a line. ------------------------------------ */
.gate {
  display: flex;
  align-items: flex-start;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  border: 1px solid var(--border);
  border-left: 3px solid var(--text-muted);
  background: var(--surface);
}
.gate--armed {
  border-left-color: var(--warning);
}
.gate__mark {
  flex: none;
  width: 0.7rem;
  height: 0.7rem;
  margin-top: 0.3rem;
  border: 1px solid var(--text-muted);
}
.gate--armed .gate__mark {
  border-color: var(--warning);
  background: var(--warning);
}
.gate__word {
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  color: var(--text);
}
.gate__say {
  margin: 0.3rem 0 0;
  max-width: 74ch;
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  color: var(--text-2);
}
.gatebox {
  display: grid;
  gap: var(--s-2);
  min-width: 0;
  padding: var(--s-3);
  border: 1px solid var(--warning);
}
.gatebox--stale {
  border-color: var(--border-strong);
}
.gatebox__acts {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
}
.gatebox__note {
  margin: 0;
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  color: var(--text-muted);
}

/* The panel doors (TT-06): a centred line of mono text across the pane that
   sends the edit to the dock task panel. Drawn but not pressable while no
   panel is there to open, and then it looks inert. */
.tt__more {
  display: block;
  width: 100%;
  padding: var(--s-2) 0;
  border: 0;
  background: none;
  color: var(--ink-muted);
  text-align: center;
  cursor: pointer;
}
.tt__more:hover:not(:disabled) {
  color: var(--accent);
}
.tt__more:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.tt__more:disabled {
  cursor: default;
}

/* The burn bar (MP-4-6, DT-09): logged time against the estimate, capped at
   the track's end; the fill turns danger only past the estimate. */
.sb__burn {
  height: 4px;
  margin: var(--s-1) 0;
  background: var(--border);
}
.sb__burn > span {
  display: block;
  height: 100%;
  background: var(--accent);
}
.sb__burn[data-danger='true'] > span {
  background: var(--danger);
}

/* A gate step (MP-4-4, DT-04): no tick; the note sits right of the title on
   one line, and at 640 and below drops to a line of its own (D-17). */
.sb__step[data-gate] {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s-2);
}
.sb__gate-note {
  margin-inline-start: auto;
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  color: var(--text-muted);
  white-space: nowrap;
}
@media (width <= 640px) {
  .sb__gate-note {
    flex-basis: 100%;
    margin-inline-start: 0;
    white-space: normal;
  }
}

/* -- The description and the agent brief (MP-4-7, DP-34, DP-35, TT-01, TA-10).
   One font rule (R60): the description is sans on every surface, and so is
   the rendered brief; mono is kept for the brief's markdown field alone. --- */
.tt__prose {
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
  color: var(--text-2);
}
.md p,
.md ul,
.md ol {
  margin: 0 0 var(--s-2);
}
.tf__ta {
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
  width: 100%;
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--rule-faint);
  background: var(--surface);
  color: var(--text);
  resize: vertical;
}
.tf__ta:focus {
  border-color: var(--accent);
  outline: none;
}
.tf__ta--md {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

/* MP-4-5 thread: replies one level under their message (R42); the pencil and
   the × revealed on hover or keyboard focus, and at rest below 900px where
   there is no hover (DT-17); the client message signal a label (DT-19). */
.msg__replies {
  margin: var(--s-2) 0 0 var(--s-4);
  padding-left: var(--s-3);
  border-left: 1px solid var(--border);
}
.msg--deleted > .card__body {
  color: var(--text-muted);
  font-style: italic;
}
.msg__acts {
  display: flex;
  gap: var(--s-2);
}
.msg__acts [data-comment-act='edit'],
.msg__acts [data-comment-act='delete'] {
  opacity: 0;
}
.msg:hover > .msg__acts [data-comment-act],
.msg__acts [data-comment-act]:focus-visible {
  opacity: 1;
}
@media (width < 900px) {
  .msg__acts [data-comment-act='edit'],
  .msg__acts [data-comment-act='delete'] {
    opacity: 1;
  }
}
.msg__signal {
  color: var(--text-muted);
}
.msg__signal[data-signal='owed'] {
  color: var(--warning);
}

.dtp__action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 1.75rem;
  height: 1.75rem;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text-muted);
  text-decoration: none;
  cursor: pointer;
}
.dtp__action:hover,
.dtp__action:focus-visible {
  color: var(--accent);
}
.dtp__action:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.dtp__action[data-task-pin][aria-pressed='true'] {
  color: var(--accent);
}
/* SPDX-License-Identifier: AGPL-3.0-only */

/* The Agent pane (MP-6-1): the run summary, the workflow, the staged output
   and the gate, ported from the mockup's `app.css` (8454-8466, 8836-8864,
   12607-12657) onto the product's tokens. The workflow's ring takes its tone
   from the job's own state word; the demonstration note is not ported (R44). */

.agent {
  display: grid;
  gap: var(--s-3);
  min-width: 0;
}

/* MP-6-2: the run in main, what it was given in a side column after it; 21rem
   beside main at 1279 and above, stacked under it below (the mockup's `.tpg`,
   app.css:12696). A side section opens on a rule. */
.tpg {
  display: grid;
  gap: var(--s-5);
  min-width: 0;
}
@media (width >= 1279px) {
  .tpg {
    grid-template-columns: minmax(0, 1fr) 21rem;
    align-items: start;
  }
}
.tpg__main {
  display: grid;
  gap: var(--s-3);
  min-width: 0;
}
.tpg__side {
  display: grid;
  min-width: 0;
}
.tpg__side > * {
  border-top: 1px solid var(--border);
  padding: var(--s-2) 0 var(--s-3);
}

.gate {
  display: flex;
  gap: var(--s-4);
  align-items: flex-start;
  border: 1px solid var(--border);
  border-left: 3px solid var(--text-muted);
  background: var(--surface);
  padding: var(--s-4) var(--s-5);
}
.gate--armed {
  border-left-color: var(--warning);
}
.gate__mark {
  flex: none;
  width: 0.7rem;
  height: 0.7rem;
  margin-top: 0.3rem;
  border: 1px solid var(--text-muted);
}
.gate--armed .gate__mark {
  border-color: var(--warning);
  background: var(--warning);
}
.gate__word {
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  color: var(--text);
}
.gate__say {
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  margin: 0.3rem 0 0;
  color: var(--text-2);
  max-width: 74ch;
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}

.sout__box {
  border: 1px solid var(--border);
  padding: var(--s-3);
  display: grid;
  gap: var(--s-3);
}
.sout__where {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  color: var(--ink-faint);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.sout__row {
  display: grid;
  gap: 0.3rem;
}
.sout__v {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  color: var(--text-2);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.sout__t {
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  color: var(--text);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.sout__meta {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  color: var(--ink-faint);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.sout__say {
  color: var(--text-muted);
  margin: 0;
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  color: var(--text-muted);
  margin: 0;
}

/* The diff is two stacked halves, not side by side: the dock's panel is 380px
   at rest, and two columns of prose there are a column of one word each. The
   rule down the left edge says which is which: an edge, never a fill, so a
   diff is never mistaken for a status. */
.sout__diff {
  display: grid;
  gap: var(--s-3);
}
.sout__d {
  display: grid;
  gap: 0.25rem;
  padding-left: var(--s-3);
  border-left: 2px solid var(--border);
}
.sout__d--was .sout__t {
  color: var(--text-muted);
  text-decoration: line-through;
  text-decoration-color: var(--border-strong);
}
.sout__d--will {
  border-left-color: var(--success);
}

/* The pull request's two counts are a quantity with a sign, not a status. */
.sout__adds {
  color: var(--success);
}
.sout__dels {
  color: var(--danger);
}

.sout__ads {
  display: grid;
  gap: var(--s-3);
}
.sout__ad {
  display: grid;
  gap: 0.25rem;
}
.sout__adname {
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  color: var(--text);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.sout__band {
  color: var(--text-muted);
}
.sout__acts {
  display: grid;
  gap: 0.4rem;
  justify-items: start;
}

.trs {
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  padding: var(--s-3);
  display: grid;
  gap: var(--s-2);
  min-width: 0;
}
.trs[data-tone='gate'] {
  border-left-color: var(--warning);
}
.trs[data-tone='run'] {
  border-left-color: var(--accent);
}
.trs[data-tone='done'] {
  border-left-color: var(--success);
}
.trs[data-tone='bad'] {
  border-left-color: var(--danger);
}
.trs__top {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  justify-content: space-between;
  min-width: 0;
}
.trs__say {
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
  margin: 0;
  color: var(--text);
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
}
/* MP-6-2: the run's figures (the mockup's `.tph__stats`, taskrun.js runHero). */
.tph__stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-2) var(--s-4);
}
.tph__stat {
  display: grid;
  gap: 0.15rem;
  min-width: 0;
}
.tph__of {
  color: var(--text-muted);
}
.trs__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-top: 1px solid var(--border);
}
.trs__c {
  display: grid;
  gap: 0.15rem;
  padding: var(--s-2) var(--s-2) var(--s-2) 0;
  min-width: 0;
  border-bottom: 1px solid var(--border);
}
.trs__c:nth-child(odd) {
  border-right: 1px solid var(--border);
}
.trs__c:nth-child(even) {
  padding-left: var(--s-2);
}
.trs__c:nth-last-child(-n + 2) {
  border-bottom: 0;
  padding-bottom: 0;
}
.trs__v {
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  color: var(--text);
  overflow-wrap: anywhere;
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.trs__snap {
  color: var(--text-muted);
}
@media (max-width: 640px) {
  .trs__grid {
    grid-template-columns: 1fr;
  }
  .trs__c:nth-child(odd) {
    border-right: 0;
  }
  .trs__c:nth-child(even) {
    padding-left: 0;
  }
  .trs__c:nth-last-child(-n + 2) {
    border-bottom: 1px solid var(--border);
    padding-bottom: var(--s-2);
  }
  .trs__c:last-child {
    border-bottom: 0;
    padding-bottom: 0;
  }
}

.wf {
  min-width: 0;
}
.wf__toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  width: 100%;
  padding: var(--s-2) 0;
  background: none;
  border: 0;
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  cursor: pointer;
}
.wf__toggle:hover {
  color: var(--accent);
}
.wf__list {
  display: grid;
  gap: 0;
}
.wf__list[hidden] {
  display: none;
}
.wf__row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: var(--s-2);
  align-items: start;
  padding: var(--s-2) 0;
  border-top: 1px solid var(--border);
}
.wf__row:first-child {
  border-top: 0;
}
/* The state mark is an outline ring, never a fill. */
.wf__mark {
  width: 0.95rem;
  height: 0.95rem;
  margin-top: 0.1rem;
  border: 1.5px solid var(--border-strong);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
}
.wf__mark[data-tone='done'],
.wf__mark[data-tone='approved'] {
  border-color: var(--success);
  color: var(--success);
}
.wf__mark[data-tone='running'] {
  border-color: var(--accent);
  color: var(--accent);
}
.wf__mark[data-tone='pending'] {
  border-color: var(--warning);
  color: var(--warning);
}
.wf__mark[data-tone='failed'],
.wf__mark[data-tone='refused'] {
  border-color: var(--danger);
  color: var(--danger);
}
.wf__mark[data-tone='waiting'] {
  border-style: dashed;
}
.wf__body {
  display: grid;
  gap: 0.1rem;
  min-width: 0;
}
.wf__t {
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  color: var(--text);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.wf__fail {
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  color: var(--danger);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.wf__state {
  flex: none;
}
.wf__par {
  border-left: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
  padding-left: var(--s-2);
  margin: var(--s-1) 0;
}
.wf__parlab {
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  display: block;
  padding-top: var(--s-1);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
.wf__par .wf__row:first-of-type {
  border-top: 0;
}

.gatebox {
  display: grid;
  gap: var(--s-2);
  border: 1px solid var(--warning);
  padding: var(--s-3);
  min-width: 0;
}
.gatebox--stale {
  border-color: var(--border-strong);
}
.gatebox__acts {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
}

/* The scope stamp (MP-6-4, DS-TASK-3; mockup app.css:8814-8820): read-only,
   mono parts, the clearance as an outlined chip that keeps its accent in dark. */
.mstamp {
  display: grid;
  gap: 0.3rem;
  padding: var(--s-3) 0 0;
}
.mstamp__v {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
  color: var(--text-2);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.mstamp__lock {
  inline-size: 0.6rem;
  block-size: 0.5rem;
  border: 1.5px solid var(--ink-faint);
  border-radius: 2px;
}
.mstamp__p {
  color: var(--text-2);
}
.mstamp__x {
  color: var(--ink-faint);
}
.mstamp__chip {
  border: 1px solid var(--accent);
  color: var(--accent);
}
.mstamp__say {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  color: var(--ink-faint);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

/* C36: a conversation at its own address, and the drawer's link to it. */
.aip__address {
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  padding: var(--s-2) var(--s-5) 0;
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.convrec {
  display: grid;
  gap: var(--s-4);
  max-width: 72ch;
  padding: var(--s-5);
}
.convrec__subject,
.convrec__note {
  color: var(--text-muted);
}
/* The drawer's transcript at the conversation's own address: its messages
   wear `.aip__msg` (AI-09), the agent's on the left and the person's on the
   right, so the column is a flex column as the drawer's is. */
/* The messages stack as the drawer's do: the agent's at the start, the person's at the end. */
.convrec__log {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.convrec__who {
  display: block;
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.convrec__msg p {
  margin: 0;
  white-space: pre-wrap;
}
.convrec__request {
  margin: 0;
  padding-left: var(--s-3);
  border-left: 2px solid var(--border);
}

/* ── Token tracked (MP-6-5, DS-TASK-9, DA-08, DA-09; mockup app.css:9453-9531,
   :5264-5269, :8237). The allowance is money in the envelope's currency: the
   reservation ledger reserves money. Label, value and provenance on one line
   while there is room; nothing in a run row truncates. */
.tokpanel {
  display: grid;
  gap: var(--s-2);
  margin-top: var(--s-2);
}
.tokpanel__est,
.tokpanel__sk,
.tokpanel__src,
.toksplit {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.3rem var(--s-3);
}
.tokpanel__by {
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  color: var(--text-muted);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.tokpanel__chips,
.tokrun__skills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.tokrun__skills {
  flex-basis: 100%;
}
/* A skill chip is a door to the Docs panel, drawn unavailable until it exists. */
.tokchip {
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  background: none;
  cursor: not-allowed;
  color: var(--text-muted);
}
.tokest__n,
.tokrun__n {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  font-variant-numeric: tabular-nums;
  color: var(--text);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.tokpanel .tt__bar {
  height: 4px;
  margin: 0.25rem 0 0.15rem;
  background: color-mix(in oklch, var(--ink) 12%, transparent);
}
.tt__fill {
  height: 100%;
  background: var(--accent);
}
.tt__fill.is-over {
  background: var(--danger);
}
.brn__over {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  flex: none;
  color: var(--danger);
  white-space: nowrap;
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.tokruns {
  display: grid;
  gap: 0.1rem;
}
.tokrun {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.25rem 0.55rem;
  padding: 0.38rem 0;
  border-top: 1px solid var(--rule-faint);
}
.tokrun:first-child {
  border-top: 0;
}
/* The run dot by outcome: the ruled carve-out (§115 item 5). */
.tokrun__dot {
  flex: none;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--ink-faint);
}
.tokrun__dot[data-outcome='settled'] {
  background: var(--success);
}
.tokrun__dot[data-outcome='held'] {
  background: var(--accent);
}
.tokrun__dot[data-outcome='quarantined'] {
  background: var(--warning);
}
/* The run id keeps its case: mono family, never `.u-mono`, never truncated. */
.tokrun__model {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  color: var(--text-2);
  word-break: break-word;
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.tokrun__io {
  display: inline-flex;
  align-items: baseline;
  gap: 0.25rem;
  margin-left: auto;
}
.tokrun__k,
.tokrun__when,
.tokpanel__reason {
  color: var(--text-muted);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
  color: var(--text-muted);
}
.tokpanel__reason {
  margin: 0;
}

/* AW-04: the plan as a card in the drawer's chat, and its approved card. */
.aip__msg--plan {
  display: grid;
  gap: var(--s-2);
}
.aip__plan {
  display: grid;
  gap: var(--s-2);
  padding: var(--s-3);
  border: 1px solid var(--border);
  background: var(--surface);
}
.aip__plan-k {
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  color: var(--text-muted);
}
.aip__plan-steps {
  margin: 0;
  padding-left: 1.1rem;
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.aip__plan-meta {
  margin: 0;
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  color: var(--text-2);
}
.aip__plan-refused {
  color: var(--danger);
}
.aip__plan-act {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
}
.aip__plan-done {
  display: grid;
  gap: var(--s-1);
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
}
.aip__plan-words {
  margin: 0;
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  white-space: pre-wrap;
}
/* SPDX-License-Identifier: AGPL-3.0-only */

/* The execution map (MP-6-3, DS-TASK-12 to DS-TASK-14), ported from the
   mockup's `app.css` 12448-12593 onto the product's tokens. Rail only (R63):
   the other four studies, the study bar and the route facets are not built.
   Three connector colours: --accent, dashed --warning, and the grid quieter
   than --border. The card's 3px left rule is its state and nothing else:
   hover and selection take the other three sides. */

.tg {
  display: grid;
  gap: 0;
  min-width: 0;
}
.tg__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-4) var(--s-5);
  padding: 0 0 var(--s-3);
}
.tg__legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-4);
}
.tg__legend .sb__k {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}
.tg__lline {
  flex: none;
  width: 1.1rem;
  border-top: 2px solid var(--accent);
}
.tg__lline--wait {
  border-top-style: dashed;
  border-top-color: var(--warning);
}

/* The scroll region is the map's own, never the page's. */
.tg__scroll {
  min-width: 0;
  max-width: 100%;
  overflow: auto hidden;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.tg__canvas {
  position: relative;
  box-sizing: border-box;
  width: var(--tg-w, auto);
  height: var(--tg-h, auto);
  margin: 0 auto;
  background-color: var(--surface);
  background-image:
    linear-gradient(color-mix(in oklch, var(--border) 55%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in oklch, var(--border) 55%, transparent) 1px, transparent 1px);
  background-position: -1px -1px;
  background-size: 28px 28px;
}
.tg__stage {
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.45rem;
  overflow: hidden;
  white-space: nowrap;
}
.tg__stage::after {
  flex: 1;
  height: 1px;
  background: var(--border);
  content: '';
}

/* The card mould: fixed outer geometry, three reserved tracks inside. */
.tg__node {
  position: absolute;
  z-index: 2;
  display: grid;
  grid-template-rows: 1.9rem minmax(0, 1fr);
  box-sizing: border-box;
  width: 208px;
  height: 136px;
  min-width: 0;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: 0;
  background: var(--surface);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition:
    border-color var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease);
}
.tg__node[data-tone='gate'] {
  border-left-color: var(--warning);
}
.tg__node[data-tone='run'] {
  border-left-color: var(--accent);
}
.tg__node[data-kind='terminal'] {
  border-style: dashed;
  border-left-style: solid;
}
.tg__node:hover {
  border-top-color: var(--border-strong);
  border-right-color: var(--border-strong);
  border-bottom-color: var(--border-strong);
  background: var(--surface-2);
}
/* One ring: the global focus ring (DS-TASK-13 drift: never two). */
.tg__node[aria-pressed='true'] {
  border-top-color: var(--accent);
  border-right-color: var(--accent);
  border-bottom-color: var(--accent);
  background: var(--surface-2);
}
.tg__ntop {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0 0.55rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}
.tg__nkey {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.tg__nstate {
  flex: none;
  margin-left: auto;
}
.tg__nmain {
  display: grid;
  grid-template-rows: 2.6rem 1.15rem minmax(0, 1fr);
  min-height: 0;
  padding: 0.5rem 0.55rem 0;
}
.tg__nt {
  display: -webkit-box;
  overflow: hidden;
  color: var(--text);
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
.tg__nowner {
  align-self: center;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tg__nout {
  align-self: end;
  margin: 0 -0.55rem;
  padding: 0.35rem 0.55rem;
  overflow: hidden;
  border-top: 1px solid var(--border);
  color: var(--text-2);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tg__nout b {
  color: var(--accent);
}
.tg__node[data-tone='gate'] .tg__nout b {
  color: var(--warning);
}
.tg__ndep {
  display: none;
}

/* The connector plane: behind the cards, never eating a click. */
.tg__edges {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.tg__edge {
  fill: none;
  stroke: var(--accent);
  stroke-linecap: butt;
  stroke-linejoin: round;
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}
.tg__edge--wait {
  stroke: var(--warning);
  stroke-dasharray: 5 4;
}
.tg__arrow {
  fill: var(--accent);
}
.tg__arrow--wait {
  fill: var(--warning);
}
.tg__join {
  fill: var(--surface);
  stroke: var(--accent);
  stroke-width: 2;
}

.tg__insp {
  display: grid;
  gap: var(--s-3);
  min-width: 0;
  padding: var(--s-4) 0 0;
}
.tg__insp__t {
  margin: 0;
  color: var(--text);
  font: var(--type-card-title);
  letter-spacing: var(--type-card-title-tracking);
  text-transform: var(--type-card-title-case);
}
.tg__insp__facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  gap: var(--s-3);
}
/* D-16: an unbroken digest or run id wraps; the page never scrolls sideways. */
.tg__insp .gate__say,
.tg__insp__facts .sout__row > span:last-child {
  overflow-wrap: anywhere;
}
.tg__orphan {
  padding-top: var(--s-3);
}

/* At 900 and below the map is a vertical list: full-width cards in plan
   order, no lines, no stage labels, each card's dependency said in words. */
@media (width <= 900px) {
  .tg__canvas {
    width: auto;
    height: auto;
    padding: var(--s-3);
    background-image: none;
  }
  .tg__edges,
  .tg__stage {
    display: none;
  }
  .tg__scroll {
    overflow: visible;
  }
  .tg__node {
    position: static;
    grid-template-rows: 1.9rem auto;
    width: 100%;
    height: auto;
    margin: 0 0 var(--s-2);
  }
  .tg__nmain {
    grid-template-rows: auto auto auto;
    gap: 0.3rem;
  }
  .tg__nt {
    -webkit-line-clamp: 3;
  }
  .tg__nout,
  .tg__nowner {
    overflow-wrap: anywhere;
    white-space: normal;
  }
  .tg__ndep {
    display: block;
    padding: 0.3rem 0.55rem 0.4rem;
    border-top: 1px solid var(--border);
    color: var(--text-muted);
  }
}
/* SPDX-License-Identifier: AGPL-3.0-only */
/* The page kit's composites: section head (DS-COMP-4), stat row (DS-COMP-6),
   disclosure layer (DS-COMP-12), the sortable table's box, the bar list, the
   meter's label line, the legend and the row that opens to its detail. The
   primitives they place (banner, stat, meter, table, term tip, hint) are styled
   by the kit; a test holds this file to that. */

.sec__meta {
  display: flex;
  justify-content: space-between;
  gap: var(--s-4);
  padding-top: var(--s-3);
  border-top: 1px solid var(--rule);
  font: var(--type-tag);
  letter-spacing: var(--type-tag-tracking);
  text-transform: var(--type-tag-case);
}
.sec__right {
  color: var(--text-muted);
}

.statrow {
  display: grid;
  border-bottom: 1px dotted var(--border-strong);
}
.statrow--2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.statrow--3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.statrow--4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.statrow--5 {
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
.statrow--6 {
  grid-template-columns: repeat(6, minmax(0, 1fr));
}
.delta--up {
  color: var(--success);
}
.delta--down {
  color: var(--danger);
}
.delta--flat {
  color: var(--text-muted);
}

.layer {
  border: 1px solid var(--border);
  background: var(--surface);
}
.layer__sum {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--rule);
  cursor: pointer;
  list-style: none;
}
.layer__sum::-webkit-details-marker {
  display: none;
}
.layer__sum:hover {
  background: var(--surface-2);
}
.layer__count {
  color: var(--text-muted);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.layer__chev {
  margin-left: auto;
  width: 8px;
  height: 8px;
  border-right: 1px solid currentcolor;
  border-bottom: 1px solid currentcolor;
  transform: rotate(45deg);
}
.layer[open] > .layer__sum .layer__chev {
  transform: rotate(225deg);
}
.layer__body {
  padding: 17px;
}

.tbl-box {
  max-width: 100%;
  overflow: auto;
}

.barlist {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.barlist__row {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr) auto;
  gap: var(--s-3);
  align-items: center;
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}
.barlist__label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.barlist__track {
  position: relative;
  height: 16px;
  overflow: hidden;
  background: var(--surface-2);
}
.barlist__fill {
  position: absolute;
  inset: 0 auto 0 0;
  background: color-mix(in oklch, var(--ink) 82%, transparent);
}
.barlist__val {
  min-width: 66px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
  text-align: right;
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

.pmeter {
  display: grid;
  gap: var(--s-2);
}
.pmeter__line {
  display: flex;
  justify-content: space-between;
  gap: var(--s-3);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.pmeter__val {
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--text-2);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
.legend li {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.legend__key {
  width: 10px;
  height: 10px;
}
.legend__key--ink {
  background: var(--ink);
}
.legend__key--accent {
  background: var(--accent);
}
.legend__key--muted {
  background: var(--ink-faint);
}
.legend__key--success {
  background: var(--success);
}
.legend__key--warning {
  background: var(--warning);
}
.legend__key--danger {
  background: var(--danger);
}

.opp {
  border-bottom: 1px solid var(--rule-faint);
}
.opp:last-child {
  border-bottom: 0;
}
.opp__sum {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  padding: 0.55rem var(--s-5);
  cursor: pointer;
  list-style: none;
}
.opp__sum::-webkit-details-marker {
  display: none;
}
.opp__sum:hover .opp__t {
  color: var(--accent);
}
.opp__chev {
  flex: none;
  color: var(--ink-faint);
  transition: transform var(--dur-1);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.opp[open] .opp__chev {
  transform: rotate(90deg);
}
.opp__t {
  min-width: 0;
}
.opp__save {
  margin-left: auto;
  white-space: nowrap;
}
.opp__body {
  padding: 0 var(--s-5) var(--s-4) calc(var(--s-5) + 1.15rem);
}
.opp__detail {
  margin: 0;
  color: var(--text-2);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.opp__items {
  margin: var(--s-3) 0 0;
  padding-left: 1.05rem;
  color: var(--ink-faint);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

@media (width <= 1279px) {
  .statrow--4,
  .statrow--5,
  .statrow--6 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
@media (width <= 900px) {
  .statrow--3,
  .statrow--4,
  .statrow--5,
  .statrow--6 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (width <= 640px) {
  .statrow--2,
  .statrow--3,
  .statrow--4,
  .statrow--5,
  .statrow--6 {
    grid-template-columns: minmax(0, 1fr);
  }
}
/* SPDX-License-Identifier: AGPL-3.0-only */

/* Connections & signal, sections 001 to 008: the fleet banner, the connector
   controls and table, the grants, the tripwires and the night round. Ported
   from the mockup's `app.css` (294-295, 613-676, 2912-2955, 8878-8953,
   8999-9037, 9046-9118) onto the product's tokens. The section head, the
   stat row, the banner, the table and the legend come from the kit; only what
   they leave unplaced is here. */

/* The fleet banner: one body that grows, then its action, centred. */
[data-fleet-banner] .banner {
  align-items: center;
}

/* The mono note line the page's sections share (mockup `.approval__meta`). */
.approval__meta {
  margin: 0;
  color: var(--text-muted);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

/* -- 002 Connectors ------------------------------------------------------ */
.connctrls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
  margin-bottom: var(--s-3);
}
.connctrls .facet {
  background: var(--surface);
}
.connmore {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  margin-top: var(--s-3);
}
.connmore .pginfo {
  color: var(--ink-faint);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.conn__scroll {
  overflow-x: auto;
}
.conn__row {
  border-bottom: 1px solid var(--border);
  cursor: pointer;
}
.conn__row td {
  padding: 0.45rem var(--s-5);
  vertical-align: middle;
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}
.conn__row[aria-expanded='true'],
.conn__row:hover {
  background: var(--surface-2);
}
.conn__detail > td {
  padding: 0;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}
.conn__panel {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: var(--s-6);
  padding: var(--s-5) var(--s-5) var(--s-6) 2.6rem;
}
.conn__panel p {
  margin: 0;
}
.panel__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--s-2);
}
.panel__actions > p {
  flex-basis: 100%;
}

/* -- 006 Grants ---------------------------------------------------------- */
.grl__lede,
.tw__lede,
.nr__lede {
  margin: 0;
}
.grl__lede {
  color: var(--text);
  font: var(--type-subheading);
  letter-spacing: var(--type-subheading-tracking);
  text-transform: var(--type-subheading-case);
}
.grl__grp + .grl__grp {
  border-top: 1px solid var(--border-strong);
}
.grl__banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  margin: 0;
  padding: var(--s-3) var(--s-5);
  background: color-mix(in srgb, var(--border) 22%, transparent);
}
.grl__grp ul,
.tw__row,
.nr,
.nr__roster ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
.grl__row {
  display: grid;
  gap: 0.35rem var(--s-4);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--border);
}
.grl__row:last-child {
  border-bottom: 0;
}
.grl__row p {
  margin: 0;
}

/* -- 007 Tripwires and 008 The night round ------------------------------- */
.tw__row {
  display: grid;
  gap: 0.35rem;
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--border);
}
.tw__row:last-child {
  border-bottom: 0;
}
.tw__row p {
  margin: 0;
}
.tw__row--dead {
  border-left: 2px solid var(--warning);
}
.nr {
  padding: var(--s-4) var(--s-5);
}
.nr > li {
  padding: var(--s-1) 0;
}
.nr time {
  display: inline-block;
  min-width: 4.2rem;
}
.nr__roster h3 {
  margin: 0;
  padding: var(--s-3) var(--s-5) 0;
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
}
.nr__roster li {
  padding: var(--s-2) var(--s-5);
}

@media (width <= 900px) {
  .conn__panel {
    grid-template-columns: 1fr;
  }
}
/* SPDX-License-Identifier: AGPL-3.0-only */

/* Connections & signal, the per-client region (MP-14-10a): the scope bar, 010
   Graduation with its standing approvals, and 011 Channels and 012 Exceptions
   drawn as mock rows. Ported from the mockup's `app.css` (556, 4314-4319,
   5079-5081, 8328-8494, 8758-8786) onto the product's tokens. The mockup's
   `.chan__mark` and `.vaultpill` glyphs are not drawn: the product's mock rows
   carry no kind and no custody. */

.gradsec {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  min-width: 0;
}

/* -- The client scope bar ------------------------------------------------ */
.gradbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  padding-bottom: var(--s-2);
}
.gradbar__l {
  color: var(--ink-faint);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
.gradbar select {
  width: auto;
  min-width: 15rem;
}

/* -- 010 Graduation: the class and its record left, the switch right; the
   note runs the full width under both, since it is the row's argument. -- */
.grad__row,
.chan__row,
.exc__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.35rem var(--s-5);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--border);
}
.grad__row:last-child,
.chan__row:last-child,
.exc__row:last-child {
  border-bottom: 0;
}
.grad__head,
.chan__head,
.exc__head {
  display: flex;
  flex-wrap: wrap;
  grid-column: 1;
  align-items: center;
  gap: var(--s-3);
}
.grad__name,
.chan__name,
.exc__what {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s-3);
  min-width: 0;
}
.grad__name b,
.chan__name b,
.exc__what b {
  font: var(--type-body-strong);
  letter-spacing: var(--type-body-strong-tracking);
  text-transform: var(--type-body-strong-case);
}
/* The action class reads exactly as typed: mono, never uppercased. */
.grad__type {
  color: var(--ink-faint);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.grad__act,
.chan__act,
.exc__act {
  display: flex;
  grid-row: 1 / span 2;
  grid-column: 2;
  align-items: center;
  justify-content: flex-end;
  gap: var(--s-3);
}
.exc__act {
  align-items: flex-start;
}
.autosw__lbl {
  max-width: 12.5rem;
  overflow-wrap: anywhere;
  color: var(--text-muted);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
  text-align: right;
}
.grad__rec {
  display: flex;
  flex-wrap: wrap;
  grid-column: 1;
  align-items: baseline;
  gap: var(--s-4);
  color: var(--text-muted);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
/* Three counts, never a score. */
.grad__n b {
  color: var(--text);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.grad__note {
  grid-column: 1 / -1;
  max-width: 62ch;
  margin: 0.25rem 0 0;
  color: var(--text-2);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}

/* -- 011 Channels and 012 Exceptions: the graduation row's frame; each
   row's argument runs full width under it. -------------------------- */
.chan__where,
.exc__where {
  color: var(--ink-faint);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  overflow-wrap: anywhere;
}
.chan__meta {
  display: flex;
  flex-wrap: wrap;
  grid-column: 1;
  align-items: center;
  gap: var(--s-3);
  color: var(--text-muted);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.chan__note,
.exc__why {
  grid-column: 1 / -1;
  max-width: 74ch;
  margin: 0.25rem 0 0;
  color: var(--text-2);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.exc__why {
  grid-column: 1;
  margin-top: 0.2rem;
}
.exc__meta {
  display: flex;
  flex-wrap: wrap;
  grid-column: 1 / -1;
  gap: var(--s-2) var(--s-4);
  margin-top: 0.3rem;
  color: var(--ink-faint);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}

/* The switch is on every row, the dead ones included: squared, its knob an
   outline that fills only while the class runs unattended. */
.autosw {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: flex-start;
  width: 2.6rem;
  height: 1.25rem;
  padding: 2px;
  border: 1px solid var(--border);
  background: var(--surface);
  cursor: pointer;
}
.autosw__k {
  display: block;
  width: 1rem;
  height: 100%;
  border: 1px solid var(--border-strong);
  background: var(--paper);
}
.autosw[aria-checked='true'] {
  justify-content: flex-end;
  border-color: var(--success);
}
.autosw[aria-checked='true'] .autosw__k {
  border-color: var(--success);
  background: var(--success);
}
.autosw:hover:not(:disabled) {
  border-color: var(--border-strong);
}
.autosw:focus-visible {
  border-color: var(--accent);
  outline: none;
}
.autosw:disabled {
  border-style: dashed;
  cursor: not-allowed;
}
.autosw:disabled .autosw__k {
  border-style: dashed;
  border-color: var(--border);
}

/* -- Standing approvals: a sentence is a record; a refusal's left rule is
   the whole difference from an approval. ------------------------------- */
.pslist {
  display: grid;
  gap: var(--s-2);
}
.ps {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  background: var(--surface);
}
.ps--no {
  border-left-color: var(--danger);
}
.ps__text {
  margin: 0;
  color: var(--text);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.ps__meta {
  margin-top: 0.25rem;
  color: var(--ink-faint);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
.ps__x {
  padding: 0 0.2rem;
  border: 0;
  background: none;
  color: var(--text-muted);
  font: var(--type-subheading);
  letter-spacing: var(--type-subheading-tracking);
  text-transform: var(--type-subheading-case);
  cursor: pointer;
}
.ps__x:hover {
  color: var(--danger);
}
/* The graduation forms' row. Scoped to the region, since Projects > Work log
   has a `.fieldrow` of its own that keeps the kit button's height. A row wraps
   when its fields no longer fit, and each field keeps room to be read. */
.gradsec .fieldrow {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 0.35rem;
}
.gradsec .fieldrow > input {
  flex: 1 1 8rem;
}
.gradsec .fieldrow > .btn {
  align-self: stretch;
  height: auto;
  white-space: nowrap;
}
.connnote__field {
  min-width: 8rem;
  padding: 0.45rem 0.55rem;
  border: 1px solid var(--border);
  background: var(--paper);
  color: var(--text);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}
.connnote__field:focus {
  border-color: var(--accent);
  outline: none;
}

/* 640 is the narrow stop: the figure row stacks, the switch drops under its
   class, and the mandate form's controls stack. */
@media (width <= 640px) {
  .grad__row,
  .chan__row,
  .exc__row {
    grid-template-columns: minmax(0, 1fr);
  }
  .grad__act,
  .chan__act,
  .exc__act {
    grid-row: auto;
    grid-column: 1;
    justify-content: flex-start;
    padding-top: 0.2rem;
  }
  .autosw__lbl {
    max-width: none;
    text-align: left;
  }
  .gradbar select {
    width: 100%;
    min-width: 0;
  }
  .gradsec .fieldrow > input {
    flex: 1 1 100%;
  }
}
/* SPDX-License-Identifier: AGPL-3.0-only */

/* What agent runs cost: Connections & signal section 009, skill costing, and
   the Executive page's section 005, what our agents cost us. Ported from the
   mockup's `app.css` (9600-9657 and the #agentcost layout) onto the
   product's tokens. The mockup prints skill costing 012; the product numbers
   it 009. Nothing on either carries a tone: a large figure is a large
   process, not a problem. */

.skcsec {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  min-width: 0;
}

/* The mono note line (mockup `.approval__meta`), held here until the page's
   own sheet carries it for every section. */
.skcsec .approval__meta {
  margin: 0;
  color: var(--text-muted);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

/* -- 009 Skill costing -------------------------------------------------- */
.skc__lede {
  display: grid;
  gap: var(--s-2);
}
.skc__count {
  margin: 0;
  color: var(--text);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.skc__say {
  max-width: 68ch;
  margin: 0;
  color: var(--text-2);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.skc {
  margin: 0;
  padding: 0;
  list-style: none;
}
.skc__row {
  display: grid;
  gap: 0.35rem;
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--border);
}
.skc__row:last-child {
  border-bottom: 0;
}
.skc__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
}
.skc__what {
  color: var(--text);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
/* Mono: quantities read down a column. */
.skc__fig {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s-4);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.skc__figv {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
}
.skc__n {
  color: var(--text);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  font-variant-numeric: tabular-nums;
}
.skc__u,
.skc__iok {
  color: var(--ink-faint);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.skc__spread {
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.skc__io {
  display: inline-flex;
  align-items: baseline;
  gap: 0.3rem;
  color: var(--text-2);
}
.skc__ion {
  font-variant-numeric: tabular-nums;
}
/* The two silences are sentences, never a thinner number. */
.skc__fig--thin .skc__say,
.skc__fig--none .skc__say {
  color: var(--text-muted);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.skc__fig--none {
  color: var(--text-muted);
}
.skc__obs,
.skc__mods,
.skc__alt {
  margin: 0;
  color: var(--text-2);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.skc__k {
  margin-right: 0.5rem;
  color: var(--ink-faint);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
/* Exact model ids wrap; they never truncate. */
.skc__model {
  display: inline-block;
  margin-right: var(--s-3);
  color: var(--text-2);
  overflow-wrap: anywhere;
}
.skc__foot {
  padding-top: var(--s-4);
  border-top: 1px solid var(--border);
}
.skc__split {
  display: grid;
  gap: 0.3rem;
  margin: 0;
  color: var(--text-2);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.skc__leg {
  font-variant-numeric: tabular-nums;
}
.skc__leg b {
  color: var(--text);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

/* -- 005 What our agents cost us: the log beside its two roll-ups -------- */
.agentcost__grid {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  align-items: start;
  gap: var(--s-4);
}

/* 900 stacks the roll-ups under the log; 640 stacks the figure row. */
@media (width <= 900px) {
  .agentcost__grid {
    grid-template-columns: minmax(0, 1fr);
  }
}
@media (width <= 640px) {
  .skc__fig {
    gap: var(--s-2) var(--s-3);
  }
  .skc__head {
    gap: var(--s-2);
  }
}
/* SPDX-License-Identifier: AGPL-3.0-only */
/* The Notifications panel and `/inbox/` (MP-7-3): the pinned mockup's `nt__`
   rules. The count badge is the kit's `cbadge`, placed, never restyled; a tab's
   count is its plain member (`.cmtab .cbadge--plain`). */

.nt {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}
.nt__sum {
  margin: 0;
  color: var(--text-2);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.nt__sum b {
  color: var(--text);
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
}
.nt__tabs {
  border-bottom: 1px solid var(--border);
}
.nt__pane {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}
.nt__grp {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
.nt__ghead {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--border);
  color: var(--text);
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
}
.nt__gname {
  overflow: hidden;
  color: inherit;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The owner's spacing (mockup app.css:10660): cards 8px apart, 4px inside. */
.nt__band {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
.nt__bh {
  margin: var(--s-2) 0 0.15rem;
  color: var(--ink-faint);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
/* A grid of the kind mark and the text: with the rule and padding, the text
   sits 40px in (mockup app.css:9709). */
.nt__row {
  display: grid;
  grid-template-columns: 1.1rem minmax(0, 1fr);
  gap: var(--s-2);
  padding: var(--s-1) var(--s-3);
  border-left: 2px solid var(--border);
  color: inherit;
  text-decoration: none;
}
.nt__row:hover,
.nt__row:focus-visible {
  outline: none;
  background: color-mix(in oklch, var(--accent) 6%, transparent);
}
.nt__row--owe {
  border-left-color: var(--accent);
}
.nt__mark {
  color: var(--ink-faint);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.nt__mark--team {
  color: var(--text-2);
}
.nt__mark--progress {
  color: var(--text-muted);
}
/* The mention mark is mono (the mockup's CM 12.8/500); the data style is the
   nearest declared one, so it draws at 400 (MP-1-4 census). */
.nt__at {
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.nt__body {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}
.nt__text {
  color: var(--text);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.nt__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.45rem;
  color: var(--text-muted);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.nt__when {
  color: var(--text-muted);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.nt__closed {
  margin-top: var(--s-2);
}
.nt__summary {
  padding: 0.2rem 0;
  color: var(--text-muted);
  cursor: pointer;
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
.nt__summary:hover {
  color: var(--text-2);
}
.nt__closed .nt__row {
  opacity: 0.7;
}

.bell {
  position: relative;
}
/* SPDX-License-Identifier: AGPL-3.0-only */
/* The activity ledger (MP-8-4): the pinned mockup's `act__` rules. The day head
   sticks while its day scrolls under it. The search row, the reading line (in
   the accent: what the box understood) and the count line sit above the list. */

.act__find {
  display: flex;
  gap: var(--s-3);
  align-items: center;
  max-width: 40rem;
}
.act__find .search {
  flex: 1;
}
.act__read {
  margin: var(--s-3) 0 0;
  color: var(--accent);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.act__count {
  margin: var(--s-2) 0 0;
  color: var(--text-muted);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

.act__list {
  margin-top: var(--s-5);
}
.act__day {
  position: sticky;
  top: 0;
  z-index: 1;
  margin: 0;
  padding: var(--s-3) 0 var(--s-2);
  border-bottom: 1px solid var(--border-strong);
  background: var(--bg);
  color: var(--text);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
.act__row {
  display: grid;
  grid-template-columns: 3.2rem 6.5rem 5rem minmax(0, 1fr);
  gap: var(--s-4);
  align-items: baseline;
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
}
.act__t {
  color: var(--text-muted);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.act__kind {
  color: var(--text-2);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
.act__who {
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
}
.act__body {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}
.act__text {
  color: var(--text);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.act__proj {
  color: var(--text-muted);
  text-decoration: none;
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}
.act__proj:hover {
  color: var(--accent);
  text-decoration: underline;
}
.act__more {
  margin-top: var(--s-4);
}

@media (width <= 640px) {
  .act__row {
    grid-template-columns: 3.2rem minmax(0, 1fr);
  }
}
/* SPDX-License-Identifier: AGPL-3.0-only */
/* The Team panel (MP-7-10, C71-D, C71-G): the pinned mockup's `tmc__` rules. Buttons
   are the kit's `btn`, counts its `cbadge`, the empty line the kit's `Empty`, and the
   thread the task page's `thread`/`msg` dialect, all placed, never restyled.
   Faces are the kit's team-card avatar and the door its door mark. Away is a
   dashed ring and the word Away, never a coloured dot. The group
   list, picker and head (C71-G) are drawn by no mockup surface: spacing only,
   everything else from the kit. */

.tmc {
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
}
.tmc__me {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  margin: 0 0 var(--s-3);
  color: var(--text-2);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.tmc__why {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 0.25rem;
}
.tmc__strip {
  display: flex;
  flex: none;
  gap: var(--s-3);
  overflow-x: auto;
  padding-bottom: var(--s-3);
  border-bottom: 1px solid var(--border);
}
.tmc__p {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  padding: 0.1rem;
  color: var(--text-muted);
}
.tmc__face {
  padding: 0;
  border: 0;
  background: none;
}
button.tmc__face {
  cursor: pointer;
}
.tmc__n {
  color: inherit;
  text-decoration: none;
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
a.tmc__n:hover {
  color: var(--accent);
  text-decoration: underline;
}
.tmc__u {
  position: absolute;
  top: -3px;
  right: -3px;
}
.tmc__away {
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
}
.tmc__p.is-on .tmc__n {
  color: var(--text);
}
.tmc__conv {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-height: 0;
}
.tmc__scroll {
  flex: 1;
  min-height: 0;
  overflow: auto;
}
.tmc .thread {
  padding-top: var(--s-3);
  border-top: 0;
}
.tmc .composer {
  display: flex;
  flex: none;
  gap: var(--s-2);
  padding-top: var(--s-3);
}
.tmc .composer input {
  flex: 1;
}

/* C71-G group conversations: spacing and layout only. */
.tmc__groups {
  display: flex;
  flex: none;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--border);
}
.tmc__glist {
  margin: 0;
  padding: 0;
}
.tmc__members {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.tmc__members li {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}
.tmc__g {
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-2);
  cursor: pointer;
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.tmc__g[aria-pressed='true'] {
  color: var(--text);
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
}
.tmc__new,
.tmc__renaming,
.tmc__adding {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--s-2);
}
.tmc__pick {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  border: 0;
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.tmc__ghead {
  flex: none;
  padding-top: var(--s-3);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.tmc__gname,
.tmc__with {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin: 0 0 var(--s-2);
}
.tmc__with {
  color: var(--text-muted);
}
/* SPDX-License-Identifier: AGPL-3.0-only */
/* The Clients panel (DOCK.md section 2): the pinned mockup's `cl__` rules
   (app.css:6462-6627, 9387-9406, 11583-11592) under `clbook__`. The field is the
   kit's `tf`, the waiting count its corner `cbadge`, the sample mark its
   `MockRegion`, all placed, never restyled. Radius is 0 and status has no fill.
   R37 (D-10): a row's door shows at rest below 900 and on any device that
   cannot hover; above 900 with a hovering pointer it shows on hover or focus. */

.clbook__note {
  margin: 0 0 var(--s-3);
  color: var(--text-muted);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
.clbook__find {
  margin-bottom: var(--s-2);
}
.clbook__count {
  margin: 0 0 var(--s-3);
  color: var(--ink-faint);
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
}
.clbook__list {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* One row to a reader: the rule spans the door and the count, and hovering
   either half lights the whole row. */
.clbook__item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  border-bottom: 1px solid var(--border);
}
.clbook__item:hover {
  background: var(--surface);
}
.clbook__row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.1rem 0.6rem;
  align-items: center;
  padding: 0.55rem 0.35rem 0.55rem 0;
}
.clbook__tile {
  display: grid;
  place-items: center;
  width: 1.4rem;
  height: 1.4rem;
  border: 1px solid var(--border-strong);
  background: var(--paper);
  color: var(--text-2);
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
}
.clbook__who {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}
.clbook__name {
  overflow: hidden;
  color: var(--text);
  font: var(--type-small-strong);
  letter-spacing: var(--type-small-strong-tracking);
  text-transform: var(--type-small-strong-case);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.clbook__industry {
  color: var(--text-muted);
  font: var(--type-caption);
  letter-spacing: var(--type-caption-tracking);
  text-transform: var(--type-caption-case);
}
/* The door keeps its track while hidden, so rows never shift under the pointer.
   It hides by opacity, and only for a hovering pointer above 900, so Tab,
   screen readers and touch always reach it. */
.clbook__go {
  display: inline-flex;
}
@media (hover: hover) and (width > 900px) {
  .clbook__go {
    opacity: 0;
  }
  .clbook__item:hover .clbook__go,
  .clbook__item:focus-within .clbook__go {
    opacity: 1;
  }
}
.clbook__door {
  display: inline-grid;
  place-items: center;
  padding: 0.35rem 0.3rem;
  color: var(--text-muted);
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
}
.clbook__door:hover,
.clbook__door:focus-visible {
  color: var(--accent);
}
/* `position: relative` anchors the corner count to the glyph, not the panel. */
.clbook__waiting {
  position: relative;
  display: inline-grid;
  place-items: center;
  margin-right: 0.1rem;
  padding: 0.35rem 0.5rem 0.35rem 0.35rem;
  color: var(--text-muted);
  font: var(--type-badge);
  letter-spacing: var(--type-badge-tracking);
  text-transform: var(--type-badge-case);
}
.clbook__empty {
  margin: var(--s-3) 0 0;
  color: var(--text-muted);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}
/* The client the panel was opened at (CS-7.29), above the book: lit as a
   hovered row stays lit, so it reads as the one chosen. */
.clbook__opened {
  margin: 0 0 var(--s-3);
}
.clbook__opened[aria-current='true'] {
  background: var(--surface);
}
/* SPDX-License-Identifier: AGPL-3.0-only
   ============================================================================
   Layer 6. THE LOAD ORDER IS THE CONTRACT: this sheet loads last and it is the
   only one that may. Layers 1-5 are the ported estate and are not edited here.

   What is in it: the controls the working slice adds that the pinned mockup
   never drew, because it shipped populated demonstration data and had nothing
   to submit. A sign-in form, a create form, a lifecycle button row and the five
   read-state containers. Everything borrows layer 1's tokens; no colour, radius
   or space literal appears below.

   What is NOT in it: any override of a ported rule. A change to the drawn
   estate belongs in the layer that drew it, or it is a divergence from the
   pinned source that nobody can find later.
   ========================================================================= */

.readstate {
  padding: var(--s-4) 0;
}

/* A read state with nothing to say (the read answered) takes no room. */
.readstate:empty {
  display: none;
}

/* Sign in, signed out and with no shell (B6): the brand mark over one card
   of kit fields (DS-COMP-26's labels, DS-PRIM-3's input, DS-PRIM-1's primary),
   centred on the page ground. */
.signin {
  display: grid;
  place-items: center;
  align-content: center;
  gap: var(--s-5);
  min-height: 100vh;
  padding: var(--s-6) var(--s-4);
  background: var(--bg);
  color: var(--text);
}

.signin__form {
  width: min(24rem, 100%);
}

.signin__brand {
  display: grid;
  justify-items: start;
  gap: 0.4rem;
}

/* The rail's wordmark as it lands: its 176px ceiling in the rail's column. */
.signin__brand .brand--wordmark {
  width: 175px;
  color: var(--text);
}

.signin .field,
.setrow .field {
  margin-block-end: 0;
}

.signin__build {
  margin: 0;
  padding: 0;
}

.signin__foot {
  display: flex;
  justify-content: flex-end;
}

/* The settings rows' own parts (B5): the number and its on and off on one
   line, the provenance under the explanation, and a lost race across the row. */
.setrow__line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--s-2);
}

.setrow__num {
  width: 8rem;
}

.setrow__meta {
  margin: var(--s-2) 0 0;
  color: var(--text-muted);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
  overflow-wrap: anywhere;
}

.setrow__conflict {
  grid-column: 1 / -1;
  display: grid;
  gap: var(--s-2);
  justify-items: start;
}

@media (width <= 640px) {
  .setrow__line {
    justify-content: flex-start;
  }
}

/* The session-ended notice. Bordered rather than coloured: the surface has one
   interactive signal and this is not it, and a notice that shouts is a notice
   people learn to look past. */
.signin__ended {
  margin-block-end: var(--s-3);
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--text);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}

.signin__ended code {
  font: var(--type-mono);
  letter-spacing: var(--type-mono-tracking);
  text-transform: var(--type-mono-case);
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  margin-block-end: var(--s-3);
}

.input {
  width: 100%;
  padding: var(--s-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: inherit;
  font: inherit;
}

/* No focus rule and no button rule here. Layer 1 draws `--focus-ring` on every
   `:focus-visible` control and layer 2 owns `.btn`, `.btn--primary` and their
   disabled states: redrawing either would be the override of a ported rule
   this sheet exists not to make. */

/* A settings page's sections (SL09: Access, Telemetry), 32px apart, as the
   placeholder page's `.content` spaces its `.sec` blocks (PAGE-MAP SH-40 to 44). */
.secs {
  display: flex;
  flex-direction: column;
  gap: var(--s-6);
}

/* Timer recovery uses the strip's on-dark ink and the existing secondary control. */
[data-task-timer-strip],
[data-task-timer-strip] [data-task-timer-notice] {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
}
[data-task-timer-strip] [data-task-timer-notice] {
  --text: var(--on-dark);
  --btn-outline: var(--on-dark);
  --bg: var(--app-chrome);
}

.btnrow {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

/* The create form wears the mockup's quick-add field (`.cbd__field`, layer 4)
   and its secondary sm button, in one row above the board. */
.projects__create {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
}

.projects__create .cbd__field {
  flex: 0 1 31rem;
}

.projects__create > p {
  flex: 1 0 100%;
  margin: 0;
}

/* The inbox minimum (INB-1) is a flush list card: the head keeps the card's
   padding and the rows (the kit's page rows) run to its edges. A state that
   is not a list (loading, empty, refused) sits inside the card's padding. */
.inbox > .readstate {
  padding: 0 var(--s-5) var(--s-5);
}

.inbox > .readstate[data-outcome='ready'] {
  padding: 0;
}

.inbox__list {
  margin: 0;
  padding: 0;
}

.inbox__task {
  color: inherit;
  text-decoration: none;
}

.inbox__task:hover {
  text-decoration: underline;
}

/* The title box is the board's quick-add field (DS-COMP-16): the box draws the
   border and the focus, the input inside it draws nothing. */
.projects__create .cbd__field {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.3rem 0.55rem;
  border: 1px solid var(--border);
  background: var(--surface);
}

.projects__create .cbd__field:focus-within {
  border-color: var(--accent);
}

.projects__create .cbd__field input {
  width: 100%;
  min-width: 3rem;
  /* The control's own 1px 2px, which the mockup's field keeps: the box is 34 tall. */
  padding: 1px 2px;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--text);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}

/* The Projects page's Board and Work log, drawn as the tab row (DS-COMP-2):
   43 tall, the tabs 32 apart, the current one in --text at 500 over a 2px
   accent rule. At 390 the row scrolls sideways with no scrollbar. */
.routetabs {
  display: flex;
  align-items: stretch;
  gap: var(--s-6);
  min-width: 0;
  padding: 0 var(--s-6);
  overflow-x: auto;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  scrollbar-width: none;
}

.routetabs::-webkit-scrollbar {
  display: none;
}

.routetabs__t {
  flex: none;
  padding: 0.65rem 0 0.525rem;
  border-bottom: 2px solid transparent;
  color: var(--text-2);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
  text-decoration: none;
  white-space: nowrap;
}

.routetabs__t:hover {
  color: var(--text);
}

.routetabs__t[aria-current='page'] {
  border-bottom-color: var(--accent);
  color: var(--text);
  font: var(--type-body-strong);
  letter-spacing: var(--type-body-strong-tracking);
  text-transform: var(--type-body-strong-case);
}

/* The inbox is a flush card (DS-COMP-7): its head is padded by the card's
   rule, and the list and its read states sit inside the same gutter. */
.inbox > :not(.card__head) {
  margin: 0;
  padding: 0 var(--s-5) var(--s-5);
}

/* 390: the narrowest pinned comparison width. The create form stacks rather
   than scrolling sideways, because a horizontal scroll on a form is a control
   a thumb cannot reach. */
@media (width <= 480px) {
  .projects__create {
    flex-direction: column;
    align-items: stretch;
  }

  .projects__create .cbd__field {
    flex: 1 1 auto;
  }
}

/* The proposal section prints stored values it did not choose the length of: an
   evidence pack, a payload, a 64-character hash, a digest. Measured at 390 the
   page and the section both scrolled sideways and the evidence body was wider
   than the viewport, because a `pre` does not wrap and a hash has nowhere to
   break. Wrapping is the honest fix: the value stays exactly what was stored
   and the reader can still see all of it. Breaking anywhere is confined to
   these blocks, where the content is a digest rather than prose. */
[data-evidence='body'],
[data-version='payload'] {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-width: 100%;
}

[data-decision='hash'],
[data-version='digest'],
[data-evidence='digest'] {
  overflow-wrap: anywhere;
}

/* The Projects dock panel's to-dos (MP-7-1), drawn as the mockup's Projects
   panel list (PJ-02 to PJ-12, `assets/app.css` .tsearch and .tl). The list is
   its own container, so the priority column yields first when the list is
   narrower than 380px, wherever the panel is seated. */
.todos {
  container-type: inline-size;
}

.dp__list {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.todos .tsearch__tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem;
  padding: 0.3rem 0.35rem;
  border: 1px solid var(--border);
  background: var(--bg);
}

.todos .tsearch__tags:focus-within {
  border-color: var(--accent);
}

.todos .tsearch__in {
  flex: 1;
  min-width: 7rem;
  padding: 0.2rem 0.25rem;
  border: 0;
  background: none;
  color: var(--text);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}

/* The box draws the focus: its border turns to the accent. */
.todos .tsearch__in:focus {
  outline: none;
}

/* A chip (PJ-03): its kind in mono capitals above the value, and its cross. */
.todos .tsearch__tag {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.1rem 0.2rem 0.1rem 0.4rem;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  font: var(--type-small);
  letter-spacing: var(--type-small-tracking);
  text-transform: var(--type-small-case);
}

.todos .tsearch__tag:hover {
  border-color: var(--ink);
}

.todos .tsearch__kind {
  color: var(--ink-faint);
  font: var(--type-chip);
  letter-spacing: var(--type-chip-tracking);
  text-transform: var(--type-chip-case);
}

.todos .tsearch__x {
  padding: 0 0.2rem;
  border: 0;
  background: none;
  color: var(--ink-faint);
  cursor: pointer;
}

.todos .tsearch__read {
  margin: 0;
  padding-top: var(--s-2);
  color: var(--ink-faint);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

.todos__acts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  padding-top: var(--s-2);
}

.todos .tl {
  display: grid;
  padding: 0.2rem 0.8rem 0.9rem 0;
}

.todos__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.todos .tl__row {
  display: grid;
  grid-template-columns: 0.95rem 1.35rem minmax(0, 1fr) 1.5rem 4.2rem 3.4rem;
  gap: 0.4rem;
  align-items: center;
}

/* PJ-05: the column heads are a list row (DS-COMP-13) of the kit's sort
   buttons, mono and muted; the sorted one in the text colour. */
.todos .tl__row .table__sort {
  color: var(--text-muted);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

.todos .tl__row .table__sort.is-sort {
  color: var(--text);
}

.todos .tl__row {
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--rule-faint);
}

.todos .tl__row:hover {
  background: color-mix(in oklch, var(--ink) 3%, transparent);
}

/* DS-PRIM-7, the task list's size. */
.todos .sbbox {
  display: grid;
  place-items: center;
  width: 0.95rem;
  height: 0.95rem;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--border-strong);
  background: var(--bg);
  color: transparent;
  cursor: pointer;
}

.todos .sbbox:hover {
  border-color: var(--accent);
}

.todos .tl__av {
  display: grid;
  place-items: center;
  width: 1.35rem;
  height: 1.35rem;
  overflow: hidden;
  border-radius: 50%;
}

.todos .tl__av .av {
  width: 100%;
  height: 100%;
}

.todos .tl__t {
  min-width: 0;
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}

.todos .tl__t a {
  color: var(--text);
  text-decoration: none;
}

.todos .tl__t a:hover {
  color: var(--accent);
}

.todos .tl__cmt {
  display: inline-flex;
  align-items: center;
  min-width: 0;
}

.todos .tl__cmtb {
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.todos .tl__due {
  color: var(--text);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

.todos .tl__due.is-now {
  color: var(--text);
}

.todos .tl__due.is-bad {
  color: var(--danger);
}

.todos .tl__pri {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  color: var(--text-muted);
  font: var(--type-data);
  letter-spacing: var(--type-data-tracking);
  text-transform: var(--type-data-case);
}

.todos .tl__pri .sline {
  display: inline-block;
  width: 3px;
  height: 0.85em;
  background: currentColor;
}

@container (max-width: 379px) {
  .todo__priority {
    display: none;
  }

  .todos .tl__row {
    grid-template-columns: 0.95rem 1.35rem minmax(0, 1fr) 1.5rem 4.2rem;
  }
}

/* C2 presence (SH-15, DS-COMP-1): who else is on this page, as the kit's
   AvatarStack (overlapping circles, each named); hidden at 640 and under. */
.presence-strip {
  display: inline-flex;
  align-items: center;
  margin-inline-end: 8px;
}

@media (width <= 640px) {
  .presence-strip {
    display: none;
  }
}

.presence-task {
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--ink-muted);
}

/* MP-2-11 Settings General: its three settings cards stand a section apart,
   as the mockup's content spaces its sections (app.css .content, --s-6). */
.settings__page {
  gap: var(--s-6);
}

/* MP-2-11: a chosen appearance crossfades for 500ms; the marker is on only
   while it does, and a person who asks for less motion gets none. */
[data-theme-fade],
[data-theme-fade] * {
  transition:
    background-color 500ms ease,
    color 500ms ease,
    border-color 500ms ease,
    fill 500ms ease !important;
}

@media (prefers-reduced-motion: reduce) {
  [data-theme-fade],
  [data-theme-fade] * {
    transition: none !important;
  }
}

/* The to-dos panel's scope switch (MP-7-2): its controls wrap in a narrow panel. */
.todos__scope {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
}

/* The dock task panel's body (MP-4-8), drawn as the mockup's panel (TASKS S1
   to S3, `assets/app.css` .sb): the name an inline field in the display face,
   the rank in mono, the fields on the paper, the description in mono and the
   subtask add a bare line. Each text snaps to its canonical style (TOKENS.md
   census, R53). Scoped to the panel: the task page draws the same parts its
   own way. */
.dtp .sb__name {
  display: block;
  box-sizing: border-box;
  width: 100%;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--border-strong);
  background: var(--bg);
  color: var(--text);
  font: var(--type-subheading);
  letter-spacing: var(--type-subheading-tracking);
  text-transform: var(--type-subheading-case);
  text-align: start;
  cursor: text;
}

.dtp .sb__name:focus {
  outline: none;
  border-color: var(--accent);
}

.dtp [data-fact='rank'] output {
  font: var(--type-eyebrow);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: var(--type-eyebrow-case);
  color: var(--text);
}

.dtp .tpr__tick {
  background: var(--bg);
}

/* A native select sizes to its font's own line: the height is set to the
   mockup's button, a 14.4px 1.2 line, its padding and its border. */
.dtp .dtp__fields select.input {
  block-size: calc(0.9rem * 1.2 + 1.1rem + 2px);
  padding: 0.55rem var(--s-3);
  border-radius: 0;
  background: var(--bg);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}

.dtp .tf__ta {
  padding: 0.5rem var(--s-3);
  background: var(--bg);
}

.dtp .sb__k {
  color: var(--ink-faint);
}

.dtp [data-step-add] {
  width: 100%;
  padding: 0.25rem 0;
  border: 0;
  border-bottom: 1px solid transparent;
  background: none;
  color: var(--text);
  font: var(--type-body);
  letter-spacing: var(--type-body-tracking);
  text-transform: var(--type-body-case);
}

.dtp [data-step-add]:focus {
  outline: none;
  border-bottom-color: var(--accent);
}

/* Settings ▸ Workflow triggers (C33): the list card's rows run to its edges. */
.triggers__list {
  margin: 0;
  padding: 0;
}

.triggers__note {
  margin: 0;
  padding: var(--s-4) var(--s-5);
}

/* Child doors, owner and retirement reason share the page and panel layout. */
[data-step-list] .sb__step {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
[data-step-list] .sb__step-title {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}
[data-step-list] [data-step-archived] {
  flex-basis: 100%;
  overflow-wrap: anywhere;
}
