/* Noir OFM — component layer. Written only against tokens.css.
   Every class is prefixed .ui-; variants are data-* attributes; state is ARIA.
   Nothing in the app links this yet — playground.html is the only consumer. */

/* ================= base ================= */
.ui-root { font-family: var(--font); font-size: var(--t-13); line-height: var(--lh-body); color: var(--fg-1); background: var(--bg-0); -webkit-font-smoothing: antialiased; font-synthesis: none; }
.ui-root *, .ui-root *::before, .ui-root *::after { box-sizing: border-box; }
.ui-root :focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.ui-root ::selection { background: var(--accent); color: var(--accent-fg); }
.ui-root ::placeholder { color: var(--fg-3); }
.ui-root a { color: inherit; }
.ui-root svg.ui-icon { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.ui-root svg.ui-icon[data-size="16"] { width: 16px; height: 16px; }
.ui-root svg.ui-icon[data-size="24"] { width: 24px; height: 24px; }
html { scrollbar-gutter: stable; }
html:has(dialog:modal) { overflow: hidden; }

/* ================= type ================= */
.ui-eyebrow { font-size: var(--t-11); font-weight: var(--w-semibold); letter-spacing: var(--track-eyebrow); text-transform: uppercase; color: var(--fg-3); }
.ui-display { font-size: var(--t-30); font-weight: var(--w-semibold); letter-spacing: var(--track-display); line-height: var(--lh-tight); font-variant-numeric: tabular-nums; }
.ui-display[data-size="lg"] { font-size: var(--t-40); }
.ui-display[data-size="sm"] { font-size: var(--t-24); }
.ui-muted { color: var(--fg-2); }
.ui-faint { color: var(--fg-3); }
.ui-num { font-variant-numeric: tabular-nums; }
.ui-kbd { display: inline-block; padding: 1px 6px; border-radius: var(--r-xs); background: var(--bg-2); color: var(--fg-2); font: var(--w-medium) var(--t-11) / 1.4 var(--font); box-shadow: var(--edge-light); }

/* ================= heading ================= */
.ui-heading { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--s-4); flex-wrap: wrap; }
.ui-heading > div { min-width: 0; }
.ui-heading h1, .ui-heading h2, .ui-heading h3 { margin: 0; font-weight: var(--w-semibold); letter-spacing: var(--track-display); line-height: var(--lh-tight); }
.ui-heading[data-level="page"] h1 { font-size: var(--t-24); margin-top: var(--s-1); }
.ui-heading[data-level="section"] h2 { font-size: var(--t-16); }
.ui-heading[data-level="panel"] h3 { font-size: var(--t-14); }
.ui-subtitle { margin: var(--s-1) 0 0; color: var(--fg-2); font-size: var(--t-13); max-width: 62ch; }
.ui-actions { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }

/* ================= button ================= */
.ui-btn { --_bg: var(--bg-2); --_fg: var(--fg-1); --_h: var(--h-md);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2); min-height: var(--_h); padding: 0 var(--s-3);
  border: 0; border-radius: var(--r-md); background: var(--_bg); color: var(--_fg); font: var(--w-medium) var(--t-13) / 1 var(--font);
  cursor: pointer; white-space: nowrap; box-shadow: var(--edge-light); transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out), opacity var(--dur-1) var(--ease-out); }
.ui-btn:hover { --_bg: var(--bg-3); }
.ui-btn:active { transform: translateY(.5px); }
.ui-btn[data-variant="primary"] { --_bg: var(--accent); --_fg: var(--accent-fg); box-shadow: none; }
.ui-btn[data-variant="primary"]:hover { --_bg: var(--accent-hover); }
.ui-btn[data-variant="quiet"] { --_bg: transparent; --_fg: var(--fg-2); box-shadow: none; }
.ui-btn[data-variant="quiet"]:hover { --_bg: var(--bg-2); --_fg: var(--fg-1); }
.ui-btn[data-variant="danger"] { --_bg: transparent; --_fg: var(--bad); box-shadow: none; }
.ui-btn[data-variant="danger"]:hover { --_bg: var(--bg-2); }
.ui-btn[data-variant="icon"] { width: var(--_h); padding: 0; }
.ui-btn[data-variant="icon"][data-quiet] { --_bg: transparent; --_fg: var(--fg-2); box-shadow: none; }
.ui-btn[data-variant="icon"][data-quiet]:hover { --_bg: var(--bg-2); --_fg: var(--fg-1); }
.ui-btn[data-size="sm"] { --_h: var(--h-sm); padding: 0 var(--s-2); font-size: var(--t-12); border-radius: var(--r-sm); }
.ui-btn[data-size="lg"] { --_h: var(--h-lg); padding: 0 var(--s-4); font-size: var(--t-14); }
.ui-btn:disabled, .ui-btn[aria-disabled="true"] { opacity: .4; cursor: not-allowed; transform: none; }
.ui-btn[aria-busy="true"] { cursor: progress; }
.ui-btn[aria-busy="true"] > .ui-icon { display: none; }
.ui-btn[aria-busy="true"]::before { content: ""; width: 14px; height: 14px; border-radius: 50%; border: 2px solid currentColor; border-right-color: transparent; animation: ui-spin .8s linear infinite; }
.ui-btn .ui-icon { width: 16px; height: 16px; }

/* ================= fields ================= */
.ui-field { display: grid; gap: var(--s-1); min-width: 0; }
.ui-field .ui-label { font-size: var(--t-12); font-weight: var(--w-medium); color: var(--fg-2); }
.ui-field .ui-input, .ui-field .ui-textarea, .ui-field .ui-select select {
  width: 100%; min-height: var(--h-md); padding: 0 var(--s-3); border: 0; border-radius: var(--r-sm); background: var(--bg-2); color: var(--fg-1);
  font: var(--w-regular) var(--t-13) / var(--lh-body) var(--font); box-shadow: var(--edge-light); transition: background var(--dur-1) var(--ease-out); }
.ui-field .ui-textarea { padding: var(--s-2) var(--s-3); min-height: 84px; resize: vertical; }
.ui-field :is(.ui-input, .ui-textarea, .ui-select select):hover { background: var(--bg-3); }
.ui-field :is(.ui-input, .ui-textarea, .ui-select select):focus-visible { outline: 2px solid var(--focus); outline-offset: 0; }
.ui-field :is(.ui-input, .ui-textarea, .ui-select select):disabled { opacity: .4; cursor: not-allowed; }
.ui-field [aria-invalid="true"] { outline: 1px solid var(--bad); outline-offset: 0; }
.ui-field [aria-invalid="true"]:focus-visible { outline: 2px solid var(--bad); }
.ui-field .ui-help { font-size: var(--t-12); color: var(--fg-3); }
.ui-field .ui-error { font-size: var(--t-12); color: var(--bad); display: flex; align-items: center; gap: var(--s-2); }
.ui-field .ui-error:empty { display: none; }
.ui-search { position: relative; }
.ui-search > .ui-icon { position: absolute; left: 10px; top: 50%; translate: 0 -50%; width: 16px; height: 16px; color: var(--fg-3); pointer-events: none; }
.ui-search > .ui-input { padding-left: 32px; }
.ui-select { position: relative; }
.ui-select select { appearance: none; padding-right: 32px; cursor: pointer; }
.ui-select::after { content: ""; position: absolute; right: 12px; top: 50%; width: 7px; height: 7px; border-right: 1.5px solid var(--fg-3); border-bottom: 1.5px solid var(--fg-3); rotate: 45deg; translate: 0 -70%; pointer-events: none; }
.ui-field input[type="number"].ui-input { font-variant-numeric: tabular-nums; }

/* check / radio */
.ui-check { display: inline-flex; align-items: center; gap: var(--s-2); font-size: var(--t-13); cursor: pointer; }
.ui-check input { appearance: none; margin: 0; width: 16px; height: 16px; flex: none; border-radius: 4px; background: var(--bg-2); box-shadow: var(--edge-light); display: grid; place-items: center; cursor: inherit; transition: background var(--dur-1) var(--ease-out); }
.ui-check input[type="radio"] { border-radius: 50%; }
.ui-check input::before { content: ""; width: 8px; height: 8px; scale: 0; transition: scale var(--dur-1) var(--ease-out); }
.ui-check input[type="checkbox"]::before { width: 9px; height: 5px; border-left: 2px solid var(--accent-fg); border-bottom: 2px solid var(--accent-fg); rotate: -45deg; translate: 0 -1px; }
.ui-check input[type="radio"]::before { border-radius: 50%; background: var(--accent-fg); }
.ui-check input:checked { background: var(--accent); }
.ui-check input:checked::before { scale: 1; }
.ui-check input:disabled, .ui-check:has(input:disabled) { opacity: .4; cursor: not-allowed; }
.ui-check input:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* switch */
.ui-switch { display: inline-flex; align-items: center; gap: var(--s-2); padding: 0; border: 0; background: none; color: var(--fg-1); font: var(--w-medium) var(--t-13) / 1 var(--font); cursor: pointer; }
.ui-switch i { width: 32px; height: 18px; border-radius: var(--r-pill); background: var(--bg-3); box-shadow: var(--edge-light); position: relative; flex: none; transition: background var(--dur-2) var(--ease-out); }
.ui-switch i::after { content: ""; position: absolute; top: 3px; left: 3px; width: 12px; height: 12px; border-radius: 50%; background: var(--fg-2); transition: translate var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out); }
.ui-switch[aria-checked="true"] i { background: var(--accent); }
.ui-switch[aria-checked="true"] i::after { translate: 14px 0; background: var(--accent-fg); }
.ui-switch:disabled { opacity: .4; cursor: not-allowed; }
.ui-switch:focus-visible { outline: none; }
.ui-switch:focus-visible i { outline: 2px solid var(--focus); outline-offset: 2px; }

/* segmented control (radio-based; aria-pressed alias for choiceMarkup migration) */
.ui-seg { display: inline-flex; gap: 2px; padding: 2px; margin: 0; border: 0; border-radius: var(--r-md); background: var(--bg-1); box-shadow: var(--edge-light); }
.ui-seg legend { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.ui-seg-opt { position: relative; }
.ui-seg-opt input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.ui-seg-opt span, .ui-seg > button { display: inline-flex; align-items: center; gap: var(--s-1); min-height: calc(var(--h-md) - 4px); padding: 0 var(--s-3); border: 0; border-radius: calc(var(--r-md) - 2px); background: transparent; color: var(--fg-2); font: var(--w-medium) var(--t-12) / 1 var(--font); cursor: pointer; transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); }
.ui-seg-opt:hover span, .ui-seg > button:hover { color: var(--fg-1); }
.ui-seg-opt input:checked + span, .ui-seg > button[aria-pressed="true"] { background: var(--bg-3); color: var(--fg-1); box-shadow: var(--edge-light); }
/* with a thumb (ui.js wireSegs) the pill itself moves and the option stays transparent */
.ui-seg { position: relative; }
.ui-seg-thumb { position: absolute; left: 0; top: 0; border-radius: calc(var(--r-md) - 2px); background: var(--bg-3); box-shadow: var(--edge-light); pointer-events: none; transition: translate 150ms var(--ease-out), width 150ms var(--ease-out); opacity: 0; }
.ui-seg:has(.ui-seg-thumb) .ui-seg-opt input:checked + span, .ui-seg:has(.ui-seg-thumb) > button[aria-pressed="true"] { background: transparent; box-shadow: none; }
.ui-seg-opt, .ui-seg > button { position: relative; z-index: 1; }
.ui-seg-opt input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: -2px; }
.ui-seg-opt input:disabled + span { opacity: .4; cursor: not-allowed; }
.ui-seg[data-size="sm"] .ui-seg-opt span, .ui-seg[data-size="sm"] > button { min-height: calc(var(--h-sm) - 4px); padding: 0 var(--s-2); }

/* ================= status mark ================= */
.ui-mark { --_c: var(--idle); display: inline-block; width: 8px; height: 8px; flex: none; background: var(--_c); border-radius: 50%; vertical-align: middle; }
.ui-mark[data-state="ok"] { --_c: var(--ok); }
.ui-mark[data-state="bad"] { --_c: var(--bad); border-radius: 1px; }
/* busy: a dim hollow ring with a bright satellite orbiting it; motion off leaves the ring. Instances are staggered so a grid never spins in lockstep. */
.ui-mark[data-state="busy"] { --_c: var(--busy); background: transparent; border: 2px solid rgba(255, 255, 255, .22); position: relative; animation: ui-spin var(--dur-busy) linear infinite; animation-delay: calc(var(--_phase, 0) * -1s); }
.ui-mark[data-state="busy"]::after { content: ""; position: absolute; top: -3px; left: 50%; width: 4px; height: 4px; translate: -50% 0; border-radius: 50%; background: var(--fg-1); }
.ui-mark[data-state="busy"]:nth-of-type(2n) { --_phase: .7; } .ui-mark[data-state="busy"]:nth-of-type(3n) { --_phase: 1.3; }
:is(.ui-card, .ui-row, .ui-tile):nth-child(2n) .ui-mark[data-state="busy"] { --_phase: .5; }
:is(.ui-card, .ui-row, .ui-tile):nth-child(3n) .ui-mark[data-state="busy"] { --_phase: 1.1; }
:is(.ui-card, .ui-row, .ui-tile):nth-child(4n+1) .ui-mark[data-state="busy"] { --_phase: 1.6; }
.ui-mark[data-state="idle"] { --_c: var(--idle); width: 6px; height: 6px; margin: 1px; }
/* attention: the triangle is drawn by ::before so the element itself can carry a halo (::after) without being clipped */
.ui-mark[data-state="attention"] { --_c: var(--attention); --_w: 10px; --_h: 9px; width: var(--_w); height: var(--_h); background: transparent; border-radius: 0; position: relative; animation: ui-pulse var(--dur-pulse) var(--ease-in-out) infinite; }
.ui-mark[data-state="attention"]::before { content: ""; position: absolute; inset: 0; background: var(--_c); clip-path: polygon(50% 0, 100% 100%, 0 100%); }
/* attention carries weight, not just hue: any card or tile whose state is attention also gets a 1px edge (data-attn) */
:is(.ui-card, .ui-tile)[data-attn] { box-shadow: var(--edge-light), inset 0 0 0 1px var(--attention); }
.ui-status { display: inline-flex; align-items: center; gap: var(--s-2); font-size: var(--t-12); color: var(--fg-2); white-space: nowrap; }
.ui-status[data-size="lg"] { font-size: var(--t-13); }
.ui-status[data-size="lg"] .ui-mark { scale: 1.25; }
.ui-status .ui-mark[data-state="attention"] { margin-top: -1px; }

/* ================= chip ================= */
.ui-chip { display: inline-flex; align-items: center; gap: var(--s-1); min-height: 22px; padding: 0 var(--s-2); border: 0; border-radius: var(--r-xs); background: var(--bg-2); color: var(--fg-2); font: var(--w-medium) var(--t-11) / 1 var(--font); white-space: nowrap; }
.ui-chip[data-interactive] { cursor: pointer; transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); }
.ui-chip[data-interactive]:hover { background: var(--bg-3); color: var(--fg-1); }
.ui-chip[aria-pressed="true"] { background: var(--fg-1); color: var(--bg-0); }
.ui-chip[data-shape="pill"] { border-radius: var(--r-pill); min-height: 26px; padding: 0 var(--s-3); font-size: var(--t-12); }
.ui-chip .ui-count { font-variant-numeric: tabular-nums; opacity: .7; }

/* ================= panel / card / metric ================= */
.ui-panel { background: var(--bg-1); border-radius: var(--r-lg); padding: var(--pad-panel); box-shadow: var(--edge-light); }
.ui-panel[data-tone="2"] { background: var(--bg-2); }
.ui-card { background: var(--bg-1); border-radius: var(--r-lg); padding: var(--s-4); box-shadow: var(--edge-light); position: relative; min-width: 0; }
.ui-card[data-selectable] { cursor: pointer; transition: background var(--dur-1) var(--ease-out); }
.ui-card[data-selectable]:hover { background: var(--bg-2); }
.ui-card[aria-selected="true"] { outline: 2px solid var(--accent); outline-offset: -2px; }
/* selection's second cue is a shape, not a colour: a check badge on the top-right corner, so a selected card and an attention-edged card cannot be confused under colour-vision loss */
.ui-card[aria-selected="true"]::after { content: ""; position: absolute; top: -6px; right: -6px; width: 18px; height: 18px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--bg-0); }
.ui-card[aria-selected="true"]::before { content: ""; position: absolute; top: -1px; right: -1px; width: 8px; height: 4px; border-left: 2px solid var(--accent-fg); border-bottom: 2px solid var(--accent-fg); rotate: -45deg; z-index: 1; }
.ui-metric { display: grid; gap: var(--s-1); }
.ui-metric .ui-display { margin-top: var(--s-1); }
.ui-metric .ui-delta { font-size: var(--t-12); color: var(--fg-2); display: inline-flex; gap: var(--s-1); align-items: center; }
.ui-metric .ui-delta[data-tone="ok"] { color: var(--ok); }
.ui-metric .ui-delta[data-tone="bad"] { color: var(--bad); }
.ui-metric[data-density="tight"] { grid-template-columns: 1fr auto; align-items: baseline; gap: 0 var(--s-2); }
.ui-metric[data-density="tight"] .ui-eyebrow { grid-column: 1 / -1; }
.ui-metric[data-density="tight"] .ui-display { font-size: var(--t-24); margin: 0; }
.ui-metric[data-density="tight"] .ui-delta { justify-self: end; }
.ui-metric .ui-spark { grid-column: 1 / -1; width: 100%; height: 28px; margin-top: var(--s-1); color: var(--fg-3); }
.ui-metric .ui-spark[data-accent] { color: var(--accent); }
.ui-metric .ui-spark polyline { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.ui-metric .ui-spark circle { fill: currentColor; }
.ui-panel[data-density="tight"] { padding: var(--s-3) var(--s-4); }
.ui-hair { border: 0; height: 1px; background: var(--edge); margin: var(--s-4) 0; }

/* ================= media tile ================= */
.ui-tile { position: relative; border-radius: var(--r-md); background: var(--bg-1); overflow: hidden; cursor: pointer; box-shadow: var(--edge-light); outline-offset: -2px; }
.ui-tile[aria-selected="true"] { outline: 2px solid var(--accent); }
.ui-tile-media { aspect-ratio: 9 / 16; background: var(--bg-2); display: grid; place-items: center; color: var(--fg-3); overflow: hidden; }
.ui-tile-media img, .ui-tile-media video { width: 100%; height: 100%; object-fit: cover; display: block; }
.ui-tile[data-ratio="1"] .ui-tile-media { aspect-ratio: 1; }
.ui-tile[data-ratio="4-5"] .ui-tile-media { aspect-ratio: 4 / 5; }
.ui-tile-ordinal { position: absolute; top: 8px; left: 8px; width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; background: rgba(0,0,0,.6); color: var(--fg-1); font: var(--w-semibold) var(--t-11) / 1 var(--font); backdrop-filter: blur(2px); }
.ui-tile[aria-selected="true"] .ui-tile-ordinal { background: var(--accent); color: var(--accent-fg); }
.ui-tile-badge { position: absolute; top: 8px; right: 8px; }
.ui-tile-meta { padding: var(--s-2) var(--s-3) var(--s-3); display: grid; gap: 4px; }
.ui-tile-title { font-size: var(--t-12); font-weight: var(--w-medium); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-tile-sub { font-size: var(--t-11); color: var(--fg-3); display: flex; gap: var(--s-2); align-items: center; }
.ui-tile-actions { position: absolute; inset: auto 8px 8px 8px; display: flex; gap: 4px; justify-content: flex-end; opacity: 0; translate: 0 4px; transition: opacity var(--dur-2) var(--ease-out), translate var(--dur-2) var(--ease-out); }
.ui-tile:hover .ui-tile-actions, .ui-tile:focus-within .ui-tile-actions { opacity: 1; translate: 0 0; }
.ui-tile-empty { display: grid; place-items: center; gap: var(--s-1); font-size: var(--t-11); color: var(--fg-3); text-align: center; padding: var(--s-3); }

/* ================= skeleton ================= */
.ui-skel { position: relative; overflow: hidden; background: var(--bg-2); border-radius: var(--r-sm); color: transparent; }
.ui-skel::after { content: ""; position: absolute; inset: 0; translate: -100% 0; background: linear-gradient(90deg, transparent, rgba(255,255,255,.05), transparent); animation: ui-shimmer var(--dur-shimmer) var(--ease-in-out) infinite; }
.ui-skel[data-shape="line"] { height: 12px; border-radius: 4px; }
.ui-skel[data-shape="line"][data-w="60"] { width: 60%; }
.ui-skel[data-shape="line"][data-w="35"] { width: 35%; }
.ui-skel[data-shape="tile"] { aspect-ratio: 9 / 16; border-radius: var(--r-md); }
.ui-skel[data-shape="metric"] { height: 34px; width: 120px; }
.ui-skel[data-shape="circle"] { width: 32px; height: 32px; border-radius: 50%; }

/* ================= list row / table ================= */
.ui-list { display: grid; }
.ui-row { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--s-3); padding: var(--pad-row) var(--s-3); border-radius: var(--r-md); min-width: 0; transition: background var(--dur-1) var(--ease-out); }
.ui-row + .ui-row { box-shadow: inset 0 1px 0 var(--edge); border-radius: 0; }
.ui-row:hover { background: var(--bg-2); box-shadow: none; }
.ui-row[data-interactive] { cursor: pointer; }
.ui-row-main { min-width: 0; display: grid; gap: 2px; }
.ui-row-title { font-size: var(--t-13); font-weight: var(--w-medium); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-row-meta { font-size: var(--t-12); color: var(--fg-3); display: flex; gap: var(--s-2); flex-wrap: wrap; }
.ui-row-thumb { width: 40px; height: 40px; border-radius: var(--r-sm); background: var(--bg-2); object-fit: cover; }
.ui-table { width: 100%; border-collapse: collapse; font-size: var(--t-13); }
.ui-table th { text-align: left; font-size: var(--t-11); font-weight: var(--w-semibold); letter-spacing: var(--track-eyebrow); text-transform: uppercase; color: var(--fg-3); padding: var(--s-2) var(--s-3); }
.ui-table th button { all: unset; cursor: pointer; display: inline-flex; gap: 4px; align-items: center; }
.ui-table th button:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 4px; }
.ui-table th[aria-sort] button::after { content: ""; width: 5px; height: 5px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; rotate: 45deg; translate: 0 -2px; }
.ui-table th[aria-sort="ascending"] button::after { rotate: -135deg; translate: 0 2px; }
.ui-table td { padding: var(--s-3); box-shadow: inset 0 1px 0 var(--edge); vertical-align: middle; }
.ui-table td.ui-num, .ui-table th.ui-num { text-align: right; }
.ui-table tbody tr:hover td { background: var(--bg-2); }
.ui-table-wrap { overflow-x: auto; }

/* ================= tabs ================= */
.ui-tabs { display: inline-flex; gap: 2px; padding: 2px; border-radius: var(--r-md); background: var(--bg-1); box-shadow: var(--edge-light); }
.ui-tab { display: inline-flex; align-items: center; gap: var(--s-2); min-height: calc(var(--h-md) - 4px); padding: 0 var(--s-3); border: 0; border-radius: calc(var(--r-md) - 2px); background: transparent; color: var(--fg-2); font: var(--w-medium) var(--t-13) / 1 var(--font); cursor: pointer; transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); }
.ui-tab:hover { color: var(--fg-1); }
.ui-tab[aria-selected="true"] { background: var(--bg-3); color: var(--fg-1); box-shadow: var(--edge-light); }
.ui-tab .ui-count { font-size: var(--t-11); color: var(--fg-3); font-variant-numeric: tabular-nums; }
.ui-tab[aria-selected="true"] .ui-count { color: var(--fg-2); }
.ui-tabs[data-variant="line"] { background: transparent; box-shadow: none; padding: 0; gap: var(--s-4); border-radius: 0; }
.ui-tabs[data-variant="line"] .ui-tab { border-radius: 0; padding: var(--s-2) 0; box-shadow: none; background: transparent; }
.ui-tabs[data-variant="line"] .ui-tab[aria-selected="true"] { box-shadow: inset 0 -2px 0 var(--fg-1); }

/* ================= sidebar nav / topbar ================= */
.ui-sidebar { width: 230px; background: var(--bg-0); padding: var(--s-4) var(--s-3); display: flex; flex-direction: column; gap: 2px; }
.ui-sidebar[data-collapsed] { width: 64px; }
.ui-sidebar[data-collapsed] .ui-nav-item span, .ui-sidebar[data-collapsed] .ui-nav-caption { display: none; }
.ui-nav-caption { padding: var(--s-4) var(--s-3) var(--s-1); }
.ui-nav-item { display: flex; align-items: center; gap: var(--s-3); min-height: var(--h-md); padding: 0 var(--s-3); border-radius: var(--r-md); color: var(--fg-2); text-decoration: none; font: var(--w-medium) var(--t-13) / 1 var(--font); transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); }
.ui-nav-item:hover { background: var(--bg-1); color: var(--fg-1); }
.ui-nav-item[aria-current="page"] { background: var(--bg-2); color: var(--fg-1); box-shadow: var(--edge-light); }
.ui-nav-item .ui-icon { width: 18px; height: 18px; color: var(--fg-3); }
.ui-nav-item[aria-current="page"] .ui-icon { color: var(--fg-1); }
.ui-nav-item .ui-count { margin-left: auto; font-size: var(--t-11); color: var(--fg-3); font-variant-numeric: tabular-nums; }
.ui-topbar { display: flex; align-items: center; gap: var(--s-3); min-height: 56px; padding: 0 var(--s-5); background: var(--bg-0); }
.ui-crumb { display: flex; align-items: center; gap: var(--s-2); font-size: var(--t-13); color: var(--fg-3); }
.ui-crumb b { color: var(--fg-1); font-weight: var(--w-medium); }
.ui-topbar-right { margin-left: auto; display: flex; align-items: center; gap: var(--s-2); }
.ui-brand { display: flex; align-items: center; gap: var(--s-2); padding: var(--s-2) var(--s-3) var(--s-4); color: var(--fg-1); text-decoration: none; }
.ui-monogram { width: 28px; height: 28px; border-radius: var(--r-sm); background: var(--fg-1); color: var(--bg-0); display: grid; place-items: center; font: var(--w-semibold) var(--t-14) / 1 var(--font); }

/* ================= avatar ================= */
.ui-avatar { display: inline-grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; background: var(--bg-2); color: var(--fg-1); font: var(--w-semibold) var(--t-12) / 1 var(--font); box-shadow: var(--edge-light); flex: none; overflow: hidden; }
.ui-avatar[data-size="sm"] { width: 24px; height: 24px; font-size: var(--t-11); }
.ui-avatar[data-size="lg"] { width: 40px; height: 40px; font-size: var(--t-14); }
.ui-avatar img { width: 100%; height: 100%; object-fit: cover; }

/* ================= notice / callout ================= */
.ui-notice { display: flex; gap: var(--s-3); align-items: flex-start; padding: var(--s-3) var(--s-4); border-radius: var(--r-md); background: var(--bg-2); color: var(--fg-2); font-size: var(--t-13); box-shadow: var(--edge-light); }
.ui-notice .ui-mark { margin-top: 6px; }
.ui-notice strong { color: var(--fg-1); font-weight: var(--w-medium); }
.ui-notice .ui-actions { margin-left: auto; }

/* ================= progress / spinner ================= */
.ui-progress { height: 4px; border-radius: var(--r-pill); background: var(--bg-2); overflow: hidden; }
.ui-progress > span { display: block; height: 100%; width: var(--_v, 0%); background: var(--fg-1); border-radius: inherit; transition: width var(--dur-3) var(--ease-out); }
.ui-progress[data-accent] > span { background: var(--accent); }
.ui-progress[data-indeterminate] > span { width: 40%; animation: ui-indeterminate 1.4s var(--ease-in-out) infinite; }
.ui-spinner { display: inline-block; width: 20px; height: 20px; border-radius: 50%; border: 2px solid var(--bg-3); border-top-color: var(--fg-1); animation: ui-spin .8s linear infinite; flex: none; }
.ui-spinner[data-size="16"] { width: 16px; height: 16px; }
.ui-loading { display: flex; align-items: center; gap: var(--s-3); color: var(--fg-2); padding: var(--s-6); justify-content: center; }

/* ================= empty ================= */
.ui-empty { display: grid; justify-items: center; text-align: center; gap: var(--s-2); padding: var(--s-10) var(--s-6); color: var(--fg-2); }
.ui-empty .ui-icon { width: 28px; height: 28px; color: var(--fg-3); stroke-width: 1.25; }
.ui-empty strong { color: var(--fg-1); font-size: var(--t-14); font-weight: var(--w-semibold); }
.ui-empty p { margin: 0; max-width: 40ch; }
.ui-empty .ui-btn { margin-top: var(--s-2); }

/* ================= disclosure ================= */
.ui-disclosure { border-radius: var(--r-md); background: var(--bg-1); box-shadow: var(--edge-light); }
.ui-disclosure > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: var(--s-2); padding: var(--s-3) var(--s-4); font-weight: var(--w-medium); color: var(--fg-1); }
.ui-disclosure > summary::-webkit-details-marker { display: none; }
.ui-disclosure > summary::before { content: ""; width: 6px; height: 6px; border-right: 1.5px solid var(--fg-3); border-bottom: 1.5px solid var(--fg-3); rotate: -45deg; transition: rotate var(--dur-2) var(--ease-out); }
.ui-disclosure[open] > summary::before { rotate: 45deg; }
.ui-disclosure > summary:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; border-radius: var(--r-md); }
.ui-disclosure > div { padding: 0 var(--s-4) var(--s-4); color: var(--fg-2); }

/* ================= menu (popover) ================= */
.ui-menu { position: fixed; inset: auto; margin: 0; padding: var(--s-1); border: 0; border-radius: var(--r-md); background: var(--bg-3); color: var(--fg-1); box-shadow: var(--shadow-menu), var(--edge-light); min-width: 180px; overflow: visible; }
.ui-menu:popover-open { animation: ui-fade-in var(--dur-2) var(--ease-out); }
.ui-menu-item { display: flex; align-items: center; gap: var(--s-2); width: 100%; min-height: var(--h-md); padding: 0 var(--s-3); border: 0; border-radius: var(--r-sm); background: transparent; color: var(--fg-1); font: var(--w-regular) var(--t-13) / 1 var(--font); cursor: pointer; text-align: left; }
.ui-menu-item:hover, .ui-menu-item:focus-visible { background: var(--bg-2); outline: none; }
.ui-menu-item[data-tone="danger"] { color: var(--bad); }
.ui-menu-item .ui-icon { width: 16px; height: 16px; color: var(--fg-3); }
.ui-menu-item:hover .ui-icon { color: inherit; }
.ui-menu-sep { height: 1px; background: var(--edge); margin: var(--s-1) 0; }
.ui-menu-item .ui-kbd { margin-left: auto; }

/* ================= toast ================= */
.ui-toast-root { position: fixed; inset: auto var(--s-5) var(--s-5) auto; margin: 0; padding: 0; border: 0; background: transparent; display: grid; gap: var(--s-2); pointer-events: none; overflow: visible; width: min(360px, calc(100vw - 40px)); }
.ui-toast-root, .ui-toast-root:popover-open { top: auto; height: auto; max-height: calc(100vh - 40px); align-content: end; }
.ui-toast { align-self: end; height: auto; align-items: center; gap: var(--s-3); padding: var(--s-3) var(--s-4); border-radius: var(--r-md); background: var(--bg-3); color: var(--fg-1); font-size: var(--t-13); box-shadow: var(--shadow-menu), var(--edge-light); pointer-events: auto; animation: ui-toast-in var(--dur-2) var(--ease-out); }
.ui-toast[data-tone="error"] { box-shadow: var(--shadow-menu), inset 0 0 0 1px var(--bad); }
.ui-toast .ui-mark { flex: none; }
.ui-toast .ui-btn { margin-left: auto; }

/* ================= dialog ================= */
.ui-dialog { --_w: 600px; width: min(var(--_w), calc(100vw - 32px)); max-height: calc(100dvh - 32px); margin: auto; padding: 0; border: 0; border-radius: var(--r-xl); background: var(--bg-3); color: var(--fg-1); box-shadow: var(--shadow-dialog), var(--edge-light); display: none; flex-direction: column; overflow: hidden; }
.ui-dialog[open] { display: flex; animation: ui-dialog-in var(--dur-3) var(--ease-out); }
.ui-dialog[data-size="sm"] { --_w: 440px; }
.ui-dialog[data-size="lg"] { --_w: 1080px; }
.ui-dialog::backdrop { background: var(--backdrop); }
.ui-dialog-head { display: flex; align-items: flex-start; gap: var(--s-3); padding: var(--s-5) var(--s-5) 0; }
.ui-dialog-head h2 { margin: 0; font-size: var(--t-16); font-weight: var(--w-semibold); letter-spacing: var(--track-display); }
.ui-dialog-head .ui-subtitle { margin-top: 2px; }
.ui-dialog-body { padding: var(--s-4) var(--s-5); overflow: auto; min-height: 0; color: var(--fg-2); }
.ui-dialog-body p { margin: 0 0 var(--s-3); }
.ui-dialog-foot { display: flex; align-items: center; justify-content: flex-end; gap: var(--s-2); padding: 0 var(--s-5) var(--s-5); }
.ui-dialog-close { position: absolute; top: var(--s-3); right: var(--s-3); }
@media (max-width: 700px) {
  .ui-dialog { --_w: 100vw; width: 100vw; max-height: 92dvh; margin: auto 0 0; border-radius: var(--r-xl) var(--r-xl) 0 0; }
  .ui-dialog[open] { animation: ui-sheet-in var(--dur-3) var(--ease-out); }
}

/* ================= tooltip ================= */
/* Tooltips: one fixed element positioned by ui.js and clamped to the viewport, so a tip near an edge never runs off screen and never widens the page. */
.ui-tip { position: fixed; z-index: var(--z-popover); max-width: min(240px, calc(100vw - 16px)); padding: 3px 7px; border-radius: var(--r-xs); background: var(--fg-1); color: var(--bg-0); font: var(--w-medium) var(--t-11) / 1.3 var(--font); pointer-events: none; opacity: 0; transition: opacity var(--dur-1) var(--ease-out); }
.ui-tip[data-on] { opacity: 1; }

/* ================= range ================= */
.ui-range { appearance: none; width: 100%; height: 20px; background: transparent; margin: 0; }
.ui-range::-webkit-slider-runnable-track { height: 4px; border-radius: var(--r-pill); background: var(--bg-3); }
.ui-range::-moz-range-track { height: 4px; border-radius: var(--r-pill); background: var(--bg-3); }
.ui-range::-webkit-slider-thumb { appearance: none; width: 14px; height: 14px; margin-top: -5px; border-radius: 50%; background: var(--fg-1); border: 0; box-shadow: 0 1px 3px rgba(0,0,0,.5); }
.ui-range::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: var(--fg-1); border: 0; }
.ui-range:focus-visible { outline: none; }
.ui-range:focus-visible::-webkit-slider-thumb { outline: 2px solid var(--focus); outline-offset: 2px; }
.ui-range:disabled { opacity: .4; }

/* ================= auto-loading list ================= */
.ui-loadmore { display: grid; justify-items: center; gap: var(--s-3); padding: var(--s-4) 0; }
.ui-loadmore-sentinel { height: 1px; width: 100%; }
.ui-loadmore-skel { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--s-3); width: 100%; }

/* ================= grids + density ================= */
.ui-grid { display: grid; gap: var(--s-3); grid-template-columns: repeat(auto-fill, minmax(var(--_min, 150px), 1fr)); }
/* a density-controlled grid: exactly --tiles per row; thumbnails follow --tile-ratio (set together by the density control) */
.ui-grid[data-tiles] { grid-template-columns: repeat(var(--tiles), minmax(0, 1fr)); gap: var(--s-2); }
.ui-grid[data-tiles] .ui-tile-media, .ui-grid[data-tiles] .ui-skel[data-shape="tile"] { aspect-ratio: var(--tile-ratio); }
/* ≥ 9 per row: text no longer fits; keep only the mark, overlaid on the thumbnail (set by the density control as data-dense) */
.ui-grid[data-dense="true"] .ui-tile-meta { position: absolute; inset: auto 0 0 0; padding: 4px 8px 6px; background: linear-gradient(transparent, rgba(0, 0, 0, .55)); gap: 0; }
.ui-grid[data-dense="true"] .ui-tile-title { display: none; }
.ui-grid[data-dense="true"] .ui-tile-sub { font-size: 0; }
.ui-grid[data-dense="true"] .ui-tile-ordinal { width: 18px; height: 18px; top: 5px; left: 5px; font-size: 10px; }
.ui-grid[data-dense="true"] .ui-tile-badge, .ui-grid[data-dense="true"] .ui-tile-actions { display: none; }
.ui-density { display: inline-flex; align-items: center; gap: var(--s-1); padding: 2px; border-radius: var(--r-md); background: var(--bg-1); box-shadow: var(--edge-light); }
.ui-density > output { min-width: 68px; text-align: center; font-size: var(--t-12); color: var(--fg-2); font-variant-numeric: tabular-nums; }
.ui-density > .ui-range { width: 96px; height: 24px; }

/* ================= selection bar ================= */
.ui-selbar { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; padding: var(--s-2) var(--s-3); border-radius: var(--r-md); background: var(--bg-2); box-shadow: var(--edge-light); position: sticky; top: var(--s-2); z-index: var(--z-sticky); }
.ui-selbar > strong { font-weight: var(--w-semibold); margin-right: var(--s-2); }

/* ================= animations ================= */
@keyframes ui-spin { to { rotate: 360deg; } }
@keyframes ui-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@keyframes ui-shimmer { to { translate: 100% 0; } }
@keyframes ui-indeterminate { 0% { margin-left: -40%; } 100% { margin-left: 100%; } }
@keyframes ui-fade-in { from { opacity: 0; translate: 0 -4px; } }
@keyframes ui-toast-in { from { opacity: 0; translate: 0 8px; } }
@keyframes ui-dialog-in { from { opacity: 0; scale: .98; } }
@keyframes ui-sheet-in { from { translate: 0 24px; opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .ui-root *, .ui-root *::before, .ui-root *::after { animation-duration: 0ms !important; transition-duration: 0ms !important; } }
:root[data-motion="reduce"] .ui-root *, :root[data-motion="reduce"] .ui-root *::before, :root[data-motion="reduce"] .ui-root *::after, :root[data-motion="reduce"] .ui-dialog, :root[data-motion="reduce"] .ui-toast, :root[data-motion="reduce"] .ui-menu { animation-duration: 0ms !important; transition-duration: 0ms !important; }
/* ---- media viewer (ui.js viewer) ---- */
.ui-view { display: grid; place-items: center; background: #000; border-radius: var(--r-md); overflow: hidden; max-height: min(78vh, 900px); }
.ui-view video, .ui-view img { max-width: 100%; max-height: min(78vh, 900px); width: auto; height: auto; display: block; object-fit: contain; }
.ui-viewer .ui-dialog-body { padding-top: var(--s-2); }
/* while dragging across tiles nothing else may be selected or dragged */
.ui-dragging, .ui-dragging * { user-select: none !important; -webkit-user-select: none !important; }
.ui-dragging img { pointer-events: none; }
