/* ══════════════════════════════════════════════════════════════════════════
   thm_depth · depth.controls.css · v2.4 (2026-10-08)

   One look per job. Every component here is a CLASS; there is no rule for a
   bare element apart from the zero-specificity reset below, so no app ever
   has to undo this file. Every value is a token from depth.tokens.css.

   Principles
   1. Depth is planes, not effects. A resting surface is a plane plus a 1px
      line. Only what floats over content (menu, tooltip, toast, dialog)
      casts a shadow. No gradient, glow, lit edge or hover lift in the chrome.
      The sky theme picker is the one kept delight.
   2. Shape carries meaning. Rectangles act. Small square-cornered tags
      report. Only the count badge, the switch and the status dot are round.
   3. Words first, quietly. Title Case for labels and titles; capitals only
      rarely. At most one sentence of help. Labels sit dead centre in their box.
   4. Accessibility is a floor. WCAG 2.1 AA in both themes, measured rendered;
      no control below --hit-min (24px);
      meaning never rides on colour alone; every control has a visible focus
      ring and an accessible name.

   State hooks. Each interactive state also answers to a class
   (.is-hover, .is-focus) so a specimen or a test can show it without a
   pointer. Apps never need to set them.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Reset (zero specificity) ──────────────────────────────────────────── */
:where(*, *::before, *::after) { box-sizing: border-box; }
:where(button, input, select, textarea) { font: inherit; color: inherit; }
/* v2.2: the hidden attribute always hides. Components below set a display type
   (.btn, .field, .menu-item ...), which would otherwise beat the browser's own
   [hidden] rule and leave a hidden control visible (DTC_FileLauncher's guard
   test_hidden_display_trap, 2026-10-03). Zero specificity plus !important, so
   no app rule has to undo it; hidden="until-found" keeps its own meaning. */
:where([hidden]:not([hidden="until-found" i])) { display: none !important; }

/* ── Text styles ───────────────────────────────────────────────────────── */
.t-display  { font: var(--fw-strong) var(--fs-display)/var(--lh-display) var(--font-display); color: var(--ink-1); }
.t-title    { font: var(--fw-strong) var(--fs-title)/var(--lh-title) var(--font-display); color: var(--ink-1); }
.t-subtitle { font: var(--fw-strong) var(--fs-subtitle)/var(--lh-subtitle) var(--font-ui); color: var(--ink-1); }
.t-body     { font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui); color: var(--ink-1); }
.t-section  { font: var(--fw-strong) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-2); }
.t-meta     { font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-3); }
.t-mono     { font-family: var(--font-mono); }
.link { color: var(--accent-ink); text-decoration: underline; text-underline-offset: var(--glyph-stroke); }
.link:is(:hover, .is-hover) { text-decoration-thickness: var(--glyph-stroke); }
.link:is(:focus-visible, .is-focus) { outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-offset); border-radius: var(--radius-xs); }

/* ── Icon (inline SVG, stroke follows the text colour) ─────────────────── */
.icon { width: var(--icon-sm); height: var(--icon-sm); flex: none; fill: none; stroke: currentColor;
        stroke-width: var(--icon-stroke-sm); stroke-linecap: round; stroke-linejoin: round; }
.icon-md { width: var(--icon-md); height: var(--icon-md); }
.icon-md, .nav-row > .icon, .list-row > .icon { stroke-width: var(--icon-stroke-md); }

/* ── Panel: a resting surface. A plane and a line, never a shadow. ─────── */
.panel { background: var(--surface-1); border: var(--line-w) solid var(--line-subtle);
         border-radius: var(--radius-surface); box-shadow: var(--elev-0); }

/* ══ Buttons ═══════════════════════════════════════════════════════════════
   .btn (secondary, the default) · .btn-primary (one per dialog, panel or
   toolbar group) · .btn-subtle (toolbar verbs, row actions) · .btn-danger
   (destructive, outlined) · .btn-danger-confirm (the confirming step only) ·
   .btn-icon (square; aria-label required) · .btn-toggle (aria-pressed) ·
   sizes .btn-sm / .btn-lg. Disabled buttons keep their place and say why in
   a tooltip. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  height: var(--ctl-h); padding: 0 var(--sp-3);
  border: var(--line-w) solid var(--line-strong); border-radius: var(--radius-ctl);
  background: var(--surface-1); color: var(--ink-1);
  font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui);
  white-space: nowrap; text-decoration: none; cursor: pointer; user-select: none;
  transition: var(--transition-colors);
}
.btn:is(:hover, .is-hover) { background: var(--surface-2); }
.btn:is(:focus-visible, .is-focus) { outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-offset); }
.btn:is(:disabled, [aria-disabled="true"]) {
  background: var(--surface-1); border-color: var(--line-subtle); color: var(--ink-disabled); cursor: default;
}

/* Primary ("go") is an outline (Carter, 2026-09-27): ink text, only the edge
   carries the accent, a wash on hover. v1 was a filled accent button.
   v2.4 (Carter, 2026-10-08): the edge is 2px, the second pixel drawn inside so the
   box does not move; the plain button stays 1px. */
.btn-primary { background: transparent; border-color: var(--accent-ink); color: var(--ink-1); font-weight: var(--fw-strong);
               box-shadow: inset 0 0 0 var(--line-w) var(--accent-ink); }
.btn-primary:is(:hover, .is-hover) { background: var(--accent-wash); border-color: var(--accent-ink); }
.btn-primary:is(:disabled, [aria-disabled="true"]) { background: var(--surface-2); border-color: var(--line-subtle); color: var(--ink-disabled); box-shadow: none; }

.btn-subtle { background: transparent; border-color: transparent; }
.btn-subtle:is(:hover, .is-hover) { background: var(--surface-2); }
.btn-subtle:is(:disabled, [aria-disabled="true"]) { background: transparent; border-color: transparent; }

.btn-danger { background: transparent; border-color: var(--danger-ink); color: var(--danger-ink); }
.btn-danger:is(:hover, .is-hover) { background: color-mix(in srgb, var(--danger-fill) var(--mix-wash), transparent); }
.btn-danger:is(:disabled, [aria-disabled="true"]) { background: transparent; }

/* Dark scheme (documented, Carter 2026-10-08, no colour change): the solid fill measures 2.75:1 on a panel and 2.19:1 on
   a dialog, under 3:1 as a boundary. The white label (6.40:1) is what names the button, so it stands, but in dark the
   outlined .btn-danger is the preferred destructive control and this one appears only on the confirming step. */
.btn-danger-confirm { background: var(--danger-fill); border-color: var(--danger-fill); color: var(--on-danger); font-weight: var(--fw-strong); }
.btn-danger-confirm:is(:hover, .is-hover) { background: var(--danger-fill); border-color: var(--danger-ink); }
.btn-danger-confirm:is(:disabled, [aria-disabled="true"]) { background: var(--surface-2); border-color: var(--line-subtle); color: var(--ink-disabled); }

.btn-icon { width: var(--ctl-h); padding: 0; background: transparent; border-color: transparent; }
.btn-icon:is(:hover, .is-hover) { background: var(--surface-2); }
.btn-icon:is(:disabled, [aria-disabled="true"]) { background: transparent; border-color: transparent; }

/* One rule for every on/off verb. The label changes too ("Record" -> "Recording"). */
.btn-toggle { background: transparent; border-color: transparent; }
.btn-toggle:is(:hover, .is-hover) { background: var(--surface-2); }
.btn-toggle[aria-pressed="true"] { background: var(--accent-wash); border-color: var(--accent); color: var(--ink-1); }
.btn-toggle[aria-pressed="true"] .icon { color: var(--accent-ink); }

/* Pressed (v2.4, buttons only): the hover ground of every variant, darkened or lightened by 10% ink while the button is
   held. Placed after every variant so it wins on specificity. .is-active is the state hook for the specimen; apps never
   set it. "Pressed" here is the momentary state; an on/off verb is .btn-toggle with aria-pressed ("on"). */
.btn:is(:active, .is-active):not(:is(:disabled, [aria-disabled="true"])) {
  background-image: linear-gradient(var(--press-tint), var(--press-tint));
}

.btn-sm { height: var(--ctl-h-sm); padding: 0 var(--sp-2); font-size: var(--fs-caption); line-height: var(--lh-caption); }
.btn-sm.btn-icon { width: var(--ctl-h-sm); padding: 0; }
.btn-lg { height: var(--ctl-h-lg); padding: 0 var(--sp-4); }
.btn-lg.btn-icon { width: var(--ctl-h-lg); padding: 0; }

.btn .icon { color: inherit; }

/* ══ Window caption buttons ════════════════════════════════════════════════
   For a frameless desktop window: minimize / maximize-restore / close, top
   right of the drag region (see .drag-region in depth.layouts.css). Group
   them in .caption-btns; each .caption-btn carries two icons for the middle
   slot and toggles its own aria-pressed to swap them ([aria-pressed="true"]
   reads as "restore"). .caption-btn-close is the only button allowed a solid
   fill, and only on hover or focus, never at rest. */
.caption-btns { display: inline-flex; align-items: stretch; gap: 2px; flex: none; }
.caption-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: var(--ctl-h); min-height: var(--ctl-h); padding: 0;
  border: var(--line-w) solid transparent; border-radius: var(--radius-ctl);
  background: transparent; color: var(--ink-2); cursor: pointer; box-shadow: none;
  transition: var(--transition-colors);
}
/* fixed at 12px with a heavier stroke: 3.2 units at 12px is 1.6px, the weight
   K9's own 12-box glyphs had, and no token names it. */
.caption-btn > svg { width: 12px; height: 12px; stroke: currentColor; fill: none;
                      stroke-width: 3.2; stroke-linecap: round; stroke-linejoin: round; display: block; }
.caption-btn:is(:hover, .is-hover) { background: var(--surface-2); color: var(--ink-1); }
.caption-btn:is(:focus-visible, .is-focus) { outline: var(--focus-w) solid var(--focus-ring); outline-offset: -2px; }
.caption-btn .caption-i-restore { display: none; }
.caption-btn[aria-pressed="true"] .caption-i-max { display: none; }
.caption-btn[aria-pressed="true"] .caption-i-restore { display: block; }
.caption-btn-close:is(:hover, .is-hover) { background: var(--danger-fill); color: var(--on-danger); }

/* ══ Fields ════════════════════════════════════════════════════════════════
   .field on <input>, <textarea class="field textarea"> and <select class="field
   select">. The label sits above (.field-label); one sentence of help below
   (.field-help); an error says so in words with an icon (.field-error) and the
   field carries aria-invalid="true". */
.field-group { display: flex; flex-direction: column; gap: var(--sp-1); min-width: 0; }
.field-label { font: var(--fw-strong) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-2); }
.field-help  { font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-3); }
.field-error { display: flex; align-items: center; gap: var(--sp-1);
               font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--danger-ink); }

.field {
  display: block; width: 100%; min-width: 0; height: var(--ctl-h); padding: 0 var(--sp-2);
  border: var(--line-w) solid var(--line-strong); border-radius: var(--radius-ctl);
  background: var(--surface-sunken); color: var(--ink-1);
  font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui);
  transition: var(--transition-colors);
}
.field::placeholder { color: var(--ink-3); opacity: 1; }
.field:is(:hover, .is-hover) { border-color: var(--ink-3); }
.field:is(:focus, .is-focus) { border-color: var(--accent); outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-offset); }
.field:is(:disabled, [aria-disabled="true"]) { background: var(--surface-2); border-color: var(--line-subtle); color: var(--ink-disabled); cursor: default; }
.field:is(:disabled, [aria-disabled="true"])::placeholder { color: var(--ink-disabled); }
.field[aria-invalid="true"] { border-color: var(--danger-ink); }

.textarea { height: auto; min-height: calc(3 * var(--lh-body) + 2 * var(--sp-2)); padding: var(--sp-2); resize: vertical; }

/* Search: a field with a leading icon, the same corners as every field. */
.search { position: relative; display: block; min-width: 0; }
.search > .icon { position: absolute; left: var(--sp-2); top: 50%; translate: 0 -50%; color: var(--ink-3); pointer-events: none; }
.search > .field { padding-left: calc(var(--sp-2) + var(--icon-sm) + var(--sp-2)); padding-right: calc(var(--sp-2) + var(--sp-7)); }
.search-hint { position: absolute; right: var(--sp-2); top: 50%; translate: 0 -50%; pointer-events: none;
               font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-3); }

/* Select: looks exactly like a field plus a chevron. Works on a native
   <select> and on a menu button drawn as a field ("Sort: by name"). */
.select {
  appearance: none; display: flex; align-items: center; text-align: left; cursor: pointer;
  padding-right: calc(var(--sp-2) + var(--icon-sm) + var(--sp-1));
  background-image:
    linear-gradient(45deg,  transparent 50%, var(--ink-2) 50%),
    linear-gradient(135deg, var(--ink-2) 50%, transparent 50%);
  background-position:
    calc(100% - var(--sp-3) - var(--chevron-size)) 50%,
    calc(100% - var(--sp-3)) 50%;
  background-size: var(--chevron-size) var(--chevron-size);
  background-repeat: no-repeat;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.select[aria-expanded="true"] {
  background-image:
    linear-gradient(135deg, transparent 50%, var(--ink-2) 50%),
    linear-gradient(45deg,  var(--ink-2) 50%, transparent 50%);
}
.select:is(:disabled, [aria-disabled="true"]) {
  background-image:
    linear-gradient(45deg,  transparent 50%, var(--ink-disabled) 50%),
    linear-gradient(135deg, var(--ink-disabled) 50%, transparent 50%);
}
.select-key { color: var(--ink-2); margin-right: var(--sp-1); }

/* ══ Checkbox and radio ════════════════════════════════════════════════════
   <label class="check"><input class="check-input" type="checkbox">
   <span class="check-mark" aria-hidden="true"></span> Label</label>
   The whole row is the target (at least --hit-min tall). The native input
   stays in the page for the keyboard and the screen reader. */
.check, .radio {
  position: relative; display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: var(--hit-min); cursor: pointer;
  font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui); color: var(--ink-1);
}
.check-input, .radio-input {
  position: absolute; left: 0; top: 50%; translate: 0 -50%;
  width: var(--mark-size); height: var(--mark-size); margin: 0; opacity: 0; cursor: pointer;
}
.check-mark, .radio-mark {
  position: relative; flex: none; width: var(--mark-size); height: var(--mark-size);
  border: var(--line-w) solid var(--line-strong); background: var(--surface-sunken);
  transition: var(--transition-colors);
}
.check-mark { border-radius: var(--radius-xs); }
.radio-mark { border-radius: var(--radius-round); }
.check:is(:hover, .is-hover) .check-mark, .radio:is(:hover, .is-hover) .radio-mark { border-color: var(--ink-3); }
.check-input:is(:focus-visible, .is-focus) + .check-mark,
.radio-input:is(:focus-visible, .is-focus) + .radio-mark { outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-offset); }
.check-input:is(:checked, :indeterminate) + .check-mark { background: var(--accent); border-color: var(--accent); }
.check-input:checked + .check-mark::after {
  content: ""; position: absolute; left: 50%; top: 45%;
  width: calc(var(--mark-size) * .3); height: calc(var(--mark-size) * .56);
  border: solid var(--on-accent); border-width: 0 var(--glyph-stroke) var(--glyph-stroke) 0;
  translate: -50% -50%; rotate: 45deg;
}
.check-input:indeterminate + .check-mark::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: calc(var(--mark-size) * .5); height: var(--glyph-stroke);
  background: var(--on-accent); translate: -50% -50%;
}
.radio-input:checked + .radio-mark { border-color: var(--accent); }
.radio-input:checked + .radio-mark::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: var(--radio-dot); height: var(--radio-dot);
  border-radius: var(--radius-round); background: var(--accent); translate: -50% -50%;
}
.check:has(.check-input:disabled), .radio:has(.radio-input:disabled) { color: var(--ink-disabled); cursor: default; }
.check-input:disabled + .check-mark, .radio-input:disabled + .radio-mark { border-color: var(--line-subtle); background: var(--surface-2); }
.check-input:disabled:checked + .check-mark { background: var(--ink-disabled); border-color: transparent; }
.check-input[aria-invalid="true"] + .check-mark { border-color: var(--danger-ink); }

/* ══ Switch ════════════════════════════════════════════════════════════════
   Only for an on/off that applies immediately. A choice applied by a Save
   button stays a checkbox. The state word sits beside it: supply both words,
   .switch-on and .switch-off; the right one shows. The input carries
   role="switch". */
.switch {
  position: relative; display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: var(--hit-min); cursor: pointer;
  font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui); color: var(--ink-1);
}
.switch-input { position: absolute; left: 0; top: 50%; translate: 0 -50%; width: var(--switch-w); height: var(--switch-h); margin: 0; opacity: 0; cursor: pointer; }
.switch-track {
  position: relative; flex: none; width: var(--switch-w); height: var(--switch-h);
  border: var(--line-w) solid var(--line-strong); border-radius: var(--radius-round); background: var(--surface-sunken);
  transition: var(--transition-colors);
}
.switch-track::after {
  content: ""; position: absolute; top: 50%; left: calc((var(--switch-h) - var(--switch-knob)) / 2 - var(--line-w));
  width: var(--switch-knob); height: var(--switch-knob); translate: 0 -50%;
  border-radius: var(--radius-round); background: var(--ink-2);
}
.switch:is(:hover, .is-hover) .switch-track { border-color: var(--ink-3); }
.switch-input:is(:focus-visible, .is-focus) + .switch-track { outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-offset); }
.switch-input:checked + .switch-track { background: var(--accent); border-color: var(--accent); }
.switch-input:checked + .switch-track::after {
  left: auto; right: calc((var(--switch-h) - var(--switch-knob)) / 2 - var(--line-w)); background: var(--on-accent);
}
.switch-state { color: var(--ink-2); }
.switch-on { display: none; }
.switch-input:checked ~ .switch-state .switch-on { display: inline; }
.switch-input:checked ~ .switch-state .switch-off { display: none; }
.switch:has(.switch-input:disabled) { color: var(--ink-disabled); cursor: default; }
.switch:has(.switch-input:disabled) .switch-state { color: var(--ink-disabled); }
.switch-input:disabled + .switch-track { border-color: var(--line-subtle); background: var(--surface-2); }
.switch-input:disabled + .switch-track::after { background: var(--ink-disabled); }

/* ══ Segmented control ═════════════════════════════════════════════════════
   role="radiogroup" with role="radio" items (aria-checked), or a group of
   aria-pressed buttons. The selected segment is a raised plane with a line,
   never a glow. */
.seg {
  display: inline-flex; align-items: stretch; gap: var(--seg-pad); height: var(--ctl-h); padding: var(--seg-pad);
  background: var(--surface-sunken); border: var(--line-w) solid var(--line-subtle); border-radius: var(--radius-ctl);
}
.seg-item {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-1);
  padding: 0 var(--sp-3); border: var(--line-w) solid transparent; border-radius: var(--radius-ctl);
  background: transparent; color: var(--ink-2); cursor: pointer; white-space: nowrap;
  font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui);
  transition: var(--transition-colors);
}
.seg-item:is(:hover, .is-hover) { background: var(--surface-2); color: var(--ink-1); }
.seg-item:is(:focus-visible, .is-focus) { outline: var(--focus-w) solid var(--focus-ring); outline-offset: 0; }
.seg-item:is([aria-checked="true"], [aria-pressed="true"]) {
  background: var(--surface-1); border-color: var(--line-strong); color: var(--ink-1); font-weight: var(--fw-strong);
}
.seg-item:is(:disabled, [aria-disabled="true"]) { background: transparent; color: var(--ink-disabled); cursor: default; }

/* ══ Tabs ══════════════════════════════════════════════════════════════════ */
.tabs { display: flex; gap: var(--sp-1); border-bottom: var(--line-w) solid var(--line-subtle); }
.tab {
  display: inline-flex; align-items: center; gap: var(--sp-2); height: var(--ctl-h); padding: 0 var(--sp-3);
  margin-bottom: calc(-1 * var(--line-w));
  border: 0; border-bottom: var(--underline-w) solid transparent; background: transparent;
  color: var(--ink-2); cursor: pointer; white-space: nowrap;
  font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui);
  transition: var(--transition-colors);
}
.tab:is(:hover, .is-hover) { color: var(--ink-1); }
.tab:is(:focus-visible, .is-focus) { outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-inset); border-radius: var(--radius-ctl); }
.tab[aria-selected="true"] { color: var(--ink-1); font-weight: var(--fw-strong); border-bottom-color: var(--accent-ink); }
.tab:is(:disabled, [aria-disabled="true"]) { color: var(--ink-disabled); cursor: default; }

/* ══ Nav row: one component for every side rail and settings list ═════════ */
.nav { display: flex; flex-direction: column; gap: var(--seg-pad); }
.nav-section { padding: var(--sp-3) var(--sp-3) var(--sp-1); font: var(--fw-strong) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-2); }
.nav-row {
  position: relative; display: flex; align-items: center; gap: var(--sp-3); width: 100%;
  min-height: var(--row-h); padding: 0 var(--sp-3);
  border: 0; border-radius: var(--radius-ctl); background: transparent; color: var(--ink-1);
  font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui); text-align: left; text-decoration: none; cursor: pointer;
  transition: var(--transition-colors);
}
.nav-row > .icon { width: var(--icon-md); height: var(--icon-md); color: var(--ink-2); }
.nav-row-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.nav-row-hint { font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-3); }
.nav-row > .badge { margin-left: auto; }
.nav-row:is(:hover, .is-hover) { background: var(--surface-2); }
.nav-row:is(:focus-visible, .is-focus) { outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-inset); }
.nav-row[aria-current]:not([aria-current="false"]) { background: var(--surface-2); font-weight: var(--fw-strong); }
.nav-row[aria-current]:not([aria-current="false"])::before {
  content: ""; position: absolute; left: 0; top: var(--sp-2); bottom: var(--sp-2); width: var(--bar-w);
  border-radius: var(--radius-xs); background: var(--mark-ink);
}
.nav-row[aria-current]:not([aria-current="false"]) > .icon { color: var(--mark-ink); }
.nav-row:is(:disabled, [aria-disabled="true"]) { color: var(--ink-disabled); cursor: default; }

/* ══ Menu: context, toolbar, filter, sort, status popover, overflow ════════ */
.menu {
  display: flex; flex-direction: column; min-width: var(--menu-min); padding: var(--sp-1);
  background: var(--surface-3); border: var(--line-w) solid var(--line-subtle); border-radius: var(--radius-surface);
  box-shadow: var(--elev-float); z-index: var(--z-menu);
}
.menu-item {
  position: relative; display: grid; grid-template-columns: var(--icon-sm) 1fr auto; align-items: center; column-gap: var(--sp-2);
  min-height: var(--ctl-h); padding: 0 var(--sp-3) 0 var(--sp-2);
  border: 0; border-radius: var(--radius-ctl); background: transparent; color: var(--ink-1);
  font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui); text-align: left; cursor: pointer;
  transition: var(--transition-colors);
}
.menu-item > .icon { grid-column: 1; }
.menu-item-text { grid-column: 2; display: flex; flex-direction: column; min-width: 0; }
.menu-item-key { grid-column: 3; font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-3); }
.menu-item-reason { font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-3); }
.menu-item:is(:hover, .is-hover) { background: var(--surface-2); }
.menu-item:is(:focus-visible, .is-focus) { outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-inset); }
.menu-item:is(:disabled, [aria-disabled="true"]) { color: var(--ink-disabled); cursor: default; background: transparent; }
.menu-item-danger { color: var(--danger-ink); }
.menu-item[aria-checked="true"]::before {
  content: ""; grid-column: 1; grid-row: 1; justify-self: center;
  width: calc(var(--mark-size) * .3); height: calc(var(--mark-size) * .56); margin-top: calc(-1 * var(--glyph-stroke));
  border: solid var(--accent-ink); border-width: 0 var(--glyph-stroke) var(--glyph-stroke) 0; rotate: 45deg;
}
.menu-label { padding: var(--sp-2) var(--sp-2) var(--sp-1); font: var(--fw-strong) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-2); }
.menu-sep { height: var(--line-w); margin: var(--sp-1) 0; border: 0; background: var(--line-subtle); }
[data-density="compact"] .menu-item { font-size: var(--fs-dense); line-height: var(--lh-dense); }

/* ══ Tooltip: replaces title= and serves the "?" help ═════════════════════
   Put .tip inside a .tip-host; it shows on hover and on keyboard focus after
   --tip-delay. The app closes it on Esc. .tip.is-open shows it outright.
   It opens below, aligned to the host's start edge; .tip-end aligns it to the
   end edge for hosts near the right of a window. */
.tip-host { position: relative; display: inline-flex; }
.tip {
  position: absolute; left: 0; top: calc(100% + var(--sp-1)); z-index: var(--z-tip);
  width: max-content; max-width: var(--tip-max); padding: var(--sp-1) var(--sp-2);
  background: var(--surface-3); color: var(--ink-1); border: var(--line-w) solid var(--line-subtle); border-radius: var(--radius-ctl);
  box-shadow: var(--elev-float);
  font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--font-ui); text-align: left; white-space: normal;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease), visibility 0s linear var(--dur-fast);
}
.tip-host:is(:hover, :focus-within) > .tip {
  opacity: 1; visibility: visible;
  transition: opacity var(--dur-fast) var(--ease) var(--tip-delay), visibility 0s linear var(--tip-delay);
}
.tip-end { left: auto; right: 0; }
.tip.is-open { position: static; opacity: 1; visibility: visible; transition: none; }
.tip-host.is-dismissed > .tip { opacity: 0; visibility: hidden; }
.help {
  display: inline-flex; align-items: center; justify-content: center; width: var(--hit-min); height: var(--hit-min);
  padding: 0; border: var(--line-w) solid var(--line-strong); border-radius: var(--radius-round);
  background: transparent; color: var(--ink-2); cursor: help;
  font: var(--fw-strong) var(--fs-caption)/1 var(--font-ui);
}
.help:is(:focus-visible, .is-focus) { outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-offset); }

/* ══ Dialog ════════════════════════════════════════════════════════════════
   Widths sm / md / lg / full. Title left, close at the right; the footer is
   right-aligned with the primary rightmost and Cancel left of it. A confirm
   step names the count or the targets in one sentence. */
.dialog {
  display: flex; flex-direction: column; width: var(--dialog-md); max-width: calc(100vw - 2 * var(--sp-4));
  max-height: calc(100vh - 2 * var(--sp-4)); padding: 0; margin: auto;
  background: var(--surface-1); color: var(--ink-1);
  border: var(--line-w) solid var(--line-subtle); border-radius: var(--radius-surface); box-shadow: var(--elev-dialog);
}
.dialog:not([open]):is(dialog) { display: none; }
.dialog::backdrop { background: var(--scrim); }
.dialog-sm { width: var(--dialog-sm); }
.dialog-md { width: var(--dialog-md); }
.dialog-lg { width: var(--dialog-lg); }
.dialog-full { width: calc(100vw - 2 * var(--sp-4)); height: calc(100vh - 2 * var(--sp-4)); }
.dialog-header { display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-4); border-bottom: var(--line-w) solid var(--line-subtle); }
.dialog-title { flex: 1; min-width: 0; margin: 0; font: var(--fw-strong) var(--fs-subtitle)/var(--lh-subtitle) var(--font-display); color: var(--ink-1); }
.dialog-body { display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-4); overflow: auto;
               font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui); }
.dialog-footer { display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: var(--sp-2);
                 padding: var(--sp-3) var(--sp-4); border-top: var(--line-w) solid var(--line-subtle); }
.dialog-confirm-text { flex: 1 1 auto; margin-right: auto; color: var(--ink-1); font: var(--fw-strong) var(--fs-body)/var(--lh-body) var(--font-ui); }

/* ══ Table and list row ════════════════════════════════════════════════════ */
.table { width: 100%; border-collapse: collapse; font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui); color: var(--ink-1); }
.table th {
  height: var(--ctl-h); padding: 0 var(--cell-pad-x); text-align: left; white-space: nowrap;
  font: var(--fw-strong) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-2);
  border-bottom: var(--line-w) solid var(--line-subtle);
}
/* Sortable heading (v2.4, from NexusStats' own component, 2026-10-07). Markup:
   <th scope="col" data-sort="field"><button class="sort-head" type="button">Label</button></th>
   A real button inside the heading: Tab reaches it, Enter or Space sorts. The <th> keeps aria-sort ("ascending" or
   "descending"); the arrow only echoes it, so it is given an empty text alternative where that is supported.
   Target at least --ctl-h-sm (24px or more at every density) each way. */
.sort-head {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  min-height: var(--ctl-h-sm); min-width: var(--ctl-h-sm);
  margin: 0 calc(-1 * var(--sp-1)); padding: 0 var(--sp-1);
  background: transparent; border: 0; border-radius: var(--radius-xs);
  color: inherit; font: inherit; text-align: inherit; white-space: nowrap; cursor: pointer;
  transition: var(--transition-colors);
}
.sort-head:is(:hover, .is-hover) { color: var(--ink-1); }
.sort-head:focus-visible { outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-offset); }
.sort-head.is-focus { outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-offset); }
[aria-sort] > .sort-head { color: var(--ink-1); }
[aria-sort="ascending"] > .sort-head::after { content: "\25B2"; content: "\25B2" / ""; font-size: var(--fs-caption); }
[aria-sort="descending"] > .sort-head::after { content: "\25BC"; content: "\25BC" / ""; font-size: var(--fs-caption); }
.table td { height: var(--row-h); padding: 0 var(--cell-pad-x); border-bottom: var(--line-w) solid var(--line-subtle); }
.table .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; } /* v2.1: numbers right-aligned (Carter) */
.table .cell-meta { color: var(--ink-3); font-size: var(--fs-caption); }
.table tbody tr { transition: var(--transition-colors); }
.table tbody tr:is(:hover, .is-hover) { background: var(--surface-2); }
.table tbody tr:is(:focus-visible, .is-focus) { outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-inset); }
.table tbody tr[aria-selected="true"] { background: var(--accent-wash); }
[data-density="compact"] .table { font-size: var(--fs-dense); line-height: var(--lh-dense); }

.list { display: flex; flex-direction: column; }
.list-row {
  display: flex; align-items: center; gap: var(--sp-3); min-height: var(--row-h); padding: var(--sp-1) var(--cell-pad-x);
  border-bottom: var(--line-w) solid var(--line-subtle); transition: var(--transition-colors);
}
.list-row-text { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.list-row-title { font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui); color: var(--ink-1); }
.list-row-meta  { font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-3); }
.list-row-actions { display: flex; gap: var(--sp-1); flex: none; }
.list-row:is(:hover, .is-hover) { background: var(--surface-2); }
.list-row:is(:focus-visible, .is-focus) { outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-inset); }
.list-row[aria-selected="true"] { background: var(--accent-wash); }
/* The one list row for every app (2026-09-27; unifies K9's .item, .adm-row,
   .tp-kiosk-row, .pick-row). Slots, left to right: a leading .icon, the text,
   a .list-row-trail (a time, a size, a count), the .list-row-actions.
   A row that opens something is a <button> or <a class="list-row">. Selected
   also gets a bar, so it never rides on colour alone. */
.list-row { position: relative; }
.list-row:is(button, a) { width: 100%; background: transparent; border-width: 0 0 var(--line-w); border-style: solid; border-color: var(--line-subtle);
  color: var(--ink-1); text-align: left; text-decoration: none; cursor: pointer; }
.list-row > .icon { width: var(--icon-md); height: var(--icon-md); color: var(--ink-2); }
.list-row-trail { flex: none; font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-3);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.list-row[aria-selected="true"]::before {
  content: ""; position: absolute; left: 0; top: var(--sp-1); bottom: var(--sp-1); width: var(--bar-w);
  border-radius: var(--radius-xs); background: var(--mark-ink);
}
.list-row[aria-selected="true"] > .icon { color: var(--mark-ink); }
.list-row:is(:disabled, [aria-disabled="true"]) { background: transparent; cursor: default; }
.list-row:is(:disabled, [aria-disabled="true"]) :is(.list-row-title, .list-row-meta, .list-row-trail),
.list-row:is(:disabled, [aria-disabled="true"]) > .icon { color: var(--ink-disabled); }

/* ══ Tag, count badge, chip, status dot ════════════════════════════════════
   A tag reports a status in words. It is never the shape of a button.
   Tones: default (neutral), .tag-accent, .tag-success, .tag-warning, .tag-danger. */
.tag, .status, .banner { --tone: var(--ink-2); }
.tag-accent,  .status-accent,  .banner-info    { --tone: var(--accent-ink); }
.tag-success, .status-success, .banner-success { --tone: var(--success-ink); }
.tag-warning, .status-warning                  { --tone: var(--warning-ink); }
.tag-danger,  .status-danger,  .banner-danger  { --tone: var(--danger-ink); }
.status-off { --tone: var(--ink-3); }

.tag {
  display: inline-flex; align-items: center; gap: var(--sp-1); height: var(--tag-h); padding: 0 var(--tag-pad-x);
  border: var(--line-w) solid color-mix(in srgb, var(--tone) var(--mix-rim), transparent); border-radius: var(--radius-xs);
  background: color-mix(in srgb, var(--tone) var(--mix-tag), transparent); color: var(--tone);
  font: var(--fw-strong) var(--fs-caption)/var(--lh-caption) var(--font-ui); white-space: nowrap;
}
.tag > .icon { width: var(--fs-caption); height: var(--fs-caption); stroke-width: 2.6; }

.badge {
  display: inline-flex; align-items: center; justify-content: center; min-width: var(--badge-min); height: var(--badge-min);
  padding: 0 var(--sp-1); border-radius: var(--radius-round);
  background: var(--danger-fill); color: var(--on-danger);
  font: var(--fw-strong) var(--fs-caption)/var(--badge-min) var(--font-mono);
}
.badge-accent { background: var(--accent); color: var(--on-accent); }

.chip {
  display: inline-flex; align-items: center; gap: var(--sp-1); height: var(--ctl-h-sm); padding: 0 var(--seg-pad) 0 var(--sp-2);
  min-height: calc(var(--hit-min) + 2 * var(--line-w)); /* room for the 24px .chip-remove */
  border: var(--line-w) solid var(--line-subtle); border-radius: var(--radius-xs);
  background: var(--surface-2); color: var(--ink-1);
  font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--font-ui); white-space: nowrap;
}
.chip-remove {
  display: inline-flex; align-items: center; justify-content: center; width: var(--hit-min); height: var(--hit-min);
  padding: 0; border: 0; border-radius: var(--radius-xs); background: transparent; color: var(--ink-2); cursor: pointer;
  transition: var(--transition-colors);
}
.chip-remove:is(:hover, .is-hover) { background: var(--surface-3); color: var(--ink-1); }
.chip-remove:is(:focus-visible, .is-focus) { outline: var(--focus-w) solid var(--focus-ring); outline-offset: 0; }

.status { display: inline-flex; align-items: center; gap: var(--sp-2); color: var(--ink-1);
          font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui); }
.status-dot { flex: none; width: var(--dot-size); height: var(--dot-size); border-radius: var(--radius-round); background: var(--tone); }

/* ══ Toast and banner ══════════════════════════════════════════════════════ */
.toast {
  display: flex; align-items: center; gap: var(--sp-3); max-width: var(--dialog-sm); padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-3);
  background: var(--surface-3); color: var(--ink-1); border: var(--line-w) solid var(--line-subtle);
  border-radius: var(--radius-surface); box-shadow: var(--elev-float); z-index: var(--z-toast);
  font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui);
}
.toast-text { flex: 1; min-width: 0; }

.banner-warning { --tone: var(--warning-ink); --tone-line: var(--warning-line); }
.banner {
  display: flex; align-items: center; gap: var(--sp-2); width: 100%; padding: var(--sp-2) var(--sp-3);
  border: var(--line-w) solid var(--tone-line, var(--tone)); border-left-width: var(--bar-w); border-radius: var(--radius-ctl);
  background: color-mix(in srgb, var(--tone) var(--mix-wash), transparent); color: var(--ink-1);
  font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-ui);
}
.banner > .icon { color: var(--tone); }
.banner-text { flex: 1; min-width: 0; }

/* ══ Toolbar and status bar (verbs up top, counts at the bottom) ══════════ */
.toolbar { display: flex; align-items: center; gap: var(--sp-1); min-height: calc(var(--ctl-h) + 2 * var(--sp-2)); padding: 0 var(--sp-2);
           background: var(--surface-1); border-bottom: var(--line-w) solid var(--line-subtle); }
.toolbar-sep { align-self: stretch; width: var(--line-w); margin: var(--sp-2) var(--sp-1); background: var(--line-subtle); }
.toolbar-spacer { flex: 1; }
.statusbar { display: flex; align-items: center; gap: var(--sp-4); min-height: var(--ctl-h-sm); padding: 0 var(--sp-3);
             background: var(--surface-1); border-top: var(--line-w) solid var(--line-subtle);
             font: var(--fw-regular) var(--fs-caption)/var(--lh-caption) var(--font-ui); color: var(--ink-2); }
.statusbar-value { font-family: var(--font-mono); color: var(--ink-1); }

/* ══ Sky theme picker: the one kept delight ════════════════════════════════
   Three tiles, Light / Dark / Match system, each an illustrated sky. The
   system tile paints whichever sky the operating system is on now. The chosen
   tile is marked by a 2px accent border and a bar (shape as well as colour)
   and by aria-pressed. The art is fixed; only the frame follows the theme. */
.sky { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sky-gap); }
.sky-tile {
  position: relative; overflow: hidden; isolation: isolate; display: grid; place-items: center;
  min-height: var(--sky-tile-h); padding: var(--sp-1); cursor: pointer;
  border: var(--line-w) solid var(--line-subtle); border-radius: var(--radius-ctl); background: var(--surface-2);
  font: var(--fw-strong) var(--fs-caption)/var(--lh-caption) var(--font-ui); text-align: center;
  transition: var(--transition-colors);
}
.sky-art { position: absolute; inset: 0; z-index: 0; border-radius: inherit; overflow: hidden; }
.sky-art::after { content: ""; position: absolute; inset: 0; background: var(--sky-scrim); }
.sky-stars, .sky-clouds { position: absolute; inset: var(--sky-over-y) var(--sky-over-x); background-size: 100% 100%; background-repeat: no-repeat; }
.sky-stars  { background-image: var(--sky-stars); }
.sky-clouds { background-image: var(--sky-clouds-low), var(--sky-clouds); }
.sky-orb { position: absolute; top: var(--sky-orb-top); right: var(--sky-orb-right); width: var(--sky-orb); height: var(--sky-orb); border-radius: var(--radius-round); }
.sky-label { position: relative; z-index: 1; }

.sky-tile[data-sky="light"] .sky-art { background: var(--sky-day); }
.sky-tile[data-sky="light"] .sky-orb { background: var(--sky-sun); box-shadow: var(--sky-sun-shadow); }
.sky-tile[data-sky="light"] .sky-stars { display: none; }
.sky-tile[data-sky="light"] .sky-label { color: var(--sky-ink-day); text-shadow: var(--sky-ink-day-halo); }
.sky-tile[data-sky="dark"] .sky-art { background: var(--sky-night); }
.sky-tile[data-sky="dark"] .sky-orb { background: var(--sky-moon); background-size: var(--sky-orb) var(--sky-orb); box-shadow: var(--sky-moon-shadow); }
.sky-tile[data-sky="dark"] .sky-clouds { display: none; }
.sky-tile[data-sky="dark"] .sky-label { color: var(--sky-ink-night); text-shadow: var(--sky-ink-night-halo); }
@media (prefers-color-scheme: light) {
  .sky-tile[data-sky="system"] .sky-art { background: var(--sky-day); }
  .sky-tile[data-sky="system"] .sky-orb { background: var(--sky-sun); box-shadow: var(--sky-sun-shadow); }
  .sky-tile[data-sky="system"] .sky-stars { display: none; }
  .sky-tile[data-sky="system"] .sky-label { color: var(--sky-ink-day); text-shadow: var(--sky-ink-day-halo); }
}
@media (prefers-color-scheme: dark) {
  .sky-tile[data-sky="system"] .sky-art { background: var(--sky-night); }
  .sky-tile[data-sky="system"] .sky-orb { background: var(--sky-moon); background-size: var(--sky-orb) var(--sky-orb); box-shadow: var(--sky-moon-shadow); }
  .sky-tile[data-sky="system"] .sky-clouds { display: none; }
  .sky-tile[data-sky="system"] .sky-label { color: var(--sky-ink-night); text-shadow: var(--sky-ink-night-halo); }
}
.sky-tile:is(:hover, .is-hover) { border-color: var(--line-strong); }
.sky-tile:is(:focus-visible, .is-focus) { outline: var(--focus-w) solid var(--focus-ring); outline-offset: var(--focus-offset); }
.sky-tile[aria-pressed="true"] { border-color: var(--accent-ink); box-shadow: 0 0 0 var(--line-w) var(--accent-ink); }
.sky-tile[aria-pressed="true"] .sky-art::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: var(--bar-w); z-index: 1; background: var(--accent-ink);
}

/* ── Label centring (v2) ───────────────────────────────────────────────────
   Trim each label's text box to cap height and baseline, so the words sit
   dead centre in a fixed-height box whatever the face (DIN, serif, Segoe). */
.btn, .tag, .badge, .status, .seg-item, .nav-row-text, .list-row-trail, .switch-state, .banner-text { text-box: trim-both cap alphabetic; }
