/* Vendored from ~/.agents/design/kit/components/components.css on 2026-11-08. Do not edit here: change the kit, then re-copy. Project overrides live in ../vanity.css. */
/* Component classes. Plain names, roles only (theme.css), spacing from the --s-* scale, type from the
   --type-* ramp, radius from the three --radius-* tokens. Depth is a tone step: ground, surface, raised.
   Lines only where the core allows them: .table-dense, .kv rows, .row-list rows, .coin-row rows, inputs,
   .field and .menu-sep. Shadows only on things that float: tooltip, popover, dialog, sheet, toast.
   Mono only on .addr (addresses, hashes) and .code-pre (code); numbers use the body face, tabular.
   Every control has hover, focus-visible, active (scale .97), disabled and loading (.is-loading or
   aria-busy="true"), 28/32/36px heights and a 44px hit area on coarse pointers.
   Motion is transform and opacity; base.css zeroes durations under prefers-reduced-motion.
   Tint any block with data-tone="positive|ok|up, negative|destructive|bad|down, warning|warn|wait, info, neutral". */

@layer components {
  /* Icon: sprite icons are 1px strokes in a 24 box; 1.5 reads at small sizes. Sized by the em. */
  .icon,
  .btn svg,
  .input-group > svg,
  .search > svg,
  .addr svg,
  .toast > svg {
    stroke-width: 1.5;
  }

  .icon {
    width: 1em;
    height: 1em;
    flex: none;
  }

  /* ------------------------------------------------------------------ Shared control behaviour */

  /* 44px hit area on touch without changing the drawn size */
  @media (pointer: coarse) {
    :is(.btn, .chip-toggle, .seg > button, .seg > label, .addr, .switch)::before {
      content: "";
      position: absolute;
      top: 50%;
      left: 50%;
      width: max(100%, var(--hit));
      height: max(100%, var(--hit));
      transform: translate(-50%, -50%);
    }

    .tab,
    .menu-item {
      min-height: var(--hit);
    }
  }

  /* Loading: the label stays in place (so the size never changes) and a spinner sits over it */
  :is(.btn, .chip-toggle, .seg > button, .menu-item, .addr, .step):is(.is-loading, [aria-busy="true"]) {
    color: transparent;
    pointer-events: none;
  }

  :is(.btn, .chip-toggle, .seg > button, .menu-item, .addr, .step):is(.is-loading, [aria-busy="true"])::after {
    content: "";
    position: absolute;
    inset: 0;
    width: 1em;
    height: 1em;
    margin: auto;
    border: 2px solid var(--ink);
    border-right-color: transparent;
    border-radius: var(--radius-pill);
    animation: spin var(--duration-long) var(--ease-linear) infinite;
  }

  @keyframes spin {
    to {
      transform: rotate(360deg);
    }
  }

  /* ------------------------------------------------------------------ Buttons */

  /* Base button = secondary: the raised-hover tone. Sizes set --btn-h; variants set --btn-bg, --btn-hover, --ink. */
  .btn {
    --btn-h: var(--control-md);
    --btn-bg: var(--raised-hover);
    --btn-hover: var(--raised-active);
    --ink: var(--text-strong);
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    gap: var(--s-2);
    height: var(--btn-h);
    padding: 0 var(--s-3);
    border: 0;
    border-radius: var(--radius-control);
    background: var(--btn-bg);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: var(--type-body);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition:
      background-color var(--duration-fast) var(--ease-out),
      color var(--duration-fast) var(--ease-out),
      transform var(--duration-fast) var(--ease-out);
  }

  .btn:hover {
    background: var(--btn-hover);
  }

  .btn:active {
    transform: scale(0.97);
  }

  .btn:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
  }

  /* Icon slot: any svg or .icon inside a button, current colour, scales with the button */
  .btn svg,
  .btn .icon {
    width: 1em;
    height: 1em;
    flex: none;
    fill: currentColor;
  }

  .btn svg[fill="none"] {
    fill: none;
    stroke: currentColor;
  }

  /* Primary: the one accent fill per region (a preset may point --primary at the strong text tone) */
  .btn-primary {
    --btn-bg: var(--primary);
    --btn-hover: var(--primary-hover);
    --ink: var(--primary-foreground);
    font-weight: 600;
  }

  .btn-secondary {
    --btn-bg: var(--raised-hover);
    --btn-hover: var(--raised-active);
  }

  /* Outline: no line; the quieter neutral tone step (raised) */
  .btn-outline {
    --btn-bg: var(--raised);
    --btn-hover: var(--raised-hover);
  }

  /* Ghost: text only, raised on hover */
  .btn-ghost {
    --btn-bg: transparent;
    --btn-hover: var(--veil);
    --ink: var(--text-body);
  }

  .btn-ghost:hover {
    color: var(--text-strong);
  }

  /* Destructive and positive: the signal on its own tint (irreversible action, buy) */
  .btn-destructive {
    --btn-bg: color-mix(in oklab, var(--negative) 12%, transparent);
    --btn-hover: color-mix(in oklab, var(--negative) 18%, transparent);
    --ink: color-mix(in oklab, var(--negative) 75%, var(--text-strong));
  }

  .btn-positive {
    --btn-bg: color-mix(in oklab, var(--positive) 12%, transparent);
    --btn-hover: color-mix(in oklab, var(--positive) 18%, transparent);
    --ink: color-mix(in oklab, var(--positive) 75%, var(--text-strong));
    font-weight: 600;
  }

  .btn-sm {
    --btn-h: var(--control-sm);
    padding: 0 var(--s-2);
    font-size: var(--type-small);
    gap: var(--s-1);
  }

  .btn-lg {
    --btn-h: var(--control-lg);
    padding: 0 var(--s-4);
  }

  /* Icon button: a square of the size's height. Give it aria-label and a tooltip. */
  .btn-icon {
    width: var(--btn-h);
    padding: 0;
  }

  .btn-icon svg {
    width: 1.125em;
    height: 1.125em;
  }

  /* Disabled: the neutral tone with dim text (4.5:1), no accent, no press */
  .btn:disabled,
  .btn[aria-disabled="true"] {
    --btn-bg: var(--raised);
    --btn-hover: var(--raised);
    --ink: var(--text-dim);
    cursor: not-allowed;
    transform: none;
  }

  .btn-ghost:disabled,
  .btn-ghost[aria-disabled="true"] {
    --btn-bg: transparent;
    --btn-hover: transparent;
  }

  /* ------------------------------------------------------------------ Inputs and fields */

  /* Text input: a well one tone below its panel, a 3:1 field line, the focus ring on focus */
  .input {
    width: 100%;
    min-width: 0;
    height: var(--control-md);
    padding: 0 var(--s-3);
    border: 1px solid var(--line);
    border-radius: var(--radius-control);
    background: var(--ground);
    color: var(--text-strong);
    font-size: var(--type-body);
    transition: border-color var(--duration-fast) var(--ease-out);
  }

  textarea.input {
    height: auto;
    min-height: 4.5rem;
    padding-block: var(--s-2);
    line-height: var(--leading-body);
  }

  select.input {
    padding-right: var(--s-2);
    cursor: pointer;
  }

  .input::placeholder {
    color: var(--text-dim);
  }

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

  .input:focus-visible {
    border-color: var(--focus);
    outline: 2px solid var(--focus);
    outline-offset: 2px;
  }

  .input[aria-invalid="true"] {
    border-color: var(--negative);
  }

  .input:disabled {
    border-color: var(--line-row);
    background: var(--raised);
    color: var(--text-dim);
    cursor: not-allowed;
  }

  /* Input group: an input-looking box holding an icon, a bare input, a unit or a kbd hint. Search and amount fields. */
  .input-group,
  .search {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    width: 100%;
    height: var(--control-md);
    padding: 0 var(--s-1) 0 var(--s-3);
    border: 1px solid var(--line);
    border-radius: var(--radius-control);
    background: var(--ground);
    color: var(--text-dim);
    font-size: var(--type-body);
    transition: border-color var(--duration-fast) var(--ease-out);
  }

  .input-group:hover,
  .search:hover {
    border-color: var(--text-dim);
  }

  .input-group:focus-within,
  .search:focus-within {
    border-color: var(--focus);
    outline: 2px solid var(--focus);
    outline-offset: 2px;
  }

  .input-group:has(input:disabled),
  .search:has(input:disabled) {
    border-color: var(--line-row);
    background: var(--raised);
    cursor: not-allowed;
  }

  .input-group > svg,
  .search > svg {
    width: 0.875rem;
    height: 0.875rem;
    flex: none;
    fill: none;
    stroke: currentColor;
  }

  .input-group > input,
  .search > input {
    flex: 1;
    min-width: 0;
    height: 100%;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-strong);
    font-size: inherit;
    outline: 0;
  }

  .input-group > input::placeholder,
  .search > input::placeholder {
    color: var(--text-dim);
  }

  /* Loading: the leading icon becomes a spinner, the box keeps its size */
  .search:is(.is-loading, [aria-busy="true"]) > svg,
  .input-group:is(.is-loading, [aria-busy="true"]) > svg {
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: var(--radius-pill);
    animation: spin var(--duration-long) var(--ease-linear) infinite;
  }

  .search:is(.is-loading, [aria-busy="true"]) > svg > *,
  .input-group:is(.is-loading, [aria-busy="true"]) > svg > * {
    visibility: hidden;
  }

  /* Amount input: right-aligned tabular figure with a unit suffix ("SOL") */
  .input-group.is-amount > input {
    text-align: right;
    font-variant-numeric: tabular-nums;
  }

  .input-unit {
    flex: none;
    padding-right: var(--s-2);
    color: var(--text-dim);
    font-size: var(--type-small);
  }

  /* Phones: 16px so iOS does not zoom on focus */
  @media (pointer: coarse) {
    .input,
    .input-group > input,
    .search > input {
      font-size: max(16px, var(--type-reading));
    }
  }

  /* Field: label, control, then a message slot that keeps its height (hint, or the error in its place) */
  .field {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
    min-width: 0;
  }

  .field-label {
    color: var(--text-strong);
    font-size: var(--type-small);
    font-weight: 500;
  }

  .field-hint,
  .field-error {
    display: flex;
    align-items: center;
    gap: var(--s-1);
    min-height: calc(var(--type-label) * var(--leading-tight));
    color: var(--text-dim);
    font-size: var(--type-label);
    line-height: var(--leading-tight);
  }

  .field-error {
    color: var(--negative);
  }

  .field-error svg {
    width: 1em;
    height: 1em;
    flex: none;
    fill: none;
    stroke: currentColor;
  }

  .field[data-invalid] .input,
  .field[data-invalid] .input-group {
    border-color: var(--negative);
  }

  /* Keyboard key: body face, 12px, raised tone */
  .kbd {
    display: inline-grid;
    min-width: 1.5rem;
    height: 1.5rem;
    padding: 0 var(--s-1);
    place-items: center;
    flex: none;
    border-radius: var(--radius-control);
    background: var(--raised-hover);
    color: var(--text-body);
    font-family: var(--font-sans);
    font-size: var(--type-label);
    font-weight: 500;
    line-height: 1;
  }

  /* ------------------------------------------------------------------ Segmented control, tabs, toggles */

  /* Segmented control (SOL | USD, P1 P2 P3). Options are buttons with aria-checked or aria-pressed,
     or labels around a hidden radio. The selected option is one tone up and bold. */
  .seg {
    display: inline-flex;
    flex: none;
    gap: var(--s-1);
    height: var(--control-md);
    padding: var(--s-1);
    border-radius: var(--radius-control);
    background: var(--ground);
    font-size: var(--type-small);
  }

  .seg > button,
  .seg > label {
    --ink: var(--text-dim);
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--s-6);
    padding: 0 var(--s-2);
    border: 0;
    border-radius: var(--radius-control);
    background: transparent;
    color: var(--ink);
    font: inherit;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition:
      background-color var(--duration-fast) var(--ease-out),
      color var(--duration-fast) var(--ease-out),
      transform var(--duration-fast) var(--ease-out);
  }

  .seg > button:hover,
  .seg > label:hover {
    --ink: var(--text-strong);
  }

  .seg > button:active,
  .seg > label:active {
    transform: scale(0.97);
  }

  .seg > [aria-checked="true"],
  .seg > [aria-selected="true"],
  .seg > [aria-pressed="true"],
  .seg > .is-active,
  .seg > label:has(input:checked) {
    --ink: var(--text-strong);
    background: var(--raised-hover);
    font-weight: 600;
  }

  .seg > label:has(input:focus-visible),
  .seg > button:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
  }

  .seg > button:disabled,
  .seg > label:has(input:disabled) {
    --ink: var(--text-dim);
    background: transparent;
    cursor: not-allowed;
    transform: none;
    text-decoration: line-through;
  }

  .seg input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
  }

  .seg-lg {
    height: var(--control-lg);
    font-size: var(--type-body);
  }

  .seg-lg > button,
  .seg-lg > label {
    padding: 0 var(--s-3);
  }

  /* Tabs with an active underline in the accent (colour plus a second cue: weight and the bar).
     Active: aria-selected, aria-current or .is-active. */
  .tabs {
    display: flex;
    align-items: stretch;
    gap: var(--s-5);
    min-width: 0;
  }

  .tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    height: var(--control-lg);
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text-dim);
    font-size: var(--type-body);
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition:
      color var(--duration-fast) var(--ease-out),
      transform var(--duration-fast) var(--ease-out);
  }

  .tab::after {
    content: "";
    position: absolute;
    inset: auto 0 0;
    height: 0.125rem;
    background: var(--accent);
    transform: scaleX(0);
    transition: transform var(--duration-base) var(--ease-out);
  }

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

  .tab:active {
    transform: scale(0.97);
  }

  .tab[aria-selected="true"],
  .tab[aria-current]:not([aria-current="false"]),
  .tab.is-active {
    color: var(--text-strong);
    font-weight: 600;
  }

  .tab[aria-selected="true"]::after,
  .tab[aria-current]:not([aria-current="false"])::after,
  .tab.is-active::after {
    transform: scaleX(1);
  }

  .tab[aria-disabled="true"],
  .tab:disabled {
    color: var(--text-dim);
    cursor: not-allowed;
    transform: none;
    text-decoration: line-through;
  }

  /* Loading tab: the label stays, a small spinner leads it */
  .tab:is(.is-loading, [aria-busy="true"])::before {
    content: "";
    width: 0.75em;
    height: 0.75em;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: var(--radius-pill);
    animation: spin var(--duration-long) var(--ease-linear) infinite;
  }

  .tab .count-quiet {
    font-size: var(--type-label);
  }

  /* Top-nav tabs: full header height, the clipped edge fades when it scrolls */
  .tabs-nav {
    gap: var(--s-5);
    overflow-x: auto;
    scrollbar-width: none;
  }

  .tabs-nav::-webkit-scrollbar {
    display: none;
  }

  .tabs-nav .tab {
    height: var(--header-height);
  }

  /* Toggle chip: a filter you switch on and off. Pressed takes the accent tint (active state) or its data-tone. */
  .chip-toggle {
    --ink: var(--text-body);
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    height: var(--control-sm);
    padding: 0 var(--s-3);
    border: 0;
    border-radius: var(--radius-control);
    background: var(--raised);
    color: var(--ink);
    font-size: var(--type-small);
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
    transition:
      background-color var(--duration-fast) var(--ease-out),
      color var(--duration-fast) var(--ease-out),
      transform var(--duration-fast) var(--ease-out);
  }

  .chip-toggle:hover {
    --ink: var(--text-strong);
    background: var(--raised-hover);
  }

  .chip-toggle:active {
    transform: scale(0.97);
  }

  .chip-toggle[aria-pressed="true"],
  .chip-toggle.is-active {
    --ink: var(--accent-text);
    background: var(--accent-soft);
    font-weight: 600;
  }

  .chip-toggle[data-tone][aria-pressed="true"] {
    --ink: var(--tone-ink);
    background: color-mix(in oklab, var(--tone) 12%, transparent);
  }

  .chip-toggle:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
  }

  .chip-toggle:disabled {
    --ink: var(--text-dim);
    background: var(--raised);
    cursor: not-allowed;
    transform: none;
  }

  /* Switch: a checkbox drawn as a track and a thumb. Off track is the 3:1 line tone; on is the accent. */
  .switch {
    appearance: none;
    position: relative;
    flex: none;
    width: 2.25rem;
    height: 1.25rem;
    margin: 0;
    border-radius: var(--radius-pill);
    background: var(--line);
    cursor: pointer;
    transition:
      background-color var(--duration-fast) var(--ease-out),
      transform var(--duration-fast) var(--ease-out);
  }

  .switch::after {
    content: "";
    position: absolute;
    top: 0.125rem;
    left: 0.125rem;
    width: 1rem;
    height: 1rem;
    border-radius: var(--radius-pill);
    background: var(--text-strong);
    transition: transform var(--duration-base) var(--ease-out);
  }

  .switch:hover {
    background: var(--text-dim);
  }

  .switch:active {
    transform: scale(0.97);
  }

  .switch:checked {
    background: var(--accent);
  }

  .switch:checked:hover {
    background: var(--accent-hover);
  }

  .switch:checked::after {
    background: var(--accent-ink);
    transform: translateX(1rem);
  }

  .switch:disabled {
    background: var(--raised-active);
    cursor: not-allowed;
    transform: none;
  }

  .switch:disabled::after {
    background: var(--text-dim);
  }

  .switch[aria-busy="true"] {
    pointer-events: none;
  }

  .switch[aria-busy="true"]::after {
    animation: pulse var(--duration-long) var(--ease-in-out) infinite alternate;
  }

  @keyframes pulse {
    to {
      opacity: 0.4;
    }
  }

  /* ------------------------------------------------------------------ Badges and chips */

  /* Chip: a small static label, neutral by default; data-tone tints it */
  .chip {
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    flex: none;
    height: 1.5rem;
    padding: 0 var(--s-2);
    border-radius: var(--radius-control);
    background: var(--raised);
    color: var(--text-body);
    font-size: var(--type-label);
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
  }

  .chip[data-tone] {
    background: color-mix(in oklab, var(--tone) 12%, transparent);
    color: var(--tone-ink);
  }

  /* Stat chip: label plus value; the value takes the tone (ok, warn, bad). Top 10, Dev, Snipers. */
  .stat-chip {
    --tone: var(--text-strong);
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    height: 1.5rem;
    padding: 0 var(--s-2);
    border-radius: var(--radius-control);
    background: var(--raised);
    color: var(--text-body);
    font-size: var(--type-label);
    white-space: nowrap;
  }

  .stat-chip[data-tone] {
    background: color-mix(in oklab, var(--tone) 10%, transparent);
  }

  .stat-value {
    color: var(--tone-ink, var(--tone));
    font-weight: 600;
    font-variant-numeric: tabular-nums;
  }

  /* Count badge: a pill with a number (active filters, unread). The accent marks an active count. */
  .count {
    display: inline-grid;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 var(--s-1);
    place-items: center;
    border-radius: var(--radius-pill);
    background: var(--accent);
    color: var(--accent-ink);
    font-size: var(--type-label);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1;
  }

  /* Quiet count: a dim figure beside a title */
  .count-quiet {
    color: var(--text-dim);
    font-size: var(--type-small);
    font-weight: 400;
    font-variant-numeric: tabular-nums;
  }

  /* Live state: word plus shape, never colour alone. data-state: live (default), connecting, stale, off, error. */
  .live {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    color: var(--text-body);
    font-size: var(--type-small);
    white-space: nowrap;
  }

  .live > .dot {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: var(--radius-pill);
    color: var(--positive);
  }

  .live[data-state="connecting"] > .dot {
    border: 2px solid var(--info);
    border-right-color: transparent;
    background: transparent;
    color: var(--info);
    animation: spin var(--duration-long) var(--ease-linear) infinite;
  }

  .live[data-state="stale"] > .dot {
    border: 2px solid var(--warning);
    background: transparent;
    color: var(--warning);
  }

  .live[data-state="stale"] > .dot::before {
    content: "";
    position: absolute;
    inset: 0 0 0 50%;
    background: var(--warning);
  }

  .live[data-state="off"] > .dot {
    border: 2px solid var(--text-dim);
    background: transparent;
  }

  .live[data-state="error"] > .dot {
    width: 0.625rem;
    height: 0.5625rem;
    border-radius: 0;
    color: var(--negative);
    clip-path: polygon(50% 0, 100% 100%, 0 100%);
  }

  .live:is([data-state="connecting"], [data-state="stale"], [data-state="off"], [data-state="error"]) > .dot::after {
    content: none;
  }

  /* ------------------------------------------------------------------ Data */

  /* Metric: label and figure. Inline by default (MC $3.1K); .metric-stack puts the label above. */
  .metric {
    --tone: var(--text-strong);
    display: inline-flex;
    align-items: baseline;
    gap: var(--s-1);
    white-space: nowrap;
  }

  .metric-label {
    color: var(--text-dim);
    font-size: var(--type-label);
  }

  .metric-value {
    color: var(--tone);
    font-size: var(--type-head);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1;
  }

  .metric-stack {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s-1);
  }

  /* The key figure on a screen: larger, and the accent text tone unless a data-tone says otherwise */
  .metric-lg {
    --tone: var(--accent-text);
  }

  .metric-lg .metric-value {
    font-size: var(--type-figure);
    letter-spacing: var(--tracking-display);
  }

  .metric-sm .metric-value {
    font-size: var(--type-body);
    font-weight: 500;
  }

  /* Delta: signed change in the text, tone from data-tone (up, down) */
  .delta {
    --tone: var(--text-dim);
    color: var(--tone);
    font-size: var(--type-small);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
  }

  /* Split bar: two segments, --a is the first share (buys vs sells) */
  .split-bar {
    display: flex;
    width: 5.75rem;
    height: 0.25rem;
    overflow: hidden;
    border-radius: var(--radius-pill);
    background: var(--raised-active);
  }

  .split-bar > i {
    display: block;
    background: var(--negative);
  }

  .split-bar > i:first-child {
    width: var(--a, 50%);
    background: var(--positive);
  }

  .split-bar > i:last-child {
    flex: 1;
  }

  /* Progress bar: --value is the fill. Inside .avatar it hugs the bottom edge (bonding curve). */
  .progress {
    display: block;
    height: 0.25rem;
    overflow: hidden;
    border-radius: var(--radius-pill);
    background: var(--raised-active);
  }

  .progress > i {
    display: block;
    width: var(--value, 0%);
    height: 100%;
    background: var(--tone, var(--positive));
  }

  .avatar > .progress {
    position: absolute;
    inset: auto 0 0;
    border-radius: 0;
    background: color-mix(in oklab, var(--ground) 60%, transparent);
  }

  /* Address: the mono face (addresses and hashes only), middle-truncated in markup, click to copy.
     .is-copied swaps the text for a confirmation. */
  .addr {
    --ink: var(--text-dim);
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    padding: 0;
    border: 0;
    border-radius: var(--radius-control);
    background: transparent;
    color: var(--ink);
    font-family: var(--font-mono);
    font-size: var(--type-label);
    line-height: var(--leading-tight);
    cursor: pointer;
    transition:
      color var(--duration-fast) var(--ease-out),
      transform var(--duration-fast) var(--ease-out);
  }

  .addr:hover {
    --ink: var(--text-strong);
  }

  .addr:active {
    transform: scale(0.97);
  }

  .addr:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
  }

  .addr:disabled {
    cursor: not-allowed;
    transform: none;
  }

  .addr svg {
    width: 0.75rem;
    height: 0.75rem;
    flex: none;
    fill: none;
    stroke: currentColor;
  }

  .addr.is-copied {
    --ink: var(--positive);
  }

  /* Key-value rows: dl > div > dt + dd, a quiet row line between rows */
  .kv {
    display: flex;
    flex-direction: column;
  }

  .kv > div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s-4);
    padding: var(--s-2) 0;
    border-top: 1px solid var(--line-row);
    font-size: var(--type-body);
  }

  .kv > div:first-child {
    border-top: 0;
  }

  .kv dt {
    color: var(--text-dim);
  }

  .kv dd {
    margin: 0;
    color: var(--text-strong);
    text-align: right;
    font-variant-numeric: tabular-nums;
  }

  /* Dense table: lines between rows only, numbers right-aligned (td.num, th.num), sticky header.
     Wrap in .table-wrap to scroll sideways. */
  .table-wrap {
    overflow-x: auto;
  }

  .table-dense {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--type-small);
    font-variant-numeric: tabular-nums;
  }

  .table-dense th {
    position: sticky;
    top: 0;
    padding: var(--s-2) var(--s-3);
    border-bottom: 1px solid var(--line-row);
    background: var(--surface);
    color: var(--text-dim);
    font-size: var(--type-label);
    font-weight: 500;
    text-align: left;
    white-space: nowrap;
  }

  .table-dense td {
    padding: var(--s-2) var(--s-3);
    border-bottom: 1px solid var(--line-row);
    color: var(--text-body);
    white-space: nowrap;
  }

  .table-dense .num {
    text-align: right;
  }

  .table-dense tbody tr {
    transition: background-color var(--duration-fast) var(--ease-out);
  }

  .table-dense tbody tr:hover {
    background: var(--veil);
  }

  .table-dense tbody tr:last-child td {
    border-bottom: 0;
  }

  /* Row list: aligned rows (fields, models, keys). data-cols picks one column template so every row aligns. */
  .row-list {
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .row-item {
    display: grid;
    align-items: center;
    gap: var(--s-1) var(--s-4);
    min-height: var(--hit);
    padding: var(--s-2) 0;
    border-bottom: 1px solid var(--line-row);
    font-size: var(--type-body);
  }

  .row-item:last-child {
    border-bottom: 0;
  }

  .row-item[data-cols="field"] {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .row-item[data-cols="item"] {
    grid-template-columns: minmax(0, 1fr) auto auto;
  }

  .row-item[data-cols="pair"] {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  @media screen and (min-width: 640px) {
    .row-item[data-cols="field"] {
      grid-template-columns: 8rem minmax(0, 1fr) auto;
    }
  }

  /* Sparkline: drop an svg with a polyline inside; the stroke takes the tone */
  .spark {
    display: inline-block;
    width: 5rem;
    height: 1.5rem;
    color: var(--tone, var(--positive));
  }

  .spark svg {
    width: 100%;
    height: 100%;
    overflow: visible;
  }

  .spark polyline {
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
  }

  .spark path {
    fill: color-mix(in oklab, currentColor 12%, transparent);
    stroke: none;
  }

  /* Code: the mono face. Block on a well; .is-inline for a class name or path inside prose. */
  .code-pre {
    margin: 0;
    padding: var(--s-4);
    overflow: auto;
    border-radius: var(--radius-control);
    background: var(--ground);
    color: var(--text-body);
    font-family: var(--font-mono);
    font-size: var(--type-small);
    line-height: var(--leading-reading);
    white-space: pre;
    tab-size: 2;
  }

  .code-pre.is-inline {
    display: inline;
    padding: 0 var(--s-1);
    background: var(--raised);
    font-size: 0.9em;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .code-k {
    color: var(--text-strong);
    font-weight: 600;
  }

  .code-s {
    color: var(--text-dim);
  }

  /* ------------------------------------------------------------------ Layout */

  /* Panel: a surface one tone up from the ground. No line, no shadow. */
  .panel,
  .card {
    border-radius: var(--radius-panel);
    background: var(--surface);
    color: var(--text-body);
  }

  .panel-flush {
    overflow: hidden;
  }

  /* Header row: the title is the panel's own heading (body face, sentence case), the state word sits right */
  .panel-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-1) var(--s-3);
    min-height: var(--s-7);
    padding: var(--s-2) var(--s-4);
  }

  .panel-head h2,
  .panel-head h3,
  .panel-title {
    color: var(--text-strong);
    font-family: var(--font-sans);
    font-size: var(--type-body);
    font-weight: 600;
    line-height: var(--leading-tight);
  }

  .panel-state,
  .panel-actions {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    margin-left: auto;
  }

  .panel-state {
    color: var(--text-dim);
    font-size: var(--type-small);
  }

  .panel-state + .panel-actions {
    margin-left: 0;
  }

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

  .panel-head + .panel-body {
    padding-top: 0;
  }

  .panel > .panel-body:first-child {
    padding-top: var(--s-4);
  }

  .panel-foot {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-2);
    padding: var(--s-3) var(--s-4);
  }

  /* Page head: title, live state, controls on the right */
  .page-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-2) var(--s-4);
    padding-block: var(--s-1) var(--s-3);
  }

  .page-title {
    color: var(--text-strong);
    font-family: var(--font-display);
    font-size: var(--type-figure);
    font-weight: 600;
    letter-spacing: var(--tracking-display);
    line-height: var(--leading-display);
  }

  .page-head-main {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--s-1) var(--s-3);
  }

  /* Toolbar: a row of controls that wraps. .toolbar-sep is a wider gap between groups (no line). */
  .toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--s-2);
  }

  .toolbar-spacer {
    margin-left: auto;
  }

  .toolbar-sep {
    width: var(--s-2);
    flex: none;
  }

  /* Column board: three equal columns that scroll on their own. Set --board-h for a fixed height.
     Below 768px columns stack; data-mode="tabs" shows one column at a time (put a .tabs.board-tabs first,
     mark one column .is-active). */
  .board {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s-3);
    height: var(--board-h, auto);
    min-height: 0;
  }

  .board > .panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
  }

  .board-scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-gutter: stable;
  }

  .board-tabs {
    display: none;
  }

  @media screen and (max-width: 767px) {
    .board {
      grid-template-columns: minmax(0, 1fr);
      height: auto;
    }

    .board-tabs {
      display: flex;
    }

    .board[data-mode="tabs"] > .panel:not(.is-active) {
      display: none;
    }
  }

  /* Avatar: square art on the raised tone. data-stage draws a 2px state frame (mayhem red, migrated gold). */
  .avatar {
    --tone: var(--text-dim);
    position: relative;
    display: grid;
    place-items: center;
    flex: none;
    width: 4.75rem;
    height: 4.75rem;
    overflow: hidden;
    border-radius: var(--radius-control);
    background: var(--raised);
    color: var(--text-body);
    font-size: var(--type-head);
    font-weight: 600;
  }

  .avatar > img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  /* Drawn over the art (the image is positioned, so an outline would sit under it) */
  .avatar[data-stage]::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    border: 2px solid var(--tone);
    border-radius: inherit;
    pointer-events: none;
  }

  .avatar-sm {
    width: 2rem;
    height: 2rem;
    font-size: var(--type-label);
  }

  /* Coin row: avatar column, identity and chips, right-aligned metric and action.
     Areas: .coin-art, .coin-main (.coin-title, .coin-meta, .coin-chips), .coin-side. A list row, so it keeps its row line. */
  .coin-row {
    position: relative;
    isolation: isolate;
    display: grid;
    grid-template-columns: 4.75rem minmax(0, 1fr) auto;
    gap: var(--s-3);
    padding: var(--s-3) var(--s-4);
    overflow: hidden;
    border-bottom: 1px solid var(--line-row);
  }

  /* Hover tint slides up from the bottom edge (transform only) */
  .coin-row::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: var(--veil);
    transform: translateY(101%);
    transition: transform var(--duration-quick) var(--ease-out);
  }

  .coin-row:hover::before {
    transform: translateY(0);
  }

  /* Selected row: a faint accent tint (the active state), light enough that dim text keeps 4.5:1 */
  .coin-row[aria-current="true"] {
    background: color-mix(in oklab, var(--accent) 8%, transparent);
  }

  /* Stage rows: a faint tint of the state; the chip in the title names it */
  .coin-row[data-stage] {
    background: color-mix(in oklab, var(--tone) 7%, transparent);
  }

  /* A row that just arrived drops in once */
  .coin-row.is-new {
    animation: coin-in var(--duration-slow) var(--ease-out);
  }

  @keyframes coin-in {
    from {
      opacity: 0;
      transform: translateY(-0.5rem);
    }
  }

  .coin-art {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s-1);
    min-width: 0;
  }

  /* The address never runs past the art column */
  .coin-art .addr {
    max-width: 100%;
  }

  .coin-art .addr > span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .coin-main {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
    min-width: 0;
  }

  .coin-title {
    display: flex;
    align-items: baseline;
    gap: var(--s-2);
    min-width: 0;
    white-space: nowrap;
  }

  .coin-ticker {
    flex: none;
    color: var(--text-strong);
    font-size: var(--type-reading);
    font-weight: 700;
    line-height: var(--leading-tight);
    text-decoration: none;
  }

  .coin-ticker:hover {
    text-decoration: underline;
    text-underline-offset: 0.2em;
  }

  .coin-name {
    min-width: 0;
    overflow: hidden;
    color: var(--text-dim);
    font-size: var(--type-body);
    text-overflow: ellipsis;
  }

  .coin-meta {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    min-width: 0;
    overflow: hidden;
    color: var(--text-dim);
    font-size: var(--type-label);
    white-space: nowrap;
  }

  .coin-meta b {
    color: var(--text-strong);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
  }

  .coin-age {
    color: var(--positive);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
  }

  .coin-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-1);
  }

  .coin-side {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: var(--s-2);
  }

  .coin-side .btn {
    margin-top: auto;
  }

  .coin-stats {
    display: flex;
    align-items: baseline;
    gap: var(--s-3);
    color: var(--text-dim);
    font-size: var(--type-label);
    white-space: nowrap;
  }

  .coin-stats b {
    color: var(--text-strong);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
  }

  @media screen and (max-width: 479px) {
    .coin-row {
      grid-template-columns: 3.5rem minmax(0, 1fr);
      gap: var(--s-2) var(--s-3);
      padding-inline: var(--s-3);
    }

    .coin-row .avatar {
      width: 3.5rem;
      height: 3.5rem;
    }

    /* Metric, stats and bar stack on the left; the buy key sits right, centred on them */
    .coin-side {
      grid-column: 1 / -1;
      display: grid;
      grid-template-columns: minmax(0, 1fr) auto;
      column-gap: var(--s-3);
      align-items: center;
      justify-items: start;
    }

    .coin-side > :not(.btn) {
      grid-column: 1;
    }

    .coin-side .btn {
      grid-column: 2;
      grid-row: 1 / span 3;
      margin: 0;
    }
  }

  /* App top bar: brand, nav tabs, search, balance, account. A tone step above the ground, no line. */
  .topbar {
    display: flex;
    align-items: center;
    gap: var(--s-4);
    height: var(--header-height);
    padding-inline: var(--gutter);
    background: var(--surface);
  }

  .brand {
    display: inline-flex;
    align-items: center;
    flex: none;
    gap: var(--s-2);
    color: var(--text-strong);
    font-family: var(--font-display);
    font-size: var(--type-head);
    font-weight: 700;
    letter-spacing: var(--tracking-display);
    text-decoration: none;
  }

  .topbar .tabs-nav {
    flex: 0 1 auto;
  }

  .topbar .search {
    flex: 1;
    max-width: 20rem;
    min-width: 12rem;
    margin-left: auto;
  }

  .topbar-end {
    display: flex;
    align-items: center;
    flex: none;
    gap: var(--s-3);
    margin-left: auto;
  }

  .topbar .search + .topbar-end {
    margin-left: 0;
  }

  /* Balance: a tabular figure and its change on the raised tone */
  .balance {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    height: var(--control-md);
    padding: 0 var(--s-3);
    border-radius: var(--radius-control);
    background: var(--raised);
    color: var(--text-strong);
    font-size: var(--type-body);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }

  .balance .delta {
    font-size: var(--type-label);
    font-weight: 500;
  }

  @media screen and (max-width: 767px) {
    .topbar {
      gap: var(--s-3);
    }

    .topbar .search {
      display: none;
    }

    .topbar .tabs-nav {
      flex: 1;
      gap: var(--s-4);
      min-width: 0;
      /* fade the clipped edge so a cut-off tab reads as "scroll for more" */
      mask-image: linear-gradient(to right, black calc(100% - 2rem), transparent);
    }

    .topbar-end {
      margin-left: 0;
      gap: var(--s-2);
    }
  }

  /* ------------------------------------------------------------------ Overlays (they float, so they cast the pop shadow) */

  /* Tooltip surface. Also behaviour: put data-tooltip="text" (and data-side=bottom) on any element. */
  .tooltip,
  [data-tooltip]::after {
    padding: var(--s-1) var(--s-2);
    border-radius: var(--radius-control);
    background: var(--text-strong);
    color: var(--ground);
    font-family: var(--font-sans);
    font-size: var(--type-label);
    font-weight: 500;
    line-height: var(--leading-tight);
    box-shadow: var(--shadow-pop);
  }

  [data-tooltip] {
    position: relative;
  }

  [data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + var(--s-2));
    left: 50%;
    z-index: 60;
    width: max-content;
    max-width: 16rem;
    white-space: normal;
    text-align: left;
    opacity: 0;
    pointer-events: none;
    transform: translate(-50%, 0.25rem);
    transition:
      opacity var(--duration-quick) var(--ease-out),
      transform var(--duration-quick) var(--ease-out);
  }

  [data-tooltip]:hover::after,
  [data-tooltip]:focus-visible::after {
    opacity: 1;
    transform: translate(-50%, 0);
    transition-delay: 350ms;
  }

  [data-tooltip][data-side="bottom"]::after {
    top: calc(100% + var(--s-2));
    bottom: auto;
    transform: translate(-50%, -0.25rem);
  }

  [data-tooltip][data-side="bottom"]:hover::after,
  [data-tooltip][data-side="bottom"]:focus-visible::after {
    transform: translate(-50%, 0);
  }

  /* Popover and dropdown surface. With <details class="dropdown"><summary>…</summary><div class="popover">…</div></details>
     it opens with no script. */
  .popover {
    min-width: 10rem;
    padding: var(--s-1);
    border-radius: var(--radius-panel);
    background: var(--overlay);
    color: var(--text-body);
    box-shadow: var(--shadow-pop);
  }

  .dropdown {
    position: relative;
    display: inline-block;
  }

  .dropdown > summary {
    list-style: none;
  }

  .dropdown > summary::-webkit-details-marker {
    display: none;
  }

  .dropdown > .popover {
    position: absolute;
    top: calc(100% + var(--s-2));
    left: 0;
    z-index: 50;
    transform-origin: top left;
    animation: pop-in var(--duration-quick) var(--ease-out);
  }

  .dropdown[data-align="end"] > .popover {
    left: auto;
    right: 0;
    transform-origin: top right;
  }

  @keyframes pop-in {
    from {
      opacity: 0;
      transform: scale(0.97);
    }
  }

  .menu-item {
    --ink: var(--text-body);
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--s-2);
    width: 100%;
    height: var(--control-md);
    padding: 0 var(--s-2);
    border: 0;
    border-radius: var(--radius-control);
    background: transparent;
    color: var(--ink);
    font-size: var(--type-body);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition:
      background-color var(--duration-fast) var(--ease-out),
      transform var(--duration-fast) var(--ease-out);
  }

  .menu-item:hover,
  .menu-item:focus-visible {
    --ink: var(--text-strong);
    background: var(--veil);
  }

  .menu-item:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: -2px;
  }

  .menu-item:active {
    transform: scale(0.97);
  }

  .menu-item:disabled,
  .menu-item[aria-disabled="true"] {
    --ink: var(--text-dim);
    background: transparent;
    cursor: not-allowed;
    transform: none;
  }

  /* Checked item: the accent marks the active choice */
  .menu-item[aria-checked="true"],
  .menu-item.is-active {
    --ink: var(--text-strong);
    font-weight: 600;
  }

  .menu-item[aria-checked="true"]:not(.is-loading, [aria-busy="true"])::after,
  .menu-item.is-active:not(.is-loading, [aria-busy="true"])::after {
    content: "";
    width: 0.5rem;
    height: 0.5rem;
    margin-left: auto;
    border-radius: var(--radius-pill);
    background: var(--accent);
  }

  .menu-item .kbd {
    margin-left: auto;
  }

  /* Group heading inside a menu: body face, sentence case */
  .menu-label {
    padding: var(--s-2) var(--s-2) var(--s-1);
    color: var(--text-dim);
    font-size: var(--type-label);
    font-weight: 600;
  }

  .menu-sep {
    height: 1px;
    margin: var(--s-1) calc(var(--s-1) * -1);
    background: var(--line-row);
  }

  /* Dialog for <dialog class="dialog">: showModal() gives the backdrop and focus trap. .sheet docks it to an edge. */
  .dialog {
    width: min(28rem, calc(100vw - var(--s-6)));
    max-height: calc(100svh - var(--s-6));
    padding: 0;
    overflow: auto;
    border: 0;
    border-radius: var(--radius-panel);
    background: var(--overlay);
    color: var(--text-body);
    box-shadow: var(--shadow-pop);
    /* centred in the viewport; base.css keeps the UA auto margins on dialog */
    margin: auto;
  }

  .dialog[open] {
    animation: dialog-in var(--duration-quick) var(--ease-out);
  }

  .dialog::backdrop {
    background: color-mix(in oklab, var(--scrim) 60%, transparent);
  }

  @keyframes dialog-in {
    from {
      opacity: 0;
      transform: scale(0.97);
    }
  }

  /* Static preview of the surface (no dialog element needed) */
  .dialog-static {
    position: static;
    display: block;
    width: auto;
    max-width: 28rem;
    margin: 0;
  }

  .dialog-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-4);
    min-height: var(--s-7);
    padding: var(--s-2) var(--s-3) var(--s-2) var(--s-4);
  }

  .dialog-title {
    color: var(--text-strong);
    font-family: var(--font-sans);
    font-size: var(--type-reading);
    font-weight: 600;
  }

  .dialog-body {
    padding: 0 var(--s-4) var(--s-4);
    color: var(--text-body);
    font-size: var(--type-body);
  }

  .dialog-foot {
    display: flex;
    justify-content: flex-end;
    gap: var(--s-2);
    padding: var(--s-3) var(--s-4) var(--s-4);
  }

  /* Sheet: from the bottom on phones with a grab handle, from the right on desktop with data-side="right" */
  .sheet {
    margin: auto 0 0;
    width: 100%;
    max-width: none;
    max-height: 85svh;
    border-radius: var(--radius-panel) var(--radius-panel) 0 0;
  }

  .sheet::before {
    content: "";
    display: block;
    width: 2.5rem;
    height: 0.25rem;
    margin: var(--s-2) auto 0;
    border-radius: var(--radius-pill);
    background: var(--raised-active);
  }

  .sheet[open] {
    animation: sheet-up var(--duration-base) var(--ease-out);
  }

  @keyframes sheet-up {
    from {
      transform: translateY(100%);
    }
  }

  @media screen and (min-width: 768px) {
    .sheet[data-side="right"] {
      margin: 0 0 0 auto;
      width: 24rem;
      height: 100svh;
      max-height: none;
      max-width: calc(100vw - var(--s-6));
      border-radius: 0;
    }

    .sheet[data-side="right"]::before {
      content: none;
    }

    .sheet[data-side="right"][open] {
      animation-name: sheet-in;
    }
  }

  @keyframes sheet-in {
    from {
      transform: translateX(100%);
    }
  }

  /* Toast: surface with a tone icon slot. .toaster stacks them bottom right, full width at the bottom on phones. */
  .toaster {
    position: fixed;
    right: var(--s-4);
    bottom: var(--s-4);
    z-index: 70;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: var(--s-2);
    width: min(22.5rem, calc(100vw - var(--s-6)));
    pointer-events: none;
  }

  .toast {
    --tone: var(--info);
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: var(--s-3);
    align-items: start;
    width: 100%;
    padding: var(--s-3) var(--s-4);
    overflow: hidden;
    border-radius: var(--radius-panel);
    background: var(--overlay);
    color: var(--text-strong);
    font-size: var(--type-body);
    box-shadow: var(--shadow-pop);
    pointer-events: auto;
    animation: toast-in var(--duration-quick) var(--ease-out);
  }

  @keyframes toast-in {
    from {
      opacity: 0;
      transform: translateY(0.5rem);
    }
  }

  .toast > svg,
  .toast-icon {
    width: 1rem;
    height: 1rem;
    margin-top: 0.125rem;
    color: var(--tone);
  }

  .toast-title {
    font-weight: 500;
  }

  .toast-text {
    margin-top: var(--s-1);
    color: var(--text-dim);
    font-size: var(--type-small);
  }

  /* Fuse: a bar that runs out; --toast-ms sets the time */
  .toast.has-fuse::after {
    content: "";
    position: absolute;
    inset: auto 0 0;
    height: 0.125rem;
    background: var(--tone);
    transform-origin: left;
    animation: fuse var(--toast-ms, 4s) linear forwards;
  }

  @keyframes fuse {
    to {
      transform: scaleX(0);
    }
  }

  @media screen and (max-width: 639px) {
    .toaster {
      inset: auto var(--s-2) var(--s-2);
      width: auto;
      align-items: stretch;
    }
  }

  .toast-close {
    margin: calc(var(--s-1) * -1) calc(var(--s-2) * -1) 0 0;
  }

  /* Skeleton: a tone pulse, sized like the content it stands for. Swap to the error state after 8 s. */
  .skeleton {
    display: block;
    border-radius: var(--radius-control);
    background: var(--raised-hover);
    animation: skeleton-pulse calc(var(--duration-long) * 2) var(--ease-in-out) infinite;
  }

  @keyframes skeleton-pulse {
    50% {
      opacity: 0.5;
    }
  }

  /* Empty state: the cause in one plain sentence, an optional detail line, then the next action.
     data-kind="error" adds the failure shape. Keeps a compact reserved height inside its frame. */
  .empty {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: var(--s-2);
    min-height: var(--empty-h, 8rem);
    padding: var(--s-5) var(--s-4);
  }

  .empty-icon {
    display: grid;
    width: var(--s-6);
    height: var(--s-6);
    place-items: center;
    border-radius: var(--radius-control);
    background: var(--raised);
    color: var(--text-dim);
  }

  .empty-cause {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    color: var(--text-strong);
    font-size: var(--type-body);
    font-weight: 600;
  }

  .empty[data-kind="error"] .empty-cause::before {
    content: "";
    width: 0.75rem;
    height: 0.6875rem;
    flex: none;
    background: var(--negative);
    clip-path: polygon(50% 0, 100% 100%, 0 100%);
  }

  .empty-text {
    max-width: 32rem;
    color: var(--text-dim);
    font-size: var(--type-small);
  }

  .empty-action {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
    margin-top: var(--s-1);
  }

  /* Spinner: only inside a control or a state slot, never in the middle of content */
  .spinner {
    display: inline-block;
    flex: none;
    width: 1rem;
    height: 1rem;
    border: 2px solid var(--raised-active);
    border-top-color: var(--text-strong);
    border-radius: var(--radius-pill);
    animation: spin var(--duration-long) var(--ease-linear) infinite;
  }

  .spinner-lg {
    width: 1.5rem;
    height: 1.5rem;
    border-width: 3px;
  }

  /* ------------------------------------------------------------------ Docs patterns */

  /* Event ticker: a slow marquee of events. Duplicate the .ticker-group with aria-hidden for a seamless loop.
     Pauses on hover, focus, [data-play="false"]; under reduced motion it stops and scrolls by hand. */
  .ticker {
    position: relative;
    overflow: hidden;
    padding-block: var(--s-2);
    mask-image: linear-gradient(90deg, transparent, black 8%, black 92%, transparent);
  }

  .ticker-track {
    display: flex;
    width: max-content;
  }

  .ticker-group {
    display: flex;
    flex: none;
    gap: var(--s-6);
    margin: 0;
    padding: 0 var(--s-4);
    list-style: none;
  }

  .ticker-item {
    --tone: var(--text-dim);
    display: inline-flex;
    align-items: baseline;
    gap: var(--s-2);
    color: var(--text-strong);
    font-size: var(--type-small);
    font-variant-numeric: tabular-nums;
    line-height: var(--leading-body);
    white-space: nowrap;
  }

  .ticker-kind {
    padding: 0 var(--s-2);
    border-radius: var(--radius-control);
    background: color-mix(in oklab, var(--tone) 12%, transparent);
    color: var(--tone-ink, var(--tone));
    font-size: var(--type-label);
    font-weight: 500;
  }

  .ticker-detail {
    color: var(--text-dim);
  }

  @keyframes ticker {
    to {
      transform: translateX(-50%);
    }
  }

  @media (prefers-reduced-motion: no-preference) {
    .ticker-track {
      animation: ticker 48s var(--ease-linear) infinite;
    }

    .ticker[data-play="false"] .ticker-track,
    .ticker:hover .ticker-track,
    .ticker:focus-within .ticker-track {
      animation-play-state: paused;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .ticker {
      overflow-x: auto;
    }

    .ticker-group[aria-hidden="true"] {
      display: none;
    }
  }

  /* Steps: a row of stages. Numbers appear only when the list is an <ol>. Mark one aria-current="step";
     data-done marks earlier ones. The current step takes the accent (active state). */
  .steps {
    display: grid;
    grid-template-columns: repeat(var(--steps, 5), minmax(0, 1fr));
    gap: var(--s-1);
    margin: 0;
    padding: 0;
    list-style: none;
    counter-reset: step;
  }

  ol.steps > li {
    counter-increment: step;
  }

  .step {
    --ink: var(--text-dim);
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    width: 100%;
    min-height: var(--hit);
    padding: var(--s-1);
    border: 0;
    border-radius: var(--radius-control);
    background: transparent;
    color: var(--ink);
    font-size: var(--type-small);
    cursor: pointer;
    transition:
      background-color var(--duration-fast) var(--ease-out),
      color var(--duration-fast) var(--ease-out),
      transform var(--duration-fast) var(--ease-out);
  }

  ol.steps .step::before {
    content: counter(step);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
  }

  .step:hover {
    --ink: var(--text-strong);
    background: var(--raised);
  }

  .step:active {
    transform: scale(0.97);
  }

  .step:focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 2px;
  }

  .step[data-done] {
    --ink: var(--text-body);
  }

  .step[aria-current="step"] {
    --ink: var(--accent-text);
    background: var(--accent-soft);
    font-weight: 600;
  }

  .step:disabled {
    --ink: var(--text-dim);
    background: transparent;
    cursor: not-allowed;
    transform: none;
  }

  /* Story under the steps: one sentence, then the controls */
  .step-story {
    display: flex;
    align-items: flex-start;
    min-height: 5rem;
    padding-block: var(--s-4);
    color: var(--text-strong);
    font-size: var(--type-reading);
  }

  .step-controls {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--s-3);
  }

  @media screen and (max-width: 639px) {
    .step {
      flex-direction: column;
      gap: var(--s-1);
      min-height: 3.5rem;
      font-size: var(--type-label);
    }
  }

  /* Feature grid: title and one line on the raised tone. No icon or art on top. Three, two, one columns. */
  .feature-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s-3);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .feature {
    display: flex;
    flex-direction: column;
    gap: var(--s-1);
    height: 100%;
    padding: var(--s-4);
    border-radius: var(--radius-panel);
    background: var(--raised);
    color: inherit;
    text-decoration: none;
    transition: background-color var(--duration-fast) var(--ease-out);
  }

  a.feature:hover {
    background: var(--raised-hover);
  }

  /* Optional wrapper kept for older markup */
  .feature-body {
    display: flex;
    flex-direction: column;
    gap: var(--s-1);
  }

  .feature-title {
    color: var(--text-strong);
    font-size: var(--type-reading);
    font-weight: 600;
    line-height: var(--leading-tight);
  }

  .feature-text {
    color: var(--text-dim);
    font-size: var(--type-body);
    line-height: var(--leading-body);
  }

  @media screen and (max-width: 767px) {
    .feature-grid {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
  }

  @media screen and (max-width: 639px) {
    .feature-grid {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--s-2);
    }
  }

  /* Plain list: short one-line points on the raised tone. An <ol> shows plain numbers; a <ul> shows none. */
  .plain-list {
    display: grid;
    gap: var(--s-2);
    margin: 0;
    padding: 0;
    list-style: none;
    counter-reset: plain;
  }

  .plain-list > li {
    display: flex;
    align-items: baseline;
    gap: var(--s-3);
    padding: var(--s-3) var(--s-4);
    border-radius: var(--radius-control);
    background: var(--raised);
    color: var(--text-strong);
    font-size: var(--type-reading);
  }

  ol.plain-list > li {
    counter-increment: plain;
  }

  ol.plain-list > li::before {
    content: counter(plain);
    flex: none;
    color: var(--text-dim);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
  }

  /* Callout: a tinted block, no side border. data-tone info (default) or warning. Title is a plain bold lead. */
  .callout {
    --tone: var(--info);
    display: flex;
    flex-direction: column;
    gap: var(--s-1);
    padding: var(--s-3) var(--s-4);
    border-radius: var(--radius-control);
    background: color-mix(in oklab, var(--tone) 10%, var(--surface));
    color: var(--text-body);
    font-size: var(--type-body);
    line-height: var(--leading-body);
  }

  .callout-title {
    color: var(--text-strong);
    font-weight: 600;
  }

  /* Section heading with an anchor: the # appears on hover and focus */
  .h-anchor {
    color: var(--text-strong);
    font-family: var(--font-display);
    font-size: var(--type-head);
    font-weight: 600;
    line-height: var(--leading-tight);
  }

  .h-anchor > a {
    display: inline-flex;
    align-items: baseline;
    gap: var(--s-2);
    color: inherit;
    text-decoration: none;
  }

  .h-anchor > a::after {
    content: "#";
    color: var(--text-dim);
    font-weight: 400;
    opacity: 0;
    transition: opacity var(--duration-fast) var(--ease-out);
  }

  .h-anchor > a:hover::after,
  .h-anchor > a:focus-visible::after {
    opacity: 1;
  }

  /* Lead paragraph under a page title */
  .lead {
    max-width: 62ch;
    color: var(--text-body);
    font-size: var(--type-head);
    line-height: var(--leading-reading);
  }

  /* Go-deeper break between the simple layer and the exact rules: space and a bold line, no rule */
  .deeper {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--s-2);
    padding-block: var(--s-6) var(--s-2);
    color: var(--text-dim);
    font-size: var(--type-small);
  }

  .deeper b {
    color: var(--text-strong);
    font-size: var(--type-body);
    font-weight: 600;
  }

  /* Demo frame: a title row with a state word on the right, then the example, on the surface tone */
  .demo {
    overflow: hidden;
    border-radius: var(--radius-panel);
    background: var(--surface);
  }

  .demo-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-4);
    min-height: var(--s-7);
    padding: var(--s-2) var(--s-4);
    color: var(--text-strong);
    font-size: var(--type-body);
    font-weight: 600;
  }

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

/* Tone map, last in the layer so it wins over component defaults. */
@layer components {
  [data-tone="positive"],
  [data-tone="ok"],
  [data-tone="up"] {
    --tone: var(--positive);
  }

  [data-tone="negative"],
  [data-tone="destructive"],
  [data-tone="bad"],
  [data-tone="down"] {
    --tone: var(--negative);
  }

  [data-tone="warning"],
  [data-tone="warn"],
  [data-tone="wait"] {
    --tone: var(--warning);
  }

  [data-tone="info"] {
    --tone: var(--info);
  }

  [data-tone="neutral"] {
    --tone: var(--text-dim);
  }

  [data-stage="mayhem"] {
    --tone: var(--negative);
  }

  [data-stage="migrated"] {
    --tone: var(--warning);
  }

  /* Signal text on its own tint: a quarter of the way to the strong text tone, so it holds 4.5:1 in both themes */
  [data-tone],
  [data-stage] {
    --tone-ink: color-mix(in oklab, var(--tone) 75%, var(--text-strong));
  }
}

@layer utilities {
  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  /* Hide below 768px / show only below 768px */
  @media screen and (max-width: 767px) {
    .hide-sm {
      display: none !important;
    }
  }

  @media screen and (min-width: 768px) {
    .show-sm {
      display: none !important;
    }
  }
}
