/* castomo-dashkit. Generated by tools/build.mjs from kit/css/*.css. Do not edit. */

/* ---- 00-tokens.css ---- */
/* The theme-independent tokens. Every colour a component reads is defined in a
   theme file (kit/themes/<product>.css, generated from the product's setup) in
   all four modes; what lives here is either not a colour or is mixed from the
   theme's colours, so it follows every mode for free.

   No colour literal may appear in any other kit/css file: tools/check.mjs fails
   the build on one. Status colours are the exception that proves it: they are
   the same hues in every product, so they are defined here, per mode. */

/* Type: the reader's system face (--font, from derive.js: system-ui, -apple-system,
   "Segoe UI", sans-serif) at 15px / 1.5 for body copy, +0.3px tracking set once on
   <body> and inherited everywhere — never tightened, never widened per element.
   Every size is a step of the scale below; no component types a pixel size. */

:root {
  /* Product UI takes a fixed rem scale at a 1.2 ratio, not the marketing
     pages' clamp() sizes: a heading that shrinks in a sidebar reads as a bug. */
  --t-3: .6875rem;   /* 11px: a count badge, a tab-bar label, a chart axis — nothing longer */
  --t-2: .75rem;
  --t-1: .8125rem;
  --t0: .9375rem;
  --t1: 1.0625rem;
  --t2: 1.25rem;
  --t3: 1.5rem;
  --t4: 1.875rem;
  --t5: 2.375rem;

  /* One spacing rhythm, the castomo.com scale. */
  --s-2: 2px;
  --s-1: 4px;
  --s0: 8px;
  --s1: 12px;
  --s2: 16px;
  --s3: 24px;
  --s4: 32px;
  --s5: 48px;
  --s6: 64px;

  --radius-sm: 8px;
  --radius-pill: 999px;
  --target: 44px;         /* the smallest thing a thumb is asked to hit (§0.7) */
  --control-h: 40px;      /* a desktop control; it grows to --target under coarse pointers */
  --bar-h: 64px;
  --tabbar-h: 64px;
  --wrap: 1320px;         /* the ecosystem width standard (§0.1) */
  /* The setup's spacing arrives as --setup-*, and the kit's own rules (phone
     gutters, compact density) override these three: a theme file's selector
     is more specific than any rule here, so it must not set them directly. */
  --gap: var(--setup-gap, 20px);
  --pad: var(--setup-pad, 32px);
  --card-pad: var(--setup-card-pad, 24px);
  --measure: 68ch;

  --ease: cubic-bezier(.2, .7, .2, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-spring: cubic-bezier(.34, 1.56, .64, 1);
  --dur-fast: 120ms;
  --dur: 180ms;
  --dur-slow: 280ms;

  /* Mixed from the theme, so each follows the mode it is read in. */
  --rule: color-mix(in oklab, var(--ink) 11%, var(--paper-2));
  --rule-strong: color-mix(in oklab, var(--ink) 22%, var(--paper-2));
  --rule-w: 1px;
  --field: color-mix(in oklab, var(--ink) 5%, var(--paper-2));
  --field-hover: color-mix(in oklab, var(--ink) 8%, var(--paper-2));
  /* The chosen segment: the card's own white in light; in dark a lifted grey, because
     paper-2 on the field sank below its track and read as "nothing to choose here". */
  --segment-on: var(--paper-2);
  --hover: color-mix(in oklab, var(--ink) 5%, transparent);
  --press: color-mix(in oklab, var(--ink) 9%, transparent);
  --accent-soft: color-mix(in oklab, var(--accent-ink) 13%, transparent);
  --accent-wash: color-mix(in oklab, var(--accent-ink) 7%, var(--paper-2));
  --accent-hover: color-mix(in oklab, var(--accent) 86%, var(--ink));
  --scrim: color-mix(in oklab, var(--paper) 30%, rgb(0 0 0 / .55));
  --focus: var(--accent-ink);

  /* The castomo wash (guidelines §2.1), kept faint for a working screen. */
  --wash: linear-gradient(22deg, transparent 20%, color-mix(in oklab, var(--ink) 4%, transparent) 90%);

  --ok: #0E7C3A;
  --warn: #8A5200;
  --bad: #C2261A;
  --info: #1D5FB8;

  /* Support view (72-support-view.css): castomo staff inside a customer's
     account. Fixed, not the brand's, and the same in light and dark, so the
     bar means one thing in every product. White on it is 5.2:1; editing is a
     deeper, redder tone (7.0:1), because editing is the one to notice. */
  --support: #A8560B;
  --support-edit: #A3300B;
  --on-support: #FFFFFF;

  /* The two middle stops a drawing is toned with (90-art.css): the brand's
     own ramp, raw, exactly as the website tones it — the theme writes
     --brand-1..3 untouched by any contrast walk, because art is not text. */
  --art-1: var(--brand-1, var(--accent));
  --art-2: var(--brand-3, var(--accent-2));
  /* The ramp's middle, for the flat-vector kit (Andy) that paints three
     brand colours rather than toning with two: teal, red and orange in the
     pack become --brand-1, -2 and -3, as castomo.com paints them. */
  --art-3: var(--brand-2, var(--art-1));
  /* Andy's clothing and hair (the pack's navy and plum). As drawn on a light
     ground; the dark themes lift them, or a dark jacket vanishes into a dark
     page (the kit-ink trap the 2026 sites fell into). */
  --art-ink: #302D43;
  --art-ink-2: #573957;
  /* The pen and the sheet of a line-drawn kit (Minimalistic, clickSomo's): its
     near-black line work is the text's own ink and its white is the card's
     surface. Both are per-mode tokens already, so the drawing turns with every
     theme by itself — light lines on the dark card in dark, pure black and white
     in high contrast — with no fourth set of colours to keep in step. */
  --art-pen: var(--ink);
  --art-sheet: var(--paper-2);
  /* Its two accents (the pack's red and violet, largest first) and a third for
     a piece with more: the brand ramp, as Andy's. High contrast greys them like
     every drawing; high-contrast dark turns the greys round (below), because the
     darkest grey filling a figure's clothes on a black card reads as a hole. */
  --art-mark-1: var(--art-1);
  --art-mark-2: var(--art-3);
  --art-mark-3: var(--art-2);

  /* Six colours a game tells apart (71-rewards.css, Flood). Fixed, NOT the
     brand's: a green product's accent, success and art tones are three greens,
     and a board built from them cannot be played. The Okabe–Ito set, chosen
     because it stays distinguishable under the common colour-vision
     deficiencies; the same six in light and dark. */
  --game-1: #E69F00;
  --game-2: #56B4E9;
  --game-3: #009E73;
  --game-4: #F0E442;
  --game-5: #0072B2;
  --game-6: #CC79A7;
  /* What is drawn ON a game colour: dark in every theme, because the six are
     mid-to-light in every theme. */
  --game-ink: #1B1B1F;

  /* Medal metals (71-rewards.css): the four badge tiers, each a light, a mid
     and a deep stop for the struck-metal gradient, and one engraving ink that
     reads on all three. Fixed, not the brand's: gold must look like gold in
     every product, or a badge stops meaning "rare". */
  --medal-bronze-1: #F6C9A0;
  --medal-bronze-2: #C9824A;
  --medal-bronze-3: #8A4B22;
  --medal-silver-1: #FFFFFF;
  --medal-silver-2: #C4CAD3;
  --medal-silver-3: #7D8794;
  --medal-gold-1: #FFF1B8;
  --medal-gold-2: #F2BC2E;
  --medal-gold-3: #A86A00;
  --medal-platinum-1: #F3F0FF;
  --medal-platinum-2: #B8A8F0;
  --medal-platinum-3: #5B45B8;
  --medal-ink: #2A1A08;
  --medal-shine: rgb(255 255 255 / .75);
  --coin-1: #FFE38A;
  --coin-2: #F2B21B;
  --coin-3: #B57300;
  --flame-1: #FFE17A;
  --flame-2: #FF9F1C;
  --flame-3: #E5461F;
}

:root[data-theme="dark"] {
  --ok: #5FD898;
  --warn: #FFC46B;
  --bad: #FF8D81;
  --info: #8AB8FF;
  --rule: color-mix(in oklab, var(--ink) 12%, var(--paper-2));
  --scrim: rgb(0 0 0 / .66);
  --segment-on: color-mix(in oklab, var(--ink) 16%, var(--paper-2));
  --art-ink: #CFD0E6;
  --art-ink-2: #E3C7E3;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --ok: #5FD898;
    --warn: #FFC46B;
    --bad: #FF8D81;
    --info: #8AB8FF;
    --scrim: rgb(0 0 0 / .66);
    --segment-on: color-mix(in oklab, var(--ink) 16%, var(--paper-2));
    --art-ink: #CFD0E6;
    --art-ink-2: #E3C7E3;
  }
}
:root[data-theme="contrast"] {
  --ok: #005A24;
  --warn: #6B3F00;
  --bad: #A81208;
  --info: #0B3F8A;
  --support: #7A3E00;
  --support-edit: #7A1A00;
  --art-ink: #111111;
  --art-ink-2: #3A3A3A;
}
:root[data-theme="contrast-dark"] {
  --ok: #7FFF9F;
  --warn: #FFE066;
  --bad: #FF8D81;
  --info: #A8CBFF;
  --support: #7A3E00;
  --support-edit: #7A1A00;
  --art-ink: #F2F2F2;
  --art-ink-2: #D0D0D0;
  --art-mark-1: #C8C8C8;
  --art-mark-2: #7A7A7A;
  --art-mark-3: #3D3D3D;
}
/* High contrast: edges instead of shadows, heavier rules, no washes. */
:root[data-theme^="contrast"] {
  --rule: var(--ink);
  --rule-strong: var(--ink);
  --rule-w: 2px;
  --field: var(--paper-2);
  --field-hover: var(--paper-2);
  --wash: none;
  --accent-soft: transparent;
  --accent-wash: var(--paper-2);
  /* A drawing in high contrast is greyscale: no brand hue to lean on. */
  --art-1: #3D3D3D;
  --art-2: #C8C8C8;
  --art-3: #7A7A7A;
}
@media (prefers-contrast: more) {
  :root:not([data-theme]) {
    --rule: var(--ink);
    --rule-strong: var(--ink);
    --rule-w: 2px;
    --wash: none;
    --accent-soft: transparent;
    --art-1: #3D3D3D;
    --art-2: #C8C8C8;
    --art-3: #7A7A7A;
  }
}
@media (prefers-contrast: more) and (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --art-mark-1: #C8C8C8;
    --art-mark-2: #7A7A7A;
    --art-mark-3: #3D3D3D;
  }
}

/* The reader's own preferences, set by the display menu, stored on <html>. */
/* Text size, one of four: smaller, regular (nothing stored), larger, big. The whole rem scale follows. */
:root[data-size="small"] { font-size: calc(var(--base-size, 16px) * .9375); }
:root[data-size="large"] { font-size: calc(var(--base-size, 16px) * 1.125); }
:root[data-size="big"] { font-size: calc(var(--base-size, 16px) * 1.25); }
:root[data-density="compact"] {
  --s2: 12px;
  --s3: 16px;
  --s4: 24px;
  --card-pad: 16px;
  --gap: 12px;
  --control-h: 34px;
}
@media (pointer: coarse) {
  :root { --control-h: var(--target); }
}


/* ---- 10-base.css ---- */
/* Reset and the browser surfaces nobody draws: selection, caret, focus,
   scrollbars and figures. Themed from the palette, because a default blue
   selection on an orange product is the cheapest tell of an assembled page. */

*, *::before, *::after { box-sizing: border-box; }
/* `hidden` always wins: a component's own display must never resurrect it. */
[hidden] { display: none !important; }
html {
  font-size: var(--base-size, 16px);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scrollbar-gutter: stable;
}
body {
  margin: 0;
  min-height: 100dvh;
  /* 15px / 1.5 in the system face, the one line every screen's type comes from. */
  font: var(--t0) / var(--lh, 1.5) var(--font);
  /* §7a: a hair of tracking, near the face's own; .3px read as loose at 15px. */
  letter-spacing: .01px;
  color: var(--ink-2);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  /* §0.14: nothing overflows its box, in any language, at any width. */
  overflow-wrap: anywhere;
  word-break: normal;
  caret-color: var(--accent-ink);
  accent-color: var(--accent);
}
/* Joined scripts (Arabic and its neighbours), CJK and the Brahmic scripts break or crowd when tracked:
   i18n.js marks those languages and they keep the face's own spacing. */
:root[data-no-tracking] body { letter-spacing: normal; }
/* Icons are the exception: an icon written into a heading or a sentence stays on that line.
   As a block it pushed the words onto the line below it ("✦" over "Set up a channel with AI").
   Inside a flex or grid control the parent lays it out, so this changes nothing there. */
img, svg:not(.ci), video, canvas { display: block; max-width: 100%; }
/* A heading's lead icon: sized with the heading, a word's gap before the text. The gap is
   the margin, so markup puts no space between the icon and the words. */
:is(h1, h2, h3, h4, h5, h6) > .ci:first-child { --ci-size: 1.15em; margin-inline-end: .3em; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
:where(h1, h2, h3, h4, h5, h6) {
  margin: 0;
  color: var(--ink);
  font-weight: var(--heading-weight, 700);
  line-height: 1.2;
  text-wrap: balance;
}
h1 { font-size: var(--t4); }
h2 { font-size: var(--t2); }
h3 { font-size: var(--t1); }
h4 { font-size: var(--t0); }
p { margin: 0; text-wrap: pretty; }
:where(ul, ol) { margin: 0; padding: 0; }
table { border-collapse: collapse; }
code, kbd, samp { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: .92em; }
/* Code, keys and addresses read left to right in every language; isolated so the sentence around them keeps its own direction. */
:root[dir="rtl"] :is(code, kbd, samp, pre) { direction: ltr; unicode-bidi: isolate; }
:root[dir="rtl"] pre { text-align: left; }
/* Icons that point along the line of reading (icons.js FLIP) face the other way in RTL. */
:root[dir="rtl"] .ci-flip { scale: -1 1; }
/* What a person types, or an assistant writes back, takes its direction from its own first letter:
   a Hebrew reply in an English app reads right to left, an English one in an Arabic app left to right. */
textarea, .agent-msg, [data-user-text] { unicode-bidi: plaintext; }
:root[dir="rtl"] input:is([type="url"], [type="email"]) { direction: ltr; text-align: end; }
kbd {
  display: inline-grid;
  place-items: center;
  min-width: 1.6em;
  padding: 0 .35em;
  border: var(--rule-w) solid var(--rule-strong);
  border-bottom-width: calc(var(--rule-w) + 1px);
  border-radius: 6px;
  font-size: var(--t-2);
  line-height: 1.5;
  color: var(--ink-2);
}
.num, [data-num] { font-variant-numeric: tabular-nums; }

::selection { background: color-mix(in oklab, var(--accent-ink) 26%, transparent); color: var(--ink); }

/* One focus ring everywhere: 3 px, offset, never hidden (WCAG 2.4.7 / 2.4.11). */
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
:focus:not(:focus-visible) { outline: none; }

/* Scrollbars follow the product: thin, the rule colour, the accent on hover. */
* { scrollbar-width: thin; scrollbar-color: var(--rule-strong) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--rule-strong); border: 3px solid transparent; border-radius: 99px; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background-color: var(--ink-3); }
::-webkit-scrollbar-track { background: transparent; }

.visually-hidden, .sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.skip-link {
  position: fixed;
  z-index: 100;
  inset-block-start: var(--s1);
  inset-inline-start: var(--s1);
  padding: var(--s0) var(--s2);
  border-radius: var(--radius-pill);
  background: var(--inverse);
  color: var(--on-inverse);
  font-weight: 700;
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; }

/* §0.11: a content link shows a short line that stretches with a spring on
   hover and focus. Navigation, buttons and anything button-shaped opt out by
   not being `.link` or a bare <a> inside `.prose`. */
:is(.link, .prose a:not([class])) {
  color: var(--accent-ink);
  font-weight: 600;
  text-decoration: none;
  background: linear-gradient(currentColor, currentColor) no-repeat 0 100% / max(33%, 1.5em) 2px;
  padding-bottom: 2px;
  transition: background-size .6s var(--ease-spring);
}
:is(.link, .prose a:not([class])):is(:hover, :focus-visible) { background-size: 100% 2px; }
:root[data-theme^="contrast"] :is(.link, .prose a:not([class])) { background-size: max(33%, 1.5em) 3px; }
@media (forced-colors: active) {
  :is(.link, .prose a:not([class])) { background: none; text-decoration: underline; }
}

/* Motion off: the system setting or the display menu's switch. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
}
:root[data-motion="reduce"] *, :root[data-motion="reduce"] *::before, :root[data-motion="reduce"] *::after {
  animation-duration: .01ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: .01ms !important;
}


/* ---- 20-shell.css ---- */
/* The app shell: sidebar, top bar, content, and the phone's tab bar.

   Three shapes, one markup (docs/GUIDELINES.md §3):
   - desktop, > 1200 px: the sidebar with labels, collapsible to a rail;
   - tablet, 861–1200 px: the rail, which opens the full sidebar as a drawer;
   - phone, ≤ 860 px (dash-b's own PHONE_QUERY): a slim top bar, a bottom tab
     bar in the thumb's reach, and the sidebar as a drawer behind "More".
   The layout keys come from the setup (`layout.grid`, `layout.menuStyle`) as
   data-grid and data-menu on <html>. */

.app {
  display: grid;
  min-height: 100dvh;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  grid-template-areas: "side top" "side main";
}
/* A shell drawn by renderShell() stays hidden until it is whole, so nobody
   sees a page without its chrome and then watches it jump. start() sets
   data-ready however it ends, and boot.js sets it when start() fails or has not
   finished after 10 s, so a failed script never leaves the page blank. */
.js:not([data-ready]) .app { visibility: hidden; }

/* While it is hidden, boot.js's loader stands in the middle of the page. It
   appears only after 300 ms, so a fast load never flashes it. Without motion
   (the system's setting or the display menu's) the ring stands still and the
   word under it says the same thing. */
.boot-wait { display: none; }
.js:not([data-ready]) .boot-wait {
  position: fixed;
  inset: 0;
  z-index: 1;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--s1);
  color: var(--ink-3);
  font-size: var(--t-1);
  font-weight: 600;
  pointer-events: none;
  animation: dk-fade-in var(--dur-slow) var(--ease) 300ms both;
}
.boot-ring {
  inline-size: 36px;
  block-size: 36px;
  border: 3px solid var(--rule);
  border-block-start-color: var(--accent-ink);
  border-radius: 50%;
  animation: dk-spin .9s linear infinite;
}
@keyframes dk-fade-in { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .boot-ring { animation: none; } }
:root[data-motion="reduce"] .boot-ring { animation: none; }

/* The notice boot.js puts at the top of <main> when the page could not start. */
.boot-fail { margin-block: var(--s3); }
.boot-fail .empty { padding-block: var(--s4); }
.boot-fail h2 { font-size: var(--t2); }
body > .boot-fail { padding: var(--s6) var(--pad) 0; }
.side { grid-area: side; }
.top { grid-area: top; }
.main { grid-area: main; }

/* ---------- Sidebar ---------- */
.side {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  height: 100dvh;
  min-width: 0;
  padding: var(--s2) var(--s1);
  background: var(--frame);
  border-inline-end: var(--rule-w) solid color-mix(in oklab, var(--rule) 60%, transparent);
}
.side-head {
  display: flex;
  align-items: center;
  gap: var(--s0);
  min-height: var(--control-h);
  padding-inline: var(--s0) 0;
  margin-bottom: var(--s2);
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  margin-inline-end: auto;
  padding: 4px;
  border-radius: 12px;
  color: var(--ink);
  font-weight: 700;
  font-size: var(--t1);
  text-decoration: none;
}
.brand-mark { width: 28px; height: 28px; flex: none; }
.brand-mark svg { width: 100%; height: 100%; }
.brand-name { white-space: nowrap; overflow-wrap: normal; }

.side-nav { flex: 1; overflow-y: auto; margin-inline: calc(var(--s-1) * -1); padding-inline: var(--s-1); }
.side-nav ul { list-style: none; display: grid; gap: 2px; }
.side-heading {
  margin: var(--s3) 0 var(--s-1);
  padding-inline: var(--s1);
  font-size: var(--t-2);
  font-weight: 700;
  text-transform: uppercase;
  color: var(--ink-3);
}
/* Groups (GUIDELINES §3): a small-caps name over each, closer to its own
   pages than to the group above, so the eye reads them as sets. */
.nav-group .side-heading { margin-top: var(--s2); }
.nav-lead + .nav-group .side-heading, .side-nav > .nav-group:first-child .side-heading { margin-top: var(--s1); }
/* Grouped, a product's twelve pages and the four help doors must fit a laptop's
   height without the menu scrolling: with a mouse a row can be slimmer than the
   44 px a finger needs (WCAG 2.5.8 asks 24; 36 keeps it easy). */
@media (pointer: fine) {
  .side-nav .nav-item, .side-foot .nav-item { min-height: 36px; }
  .side-foot { gap: 0; }
}
.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s1);
  min-height: var(--control-h);
  padding: 0 var(--s1);
  border-radius: var(--radius-control);
  color: var(--ink-2);
  font-weight: 600;
  text-decoration: none;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
/* The two help doors at the foot are buttons (they open dialogs), dressed as the links above them. */
:where(button).nav-item { width: 100%; border: 0; background: none; font-family: inherit; font-size: inherit; text-align: start; cursor: pointer; }
.nav-item .ci { flex: none; --ci-size: 20px; }
.nav-item > span:not(.count) { flex: 1; min-width: 0; }
@media (hover: hover) { .nav-item:hover { background: var(--hover); color: var(--ink); } }
.nav-item[aria-current="page"] {
  background: var(--accent-soft);
  color: var(--accent-ink);
}
/* The current page is marked by more than colour (WCAG 1.4.1): a bar at the edge. */
.nav-item[aria-current="page"]::before {
  content: "";
  position: absolute;
  inset-inline-start: -4px;
  inset-block: 10px;
  width: 3px;
  border-radius: 3px;
  background: currentColor;
}
.count {
  min-width: 22px;
  padding: 0 7px;
  border-radius: var(--radius-pill);
  background: var(--field);
  color: var(--ink-2);
  font-size: var(--t-2);
  font-weight: 700;
  line-height: 20px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.nav-item[aria-current="page"] .count { background: var(--accent); color: var(--on-accent); }

.side-foot {
  display: grid;
  gap: var(--s0);
  padding-top: var(--s1);
  border-top: var(--rule-w) solid var(--rule);
}

/* The scope switcher: which site, workspace or tenant the whole screen is about. */
.scope {
  display: flex;
  align-items: center;
  gap: var(--s1);
  width: 100%;
  min-height: 48px;
  margin-bottom: var(--s2);
  padding-block: 6px;
  padding-inline: 6px var(--s1);
  border: var(--rule-w) solid var(--rule);
  border-radius: 14px;
  background: var(--paper-2);
  color: var(--ink);
  text-align: start;
}
.scope-avatar {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 10px;
  background: var(--accent-wash);
  color: var(--accent-ink);
  font-weight: 700;
}
.scope-text { display: grid; flex: 1; min-width: 0; line-height: 1.25; }
.scope-text b { font-size: var(--t0); }
.scope-text small { color: var(--ink-3); font-size: var(--t-1); }
.scope-text :is(b, small) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (hover: hover) { .scope:hover { border-color: var(--rule-strong); } }
/* In the menu, the person's role in each one sits small under its name. */
.scope-item { min-height: 44px; padding-block: 4px; }
.scope-item > span { display: grid; line-height: 1.3; overflow-wrap: anywhere; }
.scope-item small { color: var(--ink-3); font-size: var(--t-1); font-weight: 500; }

/* ---------- Top bar ---------- */
.top {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--s1);
  min-height: var(--bar-h);
  padding: var(--s1) var(--pad);
  background: color-mix(in oklab, var(--paper) 86%, transparent);
  backdrop-filter: saturate(1.4) blur(14px);
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
  transition: transform var(--dur-slow) var(--ease-out);
}
:root[data-theme^="contrast"] .top { background: var(--paper); border-bottom: var(--rule-w) solid var(--rule); }
.top-title { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--s1); }
.top-title .top-h { display: none; font-size: var(--t1); font-weight: 700; color: var(--ink); white-space: nowrap; overflow-wrap: normal; }
.top-tools { display: flex; align-items: center; gap: 4px; }

/* The search trigger reads as a field but is a button: it opens the palette. */
.search-trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--s0);
  width: min(360px, 32vw);
  min-height: var(--control-h);
  padding-block: 0;
  padding-inline: var(--s1) var(--s0);
  border: var(--rule-w) solid var(--rule);
  border-radius: var(--radius-pill);
  background: var(--paper-2);
  color: var(--ink-3);
  font-weight: 500;
}
.search-trigger > span { flex: 1; text-align: start; }
.search-trigger kbd { flex: none; }
@media (hover: hover) { .search-trigger:hover { border-color: var(--rule-strong); color: var(--ink-2); } }

/* ---------- Content ---------- */
.main {
  min-width: 0;
  padding: var(--s1) var(--pad) var(--s6);
}
.page { max-width: var(--wrap); margin-inline: auto; }
.page[data-width="full"] { max-width: none; }
.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--s2) var(--s3);
  margin: var(--s1) 0 var(--s4);
}
.page-head > :first-child { flex: 1 1 320px; min-width: 0; }
.page-lead { margin-top: var(--s0); max-width: var(--measure); color: var(--ink-2); font-size: var(--t1); }
.page-actions { display: flex; flex-wrap: wrap; gap: var(--s0); }

/* §0.17 breadcrumbs, adapted for an app: first in <main>, on the content edge. */
.crumbs ol { display: flex; flex-wrap: wrap; align-items: center; list-style: none; gap: 2px 0; font-size: var(--t-1); color: var(--ink-3); }
.crumbs li { display: inline-flex; align-items: center; }
.crumbs li + li::before { content: "/" / ""; margin-inline: 8px; color: var(--rule-strong); }
.crumbs a { color: var(--ink-3); text-decoration: none; border-radius: 6px; }
.crumbs a:hover { color: var(--ink); }
.crumbs [aria-current="page"] { color: var(--ink-2); font-weight: 600; }

/* ---------- Tab bar (phone) ---------- */
.tabbar { display: none; }

/* ---------- Scrim for the drawer ---------- */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 25;
  background: var(--scrim);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-slow) var(--ease);
}

/* ---------- Layout variants from the setup ---------- */
:root[data-grid="sidebarRight"] .app {
  grid-template-columns: minmax(0, 1fr) var(--sidebar-w);
  grid-template-areas: "top side" "main side";
}
:root[data-grid="sidebarRight"] .side { border-inline: var(--rule-w) solid color-mix(in oklab, var(--rule) 60%, transparent); border-inline-end: 0; }
:root[data-grid="bannerLeft"] .app {
  grid-template-rows: var(--bar-h) 1fr;
  grid-template-areas: "top top" "side main";
}
:root[data-grid="bannerLeft"] .side { top: var(--bar-h); height: calc(100dvh - var(--bar-h)); }
:root[data-grid="bannerLeft"] .side-head { display: none; }
:root[data-grid="bannerLeft"] .top .brand { display: inline-flex; }
.top .brand { display: none; margin-inline-end: var(--s1); }

@media (min-width: 861px) {
  :root[data-grid="topOnly"] .app {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto 1fr;
    grid-template-areas: "top" "side" "main";
  }
  :root[data-grid="topOnly"] .top .brand { display: inline-flex; }
  :root[data-grid="topOnly"] .side {
    position: static;
    height: auto;
    flex-direction: row;
    padding: 0 var(--pad) var(--s1);
    background: none;
    border: 0;
  }
  :root[data-grid="topOnly"] :is(.side-head, .side-foot, .scope, .side-heading) { display: none; }
  :root[data-grid="topOnly"] .side-nav ul { display: flex; flex-wrap: nowrap; gap: 4px; overflow-x: auto; }
  :root[data-grid="topOnly"] .side-nav { display: flex; gap: 4px; overflow-x: auto; }
  :root[data-grid="topOnly"] .nav-group ul { overflow: visible; }
  :root[data-grid="topOnly"] .nav-item { border-radius: var(--radius-pill); white-space: nowrap; overflow-wrap: normal; }
  :root[data-grid="topOnly"] .nav-item[aria-current="page"]::before { display: none; }
  :root[data-grid="topOnly"] .nav-item[aria-current="page"] { background: var(--accent); color: var(--on-accent); }
}

/* ---------- The rail: collapsed by choice, or by the tablet width ---------- */
@media (min-width: 861px) {
  :root:is([data-menu="compact"], [data-rail]):not([data-grid="topOnly"]) .app { grid-template-columns: var(--rail-w) minmax(0, 1fr); }
  :root:is([data-menu="compact"], [data-rail])[data-grid="sidebarRight"] .app { grid-template-columns: minmax(0, 1fr) var(--rail-w); }
  :root:is([data-menu="compact"], [data-rail]):not([data-grid="topOnly"]) {
    & .side { padding-inline: 10px; align-items: center; }
    & .app :is(.brand-name, .side-heading, .scope-text, .nav-item > span:not(.ci), .side-foot .label) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
    & .side-head { flex-direction: column; padding: 0; gap: var(--s1); }
    & .brand { margin: 0; }
    & .scope { width: auto; padding: 6px; border: 0; background: none; }
    & .side-nav ul { justify-items: center; }
    & .nav-item { width: var(--target); height: var(--target); padding: 0; justify-content: center; }
    & .nav-item .count { position: absolute; inset-block-start: 2px; inset-inline-end: 0; min-width: 18px; padding: 0 4px; line-height: 16px; font-size: var(--t-3); }
    & .side-foot { justify-items: center; border: 0; }
    /* The group names hide on the rail; a short rule keeps the sets apart. */
    & :is(.nav-lead, .nav-group) + .nav-group { margin-top: var(--s0); padding-top: var(--s0); border-top: var(--rule-w) solid var(--rule); }
    /* A rail item names itself on hover and focus: the label is the tooltip. */
    & .nav-item[data-tip]:is(:hover, :focus-visible)::after {
      content: attr(data-tip);
      position: absolute;
      inset-inline-start: calc(100% + 12px);
      z-index: 40;
      padding: 6px 10px;
      border-radius: 8px;
      background: var(--inverse);
      color: var(--on-inverse);
      font-size: var(--t-1);
      font-weight: 600;
      white-space: nowrap;
      box-shadow: var(--shadow-pop);
      pointer-events: none;
    }
  }
}

/* Tablet: the rail is the resting shape; the menu button opens the full sidebar over the page. */
@media (min-width: 861px) and (max-width: 1200px) {
  :root:not([data-grid="topOnly"]) .app { grid-template-columns: var(--rail-w) minmax(0, 1fr); }
  :root[data-grid="sidebarRight"] .app { grid-template-columns: minmax(0, 1fr) var(--rail-w); }
  :root:not([data-grid="topOnly"]):not([data-nav-open]) {
    & .side { padding-inline: 10px; align-items: center; }
    & .app :is(.brand-name, .side-heading, .scope-text, .nav-item > span:not(.ci), .side-foot .label) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
    & .side-head { flex-direction: column; padding: 0; gap: var(--s1); }
    & .brand { margin: 0; }
    & .scope { width: auto; padding: 6px; border: 0; background: none; }
    & .side-nav ul { justify-items: center; }
    & .nav-item { width: var(--target); height: var(--target); padding: 0; justify-content: center; }
    & .nav-item .count { position: absolute; inset-block-start: 2px; inset-inline-end: 0; min-width: 18px; padding: 0 4px; line-height: 16px; font-size: var(--t-3); }
    & .side-foot { justify-items: center; border: 0; }
    & :is(.nav-lead, .nav-group) + .nav-group { margin-top: var(--s0); padding-top: var(--s0); border-top: var(--rule-w) solid var(--rule); }
  }
  :root[data-nav-open]:not([data-grid="topOnly"]) .side {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    width: min(var(--sidebar-w), 86vw);
    box-shadow: var(--shadow-pop);
  }
  :root[data-nav-open] .scrim { opacity: 1; pointer-events: auto; }
}

/* ---------- Phone ---------- */
@media (max-width: 860px) {
  :root { --pad: 16px; --bar-h: 56px; }
  .app { grid-template-columns: minmax(0, 1fr); grid-template-areas: "top" "main"; }
  .top {
    gap: 4px;
    padding-block: var(--s0);
    padding-inline: var(--s2) var(--s0);
    padding-top: max(var(--s0), env(safe-area-inset-top));
  }
  .top .brand { display: inline-flex; margin-inline-end: 4px; padding: 2px; }
  .top .brand .brand-name { display: none; }
  .top-title .crumbs { display: none; }
  .search-trigger { width: var(--target); padding: 0; justify-content: center; border: 0; background: none; color: var(--ink-2); }
  .search-trigger > :not(.ci) { display: none; }
  :root[data-bar-away] .top { transform: translateY(-100%); }

  /* The sidebar becomes a drawer from the start edge. */
  .side {
    position: fixed;
    inset-block: 0;
    inset-inline-start: 0;
    width: min(320px, 88vw);
    height: 100dvh;
    padding-top: max(var(--s2), env(safe-area-inset-top));
    padding-bottom: max(var(--s2), env(safe-area-inset-bottom));
    box-shadow: var(--shadow-pop);
    transform: translateX(-104%);
    transition: transform var(--dur-slow) var(--ease-out), visibility 0s linear var(--dur-slow);
    visibility: hidden;
  }
  :root[dir="rtl"] .side { transform: translateX(104%); }
  :root[data-nav-open] .side { transform: none; visibility: visible; transition: transform var(--dur-slow) var(--ease-out); }
  :root[data-nav-open] .scrim { opacity: 1; pointer-events: auto; }
  .side-collapse { display: none; }

  .main { padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + var(--s5)); }
  .page-head { margin-bottom: var(--s3); }
  h1 { font-size: var(--t3); }

  /* The primary destinations sit where a thumb rests (§0.7). */
  .tabbar {
    position: fixed;
    inset-inline: 0;
    inset-block-end: 0;
    z-index: 20;
    display: grid;
    grid-template-columns: repeat(var(--tabs, 5), minmax(0, 1fr));
    padding: 6px 6px max(6px, env(safe-area-inset-bottom));
    background: color-mix(in oklab, var(--paper-2) 90%, transparent);
    backdrop-filter: saturate(1.4) blur(16px);
    -webkit-backdrop-filter: saturate(1.4) blur(16px);
    border-top: var(--rule-w) solid var(--rule);
  }
  :root[data-theme^="contrast"] .tabbar { background: var(--paper-2); }
  .tab {
    display: grid;
    justify-items: center;
    align-content: center;
    gap: 2px;
    min-height: 52px;
    padding: 4px 2px;
    border: 0;
    border-radius: 14px;
    background: none;
    color: var(--ink-3);
    font-size: var(--t-3);
    font-weight: 600;
    text-decoration: none;
    line-height: 1.2;
  }
  .tab .ci { --ci-size: 22px; }
  .tab > span { max-width: 100%; overflow-wrap: normal; white-space: nowrap; overflow: clip; text-overflow: clip; }
  .tab[aria-current="page"] { color: var(--accent-ink); }
  .tab[aria-current="page"] .ci { background: var(--accent-soft); border-radius: 999px; box-shadow: 0 0 0 6px var(--accent-soft); }
}

/* The drawer locks the page on phone and tablet only (§0.25), on <html>, so
   the sticky bar and scrollY stay exactly where they were. */
@media (max-width: 1200px) {
  :root[data-nav-open] { overflow: hidden; }
}


/* ---- 30-controls.css ---- */
/* Buttons, fields, choice controls, chips, badges, avatars.

   §0.2: every button carries exactly one icon, drawn in currentColor, that
   moves on hover and keyboard focus (castomo-icons' data-motion does the
   moving). tools/check.mjs fails a template with a bare-text button. */

/* ---------- Buttons ---------- */
.btn {
  --btn-bg: var(--paper-2);
  --btn-fg: var(--ink);
  --btn-edge: var(--rule-strong);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--control-h);
  padding: 0 18px;
  border: var(--rule-w) solid var(--btn-edge);
  border-radius: var(--radius-button, 999px);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-weight: 650;
  font-size: var(--t0);
  line-height: 1.1;
  text-decoration: none;
  white-space: nowrap;
  overflow-wrap: normal;
  user-select: none;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease-spring), box-shadow var(--dur) var(--ease);
}
.btn .ci { --ci-size: 18px; flex: none; }
.btn:has(.ci:first-child) { padding-inline-start: 14px; }
.btn:has(.ci:last-child):not(:has(.ci:first-child)) { padding-inline-end: 14px; }
@media (hover: hover) { .btn:hover { background: color-mix(in oklab, var(--btn-bg) 92%, var(--ink)); } }
.btn:active { transform: translateY(1px) scale(.985); }

.btn-primary {
  --btn-bg: var(--accent);
  --btn-fg: var(--on-accent);
  --btn-edge: var(--accent);
  box-shadow: 0 1px 0 color-mix(in oklab, var(--accent) 40%, transparent), 0 6px 16px -8px color-mix(in oklab, var(--accent) 70%, transparent);
}
@media (hover: hover) { .btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); } }
:root[data-btn2="ghost"] .btn:not(.btn-primary, .btn-danger),
.btn-ghost { --btn-bg: transparent; --btn-edge: transparent; }
:root[data-btn2="ghost"] .btn:not(.btn-primary, .btn-danger):hover,
.btn-ghost:hover { background: var(--hover); }
:root[data-btn2="filled"] .btn:not(.btn-primary, .btn-danger, .btn-ghost) { --btn-bg: var(--field); --btn-edge: transparent; }
.btn-danger { --btn-bg: var(--bad); --btn-fg: var(--paper-2); --btn-edge: var(--bad); }
:root:is([data-theme="dark"], [data-theme="contrast-dark"]) .btn-danger { --btn-fg: var(--paper); }
@media (prefers-color-scheme: dark) { :root:not([data-theme]) .btn-danger { --btn-fg: var(--paper); } }
.btn-quiet-danger { --btn-fg: var(--bad); }

.btn-sm { min-height: 32px; padding-inline: 12px; font-size: var(--t-1); gap: 6px; }
.btn-sm .ci { --ci-size: 16px; }
/* A full-width button is sized by its card, not its words: on a phone a long label wraps
   inside the pill instead of running into (or past) its rounded ends. */
.btn-block { width: 100%; padding: 10px 22px; white-space: normal; text-align: center; text-wrap: balance; }
.btn-block:has(.ci:first-child) { padding-inline-start: 18px; }
@media (pointer: coarse) { .btn-sm { min-height: var(--target); } }

/* Icon-only: a square target with an accessible name (aria-label, always). */
.icon-btn {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: var(--control-h);
  height: var(--control-h);
  flex: none;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--ink-2);
  text-decoration: none;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease-spring);
}
.icon-btn .ci { --ci-size: 20px; }
@media (hover: hover) { .icon-btn:hover { background: var(--hover); color: var(--ink); } }
.icon-btn:active { transform: scale(.94); }
.icon-btn[aria-pressed="true"], .icon-btn[aria-expanded="true"] { background: var(--press); color: var(--ink); }
.icon-btn .dot {
  position: absolute;
  inset-block-start: 8px;
  inset-inline-end: 8px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--paper);
}
/* An unread count on the bell: a number while it is small, "9+" after (notes-model.js). */
.icon-btn .count {
  position: absolute;
  inset-block-start: 3px;
  inset-inline-end: 1px;
  min-width: 18px;
  height: 18px;
  padding-inline: 5px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: 0 0 0 2px var(--paper);
  font-size: 11px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* Busy keeps its size and says so (aria-busy + a live label), never a bare spinner. */
.btn[aria-busy="true"], .agent-mic[aria-busy="true"] { pointer-events: none; }
.btn[aria-busy="true"] .ci, .agent-mic[aria-busy="true"] .ci { animation: dk-spin .8s linear infinite; }
@keyframes dk-spin { to { transform: rotate(1turn); } }
.btn:disabled, .btn[aria-disabled="true"], .icon-btn:disabled {
  cursor: not-allowed;
  opacity: .55;
  box-shadow: none;
  transform: none;
}

.btn-row { display: flex; flex-wrap: wrap; gap: var(--s0); align-items: center; }

/* ---------- Fields ---------- */
.field { display: grid; gap: 6px; min-width: 0; }
.field > label, .label {
  color: var(--ink);
  font-weight: 650;
  font-size: var(--t-1);
}
.field .optional { color: var(--ink-3); font-weight: 500; }
.hint { color: var(--ink-3); font-size: var(--t-1); }
.error-text {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  color: var(--bad);
  font-size: var(--t-1);
  font-weight: 600;
}
.error-text .ci { --ci-size: 16px; margin-top: 1px; }

.input, .select, .textarea {
  width: 100%;
  min-height: var(--control-h);
  padding: 8px 14px;
  border: var(--rule-w) solid transparent;
  border-radius: var(--radius-control);
  background: var(--field);
  color: var(--ink);
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
:root[data-input="outline"] :is(.input, .select, .textarea) { background: var(--paper-2); border-color: var(--rule-strong); }
:root[data-input="underline"] :is(.input, .select, .textarea) { background: transparent; border-radius: 0; border-width: 0 0 2px; border-color: var(--rule-strong); padding-inline: 2px; }
:root[data-theme^="contrast"] :is(.input, .select, .textarea) { border-color: var(--ink); background: var(--paper-2); }
.textarea { min-height: 112px; resize: vertical; line-height: 1.5; }
.input::placeholder, .textarea::placeholder { color: var(--ink-3); opacity: 1; }
@media (hover: hover) { :is(.input, .select, .textarea):hover { background: var(--field-hover); } }
:is(.input, .select, .textarea):focus-visible {
  outline: none;
  border-color: var(--accent-ink);
  background: var(--paper-2);
  box-shadow: 0 0 0 4px var(--accent-soft);
}
:root[data-theme^="contrast"] :is(.input, .select, .textarea):focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
:is(.input, .select, .textarea)[aria-invalid="true"] { border-color: var(--bad); }
:is(.input, .select, .textarea):disabled { opacity: .6; cursor: not-allowed; }
.select {
  appearance: none;
  padding-inline-end: 40px;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-3) 50%), linear-gradient(135deg, var(--ink-3) 50%, transparent 50%);
  background-position: calc(100% - 20px) 55%, calc(100% - 15px) 55%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

/* A field with an icon inside it (search, currency, URL). */
.input-wrap { position: relative; display: flex; align-items: center; }
.input-wrap > .ci { position: absolute; inset-inline-start: 12px; --ci-size: 18px; color: var(--ink-3); pointer-events: none; }
.input-wrap > .input { padding-inline-start: 40px; }
.input-wrap > .input-suffix { position: absolute; inset-inline-end: 12px; color: var(--ink-3); font-size: var(--t-1); }

fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
legend { padding: 0; color: var(--ink); font-weight: 700; }

/* Checkbox and radio: native, drawn larger, in the accent (accent-color on body). */
.check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-height: 28px;
  cursor: pointer;
  color: var(--ink-2);
}
.check input { width: 18px; height: 18px; margin: 2px 0 0; flex: none; cursor: pointer; }
.check b { display: block; color: var(--ink); font-weight: 650; }
@media (pointer: coarse) { .check { min-height: var(--target); align-items: center; } }

/* The switch: a checkbox with role="switch", for settings that apply at once. */
.switch {
  appearance: none;
  position: relative;
  width: 42px;
  height: 26px;
  flex: none;
  margin: 0;
  border-radius: 999px;
  background: var(--rule-strong);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease);
}
.switch::after {
  content: "";
  position: absolute;
  inset-block-start: 3px;
  inset-inline-start: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--paper-2);
  box-shadow: 0 1px 3px rgb(0 0 0 / .25);
  transition: transform var(--dur-slow) var(--ease-spring);
}
.switch:checked { background: var(--accent); }
.switch:checked::after { transform: translateX(16px); }
:root[dir="rtl"] .switch:checked::after { transform: translateX(-16px); }
:root[data-theme^="contrast"] .switch { outline: 2px solid var(--ink); outline-offset: 0; }
:root[data-theme^="contrast"] .switch::after { background: var(--ink); }
:root[data-theme^="contrast"] .switch:checked::after { background: var(--on-accent); }

/* The caret sits at the inline end, where padding-inline-end made room for it: the left in RTL. */
:root[dir="rtl"] .select { background-position: 15px 55%, 20px 55%; }

/* Segmented control: a radio group dressed as one pill (keyboard = arrows, natively). */
.segmented {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: 3px;
  border-radius: var(--radius-pill);
  background: var(--field);
  /* The ring makes the track read as one group of choices on any card, dark included;
     inset, so it adds no size. */
  box-shadow: inset 0 0 0 var(--rule-w) var(--rule);
}
.segmented label { position: relative; }
.segmented input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.segmented span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: calc(var(--control-h) - 6px);
  padding: 0 14px;
  border-radius: var(--radius-pill);
  color: var(--ink-2);
  font-weight: 600;
  font-size: var(--t-1);
  white-space: nowrap;
  overflow-wrap: normal;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
/* An unchosen segment answers the pointer, so each reads as something to press. */
.segmented input:not(:checked):hover + span { background: var(--hover); color: var(--ink); }
.segmented input:checked + span { background: var(--segment-on); color: var(--ink); box-shadow: inset 0 0 0 var(--rule-w) var(--rule-strong), 0 1px 2px rgb(0 0 0 / .08), 0 2px 8px -2px rgb(0 0 0 / .12); }
.segmented input:focus-visible + span { outline: 3px solid var(--focus); outline-offset: 1px; }
:root[data-theme^="contrast"] .segmented input:checked + span { outline: 2px solid var(--ink); }

/* A file control drawn by the kit: the native one speaks the browser's language, not the page's.
   The input stays in the label (visually hidden), so a click, a tap and the keyboard all reach it. */
.file-pick { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); min-width: 0; }
.file-pick .hint { min-width: 0; overflow-wrap: anywhere; }
.file-pick .btn:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; }

/* The drop zone component (dropzone.js): the `.dropzone` look (40-content.css), its list and live line. */
.dropzone-field { display: grid; gap: var(--s1); min-width: 0; }
.dropzone-field .dropzone { cursor: pointer; }
.dropzone-field .dropzone:hover { border-color: var(--ink-3); }
.dropzone-field .dropzone:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; }
.dropzone-label { color: var(--ink); }
.dropzone-label:empty { display: none; }
.dropzone .btn .ci { --ci-size: 16px; color: inherit; }
.dropzone-choose { pointer-events: none; }
.dropzone-list { display: grid; gap: 6px; list-style: none; }
.dropzone-file { display: flex; align-items: center; gap: var(--s1); padding-block: 6px; padding-inline: 8px 6px; border: var(--rule-w) solid var(--rule); border-radius: var(--radius-control); background: var(--paper); }
.dropzone-thumb { display: grid; place-items: center; inline-size: 40px; block-size: 40px; border-radius: 10px; background: var(--field); color: var(--ink-3); object-fit: cover; flex: none; }
.dropzone-thumb .ci { --ci-size: 20px; }
.dropzone-file-words { display: grid; min-width: 0; flex: 1; }
.dropzone-file-name { color: var(--ink); overflow-wrap: anywhere; }
.dropzone-file-size { font-size: var(--t-2); color: var(--ink-3); }
.dropzone-live:empty { display: none; }

/* ---------- Chips (filters) ---------- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding: 0 12px;
  border: var(--rule-w) solid var(--rule);
  border-radius: var(--radius-pill);
  background: var(--paper-2);
  color: var(--ink-2);
  font-weight: 600;
  font-size: var(--t-1);
  white-space: nowrap;
  overflow-wrap: normal;
}
.chip .ci { --ci-size: 16px; }
button.chip { cursor: pointer; }
@media (hover: hover) { button.chip:hover { border-color: var(--rule-strong); color: var(--ink); } }
.chip[aria-pressed="true"] { background: var(--accent-soft); border-color: transparent; color: var(--accent-ink); }
@media (pointer: coarse) { .chip { min-height: 40px; } }

/* ---------- Badges: status is a word and a shape, never colour alone ---------- */
.badge {
  --tone: var(--ink-3);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding-block: 2px;
  padding-inline: 8px 9px;
  border-radius: var(--radius-pill);
  background: color-mix(in oklab, var(--tone) 12%, transparent);
  color: color-mix(in oklab, var(--tone) 84%, var(--ink));
  font-size: var(--t-1);
  font-weight: 650;
  line-height: 1.5;
  white-space: nowrap;
  overflow-wrap: normal;
}
.badge::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--tone);
  flex: none;
}
.badge[data-tone="ok"] { --tone: var(--ok); }
.badge[data-tone="warn"] { --tone: var(--warn); }
.badge[data-tone="bad"] { --tone: var(--bad); }
.badge[data-tone="info"] { --tone: var(--info); }
.badge[data-tone="accent"] { --tone: var(--accent-ink); }
/* Warn and bad differ in shape as well as hue: a square and a diamond. */
.badge[data-tone="warn"]::before { border-radius: 2px; }
.badge[data-tone="bad"]::before { border-radius: 1px; transform: rotate(45deg) scale(.9); }
/* Sample: example content, not the person's own (GUIDELINES §6). Its shape is its own: a dashed
   outline and a hollow dot, no fill, so it reads as "not real" in greyscale and in every mode. */
.badge[data-tone="sample"] {
  --tone: var(--ink-3);
  background: transparent;
  outline: 1.5px dashed var(--tone);
  outline-offset: -1.5px;
  color: var(--ink-2);
}
.badge[data-tone="sample"]::before { background: transparent; box-shadow: inset 0 0 0 1.5px var(--tone); }
.badge[data-live]::before { animation: dk-live 1.6s var(--ease) infinite; }
@keyframes dk-live { 50% { box-shadow: 0 0 0 5px color-mix(in oklab, var(--tone) 22%, transparent); } }
:root[data-theme^="contrast"] .badge { background: transparent; outline: 2px solid currentColor; outline-offset: -2px; color: var(--ink); }
:root[data-theme^="contrast"] .badge[data-tone="sample"] { outline-style: dashed; }

.tag {
  display: inline-flex;
  align-items: center;
  padding: 1px 8px;
  border-radius: 6px;
  background: var(--field);
  color: var(--ink-2);
  font-size: var(--t-1);
  font-weight: 600;
}

/* ---------- Avatars ---------- */
.avatar {
  --size: 32px;
  display: inline-grid;
  place-items: center;
  width: var(--size);
  height: var(--size);
  flex: none;
  border-radius: 50%;
  background: color-mix(in oklab, var(--hue, var(--accent-ink)) 16%, var(--paper-2));
  color: color-mix(in oklab, var(--hue, var(--accent-ink)) 80%, var(--ink));
  font-size: calc(var(--size) * .38);
  font-weight: 700;
  line-height: 1;
  overflow: hidden;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
:root[data-theme^="contrast"] .avatar { background: var(--paper-2); color: var(--ink); box-shadow: inset 0 0 0 2px var(--ink); }
.avatar-lg { --size: 56px; }
.avatar-sm { --size: 24px; }
/* Nobody: an empty dashed circle the size of a person (the people picker's "Unassigned"). */
.avatar-none { background: transparent; border: 1.5px dashed var(--ink-3); }
:root[data-theme^="contrast"] .avatar-none { box-shadow: none; border-color: var(--ink); }
.avatars { display: flex; }
.avatars .avatar { box-shadow: 0 0 0 2px var(--paper-2); }
.avatars .avatar + .avatar { margin-inline-start: -8px; }


/* ---- 40-content.css ---- */
/* What sits on a page: cards, grids, stats, lists, tabs, alerts, meters,
   timelines, key-value facts, steps, plans, the drop zone and the save bar. */

/* ---------- Grids that are always full (§0.13) ----------
   The column count is chosen from the item count, never from the width, so
   a row never ends in a hole. `.grid` takes --cols; the breakpoints below
   halve or stack it by the same rule (6 = 3×2 → 2×3 → 1×6). */
.grid {
  display: grid;
  grid-template-columns: repeat(var(--cols, 1), minmax(0, 1fr));
  gap: var(--gap);
}
.grid > * { min-width: 0; }
.cols-2 { --cols: 2; }
.cols-3 { --cols: 3; }
.cols-4 { --cols: 4; }
.cols-6 { --cols: 6; }
/* Mixed spans on a 12-track row, for a chart beside a list (8 + 4, 7 + 5, 6 + 6). */
.split { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--gap); }
.split > * { min-width: 0; }
.span-4 { grid-column: span 4; }
.span-5 { grid-column: span 5; }
.span-6 { grid-column: span 6; }
.span-7 { grid-column: span 7; }
.span-8 { grid-column: span 8; }
.span-12 { grid-column: span 12; }
@media (max-width: 1100px) {
  .cols-4 { --cols: 2; }
  .cols-6 { --cols: 3; }
  .split > * { grid-column: span 12; }
}
@media (max-width: 860px) {
  .cols-3, .cols-6 { --cols: 2; }
  .cols-3 > :last-child:nth-child(odd) { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .cols-2, .cols-3, .cols-6 { --cols: 1; }
  .cols-3 > :last-child:nth-child(odd) { grid-column: auto; }
  /* Four numbers stay 2 × 2 on a phone: a stat tile is short enough, and one column of four is a scroll. */
}
.stack { display: grid; gap: var(--gap); }
.stack-sm { display: grid; gap: var(--s1); }
.section { margin-top: var(--s5); }
.section-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s2); margin-bottom: var(--s2); }
/* The heading keeps at least 14ch; when a control beside it cannot leave
   that much, the control drops to its own line instead of squeezing the words. */
.section-head > h2 { flex: 1 1 14ch; }
/* A heading with a badge beside it (Sample, Beta, Live): the pair takes the heading's place. */
.section-head > .section-title { flex: 1 1 14ch; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s0) var(--s1); min-width: 0; }
@media (max-width: 860px) { .hide-phone { display: none !important; } }
@media (min-width: 861px) { .only-phone { display: none !important; } }

/* ---------- Cards (the tile) ---------- */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: var(--card-pad);
  border-radius: var(--radius-card);
  background: var(--paper-2);
  box-shadow: var(--shadow);
}
/* On a phone every inset is paid twice — the page's gutter, then the card's — and a product
   nests more inside (a panel in a row, a form in the panel). 24px of card padding on top of a
   16px gutter left a third of a 375px screen as margin, so a phone's card keeps 16px, the same
   as the gutter: one even step in from the edge, and the words get the rest. */
@media (max-width: 560px) {
  /* min(): a setup that already asked for less than 16px keeps its own. */
  :root { --card-pad: min(var(--setup-card-pad, 24px), 16px); }
}
:root[data-card="outlined"] .card { box-shadow: none; border: var(--rule-w) solid var(--rule); }
:root[data-card="flat"] .card { box-shadow: none; }
:root[data-theme^="contrast"] .card { box-shadow: none; border: var(--rule-w) solid var(--ink); }
/* Below 400px even one gutter plus one card pad is two insets a side (32px of a 375px screen),
   so a page's card runs edge to edge — its own pad is then the only inset, and it lines up
   with the gutter the page's head and text keep. Not a card in a card (it sits inside the
   bled one already). A 2 × 2 stat grid (`.cols-4` stays two columns on a phone) bleeds as one
   band instead, its tiles square and a hairline apart, so the left tile's words sit at the
   same 16px as every other card's. */
@media (max-width: 400px) {
  .main .card:not(.card .card, .cols-4 > .card) {
    margin-inline: calc(-1 * var(--pad));
    border-radius: 0;
    border-inline-width: 0;
  }
  .main .cols-4:not(.card .cols-4) { margin-inline: calc(-1 * var(--pad)); gap: 2px; }
  .main .cols-4 > .card { border-radius: 0; }
}
.card-wash { background: var(--wash), var(--paper-2); }
.card-flush { padding: 0; overflow: clip; }
.card-flush > .card-head { padding: var(--card-pad) var(--card-pad) var(--s2); }
.card-flush > .card-foot { padding: var(--s1) var(--card-pad); }
.card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s0) var(--s1);
  margin-bottom: var(--s2);
}
.card-head > :first-child { flex: 1 1 auto; min-width: 0; }
.card-title { font-size: var(--t1); font-weight: 700; color: var(--ink); }
.card-sub { margin-top: 2px; color: var(--ink-3); font-size: var(--t-1); }
.card-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s1);
  margin-top: auto;
  padding-top: var(--s2);
  border-top: var(--rule-w) solid var(--rule);
  color: var(--ink-3);
  font-size: var(--t-1);
}
/* A card that is one link: the whole tile answers, the title carries the name. */
.card-link { text-decoration: none; color: inherit; transition: transform var(--dur) var(--ease-spring), box-shadow var(--dur) var(--ease); }
@media (hover: hover) { .card-link:hover { transform: translateY(-2px); box-shadow: var(--shadow-pop); } }

/* ---------- Stat tile ----------
   A number, what it counts, and how it moved. The movement is an arrow and a
   signed word as well as a colour, and "good" is decided per metric (a falling
   error rate is good news), so the tone is set by the markup, not by the sign. */
.stat { gap: var(--s1); }
.stat-label { display: flex; align-items: center; gap: 8px; color: var(--ink-2); font-weight: 600; font-size: var(--t-1); }
.stat-label .ci { --ci-size: 18px; color: var(--ink-3); }
.stat-value {
  color: var(--ink);
  font-size: var(--t4);
  font-weight: 700;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}
.stat-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; color: var(--ink-3); font-size: var(--t-1); }
.delta {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding-block: 1px;
  padding-inline: 4px 7px;
  border-radius: var(--radius-pill);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: color-mix(in oklab, var(--tone, var(--ink-3)) 12%, transparent);
  color: color-mix(in oklab, var(--tone, var(--ink-3)) 86%, var(--ink));
}
.delta .ci { --ci-size: 15px; }
.delta[data-tone="good"] { --tone: var(--ok); }
.delta[data-tone="bad"] { --tone: var(--bad); }
.stat .spark { height: 36px; margin-top: auto; }
@media (max-width: 560px) {
  .stat-value { font-size: var(--t3); }
  .stat { --card-pad: 16px; }
}

/* ---------- Key facts ---------- */
.facts { display: grid; grid-template-columns: repeat(var(--cols, 2), minmax(0, 1fr)); gap: var(--s2) var(--s3); margin: 0; }
.facts > div { min-width: 0; }
.facts dt { color: var(--ink-3); font-size: var(--t-1); font-weight: 600; }
.facts dd { margin: 2px 0 0; color: var(--ink); font-weight: 600; }
@media (max-width: 560px) { .facts { --cols: 1; } }

/* ---------- Lists ---------- */
.list { list-style: none; display: grid; }
.list > li { display: flex; align-items: center; gap: var(--s1); min-height: 56px; padding: 10px 0; border-top: var(--rule-w) solid var(--rule); min-width: 0; }
.list > li:first-child { border-top: 0; }
.list-main { flex: 1; min-width: 0; display: grid; gap: 1px; }
.list-main b { color: var(--ink); font-weight: 650; }
.list-main small { color: var(--ink-3); font-size: var(--t-1); }
.list-end { color: var(--ink-2); font-weight: 650; font-variant-numeric: tabular-nums; text-align: end; }
.list-icon { display: grid; place-items: center; width: 36px; height: 36px; flex: none; border-radius: 10px; background: var(--field); color: var(--ink-2); }
.list-icon .ci { --ci-size: 18px; }
a.list-row { color: inherit; text-decoration: none; border-radius: 12px; margin-inline: -8px; padding-inline: 8px; }
@media (hover: hover) { a.list-row:hover { background: var(--hover); } }

/* A ranked bar list: the proportion drawn behind the label, the value at the end. */
.bars { list-style: none; display: grid; gap: 6px; }
.bars li { position: relative; display: flex; justify-content: space-between; gap: var(--s1); padding: 8px 10px; border-radius: 10px; isolation: isolate; font-weight: 600; color: var(--ink); }
.bars li::before { content: ""; position: absolute; inset-block: 0; inset-inline-start: 0; z-index: -1; width: var(--w, 0%); border-radius: 10px; background: var(--accent-soft); transform-origin: left; animation: dk-grow .7s var(--ease-out) both; }
.bars li span:last-child { color: var(--ink-2); font-variant-numeric: tabular-nums; }
:root[data-theme^="contrast"] .bars li::before { background: none; border-bottom: 3px solid var(--accent); }
@keyframes dk-grow { from { transform: scaleX(0); } }

/* ---------- Tabs ---------- */
.tabs {
  display: flex;
  gap: 4px;
  margin-bottom: var(--s3);
  border-bottom: var(--rule-w) solid var(--rule);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tabs [role="tab"] {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: var(--target);
  padding: 0 14px;
  border: 0;
  background: none;
  color: var(--ink-3);
  font-weight: 650;
  white-space: nowrap;
  overflow-wrap: normal;
}
.tabs [role="tab"] .ci { --ci-size: 18px; }
.tabs [role="tab"]:hover { color: var(--ink); }
.tabs [role="tab"][aria-selected="true"] { color: var(--ink); }
.tabs [role="tab"][aria-selected="true"]::after {
  content: "";
  position: absolute;
  inset-inline: 10px;
  inset-block-end: -1px;
  height: 3px;
  border-radius: 3px 3px 0 0;
  background: var(--accent);
}
[role="tabpanel"][hidden] { display: none; }

/* ---------- Alerts: an icon, a sentence, and what to do next ---------- */
.alert {
  --tone: var(--info);
  display: flex;
  gap: var(--s1);
  align-items: flex-start;
  padding: 14px 16px;
  border-radius: 16px;
  background: color-mix(in oklab, var(--tone) 9%, var(--paper-2));
  color: var(--ink);
}
.alert > .ci { --ci-size: 20px; color: var(--tone); margin-top: 1px; flex: none; }
.alert-body { flex: 1; min-width: 0; display: grid; gap: 2px; }
.alert-body b { font-weight: 700; }
.alert-body p { color: var(--ink-2); }
.alert[data-tone="ok"] { --tone: var(--ok); }
.alert[data-tone="warn"] { --tone: var(--warn); }
.alert[data-tone="bad"] { --tone: var(--bad); }
/* An alert usually sits inside a card, so on a phone its padding and icon column are a third
   inset before the first word; it keeps its tint, which is what marks it, and gives up room. */
@media (max-width: 560px) {
  .alert { gap: 10px; padding: 12px; }
  .alert > .ci { --ci-size: 18px; }
}
:root[data-theme^="contrast"] .alert { background: var(--paper-2); outline: 2px solid var(--ink); }
/* A note about sample content ("These posts are examples until you plan your first campaign"):
   the sample badge's dashed edge and no wash, so it is never mistaken for a status. */
.alert[data-tone="sample"] { --tone: var(--ink-3); background: transparent; outline: 1.5px dashed var(--rule-strong); outline-offset: -1.5px; }
:root[data-theme^="contrast"] .alert[data-tone="sample"] { outline-style: dashed; }

/* ---------- Sample region: wraps example content a product shows before there is real data ----------
   Paired with the sample badge, and with data-sample or this class the assistant labels
   everything inside "(sample data)" (agent/snapshot.js). */
.sample-region {
  position: relative;
  padding: var(--s2);
  border: 1.5px dashed var(--rule-strong);
  border-radius: var(--radius-tile);
  min-width: 0;
}
:root[data-theme^="contrast"] .sample-region { border-color: var(--ink); }
/* The dashed frame marks what is a sample; it does not need a card's worth of room to do it.
   On a phone it sits close around the cards it frames instead of adding a third inset. */
@media (max-width: 560px) {
  .sample-region { padding: 6px; border-radius: calc(var(--radius-tile) - 4px); }
}

/* ---------- Stand-in names (stand-in.js, GUIDELINES §0.27) ----------
   "New brand", "Untitled design": what shows for a thing with no name yet. It must never read as
   a name ("Kto prowadzi markę Twoja marka"), so it is a chip, italic and dashed in the accent: an
   empty slot waiting to be filled. Never underlined — an underline is a link (§0.11). */
.name-placeholder {
  display: inline-block;
  padding: 0 .5em;
  border: 1px dashed color-mix(in oklab, var(--accent) 65%, transparent);
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--ink);
  font-style: italic;
  line-height: 1.35;
  white-space: nowrap;
}
.name-placeholder[title] { cursor: help; }
:root[data-theme^="contrast"] .name-placeholder { border-color: var(--ink); }

/* ---------- Meters: usage against a limit ---------- */
.meter { display: grid; gap: 8px; }
.meter-top { display: flex; justify-content: space-between; gap: var(--s1); font-weight: 600; color: var(--ink); }
.meter-top span:last-child { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.meter-track { height: 8px; border-radius: 99px; background: var(--field); overflow: hidden; }
.meter-fill { height: 100%; width: var(--v, 0%); border-radius: inherit; background: var(--accent); transform-origin: left; animation: dk-grow .8s var(--ease-out) both; }
/* Bars and meters grow from where they start, which is the right edge in RTL. */
:root[dir="rtl"] :is(.meter-fill, .bars li::before) { transform-origin: right; }
.meter[data-tone="warn"] .meter-fill { background: var(--warn); }
.meter[data-tone="bad"] .meter-fill { background: var(--bad); }
:root[data-theme^="contrast"] .meter-track { outline: 2px solid var(--ink); }

/* ---------- Timeline (activity, audit, incidents, deliveries) ---------- */
.timeline { list-style: none; display: grid; }
.timeline > li { position: relative; display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: var(--s1); padding-bottom: var(--s2); }
.timeline > li:not(:last-child)::before { content: ""; position: absolute; inset-inline-start: 15px; inset-block: 34px 0; width: 2px; background: var(--rule); }
.tl-dot { display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; background: var(--field); color: var(--ink-2); }
.tl-dot .ci { --ci-size: 16px; }
.tl-dot[data-tone="ok"] { background: color-mix(in oklab, var(--ok) 14%, var(--paper-2)); color: var(--ok); }
.tl-dot[data-tone="bad"] { background: color-mix(in oklab, var(--bad) 14%, var(--paper-2)); color: var(--bad); }
.tl-dot[data-tone="accent"] { background: var(--accent-soft); color: var(--accent-ink); }
.tl-body { padding-top: 5px; min-width: 0; }
.tl-body p { color: var(--ink); }
.tl-body p b { font-weight: 650; }
.tl-body time { display: block; margin-top: 2px; color: var(--ink-3); font-size: var(--t-1); }

/* ---------- Steps (onboarding, wizards) ---------- */
.steps { list-style: none; display: grid; gap: var(--s1); }
.steps > li {
  display: flex;
  gap: var(--s2);
  align-items: flex-start;
  padding: var(--s2);
  border-radius: 18px;
  background: var(--paper-2);
  box-shadow: var(--shadow);
}
/* The mark holds the step's number, or the check icon once it is done. */
.step-mark {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex: none;
  border-radius: 50%;
  background: var(--field);
  color: var(--ink-2);
  font-weight: 700;
}
.step-mark .ci { --ci-size: 18px; }
.steps > li[data-state="done"] .step-mark { background: var(--accent); color: var(--on-accent); }
.steps > li[data-state="current"] { outline: 2px solid var(--accent-ink); outline-offset: -2px; }
.steps .step-body { flex: 1; min-width: 0; display: grid; gap: 4px; }
.steps .step-body b { color: var(--ink); font-size: var(--t1); }
.steps > li[data-state="done"] .step-body b { color: var(--ink-2); text-decoration: line-through; text-decoration-color: var(--rule-strong); }
:root[data-theme^="contrast"] .steps > li { box-shadow: none; outline: 2px solid var(--ink); }

/* ---------- Plans (billing) ---------- */
.plan { gap: var(--s2); }
.plan[aria-current="true"] { outline: 2px solid var(--accent-ink); outline-offset: -2px; }
.plan-price { display: flex; align-items: baseline; gap: 6px; color: var(--ink); }
.plan-price b { font-size: var(--t5); font-weight: 700; line-height: 1; }
.plan-price span { color: var(--ink-3); }
.ticks { list-style: none; display: grid; gap: 8px; }
.ticks li { display: flex; gap: 8px; align-items: flex-start; color: var(--ink-2); }
.ticks .ci { --ci-size: 18px; color: var(--accent-ink); margin-top: 2px; flex: none; }

/* ---------- Drop zone ---------- */
.dropzone {
  display: grid;
  place-items: center;
  gap: var(--s1);
  padding: var(--s4) var(--s3);
  border: 2px dashed var(--rule-strong);
  border-radius: var(--radius-card);
  background: var(--paper-2);
  color: var(--ink-2);
  text-align: center;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.dropzone .ci { --ci-size: 32px; color: var(--accent-ink); }
.dropzone[data-over] { border-color: var(--accent-ink); background: var(--accent-wash); }

/* ---------- Secret / code value with copy ---------- */
.secret {
  display: flex;
  align-items: center;
  gap: var(--s0);
  min-height: var(--control-h);
  padding-block: 4px;
  padding-inline: 14px 4px;
  border-radius: var(--radius-control);
  background: var(--field);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: var(--t-1);
  color: var(--ink);
}
.secret code { flex: 1; min-width: 0; overflow-wrap: anywhere; direction: ltr; unicode-bidi: isolate; text-align: start; }

/* ---------- Settings layout: a section index beside the forms ---------- */
.settings { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: var(--s4); align-items: start; }
.settings-nav { position: sticky; top: calc(var(--bar-h) + var(--s2)); display: grid; gap: 2px; }
.settings-nav a { display: flex; align-items: center; gap: 10px; min-height: var(--control-h); padding: 0 12px; border-radius: var(--radius-control); color: var(--ink-2); font-weight: 600; text-decoration: none; }
.settings-nav a .ci { --ci-size: 18px; }
.settings-nav a:hover { background: var(--hover); color: var(--ink); }
.settings-nav a[aria-current="true"] { background: var(--accent-soft); color: var(--accent-ink); }
.form-card { display: grid; gap: var(--s3); }
.form-row { display: grid; grid-template-columns: repeat(var(--cols, 2), minmax(0, 1fr)); gap: var(--s2); align-items: start; }
.form-row > * { min-width: 0; }
.setting { display: flex; align-items: center; gap: var(--s2); padding: var(--s1) 0; border-top: var(--rule-w) solid var(--rule); }
.setting:first-child { border-top: 0; }
.setting > div { flex: 1; min-width: 0; }
.setting b { display: block; color: var(--ink); font-weight: 650; }
.setting small { color: var(--ink-3); font-size: var(--t-1); }
.danger-zone { box-shadow: none; border: var(--rule-w) solid color-mix(in oklab, var(--bad) 40%, var(--rule)); }
@media (max-width: 960px) {
  .settings { grid-template-columns: minmax(0, 1fr); gap: var(--s2); }
  .settings-nav { position: static; display: flex; overflow-x: auto; gap: 4px; padding-bottom: 4px; }
  .settings-nav a { white-space: nowrap; overflow-wrap: normal; border-radius: var(--radius-pill); background: var(--field); }
}
@media (max-width: 560px) { .form-row { --cols: 1; } }

/* The unsaved-changes bar: appears when a form differs from what is stored. */
.savebar {
  position: sticky;
  inset-block-end: var(--s2);
  z-index: 15;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s1) var(--s2);
  margin-top: var(--s3);
  padding-block: 10px;
  padding-inline: 18px 10px;
  border-radius: var(--radius-pill);
  background: var(--inverse);
  color: var(--on-inverse);
  box-shadow: var(--shadow-pop);
  animation: dk-rise var(--dur-slow) var(--ease-out);
}
.savebar[hidden] { display: none; }
.savebar p { flex: 1; min-width: 12ch; font-weight: 600; }
.savebar .btn:not(.btn-primary) { --btn-bg: transparent; --btn-fg: var(--on-inverse); --btn-edge: color-mix(in oklab, var(--on-inverse) 40%, transparent); }
@media (max-width: 860px) { .savebar { inset-block-end: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + var(--s1)); border-radius: 20px; } }
@keyframes dk-rise { from { transform: translateY(12px); opacity: 0; } }

/* ---------- Empty, loading and error states ----------
   An empty state teaches the next step: a picture, one sentence and the action. */
.empty {
  display: grid;
  justify-items: center;
  gap: var(--s1);
  padding: var(--s5) var(--s3);
  text-align: center;
}
.empty-art { display: grid; place-items: center; width: 72px; height: 72px; border-radius: 22px; background: var(--accent-wash); color: var(--accent-ink); margin-bottom: var(--s0); }
.empty-art .ci { --ci-size: 34px; }
.empty h3 { font-size: var(--t2); }
.empty p { max-width: 44ch; color: var(--ink-2); }
.empty .btn-row { justify-content: center; margin-top: var(--s1); }

.skeleton {
  display: block;
  height: 1em;
  border-radius: 8px;
  background: linear-gradient(90deg, var(--field) 0 40%, var(--field-hover) 50%, var(--field) 60% 100%) 0 0 / 300% 100%;
  animation: dk-shimmer 1.4s linear infinite;
}
@keyframes dk-shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }
[aria-busy="true"] > .when-loaded { display: none; }

/* ---------- Auth: one card on the wash ---------- */
.auth {
  display: grid;
  place-items: center;
  min-height: 100dvh;
  padding: var(--s3) var(--s2);
  background: radial-gradient(1200px 600px at 85% -10%, var(--accent-soft), transparent 60%), var(--wash), var(--paper);
}
/* With a drawing from the product's kit (90-art.css), the picture stands beside
   the card on a wide screen and above it, smaller, on a phone. */
.auth-stage { display: grid; gap: var(--s4); align-items: center; justify-items: center; inline-size: min(960px, 100%); }
/* A fixed track for the card and a definite size for the drawing: a percentage
   inside an auto track resolves against itself and collapses the picture. */
.auth-stage:has(> dk-art[data-on]) { grid-template-columns: minmax(0, 1fr) minmax(0, 440px); }
.auth-stage > dk-art[size] { --art-size: 400px; }
@media (max-width: 860px) {
  .auth-stage:has(> dk-art[data-on]) { grid-template-columns: 1fr; gap: var(--s2); }
  .auth-stage > dk-art[size] { --art-size: 200px; }
}
/* The way back to the product's website (GUIDELINES §0.13): its own row above the stage, at the
   start edge, so it never lands on the drawing or the card at any width. */
.auth:has(> .auth-back) { grid-template-rows: auto 1fr; }
.auth-back { justify-self: start; align-self: start; }
:dir(rtl) .auth-back .ci { scale: -1 1; }
.auth-card { width: min(440px, 100%); gap: var(--s3); padding: clamp(24px, 5vw, 40px); }
.auth-card .brand { margin: 0 0 var(--s1); }
.divider { display: flex; align-items: center; gap: var(--s1); color: var(--ink-3); font-size: var(--t-1); }
.divider::before, .divider::after { content: ""; flex: 1; height: var(--rule-w); background: var(--rule); }
.auth-foot { text-align: center; color: var(--ink-3); font-size: var(--t-1); }
/* A suspended person (kit/js/suspended.js): what still holds, as three short plain lines. */
.suspended-facts { display: grid; gap: var(--s1); margin: 0; padding: 0; list-style: none; color: var(--ink-2); }
.suspended-facts li { padding-inline-start: var(--s2); border-inline-start: var(--rule-w) solid var(--rule); }


/* ---- 45-entrance.css ---- */
/* ---------- Page entrance ----------
   When a page or a tab opens, everything on it arrives: the heading, the lead line, the page
   drawing, the actions, the tabs, every tile (outermost .card) and every block between them, each
   after its own random 0–700 ms. What is inside a tile — the bars, the coins, the charts, the
   flame — keeps its own animation and plays once its tile has half landed, so it is seen rather
   than spent behind a tile that is still clear.
   kit/js/entrance.js `enterTiles()` gives each piece its delay (--tile-delay), marks it
   (data-tile-in) and holds its contents (data-tile-hold). It runs when a page or tab OPENS, never
   when one is redrawn in place, so an update never replays the entrance.

   The reader picks the entrance in Settings > Language and display (display.js `setEntrance`,
   stamped before first paint by boot.js as data-entrance). No attribute is the default, Focus. */
:root {
  --tile-dur: 560ms;
}
/* Appear is the slow one: a full second, so its timing is its own. */
:root[data-entrance="appear"] { --tile-dur: 1000ms; }

[data-tile-in] {
  animation: dk-tile-focus var(--tile-dur) var(--ease-out) var(--tile-delay, 0ms) both;
}
:root[data-entrance="settle"] [data-tile-in] { animation-name: dk-tile-settle; }
:root[data-entrance="rise"] [data-tile-in] { animation-name: dk-tile-rise; }
:root[data-entrance="pop"] [data-tile-in] { animation-name: dk-tile-pop; animation-timing-function: var(--ease-spring); }
:root[data-entrance="appear"] [data-tile-in] { animation-name: dk-tile-appear; animation-timing-function: cubic-bezier(.25, .8, .25, 1); }
:root[data-entrance="off"] [data-tile-in] { animation: none; }

/* Focus: out of a soft blur, a short way up. */
@keyframes dk-tile-focus { from { opacity: 0; transform: translateY(8px); filter: blur(10px); } }
/* Settle: a short rise out of a slight shrink. */
@keyframes dk-tile-settle { from { opacity: 0; transform: translateY(14px) scale(.975); } }
/* Rise: a longer way up. */
@keyframes dk-tile-rise { from { opacity: 0; transform: translateY(28px); } }
/* Pop: out of a shrink, past its size and back. */
@keyframes dk-tile-pop { from { opacity: 0; transform: scale(.9); } }
/* Appear: slides up into place while it fades from nothing to whole, in a second. */
@keyframes dk-tile-appear { from { opacity: 0; transform: translateY(40px); } }

/* Paused, not delayed: a paused animation starts from its first frame when released, whatever its
   own delay and length, so nothing inside a piece needs to know about the entrance. */
[data-tile-hold] *,
[data-tile-hold] *::before,
[data-tile-hold] *::after { animation-play-state: paused !important; }

/* Motion off: no entrance at all. The kit's global rule shortens animations but keeps their
   delays, which would leave the later pieces blank for a moment and then pop them in. */
@media (prefers-reduced-motion: reduce) {
  [data-tile-in] { animation: none !important; }
}
:root[data-motion="reduce"] [data-tile-in] { animation: none !important; }


/* ---- 46-language.css ---- */
/* ---------- Settings > Language (kit/js/language-settings.js) ----------
   Rows of flag, own name, and a line of why; the current one ringed and ticked. Rows sit two or
   three across on a wide page and stack on a phone. A flag is a picture of colours, so it keeps them
   in every theme; in high contrast it gains an ink outline instead of losing its colours. */

.lang-block { display: grid; gap: var(--s1); }
.lang-block:has(> .lang-rows[hidden]:only-of-type) { display: none; }
.lang-rows {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--s0);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
}
.lang-rows[hidden] { display: none; }
.lang-row {
  display: flex; align-items: center; gap: var(--s1);
  inline-size: 100%; min-block-size: 56px; padding: var(--s0) var(--s1);
  border: var(--rule-w) solid var(--rule); border-radius: var(--radius);
  background: var(--paper-2); color: var(--ink); text-align: start; cursor: pointer;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.lang-row:hover:not(:disabled) { border-color: var(--rule-strong); box-shadow: var(--shadow-pop); }
.lang-row:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.lang-row[aria-current="true"] { border-color: var(--accent); background: var(--accent-soft); cursor: default; }
.lang-row[aria-current="true"] > .ci { --ci-size: 20px; color: var(--accent-ink); flex: none; }
.lang-row:disabled { cursor: not-allowed; }
.lang-row:disabled :is(.lang-flag, .lang-words b) { opacity: .55; }
.lang-words { display: grid; gap: 1px; flex: 1; min-inline-size: 0; }
.lang-words b { font-weight: 650; overflow-wrap: anywhere; }
.lang-words small { color: var(--ink-3); font-size: var(--t-1); }

/* The flag: 30x20, rounded, with a hairline so white fields (Japan, Poland's top) read on white.
   It waves when the row is hovered: the row's moving icon. */
.lang-flag { display: grid; place-items: center; flex: none; inline-size: 36px; block-size: 24px; }
.lang-flag .flag {
  display: block; inline-size: 30px; block-size: 20px; border-radius: 3px;
  box-shadow: 0 0 0 1px var(--rule); transform-origin: 0 50%;
}
.lang-flag .flag-fallback { font-size: var(--t-3); font-weight: 700; text-transform: uppercase; }
:root[data-theme^="contrast"] .lang-flag .flag { box-shadow: 0 0 0 2px var(--ink); }
@media (hover: hover) {
  .lang-row:hover:not(:disabled) .flag { animation: dk-flag-wave 900ms var(--ease-out); }
}
@keyframes dk-flag-wave {
  0%, 100% { transform: none; }
  25% { transform: perspective(60px) rotateY(-14deg) skewY(-3deg); }
  60% { transform: perspective(60px) rotateY(8deg) skewY(2deg); }
}
:root[data-motion="reduce"] .lang-row .flag { animation: none; }
@media (prefers-reduced-motion: reduce) { .lang-row .flag { animation: none; } }

.lang-note { margin: 0; }
.lang-toggle { justify-self: start; }
.lang-all { display: grid; gap: var(--s2); padding-block-start: var(--s1); }
.lang-all[hidden] { display: none; }
.lang-controls { display: flex; flex-wrap: wrap; align-items: end; gap: var(--s1) var(--s2); }
.lang-controls > .field { margin: 0; }
.lang-search { flex: 1 1 16rem; }
.lang-search-box { position: relative; display: block; }
.lang-search-box > .ci { position: absolute; inset-inline-start: 12px; inset-block-start: 50%; translate: 0 -50%; --ci-size: 18px; color: var(--ink-3); pointer-events: none; }
.lang-search-box > .input { inline-size: 100%; padding-inline-start: 40px; }
.lang-list { display: grid; gap: var(--s3); }
.lang-group { display: grid; gap: var(--s0); }
.lang-group-h { display: flex; align-items: center; gap: var(--s0); margin: 0; font-size: var(--t0); color: var(--ink-2); }
.lang-group-h .count { font-size: var(--t-2); color: var(--ink-3); font-variant-numeric: tabular-nums; }
.lang-empty { margin: 0; }

/* ---------- Text size: an "A" at each of the four sizes (Settings and the display menu) ---------- */
.size-choice .size-glyph { display: inline-block; min-inline-size: 1ch; font-weight: 700; line-height: 1; }
.size-glyph[data-glyph="small"] { font-size: .8em; }
.size-glyph[data-glyph="regular"] { font-size: 1em; }
.size-glyph[data-glyph="large"] { font-size: 1.2em; }
.size-glyph[data-glyph="big"] { font-size: 1.45em; }
.menu-sizes { display: flex; margin: 0 var(--s0) var(--s0); }
.menu-sizes > label { flex: 1; }
.menu-sizes span { justify-content: center; inline-size: 100%; }


/* ---- 50-table.css ---- */
/* The data table: every product has one (docs/INVENTORY.md ranks it first
   after sign-in and the shell). One markup, a real <table>, so a screen reader
   hears headers and a copy-paste lands in a spreadsheet.

   On a phone each row turns into a card: cells stack with their column name
   (from data-label, written by kit/js/table.js) beside the value. Nothing
   scrolls sideways (§0.14), and nothing is hidden that the wide view shows. */

.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s0);
  margin-bottom: var(--s2);
}
.toolbar .input-wrap { flex: 1 1 240px; max-width: 360px; }
.toolbar .spacer { flex: 1; }

.table-card { padding: 0; overflow: clip; }
.table-scroll { overflow-x: auto; }
.table { width: 100%; font-size: var(--t0); font-variant-numeric: tabular-nums; }
.table th, .table td { padding: 12px 16px; text-align: start; vertical-align: middle; }
.table th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--paper-2);
  border-bottom: var(--rule-w) solid var(--rule);
  color: var(--ink-3);
  font-size: var(--t-1);
  font-weight: 650;
  white-space: nowrap;
  overflow-wrap: normal;
}
.table td { border-bottom: var(--rule-w) solid var(--rule); color: var(--ink-2); }
.table tbody tr:last-child td { border-bottom: 0; }
.table td.strong, .table td b { color: var(--ink); font-weight: 650; }
.table .end { text-align: end; }
.table .shrink { width: 1%; white-space: nowrap; }
@media (hover: hover) { .table tbody tr:hover td { background: var(--hover); } }
.table tbody tr[aria-selected="true"] td { background: var(--accent-wash); }
.table tbody tr[data-href] { cursor: pointer; }
:root[data-density="compact"] .table :is(th, td) { padding-block: 8px; }

/* Sortable headers are buttons, and the header cell carries aria-sort. */
.th-sort {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin: -4px -6px;
  padding: 4px 6px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: inherit;
  font: inherit;
}
.th-sort .ci { --ci-size: 14px; opacity: .45; }
.th-sort:hover { color: var(--ink); }
th[aria-sort] .th-sort { color: var(--ink); }
th[aria-sort] .th-sort .ci { opacity: 1; }
th[aria-sort="descending"] .th-sort .ci { transform: scaleY(-1); }

.cell-main { display: flex; align-items: center; gap: var(--s1); min-width: 0; }
.cell-main > :not(.avatar) { display: grid; min-width: 0; line-height: 1.3; }
.cell-main b { color: var(--ink); font-weight: 650; }
.cell-main small { color: var(--ink-3); font-size: var(--t-1); }
/* The row's own link: quiet at rest (the row is the affordance), underlined on hover. */
.link-quiet { color: inherit; text-decoration: none; border-radius: 4px; }
.link-quiet:hover b { text-decoration: underline; text-underline-offset: 3px; }
.check-cell { width: 44px; padding-inline-end: 0 !important; }
.check-cell input { width: 18px; height: 18px; margin: 0; cursor: pointer; }

/* The bulk bar replaces the toolbar's meaning while rows are selected. */
.bulkbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s0) var(--s1);
  padding-block: 10px;
  padding-inline: 18px 12px;
  border-bottom: var(--rule-w) solid var(--rule);
  background: var(--accent-wash);
  color: var(--ink);
  font-weight: 650;
}
.bulkbar[hidden] { display: none; }
.bulkbar p { flex: 1; min-width: 10ch; }

.table-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s1);
  padding: var(--s1) 16px;
  border-top: var(--rule-w) solid var(--rule);
  color: var(--ink-3);
  font-size: var(--t-1);
}
.pager { display: flex; align-items: center; gap: 4px; }
.pager .icon-btn { width: 36px; height: 36px; }
.pager [aria-current="page"] { background: var(--accent-soft); color: var(--accent-ink); font-weight: 700; }
.page-num {
  display: inline-grid;
  place-items: center;
  min-width: 36px;
  height: 36px;
  padding: 0 6px;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--ink-2);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.page-num:hover { background: var(--hover); }
@media (pointer: coarse) { .pager .icon-btn, .page-num { width: var(--target); height: var(--target); } }

@media (max-width: 720px) {
  .table-scroll { overflow: visible; }
  .table, .table tbody, .table tr, .table td { display: block; width: 100%; }
  .table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .table tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 6px var(--s1);
    padding: var(--s2);
    border-bottom: var(--rule-w) solid var(--rule);
  }
  .table tbody tr:last-child { border-bottom: 0; }
  .table td { display: flex; justify-content: space-between; gap: var(--s1); padding: 0; border: 0; text-align: end; }
  .table td::before { content: attr(data-label); color: var(--ink-3); font-size: var(--t-1); font-weight: 600; text-align: start; }
  /* The row's name spans the card; its selector and actions sit in the corner. */
  .table td.cell-lead { grid-column: 1; text-align: start; margin-bottom: 4px; }
  .table td.cell-lead::before, .table td.check-cell::before, .table td.row-actions::before { content: none; }
  .table td.check-cell { grid-column: 2; grid-row: 1; width: auto; justify-content: flex-end; }
  .table td.row-actions { grid-column: 1 / -1; justify-content: flex-end; margin-top: 4px; }
  .table td.check-cell + td.cell-lead { grid-row: 1; }
  .table td:not(.cell-lead, .check-cell) { grid-column: 1 / -1; }
  .table td.end { text-align: end; }
  .table td.shrink { width: auto; }
  .table-foot { justify-content: center; }
  /* The search takes the whole row; filters follow beneath it. */
  .toolbar .input-wrap { flex: 1 1 100%; max-width: none; }
  .toolbar .spacer { display: none; }
}


/* ---- 60-overlays.css ---- */
/* Things that float: menus, dialogs, drawers, the command palette, toasts.

   All of them are native top-layer elements (<dialog>, [popover]), so they
   escape every overflow and stacking context without a portal, and Esc,
   focus return and the backdrop come from the browser. */

/* ---------- Menus and popovers ---------- */
.menu {
  min-width: 220px;
  max-width: min(340px, calc(100vw - 24px));
  max-height: min(70dvh, 520px);
  margin: 0;
  padding: 6px;
  border: var(--rule-w) solid var(--rule);
  border-radius: 16px;
  background: var(--paper-2);
  color: var(--ink-2);
  box-shadow: var(--shadow-pop);
  overflow-y: auto;
  inset: auto;
  opacity: 0;
  transform: translateY(-4px) scale(.98);
  transform-origin: top right;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease-out), overlay var(--dur) allow-discrete, display var(--dur) allow-discrete;
}
.menu:popover-open { opacity: 1; transform: none; }
/* A menu opens from the trigger's end edge (overlays.js placeNear), which is the left one in RTL. */
:root[dir="rtl"] .menu { transform-origin: top left; }
@starting-style { .menu:popover-open { opacity: 0; transform: translateY(-4px) scale(.98); } }
:root[data-theme^="contrast"] .menu { border: 2px solid var(--ink); }
.menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 40px;
  padding: 0 12px;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--ink-2);
  font-weight: 600;
  text-align: start;
  text-decoration: none;
}
.menu-item .ci { --ci-size: 18px; color: var(--ink-3); }
.menu-item > span { flex: 1; min-width: 0; }
.menu-item:is(:hover, :focus-visible) { background: var(--hover); color: var(--ink); outline: none; }
.menu-item:focus-visible { box-shadow: inset 0 0 0 2px var(--focus); }
.menu-item[aria-checked="true"] { color: var(--accent-ink); }
.menu-item[aria-checked="true"] .ci { color: var(--accent-ink); }
.menu-item.danger { color: var(--bad); }
.menu-item.danger .ci { color: var(--bad); }
.menu-sep { height: var(--rule-w); margin: 6px 4px; background: var(--rule); border: 0; }
.menu-label { padding: 8px 12px 4px; color: var(--ink-3); font-size: var(--t-2); font-weight: 700; text-transform: uppercase; }
.menu-head { display: flex; align-items: center; gap: var(--s1); padding: 10px 12px 12px; }
.menu-head > div { display: grid; min-width: 0; line-height: 1.3; }
.menu-head b { color: var(--ink); }
.menu-head small { color: var(--ink-3); font-size: var(--t-1); }
@media (pointer: coarse) { .menu-item { min-height: var(--target); } }

/* The castomo apps grid: every product one tap away, as on castomo.com's shelves. */
.apps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px; width: 336px; max-width: 100%; padding: 4px; }
.app-tile { display: grid; justify-items: center; gap: 6px; padding: 12px 6px; border-radius: 14px; color: var(--ink-2); font-size: var(--t-1); font-weight: 600; text-align: center; text-decoration: none; }
.app-tile svg { width: 32px; height: 32px; }
.app-tile:is(:hover, :focus-visible) { background: var(--hover); color: var(--ink); }
.app-tile[aria-current="true"] { background: var(--accent-soft); color: var(--accent-ink); }

/* ---------- Dialog ---------- */
.dialog {
  width: min(520px, calc(100vw - 32px));
  max-height: calc(100dvh - 48px);
  padding: 0;
  border: 0;
  border-radius: var(--radius-tile);
  background: var(--paper-2);
  color: var(--ink-2);
  box-shadow: var(--shadow-pop);
  overflow: hidden;
  opacity: 0;
  transform: translateY(8px) scale(.98);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease-out), overlay var(--dur-slow) allow-discrete, display var(--dur-slow) allow-discrete;
}
.dialog[open] { opacity: 1; transform: none; }
@starting-style { .dialog[open] { opacity: 0; transform: translateY(8px) scale(.98); } }
.dialog::backdrop { background: var(--scrim); backdrop-filter: blur(3px); opacity: 0; transition: opacity var(--dur-slow) var(--ease), overlay var(--dur-slow) allow-discrete, display var(--dur-slow) allow-discrete; }
.dialog[open]::backdrop { opacity: 1; }
@starting-style { .dialog[open]::backdrop { opacity: 0; } }
:root[data-theme^="contrast"] :is(.dialog, .drawer) { border: 2px solid var(--ink); }
.dialog-form { display: flex; flex-direction: column; max-height: inherit; }
.dialog-head { display: flex; align-items: flex-start; gap: var(--s1); padding-block: 22px 6px; padding-inline: 24px 22px; }
.dialog-head > div { flex: 1; min-width: 0; display: grid; gap: 4px; }
.dialog-head h2 { font-size: var(--t2); }
.dialog-head p { color: var(--ink-2); }
.dialog-body { display: grid; gap: var(--s2); padding: var(--s2) 24px; overflow-y: auto; }
.dialog-foot { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s0); padding: var(--s2) 24px 24px; }
.dialog-art { display: grid; place-items: center; width: 48px; height: 48px; border-radius: 16px; background: color-mix(in oklab, var(--bad) 12%, var(--paper-2)); color: var(--bad); flex: none; }
.dialog-art .ci { --ci-size: 24px; }

/* ---------- The design dialog's library (design-library.js) ---------- */
.design-lib { display: grid; gap: var(--s1); }
.design-lib-group { display: grid; gap: 6px; }
.design-lib-group + .design-lib-group { margin-block-start: var(--s1); }
.design-lib-heading { font-size: var(--t-1); color: var(--ink-3); font-weight: 600; }
.design-lib-list { display: grid; gap: 6px; list-style: none; }
.design-lib-skeleton { display: grid; gap: 8px; }
.design-lib-skeleton .skeleton { height: 52px; border-radius: var(--radius-control); }
.design-lib-empty, .design-lib-problem { display: grid; gap: var(--s1); justify-items: start; padding: var(--s2); border: var(--rule-w) dashed var(--rule-strong); border-radius: var(--radius-control); color: var(--ink-2); }
.design-lib-search .input { inline-size: 100%; }
/* A card is one button: the swatch, the name and what it is, and where it stands. */
.design-card {
  display: flex; align-items: center; gap: var(--s1);
  inline-size: 100%; min-block-size: 52px;
  padding: 8px 12px;
  border: var(--rule-w) solid var(--rule); border-radius: var(--radius-control);
  background: var(--paper); color: var(--ink-2); text-align: start;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.design-card:hover { border-color: var(--rule-strong); background: var(--field-hover); }
.design-card[aria-current="true"] { border-color: var(--accent); }
.design-card[aria-busy="true"] { cursor: progress; }
.design-card[aria-busy="true"] > .ci { animation: dk-spin .8s linear infinite; }
.design-card > .ci { --ci-size: 18px; color: var(--ink-3); margin-inline-start: auto; }
.design-card > .badge { margin-inline-start: auto; flex: none; }
.design-card-words { display: grid; min-inline-size: 0; }
.design-card-name { color: var(--ink); font-weight: 600; overflow-wrap: anywhere; }
.design-card-meta { font-size: var(--t-2); color: var(--ink-3); }
/* Three overlapping discs in the design's own colours; the ring keeps a white disc on white visible. */
.design-swatch { display: flex; flex: none; }
.design-swatch i { inline-size: 22px; block-size: 22px; border-radius: 50%; background: var(--sw); box-shadow: 0 0 0 2px var(--paper), inset 0 0 0 1px var(--rule-strong); }
.design-swatch i + i { margin-inline-start: -7px; }
.design-swatch.is-blank { inline-size: 58px; block-size: 22px; border-radius: 999px; border: var(--rule-w) dashed var(--rule-strong); }
/* "Or bring an exported file": a rule with the words across it. */
.design-or { display: flex; align-items: center; gap: var(--s1); font-size: var(--t-1); color: var(--ink-3); }
.design-or::before, .design-or::after { content: ""; flex: 1; border-block-start: var(--rule-w) solid var(--rule); }

/* ---------- Drawer (detail panel), a bottom sheet on the phone ---------- */
.drawer {
  position: fixed;
  inset-block: 0;
  inset-inline: auto 0;
  width: min(520px, 100vw);
  height: 100dvh;
  max-width: 100vw;
  max-height: 100dvh;
  margin: 0;
  padding: 0;
  border: 0;
  --slide: 100%;
  border-radius: 0;
  border-start-start-radius: var(--radius-tile);
  border-end-start-radius: var(--radius-tile);
  background: var(--paper-2);
  color: var(--ink-2);
  box-shadow: var(--shadow-pop);
  transform: translateX(var(--slide));
  transition: transform var(--dur-slow) var(--ease-out), overlay var(--dur-slow) allow-discrete, display var(--dur-slow) allow-discrete;
}
.drawer[open] { transform: none; }
@starting-style { .drawer[open] { transform: translateX(var(--slide)); } }
.drawer::backdrop { background: var(--scrim); opacity: 0; transition: opacity var(--dur-slow) var(--ease), overlay var(--dur-slow) allow-discrete, display var(--dur-slow) allow-discrete; }
.drawer[open]::backdrop { opacity: 1; }
@starting-style { .drawer[open]::backdrop { opacity: 0; } }
.drawer .dialog-form { height: 100%; }
.drawer .dialog-body { flex: 1; align-content: start; }
.drawer .dialog-foot { border-top: var(--rule-w) solid var(--rule); padding-top: var(--s2); }
:root[dir="rtl"] .drawer { --slide: -100%; }
@media (max-width: 640px) {
  .drawer {
    inset: auto 0 0;
    width: 100vw;
    height: auto;
    max-height: 92dvh;
    border-radius: 24px 24px 0 0;
    transform: translateY(100%);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .drawer[open] { transform: none; }
  @starting-style { .drawer[open] { transform: translateY(100%); } }
  /* A grabber says "this slides" without being the only way to close it. */
  .drawer .dialog-form::before { content: ""; align-self: center; width: 40px; height: 5px; margin-top: 8px; border-radius: 3px; background: var(--rule-strong); }
  .dialog { width: calc(100vw - 16px); margin-block: auto 8px; border-radius: 24px; }
}

/* ---------- Command palette ---------- */
.palette {
  width: min(640px, calc(100vw - 24px));
  max-height: min(560px, calc(100dvh - 96px));
  margin-top: 12vh;
  padding: 0;
  border: 0;
  border-radius: 20px;
  background: var(--paper-2);
  color: var(--ink-2);
  box-shadow: var(--shadow-pop);
  overflow: hidden;
}
.palette::backdrop { background: var(--scrim); backdrop-filter: blur(2px); }
.palette[open] { display: flex; flex-direction: column; }
.palette-search { display: flex; align-items: center; gap: 10px; padding: 0 16px; border-bottom: var(--rule-w) solid var(--rule); }
.palette-search .ci { --ci-size: 20px; color: var(--ink-3); }
.palette-search input { flex: 1; min-height: 58px; border: 0; background: none; color: var(--ink); font-size: var(--t1); outline: none; }
.palette-list { flex: 1; overflow-y: auto; padding: 6px; list-style: none; }
.palette-group { padding: 10px 12px 4px; color: var(--ink-3); font-size: var(--t-2); font-weight: 700; text-transform: uppercase; }
.palette-opt { display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 0 12px; border-radius: 12px; color: var(--ink-2); font-weight: 600; cursor: pointer; }
.palette-opt .ci { --ci-size: 18px; color: var(--ink-3); }
.palette-opt > span { flex: 1; min-width: 0; }
.palette-opt small { color: var(--ink-3); font-weight: 500; }
.palette-opt[aria-selected="true"] { background: var(--accent-soft); color: var(--accent-ink); }
.palette-opt[aria-selected="true"] .ci { color: var(--accent-ink); }
.palette-foot { display: flex; flex-wrap: wrap; gap: var(--s2); padding: 10px 16px; border-top: var(--rule-w) solid var(--rule); color: var(--ink-3); font-size: var(--t-1); }
.palette-empty { padding: var(--s4) var(--s2); color: var(--ink-3); text-align: center; }
@media (max-width: 640px) { .palette { margin-top: 8px; max-height: calc(100dvh - 16px); } }

/* ---------- Toasts ---------- */
.toasts {
  position: fixed;
  inset-block-end: var(--s3);
  inset-inline-end: var(--s3);
  z-index: 60;
  display: grid;
  gap: var(--s0);
  width: min(380px, calc(100vw - 32px));
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--s1);
  padding-block: 12px;
  padding-inline: 16px 8px;
  border-radius: 16px;
  background: var(--inverse);
  color: var(--on-inverse);
  box-shadow: var(--shadow-pop);
  pointer-events: auto;
  animation: dk-rise var(--dur-slow) var(--ease-out);
}
.toast > .ci { --ci-size: 20px; margin-top: 1px; flex: none; }
.toast[data-tone="ok"] > .ci { color: color-mix(in oklab, var(--ok) 60%, var(--on-inverse)); }
.toast[data-tone="bad"] > .ci { color: color-mix(in oklab, var(--bad) 60%, var(--on-inverse)); }
.toast p { flex: 1; min-width: 0; font-weight: 600; padding-top: 1px; }
.toast .toast-action { border: 0; background: none; color: inherit; font-weight: 700; text-decoration: underline; text-underline-offset: 3px; padding: 2px 6px; border-radius: 6px; }
.toast .icon-btn { width: 32px; height: 32px; color: inherit; }
.toast[data-leaving] { opacity: 0; transform: translateY(8px); transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease); }
@media (max-width: 860px) {
  .toasts { inset-inline: 16px; inset-block-end: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 12px); width: auto; }
}

/* The language choice in the display menu: a native select, so a long list scrolls and types-to-find. */
.menu-lang { gap: var(--s1); }
.menu-lang .select { flex: 1; min-width: 0; min-height: 36px; }

/* The bell's list (nav.js updateNotifications). Wider than a menu, because an
   entry is a sentence and its when, not a one-word command. */
.menu.notes { width: min(380px, calc(100vw - 24px)); max-width: none; }
.notes-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s1); padding-inline-end: 4px; }
.notes-list { display: grid; gap: 2px; }
.menu-item.note { position: relative; align-items: flex-start; padding-block: 10px; padding-inline-end: 28px; font-weight: 400; }
.menu-item.note .ci { margin-block-start: 2px; }
.note-title { display: block; color: var(--ink); font-weight: 600; overflow-wrap: anywhere; }
.note-body { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; color: var(--ink-2); overflow-wrap: anywhere; }
.note-when { display: block; color: var(--ink-3); font-size: var(--t-1); }
.menu-item.note.is-unread { background: var(--accent-soft); }
.note-dot { position: absolute; inset-block-start: 16px; inset-inline-end: 12px; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
.notes-empty { margin: 0; padding: 12px 12px 16px; color: var(--ink-3); }


/* ---- 64-tooltip.css ---- */
/* Tooltips (kit/js/tooltip.js): one element in the top layer, placed by the
   script above or below the control it explains. The name in bold, the
   sentence under it. An arrow points at the control from whichever side the
   tooltip landed on. */

.tooltip {
  position: fixed;
  inset: auto;
  margin: 0;
  z-index: 1000;
  display: grid;
  gap: 2px;
  max-inline-size: min(18rem, calc(100vw - 16px));
  padding: 8px 11px;
  border: 0;
  border-radius: 10px;
  background: var(--inverse);
  color: var(--on-inverse);
  font-size: var(--t-1);
  line-height: 1.4;
  box-shadow: var(--shadow-pop);
  pointer-events: none;
  opacity: 0;
  transform: translateY(3px) scale(.98);
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease-out);
}
.tooltip[hidden] { display: none; }
.tooltip[data-side="bottom"] { transform: translateY(-3px) scale(.98); }
.tooltip[data-open] { opacity: 1; transform: none; }
.tooltip b { font-weight: 700; }
.tooltip span { color: color-mix(in oklab, var(--on-inverse) 84%, transparent); }
.tooltip::after {
  content: "";
  position: absolute;
  inset-inline-start: calc(var(--arrow, 50%) - 5px);
  inline-size: 10px;
  block-size: 10px;
  background: inherit;
  rotate: 45deg;
  border-radius: 2px;
}
.tooltip[data-side="top"]::after { inset-block-end: -4px; }
.tooltip[data-side="bottom"]::after { inset-block-start: -4px; }
/* The arrow is measured from the physical left (the script works in client coordinates). */
:root[dir="rtl"] .tooltip::after { inset-inline-start: auto; left: calc(var(--arrow, 50%) - 5px); }
:root[data-theme^="contrast"] .tooltip { outline: 2px solid var(--on-inverse); }

:root[data-motion="reduce"] .tooltip { transition: none; transform: none; }
@media (prefers-reduced-motion: reduce) { .tooltip { transition: none; transform: none; } }


/* ---- 65-support.css ---- */
/* The two help dialogs at the foot of the sidebar: Report a bug, and Help and
   contact (kit/js/support.js). Everything else they wear is the kit's own
   dialog, field and segmented control. */

.support .dialog-art { background: var(--accent-soft); color: var(--accent-ink); }
.support .segmented { width: fit-content; max-width: 100%; }
.support fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }
.support legend { padding: 0; margin-bottom: 6px; }
.support .textarea { min-height: 120px; }

.support-details { display: grid; gap: var(--s0); }
.support-details .check span { display: grid; gap: 2px; color: var(--ink-3); font-size: var(--t-1); }
.support-details .check b { font-size: var(--t0); }
.support-details summary { width: fit-content; color: var(--accent-ink); font-size: var(--t-1); font-weight: 650; cursor: pointer; padding-inline-start: 30px; }
.support-preview {
  max-height: 180px;
  margin-top: var(--s0);
  padding: var(--s1);
  border-radius: 12px;
  background: var(--field);
  color: var(--ink-2);
  font: 500 var(--t-2)/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  overflow-y: auto;
}

.support-fallback .support-ways { display: flex; flex-wrap: wrap; gap: var(--s0); margin-top: 6px; }

/* The assistant, offered first: the fastest answer is the one that does not wait for a reply. */
.support-ai {
  display: flex;
  align-items: center;
  gap: var(--s1);
  padding-block: var(--s1);
  padding-inline: var(--s2) var(--s1);
  border-radius: 16px;
  background: var(--accent-wash);
  border: var(--rule-w) solid color-mix(in oklab, var(--accent-ink) 18%, transparent);
}
.support-ai > div { flex: 1; min-width: 0; display: grid; gap: 2px; }
.support-ai b { color: var(--ink); }
.support-ai small { color: var(--ink-2); font-size: var(--t-1); }
.support-ai-mark { display: grid; place-items: center; width: 36px; height: 36px; flex: none; border-radius: 12px; background: var(--accent); color: var(--on-accent); }
.support-ai-mark .ci { --ci-size: 20px; }

/* The direct address sits at the start of the button row and wraps above it when space runs out. */
.support .dialog-foot { align-items: center; }
.support-direct { flex: 1 1 100%; color: var(--ink-3); font-size: var(--t-1); }
@media (min-width: 641px) { .support-direct { flex: 1 1 auto; } }

/* Phone: the choices become a two-column grid (a wrapped pill reads as a blob),
   an odd last choice spans the row so no cell is left empty (§0.13), and the
   assistant card puts its button under the words. */
@media (max-width: 480px) {
  .support .segmented { display: grid; grid-template-columns: 1fr 1fr; width: 100%; border-radius: 16px; }
  .support .segmented label:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .support .segmented span { justify-content: center; width: 100%; border-radius: 13px; }
  .support-ai { flex-wrap: wrap; }
  .support-ai > .btn { flex: 1 1 100%; }
}


/* ---- 66-handbook.css ---- */
/* The handbook (kit/js/handbook.js): the product's help articles in a drawer
   beside the work, its search field in Help and contact, and the small
   "Learn how this works" hint a screen can put under a heading. Everything
   else it wears is the kit's own drawer, field, chip and alert. */

.handbook .dialog-art { background: var(--accent-soft); color: var(--accent-ink); }
.handbook-search { padding: var(--s1) 24px var(--s0); }
.handbook-search .input::-webkit-search-cancel-button { cursor: pointer; }
.handbook-body { gap: var(--s2); }
.handbook-heading { color: var(--ink); font-size: var(--t0); }
.handbook-empty { padding: var(--s2) 0; color: var(--ink-3); overflow-wrap: anywhere; }

/* Every article as a chip. A long title wraps inside its chip rather than pushing the sheet sideways. */
.handbook-chips { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s0); }
.handbook-chips li { max-width: 100%; }
.handbook-chips .chip { max-width: 100%; min-height: 36px; padding-block: 6px; white-space: normal; text-align: start; overflow-wrap: anywhere; }
@media (pointer: coarse) { .handbook-chips .chip { min-height: var(--target); } }

/* Search results: the title, and the lede to tell two near titles apart. */
.handbook-results { list-style: none; display: grid; gap: 2px; }
.handbook-result {
  display: flex;
  align-items: flex-start;
  gap: var(--s1);
  width: 100%;
  min-height: var(--target);
  padding: 10px 12px;
  border: 0;
  border-radius: 12px;
  background: none;
  color: var(--ink-2);
  text-align: start;
}
.handbook-result .ci { --ci-size: 18px; margin-top: 2px; color: var(--ink-3); flex: none; }
.handbook-result > span { display: grid; gap: 2px; min-width: 0; }
.handbook-result b { color: var(--ink); font-weight: 650; }
.handbook-result small { color: var(--ink-3); font-size: var(--t-1); }
.handbook-result:is(:hover, :focus-visible) { background: var(--hover); outline: none; }
.handbook-result:focus-visible { box-shadow: inset 0 0 0 2px var(--focus); }
:root[data-theme^="contrast"] .handbook-result:focus-visible { outline: 3px solid var(--focus); }

/* One article. The title takes focus when it opens (so a screen reader starts
   reading there); a heading is a reading position, not a control, so no ring. */
/* Back wears a light fill so it reads as a button whose edge lines up with the article,
   not a bare label floating a few pixels inside the column. */
.handbook-back { justify-self: start; --btn-bg: var(--field); }
.handbook-back:hover { background: var(--hover); }
.handbook-article { display: grid; gap: var(--s1); min-width: 0; max-width: var(--measure); overflow-wrap: anywhere; }
/* The article's picture sits on a soft band above the title, the way a page's drawing sits on
   its head. The band collapses with the picture when the page has no kit (dk-art hides itself). */
.handbook-art { display: grid; place-items: center; padding-block: var(--s1); border-radius: var(--radius-tile); background: var(--field); }
.handbook-art:not(:has(dk-art[data-on])) { display: none; }
.handbook-art dk-art { --art-size: min(100%, 176px); }
.handbook-article > h3 { color: var(--ink); font-size: var(--t3); }
.handbook-article > h3:focus { outline: none; }
.handbook-lede { color: var(--ink-2); font-size: var(--t1); }
.handbook-article h4 { margin-top: var(--s1); color: var(--ink); font-size: var(--t1); }
.handbook-article p { color: var(--ink-2); }
.handbook-list { display: grid; gap: 4px; padding-inline-start: 1.3em; color: var(--ink-2); }
.handbook-note { margin-block: 4px; }

/* Steps are numbered in a disc, the way every castomo site numbers steps. */
.handbook-steps { list-style: none; display: grid; gap: var(--s0); counter-reset: dk-step; color: var(--ink-2); }
.handbook-steps > li { counter-increment: dk-step; display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 10px; align-items: start; }
.handbook-steps > li::before {
  content: counter(dk-step);
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-size: var(--t-1);
  font-weight: 700;
}
:root[data-theme^="contrast"] .handbook-steps > li::before { background: var(--paper-2); box-shadow: inset 0 0 0 2px var(--ink); color: var(--ink); }

.handbook-related { display: grid; gap: var(--s1); padding-top: var(--s2); border-top: var(--rule-w) solid var(--rule); }
.handbook-related h4 { color: var(--ink); font-size: var(--t0); }

/* The hint: a quiet link-button under a heading. Small, but still a 44 px target under a finger. */
.handbook-hint {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding: 0 6px;
  margin-inline-start: -6px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--accent-ink);
  font-size: var(--t-1);
  font-weight: 650;
  text-align: start;
}
.handbook-hint .ci { --ci-size: 16px; flex: none; }
.handbook-hint span { text-decoration: underline; text-decoration-color: color-mix(in oklab, currentColor 35%, transparent); text-underline-offset: 3px; }
@media (hover: hover) { .handbook-hint:hover span { text-decoration-color: currentColor; } }
.handbook-hint:focus-visible { outline: 3px solid var(--focus); outline-offset: 1px; }
@media (pointer: coarse) { .handbook-hint { min-height: var(--target); } }

/* "Search the handbook" at the top of Help and contact: the answer that needs nobody to reply. */
.support-handbook { display: grid; gap: 6px; }
.support-handbook-hits { list-style: none; display: grid; gap: var(--s0); }
.support-handbook-hits:empty { display: none; }
.support-handbook-hits li { display: grid; gap: 1px; min-width: 0; overflow-wrap: anywhere; }
.support-handbook-hits small { color: var(--ink-3); font-size: var(--t-1); }
.support-handbook-hits .link { justify-self: start; font-weight: 650; }


/* ---- 67-welcome.css ---- */
/* ---------- Welcome tour (kit/js/welcome.js) ----------
   A greeting, not a form: a big card over the app on a desktop, the whole
   screen on a phone. Each scene is a stage (the kit drawing on a soft disc,
   circled by animated icons, flanked by moving doodles) beside its words.
   Motion tells the story once — the stage rises, the headline's swash draws
   itself, the drawing blooms from brand tones into its own colours — and then
   only the small things keep moving. Under reduced motion nothing moves. */

.welcome {
  --dir: 1;
  width: min(1080px, calc(100vw - 48px));
  max-width: none;
  height: min(680px, calc(100dvh - 48px));
  max-height: none;
  padding: 0;
  border: 0;
  border-radius: var(--radius-tile);
  background: var(--paper-2);
  color: var(--ink-2);
  box-shadow: var(--shadow-pop);
  overflow: hidden;
  opacity: 0;
  transform: translateY(16px) scale(.97);
  transition: opacity var(--dur-slow) var(--ease), transform 480ms var(--ease-out), overlay var(--dur-slow) allow-discrete, display var(--dur-slow) allow-discrete;
}
.welcome[open] { opacity: 1; transform: none; }
@starting-style { .welcome[open] { opacity: 0; transform: translateY(16px) scale(.97); } }
.welcome::backdrop {
  background: var(--scrim);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 420ms var(--ease), overlay 420ms allow-discrete, display 420ms allow-discrete;
}
.welcome[open]::backdrop { opacity: 1; }
@starting-style { .welcome[open]::backdrop { opacity: 0; } }
:root[data-theme^="contrast"] .welcome { border: 2px solid var(--ink); }

.welcome-frame {
  position: relative;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  height: 100%;
  /* A wash of the accent behind the stage half, so the card reads as the product's from across the room. */
  background:
    radial-gradient(60% 70% at 24% 46%, var(--accent-soft), transparent 70%),
    var(--paper-2);
}
.welcome-close { position: absolute; inset-block-start: var(--s1); inset-inline-end: var(--s1); z-index: 3; }

/* Every scene sits in the same grid cell; only the current one is shown. */
.welcome-scenes { display: grid; min-height: 0; touch-action: pan-y; }
.welcome-scene {
  grid-area: 1 / 1;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  align-items: center;
  gap: var(--s4);
  min-height: 0;
  padding: var(--s5) var(--s5) var(--s2);
  visibility: hidden;
  opacity: 0;
  transition: opacity 360ms var(--ease), visibility 0s linear 360ms;
}
.welcome-scene[data-state="current"] { visibility: visible; opacity: 1; transition: opacity 420ms var(--ease) 80ms, visibility 0s; }

/* ---------- The stage ---------- */
.welcome-stage {
  position: relative;
  display: grid;
  place-items: center;
  justify-self: center;
  inline-size: min(100%, 440px);
  aspect-ratio: 1;
  /* The orbit's radius and the doodles' sizes are fractions of the stage (cqi). */
  container-type: inline-size;
}
.welcome-stage > * { grid-area: 1 / 1; }
.welcome-disc {
  inline-size: 86%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--accent-soft);
  transform: scale(.55);
  opacity: 0;
  transition: transform 900ms var(--ease-spring), opacity 400ms var(--ease);
}
.welcome-scene[data-state="current"] .welcome-disc { transform: none; opacity: 1; }

/* The kit drawing: its own disc gives way to the stage's, and it rises in with the scene. */
.welcome .welcome-stage dk-art { --art-size: 88%; z-index: 1; transform: translateY(18px) scale(.9) rotate(calc(var(--dir) * var(--rtl, 1) * -3deg)); opacity: 0; transition: transform 900ms var(--ease-out) 120ms, opacity 500ms var(--ease) 120ms; }
.welcome-stage dk-art::before { content: none; }
.welcome .welcome-scene[data-state="current"] .welcome-stage dk-art { transform: none; opacity: 1; }
/* Toned while it settles, then the colour arrives: the drawing "comes alive". */
.welcome-scene[data-bloom] dk-art { --hipster-tone: 0; }

/* Without a kit the big doodle is the drawing. */
.welcome-doodle { z-index: 1; display: grid; place-items: center; inline-size: 100%; color: var(--accent-ink); }
.welcome-doodle .ci.ci-big { width: 58%; --ci-stroke: 2.4; }
dk-art[data-on] + .welcome-doodle { display: none; }

/* The orbit: a dashed ring turning slowly, three animated icons riding it upright. */
.welcome-orbit {
  z-index: 2;
  inline-size: 100%;
  aspect-ratio: 1;
  border-radius: 50%;
  border: var(--rule-w) dashed var(--rule-strong);
  animation: welcome-orbit 48s linear infinite;
  opacity: 0;
  transition: opacity 600ms var(--ease) 350ms;
  pointer-events: none;
}
.welcome-scene[data-state="current"] .welcome-orbit { opacity: 1; }
.welcome-sat {
  --angle: calc(360deg / var(--n) * var(--k) - 60deg);
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: 52px;
  aspect-ratio: 1;
  margin: -26px;
  transform: rotate(var(--angle)) translateX(50cqi) rotate(calc(-1 * var(--angle)));
}
/* The tile itself counter-turns the ring's rotation, so tile and icon ride it upright; on its own
   span, because the satellite's transform places it and the icon library animates the svg. */
.welcome-sat-in {
  display: grid;
  place-items: center;
  block-size: 100%;
  border-radius: 16px;
  background: var(--paper-2);
  color: var(--accent-ink);
  box-shadow: var(--shadow-pop);
  animation: welcome-orbit 48s linear infinite reverse;
}
.welcome-sat .ci { --ci-size: 26px; }
@keyframes welcome-orbit { to { rotate: 1turn; } }

/* Two moving doodles at the corners, popping in after the drawing. */
.welcome-accent {
  position: absolute;
  z-index: 2;
  color: var(--accent-ink);
  opacity: 0;
  scale: .4;
  transition: opacity 400ms var(--ease) 500ms, scale 700ms var(--ease-spring) 500ms;
  pointer-events: none;
}
.welcome-accent .ci.ci-big { width: clamp(64px, 22cqi, 104px); }
.welcome-accent[data-pos="0"] { inset-block-start: 2%; inset-inline-end: 0; }
.welcome-accent[data-pos="1"] { inset-block-end: 4%; inset-inline-start: 0; transition-delay: 700ms; }
.welcome-scene[data-state="current"] .welcome-accent { opacity: 1; scale: 1; }

/* ---------- The words ---------- */
.welcome-words { display: grid; align-content: center; gap: var(--s2); max-inline-size: 30rem; min-width: 0; }
.welcome-words > * { opacity: 0; translate: calc(var(--dir) * var(--rtl, 1) * 28px) 0; transition: opacity 420ms var(--ease), translate 620ms var(--ease-out); }
.welcome-scene[data-state="current"] .welcome-words > * { opacity: 1; translate: none; }
.welcome-scene[data-state="current"] .welcome-words > :nth-child(2) { transition-delay: 60ms; }
.welcome-scene[data-state="current"] .welcome-words > :nth-child(3) { transition-delay: 140ms; }
.welcome-scene[data-state="current"] .welcome-words > :nth-child(n+4) { transition-delay: 220ms; }

/* --t4, not --t5: the words column is ~410 px on a laptop, and a headline line has to fit it whole
   (lines are authored, never wrapped; test/welcome.test.mjs caps a line at 22 characters). */
.welcome-title { font-size: var(--t4); line-height: 1.1; color: var(--ink); }
/* The hand-drawn swash under the headline draws itself each time its scene arrives. */
.welcome-swash { display: block; margin-block-start: calc(-1 * var(--s1)); color: var(--accent); line-height: 0; }
.welcome-swash .ci.ci-big { width: 160px; --ci-stroke: 3; }
.welcome-swash path { stroke-dasharray: 1; stroke-dashoffset: 1; }
.welcome-scene[data-state="current"] .welcome-swash path { animation: welcome-draw 900ms var(--ease-out) 380ms forwards; }
@keyframes welcome-draw { to { stroke-dashoffset: 0; } }

.welcome-text { font-size: var(--t1); line-height: 1.55; color: var(--ink-2); }

.welcome-points { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s0); padding: 0; }
.welcome-points li { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: var(--radius-pill); background: var(--accent-soft); color: var(--accent-ink); font-size: var(--t-1); font-weight: 600; }
.welcome-points .ci { --ci-size: 16px; }

.welcome-path { list-style: none; display: grid; gap: var(--s0); padding: 0; counter-reset: none; }
.welcome-path li { display: flex; align-items: center; gap: var(--s1); color: var(--ink-2); font-weight: 550; }
.welcome-path-mark { display: grid; place-items: center; flex: none; inline-size: 28px; aspect-ratio: 1; border-radius: 50%; border: var(--rule-w) solid var(--rule-strong); font-size: var(--t-1); font-variant-numeric: tabular-nums; }
.welcome-path li[data-state="done"] { color: var(--ink-3); }
.welcome-path li[data-state="done"] .welcome-path-mark { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.welcome-path-mark .ci { --ci-size: 16px; }

:root[dir="rtl"] .welcome { --rtl: -1; }
@media (min-width: 861px) { :root[dir="rtl"] .welcome-frame { background: radial-gradient(60% 70% at 76% 46%, var(--accent-soft), transparent 70%), var(--paper-2); } }

/* ---------- The foot: progress, then the buttons ---------- */
.welcome-foot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s1) var(--s3);
  padding: var(--s2) var(--s5) var(--s3);
}
/* The pills are buttons: each opens its scene. The bar stays 6px; the button around it is 28px tall,
   so the target is a finger's, not a hairline's. Hovered, a pill thickens to say it can be pressed. */
.welcome-progress { display: flex; gap: 6px; max-inline-size: 280px; }
.welcome-seg {
  position: relative;
  flex: 1;
  min-inline-size: 24px;
  block-size: 28px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: none;
  cursor: pointer;
}
.welcome-seg::before, .welcome-seg::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block: calc(50% - 3px);
  border-radius: var(--radius-pill);
  transition: inset-block 200ms var(--ease-out), background-color 200ms var(--ease-out), transform 520ms var(--ease-out);
}
.welcome-seg::before { background: var(--rule); }
.welcome-seg::after { background: var(--accent); transform: scaleX(0); transform-origin: left; }
.welcome-seg:is([data-state="done"], [data-state="current"])::after { transform: none; }
:root[dir="rtl"] .welcome-seg::after { transform-origin: right; }
.welcome-seg:hover::before, .welcome-seg:hover::after { inset-block: calc(50% - 5px); }
.welcome-seg:hover::before { background: var(--rule-strong); }
.welcome-seg:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.welcome-actions { display: flex; align-items: center; gap: var(--s1); }
.welcome-back:disabled { visibility: hidden; }
/* Next is the one thing to press on every scene, so it is the biggest thing in the foot: twice the
   kit's button, words at --t2, a bigger arrow that nudges forward on its own now and then. */
.welcome .welcome-next {
  min-block-size: calc(var(--control-h) * 1.5);
  min-inline-size: 12rem;
  padding-inline: var(--s4);
  gap: var(--s1);
  font-size: var(--t2);
}
.welcome .welcome-next .ci { --ci-size: 24px; }
.welcome .welcome-next:has(.ci:first-child) { padding-inline-start: var(--s3); }

/* ---------- Tablet and phone ---------- */
@media (max-width: 860px) {
  .welcome { width: 100vw; height: 100dvh; max-height: none; border-radius: 0; }
  .welcome-scene {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto;
    /* safe: on a short phone the scene scrolls from its top instead of losing it above the fold. */
    align-content: safe center;
    gap: var(--s3);
    padding: var(--s5) var(--s3) var(--s1);
    /* A satellite on the orbit may reach past a 320 px screen's edge; it is decoration, so it is clipped
       rather than allowed to add a sideways scroll. */
    overflow: clip auto;
  }
  .welcome-stage { inline-size: min(78%, 40dvh, 340px); }
  .welcome-words { max-inline-size: none; }
  .welcome-title { font-size: var(--t3); }
  .welcome-foot { grid-template-columns: minmax(0, 1fr); padding: var(--s1) var(--s3) calc(var(--s2) + env(safe-area-inset-bottom)); }
  .welcome-progress { max-inline-size: none; }
  .welcome-actions > .welcome-next { flex: 1; justify-content: center; }
  /* 12rem is a desktop floor; beside Skip and Back on a phone it pushed Next past the screen's edge. */
  .welcome .welcome-next { min-inline-size: 0; padding-inline: var(--s3); }
  .welcome-frame { background: radial-gradient(90% 50% at 50% 24%, var(--accent-soft), transparent 70%), var(--paper-2); }
}
@media (max-width: 420px) {
  .welcome-sat { inline-size: 44px; margin: -22px; }
  .welcome-sat-in { border-radius: 14px; }
  .welcome-sat .ci { --ci-size: 22px; }
  .welcome-skip > span { font-size: var(--t-1); }
  /* No room for three buttons in a row: Next takes the whole first row, where the thumb is,
     and Skip and Back share the row under it. */
  .welcome-actions { flex-wrap: wrap; }
  .welcome-actions > .welcome-next { order: -1; flex-basis: 100%; }
  .welcome-actions > .welcome-skip { margin-inline-end: auto; }
}
@media (max-height: 560px) and (min-width: 861px) {
  .welcome-scene { padding-block-start: var(--s4); }
}

/* ---------- Still ---------- */
:root[data-motion="reduce"] .welcome :is(.welcome-scene, .welcome-disc, .welcome-stage dk-art, .welcome-orbit, .welcome-accent, .welcome-words > *) { transition: none; }
:root[data-motion="reduce"] .welcome .welcome-seg::before, :root[data-motion="reduce"] .welcome .welcome-seg::after { transition: none; }
:root[data-motion="reduce"] .welcome :is(.welcome-orbit, .welcome-sat-in) { animation: none; }
:root[data-motion="reduce"] .welcome-swash path { animation: none; stroke-dashoffset: 0; }
@media (prefers-reduced-motion: reduce) {
  .welcome, .welcome::backdrop, .welcome :is(.welcome-scene, .welcome-disc, .welcome-stage dk-art, .welcome-orbit, .welcome-accent, .welcome-words > *) { transition: none; }
  .welcome .welcome-seg::before, .welcome .welcome-seg::after { transition: none; }
  .welcome :is(.welcome-orbit, .welcome-sat-in) { animation: none; }
  .welcome-swash path { animation: none; stroke-dashoffset: 0; }
}


/* ---- 68-people.css ---- */
/* The people picker (kit/js/people.js): a button showing who has the task, and
   the team to choose from in a list that floats beside it. The list is a
   popover of its own rather than a .menu: menus are wired by overlays.js,
   which would give it menu keys a listbox must not have. */

.people-picker { display: inline-flex; max-width: 100%; min-width: 0; }
.people-pick { max-width: 100%; justify-content: flex-start; padding-inline-start: 6px; }
.people-pick .avatar { --size: 26px; }
.people-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.people-pick[data-empty] .people-name { color: var(--ink-3); font-weight: 600; }

.people-pop {
  width: min(320px, calc(100vw - 24px));
  max-height: min(60dvh, 420px);
  margin: 0;
  padding: 6px;
  border: var(--rule-w) solid var(--rule);
  border-radius: 16px;
  background: var(--paper-2);
  color: var(--ink-2);
  box-shadow: var(--shadow-pop);
  inset: auto;
  opacity: 0;
  transform: translateY(-4px) scale(.98);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease-out), overlay var(--dur) allow-discrete, display var(--dur) allow-discrete;
}
.people-pop:popover-open { display: flex; flex-direction: column; gap: 6px; opacity: 1; transform: none; }
@starting-style { .people-pop:popover-open { opacity: 0; transform: translateY(-4px) scale(.98); } }
:root[data-theme^="contrast"] .people-pop { border: 2px solid var(--ink); }
.people-pop .input { min-height: 40px; }

.people-list { flex: 1; min-height: 0; overflow-y: auto; list-style: none; display: grid; align-content: start; gap: 2px; }
.people-opt { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 4px 10px; border-radius: 10px; cursor: pointer; }
.people-opt-text { flex: 1; min-width: 0; display: grid; line-height: 1.3; overflow-wrap: anywhere; }
.people-opt-text b { color: var(--ink); font-weight: 650; }
.people-opt-text small { color: var(--ink-3); font-size: var(--t-1); }
.people-opt .ci { --ci-size: 18px; flex: none; color: var(--accent-ink); }
.people-opt[aria-selected="true"] { background: var(--accent-soft); }
.people-opt[aria-selected="true"] .people-opt-text b { color: var(--accent-ink); }
:root[data-theme^="contrast"] .people-opt[aria-selected="true"] { outline: 2px solid var(--ink); outline-offset: -2px; }
.people-empty { padding: var(--s2) var(--s1); color: var(--ink-3); text-align: center; overflow-wrap: anywhere; }


/* ---- 69-agents.css ---- */
/* "AI agents (MCP)", the Settings card (kit/js/agents-settings.js). Built from
   the kit's own pieces — segmented choices, checks, the secret row, the table,
   the timeline, the save bar — so what is here is only how they sit together
   inside one long card, and the few states the card has of its own. */

.agents { gap: var(--s3); }
.agents h2 .ci, .agents h3 .ci { --ci-size: 1em; margin-inline-end: .4em; vertical-align: -.12em; color: var(--accent-ink); }
.agents h3 { font-size: var(--t1); }
.agents h4 { font-size: var(--t0); }
.agents fieldset.field { gap: 8px; }

/* Each part after the policy sits under a rule, so one long card still reads as chapters. */
.agents-part { display: grid; gap: var(--s2); min-width: 0; padding-top: var(--s3); border-top: var(--rule-w) solid var(--rule); }
.agents-part > div:first-child { display: grid; gap: 2px; }

/* Where things stand: the saved policy, as the server reads it. A word and an icon, never colour alone. */
.agents-standing[data-state="off"] { --tone: var(--ink-3); }
.agents-standing[data-state="read"] { --tone: var(--ok); }
.agents-standing[data-state="edit"] { --tone: var(--accent-ink); }
.agents-standing[data-state="expired"] { --tone: var(--warn); }
.agents-standing .alert-body b { overflow-wrap: anywhere; }

.agents-readonly { display: flex; align-items: flex-start; gap: 8px; }
.agents-readonly .ci { --ci-size: 16px; flex: none; margin-top: 2px; }

/* A choice is as wide as its options, not the card (a fieldset is a grid, which would stretch it). */
.agents .segmented { justify-self: start; max-width: 100%; }
/* Long choices (a scope's name, Polish) wrap inside their option rather than push past the card,
   and a group that wraps to two rows reads as a rounded box, not a lopsided pill. */
.agents .segmented label { max-width: 100%; min-width: 0; }
.agents .segmented span { white-space: normal; overflow-wrap: anywhere; padding-block: 6px; }
@media (max-width: 560px) {
  .agents .segmented { border-radius: var(--radius-control); }
  .agents .segmented span { border-radius: calc(var(--radius-control) - 3px); }
}
/* A badge that says why (a refusal) may be a sentence; on a phone it wraps like one. */
.agents-activity .badge { white-space: normal; overflow-wrap: anywhere; max-width: 100%; border-radius: 12px; }
/* A choice that cannot be changed still shows which one is on. */
.agents .segmented input:disabled { cursor: not-allowed; }
.agents .segmented input:disabled + span { opacity: .6; }
.agents .segmented input:disabled:checked + span { opacity: .85; }
.agents .segmented span .ci { --ci-size: 16px; }
.agents-groups .check { padding-block: 4px; }
.agents-groups .check small { display: block; }
.agents .check:has(input:disabled) { cursor: not-allowed; opacity: .75; }

.agents-until { max-width: 30rem; }
.agents-until-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s0); }
.agents-until-row .input { flex: 1 1 12rem; max-width: 18rem; }
.agents-warn { display: flex; align-items: flex-start; gap: 6px; color: var(--warn); font-size: var(--t-1); font-weight: 600; }
.agents-warn .ci { --ci-size: 16px; flex: none; margin-top: 1px; }

.agents-rules-foot { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px var(--s2); }
.agents-counter { color: var(--ink-3); font-size: var(--t-1); font-variant-numeric: tabular-nums; margin-inline-start: auto; }
.agents-counter[data-over] { color: var(--bad); font-weight: 700; }

/* The token, shown once: a dashed accent frame says "this is different, act now". */
.agents-reveal {
  display: grid;
  gap: var(--s2);
  min-width: 0;
  padding: var(--s2);
  border: 1.5px dashed var(--accent-ink);
  border-radius: var(--radius-tile);
  background: var(--accent-wash);
}
:root[data-theme^="contrast"] .agents-reveal { border: 2px dashed var(--ink); }
.agents-once { display: flex; align-items: flex-start; gap: 8px; color: var(--ink); font-weight: 600; }
.agents-once .ci { --ci-size: 18px; flex: none; margin-top: 1px; color: var(--warn); }
.agents-reveal .secret { background: var(--paper-2); }
.agents-token-input {
  flex: 1;
  min-width: 0;
  min-height: 32px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  text-overflow: ellipsis;
}
.agents-token-input:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; border-radius: 4px; }
.agents-snippets { display: grid; gap: var(--s1); min-width: 0; }
.agents-snippets .tabs { margin-bottom: 0; }
.agents-snippet { display: grid; gap: var(--s1); min-width: 0; }
.agents-snippet pre {
  max-width: 100%;
  margin: 0;
  padding: var(--s1) var(--s2);
  overflow-x: auto;
  border-radius: var(--radius-control);
  background: var(--paper-2);
  color: var(--ink);
  font-size: var(--t-1);
  line-height: 1.55;
  white-space: pre;
  overflow-wrap: normal;
}
.agents-snippet pre:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
:root[data-theme^="contrast"] .agents-snippet pre { outline: 2px solid var(--ink); outline-offset: -2px; }

/* Tokens: the kit's table, sitting inside the card's padding rather than edge to edge. */
.agents-table { min-width: 0; }
@media (min-width: 721px) {
  .agents-tokens th, .agents-tokens td { padding-inline: 10px; }
  .agents-tokens th:first-child, .agents-tokens td:first-child { padding-inline-start: 0; }
}
.agents-token-name { display: grid; gap: 1px; min-width: 0; line-height: 1.35; overflow-wrap: anywhere; }
.agents-token-name small, .agents-used small { color: var(--ink-3); font-size: var(--t-1); }
.agents-used { display: grid; gap: 1px; }
/* A tool name breaks at its dots, never mid-word ("records.lis / t"). */
.agents-used code { overflow-wrap: normal; word-break: normal; }
.agents-prefix { color: var(--ink-2); }
.agents-muted { color: var(--ink-3); }
@media (max-width: 720px) {
  .agents-tokens tr { padding-inline: 0; }
  /* The column name keeps its word whole; the value beside it is what wraps. */
  .agents-tokens td::before { flex: none; max-width: 45%; overflow-wrap: normal; }
  .agents-token-name { text-align: start; }
  .agents-used { justify-items: end; }
}

/* Activity: the kit's timeline, with a tone for a refusal (a square, like the warn badge). */
.agents-activity .tl-dot[data-tone="warn"] { background: color-mix(in oklab, var(--warn) 14%, var(--paper-2)); color: var(--warn); border-radius: 10px; }
.agents-act-line { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--s0); }
.agents-tool { color: var(--ink); font-weight: 600; overflow-wrap: anywhere; }
.agents-act-who { color: var(--ink-2); font-size: var(--t-1); overflow-wrap: anywhere; }
.agents-activity > li:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; border-radius: 8px; }

.agents-empty { display: flex; align-items: center; gap: var(--s1); color: var(--ink-2); }
.agents-loading { display: grid; gap: 10px; padding-block: 4px; }
.agents-loading .skeleton { height: 14px; }
/* High contrast makes --field the card's own colour, which would hide the shimmer entirely. */
:root[data-theme^="contrast"] .agents-loading .skeleton { background: none; outline: 2px dashed var(--ink); outline-offset: -2px; }
.agents fieldset[aria-busy="true"] .segmented { opacity: .7; }


/* ---- 70-charts.css ---- */
/* Charts drawn by kit/js/charts.js: inline SVG, coloured by --chart-N, which
   every theme redefines (≥3:1 on the card in every mode). Each chart is a
   <figure> with a text summary and a real data table behind a toggle, so the
   numbers are never only a picture. */

.chart { position: relative; margin: 0; min-width: 0; }
/* charts.js mirrors the geometry itself in a right-to-left language (time from the right, the value
   axis on the right), so the SVG stays ltr: inherited rtl would flip every text-anchor off its tick. */
.chart svg, svg.spark { width: 100%; height: auto; overflow: visible; direction: ltr; }
.chart-plot { position: relative; }
.chart .grid-line { stroke: var(--rule); stroke-width: 1; shape-rendering: crispEdges; }
.chart .axis-text { fill: var(--ink-3); font-size: var(--t-3); font-variant-numeric: tabular-nums; }
.chart .series-line { fill: none; stroke-width: 2.25; stroke-linejoin: round; stroke-linecap: round; }
.chart .series-area { opacity: .16; }
.chart .series-dot { stroke: var(--paper-2); stroke-width: 2; }
.chart .bar { transition: opacity var(--dur) var(--ease); }
.chart .guide { stroke: var(--ink-3); stroke-width: 1; stroke-dasharray: 3 3; }
.chart .threshold { stroke: var(--bad); stroke-width: 1.5; stroke-dasharray: 5 4; }
.chart .threshold-text { fill: var(--bad); font-size: var(--t-3); font-weight: 650; }
.chart .marker { stroke: var(--ink-3); stroke-width: 1; stroke-dasharray: 2 4; }
.chart .marker-dot { fill: var(--ink); }
.chart .donut-track { stroke: var(--field); }
.chart svg.donut { width: auto; max-width: 100%; flex: none; }
.chart .arc { fill: none; }
.chart .donut-value { fill: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; }
.chart .donut-label { fill: var(--ink-3); font-size: var(--t-2); }
.chart[data-hover] .bar:not([data-on]) { opacity: .45; }
.c1 { stroke: var(--chart-1); fill: var(--chart-1); }
.c2 { stroke: var(--chart-2); fill: var(--chart-2); }
.c3 { stroke: var(--chart-3); fill: var(--chart-3); }
.c4 { stroke: var(--chart-4); fill: var(--chart-4); }
.c5 { stroke: var(--chart-5); fill: var(--chart-5); }
.c6 { stroke: var(--chart-6); fill: var(--chart-6); }
.chart .series-line:is(.c1, .c2, .c3, .c4, .c5, .c6) { fill: none; }
/* The second series is dashed as well as a second hue: tellable apart without colour. */
.chart .series-line.c2 { stroke-dasharray: 6 4; }
.chart .series-line.c3 { stroke-dasharray: 2 3; }

.legend { display: flex; flex-wrap: wrap; gap: 6px 16px; margin: 0 0 var(--s1); list-style: none; color: var(--ink-2); font-size: var(--t-1); font-weight: 600; }
.legend li { display: inline-flex; align-items: center; gap: 6px; }
.legend i { width: 14px; height: 4px; border-radius: 2px; background: var(--c); }
.legend i.dashed { background: linear-gradient(90deg, var(--c) 0 55%, transparent 55%) 0 0 / 7px 4px; }

.chart-tip {
  position: absolute;
  z-index: 5;
  min-width: 120px;
  padding: 8px 10px;
  border-radius: 12px;
  background: var(--inverse);
  color: var(--on-inverse);
  font-size: var(--t-1);
  box-shadow: var(--shadow-pop);
  pointer-events: none;
  transform: translate(-50%, calc(-100% - 12px));
  white-space: nowrap;
  overflow-wrap: normal;
}
.chart-tip b { display: block; margin-bottom: 2px; }
.chart-tip span { display: flex; align-items: center; gap: 6px; font-variant-numeric: tabular-nums; }
.chart-tip span i { width: 8px; height: 8px; border-radius: 50%; background: var(--c); }

.chart-data { margin-top: var(--s1); }
.chart-data summary { width: max-content; color: var(--ink-3); font-size: var(--t-1); font-weight: 600; cursor: pointer; border-radius: 6px; }
.chart-data summary:hover { color: var(--ink); }
.chart-data table { margin-top: var(--s0); font-size: var(--t-1); }
.chart-data :is(th, td) { padding-block: 4px; padding-inline: 0 12px; text-align: start; border-bottom: var(--rule-w) solid var(--rule); }

.spark { display: block; width: 100%; }
.spark path { fill: none; stroke: var(--accent-ink); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.spark .spark-area { fill: var(--accent-soft); stroke: none; }

/* Uptime / status band: one cell per period, the state in the tooltip and title. */
.band { display: flex; gap: 2px; height: 32px; }
.band i { flex: 1; border-radius: 3px; background: var(--ok); }
.band i[data-s="warn"] { background: var(--warn); height: 70%; align-self: flex-end; }
.band i[data-s="bad"] { background: var(--bad); height: 45%; align-self: flex-end; }
.band i[data-s="none"] { background: var(--field); }

@media (prefers-reduced-motion: no-preference) {
  :root:not([data-motion="reduce"]) .chart .series-line { stroke-dasharray: var(--len) var(--len); stroke-dashoffset: var(--len); animation: dk-draw 1s var(--ease-out) forwards; }
  :root:not([data-motion="reduce"]) .chart .series-line.c2 { animation: none; stroke-dashoffset: 0; stroke-dasharray: 6 4; }
  :root:not([data-motion="reduce"]) .chart .series-line.c3 { animation: none; stroke-dashoffset: 0; stroke-dasharray: 2 3; }
  :root:not([data-motion="reduce"]) .chart .bar { transform-box: fill-box; transform-origin: bottom; animation: dk-bar .7s var(--ease-out) both; animation-delay: calc(var(--i, 0) * 25ms); }
}
@keyframes dk-draw { to { stroke-dashoffset: 0; } }
@keyframes dk-bar { from { transform: scaleY(0); } }


/* ---- 71-rewards.css ---- */
/* Rewards: the header chip, the level ring, the Rewards page, the shop, the
   mini games and the level-up moment. Tokens only (rule 4). Motion carries
   state — a ring filling, a card turning — and stops under reduced motion. */

/* ---------- The chip in the header ---------- */
.rewards-chip {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--target); padding-block: 0; padding-inline: 4px 10px;
  border-radius: var(--radius-pill); color: var(--ink); text-decoration: none;
  font-weight: 700; font-variant-numeric: tabular-nums;
  transition: background-color var(--dur-fast) var(--ease);
}
.rewards-chip:hover { background: var(--hover); }
.rewards-chip:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.rewards-chip .ci { --ci-size: 16px; color: var(--accent); }
.rewards-chip[aria-busy="true"] { opacity: .6; }
@media (max-width: 520px) { .rewards-chip-points, .rewards-chip .ci { display: none; } .rewards-chip { padding-inline-end: 4px; } }

/* ---------- The ring (chip and level card) ---------- */
.rewards-ring { inline-size: 30px; block-size: 30px; flex: none; rotate: -90deg; }
.rewards-ring-lg { inline-size: 96px; block-size: 96px; }
.rewards-ring circle { fill: none; stroke-width: 3.4; }
.rewards-ring-track { stroke: color-mix(in oklab, var(--ink) 10%, var(--field)); }
.rewards-ring-fill {
  stroke: var(--accent); stroke-linecap: round;
  stroke-dasharray: var(--v, 0) 100;
  transition: stroke-dasharray var(--dur-slow) var(--ease-out);
}
.rewards-ring-level {
  rotate: 90deg; transform-origin: 18px 18px;
  fill: var(--ink); font-size: 13px; font-weight: 800;
  text-anchor: middle; dominant-baseline: central;
}
.rewards-ring-lg .rewards-ring-level { font-size: 12px; }
:root[data-theme^="contrast"] .rewards-ring-track { stroke: var(--ink-3); }

/* ---------- The page ---------- */
.rewards { display: grid; gap: var(--gap); }
.rewards-promos:empty { display: none; }
.rewards-promos { display: grid; gap: var(--s1); }
.rewards-panel { display: grid; gap: var(--gap); }
.rewards .card-title { display: flex; align-items: center; gap: 8px; }
.rewards .card-title .ci { --ci-size: 18px; color: var(--ink-3); }

.rewards-level { display: flex; align-items: center; gap: var(--s2); }
.rewards-level-name { font-size: var(--t2); font-weight: 800; color: var(--ink); }
.rewards-level-points { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.rewards-title-pick { margin-top: var(--s1); }

.rewards-balance { font-variant-numeric: tabular-nums; }
.rewards-tokens { margin-top: var(--s1); }

.rewards-shields { display: flex; align-items: center; gap: 6px; color: var(--ink-2); }
.rewards-shield .ci { --ci-size: 20px; color: var(--ink-3); opacity: .35; }
.rewards-shield[data-held="true"] .ci { color: var(--accent); opacity: 1; }

.rewards-next .list-end, .rewards-quests .list-end { display: flex; align-items: center; gap: var(--s1); flex: none; }
/* A feature's name wraps as words, never letter by letter: when the card is
   narrow the badge and the button drop below it (§0.14, no text overflow). */
.rewards-next > li { flex-wrap: wrap; }
.rewards-next .list-main { flex: 1 1 10rem; overflow-wrap: normal; }
.rewards-next .list-end { margin-inline-start: auto; }
.rewards .meter-top { flex-wrap: wrap; }
.rewards .meter-top span:last-child { white-space: nowrap; }
.rewards-quests li[data-done="true"] .meter-fill { background: var(--ok); }
.rewards-products { display: grid; gap: var(--s1); margin-top: var(--s2); }

/* ---------- The hero: level, points, streak (GUIDELINES §5c) ----------
   Three tiles that are the first thing a person sees on the page, so each is
   a small scene: a ring that fills, coins that drop, a flame that burns. */
.rewards-tile { position: relative; display: flex; flex-direction: column; gap: var(--s1); overflow: clip; isolation: isolate; }
.rewards-tile::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(120% 90% at 100% 0%, var(--glow, var(--accent-soft)), transparent 60%);
}
.rewards-tile-level { --glow: color-mix(in oklab, var(--accent) 16%, transparent); }
.rewards-tile-points { --glow: color-mix(in oklab, var(--coin-2) 22%, transparent); }
.rewards-tile-streak { --glow: color-mix(in oklab, var(--flame-2) 20%, transparent); }
.rewards-tile-streak[data-heat="cold"] { --glow: var(--field); }
:root[data-theme^="contrast"] .rewards-tile::before { display: none; }
/* The glow sits behind the tile's drawing, at the inline end. */
:root[dir="rtl"] .rewards-tile::before { background: radial-gradient(120% 90% at 0% 0%, var(--glow, var(--accent-soft)), transparent 60%); }
.rewards-tile-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s1); }
.rewards-tile-head dk-art { --art-size: 88px; margin: 0; margin-block-start: calc(var(--s1) * -1); margin-inline-end: calc(var(--s1) * -1); }
.rewards-big { font-size: var(--t5); font-weight: 800; line-height: 1.05; color: var(--ink); font-variant-numeric: tabular-nums; }

.rewards-ring-lg { inline-size: 112px; block-size: 112px; filter: drop-shadow(0 6px 14px color-mix(in oklab, var(--accent) 28%, transparent)); }
.rewards-tile-level .rewards-level-name { font-size: var(--t3); line-height: 1.15; }
.rewards-next-level { display: grid; gap: 6px; margin-top: auto; }
.rewards-next-bar { block-size: 10px; border-radius: var(--radius-pill); background: var(--field); overflow: clip; }
.rewards-next-bar > span {
  display: block; block-size: 100%; inline-size: var(--v, 0%); border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--art-2));
  animation: rewards-grow 1.1s var(--ease-out) both;
}
@keyframes rewards-grow { from { inline-size: 0; } }
.rewards-next-level b { color: var(--accent-ink); }

.rewards-token-chips { display: flex; flex-wrap: wrap; gap: var(--s0); margin-top: auto; }
.rewards-token-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px;
  border-radius: var(--radius-pill); background: var(--paper-2); border: var(--rule-w) solid var(--rule);
  font-size: var(--t-1); color: var(--ink-2);
}
.rewards-token-chip b { color: var(--ink); font-variant-numeric: tabular-nums; }
.rewards-token-chip .ci { --ci-size: 16px; color: var(--accent); }

/* Coins: the pile drops in coin by coin, and jingles under the hand. */
.coins { inline-size: 76px; flex: none; margin: 0; margin-block-start: -4px; margin-inline-end: -4px; }
.coins-svg { display: block; inline-size: 100%; overflow: visible; }
.coins-svg .c1 { stop-color: var(--coin-1); }
.coins-svg .c2 { stop-color: var(--coin-2); }
.coins-svg .c3 { stop-color: var(--coin-3); }
.coin-top { fill: var(--coin-1); stroke: var(--coin-3); stroke-width: 1.2; }
.coin-rim { fill: none; stroke: var(--coin-2); stroke-width: 1.4; }
.coin-side { stroke: var(--coin-3); stroke-width: 1.2; }
.coins-shadow { fill: color-mix(in oklab, var(--ink) 14%, transparent); }
.coin { animation: rewards-coin-drop 620ms var(--ease-out) calc(var(--i) * 110ms + 200ms) both; }
@keyframes rewards-coin-drop { from { transform: translateY(-60px); opacity: 0; } 70% { transform: translateY(3px); opacity: 1; } }
@media (hover: hover) { .rewards-tile-points:hover .coin { animation: rewards-jingle 520ms var(--ease-out) calc(var(--i) * 45ms) both; } }
@keyframes rewards-jingle { 40% { transform: translateY(-5px) rotate(-2deg); } }

/* The flame: it grows with the streak (--heat 0…1) and flickers; an ember when cold. */
.flame { inline-size: calc(46px + 30px * var(--heat, 0)); flex: none; }
.flame-svg { display: block; inline-size: 100%; overflow: visible; }
.flame-svg .f1 { stop-color: var(--flame-1); }
.flame-svg .f2 { stop-color: var(--flame-2); }
.flame-svg .f3 { stop-color: var(--flame-3); }
.flame-mid { fill: var(--flame-2); opacity: .85; }
.flame-core { fill: var(--flame-1); }
.flame-glow { fill: color-mix(in oklab, var(--flame-2) 40%, transparent); }
.flame :is(.flame-outer, .flame-mid, .flame-core) { transform-box: fill-box; transform-origin: 50% 100%; }
.flame .flame-outer { animation: rewards-flicker 1.9s ease-in-out infinite; }
.flame .flame-mid { animation: rewards-flicker 1.3s ease-in-out .2s infinite reverse; }
.flame .flame-core { animation: rewards-flicker 1s ease-in-out .1s infinite; }
@keyframes rewards-flicker {
  0%, 100% { transform: scale(1, 1) skewX(0deg); }
  25% { transform: scale(.96, 1.05) skewX(2deg); }
  50% { transform: scale(1.03, .96) skewX(-2deg); }
  75% { transform: scale(.98, 1.03) skewX(1deg); }
}
.flame[data-lit="false"] :is(.flame-outer, .flame-mid) { filter: grayscale(1); opacity: .35; animation: none; }
.flame[data-lit="false"] .flame-core { opacity: .5; }
@media (hover: hover) { .rewards-tile-streak:hover .flame[data-lit="true"] { scale: 1.08; transition: scale var(--dur) var(--ease-out); } }

.rewards-weeks { list-style: none; display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px; padding: 0; }
.rewards-weeks li { block-size: 10px; border-radius: var(--radius-pill); background: var(--field); }
.rewards-weeks li[data-lit="true"] { background: linear-gradient(90deg, var(--flame-2), var(--flame-3)); }
.rewards-weeks li[data-now="open"] { outline: 2px dashed var(--flame-2); outline-offset: 1px; animation: rewards-pulse 1.6s ease-in-out infinite; }
@keyframes rewards-pulse { 50% { opacity: .45; } }
.rewards-streak-foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s0) var(--s1); margin-top: auto; }
.rewards-streak-foot .badge { margin-inline-start: auto; }

/* ---------- Badges: medals worth wanting (GUIDELINES §5c) ---------- */
.medal {
  --m1: var(--medal-bronze-1); --m2: var(--medal-bronze-2); --m3: var(--medal-bronze-3);
  position: relative; display: block; flex: none;
  inline-size: var(--medal-size, 84px); aspect-ratio: 100 / 120;
  transform: perspective(500px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform var(--dur) var(--ease-out), filter var(--dur) var(--ease);
}
.medal[data-tier="silver"] { --m1: var(--medal-silver-1); --m2: var(--medal-silver-2); --m3: var(--medal-silver-3); }
.medal[data-tier="gold"] { --m1: var(--medal-gold-1); --m2: var(--medal-gold-2); --m3: var(--medal-gold-3); }
.medal[data-tier="platinum"] { --m1: var(--medal-platinum-1); --m2: var(--medal-platinum-2); --m3: var(--medal-platinum-3); }
.medal[data-size="lg"] { --medal-size: 96px; }
.medal[data-size="xl"] { --medal-size: 168px; }
.medal-svg { display: block; inline-size: 100%; block-size: 100%; overflow: visible; filter: drop-shadow(0 6px 10px color-mix(in oklab, var(--m3) 45%, transparent)); }
.medal-svg .m1 { stop-color: var(--m1); }
.medal-svg .m2 { stop-color: var(--m2); }
.medal-svg .m3 { stop-color: var(--m3); }
.medal-rim { stroke: var(--m3); stroke-width: 1.5; }
.medal-face { stroke: var(--m3); stroke-width: 1.2; }
.medal-bead { stroke: var(--m1); stroke-width: 1.4; stroke-dasharray: 1.5 3; opacity: .9; }
.medal-ribbon-l { fill: var(--accent); }
.medal-ribbon-r { fill: color-mix(in oklab, var(--accent) 70%, var(--ink)); }
.medal-progress { fill: none; stroke: var(--accent); stroke-width: 3.2; stroke-linecap: round; stroke-dasharray: var(--p, 0) 100; transform: rotate(-90deg); transform-origin: 50px 50px; }
.medal-glyph {
  position: absolute; inset-inline: 0; inset-block-start: 0; block-size: calc(100% * 100 / 120);
  display: grid; place-items: center; color: var(--medal-ink); pointer-events: none;
}
.medal-glyph .ci { --ci-size: calc(var(--medal-size, 84px) * .3); filter: drop-shadow(0 1px 0 color-mix(in oklab, var(--m1) 80%, transparent)); }
/* A sweep of light across the face, every few seconds, on a medal that is yours. */
.medal-shine {
  position: absolute; inset-inline-start: 19%; inset-block-start: calc(19% * 100 / 120); inline-size: 62%; aspect-ratio: 1;
  border-radius: 50%; overflow: clip; pointer-events: none;
}
.medal[data-earned="true"] .medal-shine::after {
  content: ""; position: absolute; inset: -20% auto -20% -60%; inline-size: 40%;
  background: linear-gradient(100deg, transparent, var(--medal-shine), transparent);
  transform: skewX(-18deg);
  animation: rewards-shine 5.5s ease-in-out 1.2s infinite;
}
@keyframes rewards-shine { 0%, 70% { translate: 0 0; } 100% { translate: 420% 0; } }
.medal-lock {
  position: absolute; inset-inline-end: 4%; inset-block-start: 56%;
  display: grid; place-items: center; inline-size: 26%; aspect-ratio: 1; border-radius: 50%;
  background: var(--paper-2); color: var(--ink-2); box-shadow: 0 2px 6px color-mix(in oklab, var(--ink) 20%, transparent);
}
.medal-lock .ci { --ci-size: 60%; }
/* Not yet yours: the same medal, dimmed, with a hint of its metal left in it — a gold one still
   looks like gold under the dust. Full size, so it reads as "soon", never as "not for you". */
.medal[data-earned="false"] .medal-svg > :is(.medal-rim, .medal-face, .medal-bead, .medal-ribbon) { filter: grayscale(.72) opacity(.58); }
.medal[data-earned="false"] .medal-glyph { color: var(--ink-3); }
.medal[data-earned="false"] .medal-svg { filter: none; }
.medal.medal-reveal { animation: rewards-medal-in 1.1s var(--ease-out) both; }
@keyframes rewards-medal-in {
  from { transform: perspective(500px) rotateY(-540deg) scale(.4); opacity: 0; }
  60% { opacity: 1; }
  to { transform: perspective(500px) rotateY(0) scale(1); }
}
:root[data-theme^="contrast"] .medal-svg { filter: none; }

.rewards-badges-card .card-head { flex-wrap: wrap; align-items: center; }
.rewards-collection { display: grid; gap: 4px; min-inline-size: 10rem; justify-items: end; }
.rewards-collection > span { justify-self: stretch; block-size: 8px; border-radius: var(--radius-pill); background: var(--field); overflow: clip; position: relative; }
.rewards-collection > span::after { content: ""; position: absolute; inset-block: 0; inset-inline-start: 0; inline-size: var(--v, 0%); border-radius: inherit; background: linear-gradient(90deg, var(--medal-gold-2), var(--medal-gold-3)); }
.rewards-collection small { color: var(--ink-3); font-size: var(--t-1); font-weight: 600; }

.rewards-next-up { display: grid; gap: var(--s0); margin-block: var(--s1) var(--s2); }
.rewards-next-list { list-style: none; padding: 0; display: grid; gap: var(--s1); grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.rewards-next-card {
  display: flex; align-items: center; gap: var(--s2); inline-size: 100%; padding: var(--s1) var(--s2);
  border: var(--rule-w) solid var(--rule); border-radius: var(--radius); background: var(--paper-2); color: var(--ink); text-align: start;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.rewards-next-words { display: grid; gap: 4px; min-inline-size: 0; }
.rewards-next-words small { color: var(--accent-ink); font-weight: 700; }
@media (hover: hover) { .rewards-next-card:hover { border-color: var(--rule-strong); box-shadow: var(--shadow-pop); } }

.rewards-badges-card .chips { margin-block-end: var(--s2); }
.rewards-badges {
  list-style: none; display: grid; gap: var(--s1); padding: 0;
  grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr));
}
.rewards-badges-none { color: var(--ink-3); padding: var(--s2); }

/* The families: a heading with the family's icon, a line on how its badges are won, and how many of
   them are held; then its medals. A rule above each family after the first keeps them apart. */
.rewards-groups { display: grid; gap: var(--s4); }
.rewards-group { display: grid; gap: var(--s2); }
.rewards-group + .rewards-group { padding-block-start: var(--s3); border-block-start: var(--rule-w) solid var(--rule); }
.rewards-group-head { display: flex; align-items: center; gap: var(--s1) var(--s2); flex-wrap: wrap; }
.rewards-group-icon {
  display: grid; place-items: center; flex: none; inline-size: 44px; aspect-ratio: 1;
  border-radius: var(--radius); background: var(--accent-soft); color: var(--accent-ink);
}
.rewards-group-icon .ci { --ci-size: 22px; }
.rewards-group-words { display: grid; gap: 2px; flex: 1 1 16rem; min-inline-size: 0; }
.rewards-group-words h4 { margin: 0; font-size: var(--t1); }
.rewards-group-words p { margin: 0; color: var(--ink-3); font-size: var(--t-1); max-inline-size: 60ch; }
.rewards-group-count {
  flex: none; padding: 4px var(--s1); border-radius: var(--radius-pill);
  background: var(--field); color: var(--ink-2); font-size: var(--t-1); font-weight: 650; font-variant-numeric: tabular-nums;
}
.rewards-group-count[data-complete] { background: var(--accent-soft); color: var(--accent-ink); }
:root[data-theme^="contrast"] .rewards-group-icon, :root[data-theme^="contrast"] .rewards-group-count { border: var(--rule-w) solid var(--ink); }
.rewards-badge-open {
  display: grid; justify-items: center; align-content: start; gap: 6px; inline-size: 100%; block-size: 100%;
  padding: var(--s2) var(--s1) var(--s1); border: var(--rule-w) solid var(--rule); border-radius: var(--radius);
  background: var(--paper-2); color: var(--ink); text-align: center;
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
/* A badge that is yours glows in its own metal behind the medal. */
.rewards-badge { --glow-1: var(--medal-bronze-2); --glow-2: var(--medal-bronze-3); }
.rewards-badge[data-tier="silver"] { --glow-1: var(--medal-silver-2); --glow-2: var(--medal-silver-3); }
.rewards-badge[data-tier="gold"] { --glow-1: var(--medal-gold-2); --glow-2: var(--medal-gold-3); }
.rewards-badge[data-tier="platinum"] { --glow-1: var(--medal-platinum-2); --glow-2: var(--medal-platinum-3); }
.rewards-badge[data-earned="true"] .rewards-badge-open {
  background: radial-gradient(90% 62% at 50% 0%, color-mix(in oklab, var(--glow-1) 34%, transparent), var(--paper-2) 72%);
  border-color: color-mix(in oklab, var(--glow-2) 45%, var(--rule));
}
@media (hover: hover) {
  .rewards-badge-open:hover { transform: translateY(-3px); box-shadow: var(--shadow-pop); border-color: var(--rule-strong); }
  .rewards-badge-open:hover .medal[data-earned="false"] .medal-svg > * { filter: grayscale(.4) opacity(.8); }
}
.rewards-badge-open:focus-visible, .rewards-next-card:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.rewards-badge-title { font-size: var(--t0); line-height: 1.25; }
.rewards-badge-desc { color: var(--ink-3); font-size: var(--t-1); line-height: 1.35; }
.rewards-badge-when { display: inline-flex; align-items: center; gap: 4px; color: var(--ok); font-size: var(--t-1); font-weight: 600; margin-top: auto; }
.rewards-badge[data-earned="false"] .rewards-badge-when { color: var(--ink-3); }
.rewards-badge-when .ci { --ci-size: 14px; }
.rewards-badge-bar { display: grid; gap: 4px; inline-size: 100%; margin-top: auto; }
.rewards-badge-bar > span { display: block; block-size: 6px; border-radius: var(--radius-pill); background: var(--field); overflow: clip; position: relative; }
.rewards-badge-bar > span::after { content: ""; position: absolute; inset-block: 0; inset-inline-start: 0; inline-size: var(--v, 0%); background: var(--accent); border-radius: inherit; }
.rewards-badge-bar small { color: var(--ink-3); font-size: var(--t-2); font-variant-numeric: tabular-nums; }

.rewards-badge-meta { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px 8px; font-size: var(--t-2); color: var(--ink-3); }
/* Tracking breaks joined scripts (Arabic) and CJK: those languages set the tier plain. */
:root[data-no-tracking] .rewards-tier { letter-spacing: 0; }
.rewards-tier {
  padding: 1px 8px; border-radius: var(--radius-pill); font-weight: 800; text-transform: uppercase; letter-spacing: .04em;
  background: linear-gradient(135deg, var(--m1, var(--medal-bronze-1)), var(--m2, var(--medal-bronze-2)));
  color: var(--medal-ink);
}
.rewards-tier[data-tier="bronze"] { --m1: var(--medal-bronze-1); --m2: var(--medal-bronze-2); }
.rewards-tier[data-tier="silver"] { --m1: var(--medal-silver-1); --m2: var(--medal-silver-2); }
.rewards-tier[data-tier="gold"] { --m1: var(--medal-gold-1); --m2: var(--medal-gold-2); }
.rewards-tier[data-tier="platinum"] { --m1: var(--medal-platinum-1); --m2: var(--medal-platinum-2); }
.rewards-badge-pts { display: inline-flex; align-items: center; gap: 3px; font-weight: 700; color: var(--ink-2); }
.rewards-badge-pts .ci { --ci-size: 13px; color: var(--coin-3); }
.rewards-share { font-weight: 600; }

.rewards-badge-dialog .rewards-celebrate-body, .rewards-badge-won .rewards-celebrate-body { padding-block-start: var(--s3); }
.rewards-badge-stage { display: grid; place-items: center; }
.rewards-won-points { display: inline-flex; align-items: center; gap: 6px; font-weight: 800; color: var(--ink); }
.rewards-won-points .ci { color: var(--coin-3); }

/* The prize on the Introduction's last scene (welcome.js). */
.welcome-prize {
  display: inline-flex; align-items: center; gap: 8px; justify-self: start; margin-top: var(--s1);
  padding: 8px 14px; border-radius: var(--radius-pill); font-weight: 800; color: var(--medal-ink);
  background: linear-gradient(135deg, var(--coin-1), var(--coin-2));
  box-shadow: 0 6px 16px color-mix(in oklab, var(--coin-2) 40%, transparent);
  animation: rewards-prize 2.4s ease-in-out infinite;
}
.welcome-prize .ci { --ci-size: 20px; }
@keyframes rewards-prize { 50% { transform: translateY(-2px) scale(1.03); } }

.rewards-code .btn-row { flex-wrap: nowrap; }
.rewards-code .input { flex: 1 1 auto; min-width: 0; text-transform: uppercase; }

/* ---------- The shop ---------- */
.rewards-shop-balance { display: flex; align-items: center; gap: 8px; font-weight: 700; color: var(--ink); }
.rewards-shop-balance .ci { color: var(--accent); }
.rewards-item, .rewards-game { display: flex; flex-direction: column; gap: var(--s1); }
.rewards-item .card-foot, .rewards-game .card-foot { margin-top: auto; }
.rewards-item-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s1); }
.rewards-item-art {
  display: grid; place-items: center; inline-size: 44px; block-size: 44px;
  border-radius: var(--radius-sm); background: var(--accent-wash); color: var(--accent);
}
.rewards-item-art .ci { --ci-size: 24px; }
.rewards-item-effects { color: var(--ink-2); font-size: var(--t-1); }
.rewards-item-price { display: flex; align-items: baseline; gap: 8px; color: var(--ink); font-variant-numeric: tabular-nums; }
.rewards-item-price s { color: var(--ink-3); }

/* ---------- Games ---------- */
.rewards-play-dialog { inline-size: min(34rem, calc(100vw - 2 * var(--s2))); }
.rewards-play { display: grid; gap: var(--s2); justify-items: center; }
.rewards-play-status { color: var(--ink-2); }
.rewards-play-result { display: flex; justify-content: center; }
.flood-count { color: var(--ink-2); font-variant-numeric: tabular-nums; }

.flood-grid {
  display: grid; grid-template-columns: repeat(var(--side), 1fr);
  inline-size: min(100%, 22rem); aspect-ratio: 1; gap: 1px;
  border-radius: var(--radius-sm); overflow: clip; background: var(--rule);
}
.flood-cell { background: var(--c, var(--field)); transition: background-color var(--dur-fast) var(--ease); }
.flood-cell[data-own="true"] { box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--ink) 18%, transparent); }
:is(.flood-cell, .flood-swatch)[data-c="0"] { --c: var(--game-1); }
:is(.flood-cell, .flood-swatch)[data-c="1"] { --c: var(--game-2); }
:is(.flood-cell, .flood-swatch)[data-c="2"] { --c: var(--game-3); }
:is(.flood-cell, .flood-swatch)[data-c="3"] { --c: var(--game-4); }
:is(.flood-cell, .flood-swatch)[data-c="4"] { --c: var(--game-5); }
:is(.flood-cell, .flood-swatch)[data-c="5"] { --c: var(--game-6); }
.flood-palette { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s1); }
/* The swatch's icon is drawn dark over the colour, never white: yellow and
   sky blue would swallow a white glyph. */
.flood-swatch {
  inline-size: var(--target); block-size: var(--target); border-radius: 50%;
  background: var(--c); border: 2px solid var(--paper-2); outline: var(--rule-w) solid var(--rule-strong);
  display: grid; place-items: center; color: var(--game-ink);
}
.flood-swatch .ci { --ci-size: 18px; }
.flood-swatch:disabled { opacity: .5; }
.flood-swatch:focus-visible { outline: 3px solid var(--focus); }

.pairs-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s1); inline-size: min(100%, 22rem); }
.pairs-card {
  aspect-ratio: 1; min-block-size: var(--target); border-radius: var(--radius-sm);
  display: grid; place-items: center; background: var(--accent); color: var(--paper-2);
  transition: transform var(--dur) var(--ease-spring), background-color var(--dur-fast) var(--ease);
}
.pairs-card .ci { --ci-size: 28px; }
.pairs-card[data-state="up"] { background: var(--paper-2); color: var(--ink); outline: 2px solid var(--accent); transform: rotateY(0); }
.pairs-card[data-state="matched"] { background: var(--accent-wash); color: var(--accent); outline: 2px solid var(--ok); }
.pairs-card[data-state="down"]:hover { transform: translateY(-2px); }

.quiz-step { color: var(--ink-3); font-weight: 600; }
.quiz-ask { font-size: var(--t1); font-weight: 700; color: var(--ink); text-align: center; }
.quiz-options { display: grid; gap: var(--s1); inline-size: 100%; }
.quiz-option {
  display: flex; align-items: flex-start; gap: 10px; padding: var(--s2);
  border-radius: var(--radius-sm); background: var(--field); color: var(--ink); text-align: start;
}
.quiz-option:hover { background: var(--field-hover); }
.quiz-option .ci { --ci-size: 18px; color: var(--accent); flex: none; margin-top: 2px; }
.quiz-reveal { display: grid; gap: var(--s1); padding-inline-start: 0; list-style: none; inline-size: 100%; }
.quiz-reveal li { display: flex; gap: 10px; align-items: flex-start; }
.quiz-reveal li[data-ok="true"] > .ci { color: var(--ok); }
.quiz-reveal li[data-ok="false"] > .ci { color: var(--bad); }

/* ---------- The level-up moment ---------- */
.rewards-celebrate { overflow: clip; }
.rewards-celebrate-body { display: grid; justify-items: center; text-align: center; gap: var(--s1); }
.rewards-celebrate-body dk-art { inline-size: 9rem; block-size: 9rem; }
.rewards-celebrate-kicker { color: var(--accent); font-weight: 800; }
.rewards-effects { list-style: none; display: grid; gap: 6px; padding: 0; }
.rewards-effects li { display: flex; align-items: center; gap: 8px; justify-content: center; }
.rewards-confetti { position: absolute; inset: 0; pointer-events: none; }
.rewards-confetti span {
  position: absolute; inset-block-start: -8px; inset-inline-start: calc(var(--i) * 5.5%);
  inline-size: 8px; block-size: 12px; border-radius: 2px;
  background: var(--c, var(--accent));
  animation: rewards-fall 1.8s var(--ease-out) calc(var(--i) * 40ms) both;
}
.rewards-confetti span:nth-child(3n) { --c: var(--ok); }
.rewards-confetti span:nth-child(3n+1) { --c: var(--art-2); }
.rewards-confetti span:nth-child(4n) { --c: var(--warn); }
@keyframes rewards-fall {
  from { transform: translateY(0) rotate(0); opacity: 1; }
  to { transform: translateY(26rem) rotate(540deg); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .rewards-confetti { display: none; }
  .rewards-ring-fill, .pairs-card, .flood-cell, .medal { transition: none; }
  .coin, .flame *, .rewards-next-bar > span, .rewards-weeks li, .medal-shine::after, .medal.medal-reveal, .welcome-prize { animation: none !important; }
}
:root:is([data-motion="off"], [data-motion="reduce"]) .rewards-confetti { display: none; }
/* A pseudo-element cannot sit inside :is(), so the shine has a rule of its own. */
:root[data-motion="reduce"] :is(.coin, .flame *, .rewards-next-bar > span, .rewards-weeks li, .medal.medal-reveal, .welcome-prize) { animation: none !important; }
:root[data-motion="reduce"] .medal-shine::after { animation: none !important; }
:root[data-motion="reduce"] .medal { transition: none; transform: none; }
.rewards-badge-dialog .meter { inline-size: min(100%, 20rem); justify-self: center; }


/* ---- 72-support-view.css ---- */
/* Support view (kit/js/support-view.js, docs/OPS.md): castomo staff inside a
   customer's account. Two signals that cannot be missed or cropped out of a
   screenshot: a bar across the top saying whose account, which mode, who and
   until when, and an edge around the whole page in the same colour. The shell
   moves down by the bar's height; nothing else about the page changes, so staff
   see exactly what the customer sees. */

:root[data-support] { --support-h: 40px; }

.support-bar {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 95;
  display: flex;
  align-items: center;
  gap: var(--s1);
  block-size: var(--support-h);
  padding-inline: var(--pad);
  background: var(--support);
  color: var(--on-support);
  font-size: var(--t-1);
  font-weight: 600;
}
.support-bar[data-mode="edit"] { background: var(--support-edit); }
.support-bar[data-mode="ended"] { background: var(--inverse); color: var(--on-inverse); }
.support-bar-mark { flex: none; display: inline-flex; align-items: center; gap: 6px; font-weight: 800; }
.support-bar-text { flex: 1; min-width: 0; display: flex; gap: var(--s1); overflow: hidden; white-space: nowrap; }
.support-bar-text span { overflow: hidden; text-overflow: ellipsis; }
.support-bar-text span:first-child { flex-shrink: 0; max-width: 40%; }
.support-bar-text span + span::before { content: "·" / ""; margin-inline-end: var(--s1); opacity: .75; }
.support-bar-end {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 28px;
  padding-inline: 12px;
  border: 1px solid currentColor;
  border-radius: var(--radius-pill);
  background: transparent;
  color: inherit;
  font-weight: 700;
}
@media (hover: hover) { .support-bar-end:hover { background: color-mix(in oklab, currentColor 16%, transparent); } }
.support-bar-end:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

/* The edge: pointer-transparent, above the page, below dialogs (the top layer). */
:root[data-support]:not([data-support="ended"]) body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 94;
  border: 3px solid var(--support);
  pointer-events: none;
}
:root[data-support="edit"] body::after { border-color: var(--support-edit); }

/* The shell moves down by the bar. */
:root[data-support] .app { min-height: calc(100dvh - var(--support-h)); margin-block-start: var(--support-h); }
:root[data-support] :is(.side, .top) { top: var(--support-h); }
:root[data-support] .side { height: calc(100dvh - var(--support-h)); }
:root[data-support][data-grid="bannerLeft"] .side { top: calc(var(--bar-h) + var(--support-h)); height: calc(100dvh - var(--bar-h) - var(--support-h)); }
@media (min-width: 861px) and (max-width: 1200px) {
  :root[data-support][data-nav-open]:not([data-grid="topOnly"]) .side { inset-block-start: var(--support-h); }
}
@media (max-width: 860px) {
  :root[data-support] { --support-h: 36px; }
  :root[data-support] .side { inset-block-start: var(--support-h); height: calc(100dvh - var(--support-h)); }
  :root[data-support] .top { padding-top: var(--s0); }
  /* A phone keeps the two facts that matter: whose account (the name alone), and which mode. */
  .support-bar { gap: var(--s0); padding-inline: 12px; }
  .support-bar-mark b, .support-bar-text span:nth-child(n + 3) { display: none; }
  .support-bar-text span:first-child { flex-shrink: 1; max-width: none; }
  .support-bar-text span + span { flex-shrink: 0; }
  .support-bar-text [data-short] { font-size: 0; }
  /* The long words stay for screen readers; the short ones are drawn only (the "/ ''" hides them from speech). */
  .support-bar-text [data-short]::after { content: attr(data-short) / ""; font-size: var(--t-1); }
}


/* ---- 80-agent.css ---- */
/* The assistant (kit/js/agent/): its panel, the run bar, and the pieces a
   "show me" run puts on the page — cursor, ring and narration bubble.

   All of them are manual popovers, so they sit in the top layer; layer.js
   moves them into a modal dialog when one is open, because outside it they
   would be inert. Every rule resets the popover defaults it relies on
   (inset, margin, size, border, padding). */

/* ---------- The door: bottom-right, where every website keeps its chat ----------
   A round accent button that opens the panel as a chat window above itself.
   While the panel is open the spark gives way to a drawn ×, so the same spot
   closes it, as on any chat widget. On a phone it floats above the tab bar. */
:root { --fab: 60px; --fab-gap: var(--s3); }
.agent-fab {
  position: fixed;
  inset-block-end: calc(var(--fab-gap) + env(safe-area-inset-bottom));
  inset-inline-end: calc(var(--fab-gap) + env(safe-area-inset-right));
  z-index: 40;
  display: grid;
  place-items: center;
  inline-size: var(--fab);
  block-size: var(--fab);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: var(--shadow-pop);
  cursor: pointer;
  transition: transform var(--dur) var(--ease-spring), background var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.agent-fab > .ci { --ci-size: 28px; transition: opacity var(--dur) var(--ease), scale var(--dur-slow) var(--ease-spring); }
@media (hover: hover) { .agent-fab:hover { transform: scale(1.06); background: var(--accent-hover); } }
.agent-fab:active { transform: scale(.96); }
.agent-fab:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
:root[data-theme^="contrast"] .agent-fab { box-shadow: none; outline: 2px solid var(--ink); outline-offset: 2px; }
/* The × while open: two strokes in the button's own ink, so the button still carries one icon. */
.agent-fab::before, .agent-fab::after {
  content: "";
  position: absolute;
  inline-size: 22px;
  block-size: 2.5px;
  border-radius: 2px;
  background: currentColor;
  opacity: 0;
  transition: opacity var(--dur) var(--ease), rotate var(--dur-slow) var(--ease-out);
}
.agent-fab[aria-expanded="true"] > .ci { opacity: 0; scale: .5; }
.agent-fab[aria-expanded="true"]::before { opacity: 1; rotate: 45deg; }
.agent-fab[aria-expanded="true"]::after { opacity: 1; rotate: -45deg; }
/* A greeting bubble, once per browser (agent/run.js decides), as a website's chat says hello. */
.agent-fab-hello {
  position: absolute;
  inset-block-end: calc(100% + var(--s1));
  inset-inline-end: 0;
  padding: 10px 14px;
  border-radius: 16px 16px 4px 16px;
  background: var(--paper-2);
  color: var(--ink);
  box-shadow: var(--shadow-pop);
  font-size: var(--t-1);
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  translate: 0 8px;
  pointer-events: none;
  transition: opacity var(--dur-slow) var(--ease), translate var(--dur-slow) var(--ease-out);
}
:root[dir="rtl"] .agent-fab-hello { border-radius: 16px 16px 16px 4px; }
.agent-fab[data-hello]:not([aria-expanded="true"]) .agent-fab-hello { opacity: 1; translate: none; }
/* A "show me" run moves a pointer over the page; the door steps aside while its bar is up. */
:root:has(.agent-bar:popover-open) .agent-fab { opacity: 0; pointer-events: none; }
/* Content scrolls clear of the door, so the last row of a page is never under it. */
.app:has(.agent-fab) .main { padding-block-end: calc(var(--fab) + var(--fab-gap) * 2); }
/* The corner is the door's, and nothing else that floats may cover it or be covered by it.
   --fab-clear is the height of its top edge above the bottom of the window. Toasts stand above
   it (they sit higher in the stack, so the door would vanish under the very message that may be
   about it), and a toast outranks the hello bubble that would share that spot. The save bar keeps
   its line beside the door where the page is wide, and stands above it on a phone, where the bar
   is as wide as the screen. */
:root { --fab-clear: calc(var(--fab-gap) + env(safe-area-inset-bottom) + var(--fab) + var(--s1)); }
:root:has(.agent-fab) .toasts { inset-block-end: var(--fab-clear); }
:root:has(.toasts > .toast) .agent-fab-hello { visibility: hidden; }
.app:has(.agent-fab) .savebar { margin-inline-end: calc(var(--fab) + var(--s1)); }
@media (max-width: 860px) {
  :root { --fab: 56px; --fab-gap: var(--s2); --fab-clear: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + var(--fab-gap) + var(--fab) + var(--s1)); }
  .agent-fab { inset-block-end: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + var(--fab-gap)); }
  .app:has(.agent-fab) .main { padding-block-end: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + var(--fab) + var(--fab-gap) * 2); }
  .app:has(.agent-fab) .savebar { margin-inline-end: 0; inset-block-end: var(--fab-clear); }
}
:root[data-motion="reduce"] :is(.agent-fab, .agent-fab > .ci, .agent-fab-hello) { transition: none; }
:root[data-motion="reduce"] .agent-fab::before, :root[data-motion="reduce"] .agent-fab::after { transition: none; }
@media (prefers-reduced-motion: reduce) {
  :is(.agent-fab, .agent-fab > .ci, .agent-fab-hello) { transition: none; }
  .agent-fab::before, .agent-fab::after { transition: none; }
}

/* ---------- The panel: a chat window standing on the door ---------- */
.agent {
  position: fixed;
  inset: auto calc(var(--fab-gap) + env(safe-area-inset-right)) calc(var(--fab-gap) + var(--fab) + var(--s1) + env(safe-area-inset-bottom)) auto;
  width: min(420px, calc(100vw - 24px));
  height: min(680px, calc(100dvh - var(--fab) - var(--fab-gap) * 2 - var(--s1) - var(--s2)));
  max-height: none;
  transform-origin: bottom right;
  margin: 0;
  padding: 0;
  border: var(--rule-w) solid var(--rule);
  border-radius: var(--radius-tile);
  background: var(--paper-2);
  color: var(--ink-2);
  box-shadow: var(--shadow-pop);
  overflow: hidden;
  flex-direction: column;
  opacity: 0;
  transform: translateY(12px) scale(.96);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease-out), overlay var(--dur-slow) allow-discrete, display var(--dur-slow) allow-discrete;
}
.agent:popover-open { display: flex; opacity: 1; transform: none; }
@starting-style { .agent:popover-open { opacity: 0; transform: translateY(12px) scale(.96); } }
:root[dir="rtl"] .agent { inset: auto auto calc(var(--fab-gap) + var(--fab) + var(--s1) + env(safe-area-inset-bottom)) calc(var(--fab-gap) + env(safe-area-inset-left)); transform-origin: bottom left; }
:root[dir="rtl"] .agent-fab { inset-inline-end: calc(var(--fab-gap) + env(safe-area-inset-left)); }
:root[data-theme^="contrast"] .agent { border: 2px solid var(--ink); }
@media (max-width: 640px) {
  .agent, :root[dir="rtl"] .agent {
    inset: auto 0 0;
    width: 100vw;
    height: min(88dvh, 760px);
    border-radius: 24px 24px 0 0;
    border-width: var(--rule-w) 0 0;
    transform: translateY(24px);
    padding-bottom: env(safe-area-inset-bottom);
  }
  /* The RTL selector above outranks a bare :popover-open, so the open state names it too. */
  .agent:popover-open, :root[dir="rtl"] .agent:popover-open { transform: none; }
  @starting-style { .agent:popover-open { opacity: 0; transform: translateY(24px); } }
}

/* ---------- Full screen: the chat fills the viewport ----------
   Still the same popover in the top layer (so Show me can fold it away and a
   modal can adopt it, layer.js); only its box changes. The header keeps the
   edges, and everything a person reads or types sits in one centred column
   of a comfortable measure, as a chat app does. `100%` in --agent-side is
   resolved where it is used — each child's padding — i.e. the panel's width.
   :is() lifts the selector over the phone sheet's RTL rule above. */
:is(:root, :root[dir="rtl"]) .agent[data-full] {
  --agent-measure: 760px;
  --agent-side: max(16px, calc((100% - var(--agent-measure)) / 2));
  inset: 0;
  width: auto;
  height: auto;
  border-width: 0;
  border-radius: 0;
  box-shadow: none;
  transform-origin: center;
  padding-block: env(safe-area-inset-top) env(safe-area-inset-bottom);
}
.agent[data-full] .agent-head { padding-inline: max(16px, env(safe-area-inset-left)) max(10px, env(safe-area-inset-right)); padding-block-end: 12px; border-block-end: var(--rule-w) solid var(--rule); }
.agent[data-full] .agent-modes { padding-block-start: 12px; }
.agent[data-full] :is(.agent-modes, .agent-log, .agent-note, .agent-convos) { padding-inline: var(--agent-side); }
.agent[data-full] .agent-compose { padding-inline: calc(var(--agent-side) - 4px); }
@media (min-width: 900px) { .agent[data-full] .agent-log { padding-block: 28px; gap: 14px; } }
:root[data-theme^="contrast"] .agent[data-full] { border: 0; }
/* The page under a full-screen chat does not scroll behind it; the gutter is stable (10-base.css), so nothing shifts. */
:root:has(.agent[data-full]:popover-open) { overflow: hidden; }

.agent-head { display: flex; align-items: center; gap: var(--s1); padding-block: 14px 10px; padding-inline: 16px 10px; }
.agent-mark { display: grid; place-items: center; width: 38px; height: 38px; flex: none; border-radius: 13px; background: var(--accent); color: var(--on-accent); }
.agent-mark .ci { --ci-size: 22px; }
.agent-title { flex: 1; min-width: 0; display: grid; line-height: 1.25; }
.agent-title :is(h2, small) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agent-title h2 { font-size: var(--t1); }
.agent-title small { color: var(--ink-3); font-size: var(--t-1); }
.agent-tools { display: flex; align-items: center; flex: none; }
.agent-tools .icon-btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
@media (hover: hover) { .agent-tools .icon-btn[aria-disabled="true"]:hover { background: transparent; color: var(--ink-2); } }
/* Four header buttons leave a narrow phone little room: the mark goes, the title keeps the space. */
@media (max-width: 420px) { .agent-mark { display: none; } .agent-head { padding-inline-start: 14px; } }

/* ---------- The list of conversations: a view that takes the chat's place ---------- */
.agent[data-view="list"] :is(.agent-modes, .agent-log, .agent-compose, .agent-note) { display: none; }
.agent-convos { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 10px; padding: 4px 12px 16px; overflow-y: auto; overscroll-behavior: contain; }
.agent-convos[hidden] { display: none; }
.agent-convos-body { flex: 1; display: flex; flex-direction: column; }
.agent-convos-head { display: flex; align-items: center; gap: var(--s0); padding-block-end: 4px; }
/* The arrow points back the way the reader's language reads. */
:root[dir="rtl"] .agent-convos-back .ci { scale: -1 1; }
.agent-convos-title { display: grid; min-width: 0; line-height: 1.3; }
.agent-convos-title h3 { font-size: var(--t1); color: var(--ink); }
.agent-convos-title h3:focus { outline: none; }
.agent-convos-title small { color: var(--ink-3); font-size: var(--t-1); }
.agent-convos-list { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; }
.agent-convo { display: flex; align-items: center; gap: 2px; min-width: 0; border-radius: 14px; }
.agent-convo-open {
  flex: 1;
  min-width: 0;
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr);
  column-gap: 12px;
  align-items: start;
  min-height: var(--target);
  padding: 10px 12px;
  border: 0;
  border-radius: 14px;
  background: transparent;
  color: var(--ink);
  text-align: start;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease);
}
.agent-convo-open > .ci { --ci-size: 20px; margin-block-start: 1px; color: var(--ink-3); }
@media (hover: hover) { .agent-convo-open:hover { background: var(--hover); } }
.agent-convo-open:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
.agent-convo-open[aria-current="true"] { background: var(--accent-soft); }
.agent-convo-open[aria-current="true"] > .ci { color: var(--accent-ink); }
:root[data-theme^="contrast"] .agent-convo-open[aria-current="true"] { outline: 2px solid var(--ink); outline-offset: -2px; }
.agent-convo-text { display: grid; min-width: 0; gap: 2px; }
.agent-convo-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.agent-convo-text small { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; color: var(--ink-3); font-size: var(--t-1); }
.agent-convo-now { padding-inline: 8px; border-radius: var(--radius-pill); background: var(--paper-2); color: var(--accent-ink); font-size: var(--t-2); font-weight: 700; line-height: 1.6; }
:root[data-theme^="contrast"] .agent-convo-now { outline: 1px solid var(--ink); }
.agent-convo[data-removed] { justify-content: space-between; flex-wrap: wrap; gap: var(--s0); min-height: var(--target); padding-block: 6px; padding-inline: 16px 6px; background: var(--field); color: var(--ink-2); font-size: var(--t-1); animation: dk-rise var(--dur-slow) var(--ease-out); }
.agent-convo[data-removed] p { min-width: 0; }
.agent-convos-empty { margin-block: auto; }
.agent-convos-empty h4 { font-size: var(--t2); color: var(--ink); }
@media (prefers-reduced-motion: reduce) { .agent-convo[data-removed] { animation: none; } }
:root[data-motion="reduce"] .agent-convo[data-removed] { animation: none; }

.agent-modes { display: grid; gap: 6px; padding: 0 16px 12px; border-bottom: var(--rule-w) solid var(--rule); }
.agent-modes .segmented { display: grid; grid-template-columns: 1fr 1fr; }
.agent-modes .segmented span { justify-content: center; width: 100%; }
.agent-modes .segmented .ci { --ci-size: 16px; }
.agent-mode-hint { color: var(--ink-3); font-size: var(--t-1); }

.agent-log {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.agent-msg { max-width: 92%; line-height: 1.5; overflow-wrap: anywhere; }
.agent-msg > * + * { margin-top: 8px; }
.agent-msg :is(ul, ol) { padding-inline-start: 20px; }
.agent-msg code { padding: 1px 5px; border-radius: 6px; background: var(--field); font-size: .92em; }
.agent-msg[data-from="you"] {
  align-self: flex-end;
  padding: 10px 14px;
  border-radius: 18px;
  border-end-end-radius: 6px;
  background: var(--accent-soft);
  color: var(--ink);
}
:root[data-theme^="contrast"] .agent-msg[data-from="you"] { outline: 2px solid var(--ink); }
.agent-msg[data-from="ai"] { align-self: flex-start; color: var(--ink); }

.agent-step {
  display: grid;
  grid-template-columns: 20px 1fr;
  column-gap: 10px;
  align-items: start;
  padding: 8px 12px;
  border-radius: 12px;
  background: var(--field);
  color: var(--ink-2);
  font-size: var(--t-1);
  font-weight: 600;
}
.agent-step .ci { --ci-size: 18px; color: var(--ink-3); margin-top: 1px; }
.agent-step small { grid-column: 2; color: var(--ink-3); font-weight: 500; }
.agent-step[data-state="run"] .ci { color: var(--accent-ink); animation: dk-spin .9s linear infinite; }
.agent-step[data-state="ok"] .ci { color: var(--ok); }
.agent-step[data-state="bad"] { background: color-mix(in oklab, var(--bad) 9%, var(--paper-2)); }
.agent-step[data-state="bad"] .ci, .agent-step[data-state="bad"] small { color: var(--bad); }
.agent-step[data-state="wait"] .ci { color: var(--warn); }
.agent-step[data-state="skip"] { opacity: .75; }
.agent-step + .agent-step { margin-top: -6px; }

.agent-ask, .agent-bar-ask { display: grid; gap: 10px; }
.agent-ask { padding: 12px 14px; border-radius: 14px; border: var(--rule-w) solid color-mix(in oklab, var(--warn) 45%, transparent); background: color-mix(in oklab, var(--warn) 8%, var(--paper-2)); color: var(--ink); animation: dk-rise var(--dur-slow) var(--ease-out); }
.agent-ask span { color: var(--ink-3); }
.agent-ask-actions { display: flex; flex-wrap: wrap; gap: var(--s0); }

.agent-think { display: flex; gap: 5px; padding: 6px 2px; }
.agent-think span { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-3); animation: dk-think 1.2s var(--ease) infinite; }
.agent-think span:nth-child(2) { animation-delay: .15s; }
.agent-think span:nth-child(3) { animation-delay: .3s; }
@keyframes dk-think { 0%, 70%, 100% { opacity: .35; transform: none; } 35% { opacity: 1; transform: translateY(-3px); } }

.agent-empty { display: grid; justify-items: start; gap: 8px; margin-block: auto; padding: 8px 4px; }
.agent-empty h3 { font-size: var(--t2); color: var(--ink); }
.agent-empty p { color: var(--ink-2); }
.agent-empty-mark { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 14px; background: var(--accent-soft); color: var(--accent-ink); }
.agent-empty-mark .ci { --ci-size: 24px; }
.agent-suggest { display: grid; gap: 6px; width: 100%; margin-top: 6px; }
.agent-suggest .btn { justify-content: flex-start; width: 100%; white-space: normal; text-align: start; min-height: 40px; padding-block: 8px; }
.agent-suggest .btn span { min-width: 0; }

.agent-compose { display: flex; align-items: flex-end; gap: 8px; padding: 12px 12px 6px; border-top: var(--rule-w) solid var(--rule); }
.agent-input { flex: 1; min-height: 44px; max-height: 160px; padding-block: 11px; resize: none; line-height: 1.4; }
.agent-send {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--on-accent);
  transition: background-color var(--dur) var(--ease), transform var(--dur) var(--ease-spring);
}
.agent-send .ci { --ci-size: 20px; }
@media (hover: hover) { .agent-send:hover { background: var(--accent-hover); } }
.agent-send:active { transform: scale(.94); }
.agent[data-busy] .agent-send:not([data-steer]) { background: var(--ink); color: var(--paper-2); }
.agent-note { padding: 0 16px 12px; color: var(--ink-3); font-size: var(--t-2); }

/* ---------- The run bar: a "show me" run folds the panel into this ---------- */
.agent-bar {
  position: fixed;
  inset: auto auto 20px 50%;
  translate: -50% 0;
  width: min(560px, calc(100vw - 24px));
  height: auto;
  margin: 0;
  padding-block: 6px;
  padding-inline: 16px 6px;
  border: 0;
  border-radius: 26px;
  background: var(--inverse);
  color: var(--on-inverse);
  box-shadow: var(--shadow-pop);
  flex-wrap: nowrap;
  align-items: center;
  gap: 4px 10px;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease-out), overlay var(--dur-slow) allow-discrete, display var(--dur-slow) allow-discrete;
}
.agent-bar:popover-open { display: flex; opacity: 1; transform: none; }
@starting-style { .agent-bar:popover-open { opacity: 0; transform: translateY(12px); } }
:root[data-theme^="contrast"] .agent-bar { outline: 2px solid var(--on-inverse); }
@media (max-width: 860px) { .agent-bar { inset-block-end: calc(var(--tabbar-h) + env(safe-area-inset-bottom) + 10px); } }
.agent-bar-dot { width: 10px; height: 10px; flex: none; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 60%, transparent); animation: dk-beacon 1.6s var(--ease) infinite; }
.agent-bar[data-paused] .agent-bar-dot { animation: none; background: var(--warn); }
@keyframes dk-beacon { 70% { box-shadow: 0 0 0 9px transparent; } }
.agent-bar-text { flex: 1 1 200px; min-width: 0; font-weight: 600; font-size: var(--t-1); line-height: 1.35; padding-block: 8px; }
.agent-bar-text b { opacity: .7; font-weight: 700; margin-inline-end: 4px; }
.agent-bar .icon-btn { color: inherit; width: 40px; height: 40px; }
@media (hover: hover) { .agent-bar .icon-btn:hover { background: color-mix(in oklab, var(--on-inverse) 14%, transparent); } }
.agent-bar-ask { flex: 1 1 240px; min-width: 0; padding-block: 6px; font-size: var(--t-1); }
.agent-bar[data-asking] { flex-wrap: wrap; }
.agent-bar-ask span { opacity: .75; }
.agent-bar-ask .btn:not(.btn-primary) { --btn-bg: transparent; --btn-fg: var(--on-inverse); --btn-edge: color-mix(in oklab, var(--on-inverse) 40%, transparent); }
.agent-bar[data-asking] .agent-bar-text { display: none; }

/* ---------- Hands-free (agent/voice.js) ----------
   The microphone sits beside Send; while it is on, a strip above the field
   says what the assistant is waiting for and shows the room's loudness, the
   run bar carries a live microphone (its press turns voice off), and the door
   wears a slow ring, so an open microphone is never invisible. */
.agent-mic {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--field);
  color: var(--ink-2);
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease-spring);
}
.agent-mic[hidden] { display: none; }
.agent-mic .ci { --ci-size: 20px; }
@media (hover: hover) { .agent-mic:hover { background: var(--hover); color: var(--ink); } }
.agent-mic:active { transform: scale(.94); }
.agent-mic:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.agent-mic[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-ink); box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 50%, transparent); animation: dk-beacon 1.8s var(--ease) infinite; }
:root[data-theme^="contrast"] .agent-mic[aria-pressed="true"] { outline: 2px solid var(--ink); animation: none; }

.agent-voice { display: flex; align-items: center; gap: 12px; padding: 10px 16px; border-top: var(--rule-w) solid var(--rule); background: color-mix(in oklab, var(--accent) 6%, var(--paper-2)); color: var(--ink); }
.agent-voice[hidden] { display: none; }
.agent-voice[data-state="asking"] { background: color-mix(in oklab, var(--warn) 10%, var(--paper-2)); }
.agent-voice-text { flex: 1; min-width: 0; font-size: var(--t-1); font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.agent-voice .btn { flex: none; }
.agent-voice .btn[hidden] { display: none; }
/* Five bars that follow --level (0..1, set per frame by the recording ear; still for the on-device one, which gives no level). */
.agent-voice-meter { --level: 0; display: flex; align-items: center; gap: 3px; height: 22px; flex: none; }
.agent-voice-meter i { width: 3px; height: 100%; border-radius: 2px; background: var(--accent); transform-origin: center; transform: scaleY(calc(.18 + var(--level) * .82)); transition: transform 90ms linear; }
.agent-voice-meter i:nth-child(2), .agent-voice-meter i:nth-child(4) { transform: scaleY(calc(.18 + var(--level) * .6)); }
.agent-voice-meter i:nth-child(1), .agent-voice-meter i:nth-child(5) { transform: scaleY(calc(.18 + var(--level) * .35)); }
.agent-voice[data-state="idle"] .agent-voice-meter i { background: var(--ink-3); }
.agent-voice[data-state="asking"] .agent-voice-meter i { background: var(--warn); }
/* Speaking and working have no level to show: the bars move by themselves instead. */
.agent-voice:is([data-state="speaking"], [data-state="running"]) .agent-voice-meter i { animation: dk-voice 1s var(--ease) infinite; }
/* Waiting for the person's words: a slow breath, so an open microphone reads as live even with no level to show. */
.agent-voice[data-state="open"] .agent-voice-meter i { animation: dk-voice 2.2s var(--ease) infinite; }
.agent-voice-meter i:nth-child(2) { animation-delay: .12s; }
.agent-voice-meter i:nth-child(3) { animation-delay: .24s; }
.agent-voice-meter i:nth-child(4) { animation-delay: .36s; }
.agent-voice-meter i:nth-child(5) { animation-delay: .48s; }
@keyframes dk-voice { 0%, 100% { transform: scaleY(.25); } 50% { transform: scaleY(.95); } }
.agent[data-full] .agent-voice { padding-inline: var(--agent-side); }
.agent[data-view="list"] .agent-voice { display: none; }

.agent-msg[data-from="you"][data-voice] { display: flex; gap: 8px; align-items: flex-start; }
.agent-msg-mic { flex: none; color: var(--accent-ink); }
.agent-msg-mic .ci { --ci-size: 16px; margin-block-start: 3px; }

.agent-bar-mic { display: none; }
.agent-bar[data-voice] .agent-bar-mic { display: grid; place-items: center; }

:root[data-agent-listening] .agent-fab { animation: dk-listen 2.4s var(--ease) infinite; }
@keyframes dk-listen {
  0%, 100% { box-shadow: var(--shadow-pop), 0 0 0 0 color-mix(in oklab, var(--accent) 45%, transparent); }
  60% { box-shadow: var(--shadow-pop), 0 0 0 12px transparent; }
}
:root[data-theme^="contrast"][data-agent-listening] .agent-fab { animation: none; outline-width: 4px; }

:root[data-motion="reduce"] :is(.agent-mic, .agent-voice-meter i, .agent-fab) { animation: none; }
@media (prefers-reduced-motion: reduce) {
  :is(.agent-mic, .agent-voice-meter i) { animation: none; }
  :root[data-agent-listening] .agent-fab { animation: none; }
}

/* ---------- On the page during a "show me" run ---------- */
.agent-cursor {
  position: fixed;
  inset: 0 auto auto 0;
  width: 28px;
  height: 28px;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  overflow: visible;
  pointer-events: none;
  translate: -5px -3px;
  transition: transform 620ms var(--ease-out);
}
.agent-cursor svg { width: 28px; height: 28px; overflow: visible; filter: drop-shadow(0 2px 3px rgb(0 0 0 / .35)); }
.agent-cursor path { fill: var(--accent); stroke: var(--paper-2); stroke-width: 1.6; stroke-linejoin: round; }
:root[data-theme^="contrast"] .agent-cursor path { fill: var(--ink); stroke: var(--paper); stroke-width: 2.2; }
.agent-cursor::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 34px;
  height: 34px;
  margin: -12px 0 0 -12px;
  border-radius: 50%;
  border: 2px solid var(--accent);
  opacity: 0;
}
.agent-cursor[data-click]::after { animation: dk-tap 420ms var(--ease-out); }
.agent-cursor[data-click] svg { scale: .88; transition: scale 120ms var(--ease); }
@keyframes dk-tap { from { opacity: 1; scale: .3; } to { opacity: 0; scale: 1.4; } }

.agent-ring {
  position: fixed;
  margin: 0;
  padding: 0;
  border: 0;
  inset: auto;
  background: color-mix(in oklab, var(--accent) 8%, transparent);
  border-radius: 12px;
  box-shadow: 0 0 0 2px var(--accent), 0 0 0 7px color-mix(in oklab, var(--accent) 22%, transparent);
  pointer-events: none;
  transition: left 300ms var(--ease-out), top 300ms var(--ease-out), width 300ms var(--ease-out), height 300ms var(--ease-out), opacity var(--dur) var(--ease);
}
.agent-ring[data-flash] { animation: dk-flash 500ms var(--ease) both; }
@keyframes dk-flash { from { opacity: 1; } to { opacity: 0; } }
:root[data-theme^="contrast"] .agent-ring { box-shadow: 0 0 0 3px var(--ink), 0 0 0 6px var(--paper); background: none; }

.agent-say {
  position: fixed;
  inset: auto;
  max-width: min(300px, calc(100vw - 24px));
  height: auto;
  margin: 0;
  padding: 9px 13px;
  border: 0;
  border-radius: 14px;
  background: var(--inverse);
  color: var(--on-inverse);
  font-size: var(--t-1);
  font-weight: 650;
  line-height: 1.35;
  box-shadow: var(--shadow-pop);
  pointer-events: none;
  animation: dk-rise var(--dur-slow) var(--ease-out);
}

@media (prefers-reduced-motion: reduce) {
  .agent-cursor, .agent-ring { transition: none; }
  .agent-bar-dot, .agent-think span { animation: none; }
}


/* ---- 90-art.css ---- */
/* ---------- Art: one drawing from the product's kit (kit/js/art.js) ----------
   The website's treatment, so the two read as one product: the drawing toned
   to the brand ramp and set on a soft disc of the accent, full colour as the
   reveal. --slot-0 / --slot-2 are the names artwork-parallax's kits read. */

dk-art {
  --art-size: 168px;
  --slot-0: var(--art-1);
  --slot-1: var(--art-3);
  --slot-2: var(--art-2);
  /* Andy's navy and plum: lifted by the dark themes (00-tokens.css). */
  --andy-ink: var(--art-ink);
  --andy-ink-2: var(--art-ink-2);
  /* Blues' black line work, and the pale blue its spot shapes show before the
     tide fills them: the pack's own pale blue is a light-ground tint that glares on a
     dark page, so it is mixed from the brand's light stop and the page instead. */
  --blues-ink: var(--art-ink);
  --blues-empty: color-mix(in oklab, var(--art-2) 24%, var(--paper));
  /* Activities (castoMIND) paints its brush outline in var(--activities-ink,
     black) and its white in var(--activities-paper, white): undeclared, the
     outline stays black on a dark page (GUIDELINES §7b). Both follow the mode
     through tokens that already change with it: the lifted ink, and the card's
     own surface — white in light, and dark paper under light line work in
     dark, the inversion artwork-parallax's art-ink.js makes on a dark ground. */
  --activities-ink: var(--art-ink);
  --activities-paper: var(--paper-2);
  /* Minimalistic's ink and paper (00-tokens.css). They outrank the element's own
     guess from the ground behind it (artwork-parallax js/art-ink.js), so a
     drawing on the accent disc reads the same as one on the bare card. */
  --minimalistic-ink: var(--art-pen);
  --minimalistic-paper: var(--art-sheet);
  --hipster-tone: 1;
  --hipster-placeholder: transparent;
  position: relative;
  display: block;
  flex: none;
  inline-size: var(--art-size);
  max-inline-size: 100%;
  aspect-ratio: 1;
}
/* Blues fills its one spot colour from --slot-0. The pack's spot is a bright sky
   blue, so it takes the ramp's light stop (--art-2): the dark first stop, which
   suits a toned raster, sinks into a dark page as a navy nobody sees. */
:root[data-art="blues"] dk-art { --slot-0: var(--art-2); }
dk-art[size="sm"] { --art-size: 96px; }
dk-art[size="lg"] { --art-size: 240px; }
dk-art[size="hero"] { --art-size: min(100%, 400px); }

/* Minimalistic paints its accents through --slot-0/1/2 as Andy does, but from
   its own marks (00-tokens.css), which high-contrast dark turns round. */
dk-art minimalistic-art {
  --slot-0: var(--art-mark-1);
  --slot-1: var(--art-mark-2);
  --slot-2: var(--art-mark-3);
}

/* Noodle (castomAI) is black line over flat colour blocks. The line reads
   --noodle-stroke and the pack's white fills --noodle-fill (artwork-parallax
   js/noodle/noodle-art.js), so both follow the mode as Minimalistic's pen and
   sheet do: dark line on the light card, light line on the dark one, black and
   white in high contrast. The blocks are its three ramp stops through the same
   marks Minimalistic paints with (00-tokens.css). Slots are set by rule and
   never by inline style: the element clears --slot-0/1/2 from its own style
   attribute when it has no `brand`. */
dk-art {
  --noodle-stroke: var(--art-pen);
  --noodle-fill: var(--art-sheet);
}
dk-art noodle-art {
  --slot-0: var(--art-mark-1);
  --slot-1: var(--art-mark-2);
  --slot-2: var(--art-mark-3);
}

/* No kit, or nothing to draw: the element takes no room and the icon beside it stays. */
:root:not([data-art]) dk-art,
dk-art:not([data-on]) { display: none; }
dk-art[data-on] + .empty-art { display: none; }

dk-art::before {
  content: "";
  position: absolute;
  inset: 9%;
  border-radius: 50%;
  background: var(--accent-soft);
}
dk-art[plain]::before { content: none; }

dk-art > * {
  position: relative;
  inline-size: 100%;
  opacity: 0;
  transform: translateY(10px) scale(.98);
  transition: opacity var(--dur-slow) var(--ease-out), transform 700ms var(--ease-out);
}
dk-art > [loaded] { opacity: 1; transform: none; }
/* The big picture breathes; `translate` so it never fights the rise above. */
dk-art[size="hero"] > [loaded] { animation: dk-art-float 7s ease-in-out 1s infinite; }
@keyframes dk-art-float { 50% { translate: 0 -6px; } }

/* Toned is the house look; colour is the reveal, as on the website. A touch
   screen has no hover to reveal with, so it shows the colour from the start. */
@media (hover: hover) {
  .card:hover dk-art,
  a:hover dk-art,
  dk-art:hover { --hipster-tone: 0; }
}
@media (hover: none) {
  dk-art { --hipster-tone: 0; }
}
:root[data-theme^="contrast"] dk-art { --hipster-tone: 1; }
:root[data-theme^="contrast"] dk-art::before { background: none; }

:root[data-motion="reduce"] dk-art > * { transition: none; animation: none; transform: none; }
@media (prefers-reduced-motion: reduce) {
  dk-art > * { transition: none; animation: none; transform: none; }
}

/* A picture in an empty state stands where the icon tile stood. */
.empty dk-art { margin-bottom: var(--s0); }

/* ---------- Andy's loose props (castomo's kit) ----------
   A big Andy picture comes apart into the character, the ground and one plane
   per loose prop (kit/js/art.js sets layers="props"): coins, a trophy, speech
   bubbles. They drift with the pointer further than the character, bob on
   their own rhythm (the kit's `float`), and scatter outward on a cheer — the
   "elements" castomo.com moves the same way. */
dk-art[data-cheer] andy-art::part(prop) {
  animation: dk-art-scatter 820ms var(--ease-out) both;
  animation-delay: calc(var(--k, 0) * 60ms);
}
@keyframes dk-art-scatter {
  35% { translate: calc(var(--cx, 0) * 22px) calc(var(--cy, 0) * 22px - 10px); rotate: calc((var(--r, .5) - .5) * 30deg); }
  100% { translate: 0 0; rotate: 0deg; }
}
:root[data-motion="reduce"] andy-art::part(prop) { animation: none; }
@media (prefers-reduced-motion: reduce) {
  andy-art::part(prop) { animation: none; }
}

/* ---------- The page drawing (page-art.js, GUIDELINES §5a) ----------
   Every page's heading carries one, at the end of the line, drawn over the
   heading's own height rather than adding to it. It breathes, drifts with the
   pointer (the kit's parallax), turns to colour under the hand, and hops when
   the person gets something done (dk:cheer). */
dk-art[size="page"] { --art-size: 124px; }
.page-head.has-art { position: relative; }
.page-head > dk-art.page-art {
  order: 99;
  align-self: center;
  margin-block: calc(var(--s2) * -1);
  cursor: default;
}
dk-art.page-art > [loaded] { animation: dk-art-float 6s ease-in-out 1.2s infinite; }
dk-art[data-cheer] > [loaded] { animation: dk-art-hop 820ms var(--ease-out) both; }
dk-art[data-cheer]::before { animation: dk-art-pulse 820ms var(--ease-out) both; }
@keyframes dk-art-hop {
  0% { transform: none; }
  30% { transform: translateY(-14px) rotate(-4deg) scale(1.05); }
  55% { transform: translateY(0) rotate(3deg) scale(.98); }
  75% { transform: translateY(-5px) rotate(-1deg); }
  100% { transform: none; }
}
@keyframes dk-art-pulse {
  40% { scale: 1.12; background: color-mix(in oklab, var(--accent) 30%, var(--accent-soft)); }
}
/* A phone keeps the drawing, smaller, beside the title (nothing is lost on a phone, §0.4). */
@media (max-width: 860px) {
  dk-art[size="page"] { --art-size: 76px; }
  .page-head.has-art > :first-child { padding-inline-end: 84px; }
  .page-head > dk-art.page-art { position: absolute; inset-block-start: 0; inset-inline-end: 0; margin: 0; }
}
:root[data-motion="reduce"] dk-art:is(.page-art, [data-cheer]) > *,
:root[data-motion="reduce"] dk-art[data-cheer]::before { animation: none; }
@media (prefers-reduced-motion: reduce) {
  dk-art:is(.page-art, [data-cheer]) > *, dk-art[data-cheer]::before { animation: none; }
}
