/* @zyxworks/ui 0.2.2 (build b45451696a4f), brand "zyx". Built by scripts/build.mjs: do not edit, change tokens/zyx/ or css/. */
@layer zyx-tokens, zyx-base, zyx-components;

@layer zyx-tokens {
/* -------------------------------------------
 *  Autogenerated by ⛋ Terrazzo. DO NOT EDIT!
 * ------------------------------------------- */

:root,
[data-theme="light"] {
  color-scheme: light;
--z-bad: #b3261e;
  --z-bad-soft: #fbe9e7;
  --z-bevel: none;
  --z-block-travel: 4px;
  --z-brand: #111;
  --z-bw: 2px;
  --z-bw-block: 3px;
  --z-bw-hair: 1px;
  --z-bw-rule: 2px;
  --z-chrome: #fff;
  /* Founder, 2026-10-14: the main button does not move under the pointer (`--z-cta-travel` is 0). Moved 5px down it stood lower than the button next to it. Its yellow shadow goes, it turns yellow and is pressed in with the same ink inner shadow as every other control. */
  --z-cta-travel: 0px;
  --z-ctl: #8a8a8a;
  /* The panels of the Zyx mark: Zyx yellow in light and dark and on every install. A white-label colour replaces the signal, never this. */
  --z-cube: #ffd23c;
  /* One round of the one loop (`zyx-loading`, three squares one after the other). */
  --z-d-loop: 900ms;
  --z-d-press: 120ms;
  /* The stagger between small parts that move one after the other (the icons of a row hop in turn). */
  --z-d-step: 60ms;
  --z-d1: 180ms;
  --z-d2: 200ms;
  --z-d3: 280ms;
  --z-dt: -0.022em;
  --z-dw: 700;
  --z-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-edge: #111;
  --z-faint: #666;
  --z-field: #fff;
  /* Focus is ink, never the signal: the signal means "act here", focus means "you are here". */
  --z-focus: #111;
  --z-font-display: "Atkinson Hyperlegible Next", "Verdana", system-ui, sans-serif;
  --z-font-mono: "Atkinson Hyperlegible Mono", ui-monospace, "Menlo", monospace;
  --z-font-text: "Atkinson Hyperlegible Next", "Verdana", system-ui, sans-serif;
  --z-ground: #f4f4f4;
  --z-hero-travel: 6px;
  --z-hw: 700;
  --z-icon-fill: #ffd23c;
  --z-ink: #111;
  --z-label-case: none;
  --z-label-font: "Atkinson Hyperlegible Next", "Verdana", system-ui, sans-serif;
  --z-label-size: 12.5px;
  --z-label-track: 0em;
  --z-label-weight: 700;
  --z-lead: 1.55;
  --z-lead-display: 1.04;
  --z-lead-heading: 1.15;
  --z-line: #dcdcdc;
  --z-line-strong: #bbb;
  /* The box behind the mark: clear in light, white in dark, so the ink lines stay seen. */
  --z-mark-box: #fff0;
  /* The lines of the mark: ink on every ground. */
  --z-mark-line: #111;
  /* The white box a mark sits in on an ink or dark ground (an ink cell, a dark scope): white in both themes, so the lines stay ink. */
  --z-mark-paper: #fff;
  /* The small mono label: a column head, a count, a label over a pop-up. Below `small`. */
  --z-micro: 11px;
  --z-muted: #444;
  --z-ok: #2f6b3a;
  --z-ok-soft: #e4f1e6;
  --z-on-brand: #f4f4f4;
  --z-on-chrome: #111;
  --z-on-signal: #14130f;
  --z-prose: 720px;
  --z-r-card: 0px;
  --z-r-chip: 0px;
  --z-r-ctl: 0px;
  --z-r-win: 0px;
  --z-raised: #ededed;
  --z-row: 42px;
  /* The big button of a marketing page (`zyx-btn-lg`): 48px, a thumb's height. A tool screen keeps `row` (42px). */
  --z-row-lg: 48px;
  /* Founder, 2026-10-15: the third button (tertiary) is a small press inside a line of text (Undo, Trust what it read, Go on, Show earlier). A 42 px control stood in a 12 px line like a second screen. Square, 1 px ink edge, small words, the same one hover (pressed in). */
  --z-row-sm: 28px;
  --z-s1: 5px;
  --z-s2: 10px;
  --z-s3: 15px;
  --z-s4: 20px;
  --z-s5: 30px;
  --z-s6: 40px;
  --z-s7: 60px;
  --z-s8: 80px;
  --z-shadow-bar: inset 3px 0px var(--z-ink);
  --z-shadow-block: var(--z-block-travel) var(--z-block-travel) var(--z-ink);
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-shadow-card: 3px 3px var(--z-edge);
  --z-shadow-card-far: 5px 5px var(--z-ink);
  --z-shadow-cta: inset 0px 0px var(--z-on-signal), 5px 5px var(--z-signal);
  --z-shadow-cta-deep: inset 5px 5px var(--z-on-signal), 0px 0px var(--z-signal);
  --z-shadow-cta-down: inset 3px 3px var(--z-on-signal), 0px 0px var(--z-signal);
  /* One colour, one meaning: this needs a human, act here. The approve button, the dot that leads to one, the count of what waits. Never a chip, a badge, a border or a status. One exception (founder decision 2026-10-13): the small solid shadow under the main ink button is yellow. Yellow never fills a large area. */
  --z-shadow-cta-near: 2px 2px var(--z-signal);
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-shadow-drop: 3px 3px var(--z-edge);
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-shadow-drop-near: 1px 1px var(--z-edge);
  --z-shadow-focus: 3px 3px var(--z-ink);
  --z-shadow-hero: var(--z-hero-travel) var(--z-hero-travel) var(--z-ink);
  --z-shadow-in: inset 3px 3px var(--z-ink);
  --z-shadow-in-bad: inset 3px 3px var(--z-bad);
  --z-shadow-in-bad-deep: inset 5px 5px var(--z-bad);
  --z-shadow-in-deep: inset 5px 5px var(--z-ink);
  --z-shadow-in-signal: inset 3px 3px var(--z-on-signal);
  --z-shadow-in-signal-deep: inset 5px 5px var(--z-on-signal);
  --z-shadow-in-sm: inset 2px 2px var(--z-ink);
  --z-shadow-in-sm-deep: inset 3px 3px var(--z-ink);
  --z-shadow-key: 0px 2px var(--z-ink);
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-shadow-near: 2px 2px var(--z-edge);
  --z-shadow-pop: 3px 3px var(--z-ink);
  --z-shadow-win: 0px 0px 0px 1px #000000e6, 10px 10px #0000001a;
  /* The widest a page column gets (1180px), the side gutters included. */
  --z-shell: 73.75rem;
  /* One colour, one meaning: this needs a human, act here. The approve button, the dot that leads to one, the count of what waits. Never a chip, a badge, a border or a status. One exception (founder decision 2026-10-13): the small solid shadow under the main ink button is yellow. Yellow never fills a large area. */
  --z-signal: #ffd23c;
  --z-signal-edge: #9a7400;
  --z-signal-mark: #7a5800;
  --z-signal-soft: #fff2c4;
  --z-small: 12.5px;
  --z-stamp: none;
  --z-sunken: #e7e7e7;
  --z-surface: #fff;
  --z-text: 15px;
  --z-u: 5px;
  --z-wm-case: none;
  --z-wm-font: "Atkinson Hyperlegible Next", "Verdana", system-ui, sans-serif;
  --z-wm-track: -0.025em;
  --z-wm-weight: 700;
}

[data-theme="dark"] {
  color-scheme: dark;
--z-bad: #f08a7a;
  --z-bad-soft: #2e1714;
  --z-bevel: none;
  --z-brand: #f2f2f2;
  --z-chrome: #151515;
  --z-ctl: #6e6e6e;
  /* The panels of the Zyx mark: Zyx yellow in light and dark and on every install. A white-label colour replaces the signal, never this. */
  --z-cube: #ffd23c;
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-edge: #404040;
  --z-faint: #8f8f8f;
  --z-field: #101010;
  /* Focus is ink, never the signal: the signal means "act here", focus means "you are here". */
  --z-focus: #f2f2f2;
  --z-ground: #0d0d0d;
  --z-icon-fill: #ffd23c;
  --z-ink: #f2f2f2;
  --z-line: #2a2a2a;
  --z-line-strong: #404040;
  /* The box behind the mark: clear in light, white in dark, so the ink lines stay seen. */
  --z-mark-box: #fff;
  /* The lines of the mark: ink on every ground. */
  --z-mark-line: #111;
  /* The white box a mark sits in on an ink or dark ground (an ink cell, a dark scope): white in both themes, so the lines stay ink. */
  --z-mark-paper: #fff;
  --z-muted: #b3b3b3;
  --z-ok: #86c994;
  --z-ok-soft: #16281a;
  --z-on-brand: #0d0d0d;
  --z-on-chrome: #f2f2f2;
  --z-on-signal: #14130f;
  --z-raised: #1e1e1e;
  --z-shadow-bar: inset 3px 0px var(--z-ink);
  --z-shadow-block: var(--z-block-travel) var(--z-block-travel) var(--z-ink);
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-shadow-card: 3px 3px var(--z-edge);
  --z-shadow-card-far: 5px 5px var(--z-ink);
  --z-shadow-cta: inset 0px 0px var(--z-on-signal), 5px 5px var(--z-signal);
  --z-shadow-cta-deep: inset 5px 5px var(--z-on-signal), 0px 0px var(--z-signal);
  --z-shadow-cta-down: inset 3px 3px var(--z-on-signal), 0px 0px var(--z-signal);
  /* One colour, one meaning: this needs a human, act here. The approve button, the dot that leads to one, the count of what waits. Never a chip, a badge, a border or a status. One exception (founder decision 2026-10-13): the small solid shadow under the main ink button is yellow. Yellow never fills a large area. */
  --z-shadow-cta-near: 2px 2px var(--z-signal);
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-shadow-drop: 3px 3px var(--z-edge);
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-shadow-drop-near: 1px 1px var(--z-edge);
  --z-shadow-focus: 3px 3px var(--z-ink);
  --z-shadow-hero: var(--z-hero-travel) var(--z-hero-travel) var(--z-ink);
  --z-shadow-in: inset 3px 3px var(--z-ink);
  --z-shadow-in-bad: inset 3px 3px var(--z-bad);
  --z-shadow-in-bad-deep: inset 5px 5px var(--z-bad);
  --z-shadow-in-deep: inset 5px 5px var(--z-ink);
  --z-shadow-in-signal: inset 3px 3px var(--z-on-signal);
  --z-shadow-in-signal-deep: inset 5px 5px var(--z-on-signal);
  --z-shadow-in-sm: inset 2px 2px var(--z-ink);
  --z-shadow-in-sm-deep: inset 3px 3px var(--z-ink);
  --z-shadow-key: 0px 2px var(--z-ink);
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-shadow-near: 2px 2px var(--z-edge);
  --z-shadow-pop: 3px 3px var(--z-ink);
  --z-shadow-win: 0px 0px 0px 1px #000000e6, 10px 10px #0000001a;
  /* One colour, one meaning: this needs a human, act here. The approve button, the dot that leads to one, the count of what waits. Never a chip, a badge, a border or a status. One exception (founder decision 2026-10-13): the small solid shadow under the main ink button is yellow. Yellow never fills a large area. */
  --z-signal: #ffd23c;
  --z-signal-edge: #0000;
  --z-signal-mark: #ffd23c;
  --z-signal-soft: #3a3010;
  --z-stamp: none;
  --z-sunken: #0a0a0a;
  --z-surface: #151515;
}

@media (prefers-color-scheme: dark) {
  [data-theme="system"] {
    color-scheme: dark;
--z-bad: #f08a7a;
  --z-bad-soft: #2e1714;
  --z-bevel: none;
  --z-brand: #f2f2f2;
  --z-chrome: #151515;
  --z-ctl: #6e6e6e;
  /* The panels of the Zyx mark: Zyx yellow in light and dark and on every install. A white-label colour replaces the signal, never this. */
  --z-cube: #ffd23c;
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-edge: #404040;
  --z-faint: #8f8f8f;
  --z-field: #101010;
  /* Focus is ink, never the signal: the signal means "act here", focus means "you are here". */
  --z-focus: #f2f2f2;
  --z-ground: #0d0d0d;
  --z-icon-fill: #ffd23c;
  --z-ink: #f2f2f2;
  --z-line: #2a2a2a;
  --z-line-strong: #404040;
  /* The box behind the mark: clear in light, white in dark, so the ink lines stay seen. */
  --z-mark-box: #fff;
  /* The lines of the mark: ink on every ground. */
  --z-mark-line: #111;
  /* The white box a mark sits in on an ink or dark ground (an ink cell, a dark scope): white in both themes, so the lines stay ink. */
  --z-mark-paper: #fff;
  --z-muted: #b3b3b3;
  --z-ok: #86c994;
  --z-ok-soft: #16281a;
  --z-on-brand: #0d0d0d;
  --z-on-chrome: #f2f2f2;
  --z-on-signal: #14130f;
  --z-raised: #1e1e1e;
  --z-shadow-bar: inset 3px 0px var(--z-ink);
  --z-shadow-block: var(--z-block-travel) var(--z-block-travel) var(--z-ink);
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-shadow-card: 3px 3px var(--z-edge);
  --z-shadow-card-far: 5px 5px var(--z-ink);
  --z-shadow-cta: inset 0px 0px var(--z-on-signal), 5px 5px var(--z-signal);
  --z-shadow-cta-deep: inset 5px 5px var(--z-on-signal), 0px 0px var(--z-signal);
  --z-shadow-cta-down: inset 3px 3px var(--z-on-signal), 0px 0px var(--z-signal);
  /* One colour, one meaning: this needs a human, act here. The approve button, the dot that leads to one, the count of what waits. Never a chip, a badge, a border or a status. One exception (founder decision 2026-10-13): the small solid shadow under the main ink button is yellow. Yellow never fills a large area. */
  --z-shadow-cta-near: 2px 2px var(--z-signal);
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-shadow-drop: 3px 3px var(--z-edge);
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-shadow-drop-near: 1px 1px var(--z-edge);
  --z-shadow-focus: 3px 3px var(--z-ink);
  --z-shadow-hero: var(--z-hero-travel) var(--z-hero-travel) var(--z-ink);
  --z-shadow-in: inset 3px 3px var(--z-ink);
  --z-shadow-in-bad: inset 3px 3px var(--z-bad);
  --z-shadow-in-bad-deep: inset 5px 5px var(--z-bad);
  --z-shadow-in-deep: inset 5px 5px var(--z-ink);
  --z-shadow-in-signal: inset 3px 3px var(--z-on-signal);
  --z-shadow-in-signal-deep: inset 5px 5px var(--z-on-signal);
  --z-shadow-in-sm: inset 2px 2px var(--z-ink);
  --z-shadow-in-sm-deep: inset 3px 3px var(--z-ink);
  --z-shadow-key: 0px 2px var(--z-ink);
  /* The edge of a card, a control and a ruled line: ink on the light ground, a strong line on the dark one. */
  --z-shadow-near: 2px 2px var(--z-edge);
  --z-shadow-pop: 3px 3px var(--z-ink);
  --z-shadow-win: 0px 0px 0px 1px #000000e6, 10px 10px #0000001a;
  /* One colour, one meaning: this needs a human, act here. The approve button, the dot that leads to one, the count of what waits. Never a chip, a badge, a border or a status. One exception (founder decision 2026-10-13): the small solid shadow under the main ink button is yellow. Yellow never fills a large area. */
  --z-signal: #ffd23c;
  --z-signal-edge: #0000;
  --z-signal-mark: #ffd23c;
  --z-signal-soft: #3a3010;
  --z-stamp: none;
  --z-sunken: #0a0a0a;
  --z-surface: #151515;
  }
}

@media (prefers-reduced-motion: reduce) {
  :root {
/* One round of the one loop (`zyx-loading`, three squares one after the other). */
    --z-d-loop: 0ms;
    --z-d-press: 0ms;
    /* The stagger between small parts that move one after the other (the icons of a row hop in turn). */
    --z-d-step: 0ms;
    --z-d1: 0ms;
    --z-d2: 0ms;
    --z-d3: 0ms;
    --z-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  }
}

}

/* ---- css/base.css ---- */
/*
 * Base: what every page of every brand gets from plain HTML, before a class is set. All of it is in
 * the `zyx-base` layer and wrapped in `:where()`, so a utility or a page rule wins without a fight.
 * Values come only from the tokens (`--z-*`).
 */
@layer zyx-base {
  /* A width is the whole box: \`width: 100%\` with side room never pushes a page wider than the window. */
  :where(*, *::before, *::after) { box-sizing: border-box; }
  :where(html) { -webkit-text-size-adjust: 100%; }
  :where(body) {
    background: var(--z-ground);
    color: var(--z-ink);
    font-family: var(--z-font-text);
    font-size: var(--z-text);
    line-height: var(--z-lead);
    /* A word longer than its line (a German compound, a URL) breaks rather than pushing out of its box. */
    overflow-wrap: break-word;
    -webkit-font-smoothing: antialiased;
    /* Sections count themselves: the number in front of a numbered label (`zyx-eyebrow-n`). */
    counter-reset: zyx-sec;
  }
  :where(h1, h2, h3, h4) { font-family: var(--z-font-display); text-wrap: balance; }
  :where(p, li) { text-wrap: pretty; }
  ::selection { background: var(--z-ink); color: var(--z-ground); }

  /* Everything you can press shows the hand. Disabled keeps the arrow. */
  :where(button:not(:disabled), [role="button"]:not([aria-disabled="true"]), [role="link"], [role="tab"],
    [role="menuitem"], [role="menuitemradio"], [role="menuitemcheckbox"], [role="option"], [role="switch"],
    [role="radio"], [role="checkbox"], summary, select:not(:disabled), label[for]) { cursor: pointer; }
  :where(summary) { list-style: none; }
  :where(summary)::-webkit-details-marker { display: none; }

  /* An underlined link has a thick underline, a little off the words. */
  :where(a, button) { text-decoration-thickness: 2px; text-underline-offset: 3px; }

  /* A check box and a radio are squares: ink edge, ink filled when on. On the ink stands a tick (a
   * check box) or a small square (a radio), in the field colour: a bare square in a square reads as
   * "partly". `zyx-check` is the big one of a form on a page. */
  :where(input[type="checkbox"], input[type="radio"]) {
    appearance: none; display: inline-grid; place-content: center; flex: none; width: 1rem; height: 1rem;
    margin: 0; vertical-align: -0.15em; border: var(--z-bw) solid var(--z-ink); border-radius: 0;
    background: var(--z-field); cursor: pointer;
  }
  :where(input[type="checkbox"], input[type="radio"])::before {
    content: ""; width: 0.625rem; height: 0.625rem; background: var(--z-field); scale: 0;
  }
  :where(input[type="checkbox"])::before { clip-path: polygon(13% 50%, 0 64%, 38% 100%, 100% 24%, 86% 11%, 37% 72%); }
  :where(input[type="radio"])::before { width: 0.375rem; height: 0.375rem; }
  :where(input[type="checkbox"], input[type="radio"]):checked { background: var(--z-ink); }
  :where(input[type="checkbox"], input[type="radio"]):checked::before { scale: 1; }
  /* Disabled is the hatch, in a grey a mark can still be seen on. */
  :where(input[type="checkbox"], input[type="radio"]):disabled {
    cursor: default; border-color: var(--z-ctl);
    background-image: repeating-linear-gradient(135deg, var(--z-ctl) 0 1px, transparent 1px 4px);
  }
  :where(input[type="checkbox"], input[type="radio"]):disabled:checked { background: var(--z-ctl); }

  /* A keyboard key: a small edged key on a 2px bottom shadow. */
  :where(kbd) {
    display: inline-block; min-width: 1.5rem; padding: 0 0.375rem; border: var(--z-bw-hair) solid var(--z-edge);
    background: var(--z-surface); color: var(--z-ink); box-shadow: var(--z-shadow-key);
    font-family: var(--z-font-mono); font-size: 0.75rem; line-height: 1.25rem; text-align: center;
  }

  /* Read out, not shown. */
  .zyx-sr {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap; border: 0;
  }
  /* WebKit at a page zoom other than 100% sizes a placeholder box with the zoom applied twice. */
  :where(textarea)::placeholder { max-width: 100%; }
}

/*
 * Focus is unlayered on purpose: a utility such as `outline-none` must not take the ring away from a
 * keyboard user. A part that draws focus another way says so (`zyx-bare`, `zyx-field`).
 */
:focus-visible { outline: var(--z-bw) solid var(--z-focus); outline-offset: 2px; }
.zyx-bare:focus-visible { outline: none; }
/* A row in a list that scrolls in its own box: the box would cut an outer ring off, so it is drawn inside. */
.zyx-focus-inset:focus-visible { outline: var(--z-bw) solid var(--z-focus); outline-offset: calc(var(--z-bw) * -1); }

/* Square scrollbars. WebKit and Blink draw the parts; Firefox has only a colour and a width. */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb { border: 2px solid transparent; border-radius: 0; background: var(--z-ctl); background-clip: content-box; }
::-webkit-scrollbar-thumb:hover, ::-webkit-scrollbar-thumb:active { background-color: var(--z-ink); }
@supports not selector(::-webkit-scrollbar) {
  * { scrollbar-width: thin; scrollbar-color: var(--z-ctl) transparent; }
}

/*
 * Less motion asked for: every animation and transition is off and the end state shows, on every
 * element and every pseudo element. `!important` because a state and a page rule are unlayered.
 * A press still changes its shadow and its fill, but nothing travels: the 1px a button moves into its
 * shadow, the arrow's step and the shape that sinks into its drop shadow stay where they are. The
 * parts that draw in (the rule, the squares, the marker) show their end state, also when a page holds
 * them back until they are seen.
 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after, *::marker, ::backdrop {
    animation: none !important; transition: none !important; scroll-behavior: auto !important;
  }
  :is(.zyx-push, .zyx-icon, .zyx-pill, .zyx-main, .zyx-main-signal, .zyx-clack, .zyx-arrow, .zyx-press-drop) { translate: none !important; }
  :is(.zyx-rule, .zyx-eyebrow, .zyx-eyebrow-n, .zyx-section-title)::before, .zyx-eyebrow-n::after, .zyx-square { scale: none !important; transform: none !important; }
  .zyx-marker { background-size: 100% 100% !important; }
}

/* ---- css/controls.css ---- */
/*
 * Controls: buttons, fields, small marks. The REST look of a part is in `zyx-components`, so a utility
 * on the same element still wins. Its STATES (hover, pressed, chosen, focus) are unlayered on purpose:
 * a state must win over any colour utility, or an inverted block shows ink words on ink.
 *
 * One hover for every control: pressed in, the hard inner ink shadow (`--z-shadow-in`) in
 * `--z-d-press`. The click: pressed deeper at once (`--z-shadow-in-deep`), back up in `--z-d-press`.
 * A click never fills a control with ink; ink fill is a state only (chosen, current, open).
 *
 * "Chosen" is read from what the element already tells a screen reader: `aria-current`,
 * `aria-selected`, `aria-pressed`, `aria-checked`, `aria-expanded`, plus `data-open` and `data-on`.
 */
@layer zyx-components {
  /* A button. 42px high (`--z-row`), a 2px edge. One line where it fits; where it does not, the
   * words wrap inside it and it never grows past its row. */
  .zyx-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 0.375rem;
    min-height: var(--z-row); max-width: 100%; flex-shrink: 0; margin: 0;
    padding: 0.375rem 1rem; border: var(--z-bw) solid var(--z-edge); border-radius: var(--z-r-ctl);
    font: inherit; font-size: 0.875rem; line-height: 1.5rem; font-weight: 500;
    text-align: center; text-decoration: none; text-wrap: balance; vertical-align: middle;
  }
  /* The third button: a small press inside a line of text (Undo, Show earlier). */
  .zyx-btn-sm {
    min-height: var(--z-row-sm); padding: 0.125rem 0.625rem; border-width: var(--z-bw-hair);
    font-size: 0.75rem; line-height: 1.25rem;
  }
  /* The big button of a marketing page: 48px for a thumb, the body size, full weight, a little more
   * room at the sides. A tool screen keeps the 42px one. Two classes, so it wins over `zyx-main`'s weight. */
  .zyx-btn.zyx-btn-lg {
    min-height: var(--z-row-lg); padding-inline: 1.25rem; font-size: var(--z-text); line-height: 1.5rem; font-weight: 700;
  }

  /* The second button, a chip, a suggestion: no shadow at rest, pressed in on hover, inverted when chosen. */
  .zyx-push { border-color: var(--z-edge); background: var(--z-surface); color: var(--z-ink); }
  .zyx-push, .zyx-icon { transition: box-shadow var(--z-d-press) ease-out, translate var(--z-d-press) ease-out; }
  .zyx-btn.zyx-push:is([aria-current]:not([aria-current="false"]), [aria-selected="true"], [aria-pressed="true"], [aria-checked="true"], [aria-expanded="true"], [data-open], [data-on]) { font-weight: 700; }
  /* The second press of a two-step destructive act (revoke, delete): an outline and a colour, never a fill. */
  .zyx-push-bad { border-color: var(--z-bad); color: var(--z-bad); }

  /* The main button. It STANDS on its shadow and is pressed all the way down onto it; it never lifts.
   * The ink one stands on the signal yellow and turns yellow as it lands. The signal one is for
   * "this needs a person, act here" only: yellow on an edge shadow, and it stays yellow. */
  .zyx-main, .zyx-main-signal, .zyx-clack {
    transition: translate var(--z-d-press) ease-out, box-shadow var(--z-d-press) ease-out,
      background-color var(--z-d-press) ease-out, color var(--z-d-press) ease-out, border-color var(--z-d-press) ease-out;
  }
  .zyx-main, .zyx-main-signal { position: relative; }
  .zyx-main { border-color: var(--z-brand); background: var(--z-brand); color: var(--z-on-brand); font-weight: 600; box-shadow: var(--z-shadow-cta); }
  .zyx-main-signal {
    border-color: var(--z-edge); background: var(--z-signal); color: var(--z-on-signal); font-weight: 700;
    box-shadow: inset 0 0 0 var(--z-on-signal), var(--z-shadow-card);
  }
  /* The place a click lands stays still: an unseen layer that, while the button is down, also covers
   * the strip it left at its top and left, so the pointer there does not lose the button. */
  .zyx-main::after, .zyx-main-signal::after { content: ""; position: absolute; inset: 0; }

  /* A small square icon press on a bar: an edge, pressed in. */
  .zyx-icon {
    display: inline-flex; flex: none; align-items: center; justify-content: center; width: 2rem; height: 2rem;
    padding: 0; border: var(--z-bw-hair) solid var(--z-edge); background: var(--z-surface); color: var(--z-ink);
  }
  .zyx-icon:disabled { border-color: var(--z-ctl); color: var(--z-faint); }

  /* A field. `zyx-field` is the focus and disabled look and nothing else, so a small field in a bar
   * keeps its own size; `zyx-input` adds the full control: 42px, a 2px `ctl` line that is not layout. */
  .zyx-input {
    display: block; width: 100%; min-height: var(--z-row); margin: 0; padding: 0.5rem 0.75rem;
    border: 0; border-radius: var(--z-r-ctl); background: var(--z-field); color: var(--z-ink);
    font: inherit; font-size: 0.875rem; line-height: 1.5rem;
    outline: var(--z-bw) solid var(--z-ctl); outline-offset: calc(var(--z-bw) * -1);
  }
  .zyx-input::placeholder { color: var(--z-faint); opacity: 1; }
  textarea.zyx-input { resize: vertical; }
  .zyx-field:disabled {
    cursor: not-allowed; color: var(--z-muted);
    background-image: repeating-linear-gradient(135deg, var(--z-line-strong) 0 1px, transparent 1px 6px);
  }
  .zyx-field:disabled::placeholder { color: var(--z-muted); }
  /* A native select with the arrow put back by a one-cell grid, so it cannot drift out of a control that grows. */
  .zyx-select { display: grid; grid-template-columns: minmax(0, 1fr); }
  .zyx-select > select { grid-area: 1 / 1; appearance: none; padding-right: 2rem; }
  .zyx-select > select > option { background: var(--z-surface); color: var(--z-ink); }
  .zyx-select > svg {
    grid-area: 1 / 1; align-self: center; justify-self: end; width: 1rem; height: 1rem; margin-right: 0.5rem;
    pointer-events: none; color: var(--z-ink);
  }
  /* The big check box of a form on a page. */
  input.zyx-check { width: 1.375rem; height: 1.375rem; }
  input.zyx-check::before { width: 0.875rem; height: 0.875rem; }

  /* A badge: an edged block with a small square, never a tint. The edge and the words carry the tone.
   * `data-tone`: quiet (default), needs-you (the signal fill), bad, ok. */
  .zyx-badge {
    display: inline-flex; max-width: 100%; align-items: center; gap: 0.375rem; padding: 0.125rem 0.5rem;
    border: var(--z-bw-hair) solid var(--z-edge); border-radius: var(--z-r-chip); background: var(--z-surface);
    color: var(--z-ink); font-size: 0.75rem; line-height: 1.25rem; font-weight: 600;
  }
  .zyx-badge::before { content: ""; flex: none; width: 6px; height: 6px; background: currentColor; }
  .zyx-badge[data-tone="needs-you"] { background: var(--z-signal); color: var(--z-on-signal); }
  .zyx-badge[data-tone="bad"] { border-color: var(--z-bad); color: var(--z-bad); }
  .zyx-badge[data-tone="ok"] { border-color: var(--z-ok); color: var(--z-ok); }

  /* A chip of a page: mono upper case in an ink edge. `zyx-chip-solid` is the one state that is done. */
  .zyx-chip {
    display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.125rem 0.5rem;
    border: var(--z-bw-hair) solid var(--z-ink); border-radius: var(--z-r-chip); background: var(--z-surface);
    color: var(--z-ink); font-family: var(--z-font-mono); font-size: var(--z-micro); font-weight: 700;
    line-height: 1.5; letter-spacing: 0.06em; text-transform: uppercase; white-space: nowrap;
  }
  .zyx-chip-solid { background: var(--z-ink); color: var(--z-on-brand); }
  /* A chip that names a thing in its own spelling ("macOS"): no upper case. */
  .zyx-chip-case { letter-spacing: 0; text-transform: none; }

  /* What waits for a person, as a count you can press: the signal fill. As a link (`a.zyx-pill`, or
   * any pill with `href`) it goes to the queue and presses in like every control; a pill that is not a
   * link or a button stands still. */
  .zyx-pill {
    display: inline-flex; flex-shrink: 0; align-items: center; padding: 0.125rem 0.625rem;
    border: var(--z-bw-hair) solid var(--z-edge); background: var(--z-signal); color: var(--z-on-signal);
    font-size: 0.75rem; line-height: 1.25rem; font-weight: 700; font-variant-numeric: tabular-nums;
    text-decoration: none; transition: box-shadow var(--z-d-press) ease-out, translate var(--z-d-press) ease-out;
  }

  /* A line of news on a screen. `data-tone`: quiet (default), needs-you (the soft signal, ink words), bad. */
  .zyx-alert {
    margin: 0; padding: 0.5rem 0.75rem; border: var(--z-bw-hair) solid var(--z-edge); border-radius: var(--z-r-ctl);
    background: var(--z-surface); color: var(--z-muted); font-size: 0.875rem; line-height: 1.5rem;
  }
  .zyx-alert[data-tone="needs-you"] { background: var(--z-signal-soft); color: var(--z-ink); }
  .zyx-alert[data-tone="bad"] { border-color: var(--z-bad); color: var(--z-bad); }

  /* A group label: small mono upper case behind a solid ink square. */
  .zyx-label {
    display: flex; align-items: center; gap: 0.5rem; margin: 0; font-family: var(--z-font-mono); font-size: var(--z-micro);
    line-height: 1.5rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--z-ink);
  }
  .zyx-label::before { content: ""; flex: none; width: 6px; height: 6px; background: var(--z-ink); }
  /* A count: a solid inverted block that flips when it appears or changes (key it by its number). */
  .zyx-count {
    display: inline-block; min-width: 1.25rem; padding: 0 0.375rem; background: var(--z-ink); color: var(--z-surface);
    font-size: var(--z-micro); line-height: 1.25rem; font-weight: 700; font-variant-numeric: tabular-nums; text-align: center;
    animation: zyx-flip var(--z-d1) step-end 1;
  }
  /* The letter disc of an agent, readable on an inverted cell too. */
  .zyx-disc { background: var(--z-raised); color: var(--z-muted); }
  /* Progress: an edged track; its one child is the solid bar (set its width). */
  .zyx-meter { height: 0.625rem; border: var(--z-bw-hair) solid var(--z-edge); background: var(--z-surface); overflow: hidden; }
  .zyx-meter > * { height: 100%; background: var(--z-ink); }
  /* Progress in steps: solid ink blocks in an ink-edged track; a block that is done has `data-on`. */
  .zyx-meter-blocks { display: flex; flex: none; border: var(--z-bw) solid var(--z-ink); background: var(--z-surface); }
  .zyx-meter-blocks > * { width: 0.75rem; height: 0.5rem; }
  .zyx-meter-blocks > * + * { border-left: var(--z-bw-hair) solid var(--z-ink); }
  .zyx-meter-blocks > [data-on] { background: var(--z-ink); }

  /* A link in running text: a thick underline that gets thicker under the pointer. */
  .zyx-link { color: inherit; text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 3px; }
  /* An arrow at the end of a link cell: it steps to the right under the pointer. */
  .zyx-arrow { margin-left: 0.5rem; font-family: var(--z-font-mono); transition: translate var(--z-d-press) steps(3, end); }
  /* A square plus that turns into an ink minus when its control is open. */
  .zyx-plus {
    display: inline-grid; place-items: center; width: 1rem; height: 1rem; border: var(--z-bw-hair) solid var(--z-ink);
    background: var(--z-surface); color: var(--z-ink); font-weight: 700; line-height: 1;
  }
  .zyx-plus::before { content: "+"; }
  /* Skip to the content: out of sight until the keyboard lands on it. */
  .zyx-skip {
    position: absolute; left: 0.75rem; top: -4rem; z-index: 100; padding: 0.625rem 1rem; border-radius: var(--z-r-ctl);
    background: var(--z-brand); color: var(--z-on-brand); font-weight: 700;
  }
  .zyx-skip:focus { top: 0.75rem; }

  /* A press that is a shape, not a box (an icon, the mark): it stands on a hard drop shadow that
   * follows its outline. Put it on the shape itself, or on the shape inside a link or a button: the
   * press of its control presses it. */
  .zyx-press-drop {
    filter: drop-shadow(var(--z-shadow-drop));
    transition: filter var(--z-d-press) ease-out, translate var(--z-d-press) ease-out;
  }
}

/* ---- States (unlayered) ---- */

@media (hover: hover) {
  .zyx-push:hover:not(:disabled, [aria-disabled="true"]) { box-shadow: var(--z-shadow-in); translate: 1px 1px; }
  .zyx-push-bad:hover:not(:disabled, [aria-disabled="true"]) { box-shadow: var(--z-shadow-in-bad); }
  .zyx-icon:hover:not(:disabled) { box-shadow: var(--z-shadow-in-sm); translate: 1px 1px; }
  :is(a[href], button:not(:disabled), [href]).zyx-pill:hover { translate: 1px 1px; box-shadow: var(--z-shadow-in-signal); }
  /* The shape sinks 2px into its drop shadow, as a button sinks into its own. */
  .zyx-press-drop:hover:not(:disabled, :disabled *),
  :is(a[href], button:not(:disabled), [role="button"], summary):hover .zyx-press-drop {
    filter: drop-shadow(var(--z-shadow-drop-near)); translate: 2px 2px;
  }
  .zyx-link:hover { text-decoration-thickness: 3px; }
  :is(.zyx-cell, .zyx-tool, a):hover .zyx-arrow { translate: 3px 0; }
  .zyx-input:hover:not(:disabled, :focus) { outline-color: var(--z-ink); }
}
.zyx-push:active:not(:disabled, [aria-disabled="true"]) { box-shadow: var(--z-shadow-in-deep); translate: 2px 2px; transition-duration: 0s; }
.zyx-push-bad:active:not(:disabled, [aria-disabled="true"]) { box-shadow: var(--z-shadow-in-bad-deep); }
.zyx-icon:active:not(:disabled) { box-shadow: var(--z-shadow-in-sm-deep); translate: 2px 2px; transition-duration: 0s; }
:is(a[href], button:not(:disabled), [href]).zyx-pill:active { translate: 1px 1px; box-shadow: var(--z-shadow-in-signal-deep); transition-duration: 0s; }
/* The click: the shape sits all the way down, no shadow left, and comes back up on release. Open
 * (its bubble or menu is out), it stays down. */
.zyx-press-drop:active:not(:disabled, :disabled *), :is(a[href], button:not(:disabled), [role="button"], summary):active .zyx-press-drop,
.zyx-press-drop:is([aria-expanded="true"], [aria-pressed="true"], [data-open]),
:is([aria-expanded="true"], [aria-pressed="true"], [data-open]) .zyx-press-drop {
  filter: none; translate: 3px 3px; transition-duration: 0s;
}

/* Inverted: chosen, or the row of a menu the keyboard is on. */
.zyx-push:is([aria-current]:not([aria-current="false"]), [aria-selected="true"], [aria-pressed="true"], [aria-checked="true"], [aria-expanded="true"], [data-open], [data-on]) {
  border-color: var(--z-ink); background: var(--z-ink); color: var(--z-surface); box-shadow: none; translate: none; outline: none;
}
.zyx-push:is([aria-current]:not([aria-current="false"]), [aria-selected="true"], [aria-pressed="true"], [aria-checked="true"], [aria-expanded="true"], [data-open], [data-on]):focus-visible {
  outline: var(--z-bw) solid var(--z-focus); outline-offset: 2px;
}
/* What stands on an inverted block takes its colour, whatever utility it wears. A key, a count, a
 * letter disc and a pill bring their own ground and keep their own words. */
.zyx-push:is([aria-current]:not([aria-current="false"]), [aria-selected="true"], [aria-pressed="true"], [aria-checked="true"], [aria-expanded="true"], [data-open], [data-on]) :where(*):not(kbd, .zyx-count, .zyx-disc, .zyx-pill) { color: inherit; }
.zyx-push:is([aria-current]:not([aria-current="false"]), [aria-selected="true"], [aria-pressed="true"], [aria-checked="true"], [aria-expanded="true"], [data-open], [data-on]) :is(.zyx-count, .zyx-disc) { background: var(--z-surface); color: var(--z-ink); }
.zyx-icon:is([aria-pressed="true"], [data-on]):not(:disabled) { background: var(--z-ink); color: var(--z-surface); box-shadow: none; }
.zyx-icon:is([aria-pressed="true"], [data-on]):not(:disabled) :where(*) { color: inherit; }
/* The mic while it records: a red block, also under the pointer. */
.zyx-icon[data-rec]:not(:disabled) { border-color: var(--z-bad); background: var(--z-bad); color: var(--z-surface); }
.zyx-icon[data-rec]:not(:disabled) :where(*) { color: inherit; }
[aria-expanded="true"] .zyx-plus, [open] > summary .zyx-plus { background: var(--z-ink); color: var(--z-on-brand); }
[aria-expanded="true"] .zyx-plus::before, [open] > summary .zyx-plus::before { content: "\2212"; }

/* THE MAIN BUTTON goes all the way down under the pointer, the keyboard and a press: it sits in its
 * shadow's place (`--z-cta-travel` is how far it moves, 0 so it stays level with its neighbour), and
 * it is pressed in like every other button. Moved with `translate`: no layout shift. */
.zyx-main:is(:active, :focus-visible):not(:disabled) {
  translate: var(--z-cta-travel) var(--z-cta-travel); box-shadow: var(--z-shadow-cta-down);
  border-color: var(--z-on-signal); background: var(--z-signal); color: var(--z-on-signal);
}
.zyx-main-signal:is(:active, :focus-visible):not(:disabled) { box-shadow: var(--z-shadow-in-signal), 0 0 0 var(--z-edge); }
.zyx-main:is(:active, :focus-visible):not(:disabled)::after { inset: calc(var(--z-cta-travel) * -1 - 2px) 0 0 calc(var(--z-cta-travel) * -1 - 2px); }
@media (hover: hover) {
  .zyx-main:hover:not(:disabled) {
    translate: var(--z-cta-travel) var(--z-cta-travel); box-shadow: var(--z-shadow-cta-down);
    border-color: var(--z-on-signal); background: var(--z-signal); color: var(--z-on-signal);
  }
  .zyx-main-signal:hover:not(:disabled) { box-shadow: var(--z-shadow-in-signal), 0 0 0 var(--z-edge); }
  .zyx-main:hover:not(:disabled)::after { inset: calc(var(--z-cta-travel) * -1 - 2px) 0 0 calc(var(--z-cta-travel) * -1 - 2px); }
}
.zyx-main:active:not(:disabled) { box-shadow: var(--z-shadow-cta-deep); transition-duration: 0s; }
.zyx-main-signal:active:not(:disabled) { box-shadow: var(--z-shadow-in-signal-deep), 0 0 0 var(--z-edge); transition-duration: 0s; }
.zyx-main:is(:hover, :active, :focus-visible):not(:disabled) :where(*) { color: inherit; }

/* A disabled button is plainly not there to press: a grey step, grey words, no shadow. */
.zyx-btn:is(:disabled, [aria-disabled="true"]) {
  border-color: var(--z-ctl); background: var(--z-raised); color: var(--z-muted); box-shadow: none; translate: none; cursor: not-allowed;
}

/* A field with the cursor in it: the 2px line goes to ink where it stands, on a small hard shadow. No ring. */
.zyx-field:focus-visible, .zyx-input:focus {
  outline: var(--z-bw) solid var(--z-ink); outline-offset: calc(var(--z-bw) * -1); box-shadow: var(--z-shadow-focus);
}
.zyx-field:disabled, .zyx-input:disabled { box-shadow: none; }

/* On a brand-coloured block the ring swaps sides. */
.zyx-on-brand :focus-visible { outline-color: var(--z-on-brand); }

/* ---- css/cells.css ---- */
/*
 * Cells, not gaps. A cell is one item of a ruled control: a row of a list, a tab, a nav link, a
 * footer link, the head of a fold. It fills its whole space; ink lines stand between cells.
 *
 *   zyx-cells       a ruled list of siblings (`zyx-cells-x`: side by side), a 1px edge line between them
 *   zyx-cell        one cell: hover = pressed in, it does not move; chosen = a 3px ink bar on its edge.
 *   zyx-cell-box    with zyx-cell: a cell on its own (a footer link, a legal chip, a language pair), a 42px box
 *   zyx-cell-ink    with zyx-cell: chosen = an ink cell (a few cells: a tab strip, a switch, a nav)
 *   zyx-row         a cell with tool cells beside it; `zyx-tool` is one tool cell
 *   zyx-item        a row of a menu or a pick list: the row the keyboard or the mouse is on is inverted
 *   zyx-nav         a bar of ink cells with 2px ink lines between them (`zyx-nav-y`: a column, 1px lines)
 *   zyx-grid        a ruled grid: the gap is the ink line (`--zyx-grid-bg` is the colour of each cell)
 *   zyx-fold        a <details>: the summary is a full cell with a square plus that turns ink when open
 *   zyx-entry       the parts of a list row (title, side note, sub line, actions)
 *
 * A cell presses in through a border on `::after`, never an inset box-shadow: WebKit rounds an inset
 * shadow on its own at a page zoom like 110%, and a hairline showed between the ink line and the press.
 */
@layer zyx-components {
  .zyx-cells > * + * { border-top: var(--z-bw-hair) solid var(--z-edge); }
  .zyx-cells-x > * + * { border-left: var(--z-bw-hair) solid var(--z-edge); }
  .zyx-cell, .zyx-tool { position: relative; transition: box-shadow var(--z-d-press) ease-out, translate var(--z-d-press) ease-out; }
  .zyx-cell::after, .zyx-tool::after {
    content: ""; position: absolute; inset: 0; pointer-events: none; border: 0 solid var(--z-ink);
    transition: border-width var(--z-d-press) ease-out;
  }
  .zyx-cell, .zyx-item { color: var(--z-ink); }
  /* A cell that stands on its own (in a ruled grid, a footer column, a bar of a site) asks for the box a
   * nav gives it: the words in the middle of a 42px row, an arrow at its end. Opt-in, because a product
   * lays out many cells itself. */
  .zyx-cell-box {
    display: flex; align-items: center; gap: 0.5rem; min-height: var(--z-row); padding: 0.5rem 1rem;
    line-height: 1.3; text-decoration: none; overflow-wrap: anywhere;
  }
  .zyx-cell-box > .zyx-arrow:last-child { margin-left: auto; }
  .zyx-tool {
    display: flex; align-items: center; justify-content: center; border-left: var(--z-bw-hair) solid var(--z-edge);
    background: var(--z-raised); color: var(--z-ink);
  }

  .zyx-nav { display: flex; align-items: stretch; }
  .zyx-nav > * + * { border-left: var(--z-bw) solid var(--z-ink); }
  .zyx-nav-y { display: flex; flex-direction: column; }
  .zyx-nav-y > * + * { border-top: var(--z-bw-hair) solid var(--z-ink); }
  :is(.zyx-nav, .zyx-nav-y) > .zyx-cell {
    display: flex; align-items: center; justify-content: center; min-height: var(--z-row); padding: 0 1rem;
    font-weight: 700; line-height: 1.2; white-space: nowrap; text-decoration: none;
  }

  .zyx-grid {
    --zyx-grid-bg: var(--z-surface);
    display: grid; gap: var(--z-bw-hair); border: var(--z-bw) solid var(--z-ink); background: var(--z-ink);
  }
  /* A cell of the grid may shrink below its words' width (a long URL, a wide table), or it pushes the grid out of the page. */
  .zyx-grid > * { min-width: 0; background-color: var(--zyx-grid-bg); }
  /* A ruled grid that stands (`zyx-stand`) keeps its ink ground: that ground is its lines. */
  .zyx-grid.zyx-stand { background: var(--z-ink); }
  .zyx-grid-wide { gap: var(--z-bw); }
  .zyx-grid-fill > :last-child:nth-child(odd) { grid-column: 1 / -1; }

  .zyx-fold > summary {
    display: flex; align-items: center; justify-content: space-between; gap: 1rem; min-height: var(--z-row);
    list-style: none; transition: box-shadow var(--z-d-press) ease-out;
  }
  .zyx-fold { transition: box-shadow var(--z-d-press) ease-out; }
  .zyx-fold > summary::-webkit-details-marker { display: none; }
  .zyx-fold > summary::after {
    content: "+"; flex: none; display: grid; place-items: center; width: 1.75rem; height: 1.75rem;
    border: var(--z-bw) solid var(--z-ink); background: var(--z-surface); color: var(--z-ink);
    font-family: var(--z-font-mono); font-size: 1rem; font-weight: 700; line-height: 1;
  }

  .zyx-entry { display: flex; flex-wrap: wrap; gap: 0.5rem 0.75rem; padding: 0.75rem 0.5rem; }
  .zyx-entry-main { min-width: 0; flex: 1; }
  .zyx-entry-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
  .zyx-entry-title { margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.875rem; line-height: 1.5rem; font-weight: 500; color: var(--z-ink); }
  .zyx-entry-side { flex-shrink: 0; font-size: 0.75rem; line-height: 1.5rem; color: var(--z-faint); }
  .zyx-entry-sub { margin: 0.125rem 0 0; font-size: 0.875rem; line-height: 1.5rem; color: var(--z-muted); }
  .zyx-entry-sub:not([data-wrap]) { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
  .zyx-entry-mark { flex-shrink: 0; margin-top: 0.375rem; }
  .zyx-entry-actions {
    position: relative; z-index: 10; display: flex; max-width: 100%; min-width: 0; flex-wrap: wrap; align-items: center;
    justify-content: flex-end; gap: 0.5rem; align-self: center; flex-basis: 100%;
  }
  /* The link that makes the whole row one target; the actions stand above it. Its ring is drawn
   * inside, so a keyboard user sees the whole row outlined. */
  .zyx-row-link { position: relative; }
  .zyx-entry-link { position: absolute; inset: 0; }
  @media (min-width: 40rem) {
    .zyx-entry { flex-wrap: nowrap; padding-inline: 0.75rem; }
    .zyx-entry-actions { flex-basis: auto; flex-shrink: 0; }
  }
  .zyx-list { margin: 0; padding: 0; list-style: none; }
  .zyx-list > li + li { border-top: var(--z-bw-hair) solid var(--z-line); }
}

/* ---- States (unlayered) ---- */

@media (hover: hover) {
  .zyx-cell:hover:not(:disabled)::after, .zyx-row:hover > .zyx-cell::after, .zyx-row:has(> .zyx-entry-link:focus-visible) > .zyx-cell::after, .zyx-tool:hover:not(:disabled)::after { border-width: 3px 0 0 3px; }
  :is(input, textarea, select).zyx-cell:hover:not(:disabled) { box-shadow: var(--z-shadow-in); }
  .zyx-fold > summary:hover { box-shadow: var(--z-shadow-in); }
  /* An open fold is one piece: the question and its answer press in together. A fold that only
   * hides more rows (`zyx-fold-list`) keeps the press on its summary. */
  .zyx-fold:not(.zyx-fold-list)[open]:hover { box-shadow: var(--z-shadow-in); }
  .zyx-fold:not(.zyx-fold-list)[open] > summary:hover { box-shadow: none; }
}
.zyx-cell:focus-visible::after, .zyx-tool:focus-visible::after { border-width: 3px 0 0 3px; }
:is(input, textarea, select).zyx-cell:focus-visible { box-shadow: var(--z-shadow-in); }
.zyx-fold > summary:focus-visible { box-shadow: var(--z-shadow-in); }
.zyx-cell:active:not(:disabled)::after, .zyx-tool:active:not(:disabled)::after { border-width: 5px 0 0 5px; transition-duration: 0s; }
:is(input, textarea, select).zyx-cell:active:not(:disabled) { box-shadow: var(--z-shadow-in-deep); transition-duration: 0s; }
.zyx-fold > summary:active { box-shadow: var(--z-shadow-in-deep); transition-duration: 0s; }

/* Chosen in a long list: the cell is a grey step and a 3px ink bar stands on its edge. */
.zyx-cell:is([aria-current]:not([aria-current="false"]), [aria-selected="true"], [aria-pressed="true"], [aria-checked="true"], [aria-expanded="true"], [data-open], [data-on]) {
  background: var(--z-raised); box-shadow: var(--z-shadow-bar); font-weight: 700;
}
/* A chosen cell shows its state, not a press. */
.zyx-cell:is([aria-current]:not([aria-current="false"]), [aria-selected="true"], [aria-pressed="true"], [aria-checked="true"], [aria-expanded="true"], [data-open], [data-on])::after { border-width: 0; }
/* An ink cell, or the row of a menu the keyboard is on: inverted. */
.zyx-cell-ink:is([aria-current]:not([aria-current="false"]), [aria-selected="true"], [aria-pressed="true"], [aria-checked="true"], [aria-expanded="true"], [data-open], [data-on]),
.zyx-item:is([data-focus], [data-active], [aria-selected="true"]:focus-visible) {
  border-color: var(--z-ink); background: var(--z-ink); color: var(--z-surface); box-shadow: none; outline: none;
}
.zyx-cell-ink:is([aria-current]:not([aria-current="false"]), [aria-selected="true"], [aria-pressed="true"], [aria-checked="true"], [aria-expanded="true"], [data-open], [data-on]) :where(*):not(kbd, .zyx-count, .zyx-disc, .zyx-pill),
.zyx-item:is([data-focus], [data-active], [aria-selected="true"]:focus-visible) :where(*):not(kbd, .zyx-count, .zyx-disc, .zyx-pill) { color: inherit; }
.zyx-cell-ink:is([aria-current]:not([aria-current="false"]), [aria-selected="true"], [aria-pressed="true"], [aria-checked="true"], [aria-expanded="true"], [data-open], [data-on]) :is(.zyx-count, .zyx-disc),
.zyx-item:is([data-focus], [data-active], [aria-selected="true"]:focus-visible) :is(.zyx-count, .zyx-disc) { background: var(--z-surface); color: var(--z-ink); }
/* The keyboard ring in a ruled grid is drawn inside the cell, so no neighbour cuts it off. On an ink
 * cell it is the paper colour, 2px in, so ink stands on both sides of it. */
.zyx-cell:focus-visible, .zyx-tool:focus-visible, .zyx-item:focus-visible, .zyx-fold > summary:focus-visible, .zyx-entry-link:focus-visible { outline: var(--z-bw) solid var(--z-focus); outline-offset: calc(var(--z-bw) * -1); }
.zyx-cell-ink:is([aria-current]:not([aria-current="false"]), [aria-selected="true"], [aria-pressed="true"], [aria-checked="true"], [aria-expanded="true"], [data-open], [data-on]):focus-visible {
  outline: var(--z-bw) solid var(--z-surface); outline-offset: -4px;
}
.zyx-cell:disabled { color: var(--z-faint); cursor: not-allowed; }
.zyx-fold[open] > summary::after { content: "\2212"; background: var(--z-ink); color: var(--z-on-brand); }

/* ---- css/blocks.css ---- */
/*
 * Blocks: cards, pages, sections, tables, lists, text. Quiet print: every box is a thin ink line, and
 * the hard shadow says what a thing does. A main block STANDS on it (`zyx-card-stand`, `zyx-stand`,
 * `zyx-window`); a thing that floats stands on `--z-shadow-card`.
 */
@layer zyx-components {
  /* A card: a 1px edge that is not layout. `zyx-card-stand`: the one main block of a screen, on its
   * block shadow, with room for it so a scroll box does not cut it. */
  .zyx-card {
    overflow: hidden; border-radius: var(--z-r-card); background: var(--z-surface);
    outline: var(--z-bw-hair) solid var(--z-edge); outline-offset: calc(var(--z-bw-hair) * -1);
  }
  .zyx-card-stand { box-shadow: var(--z-shadow-block); margin: 0 0.25rem 0.25rem 0; }
  /* The main block of a page: a 3px ink edge on a solid ink shadow. */
  .zyx-stand { border: var(--z-bw-block) solid var(--z-ink); background: var(--z-surface); box-shadow: var(--z-shadow-block); }
  /* A window: a picture of a screen. `zyx-window-hero` stands higher. */
  .zyx-window {
    overflow: hidden; border: var(--z-bw) solid var(--z-ink); border-radius: var(--z-r-win);
    background: var(--z-surface); box-shadow: var(--z-shadow-block);
  }
  .zyx-window-hero { box-shadow: var(--z-shadow-hero); }
  /* The frame of a picture or a clip: it has its final size before the file arrives.
   * `--zyx-ratio` (and `--zyx-ratio-phone` under 40rem) is set where it is used. */
  .zyx-media { width: 100%; aspect-ratio: var(--zyx-ratio-phone, var(--zyx-ratio, 16 / 10)); }
  @media (min-width: 40rem) { .zyx-media { aspect-ratio: var(--zyx-ratio, 16 / 10); } }
  .zyx-media > :is(img, video) { display: block; width: 100%; height: 100%; object-fit: cover; }
  /* Crop marks at the four corners of the hero block: the one print ornament of a page.
   * `--zyx-crop-inset` is where they stand, as `inset` reads it (one to four values; negative is
   * outside the box), for a hero whose marks reach past its nav bar: `--zyx-crop-inset: -64px -14px 4px`. */
  .zyx-crop { --zyx-crop-inset: -14px; position: relative; }
  /* `zyx-crop-wide`: the marks show only from 480px, where there is room for them beside the text. */
  @media (width < 480px) { .zyx-crop-wide::before { display: none; } }
  .zyx-crop::before {
    --m: linear-gradient(var(--z-ink), var(--z-ink));
    content: ""; position: absolute; inset: var(--zyx-crop-inset); pointer-events: none; background-repeat: no-repeat;
    background:
      var(--m) left top / 8px var(--z-bw-rule) no-repeat, var(--m) left top / var(--z-bw-rule) 8px no-repeat,
      var(--m) right top / 8px var(--z-bw-rule) no-repeat, var(--m) right top / var(--z-bw-rule) 8px no-repeat,
      var(--m) left bottom / 8px var(--z-bw-rule) no-repeat, var(--m) left bottom / var(--z-bw-rule) 8px no-repeat,
      var(--m) right bottom / 8px var(--z-bw-rule) no-repeat, var(--m) right bottom / var(--z-bw-rule) 8px no-repeat;
  }
  /* The ink block of a page: the brand is the ground, so focus and selection swap sides. */
  .zyx-on-brand { background: var(--z-brand); color: var(--z-on-brand); }
  /* The highlighter: one phrase a page, ink words on the lower half of the line. */
  .zyx-marker {
    -webkit-box-decoration-break: clone; box-decoration-break: clone;
    background: linear-gradient(transparent 58%, var(--z-signal) 58%, var(--z-signal) 94%, transparent 94%) no-repeat left / 100% 100%;
  }
  /* On a dark ground the light words would stand on the signal colour: the mark fills the line, with its own words. */
  [data-theme="dark"] .zyx-marker { background: var(--z-signal); color: var(--z-on-signal); }
  @media (prefers-color-scheme: dark) { [data-theme="system"] .zyx-marker { background: var(--z-signal); color: var(--z-on-signal); } }
  /* The column of a page: as wide as the shell, with side gutters. */
  .zyx-shell { width: 100%; max-width: var(--z-shell); margin-inline: auto; padding-inline: 1.25rem; }
  @media (min-width: 48rem) { .zyx-shell { padding-inline: 2.5rem; } }

  /* A screen of a tool: it scrolls in its own box. `data-width="wide"` for a table or a board. */
  .zyx-page { height: 100%; overflow-y: auto; position: relative; }
  .zyx-page-in { max-width: 42rem; margin-inline: auto; padding: 1.5rem 1rem; }
  .zyx-page-in[data-width="wide"] { max-width: 80rem; }
  @media (min-width: 40rem) { .zyx-page-in { padding: 2.5rem 1.5rem; } }
  .zyx-page-head { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0.75rem 1rem; padding-bottom: 1.25rem; border-bottom: var(--z-bw) solid var(--z-edge); }
  .zyx-page-head > :first-child { min-width: 0; flex: 1 1 16rem; }
  .zyx-page-title { margin: 0; font-family: var(--z-font-display); font-size: 1.5rem; line-height: 2rem; font-weight: 700; letter-spacing: var(--z-dt); color: var(--z-ink); }
  .zyx-page-lead { margin: 0.375rem 0 0; max-width: 65ch; font-size: 0.875rem; line-height: 1.5rem; color: var(--z-muted); }
  .zyx-actions { display: flex; max-width: 100%; flex-shrink: 0; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
  /* The first section under a page head needs no rule of its own: the head has one. */
  .zyx-page-body > .zyx-section:first-of-type { margin-top: 1.5rem; padding-top: 0; border-top: 0; }
  .zyx-page-body > .zyx-section:first-of-type::before { display: none; }

  /* A section: a 2px rule that draws in from the left, then its ink square stamps in. */
  .zyx-section { margin-top: 2.5rem; padding-top: 1.5rem; scroll-margin-top: 1rem; }
  .zyx-section-head { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0.75rem 1rem; }
  .zyx-section-head > :first-child { min-width: 0; flex: 1 1 16rem; }
  .zyx-section-title { display: flex; align-items: baseline; gap: 0.5rem; margin: 0; font-size: 1rem; line-height: 1.5rem; font-weight: 700; color: var(--z-ink); }
  .zyx-section-title > .zyx-square { flex-shrink: 0; width: 0.5rem; height: 0.5rem; background: var(--z-ink); }
  .zyx-section-lead { margin: 0.25rem 0 0; font-size: 0.875rem; line-height: 1.5rem; color: var(--z-muted); }
  .zyx-section-body { margin-top: 1rem; min-width: 0; }
  .zyx-section-body > * + * { margin-top: 1rem; }
  .zyx-rule { position: relative; border-top: var(--z-bw-rule) solid transparent; }
  .zyx-rule::before {
    content: ""; position: absolute; top: calc(var(--z-bw-rule) * -1); left: 0; right: 0; height: var(--z-bw-rule);
    background: var(--z-edge); transform-origin: left;
  }

  /* The section label of a page: small mono upper case behind a solid ink square. `zyx-eyebrow-n`
   * puts the section number first; in a section made of parts (`zyx-parts`) each part counts 03.1, 03.2. */
  /* A label opens what follows it, so it keeps room under it on any element (a p, an h2); alone in its
   * box (a head row) it has none. A page's own `h2 { margin }` is unlayered and wins: drop it there. */
  .zyx-eyebrow {
    display: flex; align-items: center; gap: 0.625rem; margin: 0 0 1.75rem; font-family: var(--z-font-mono); font-size: 0.75rem;
    font-weight: 700; line-height: 1.3; letter-spacing: 0.08em; text-transform: uppercase; color: var(--z-ink);
  }
  .zyx-eyebrow:last-child { margin-bottom: 0; }
  .zyx-eyebrow::before { content: ""; flex: none; width: 0.5rem; height: 0.5rem; background: var(--z-ink); }
  .zyx-eyebrow-n { counter-increment: zyx-sec; }
  /* The number is for the eye: a screen reader reads the label only. */
  .zyx-eyebrow-n::before { content: counter(zyx-sec, decimal-leading-zero); content: counter(zyx-sec, decimal-leading-zero) / ""; width: auto; height: auto; background: none; }
  .zyx-eyebrow-n::after { content: ""; flex: none; order: 1; width: 0.5rem; height: 0.5rem; background: var(--z-ink); }
  .zyx-eyebrow-n > span { order: 2; }
  .zyx-eyebrow-n:empty::after { display: none; }
  .zyx-parts { counter-increment: zyx-sec; counter-reset: zyx-part; }
  .zyx-parts .zyx-eyebrow-n { counter-increment: none; }
  .zyx-parts .zyx-eyebrow-part, .zyx-eyebrow-part { counter-increment: zyx-part; }
  .zyx-eyebrow-part::before { content: counter(zyx-sec, decimal-leading-zero) "." counter(zyx-part); content: counter(zyx-sec, decimal-leading-zero) "." counter(zyx-part) / ""; }
  /* On the screens of a tool's own style page only: section titles get a mono counter ("01"). */
  .zyx-counted { counter-reset: zyx-section; }
  .zyx-counted .zyx-section-title::before {
    counter-increment: zyx-section; content: counter(zyx-section, decimal-leading-zero); order: -1;
    font-family: var(--z-font-mono); font-size: var(--z-micro); font-weight: 700; letter-spacing: 0.08em;
  }

  /* A list with an ink tick in front of each line. Never the signal. */
  .zyx-ticks { margin: 0; padding: 0; list-style: none; }
  .zyx-ticks > li { position: relative; padding-left: 1.5rem; }
  .zyx-ticks > li::before {
    content: ""; position: absolute; left: 0.125rem; top: 0.45em; width: 0.7rem; height: 0.4rem;
    border-left: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(-45deg);
  }
  /* Rows under a 2px ink rule, a light line after each. */
  .zyx-rows { margin: 0; padding: 0; list-style: none; border-top: var(--z-bw-rule) solid var(--z-ink); }
  .zyx-rows > li { padding-block: 0.875rem; border-bottom: var(--z-bw-hair) solid var(--z-line-strong); }
  .zyx-rows.zyx-ticks > li::before { top: calc(0.875rem + 0.45em); }
  /* Numbered stages: a ruled box, the number a solid ink block in front of each. */
  .zyx-steps { margin: 0; padding: 0; list-style: none; counter-reset: zyx-step; background: var(--z-surface); }
  .zyx-steps > li { counter-increment: zyx-step; display: grid; grid-template-columns: 3rem minmax(0, 1fr); }
  .zyx-steps > li + li { border-top: var(--z-bw-hair) solid var(--z-ink); }
  .zyx-steps > li::before {
    content: counter(zyx-step, decimal-leading-zero); padding-top: 1.375rem; background: var(--z-ink); color: var(--z-on-brand);
    font-family: var(--z-font-mono); font-size: 0.75rem; font-weight: 700; line-height: 1.3; text-align: center;
  }

  /* A table that scrolls on its own on a phone, never the page. */
  .zyx-table-wrap { margin-inline: -1rem; overflow-x: auto; }
  .zyx-table { min-width: 100%; border-collapse: collapse; }
  .zyx-table > thead { border-bottom: var(--z-bw) solid var(--z-edge); }
  .zyx-table > tbody > tr + tr { border-top: var(--z-bw-hair) solid var(--z-line); }
  .zyx-table th {
    padding: 0.875rem 0.75rem; text-align: left; font-family: var(--z-font-mono); font-size: var(--z-micro); line-height: 1.5rem;
    font-weight: 700; letter-spacing: 0.08em; white-space: nowrap; text-transform: uppercase; color: var(--z-ink);
  }
  .zyx-table td { padding: 0.75rem; font-size: 0.875rem; line-height: 1.5rem; color: var(--z-muted); }
  .zyx-table :is(th, td):first-child { padding-left: 1rem; }
  .zyx-table :is(th, td):last-child { padding-right: 1rem; }
  /* A column of numbers, keys or commands: right aligned, mono, every digit as wide as the next, in
   * ink, the one thing the row is for. On a cell, or on the table for its last column. */
  .zyx-table :is(th, td).zyx-table-num, .zyx-table.zyx-table-num :is(th, td):last-child {
    padding-left: 1.125rem; text-align: right; font-family: var(--z-font-mono); font-variant-numeric: tabular-nums;
  }
  .zyx-table td.zyx-table-num, .zyx-table.zyx-table-num td:last-child { color: var(--z-ink); }
  @media (min-width: 40rem) {
    .zyx-table-wrap { margin-inline: 0; }
    .zyx-table :is(th, td):first-child { padding-left: 0; }
    .zyx-table :is(th, td):last-child { padding-right: 0; }
  }

  /* A form line: the label beside its control above 40rem, stacked below. A fact is the same with a value. */
  .zyx-form-row > label, .zyx-form-row > .zyx-form-label { display: block; min-width: 0; font-size: 0.875rem; line-height: 1.5rem; color: var(--z-muted); }
  .zyx-form-row > .zyx-form-control { margin-top: 0.25rem; min-width: 0; }
  .zyx-form-hint { margin: 0.5rem 0 0; font-size: 0.75rem; line-height: 1rem; color: var(--z-faint); }
  .zyx-fact-value { display: block; margin-top: 0.125rem; word-break: break-all; font-family: var(--z-font-mono); font-size: 0.75rem; line-height: 1rem; color: var(--z-ink); }
  @media (min-width: 40rem) {
    .zyx-form-row:not([data-stacked]) { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: baseline; gap: 1rem; }
    .zyx-form-row:not([data-stacked]) > :is(.zyx-form-control, .zyx-fact-value) { grid-column: span 2; margin-top: 0; }
  }

  /* Nothing here yet. `data-framed`: a block of its own on the ground. `zyx-empty-line`: one quiet line in a list. */
  .zyx-empty { display: flex; max-width: 24rem; flex-direction: column; align-items: center; margin-inline: auto; padding: 4rem 1.5rem; text-align: center; }
  .zyx-empty-icon { color: var(--z-muted); }
  .zyx-empty-icon > svg { width: 2.5rem; height: 2.5rem; stroke-width: 1; }
  .zyx-empty-title { margin: 0.75rem 0 0; font-size: 0.875rem; line-height: 1.5rem; font-weight: 600; color: var(--z-ink); }
  .zyx-empty-lead { margin: 0.25rem 0 0; font-size: 0.875rem; line-height: 1.5rem; color: var(--z-muted); }
  .zyx-empty-action { margin-top: 1.5rem; }
  .zyx-empty[data-framed] { max-width: none; display: block; padding: 3rem 1.5rem; border: var(--z-bw) solid var(--z-edge); border-radius: var(--z-r-card); background: var(--z-surface); }
  .zyx-empty[data-framed] > .zyx-empty-title { margin-top: 0; }
  .zyx-empty[data-framed] > .zyx-empty-lead { max-width: 24rem; margin-inline: auto; }
  .zyx-empty-line { padding: 0.5rem; font-size: 0.875rem; line-height: 1.5rem; color: var(--z-faint); }
  .zyx-empty-line > .zyx-empty-action { display: inline-block; margin: 0 0 0 0.75rem; vertical-align: middle; }
  @media (min-width: 40rem) { .zyx-empty-line { padding-inline: 0.75rem; } }

  /* The one print texture, a diagonal ink hatch: a skeleton and a disabled control. Never behind words. */
  .zyx-hatch { background-image: repeating-linear-gradient(135deg, var(--z-ink) 0 1px, transparent 1px 6px); }
  .zyx-skeleton { border: var(--z-bw-hair) solid var(--z-edge); }

  /* A popover: a thing that floats by its spot (a guide's stop, a short how-to), on the card shadow.
   * Its title is a quiet mono label, its body the screen's own text, its foot the presses (small push
   * buttons, the one that goes on last). The product places it; `zyx-stamp` brings it in. */
  .zyx-pop {
    box-sizing: border-box; width: max-content; min-width: min(13.75rem, 100%); max-width: min(20rem, 100vw - 2rem);
    padding: 0.75rem 0.875rem; border: var(--z-bw) solid var(--z-edge); border-radius: var(--z-r-ctl);
    background: var(--z-surface); color: var(--z-ink); box-shadow: var(--z-shadow-card);
    font-family: var(--z-font-text); font-size: 0.875rem; line-height: 1.5;
  }
  .zyx-pop-title {
    margin: 0 0 0.25rem; font-family: var(--z-font-mono); font-size: var(--z-micro); line-height: 1.4; font-weight: 700;
    letter-spacing: 0.08em; text-transform: uppercase; color: var(--z-muted);
  }
  .zyx-pop-body { margin: 0; }
  .zyx-pop-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 0.5rem; margin-top: 0.625rem; }
  /* "Step 2 of 4" in the foot: it stands at the start, the presses at the end. */
  .zyx-pop-step { margin-right: auto; font-family: var(--z-font-mono); font-size: 0.75rem; color: var(--z-muted); font-variant-numeric: tabular-nums; }

  /* The one tooltip: an ink block with paper words. */
  .zyx-tip {
    position: fixed; z-index: 70; max-width: 18rem; padding: 0.25rem 0.5rem; pointer-events: none;
    background: var(--z-ink); color: var(--z-surface); font-size: 12px; line-height: 1.125rem; font-weight: 500;
    white-space: pre-line; overflow-wrap: anywhere;
  }

  /* A document a tool renders (Markdown, a Word file) or a page of docs: the few rules a readable page needs. */
  .zyx-doc { max-width: 46rem; font-size: 15px; line-height: 1.75rem; color: var(--z-ink); overflow-wrap: anywhere; }
  .zyx-doc > * + * { margin-top: 0.75rem; }
  .zyx-doc :is(h1, h2, h3, h4, h5, h6) { font-weight: 600; line-height: 1.3; margin-top: 1.5rem; }
  .zyx-doc > :first-child { margin-top: 0; }
  .zyx-doc h1 { font-size: 1.6rem; }
  .zyx-doc h2 { font-size: 1.3rem; padding-bottom: 0.25rem; border-bottom: var(--z-bw-hair) solid var(--z-line); }
  .zyx-doc h3 { font-size: 1.1rem; }
  .zyx-doc :is(h4, h5, h6) { font-size: 1rem; color: var(--z-muted); }
  .zyx-doc ul { list-style: disc; padding-left: 1.5rem; }
  .zyx-doc ol { list-style: decimal; padding-left: 1.5rem; }
  .zyx-doc :is(li + li, li > ul, li > ol) { margin-top: 0.25rem; }
  .zyx-doc li:has(> input[type="checkbox"]) { list-style: none; margin-left: -1.25rem; }
  .zyx-doc input[type="checkbox"] { margin-right: 0.4rem; }
  .zyx-doc :is(a, .zyx-doc-link) { color: inherit; text-decoration: underline; text-underline-offset: 2px; text-decoration-color: var(--z-faint); }
  .zyx-doc a:not([href]) { text-decoration: none; }
  .zyx-doc blockquote { margin-inline: 0; border-left: var(--z-bw) solid var(--z-line); padding-left: 1rem; color: var(--z-muted); }
  .zyx-doc code { font-family: var(--z-font-mono); font-size: 0.85em; background: var(--z-raised); padding: 0.1em 0.3em; }
  .zyx-doc pre { font-family: var(--z-font-mono); font-size: 12px; line-height: 1.25rem; background: var(--z-raised); border: var(--z-bw-hair) solid var(--z-line); padding: 0.75rem; overflow-x: auto; }
  .zyx-doc pre code { background: none; padding: 0; font-size: inherit; }
  .zyx-doc hr { border: 0; border-top: var(--z-bw-hair) solid var(--z-line); margin: 1.5rem 0; }
  .zyx-doc img { max-width: 100%; height: auto; border: var(--z-bw-hair) solid var(--z-line); }
  .zyx-doc table { display: block; max-width: 100%; overflow-x: auto; border-collapse: collapse; font-size: 13px; line-height: 1.25rem; }
  .zyx-doc :is(th, td) { border: var(--z-bw-hair) solid var(--z-line); padding: 0.3rem 0.6rem; text-align: left; vertical-align: top; }
  .zyx-doc th { background: var(--z-raised); font-weight: 600; }
  .zyx-doc strong { font-weight: 600; }
}

@media (hover: hover) {
  .zyx-doc :is(a, .zyx-doc-link):hover { text-decoration-color: var(--z-ink); }
}

/* ---- css/site.css ---- */
/*
 * Site chrome: the parts every product page repeats, so no page hand-writes them again.
 *
 *   zyx-mark        the cube: yellow panels, ink lines on every ground; in a white box on ink or dark
 *   zyx-mark-draw   the one wipe-in of the mark on first paint (stepped, once, never a loop)
 *   zyx-lockup      the mark and a name side by side
 *   data-zyx-reveal a section whose rule, square, standing blocks and marker wait until it is seen
 *   zyx-bar         the top bar: the way up (zyx-bar-up), the page you are on (zyx-bar-here), the end
 *   zyx-lang        the EN/DE pair at the end of the bar; the chosen one has `aria-current`
 *   zyx-cmd         an install line that scrolls on its own, with a copy button that does not jump
 *   zyx-foot        the footer: a ruled grid of a brand cell, link columns and the legal line
 *   zyx-faq         questions on `zyx-fold`; `data-numbered` puts a number in front of each
 *   zyx-rule-bleed  a `zyx-rule` whose line runs the full window width, with no side scroll
 *   zyx-band        a section whose ground runs the full window width, with no side scroll
 *
 * The rest look is in `zyx-components`. What changes with a state (a revealed section, a copied
 * command) is unlayered, like the states in controls.css.
 */

/* The mark wipes in from the left, in 4 steps. */
@keyframes zyx-mark-draw { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0); } }
/* The marker draws in behind its words, in 4 steps. */
@keyframes zyx-marker-wipe { from { background-size: 0 100%; } to { background-size: 100% 100%; } }
/* A window-wide rule draws from the window's left edge, in the same steps as `zyx-draw`. The line is
 * the border image of a zero-wide box in the middle (see zyx-rule-bleed), so it is cut open with
 * clip-path, not scaled; on that box `50%` is 0, so the steps are the window's left half, middle,
 * right half. */
@keyframes zyx-rule-bleed {
  0% { clip-path: inset(0 calc(50% + 25vw) 0 -100vmax); }
  25% { clip-path: inset(0 50% 0 -100vmax); }
  50% { clip-path: inset(0 calc(50% - 25vw) 0 -100vmax); }
  75% { clip-path: inset(0 -100vmax); }
}

@layer zyx-components {
  /* ---- Mark ---- */

  /* The cube is two paths: the yellow hexagon first, then the ink lines as one filled shape, so the
   * yellow shows through the three panels. The box behind it is the svg's own ground: clear in
   * light, white in dark (`--z-mark-box`), so the ink lines are seen on every ground. Size it with
   * `width`/`height` or `--zyx-mark-size`. */
  .zyx-mark {
    --zyx-mark-box: var(--z-mark-box);
    display: inline-block; flex: none; vertical-align: middle; background: var(--zyx-mark-box);
  }
  .zyx-mark:not([width]) { width: var(--zyx-mark-size, 1.375rem); }
  .zyx-mark:not([height]) { height: var(--zyx-mark-size, 1.375rem); }
  .zyx-mark-panels { fill: var(--z-cube); }
  .zyx-mark-lines { fill: var(--z-mark-line); }
  /* On an ink ground the lines would be lost: the mark sits in a white box (`--z-mark-paper`, white in both themes). */
  .zyx-mark[data-boxed], .zyx-cell-ink .zyx-mark, .zyx-on-brand .zyx-mark { --zyx-mark-box: var(--z-mark-paper); }
  /* The one mark motion the brand allows: a wipe-in on first paint. Less motion: it is simply there. */
  .zyx-mark-draw { animation: zyx-mark-draw var(--z-d3) steps(4, end) 1 both; }

  /* The mark and a name: the lockup of a brand or a product. */
  .zyx-lockup {
    display: inline-flex; align-items: center; gap: 0.625rem; color: var(--z-ink); text-decoration: none;
    font-family: var(--z-wm-font); font-size: 1.0625rem; font-weight: var(--z-wm-weight); letter-spacing: var(--z-wm-track);
  }

  /* ---- Bar ---- */

  /* A ruled row of cells as wide as its column: the way up, the page you are on, then the end
   * cells. Add `zyx-stand` and it stands on the block shadow with the 3px edge. A button in it is a
   * cell like a link: no frame of its own. */
  .zyx-bar :where(button) {
    appearance: none; margin: 0; border: 0 solid var(--z-ink); border-radius: 0;
    background: transparent; color: inherit; font: inherit; text-transform: inherit;
  }
  .zyx-bar {
    display: flex; align-items: stretch; min-height: var(--z-row-lg); border: var(--z-bw) solid var(--z-ink); background: var(--z-surface);
  }
  .zyx-bar.zyx-stand { border-width: var(--z-bw-block); }
  .zyx-bar > * + *, .zyx-bar-end > * + *, .zyx-lang > * + * { border-left: var(--z-bw-rule) solid var(--z-ink); }
  .zyx-bar-up, .zyx-bar-here {
    display: flex; align-items: center; gap: 0.625rem; min-width: 0; padding: 0 0.875rem;
    font-family: var(--z-wm-font); font-size: 1.0625rem; font-weight: var(--z-wm-weight); letter-spacing: var(--z-wm-track);
    line-height: 1.2; white-space: nowrap; text-decoration: none;
  }
  /* The parent half of the breadcrumb is muted, so the page you are ON reads first. The ink edge
   * between the two cells stands in for the "/". */
  .zyx-bar-up { color: var(--z-muted); }
  .zyx-bar-end { display: flex; align-items: stretch; margin-left: auto; }
  .zyx-bar-end > .zyx-cell {
    display: flex; align-items: center; justify-content: center; padding: 0 1rem;
    font-size: 0.84375rem; font-weight: 700; line-height: 1.2; white-space: nowrap; text-decoration: none;
  }
  /* The language pair: two square mono cells, the chosen one inverted (`aria-current` or `aria-pressed`). */
  .zyx-lang { display: flex; align-items: stretch; font-family: var(--z-font-mono); font-size: var(--z-small); font-weight: 700; text-transform: uppercase; }
  .zyx-lang > * {
    display: flex; align-items: center; justify-content: center; min-width: 3rem; padding: 0 0.875rem; text-decoration: none;
  }
  /* On a phone the WAY BACK is what stays, not the page you are already on (its name is in the h1
   * and the tab): the parent takes the room, behind an arrow that says it is a door, 44px high. */
  @media (max-width: 35rem) {
    .zyx-bar-here { display: none; }
    .zyx-bar-up { flex: 1; min-height: 2.75rem; padding: 0 0.75rem; }
    .zyx-bar-up::before { content: "\2190"; content: "\2190" / ""; font-weight: 400; }
    .zyx-bar-up > :last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
    .zyx-bar-end > .zyx-cell { padding-inline: 0.75rem; }
    .zyx-lang > * { min-width: 2.75rem; padding-inline: 0.5rem; }
  }
  /* On the narrowest phones an end label breaks rather than push the bar wider than the page. */
  @media (max-width: 22.5rem) { .zyx-bar-end > .zyx-cell { white-space: normal; text-align: center; } }

  /* ---- Command ---- */

  /* An install line. The LINE scrolls, not the row: a copy button that scrolls out of sight with a
   * long command is one nobody finds on a phone. Wear it with `zyx-stand`. */
  .zyx-cmd { display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem 0.875rem 0.75rem 1rem; }
  .zyx-cmd-line { flex: 1; min-width: 0; overflow-x: auto; }
  .zyx-cmd-line > code { font-family: var(--z-font-mono); font-size: 0.84375rem; line-height: 1.5; color: var(--z-ink); white-space: pre; }
  /* A block caret after the command, drawn by CSS so "copy" does not copy it. On a long line it
   * sticks to the right edge, on a paper gap, instead of being cut or scrolled away. */
  .zyx-cmd-line > code::after {
    content: ""; position: sticky; right: 0; display: inline-block; width: 0.55em; height: 1.1em; margin-left: 0.375rem;
    vertical-align: -0.2em; background: var(--z-ink); box-shadow: calc(var(--z-u) * -1) 0 0 var(--z-surface);
  }
  @media (prefers-reduced-motion: no-preference) {
    /* It blinks three times, then it stands: a thing that waits for you, not a loop. */
    .zyx-cmd-line > code::after { animation: zyx-blink var(--z-d2) step-end var(--z-d3) 3 backwards; }
  }
  /* The copy button: a second button in mono, wide enough for its longer word, so "Copy" and
   * "Copied" do not change its size. */
  .zyx-cmd-copy { min-width: calc(8ch + 2rem); font-family: var(--z-font-mono); font-weight: 700; }

  /* ---- Footer ---- */

  /* One ruled grid: the brand cell and a column per list of links, the legal line closes it.
   * `--zyx-foot-cols` is the number of columns (the React part sets it). Add `zyx-stand` to stand. */
  .zyx-foot {
    display: grid; grid-template-columns: minmax(0, 1.5fr) repeat(var(--zyx-foot-cols, 3), minmax(0, 1fr));
    gap: var(--z-bw); border: var(--z-bw) solid var(--z-ink); background: var(--z-ink);
  }
  .zyx-foot.zyx-stand { border-width: var(--z-bw-block); background: var(--z-ink); }
  .zyx-foot > * { min-width: 0; margin: 0; background: var(--z-surface); }
  .zyx-foot-brand { padding: 1rem 0.875rem 1.25rem; }
  .zyx-foot-brand :where(p) { margin: 0.875rem 0 0; max-width: 42ch; font-size: 0.90625rem; line-height: 1.5; color: var(--z-muted); }
  .zyx-foot-col { display: flex; flex-direction: column; }
  .zyx-foot-col > .zyx-label { min-height: 2.75rem; margin: 0; padding: 0 0.875rem; }
  .zyx-foot-col > ul { flex: 1; margin: 0; padding: 0; list-style: none; border-top: var(--z-bw-rule) solid var(--z-ink); }
  .zyx-foot-col .zyx-cell {
    display: flex; align-items: center; justify-content: space-between; gap: 0.625rem; min-height: var(--z-row);
    padding: 0.5rem 0.875rem; font-size: 0.90625rem; line-height: 1.3; text-decoration: none;
  }
  .zyx-foot-legal {
    grid-column: 1 / -1; padding: 0.75rem 0.875rem; font-family: var(--z-font-mono); font-size: 0.75rem; line-height: 1.5;
  }
  .zyx-foot > .zyx-foot-legal { background: var(--z-ground); color: var(--z-faint); }
  /* `zyx-foot-stack`, for a narrow page column: the brand takes its own row, its words beside the
   * lockup, and the link columns share the full width under it. */
  .zyx-foot-stack { grid-template-columns: repeat(var(--zyx-foot-cols, 3), minmax(0, 1fr)); }
  .zyx-foot-stack > .zyx-foot-brand { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 2rem; }
  .zyx-foot-stack > .zyx-foot-brand :where(p) { flex: 1 1 20rem; margin: 0; }
  /* A tablet: the brand on its own row, two columns under it; a lone last column takes the row. */
  @media (max-width: 48rem) {
    .zyx-foot { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .zyx-foot-brand { grid-column: 1 / -1; }
    .zyx-foot-brand ~ .zyx-foot-col:nth-child(even):is(:last-child, :nth-last-child(2):has(+ .zyx-foot-legal)) { grid-column: 1 / -1; }
  }
  /* A phone: one column. */
  @media (max-width: 30rem) { .zyx-foot { grid-template-columns: minmax(0, 1fr); } }

  /* ---- FAQ ---- */

  /* Questions on `zyx-fold`: native <details>, so it works with no script and the answers stay in
   * the page while closed. The outer rules are ink: the questions are controls. */
  .zyx-faq { border-block: var(--z-bw-rule) solid var(--z-ink); }
  .zyx-faq > .zyx-fold + .zyx-fold { border-top: var(--z-bw-hair) solid var(--z-ink); }
  .zyx-faq > .zyx-fold > summary { padding: 1rem 0.875rem; font-size: 1.0625rem; font-weight: 700; line-height: 1.3; }
  /* An open question is one piece: its answer sits on the same paper. */
  .zyx-faq > .zyx-fold[open] { background: var(--z-surface); }
  .zyx-faq-q { flex: 1; min-width: 0; text-wrap: balance; }
  .zyx-faq-a { max-width: 64ch; padding: 0 0.875rem 1.25rem; color: var(--z-muted); text-wrap: pretty; }
  .zyx-faq-a > :first-child { margin-top: 0; }
  .zyx-faq-a > :last-child { margin-bottom: 0; }
  /* The number is for the eye: a screen reader reads the question only. */
  .zyx-faq[data-numbered] { counter-reset: zyx-faq; }
  .zyx-faq[data-numbered] > .zyx-fold { counter-increment: zyx-faq; }
  .zyx-faq[data-numbered] > .zyx-fold > summary::before {
    content: counter(zyx-faq, decimal-leading-zero); content: counter(zyx-faq, decimal-leading-zero) / "";
    flex: none; width: 2rem; font-family: var(--z-font-mono); font-size: 0.75rem; font-weight: 400; letter-spacing: 0.08em; color: var(--z-muted);
  }
  /* The answer starts under the question, past the number and the fold's 1rem gap. */
  .zyx-faq[data-numbered] .zyx-faq-a { padding-left: calc(0.875rem + 2rem + 1rem); }

  /* ---- Rule bleed ---- */

  /* The rule's line runs the whole window width. The line is a zero-wide box in the middle of its
   * section and a border image with outset paints it on both sides: like a shadow it is never
   * scrollable overflow, so the page gets no side scroll and needs no `overflow-x: clip` on its root.
   * All of the line is outset, so on a half-pixel top it rounds the same way along the whole width. */
  .zyx-rule.zyx-rule-bleed::before {
    left: 50%; right: 50%; background: none; border-image: linear-gradient(var(--z-edge) 0 0) fill 0 / 0 / 0 100vmax;
    clip-path: inset(0 -100vmax); animation-name: zyx-rule-bleed;
  }

  /* ---- Band ---- */

  /* A section whose ground runs the whole window width while its text stays in the column: the same
   * border image with outset, so no side scroll and no layout change. `--zyx-band` is the ground
   * (default `--z-raised`); white and ground can take turns with `--zyx-band: var(--z-surface)`. */
  .zyx-band { border-image: linear-gradient(var(--zyx-band, var(--z-raised)) 0 0) fill 0 / 0 / 0 100vmax; }
}

/* ---- States (unlayered) ---- */

/* Copied: the button is inverted for a moment, also on a phone with no hover. */
.zyx-btn.zyx-push[data-done] { border-color: var(--z-ink); background: var(--z-ink); color: var(--z-surface); box-shadow: none; translate: none; }
/* The main button keeps its hover look for that moment: pressed in and yellow, also on a phone with no hover. */
.zyx-btn.zyx-main[data-done] {
  translate: var(--z-cta-travel) var(--z-cta-travel); box-shadow: var(--z-shadow-cta-down);
  border-color: var(--z-on-signal); background: var(--z-signal); color: var(--z-on-signal);
}

/*
 * Reveal. A `[data-zyx-reveal]` section waits until it is seen, then plays once (`="on"`): its rule
 * draws in, its numbered square stamps in, what stands on a shadow lands on it, the marker wipes in,
 * the caret blinks. `--zyx-reveal-delay` holds one element back. Only under `html.zyx-js`, which
 * the reveal script sets, and only with motion: with no script or with less motion all of it shows.
 * A paused animation waits on its first frame, so a block waits where `zyx-land` starts it.
 * A reveal inside a reveal waits on its own: the wait rules weigh more than the play rules, and
 * each one stops the animation, so a section that plays does not play what still waits in it.
 */
@media (prefers-reduced-motion: no-preference) {
  :is(html.zyx-js [data-zyx-reveal]:not([data-zyx-reveal="on"]).zyx-rule, html.zyx-js [data-zyx-reveal]:not([data-zyx-reveal="on"]) .zyx-rule)::before {
    animation: none; scale: 0 1;
  }
  :is(html.zyx-js [data-zyx-reveal]:not([data-zyx-reveal="on"]).zyx-eyebrow-n, html.zyx-js [data-zyx-reveal]:not([data-zyx-reveal="on"]) .zyx-eyebrow-n)::after {
    animation: none; scale: 0;
  }
  :is(html.zyx-js [data-zyx-reveal]:not([data-zyx-reveal="on"]), html.zyx-js [data-zyx-reveal]:not([data-zyx-reveal="on"]) *):is(.zyx-stand, .zyx-card-stand, .zyx-window) {
    animation: zyx-land var(--z-d2) step-end var(--zyx-reveal-delay, 0s) 1 backwards; animation-play-state: paused;
  }
  :is(html.zyx-js [data-zyx-reveal]:not([data-zyx-reveal="on"]), html.zyx-js [data-zyx-reveal]:not([data-zyx-reveal="on"]) *).zyx-marker {
    animation: none; background-size: 0 100%;
  }
  html.zyx-js [data-zyx-reveal]:not([data-zyx-reveal="on"]) .zyx-cmd-line > code::after { animation-play-state: paused; }

  :is(html.zyx-js [data-zyx-reveal="on"].zyx-rule, html.zyx-js [data-zyx-reveal="on"] .zyx-rule)::before {
    animation: zyx-draw var(--z-d2) step-end var(--zyx-reveal-delay, 0s) 1 backwards;
  }
  :is(html.zyx-js [data-zyx-reveal="on"].zyx-rule-bleed, html.zyx-js [data-zyx-reveal="on"] .zyx-rule-bleed)::before {
    animation-name: zyx-rule-bleed;
  }
  :is(html.zyx-js [data-zyx-reveal="on"].zyx-eyebrow-n, html.zyx-js [data-zyx-reveal="on"] .zyx-eyebrow-n)::after {
    animation: zyx-square var(--z-d1) step-end calc(var(--z-d2) + var(--zyx-reveal-delay, 0s)) 1 backwards;
  }
  :is(html.zyx-js [data-zyx-reveal="on"], html.zyx-js [data-zyx-reveal="on"] *):is(.zyx-stand, .zyx-card-stand, .zyx-window) {
    animation: zyx-land var(--z-d2) step-end var(--zyx-reveal-delay, 0s) 1 backwards;
  }
  :is(html.zyx-js [data-zyx-reveal="on"], html.zyx-js [data-zyx-reveal="on"] *).zyx-marker {
    animation: zyx-marker-wipe var(--z-d2) steps(4, end) calc(var(--z-d1) + var(--zyx-reveal-delay, 0s)) 1 backwards;
  }
}

/* A drawn mark that also hops (motion.css): the hop is added after the draw, so the draw keeps its
 * place in the list and does not play again when the pointer leaves. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  :is(.zyx-cell, .zyx-push, .zyx-row):hover .zyx-mark-draw.zyx-hop {
    animation: zyx-mark-draw var(--z-d3) steps(4, end) 1 both, zyx-hop var(--z-d1) step-end 1;
  }
}

/* ---- css/motion.css ---- */
/*
 * Motion. Every movement is one of the names below; a screen never writes its own keyframes. Each is
 * stepped, runs once, lasts `--z-d1` (180ms) or at most `--z-d2` (200ms), and moves only `translate`,
 * `scale`, `box-shadow` or `opacity`. Each runs when its element APPEARS or its state CHANGES, never
 * on a re-render. Less motion asked for: the rule in base.css switches all of it off.
 *
 *   zyx-in       a new message rises in, once
 *   zyx-stamp    a thing that appears on its hard shadow (toast, menu, dialog): flat, then up in 2 steps
 *   zyx-land     the one main block of a screen lands on its shadow, in 3 steps (first paint only)
 *   zyx-hop      the icon in a cell: one stepped hop when the cell is hovered
 *   zyx-flip     a count that appears or changes (set by zyx-count)
 *   zyx-grow     a block whose shadow grows in steps when the cursor goes in (the message box)
 *   zyx-blink    one hard blink that ends: a thing that just started working
 *   zyx-loading  three ink squares, one after the other, `--z-d-loop` a round: the ONE movement that repeats
 *   zyx-sheet    a panel from the right: it glides (translate only), in `--z-d1`, out in `--z-d-press`
 *   zyx-veil     the dimmed page behind a sheet: opacity only, in step with the sheet
 *   zyx-rule / zyx-square   a section's rule draws in from the left, then its square stamps in
 */
@keyframes zyx-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@keyframes zyx-stamp {
  0% { box-shadow: 0 0 0 var(--z-edge); translate: 3px 3px; }
  50% { box-shadow: var(--z-shadow-near); translate: 1px 1px; }
}
@keyframes zyx-tick { 0% { scale: 0.4; } 50% { scale: 0.7; } }
@keyframes zyx-flip { 0% { scale: 1 0.15; } 50% { scale: 1 0.6; } }
@keyframes zyx-loading { 0%, 33% { opacity: 1; } 34%, 100% { opacity: 0.2; } }
@keyframes zyx-hop { 0% { translate: 0 -3px; } 45% { translate: 0 1px; } 75% { translate: 0 0; } }
@keyframes zyx-draw { 0% { scale: 0.25 1; } 25% { scale: 0.5 1; } 50% { scale: 0.75 1; } 75% { scale: 1 1; } }
@keyframes zyx-square { 0% { scale: 0; } 50% { scale: 1.5; } }
/* The two steps above the block shadow have no token of their own: they exist only on the way down. */
@keyframes zyx-land {
  /* zyx-ui-allow: a step of the land, between two shadow tokens */
  0% { translate: -4px -4px; box-shadow: 8px 8px 0 var(--z-ink); }
  /* zyx-ui-allow: a step of the land, between two shadow tokens */
  34% { translate: -2px -2px; box-shadow: 6px 6px 0 var(--z-ink); }
  67% { translate: 0 0; box-shadow: var(--z-shadow-block); }
}
@keyframes zyx-blink { 0% { opacity: 0.3; } 50% { opacity: 1; } }

@layer zyx-components {
  .zyx-in { animation: zyx-in var(--z-d2) var(--z-ease); }
  .zyx-stamp { animation: zyx-stamp var(--z-d1) step-end 1; }
  .zyx-land { animation: zyx-land var(--z-d2) step-end 1; }
  .zyx-blink { animation: zyx-blink var(--z-d2) step-end 1; }
  .zyx-flip { animation: zyx-flip var(--z-d1) step-end 1; }
  .zyx-grow { transition: box-shadow var(--z-d1) steps(3, end), border-color var(--z-d1) steps(3, end); }
  .zyx-rule::before { animation: zyx-draw var(--z-d2) step-end 1; }
  .zyx-square { animation: zyx-square var(--z-d1) step-end var(--z-d2) 1 backwards; }
  .zyx-loading { display: inline-flex; align-items: center; gap: 3px; }
  .zyx-loading > * { width: 6px; height: 6px; background: var(--z-ink); animation: zyx-loading var(--z-d-loop) step-end infinite; }
  .zyx-loading > :nth-child(2) { animation-delay: calc(var(--z-d-loop) / 3); }
  .zyx-loading > :nth-child(3) { animation-delay: calc(var(--z-d-loop) * 2 / 3); }
  /* `data-closed`, `data-transition` and `data-leave` are what Headless UI and Base UI set on a transition. */
  .zyx-sheet { transition: translate var(--z-d1) var(--z-ease); }
  .zyx-sheet[data-transition] { will-change: translate; }
  .zyx-sheet[data-closed] { translate: 100% 0; }
  .zyx-veil { transition: opacity var(--z-d1) var(--z-ease); }
  .zyx-veil[data-closed] { opacity: 0; }
  :is(.zyx-sheet, .zyx-veil)[data-leave] { transition-duration: var(--z-d-press); }
}

@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  :is(.zyx-cell, .zyx-push, .zyx-row):hover .zyx-hop { animation: zyx-hop var(--z-d1) step-end 1; }
  .zyx-row:hover .zyx-tool:nth-child(2) .zyx-hop { animation-delay: var(--z-d-step); }
  .zyx-row:hover .zyx-tool:nth-child(3) .zyx-hop { animation-delay: calc(var(--z-d-step) * 2); }
}
/* A check box ticked under the pointer or by the keyboard: its tick stamps in. */
@media (prefers-reduced-motion: no-preference) {
  :is(input[type="checkbox"], input[type="radio"]):checked:is(:hover, :focus-visible)::before { animation: zyx-tick var(--z-d1) step-end 1; }
}
