/* tinymoon — UI primitives: buttons, fields, custom select, panels, spinner,
   docs shell, context menu, modal, tooltips, toasts, toggle switch, settings
   rows, segmented control, popover. Data-display widgets (badges, cards,
   tables, stats, empty state) live in widgets.css. The DOM these style comes
   from the matching js/ modules. Requires tokens.css and base.css. */

/* ---------- shared controls ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-7);
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  color: var(--text);
  font-weight: var(--weight-medium);
  font-size: var(--text-xs);
  font-family: var(--font-ui);
  padding: var(--space-7) var(--space-14);
  cursor: pointer;
  transition: border-color var(--dur-base) ease, background var(--dur-base) ease, color var(--dur-base) ease, box-shadow var(--dur-base) ease;
  white-space: nowrap;
}
.btn svg { width: 14px; height: 14px; }
.btn:hover { border-color: var(--accent); color: var(--text); }
.btn:active { background: var(--surface-3); }
.btn:disabled { opacity: 0.45; cursor: default; pointer-events: none; }
.btn.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.btn.primary:hover {
  background: var(--accent-hi);
  border-color: var(--accent-hi);
  box-shadow: 0 0 16px var(--accent-glow);
}
.btn.ghost { background: none; border-color: transparent; color: var(--text-dim); }
.btn.ghost:hover { color: var(--text); border-color: var(--border-2); }
/* Destructive action. Solid red fill with white label (--red-solid is dark
   enough to clear 4.5:1 with --on-red; the error-accent --red is not). */
.btn.danger {
  background: var(--red-solid);
  border-color: var(--red-solid);
  color: var(--on-red);
}
.btn.danger:hover {
  background: var(--red-solid-hi);
  border-color: var(--red-solid-hi);
  box-shadow: 0 0 16px var(--red-glow);
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  background: none;
  border: 1px solid transparent;
  color: var(--text-dim);
  cursor: pointer;
  transition: color var(--dur-base) ease, border-color var(--dur-base) ease, background var(--dur-base) ease, box-shadow var(--dur-base) ease;
}
.icon-btn svg { width: 16px; height: 16px; }
.icon-btn:hover { color: var(--text); border-color: var(--border-2); background: var(--surface-2); }
.icon-btn.on { color: var(--accent-hi); border-color: var(--accent-a40); background: var(--accent-soft); }

/* All text-like input types, including number. */
:is(input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="number"]) {
  background: var(--input-bg);
  border: 1px solid var(--border-2);
  color: var(--text);
  font-weight: var(--weight-normal);
  font-size: var(--text-xs);
  font-family: var(--font-mono);
  padding: var(--space-7) var(--space-10);
  transition: border-color var(--dur-base) ease, box-shadow var(--dur-base) ease;
  user-select: text;
}
:is(input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="number"]):hover { border-color: var(--hover-border); }
:is(input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="number"]):focus { border-color: var(--accent); box-shadow: 0 0 10px var(--accent-a18); }
:is(input[type="text"], input[type="password"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="number"])::placeholder { color: var(--text-faint); }

/* Range slider */
input[type="range"] { width: 100%; height: 6px; background: var(--surface-3); border: 1px solid var(--border-2); cursor: pointer; }
input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 16px; height: 16px; background: var(--accent); border: none; cursor: pointer; }
input[type="range"]::-moz-range-thumb { width: 16px; height: 16px; background: var(--accent); border: none; cursor: pointer; }
input[type="range"]:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; box-shadow: 0 0 12px var(--accent-glow); }

/* Styled-native text controls (createInput / createTextarea). The <input> is
   already styled by the type-attribute rules above; .tm-textarea mirrors them
   (only .modal textarea existed before). */
.tm-input { width: 100%; }
.tm-textarea {
  width: 100%;
  min-height: 72px;
  resize: vertical;
  background: var(--input-bg);
  border: 1px solid var(--border-2);
  color: var(--text);
  font-weight: var(--weight-normal);
  font-size: var(--text-xs);
  font-family: var(--font-mono);
  padding: var(--space-7) var(--space-10);
  transition: border-color var(--dur-base) ease, box-shadow var(--dur-base) ease;
  user-select: text;
}
.tm-textarea:hover { border-color: var(--hover-border); }
.tm-textarea:focus { border-color: var(--accent); box-shadow: 0 0 10px var(--accent-a18); }
.tm-textarea::placeholder { color: var(--text-faint); }
.tm-input:disabled, .tm-textarea:disabled { opacity: 0.45; cursor: default; }

/* Field hint + inline validation error (createField / createInput setError). */
.field-hint { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--text-dim); }
.field-error { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--red); }
.tm-input[aria-invalid="true"], .tm-textarea[aria-invalid="true"] {
  border-color: var(--red);
  box-shadow: 0 0 10px color-mix(in srgb, var(--red) 25%, transparent);
}

/* Slider (createSlider): filled track + sharp thumb, tokens only. The filled
   portion is a gradient driven by --tm-slider-fill, set from JS on input. */
.tm-slider { width: 100%; }
.tm-slider input[type="range"] {
  width: 100%;
  height: 6px;
  border: 1px solid var(--border-2);
  cursor: pointer;
  background: linear-gradient(to right,
    var(--accent) 0 var(--tm-slider-fill, 0%),
    var(--surface-3) var(--tm-slider-fill, 0%) 100%);
}
.tm-slider input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 14px; height: 14px; border-radius: 0;
  background: var(--accent-hi); border: 1px solid var(--accent);
  box-shadow: 0 0 8px var(--accent-glow); cursor: pointer;
}
.tm-slider input[type="range"]::-moz-range-thumb {
  width: 14px; height: 14px; border-radius: 0;
  background: var(--accent-hi); border: 1px solid var(--accent);
  box-shadow: 0 0 8px var(--accent-glow); cursor: pointer;
}
.tm-slider input[type="range"]:focus-visible {
  outline: 1px solid var(--accent); outline-offset: 2px; box-shadow: 0 0 12px var(--accent-glow);
}
.tm-slider input[type="range"]:disabled { opacity: 0.45; cursor: default; }

/* Seek variant (createSlider variant:"seek"): an invisible position scrubber
   the app lays over its OWN visuals (a waveform / timeline canvas). Same native
   range mechanics — only the chrome is blanked. The track and thumb go visually
   transparent while the input fills the wrapper for a full-area hit target; the
   focus-visible outline and slider ARIA are inherited from the base rules above,
   so keyboard seeking and screen-reader value announcements stay intact. The
   app owns the visual representation drawn underneath. */
.tm-slider-seek { position: relative; height: 100%; }
.tm-slider-seek input[type="range"] {
  height: 100%;
  margin: 0;
  border-color: transparent;
  background: transparent;
}
.tm-slider-seek input[type="range"]::-webkit-slider-thumb {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}
.tm-slider-seek input[type="range"]::-moz-range-thumb {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
}

.field { display: flex; flex-direction: column; gap: var(--space-5); }
.field > label {
  font-family: var(--font-mono);
  font-size: var(--text-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.field-row { display: flex; align-items: flex-end; gap: var(--space-12); flex-wrap: wrap; }

/* custom select */
.sel { position: relative; min-width: 160px; }
.sel-btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-10);
  background: var(--input-bg);
  border: 1px solid var(--border-2);
  color: var(--text);
  font-weight: var(--weight-normal);
  font-size: var(--text-xs);
  font-family: var(--font-mono);
  padding: var(--space-7) var(--space-10);
  cursor: pointer;
  transition: border-color var(--dur-base) ease;
}
.sel-btn:hover { border-color: var(--hover-border); }
.sel.open .sel-btn { border-color: var(--accent); }
.sel-btn svg { width: 12px; height: 12px; color: var(--text-faint); flex: none; transition: transform var(--dur-base) ease; }
.sel.open .sel-btn svg { transform: rotate(180deg); color: var(--accent-hi); }
.sel-btn .sel-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sel-menu {
  position: absolute;
  top: calc(100% + 4px);
  inset-inline-start: 0;
  min-width: 100%;
  max-height: 260px;
  overflow-y: auto;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  box-shadow: var(--shadow-pop);
  z-index: var(--z-menu);
  display: none;
}
.sel.open .sel-menu { display: block; animation: menu-in var(--dur-quick) ease; }
.sel-menu.up { top: auto; bottom: calc(100% + 4px); }
@keyframes menu-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.sel-opt {
  padding: var(--space-7) var(--space-12);
  font-weight: var(--weight-normal);
  font-size: var(--text-2xs);
  font-family: var(--font-mono);
  color: var(--text-dim);
  cursor: pointer;
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: var(--space-8);
}
.sel-opt:hover, .sel-opt.hover { background: var(--surface-3); color: var(--text); }
.sel-opt[aria-selected="true"] { color: var(--accent-hi); background: var(--accent-soft); }

/* panels */
.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  padding: var(--space-20);
  margin-bottom: var(--space-24);
}
.panel > h2 {
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: var(--space-16);
  display: flex;
  align-items: center;
  gap: var(--space-8);
}
.panel > h2 svg { width: 15px; height: 15px; color: var(--accent-hi); }

/* spinner — a continuous rotation, deliberately outside the 100–180ms ease
   vocabulary (which covers one-shot eases only). */
.spin { animation: spin 0.8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- docs (mini wiki) ---------- */

.docs-layout { display: flex; gap: var(--space-28); align-items: flex-start; max-width: 1180px; }
.docs-main { flex: 1; min-width: 0; }
.doc-section {
  background: var(--surface);
  border: 1px solid var(--border);
  padding: var(--space-20) var(--space-24);
  margin-bottom: var(--space-20);
  scroll-margin-top: 8px;
}
.doc-title { font-size: var(--text-xl); font-weight: var(--weight-medium); margin-bottom: var(--space-10); cursor: pointer; }
.doc-title:hover { color: var(--accent-hi); }
.doc-body p { margin: 0 0 var(--space-10); color: var(--text-dim); font-size: var(--text-xs); line-height: var(--leading-relaxed); max-width: 820px; }
.doc-body p strong, .doc-body li strong { color: var(--text); font-weight: var(--weight-semibold); }
.doc-body code, .doc-body li code {
  font-weight: var(--weight-normal);
  font-size: var(--text-3xs);
  font-family: var(--font-mono);
  background: var(--surface-2);
  border: 1px solid var(--border);
  padding: 0 var(--space-4);
}
.doc-body .doc-sub {
  font-weight: var(--weight-medium);
  font-size: var(--text-sm);
  font-family: var(--font-brand);
  color: var(--text);
  margin: var(--space-18) 0 var(--space-8);
  padding-top: var(--space-12);
  border-top: 1px solid var(--border);
  scroll-margin-top: 8px;
}
.doc-body .doc-list { margin: 0 0 var(--space-10); padding-inline-start: var(--space-20); }
.doc-body .doc-list li { color: var(--text-dim); font-size: var(--text-xs); line-height: var(--leading-relaxed); margin-bottom: var(--space-6); max-width: 780px; }
/* Fenced ``` code blocks render as <pre class="doc-code"><code>. Reuse the base
   pre surface/border; override only the block margin and reset the inline-code
   chrome that .doc-body code would otherwise apply inside the block. */
.doc-body .doc-code { margin: 0 0 var(--space-10); max-width: 820px; }
.doc-body .doc-code code { background: none; border: none; padding: 0; font-size: var(--text-2xs); font-weight: var(--weight-normal); }

.docs-toc {
  position: sticky;
  top: 0;
  width: 220px;
  flex: none;
  background: var(--surface);
  border: 1px solid var(--border);
  padding: var(--space-12) 0;
  max-height: calc(100dvh - var(--footer-h) - var(--topbar-h) - 64px);
  overflow-y: auto;
}
.docs-toc-head {
  font-weight: var(--weight-medium);
  font-size: var(--text-label);
  font-family: var(--font-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
  padding: 0 var(--space-14) var(--space-8);
}
.docs-toc-item {
  display: block;
  width: 100%;
  text-align: start;
  padding: var(--space-5) var(--space-14);
  background: none;
  border: none;
  border-inline-start: 2px solid transparent;
  color: var(--text-dim);
  font-weight: var(--weight-normal);
  font-size: var(--text-2xs);
  font-family: var(--font-ui);
  cursor: pointer;
}
.docs-toc-item:hover { color: var(--text); background: var(--surface-2); }
.docs-toc-item.active { color: var(--accent-hi); border-inline-start-color: var(--accent); background: var(--accent-soft); }
.docs-toc-item.sub { padding-inline-start: var(--space-26); font-size: var(--text-3xs); }

/* ---------- context menu ---------- */

#tm-ctx-root {
  position: fixed;
  z-index: var(--z-ctx);
  min-width: 200px;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  box-shadow: var(--shadow-pop);
  padding: var(--space-4) 0;
  display: none;
  /* Reset popover defaults (top-layer promotion via popover="manual") */
  margin: 0;
  inset: auto;
}
#tm-ctx-root.open { display: block; animation: menu-in var(--dur-fast) ease; }
#tm-ctx-root .ctx-head {
  padding: var(--space-6) var(--space-14) var(--space-5);
  font-weight: var(--weight-medium);
  font-size: var(--text-label);
  font-family: var(--font-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
}
#tm-ctx-root .ctx-item {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  width: 100%;
  padding: var(--space-7) var(--space-14);
  background: none;
  border: none;
  color: var(--text-dim);
  font-weight: var(--weight-normal);
  font-size: var(--text-2xs);
  font-family: var(--font-ui);
  cursor: pointer;
  text-align: start;
}
#tm-ctx-root .ctx-item svg { width: 14px; height: 14px; flex: none; }
#tm-ctx-root .ctx-item:hover, #tm-ctx-root .ctx-item:focus-visible, #tm-ctx-root .ctx-item.hover { background: var(--accent-soft); color: var(--text); }
#tm-ctx-root .ctx-sep { height: 1px; background: var(--border-2); margin: var(--space-4) 0; }

/* ---------- modal ---------- */

/* Native <dialog> renders in the top-layer — no z-index needed. */
dialog.tm-modal {
  background: var(--surface);
  border: 1px solid var(--border-2);
  box-shadow: var(--shadow-modal);
  min-width: min(420px, calc(100vw - 32px));
  max-width: min(760px, calc(100vw - 64px));
  max-height: calc(100dvh - 120px);
  display: flex;
  flex-direction: column;
  padding: 0;
  animation: modal-in var(--dur-mid) ease;
}
dialog.tm-modal::backdrop {
  background: var(--backdrop);
  backdrop-filter: blur(2px);
}
@keyframes modal-in { from { opacity: 0; transform: translateY(10px) scale(0.98); } to { opacity: 1; transform: none; } }
.modal-head {
  display: flex;
  align-items: center;
  gap: var(--space-12);
  padding: var(--space-14) var(--space-18);
  border-bottom: 1px solid var(--border);
}
.modal-head h3 { font-size: var(--text-base); font-weight: var(--weight-medium); flex: 1; min-width: 0; }
.modal-body { padding: var(--space-18); overflow-y: auto; user-select: text; }
.modal-foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-8);
  padding: var(--space-12) var(--space-18);
  border-top: 1px solid var(--border);
}
.modal textarea { width: 100%; min-height: 90px; }

/* ---------- drawer (openDrawer overlay primitive) ---------- */

/* Edge-anchored overlay panel. The non-modal variant is a positioned <div>
   (needs an explicit z-index); the modal variant is a native <dialog> in the
   top layer. Both share the frame + slide styling here. */
.tm-drawer {
  position: fixed;
  inset-block: 0;
  width: min(420px, calc(100vw - 48px));
  max-width: 100vw;
  height: 100%;
  max-height: 100dvh;
  display: flex;
  flex-direction: column;
  padding: 0;
  margin: 0;
  background: var(--surface);
  border: 1px solid var(--border-2);
  box-shadow: var(--shadow-modal);
  z-index: var(--z-modal);
  transition: transform var(--dur-slow) ease;
}
.tm-drawer-right { inset-inline-end: 0; border-inline-end: none; transform: translateX(100%); }
.tm-drawer-left { inset-inline-start: 0; border-inline-start: none; transform: translateX(-100%); }
/* Logical translate: in RTL the panel still slides from its anchored edge. */
.tm-drawer-right:dir(rtl) { transform: translateX(-100%); }
.tm-drawer-left:dir(rtl) { transform: translateX(100%); }
.tm-drawer.open { transform: translateX(0); }
dialog.tm-drawer { border: 1px solid var(--border-2); }
dialog.tm-drawer::backdrop { background: var(--backdrop); backdrop-filter: blur(2px); }

.tm-drawer-head {
  display: flex;
  align-items: center;
  gap: var(--space-12);
  padding: var(--space-14) var(--space-18);
  border-bottom: 1px solid var(--border);
}
.tm-drawer-head h3 { font-size: var(--text-base); font-weight: var(--weight-medium); flex: 1; min-width: 0; }
.tm-drawer-body { padding: var(--space-18); overflow-y: auto; flex: 1; user-select: text; }

/* ---------- tooltips ---------- */

/* Tooltips are plain-text-only and non-interactive (pointer-events: none).
   Rich content (links, buttons, markdown) belongs in hovercards. */
[id^="tm-tooltip"] {
  position: fixed;
  z-index: var(--z-tooltip);
  max-width: 360px;
  background: var(--surface-3);
  border: 1px solid var(--border-2);
  color: var(--text);
  font-weight: var(--weight-normal);
  font-size: var(--text-3xs);
  line-height: var(--leading-normal);
  font-family: var(--font-ui);
  padding: var(--space-6) var(--space-9);
  box-shadow: var(--shadow-pop);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-base) ease;
  user-select: text;
}
[id^="tm-tooltip"].show { opacity: 1; }

/* ---------- hovercards ---------- */

/* Hovercards are the interactive counterpart of tooltips: they render
   mini-markdown (bold, code, links) and can be hovered/focused into. They
   use the Popover API (popover="manual") for top-layer rendering. */
.tm-hovercard {
  position: fixed;
  max-width: 420px;
  background: var(--surface-3);
  border: 1px solid var(--border-2);
  color: var(--text);
  font-weight: var(--weight-normal);
  font-size: var(--text-3xs);
  line-height: var(--leading-normal);
  font-family: var(--font-ui);
  padding: var(--space-6) var(--space-9);
  box-shadow: var(--shadow-pop);
  pointer-events: auto;
  opacity: 0;
  transition: opacity var(--dur-base) ease;
  /* Reset popover default styles */
  margin: 0;
  inset: auto;
}
.tm-hovercard.show { opacity: 1; }
.tm-hovercard .hc-body { min-width: 0; user-select: text; }
.tm-hovercard .hc-body code {
  font-weight: var(--weight-normal);
  font-size: var(--text-micro);
  font-family: var(--font-mono);
  background: var(--surface-2);
  border: 1px solid var(--border);
  padding: 0 var(--space-4);
}
.tm-hovercard .hc-body strong { font-weight: var(--weight-semibold); }

.md-link {
  color: var(--accent-hi);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.md-link:hover { color: var(--accent); }

/* copy-to-clipboard icon (hovercards + toasts) */
.copy-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex: none;
  padding: 0;
  background: none;
  border: 1px solid transparent;
  color: var(--text-faint);
  cursor: pointer;
  transition: color var(--dur-quick) ease, border-color var(--dur-quick) ease;
}
.copy-btn svg { width: 12px; height: 12px; }
.copy-btn:hover { color: var(--text); border-color: var(--border-2); }
.copy-btn.copied { color: var(--green); }

/* ---------- toasts ---------- */

/* The toast root uses popover="manual" to promote itself into the top layer
   when a <dialog> is open, so toasts remain visible above modals. Reset
   popover default styles (margin, inset, border, background) to preserve
   the original fixed positioning. */
#tm-toast-root {
  position: fixed;
  inset-inline-end: var(--space-16);
  bottom: calc(var(--footer-h) + var(--space-14));
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
  align-items: flex-end;
  pointer-events: none;
  /* Reset popover defaults */
  margin: 0;
  inset: auto;
  border: none;
  padding: 0;
  background: transparent;
}
.toast {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-inline-start: 2px solid var(--accent);
  color: var(--text);
  font-weight: var(--weight-normal);
  font-size: var(--text-2xs);
  font-family: var(--font-ui);
  padding: var(--space-10) var(--space-14);
  max-width: 420px;
  box-shadow: var(--shadow-pop);
  animation: toast-in var(--dur-slow) ease;
  pointer-events: auto;
}
.toast > svg { width: 14px; height: 14px; flex: none; color: var(--accent-hi); }
.toast .toast-msg { min-width: 0; user-select: text; flex: 1; }
.toast .copy-btn { margin-inline-start: var(--space-2); }
.toast .toast-dismiss {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex: none;
  padding: 0;
  margin-inline-start: var(--space-4);
  background: none;
  border: 1px solid transparent;
  color: var(--text-faint);
  cursor: pointer;
  transition: color var(--dur-quick) ease, border-color var(--dur-quick) ease;
}
.toast .toast-dismiss svg { width: 10px; height: 10px; }
.toast .toast-dismiss:hover { color: var(--text); border-color: var(--border-2); }
/* Action button: a compact outline button ahead of the dismiss control. */
.toast .toast-action {
  flex: none;
  margin-inline-start: var(--space-4);
  padding: var(--space-2) var(--space-8);
  background: none;
  border: 1px solid var(--border-2);
  color: var(--accent-hi);
  font-weight: var(--weight-medium);
  font-size: var(--text-3xs);
  font-family: var(--font-ui);
  cursor: pointer;
  transition: color var(--dur-quick) ease, border-color var(--dur-quick) ease;
}
.toast .toast-action:hover { color: var(--text); border-color: var(--accent); }
.toast.err { border-inline-start-color: var(--red); }
.toast.err > svg { color: var(--red); }
/* Coupled with toast.js's removal timeout (200ms): this transition must stay
   shorter than the JS removal delay. */
.toast.fading { opacity: 0; transform: translateX(8px); transition: opacity var(--dur-slow) ease, transform var(--dur-slow) ease; }
.toast.fading:dir(rtl) { transform: translateX(-8px); }
@keyframes toast-in { from { opacity: 0; transform: translateX(16px); } to { opacity: 1; transform: none; } }
@keyframes toast-in-rtl { from { opacity: 0; transform: translateX(-16px); } to { opacity: 1; transform: none; } }
.toast:dir(rtl) { animation-name: toast-in-rtl; }

/* ---------- topbar action buttons ---------- */

#tm-topbar-actions { display: flex; align-items: center; gap: var(--space-4); margin-inline-start: auto; }
#tm-busy:not(.hidden) + #tm-topbar-actions { margin-inline-start: var(--space-16); }
#tm-topbar-actions .icon-btn svg { width: 16px; height: 16px; }

/* ---------- toggle switch ---------- */

.switch {
  position: relative;
  width: 40px;
  height: 22px;
  flex: none;
  background: var(--surface-3);
  border: 1px solid var(--border-2);
  cursor: pointer;
  padding: 0;
  transition: background var(--dur-base) ease, border-color var(--dur-base) ease;
}
.switch i {
  position: absolute;
  top: 2px;
  inset-inline-start: 2px;
  width: 16px;
  height: 16px;
  background: var(--text-dim);
  transition: transform var(--dur-base) ease, background var(--dur-base) ease;
}
.switch.on { background: var(--accent-soft); border-color: var(--accent); }
.switch.on i { transform: translateX(18px); background: var(--accent); box-shadow: 0 0 8px var(--accent-glow); }
.switch.on i:dir(rtl) { transform: translateX(-18px); }

/* ---------- settings rows ---------- */

.set-group { max-width: 720px; }
.set-group > h2 {
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 0 0 var(--space-4);
  display: flex;
  align-items: center;
  gap: var(--space-8);
}
.set-group > h2 svg { width: 15px; height: 15px; color: var(--accent-hi); }
.set-rows { background: var(--surface); border: 1px solid var(--border); margin: var(--space-10) 0 var(--space-28); }
.set-row {
  display: flex;
  align-items: center;
  gap: var(--space-20);
  padding: var(--space-14) var(--space-18);
  border-bottom: 1px solid var(--border);
}
.set-row:last-child { border-bottom: none; }
.set-row .set-text { flex: 1; min-width: 0; }
.set-row .set-title { font-weight: var(--weight-medium); font-size: var(--text-sm); font-family: var(--font-ui); color: var(--text); }
.set-row .set-desc { font-weight: var(--weight-normal); font-size: var(--text-2xs); font-family: var(--font-ui); color: var(--text-dim); margin-top: var(--space-2); }

/* segmented control + tabs — both share .seg for the outer strip styling.
   Buttons (tabs, legacy segmented) and labels (createSegmented radios) are
   styled uniformly. Hidden radios inside createSegmented are visually hidden
   like the other form primitives. */
.seg { display: inline-flex; border: 1px solid var(--border-2); }
.seg button, .seg > label {
  background: none;
  border: none;
  color: var(--text-dim);
  font-weight: var(--weight-medium);
  font-size: var(--text-2xs);
  font-family: var(--font-mono);
  padding: var(--space-6) var(--space-14);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--space-7);
  transition: background var(--dur-base) ease, color var(--dur-base) ease;
}
.seg button + button, .seg > label + label { border-inline-start: 1px solid var(--border-2); }
.seg button svg, .seg > label svg { width: 13px; height: 13px; }
.seg button.on, .seg > label.on { background: var(--accent); color: var(--on-accent); }
.seg button:disabled, .seg > label.disabled { opacity: 0.45; cursor: default; pointer-events: none; }
/* Hidden radios inside createSegmented labels */
.seg > label input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
/* Focus ring for createSegmented (radio focus inside label) */
.seg > label:has(input:focus-visible) {
  outline: 1px solid var(--accent);
  outline-offset: -1px;
  box-shadow: 0 0 12px var(--accent-glow);
}
/* Focus ring for tabs (button focus-visible) */
.seg button[role="tab"]:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: -1px;
  box-shadow: 0 0 12px var(--accent-glow);
}

/* createTabPanels: the tab bar composed with a panel region. */
.tm-tabpanels { display: flex; flex-direction: column; gap: var(--space-14); }
.tm-tabpanel { padding: var(--space-4) 0; }
.tm-tabpanel:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 2px;
}

/* ---------- grid presets (createGrid content primitive) ---------- */

/* CSS-first rectangular layouts. Author in HTML with .tm-grid[data-preset] or
   build with createGrid(). Presets are columns×rows via grid-template-areas.
   A content primitive, NOT a shell mode — it lays out view content only. */
.tm-grid { display: grid; gap: var(--space-16); align-content: start; }
.tm-grid[data-preset="1x1"] { grid-template-areas: "a"; }
.tm-grid[data-preset="2x1"] {
  grid-template-columns: 1fr 1fr;
  grid-template-areas: "a b";
}
.tm-grid[data-preset="1x2"] {
  grid-template-columns: 1fr;
  grid-template-areas: "a" "b";
}
.tm-grid[data-preset="2x2"] {
  grid-template-columns: 1fr 1fr;
  grid-template-areas: "a b" "c d";
}
/* Asymmetric 3-slot presets: a row of two plus one full-width cell. The
   spanning cell uses grid-column (not a named area) so the layout collapses
   cleanly on narrow screens — span 1/-1 becomes the single stacked column. */
.tm-grid[data-preset="2+1"],
.tm-grid[data-preset="1+2"] { grid-template-columns: 1fr 1fr; }
.tm-grid[data-preset="2+1"] > .tm-grid-slot:nth-child(3) { grid-column: 1 / -1; }
.tm-grid[data-preset="1+2"] > .tm-grid-slot:nth-child(1) { grid-column: 1 / -1; }
/* Narrow screens collapse multi-column presets to a single stacked column. */
@media (max-width: 640px) {
  .tm-grid[data-preset="2x1"], .tm-grid[data-preset="2x2"],
  .tm-grid[data-preset="2+1"], .tm-grid[data-preset="1+2"] {
    grid-template-columns: 1fr;
    grid-template-areas: none;
  }
}

/* ---------- checkbox ---------- */

.tm-checkbox {
  display: inline-flex;
  align-items: center;
  gap: var(--space-8);
  cursor: pointer;
  font-weight: var(--weight-normal);
  font-size: var(--text-xs);
  font-family: var(--font-ui);
  color: var(--text);
  user-select: none;
}
/* Visually hidden but focusable and announced by AT. */
.tm-checkbox input,
.tm-radio input,
.tm-file input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.tm-check-indicator {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex: none;
  border: 1px solid var(--border-2);
  background: var(--surface-3);
  color: transparent;
  transition: background var(--dur-base) ease, border-color var(--dur-base) ease, color var(--dur-base) ease;
}
.tm-check-indicator svg { width: 12px; height: 12px; }
.tm-check-indicator.checked {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.tm-checkbox:hover .tm-check-indicator { border-color: var(--accent); }
.tm-checkbox input:focus-visible + .tm-check-indicator {
  outline: 1px solid var(--accent);
  outline-offset: 2px;
  box-shadow: 0 0 12px var(--accent-glow);
}
.tm-checkbox input:disabled + .tm-check-indicator { opacity: 0.45; }
.tm-checkbox:has(input:disabled) { cursor: default; opacity: 0.45; pointer-events: none; }

/* ---------- radio ---------- */

.tm-radio {
  display: inline-flex;
  align-items: center;
  gap: var(--space-8);
  cursor: pointer;
  font-weight: var(--weight-normal);
  font-size: var(--text-xs);
  font-family: var(--font-ui);
  color: var(--text);
  user-select: none;
}
.tm-radio-indicator {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  flex: none;
  border: 1px solid var(--border-2);
  background: var(--surface-3);
  transition: background var(--dur-base) ease, border-color var(--dur-base) ease;
}
.tm-radio-indicator::after {
  content: "";
  width: 8px;
  height: 8px;
  background: transparent;
  transition: background var(--dur-base) ease;
}
.tm-radio-indicator.checked {
  border-color: var(--accent);
}
.tm-radio-indicator.checked::after {
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent-glow);
}
.tm-radio:hover .tm-radio-indicator { border-color: var(--accent); }
.tm-radio input:focus-visible + .tm-radio-indicator {
  outline: 1px solid var(--accent);
  outline-offset: 2px;
  box-shadow: 0 0 12px var(--accent-glow);
}
.tm-radio input:disabled + .tm-radio-indicator { opacity: 0.45; }
.tm-radio:has(input:disabled) { cursor: default; opacity: 0.45; pointer-events: none; }

/* ---------- file input ---------- */

.tm-file {
  display: inline-flex;
  align-items: center;
  gap: var(--space-10);
}
.tm-file-name {
  font-weight: var(--weight-normal);
  font-size: var(--text-2xs);
  font-family: var(--font-mono);
  color: var(--text-dim);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- popover ---------- */

.popover {
  position: fixed;
  z-index: var(--z-popover);
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  box-shadow: var(--shadow-pop);
  padding: var(--space-6);
  display: flex;
  gap: var(--space-4);
  animation: menu-in var(--dur-quick) ease;
  /* Reset popover defaults (top-layer promotion via popover="manual") */
  margin: 0;
  inset: auto;
}

/* ---------- embed (isolation boundary) ---------- */

/* createEmbed's container. Marks a FOREIGN surface (sandboxed iframe or shadow
   root) as off the identity surface. Sharp corners, token colors, minimal: a
   bordered frame with an optional label strip. The isolation is the point, so
   the container stays visually quiet -- it frames foreign content, it does not
   dress it. */
.tm-embed {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-2);
  background: var(--surface);
}
.tm-embed-label {
  font-family: var(--font-mono);
  font-size: var(--text-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  padding: var(--space-6) var(--space-10);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}
.tm-embed-body {
  min-width: 0;
  min-height: 0;
}
.tm-embed-frame {
  display: block;
  width: 100%;
  min-height: 240px;
  border: none;
  background: var(--surface);
}

/* ---------- date picker ---------- */

.tm-datepicker {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  position: relative;
}
.tm-datepicker-label {
  font-family: var(--font-mono);
  font-size: var(--text-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.tm-datepicker-input-row {
  display: flex;
  align-items: center;
}
.tm-datepicker-text {
  flex: 1;
  min-width: 0;
}
.tm-datepicker-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex: none;
  padding: 0;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-inline-start: none;
  color: var(--text-dim);
  cursor: pointer;
  transition: color var(--dur-base) ease, border-color var(--dur-base) ease, background var(--dur-base) ease;
}
.tm-datepicker-toggle svg { width: 16px; height: 16px; }
.tm-datepicker-toggle:hover { color: var(--text); border-color: var(--accent); background: var(--surface-3); }
.tm-datepicker-toggle:disabled { opacity: 0.45; cursor: default; pointer-events: none; }

/* Popover: reset browser defaults and style as calendar dropdown */
.tm-datepicker-popover {
  margin: 0;
  padding: var(--space-10);
  border: 1px solid var(--border-2);
  background: var(--surface-2);
  box-shadow: var(--shadow-pop);
  inset: auto;
  position: absolute;
  top: 100%;
  inset-inline-start: 0;
  z-index: var(--z-popover);
  animation: menu-in var(--dur-quick) ease;
}

.tm-datepicker-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8);
  margin-bottom: var(--space-8);
}
.tm-datepicker-month {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--text);
  flex: 1;
  text-align: center;
  user-select: none;
}
.tm-datepicker-nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex: none;
  padding: 0;
  background: none;
  border: 1px solid transparent;
  color: var(--text-dim);
  cursor: pointer;
  transition: color var(--dur-base) ease, border-color var(--dur-base) ease, background var(--dur-base) ease;
}
.tm-datepicker-nav svg { width: 14px; height: 14px; }
.tm-datepicker-nav:hover { color: var(--text); border-color: var(--border-2); background: var(--surface-3); }
/* Prev button: rotate chevron to point left */
.tm-datepicker-header .tm-datepicker-nav:first-child svg { transform: rotate(90deg); }
/* Next button: rotate chevron to point right */
.tm-datepicker-header .tm-datepicker-nav:last-child svg { transform: rotate(-90deg); }

.tm-datepicker-grid {
  border-collapse: collapse;
  width: 100%;
}
.tm-datepicker-grid th {
  font-family: var(--font-mono);
  font-size: var(--text-label);
  font-weight: var(--weight-medium);
  color: var(--text-faint);
  text-align: center;
  padding: var(--space-4);
  width: calc(100% / 7);
}
.tm-datepicker-grid td {
  padding: var(--space-1);
  text-align: center;
}
.tm-datepicker-day {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  background: none;
  border: 1px solid transparent;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-normal);
  color: var(--text-dim);
  cursor: pointer;
  transition: background var(--dur-base) ease, border-color var(--dur-base) ease, color var(--dur-base) ease;
}
.tm-datepicker-day:hover:not(:disabled) {
  background: var(--surface-3);
  border-color: var(--border-2);
  color: var(--text);
}
.tm-datepicker-day:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: -1px;
  box-shadow: 0 0 12px var(--accent-glow);
}
.tm-datepicker-day.today {
  border-color: var(--border-2);
  font-weight: var(--weight-medium);
  color: var(--text);
}
.tm-datepicker-day.selected,
.tm-datepicker-day[aria-selected="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
  font-weight: var(--weight-medium);
}
.tm-datepicker-day:disabled {
  opacity: 0.3;
  cursor: default;
  pointer-events: none;
}

/* ---------- number stepper (createNumber) ---------- */

/* A native input[type=number] (browser spinners hidden in base.css) framed by
   two custom stepper buttons that respect min/max/step. */
.tm-number {
  display: flex;
  align-items: stretch;
}
.tm-number .tm-number-input {
  flex: 1;
  min-width: 0;
  width: auto;
  text-align: center;
  border-inline: none;
}
.tm-number-step {
  width: 34px;
  height: auto;
  flex: none;
  border: 1px solid var(--border-2);
  background: var(--surface-2);
  color: var(--text-dim);
}
.tm-number-step:hover:not(:disabled) {
  color: var(--text);
  border-color: var(--accent);
  background: var(--surface-3);
}
.tm-number-step:disabled { opacity: 0.45; cursor: default; pointer-events: none; }

/* ---------- time picker (createTimePicker) ---------- */

.tm-timepicker {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  position: relative;
}
.tm-timepicker-label {
  font-family: var(--font-mono);
  font-size: var(--text-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.tm-timepicker-input-row { display: flex; align-items: center; }
.tm-timepicker-text { flex: 1; min-width: 0; }
.tm-timepicker-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex: none;
  padding: 0;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  border-inline-start: none;
  color: var(--text-dim);
  cursor: pointer;
  transition: color var(--dur-base) ease, border-color var(--dur-base) ease, background var(--dur-base) ease;
}
.tm-timepicker-toggle svg { width: 16px; height: 16px; }
.tm-timepicker-toggle:hover { color: var(--text); border-color: var(--accent); background: var(--surface-3); }
.tm-timepicker-toggle:disabled { opacity: 0.45; cursor: default; pointer-events: none; }
.tm-timepicker-popover {
  margin: 0;
  padding: var(--space-6);
  border: 1px solid var(--border-2);
  background: var(--surface-2);
  box-shadow: var(--shadow-pop);
  /* Placed by JS (placeBelow) in viewport coordinates, correct for the
     top-layer promotion the Popover API performs. */
  inset: auto;
  position: fixed;
  z-index: var(--z-popover);
  gap: var(--space-6);
  animation: menu-in var(--dur-quick) ease;
}
/* Flex layout only while open, so the closed-popover UA rule
   ([popover]:not(:popover-open){display:none}) still hides it -- a bare
   `display:flex` on the base rule would out-specify the UA rule and keep it
   visible. The fallback path (no Popover API) toggles display via inline style. */
.tm-timepicker-popover:popover-open { display: flex; }
.tm-timepicker-col {
  max-height: 200px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  min-width: 56px;
}
.tm-timepicker-opt {
  padding: var(--space-6) var(--space-10);
  background: none;
  border: 1px solid transparent;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--text-dim);
  cursor: pointer;
  text-align: center;
  transition: background var(--dur-base) ease, color var(--dur-base) ease, border-color var(--dur-base) ease;
}
.tm-timepicker-opt:hover { background: var(--surface-3); color: var(--text); }
.tm-timepicker-opt:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: -1px;
  box-shadow: 0 0 12px var(--accent-glow);
}
.tm-timepicker-opt.selected,
.tm-timepicker-opt[aria-selected="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

/* ---------- combobox (createCombobox) ---------- */

.tm-combobox { position: relative; }
.tm-combobox-box { position: relative; display: flex; align-items: center; }
.tm-combobox-input { width: 100%; padding-inline-end: var(--space-24); }
.tm-combobox-caret {
  position: absolute;
  inset-inline-end: var(--space-8);
  display: inline-flex;
  pointer-events: none;
  color: var(--text-faint);
}
.tm-combobox-caret svg { width: 12px; height: 12px; transition: transform var(--dur-base) ease; }
.tm-combobox.open .tm-combobox-caret svg { transform: rotate(180deg); color: var(--accent-hi); }

/* Shared floating menu for combobox + multi-select. */
.tm-combobox-menu {
  position: absolute;
  top: 100%;
  inset-inline-start: 0;
  min-width: 100%;
  max-height: 240px;
  overflow-y: auto;
  background: var(--surface-2);
  border: 1px solid var(--border-2);
  box-shadow: var(--shadow-pop);
  z-index: var(--z-menu);
  display: none;
}
.tm-combobox.open .tm-combobox-menu,
.tm-multiselect.open .tm-combobox-menu {
  display: block;
  animation: menu-in var(--dur-quick) ease;
}
.tm-combobox-opt {
  padding: var(--space-7) var(--space-12);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--text-dim);
  cursor: pointer;
  white-space: nowrap;
}
.tm-combobox-opt:hover,
.tm-combobox-opt.active { background: var(--surface-3); color: var(--text); }
.tm-combobox-opt[aria-selected="true"] { color: var(--accent-hi); background: var(--accent-soft); }
.tm-combobox-status {
  padding: var(--space-7) var(--space-12);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--text-faint);
}

/* ---------- multi-select (createMultiSelect) ---------- */

.tm-multiselect { position: relative; }
.tm-multiselect-control {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-5);
  background: var(--input-bg);
  border: 1px solid var(--border-2);
  padding: var(--space-5);
  transition: border-color var(--dur-base) ease, box-shadow var(--dur-base) ease;
}
.tm-multiselect-control:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 10px var(--accent-a18);
}
.tm-multiselect-chips { display: contents; }
.tm-multiselect-input {
  flex: 1;
  min-width: 80px;
  border: none;
  background: none;
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  padding: var(--space-3) var(--space-5);
  outline: none;
}
.tm-multiselect-input::placeholder { color: var(--text-faint); }

/* Sharp removable chip -- radius 0 is the identity. */
.tm-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
  background: var(--accent-soft);
  border: 1px solid var(--accent-a40);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  padding: var(--space-2) var(--space-4) var(--space-2) var(--space-8);
}
.tm-chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  padding: 0;
  background: none;
  border: none;
  color: var(--text-dim);
  cursor: pointer;
  transition: color var(--dur-base) ease;
}
.tm-chip-remove svg { width: 12px; height: 12px; }
.tm-chip-remove:hover { color: var(--red); }
.tm-chip-remove:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 1px;
}

/* ---------- accordion (createAccordion) ---------- */

.tm-accordion {
  border: 1px solid var(--border);
  background: var(--surface);
}
.tm-accordion-item { border-bottom: 1px solid var(--border); }
.tm-accordion-item:last-child { border-bottom: none; }
.tm-accordion-header {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-10);
  background: none;
  border: none;
  padding: var(--space-12) var(--space-16);
  color: var(--text);
  font-family: var(--font-brand);
  font-weight: var(--weight-medium);
  font-size: var(--text-xs);
  text-align: start;
  cursor: pointer;
  transition: background var(--dur-base) ease, color var(--dur-base) ease;
}
.tm-accordion-header:hover { background: var(--surface-2); }
.tm-accordion-header:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: -1px;
  box-shadow: 0 0 12px var(--accent-glow);
}
.tm-accordion-chevron {
  display: inline-flex;
  flex: none;
  color: var(--text-faint);
}
.tm-accordion-chevron svg { width: 16px; height: 16px; transition: transform var(--dur-base) ease; }
.tm-accordion-item.open .tm-accordion-chevron svg { transform: rotate(180deg); color: var(--accent-hi); }
/* grid-template-rows 0fr -> 1fr expansion. Duration token only, so the global
   reduced-motion rule (which zeroes transition-duration) fully covers it. */
.tm-accordion-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-slow) ease;
}
.tm-accordion-item.open .tm-accordion-panel { grid-template-rows: 1fr; }
.tm-accordion-panel-inner { overflow: hidden; }
.tm-accordion-body {
  padding: 0 var(--space-16) var(--space-14);
  color: var(--text-dim);
  font-size: var(--text-xs);
  line-height: var(--leading-relaxed);
}

/* ---------- responsive ---------- */

/* Docs layout: stack TOC above content on narrow screens */
@media (max-width: 768px) {
  .docs-layout { flex-direction: column; }
  .docs-toc {
    position: static;
    width: 100%;
    max-height: none;
    overflow-y: visible;
  }
}

/* Toast: full-width on narrow screens */
@media (max-width: 480px) {
  #tm-toast-root {
    inset-inline-start: var(--space-8);
    inset-inline-end: var(--space-8);
    align-items: stretch;
  }
  .toast { max-width: none; }
}

/* Touch targets: ensure minimum 44px interactive area on touch devices */
@media (pointer: coarse) {
  /* buttons and icon buttons — touch target padding */
  .btn { min-height: 44px; }
  .icon-btn { min-width: 44px; min-height: 44px; }

  /* select trigger — touch target padding */
  .sel-btn { min-height: 44px; }
  .sel-opt { min-height: 44px; }

  /* context menu items — touch target padding */
  #tm-ctx-root .ctx-item { min-height: 44px; }

  /* docs TOC items — touch target padding */
  .docs-toc-item { min-height: 44px; display: flex; align-items: center; }

  /* toggle switch — touch target padding */
  .switch { min-width: 44px; min-height: 44px; }

  /* segmented control — touch target padding */
  .seg button, .seg > label { min-height: 44px; }

  /* datepicker day cells — touch target padding */
  .tm-datepicker-day { min-width: 44px; min-height: 44px; }
  .tm-datepicker-nav { min-width: 44px; min-height: 44px; }

  /* toast dismiss — touch target padding */
  .toast .toast-dismiss { min-width: 44px; min-height: 44px; }

  /* checkbox + radio indicators — touch target padding */
  .tm-checkbox { min-height: 44px; }
  .tm-radio { min-height: 44px; }
}
