/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body {
  font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 14px;
  line-height: 1.4;
  color: var(--fg);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
button { font: inherit; color: inherit; }

/* ---------- theme ---------- */
:root {
  --bg: #0f1115;
  --panel: #161a21;
  --panel-2: #1d222b;
  --border: #262c37;
  --fg: #e7ebf2;
  --fg-dim: #9aa3b2;
  --accent: #5b9dff;
  --accent-2: #7ab0ff;
  /* Foreground on an --accent fill. */
  --accent-fg: #ffffff;
  --ghost-ok: #5bd0a3;
  --ghost-bad: #ff6b6b;
  --shadow: 0 1px 0 rgba(255,255,255,0.03), 0 4px 16px rgba(0,0,0,0.35);
  --radius: 8px;
  --sidebar-w: 280px;
  --inspector-w: 260px;
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #f5f6f8;
    --panel: #ffffff;
    --panel-2: #f0f2f6;
    --border: #d8dde5;
    --fg: #1a1f29;
    --fg-dim: #5a6472;
    --shadow: 0 1px 0 rgba(0,0,0,0.04), 0 4px 16px rgba(15,20,30,0.08);
  }
}

/* ---------- app shell ---------- */
/* Three real columns. The inspector track collapses to zero when nothing is
   selected, so the viewport owns exactly the space between the two panels and
   the wgpu surface resizes with it (rather than being overlapped). The track
   width is not transitioned on purpose: every width change reconfigures the
   surface and reallocates the MSAA + depth targets. */
.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr) 0px;
  height: 100dvh;
  width: 100vw;
  overflow: hidden;
}
.app--inspector-open {
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr) var(--inspector-w);
}

.sidebar {
  background: var(--panel);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.sidebar__header {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 4px;
}
.sidebar__history {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--panel-2);
  color: var(--fg-dim);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  transition: color 100ms, border-color 100ms;
}
.sidebar__history:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}
.sidebar__history:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}
.sidebar__title {
  margin: 0;
  flex: 1;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-dim);
}
.sidebar__body {
  padding: 12px;
  overflow: auto;
  flex: 1 1 auto;
}

/* ---------- palette ---------- */
.sidebar__section-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fg-dim);
  padding-bottom: 6px;
}
/* One notch smaller and un-bolded: nested under .sidebar__section-label,
   grouping the palette into Elements vs Structure. */
.sidebar__subsection-label {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-dim);
  opacity: 0.75;
  padding: 4px 0;
}
.palette {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 10px;
}
.palette + .sidebar__subsection-label {
  margin-top: 8px;
}

.palette-chip {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  cursor: grab;
  user-select: none;
  transition: border-color 120ms ease, transform 120ms ease, background 120ms ease;
  touch-action: none;
}
.palette-chip:hover {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--panel-2));
}
.palette-chip:active,
.palette-chip[data-dragging="true"] {
  cursor: grabbing;
  transform: scale(0.98);
  border-color: var(--accent-2);
}

.palette-chip__icon {
  width: 48px;
  height: 28px;
  border: 2px solid currentColor;
  border-radius: 2px;
  position: relative;
  overflow: hidden;
  color: var(--fg-dim);
}
.palette-chip:hover .palette-chip__icon { color: var(--accent); }

/* Each icon is the same box; the marks inside say which element it is. */
.palette-chip__icon--shelves {
  background: repeating-linear-gradient(to bottom, transparent 0 7px, currentColor 7px 9px);
}
.palette-chip__icon--drawers {
  background: repeating-linear-gradient(to bottom, currentColor 0 6px, transparent 6px 8px);
}
.palette-chip__icon--doors::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 50%;
  width: 2px;
  background: currentColor;
  transform: translateX(-50%);
}
.palette-chip__icon--rail::after {
  content: "";
  position: absolute;
  inset: 35% 10%;
  border-top: 3px solid currentColor;
  border-radius: 3px;
}
/* Dashed = a divider you are about to place, not one that exists. */
.palette-chip__icon--split-h::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto 0;
  border-top: 2px dashed currentColor;
  transform: translateY(-50%);
}
.palette-chip__icon--split-v::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 50%;
  border-left: 2px dashed currentColor;
  transform: translateX(-50%);
}
.palette-chip__label {
  font-size: 12px;
  font-weight: 500;
}

/* ---------- canvas viewport ---------- */
.viewport {
  position: relative;
  background: linear-gradient(180deg, var(--panel-2) 0%, var(--bg) 100%);
  min-width: 0;
  min-height: 0;
  height: 100%;
  overflow: hidden;
}
.viewport__canvas {
  display: block;
  width: 100%;
  height: 100%;
  outline: none;
  touch-action: none;
}

.viewport__overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 12px;
  /* toolbar is absolutely positioned within overlay */
}
.status-pill {
  align-self: flex-start;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 12px;
  color: var(--fg-dim);
  box-shadow: var(--shadow);
}
.status-pill[data-state="ok"] { color: var(--ghost-ok); border-color: var(--ghost-ok); }
.status-pill[data-state="bad"] { color: var(--ghost-bad); border-color: var(--ghost-bad); }

/* ---------- viewport menu (mobile only) ---------- */
.viewport__menu {
  position: absolute;
  top: 12px;
  left: 12px;
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--fg);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  pointer-events: all;
  box-shadow: var(--shadow);
}

/* ---------- inspector ---------- */
.inspector {
  background: var(--panel);
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
}
/* Bottom-sheet grab handle. Only meaningful on mobile, where the inspector is a
   sheet rather than a column. */
.inspector__grip {
  display: none;
  flex: 0 0 auto;
  align-self: center;
  width: 40px;
  height: 4px;
  margin: 8px 0 2px;
  border-radius: 999px;
  background: var(--border);
  cursor: grab;
  touch-action: none;
}

/* Dismisses the mobile sidebar drawer. */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 35;
  background: rgba(0, 0, 0, 0.45);
}
.inspector__header {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 8px;
}
.inspector__title {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-dim);
  flex: 1;
}
.inspector__delete {
  background: none;
  border: 1px solid transparent;
  border-radius: 4px;
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  line-height: 1;
  color: var(--fg-dim);
  cursor: pointer;
  padding: 0;
  transition: border-color 100ms, color 100ms;
}
.inspector__delete:hover:not(:disabled) {
  border-color: var(--ghost-bad);
  color: var(--ghost-bad);
}
.inspector__delete:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}
/* Same shape as the trash button, but neutral — it only deselects. */
.inspector__close {
  background: none;
  border: 1px solid transparent;
  border-radius: 4px;
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  line-height: 1;
  color: var(--fg-dim);
  cursor: pointer;
  padding: 0;
  transition: border-color 100ms, color 100ms;
}
.inspector__close:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.inspector__body {
  padding: 12px 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  overflow: auto;
  flex: 1;
}
.inspector__section {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.inspector__section-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fg-dim);
  padding-bottom: 2px;
  border-bottom: 1px solid var(--border);
}
.inspector__row {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* Sits above a row whose buttons name the options but not the question.
   Its own line: the panel is only wide enough for the buttons themselves. */
.inspector__row-label {
  font-size: 11px;
  color: var(--fg-dim);
  margin-bottom: -2px;
}
.inspector__axis {
  width: 14px;
  font-size: 11px;
  font-weight: 600;
  color: var(--fg-dim);
  flex-shrink: 0;
}
.inspector__value {
  flex: 1;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.inspector__input {
  flex: 1;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 3px 6px;
  font: inherit;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  width: 0; /* let flex take over */
  transition: border-color 100ms;
}
.inspector__input:focus {
  outline: none;
  border-color: var(--accent);
}
.inspector__unit {
  font-size: 11px;
  color: var(--fg-dim);
  flex-shrink: 0;
}

/* ---------- inspector toggle button ---------- */
.inspector__toggle {
  background: none;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 500;
  color: var(--fg-dim);
  cursor: pointer;
  transition: border-color 100ms, color 100ms;
}
.inspector__toggle:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.inspector__select {
  flex: 1;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 4px 6px;
  font: inherit;
  font-size: 12px;
  color: var(--fg);
  cursor: pointer;
}
.inspector__select:focus {
  outline: none;
  border-color: var(--accent);
}
.inspector__btn {
  background: var(--accent);
  color: var(--accent-fg, #fff);
  border: none;
  border-radius: 4px;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.inspector__btn:hover:not(:disabled) {
  filter: brightness(1.08);
}
.inspector__btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.inspector__hint {
  font-size: 10px;
  color: var(--fg-dim);
  line-height: 1.35;
}
/* --- material swatch picker --- */
/* A decor is chosen by look, so the grid is images first: dense enough to
   scan a 150-entry catalogue, large enough to tell two oaks apart. */
.swatches {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(36px, 1fr));
  /* An explicit row height, rather than sizing the squares with
     `aspect-ratio`. A grid item stretches to its row by default, so an
     aspect-ratio'd item takes its height from a row whose height is itself
     derived from that item — the browser resolves the circularity by
     overflowing the cell, and the swatches pile on top of each other. */
  grid-auto-rows: 36px;
  gap: 4px;
  max-height: 176px;
  overflow-y: auto;
  padding: 2px;
  margin: 2px 0 6px;
}
.swatch {
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 4px;
  overflow: hidden;
  cursor: pointer;
  /* The inline background is the decor's average colour: it shows through
     until the swatch image loads, and stays for decors with no image. */
}
.swatch:hover {
  border-color: var(--accent);
}
.swatch__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.swatch--active {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 55%, transparent);
}
.swatch-tabs {
  display: flex;
  width: fit-content;
  border: 1px solid var(--border);
  border-radius: 3px;
  overflow: hidden;
  margin: 2px 0;
}
.swatch-tab {
  padding: 3px 10px;
  border: none;
  border-right: 1px solid var(--border);
  background: var(--panel);
  color: var(--fg-dim);
  font-size: 11px;
  cursor: pointer;
  transition: color 80ms, background 80ms;
}
.swatch-tab:last-child {
  border-right: none;
}
.swatch-tab:hover {
  color: var(--fg);
  background: color-mix(in srgb, var(--accent) 12%, var(--panel));
}
.swatch-tab.is-active {
  color: #fff;
  background: var(--accent);
}

/* --- handle variant picker --- */
.handle-swatches {
  display: grid;
  /* Bar-handle photos are wide (~6:1); give each chip enough width that
     `object-fit: contain` is readable rather than a thin strip. */
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 6px;
  max-height: 220px;
  overflow-y: auto;
  padding: 2px;
  margin: 2px 0 6px;
}
.handle-swatch {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: #fff;
  cursor: pointer;
}
.handle-swatch:hover:not(:disabled) {
  border-color: var(--accent);
}
.handle-swatch:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.handle-swatch--active {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 55%, transparent);
}
.handle-swatch__img {
  display: block;
  width: 100%;
  /* Landscape slot for bar handles; knobs letterbox inside it. */
  aspect-ratio: 2.4 / 1;
  height: auto;
  flex-shrink: 0;
  object-fit: contain;
  object-position: center;
}
.handle-swatch__label {
  margin-top: 4px;
  font-size: 10px;
  line-height: 1.2;
  text-align: center;
  color: var(--fg-dim);
}

.inspector__row--range .inspector__input--range {
  flex: 1;
  min-width: 0;
}
.inspector__btn.is-active {
  outline: 2px solid #fff;
  outline-offset: -2px;
}
/* --- door handle position grid --- */
/* Nine cells, of which the hinge-side column is always dead. The grid is
   deliberately small: it is a diagram of a door, not a control panel. */
.handle-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  width: 108px;
}
.handle-grid__cell {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: transparent;
  cursor: pointer;
}
.handle-grid__cell:hover:not(:disabled) {
  border-color: var(--accent);
}
.handle-grid__cell:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.handle-grid__cell.is-active {
  background: var(--accent);
  border-color: var(--accent);
}
/* A stub of the handle itself, turned the way that position would hang it. */
.handle-grid__bar {
  display: block;
  background: var(--fg-dim);
  border-radius: 1px;
}
.handle-grid__cell.is-active .handle-grid__bar {
  background: var(--accent-fg, #fff);
}
.handle-grid__bar--upright {
  width: 2px;
  height: 16px;
}
.handle-grid__bar--flat {
  width: 16px;
  height: 2px;
}

.inspector__checkbox-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--fg);
  cursor: pointer;
}

/* ---------- carcass editor (sidebar) ---------- */
.carcass-editor {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.carcass-editor__label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fg-dim);
  padding-bottom: 2px;
  border-bottom: 1px solid var(--border);
}
.carcass-editor__row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.carcass-editor__axis {
  width: 14px;
  font-size: 11px;
  font-weight: 600;
  color: var(--fg-dim);
  flex-shrink: 0;
}
.carcass-editor__input {
  flex: 1;
  width: 0;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 3px 6px;
  font: inherit;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  transition: border-color 100ms;
}
.carcass-editor__input:focus {
  outline: none;
  border-color: var(--accent);
}

/* ---------- nav cube ---------- */
.nav-cube {
  position: absolute;
  top: 28px;
  right: 28px;
  width: 64px;
  height: 64px;
  pointer-events: all;
  z-index: 50;
}
.nav-cube__scene {
  width: 100%;
  height: 100%;
  perspective: 180px;
}
.nav-cube__cube {
  width: 64px;
  height: 64px;
  position: relative;
  transform-style: preserve-3d;
  /* transform driven by RAF loop */
}
.nav-cube__face {
  position: absolute;
  width: 64px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border: 1px solid rgba(255,255,255,0.15);
  cursor: pointer;
  user-select: none;
  transition: filter 80ms;
  backface-visibility: visible;
}
.nav-cube__face:hover { filter: brightness(1.35); }
.nav-cube__face--front  { transform: rotateY(0deg)    translateZ(32px); background: rgba(60,100,200,0.82); color: #fff; }
.nav-cube__face--back   { transform: rotateY(180deg)  translateZ(32px); background: rgba(35, 60,120,0.82); color: rgba(255,255,255,0.7); }
.nav-cube__face--right  { transform: rotateY(90deg)   translateZ(32px); background: rgba(30,120, 80,0.82); color: #fff; }
.nav-cube__face--left   { transform: rotateY(-90deg)  translateZ(32px); background: rgba(20, 80, 55,0.82); color: rgba(255,255,255,0.7); }
.nav-cube__face--top    { transform: rotateX(90deg)   translateZ(32px); background: rgba(180,110, 25,0.82); color: #fff; }
.nav-cube__face--bottom { transform: rotateX(-90deg)  translateZ(32px); background: rgba(100, 65, 15,0.82); color: rgba(255,255,255,0.7); }

/* ---------- drag chip (follows the cursor) ---------- */
.drag-ghost {
  position: fixed;
  pointer-events: none;
  background: var(--panel);
  border: 1px solid var(--accent);
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 12px;
  color: var(--fg);
  box-shadow: var(--shadow);
  transform: translate(-50%, -50%);
  z-index: 9999;
  opacity: 0.95;
  white-space: nowrap;
  max-width: 60vw;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Matches the red cell ghost in the viewport: the drop is allowed, but it
   produces a design that cannot be exported. */
.drag-ghost--bad {
  border-color: var(--ghost-bad);
  color: var(--ghost-bad);
}

.inspector__warning {
  margin-top: 8px;
  padding: 6px 8px;
  border: 1px solid var(--ghost-bad);
  border-radius: 4px;
  background: color-mix(in srgb, var(--ghost-bad) 12%, transparent);
  color: var(--ghost-bad);
  font-size: 11px;
  line-height: 1.35;
}

/* ---------- track list ---------- */
/* Shared by split tracks, drawer slots, and shelf compartments — one sizing
   UI (F/%/⇔ mode toggle + value field) for anything divided into Fixed/
   Percent/Flex spans. Scrolls past a handful of rows rather than growing the
   inspector unboundedly. */
.track-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 260px;
  overflow-y: auto;
}
.track-list__row {
  display: flex;
  align-items: center;
  gap: 6px;
}
/* Drawer-only second line, via `TrackListEditor`'s `row_suffix`: the box-height
   field. Indented under its drawer's size row and pulled up against it so the
   pair reads as one entry rather than two list items. */
.track-list__row--sub {
  padding-left: 10px;
  margin-top: -2px;
}
.track-list__sub-label {
  font-size: 10px;
  color: var(--fg-dim);
  flex-shrink: 0;
}
/* Drawer-only: the Open/Close button, via `TrackListEditor`'s `row_prefix`. */
.track-list__toggle {
  flex-shrink: 0;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 8px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--panel);
  color: var(--fg);
  font-size: 10px;
  line-height: 1;
  cursor: pointer;
  transition: color 80ms, background 80ms, border-color 80ms;
}
.track-list__toggle:hover {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, var(--panel));
}
.track-list__toggle.is-open {
  color: #fff;
  border-color: var(--accent);
  background: var(--accent);
}
.track-list__input {
  flex: 1;
  width: 0;
  min-width: 0;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 3px;
  font: inherit;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  padding: 3px 6px;
}
.track-list__input:focus {
  outline: none;
  border-color: var(--accent);
}
/* A shared length is a derived number, not one the user typed — same dimmed
   treatment as the drawer stack's flex-row input. */
.track-list__input.is-flex {
  color: var(--fg-dim);
  font-style: italic;
}
.track-list__input:disabled {
  cursor: not-allowed;
}
.track-list__unit {
  font-size: 10px;
  color: var(--fg-dim);
  flex-shrink: 0;
  width: 14px;
}
.track-list__mode {
  flex-shrink: 0;
  display: flex;
  border: 1px solid var(--border);
  border-radius: 3px;
  overflow: hidden;
}
.track-list__mode-btn {
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-right: 1px solid var(--border);
  background: var(--panel);
  color: var(--fg-dim);
  font-size: 10px;
  line-height: 1;
  cursor: pointer;
  transition: color 80ms, background 80ms;
}
/* Wide enough for a word rather than a glyph — the front's Door/Blind toggle,
   where a symbol would be a guess. */
.track-list__mode-btn--wide {
  width: auto;
  padding: 0 6px;
  font-size: 11px;
}
.track-list__mode-btn:last-child {
  border-right: none;
}
.track-list__mode-btn:hover:not(:disabled) {
  color: var(--fg);
  background: color-mix(in srgb, var(--accent) 12%, var(--panel));
}
.track-list__mode-btn.is-active {
  color: #fff;
  background: var(--accent);
}
.track-list__mode-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.track-list__remove {
  flex-shrink: 0;
  width: 22px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 3px;
  background: none;
  color: var(--fg-dim);
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
  transition: color 80ms, border-color 80ms, background 80ms;
}
.track-list__remove:hover:not(:disabled) {
  border-color: var(--border);
  background: var(--panel);
  color: var(--ghost-bad);
}
.track-list__remove:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* ---------- mobile ---------- */
/* Below this width neither panel can afford a column: the sidebar becomes a
   left slide-over and the inspector a bottom sheet, both over a full-bleed
   canvas. Camera control is touch-driven (see ui/canvas.rs `Gesture`). */
@media (max-width: 860px) {
  .app,
  .app--inspector-open {
    grid-template-columns: minmax(0, 1fr);
  }

  .viewport__menu { display: flex; }

  .sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    width: min(320px, 85vw);
    z-index: 40;
    border-right: 1px solid var(--border);
    box-shadow: var(--shadow);
    transform: translateX(-100%);
    transition: transform 180ms ease;
  }
  .app--sidebar-open .sidebar { transform: none; }

  .inspector {
    position: fixed;
    inset: auto 0 0 0;
    height: 45dvh;
    max-height: 85dvh;
    z-index: 45;
    border-left: none;
    border-top: 1px solid var(--border);
    border-radius: 14px 14px 0 0;
    box-shadow: 0 -4px 24px rgba(0,0,0,0.35);
    animation: sheet-in 180ms ease;
    transition: height 160ms ease;
  }
  .inspector--expanded { height: 85dvh; }
  /* While the grip is held the height is written inline every pointermove;
     transitioning it would make the sheet lag behind the finger. */
  .inspector--dragging { transition: none; }
  .inspector__grip { display: block; }

  /* Keep the cube clear of the sheet and give it a thumb-sized hit area. */
  .nav-cube { top: 16px; right: 16px; }

  /* Comfortable touch targets, and 16px inputs so iOS does not zoom on focus. */
  input,
  select { font-size: 16px; }
  .inspector__btn,
  .track-list__toggle,
  .export-btn { min-height: 44px; }
  .track-list { max-height: none; }
  .track-list__row { min-height: 44px; }
  .track-list__mode-btn { width: 32px; height: 32px; }
}

@keyframes sheet-in {
  from { transform: translateY(100%); }
  to { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .inspector { animation: none; }
  .sidebar { transition: none; }
}

/* ---------- cost estimate ---------- */
/* Board cost, under the carcass editor. The total reads first and largest;
   the per-material lines and the caveat are supporting detail. */
.cost {
  padding-bottom: 12px;
}
.cost__totals {
  padding-bottom: 6px;
}
.cost__total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}
/* What you actually pay leads; the area figure sits under it as context. */
.cost__total--lead .cost__total-value {
  font-size: 18px;
}
.cost__total-value--minor {
  font-size: 12px;
  font-weight: 500;
  color: var(--fg-dim);
}
.cost__total-label {
  font-size: 12px;
  color: var(--fg-dim);
}
.cost__total-value {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.cost__lines {
  list-style: none;
  margin: 0;
  padding: 0;
}
/* Name takes the slack, quantity and cost keep their own columns so the
   figures line up down the list however long the decor names get. */
.cost__line {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 11px;
  padding: 2px 0;
}
.cost__line-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cost__line-qty {
  flex-shrink: 0;
  color: var(--fg-dim);
}
.cost__line-cost {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}
.cost__caveat {
  margin: 8px 0 0;
  font-size: 10px;
  line-height: 1.4;
  color: var(--fg-dim);
  opacity: 0.8;
}
