:root {
  --bg: #0a0a0f;
  --surface: #14141c;
  --surface-2: #1a1a26;
  --surface-3: #20202c;
  --line: #252531;
  --line-2: #353548;
  --text: #e8e8f0;
  --text-dim: #9a9aa6;
  --text-mute: #6a6a78;
  --accent: #4a7fff;
  --accent-hi: #6a99ff;
  --accent-ink: #06060a;
  --coral: #ff6f61;         /* Option B action/brand accent — logo · CUT · active camera */
  --coral-hi: #ff8a7e;
  --coral-ink: #2a0d08;
  --danger: #ff5a6e;
  --ok: #5ad9a0;
  --warn: #ffb84a;
  --ruler-tick: #3a3a48;
  --ruler-tick-major: #555568;
  --topbar-h: 36px;
  --ruler-h: 46px;
  --tools-h: 36px;
  --status-h: 22px;
  --radius: 3px;
}

* { box-sizing: border-box; }
/* The hidden attribute must always win — class rules like .tool-btn /
   .tool-toggle set display and would otherwise override the UA's
   [hidden]{display:none}, leaving "hidden" buttons visible. */
[hidden] { display: none !important; }
html, body { margin: 0; padding: 0; height: 100%; overflow: hidden; }
body {
  font: 13px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  background: var(--bg);
  color: var(--text);
}

a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }
.muted { color: var(--text-dim); font-size: 12px; }
.grow { flex: 1; }

/* ---------- Topbar ---------- */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  height: var(--topbar-h); padding: 0 14px;
  background: var(--surface); border-bottom: 1px solid var(--line);
}
.brand a { font-weight: 700; font-size: 14px; letter-spacing: 0.02em; }
.brand-accent { color: var(--accent); }
.pill {
  margin-left: 10px; padding: 2px 7px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 999px; font-size: 10px; color: var(--text-mute);
  text-transform: uppercase; letter-spacing: 0.1em;
}
.tabs { display: flex; gap: 2px; }
.tabs a {
  padding: 4px 10px; color: var(--text-dim); font-size: 12px;
  border-radius: var(--radius);
}
.tabs a:hover { color: var(--text); }
body[data-tab="viewer"]  .tabs a[data-tab="viewer"],
body[data-tab="library"] .tabs a[data-tab="library"],
body[data-tab="about"]   .tabs a[data-tab="about"] {
  color: var(--text); background: var(--surface-2);
}

/* ---------- Workspace shell ---------- */
.workspace { display: none; height: calc(100vh - var(--topbar-h)); flex-direction: column; min-height: 0; position: relative; /* anchors the floating mast cluster */ }
body[data-tab="viewer"] .workspace { display: flex; }

.page { display: none; padding: 24px; max-width: 900px; margin: 0 auto; overflow: auto; height: calc(100vh - var(--topbar-h)); }
body[data-tab="library"] .page[data-tab="library"],
body[data-tab="about"]   .page[data-tab="about"] { display: block; }

/* ---------- Index ruler bar ---------- */
.ruler-bar {
  display: flex; align-items: stretch;
  /* Locked to a FIXED pixel height regardless of viewport — fullscreen only
     reveals more teeth at the constant 16px pitch, it never scales the bar or
     its glyphs (1.2 follow-up). flex:none stops the column-flex parent from
     ever stretching it. */
  flex: 0 0 var(--ruler-h);
  height: var(--ruler-h); min-height: var(--ruler-h); max-height: var(--ruler-h);
  background: var(--surface); border-bottom: 1px solid var(--line);
  position: relative;
}
.gear-badge {
  width: 46px;
  background: var(--surface-2);
  border: 0; border-right: 1px solid var(--line);
  color: var(--text); font-weight: 700; font-size: 16px;
  display: flex; align-items: center; justify-content: center;
}
.gear-badge:hover { background: var(--surface-3); color: var(--accent); }

/* Mast Controls — live editor inputs in the ruler bar */
.mast-controls {
  display: flex; align-items: stretch;
  border-right: 1px solid var(--line);
  background: var(--surface-2);
}
.mast-field {
  display: flex; flex-direction: column; justify-content: center;
  padding: 4px 10px;
  border-right: 1px solid var(--line);
  min-width: 56px; gap: 1px;
}
.mast-field:last-child { border-right: 0; }
.mast-field > span {
  font-size: 9px; color: var(--text-mute);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.mast-field input[type="text"],
.mast-field input[type="number"] {
  background: transparent; color: var(--text);
  border: 0; padding: 1px 0;
  font: 600 13px ui-monospace, "Segoe UI Mono", monospace;
  font-variant-numeric: tabular-nums;
  width: 100%;
}
.mast-field input:focus { outline: none; color: var(--accent-hi); }
.mast-tier-field { min-width: 50px; }
.mast-tier-field input { width: 42px; text-transform: uppercase; }
/* Angle + Depth both render as a label + horizontal slider + number entry.
   Horizontal (not the earlier vertical experiment): vertical range inputs
   invert on fast drags and bleed hit-areas across neighbours. flex-grow lets
   the two share the strip's spare width so the travel is long. */
.mast-slider-field {
  flex: 1 1 210px; flex-direction: row; align-items: center; gap: 8px;
  min-width: 200px; padding: 6px 12px;
}
.mast-slider-field > span:first-child {
  font-size: 9px; color: var(--text-mute);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.mast-slider-field input[type="range"] {
  flex: 1; min-width: 90px; accent-color: var(--coral); margin: 0;
  cursor: ew-resize;
}
.mast-slider-num, .mast-depth-num {
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1px 4px;
  font: 600 12px ui-monospace, "Segoe UI Mono", monospace;
  font-variant-numeric: tabular-nums;
  width: 56px; text-align: right;
}
.mast-slider-num:focus, .mast-depth-num:focus { outline: none; border-color: var(--accent); }

/* Mast action buttons (side / fine / jump / +meet / reset) */
.mast-actions {
  display: flex; align-items: center; gap: 3px;
  padding: 0 6px; border-right: 1px solid var(--line);
}
.mast-btn {
  background: var(--surface-3); color: var(--text-dim);
  border: 1px solid var(--line); border-radius: var(--radius);
  font: 600 11px ui-monospace, "Segoe UI Mono", monospace;
  padding: 3px 6px; cursor: pointer; white-space: nowrap;
}
.mast-btn:hover { color: var(--accent); border-color: var(--accent); }
.mast-btn.active, .mast-btn.locked {
  background: var(--accent); color: var(--accent-ink); border-color: var(--accent);
}
.mast-btn.pav { color: var(--warn); border-color: var(--warn); }
.mast-btn.danger { color: var(--danger); }
.mast-btn.danger:hover { border-color: var(--danger); color: var(--danger); }
.mast-btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* Zone selector: CROWN | GIRDLE | PAV segments (mast_ui.js). The lit segment
   tracks the current angle; click jumps; wheel steps through the anatomy. */
.mc-zone { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.mc-zone-btn {
  background: var(--surface-3); color: var(--text-dim);
  border: none; border-right: 1px solid var(--line);
  font: 600 10px ui-monospace, "Segoe UI Mono", monospace;
  padding: 3px 5px; cursor: pointer; white-space: nowrap;
}
.mc-zone-btn:last-child { border-right: none; }
.mc-zone-btn:hover { color: var(--accent); }
.mc-zone-btn.active { background: var(--accent); color: var(--accent-ink); }
.mc-zone.pav .mc-zone-btn.active { background: var(--warn); }
.mc-zone-btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* Sym / Mir selectors in ruler-bar */
.ruler-stat.sym-stat, .ruler-stat.mir-stat { min-width: 56px; }
.stat-select {
  background: transparent; color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1px 4px; font: 600 12px inherit;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.stat-select:focus { outline: none; border-color: var(--accent); }
.stat-select option { background: var(--surface-2); color: var(--text); }
/* Windowed index ruler — self-sizing container, ticks positioned in px by JS,
   the scale scrolls under a fixed centre cursor. */
.ruler-wrap {
  flex: 1; position: relative; overflow: hidden;
  background: var(--surface);
  cursor: ew-resize; user-select: none; touch-action: none;
}
.ruler-track { position: absolute; inset: 0; }
.ruler-tick {
  position: absolute; top: 0; bottom: 0; width: 0;
  transform: translateX(-50%);
}
.ruler-tick .tick-line {
  position: absolute; left: 0; bottom: 5px; width: 1px; height: 6px;
  background: var(--ruler-tick, var(--line));
}
.ruler-tick.major .tick-line {
  height: 11px; background: var(--ruler-tick-major, var(--text-mute));
}
/* Small, fixed, thin labels — compact instrument scale, never scales with the
   viewport (L4). RULER_PITCH stays a constant 16px in app.js. */
.ruler-tick .tick-num {
  position: absolute; top: 5px; left: 0; transform: translateX(-50%);
  font: 500 10px ui-monospace, "Segoe UI Mono", monospace;
  color: var(--text-dim); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.ruler-tick.current .tick-num { visibility: hidden; }   /* cursor flag shows it */
.ruler-cursor {
  position: absolute; left: 50%; top: 0; bottom: 0; width: 0;
  transform: translateX(-50%); pointer-events: none;
  border-left: 2px solid var(--danger);
}
.cursor-flag {
  position: absolute; top: 3px; left: 1px; transform: translateX(-50%);
  background: var(--danger); color: #fff;
  font: 700 10px ui-monospace, "Segoe UI Mono", monospace; font-variant-numeric: tabular-nums;
  line-height: 1.2; padding: 0 4px; border-radius: 2px; white-space: nowrap; pointer-events: none;
}

/* Mode toggle (Symmetrical / Arbitrary) */
.mode-btn {
  width: 46px; background: var(--surface-2);
  border: 0; border-right: 1px solid var(--line);
  color: var(--text-mute); font-weight: 700; font-size: 11px; letter-spacing: 0.1em;
  cursor: pointer;
}
.mode-btn:hover { color: var(--accent); background: var(--surface-3); }
.mode-btn.arb { color: var(--accent-ink); background: var(--accent); }

/* Arbitrary-mode index list field (overlays the ruler track) */
.arb-field {
  position: absolute; left: 10px; right: 10px; top: 6px; bottom: 6px;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 2px 8px; font: 600 13px ui-monospace, "Segoe UI Mono", monospace;
  font-variant-numeric: tabular-nums;
}
.arb-field:focus { outline: none; border-color: var(--accent); }

/* Numeric Mir field + invalid (red) state for Sym/Mir */
.stat-num {
  width: 44px; background: transparent; color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1px 4px; font: 600 12px ui-monospace, "Segoe UI Mono", monospace;
  font-variant-numeric: tabular-nums; text-align: center;
}
.stat-num:focus { outline: none; border-color: var(--accent); }
.stat-num::-webkit-outer-spin-button, .stat-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.stat-select.bad, .stat-num.bad { border-color: var(--danger); color: var(--danger); }

/* Change-Index-Gear popup */
.gear-popup {
  position: absolute; z-index: 50; top: var(--ruler-h); left: 4px;
  width: 232px; padding: 8px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0,0,0,0.45);
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 5px;
}
.gear-popup .gp-title {
  grid-column: 1 / -1; font-size: 10px; color: var(--text-mute);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.gear-popup button {
  background: var(--surface-3); border: 1px solid var(--line); border-radius: 3px;
  color: var(--text); font: 600 12px ui-monospace, monospace; padding: 5px 0; cursor: pointer;
}
.gear-popup button:hover { border-color: var(--accent); color: var(--accent); }
.gear-popup button.red { color: var(--danger); }
.gear-popup button.current { outline: 1px solid var(--accent); }
.gear-popup .gp-custom { grid-column: 1 / -1; display: flex; gap: 5px; margin-top: 2px; }
.gear-popup .gp-custom input {
  flex: 1; background: var(--surface); border: 1px solid var(--line); color: var(--text);
  border-radius: 3px; padding: 3px 6px; font: 600 12px ui-monospace, monospace;
}
.gear-popup .gp-custom input:focus { outline: none; border-color: var(--accent); }
.gear-popup .gp-orient {
  grid-column: 1 / -1; display: flex; flex-direction: column; gap: 6px;
  margin-top: 4px; padding-top: 7px; border-top: 1px solid var(--line);
}
.gear-popup .gp-check {
  display: flex; align-items: center; gap: 6px; cursor: pointer;
  font: 600 12px ui-monospace, monospace; color: var(--text);
}
.gear-popup .gp-check input { accent-color: var(--accent); margin: 0; }
.gear-popup .gp-idrow { display: flex; align-items: center; gap: 6px; }
.gear-popup .gp-idrow span { font-size: 11px; color: var(--text-mute); }
.gear-popup .gp-idrow select, .gear-popup .gp-other {
  background: var(--surface); border: 1px solid var(--line); color: var(--text);
  border-radius: 3px; padding: 2px 6px; font: 600 12px ui-monospace, monospace;
}
.gear-popup .gp-idrow select:focus, .gear-popup .gp-other:focus { outline: none; border-color: var(--accent); }
.gear-popup .gp-other { width: 54px; }

.ruler-stat {
  border-left: 1px solid var(--line);
  padding: 0 14px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-width: 64px;
}
.ruler-stat .stat-label { font-size: 10px; color: var(--text-mute); text-transform: uppercase; letter-spacing: 0.08em; }
.ruler-stat .stat-val { font-size: 14px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.cut-btn {
  width: 72px;
  background: var(--surface-2); color: var(--text-mute);
  border: 0; border-left: 1px solid var(--line);
  font-weight: 700; font-size: 13px; letter-spacing: 0.14em;
  transition: background 120ms, color 120ms, box-shadow 120ms;
}
.cut-btn:not(:disabled) {
  background: var(--accent); color: var(--accent-ink);
  box-shadow: inset 0 0 0 1px var(--accent-hi);
}
.cut-btn:not(:disabled):hover {
  background: var(--accent-hi);
  box-shadow: inset 0 0 0 1px #fff, 0 0 18px rgba(106, 153, 255, 0.35);
}
.cut-btn:disabled { cursor: not-allowed; }

/* Zone 5: docked mast strip — all cutting controls in one band above the
   status bar. Reuses the existing .mast-controls / .mast-field / .ruler-stat /
   .cut-btn styling; just lays them out in a fixed bottom band. */
/* MOVABLE mast cluster (owner 2026-07-08: "drag and drop anywhere on the
   screen is way better"). A floating card the operator drags by the ⠿ grip;
   position persists in localStorage (mast_ui.js), clamped to the workspace.
   Defaults to the lower-right, above the status bar. */
.mast-strip {
  position: absolute; right: 12px; bottom: 36px; z-index: 60;
  display: flex; align-items: stretch; gap: 6px;
  background: var(--surface-2);
  border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5);
  padding: 6px 10px 6px 6px;
  overflow: visible;                 /* data-tip bubbles pop above the card */
}
.mc-grip {
  flex: 0 0 auto; align-self: stretch;
  display: flex; align-items: center;
  padding: 0 3px; cursor: grab; user-select: none; touch-action: none;
  color: var(--text-mute); font-size: 14px; letter-spacing: -1px;
  border-right: 1px solid var(--line);
}
.mc-grip:active { cursor: grabbing; color: var(--accent-hi); }
/* Size + dock mini-buttons next to the grip (owner 2026-07-25). */
.mc-sidebtns {
  flex: 0 0 auto; display: flex; flex-direction: column; gap: 3px;
  justify-content: center; padding: 0 4px 0 2px;
  border-right: 1px solid var(--line);
}
.mc-mini {
  width: 20px; height: 19px; line-height: 1; padding: 0;
  background: var(--surface-3); color: var(--text-dim);
  border: 1px solid var(--line); border-radius: 3px;
  font: 600 10px ui-monospace, "Segoe UI Mono", monospace; cursor: pointer;
}
.mc-mini:hover { color: var(--accent); border-color: var(--accent); }
.mc-mini.active { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
/* Cluster size cycle — zoom scales the whole card incl. hit targets. */
.mast-strip[data-size="s"] { zoom: 0.82; }
.mast-strip[data-size="l"] { zoom: 1.18; }
.mast-strip .mast-controls { display: flex; flex-direction: column; gap: 4px; }
.mc-main { display: flex; align-items: stretch; gap: 12px; }
.mc-status {
  flex: 0 0 150px; align-self: center; width: 150px;
  font-size: 11px; line-height: 1.3; color: var(--text-dim);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}
.mast-strip .mc-cmd { width: 100%; box-sizing: border-box; background: var(--surface); }
.mc-col { display: flex; flex-direction: column; justify-content: space-between; gap: 3px; }
.mc-row { display: flex; align-items: center; gap: 4px; }
.mc-jogs { width: 300px; }
.mc-jog { display: flex; align-items: center; gap: 4px; }
.mc-axis { width: 13px; text-align: center; color: var(--text-dim); font-size: 12px; flex: 0 0 auto; }
.mc-jog-slider { flex: 1 1 auto; min-width: 0; height: 18px; accent-color: var(--coral); }
/* Wide enough for the worst case "-179.95" (sign + 3 digits + 2 decimals) —
   at 60px a negative angle like -41.36 clipped its last digit and rendered as
   a half-visible glyph (owner's "glitch in the degree numbers", 2026-07-25). */
.mc-jog .mast-slider-num { width: 72px; flex: 0 0 auto; }
.mc-step {
  flex: 0 0 auto; width: 22px; height: 20px; line-height: 1;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: 3px;
  font-size: 12px; cursor: pointer;
}
.mc-step:hover { border-color: var(--accent); color: var(--accent-hi); }
.mast-strip .cut-btn { width: 72px; align-self: stretch; }
#jogRange.active { border-color: var(--accent); color: var(--accent-hi); }

/* Cluster tooltips: right-anchored data-tip bubbles that open UPWARD and grow
   LEFTWARD, so near the screen's right edge they flip inward instead of
   overflowing off-screen (owner 2026-07-08 — native title tooltips ran off
   the right edge). ::after doesn't render on replaced elements, so data-tip
   lives on labels/buttons/wrappers, never bare inputs. */
.mast-controls [data-tip] { position: relative; }
.mast-controls [data-tip]:hover::after {
  content: attr(data-tip);
  position: absolute; right: 0; bottom: calc(100% + 7px);
  width: max-content; max-width: 260px;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: 4px;
  padding: 5px 8px; font-size: 11px; line-height: 1.35; font-weight: 400;
  white-space: normal; text-transform: none; letter-spacing: normal;
  z-index: 120; pointer-events: none;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
}

/* Strip the spinner arrows on the mast number inputs — they fight the layout */
.mast-field input[type="number"]::-webkit-outer-spin-button,
.mast-field input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none; margin: 0;
}
.mast-field input[type="number"] { -moz-appearance: textfield; }

/* ---------- Toolstrip ---------- */
.toolstrip {
  display: flex; align-items: stretch; gap: 0;
  flex-wrap: wrap;                        /* narrow window: groups wrap to a second
                                             row instead of pushing OUTPUT off-screen
                                             (function audit 2026-07-07 note 3) */
  padding: 0 8px; min-height: 52px;
  background: var(--surface); border-bottom: 1px solid var(--line);
  overflow-x: auto; overflow-y: hidden;   /* scroll if too wide, never clip (L3) */
}
/* Toolbar groups keep their size — no shrinking/clipping of the Iso/Crown/… tabs. */
.toolstrip > * { flex-shrink: 0; }

/* Zone 2 ribbon groups: a row of controls with an 8px uppercase label beneath,
   separated by thin vertical dividers (AutoCAD-ribbon pattern). */
.tgroup { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; padding: 5px 9px; }
.tgroup-row { display: flex; align-items: center; gap: 5px; }
.tgroup-label { font-size: 8px; line-height: 1; letter-spacing: .1em; text-transform: uppercase; color: var(--text-mute); }
.tgroup-div { width: 1px; align-self: stretch; background: #2a2a3e; margin: 7px 4px; }
/* Contextual tier hint sits between the left groups and the right Panels group. */
.toolstrip .editor-strip-hint {
  margin-left: auto; align-self: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 240px;
  font-size: 11px; color: var(--text-dim); padding: 0 8px;
}
.tool-btn {
  padding: 5px 12px; background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  font-size: 12px;
  display: inline-flex; align-items: center; gap: 6px;
}
.tool-btn:hover:not(:disabled) { background: var(--surface-3); border-color: var(--line-2); }
.tool-btn:disabled { color: var(--text-mute); cursor: not-allowed; opacity: 0.55; }
.tool-btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
.tool-btn.primary:hover { background: var(--accent-hi); border-color: var(--accent-hi); }
.tool-btn.ghost { background: transparent; }

.tool-sep { width: 1px; height: 20px; background: var(--line); margin: 0 2px; }
.tool-sep.grow { background: transparent; flex: 1; }

.view-buttons { display: inline-flex; }
.view-buttons button {
  padding: 4px 10px; background: transparent; color: var(--text-dim);
  border: 1px solid var(--line); border-right: 0; font-size: 12px;
}
.view-buttons button:first-child { border-radius: var(--radius) 0 0 var(--radius); }
.view-buttons button:last-child  { border-radius: 0 var(--radius) var(--radius) 0; border-right: 1px solid var(--line); }
.view-buttons button:hover { color: var(--text); background: var(--surface-2); }
.view-buttons button.active {
  color: var(--text); background: var(--surface-2);
  border-color: var(--accent); position: relative; z-index: 1;
}

.tool-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-dim); cursor: pointer; }
.tool-toggle input { margin: 0; accent-color: var(--accent); }

/* ---------- Modal dialog ---------- */
.modal-overlay {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(8, 8, 14, 0.65);
  display: flex; align-items: center; justify-content: center;
}
.modal {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 6px; min-width: 420px; max-width: 92vw; max-height: 88vh;
  display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.55);
}
.modal header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 14px; background: var(--surface-2);
  border-bottom: 1px solid var(--line);
}
.modal header h3 { margin: 0; font-size: 14px; }
.modal-close {
  background: transparent; color: var(--text-dim); border: 0;
  font-size: 20px; line-height: 1; cursor: pointer;
  padding: 2px 8px; border-radius: var(--radius);
}
.modal-close:hover { background: var(--surface-3); color: var(--text); }
.modal-body { padding: 14px 16px 18px; overflow: auto; }

.yc-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
  margin-bottom: 14px;
}
.yc-grid label {
  display: flex; flex-direction: column; gap: 4px;
  font-size: 11px; color: var(--text-mute); text-transform: uppercase;
  letter-spacing: 0.06em;
}
.yc-grid input, .yc-grid select {
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 6px 10px; font: inherit; font-size: 13px;
}
.yc-grid input:focus, .yc-grid select:focus { outline: none; border-color: var(--accent); }
.yc-grid small { font-size: 10px; text-transform: none; letter-spacing: 0; color: var(--text-mute); }

.yc-results { width: 100%; border-collapse: collapse; font-size: 13px; }
.yc-results th {
  text-align: left; font-weight: 500; color: var(--text-dim);
  padding: 6px 10px; border-bottom: 1px solid var(--line);
  text-transform: uppercase; font-size: 10px; letter-spacing: 0.06em;
}
.yc-results td {
  padding: 6px 10px; border-bottom: 1px solid var(--line);
  text-align: right; font-variant-numeric: tabular-nums; color: var(--text);
}
.yc-results .yc-emphasis th, .yc-results .yc-emphasis td {
  color: var(--accent); font-weight: 700; font-size: 14px;
  border-bottom: 0;
}

/* ---------- 2D side profile (SVG) ---------- */
.topview-svg .profile-silhouette {
  fill: var(--accent);
  fill-opacity: 0.18;
  stroke: var(--accent);
  stroke-width: 0.012;
}
.topview-svg .girdle-line {
  stroke: var(--text-mute);
  stroke-width: 0.005;
  stroke-dasharray: 0.025 0.02;
  opacity: 0.5;
}
.topview-svg .center-line {
  stroke: var(--text-mute);
  stroke-width: 0.003;
  opacity: 0.35;
}
.topview-svg .girdle-thickness-line {
  stroke: var(--warn);
  stroke-width: 0.006;
  stroke-dasharray: 0.015 0.01;
  opacity: 0.75;
}
.topview-svg .girdle-thickness-bracket {
  fill: none;
  stroke: var(--warn);
  stroke-width: 0.005;
  opacity: 0.85;
}
.topview-svg .girdle-thickness-label {
  fill: var(--warn);
  font-size: 0.07px;
  font-family: ui-monospace, "Segoe UI Mono", monospace;
}
/* Cut-sheet-style per-tier facet labels (T, C1.., P1..) — white-halo text so
   they read on any tier color, in both top views and the profile. */
.topview-svg .facet-label {
  fill: var(--text);
  stroke: var(--bg);
  stroke-width: 0.014;
  paint-order: stroke;
  font-weight: 600;
  pointer-events: none;
}

/* ---------- 2D top view (SVG) ---------- */
.topview-svg .girdle-ring {
  fill: none;
  stroke: var(--text-mute);
  stroke-width: 0.005;
  stroke-dasharray: 0.02 0.02;
  opacity: 0.5;
}
.topview-svg .index-ring .tick-minor {
  stroke: var(--text-mute);
  stroke-width: 0.004;
  opacity: 0.5;
}
.topview-svg .index-ring .tick-major {
  stroke: var(--text-dim);
  stroke-width: 0.006;
}
.topview-svg .index-ring .tick-label {
  font-size: 0.06px;
  font-family: ui-monospace, "Segoe UI Mono", monospace;
  fill: var(--text-dim);
}

/* ---------- Toast notifications ---------- */
.toast-layer {
  position: fixed; right: 20px; top: 56px; z-index: 200;
  display: flex; flex-direction: column; gap: 8px;
  pointer-events: none;
}
.toast {
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-left: 3px solid var(--accent);
  border-radius: 4px; padding: 8px 14px; font-size: 12px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.4);
  opacity: 0; transform: translateX(20px);
  transition: opacity 180ms, transform 180ms;
  min-width: 200px; max-width: 320px;
}
.toast.show { opacity: 1; transform: translateX(0); }
.toast.toast-ok { border-left-color: var(--ok); }
.toast.toast-error { border-left-color: var(--danger); }

/* ---------- In-app CAD dialogs (modal.js) ---------- */
.modal-overlay {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(4, 4, 8, 0.55);
  display: flex; align-items: center; justify-content: center;
}
.modal-panel {
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: 0 16px 48px rgba(0,0,0,0.55);
  padding: 14px 16px; min-width: 300px; max-width: 420px;
}
.modal-title {
  font-size: 11px; font-weight: 600; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--text-dim); margin-bottom: 10px;
}
.modal-label { display: block; font-size: 12px; margin-bottom: 6px; }
.modal-message { font-size: 13px; line-height: 1.5; margin-bottom: 4px; }
.modal-input {
  width: 100%;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line-2); border-radius: var(--radius);
  padding: 6px 8px; font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.modal-input:focus { outline: none; border-color: var(--accent); }
.modal-hint { font-size: 11px; color: var(--text-mute); margin-top: 6px; }
.modal-actions {
  display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px;
}
.modal-btn {
  background: transparent; color: var(--text);
  border: 1px solid var(--line-2); border-radius: var(--radius);
  padding: 5px 14px; font-size: 12px; cursor: pointer;
}
.modal-btn:hover { border-color: var(--accent); }
.modal-btn-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.modal-btn-primary:hover { background: var(--accent-hi); }
.modal-btn-primary:disabled { opacity: 0.45; cursor: default; }
.modal-btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }

/* ---------- Color match from photo (color_match.js) ---------- */
.color-match-panel { max-width: 560px; }
.cm-canvas {
  display: block; max-width: 100%; margin-top: 8px;
  border: 1px solid var(--line-2); border-radius: var(--radius);
  cursor: crosshair; background: #000;
}
.cm-readout {
  display: flex; align-items: center; gap: 8px; margin-top: 10px;
  font-size: 12px; font-variant-numeric: tabular-nums; color: var(--text-dim);
}
.cm-swatch {
  width: 20px; height: 20px; border-radius: 4px;
  border: 1px solid var(--line-2); background: transparent;
}

/* ---------- Notes textarea in the rail ---------- */
.rail-notes {
  width: 100%; resize: vertical;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 6px 8px; font: 12px inherit;
  min-height: 60px; max-height: 200px;
}
.rail-notes:focus { outline: none; border-color: var(--accent); }

/* ---------- Editor strip ---------- */
.editor-strip {
  display: flex; align-items: center; gap: 6px; padding: 4px 12px;
  height: 30px; background: var(--surface-2);
  border-bottom: 1px solid var(--line);
  font-size: 12px;
}
.editor-strip-label {
  color: var(--text-mute);
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em;
  margin-right: 4px;
}
.editor-strip-hint {
  margin-left: auto; color: var(--text-mute);
  font-size: 11px; font-style: italic;
  font-variant-numeric: tabular-nums;
}

/* ---------- Cutting Assistant strip ---------- */
/* One grouped cluster, right-aligned over the rail column below it — these
   are all one control (step through the cut sequence), so they read as a
   unit instead of splitting across the far ends of the strip. */
.cutting-strip {
  display: flex; align-items: center; justify-content: flex-end; gap: 4px; padding: 4px 12px;
  height: 30px; background: var(--surface-2);
  border-bottom: 1px solid var(--line);
  font-size: 12px;
}
.cut-step {
  padding: 3px 9px; background: transparent; color: var(--text-dim);
  border: 1px solid var(--line); border-radius: var(--radius); font-size: 11px;
}
.cut-step:hover { color: var(--text); background: var(--surface-3); }
.cut-step.danger { color: var(--text-mute); border-color: var(--line); }
.cut-state {
  margin: 0 12px; color: var(--text); font-variant-numeric: tabular-nums;
  font-size: 12px;
}

.tool-select { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-dim); }
.tool-select select {
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 3px 8px; font: inherit; font-size: 12px;
  min-width: 100px;
}
.tool-select select:hover { border-color: var(--line-2); }
.tool-select select:focus { outline: none; border-color: var(--accent); }

/* Drag-and-drop overlay over the 3D viewport (Design pane hosts it now) */
.design-pane .pane-body { position: relative; }
.dropzone-overlay {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(74, 127, 255, 0.12);
  border: 2px dashed var(--accent);
  color: var(--accent); font-size: 16px; font-weight: 600;
  letter-spacing: 0.04em;
  pointer-events: none; opacity: 0;
  transition: opacity 0.12s ease;
  z-index: 5;
}
.dropzone-overlay.visible { opacity: 1; pointer-events: auto; }

/* Loading spinner over viewport */
.viewport-spinner {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(10, 10, 15, 0.55);
  z-index: 4; pointer-events: none;
}
.spinner-dot {
  width: 36px; height: 36px;
  border: 3px solid rgba(74, 127, 255, 0.25);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- CAD grid ---------- */
.cad-grid {
  flex: 1; display: grid;
  grid-template-columns: 320px 1fr 260px;
  /* minmax(0,1fr): a single row that fills the grid height AND is allowed to be
     shorter than its content. Plain `1fr` means `minmax(auto,1fr)`, whose
     min-content floor let the tall right rail inflate the row past the viewport
     — pushing the Render pane off-screen and stopping the rail from scrolling
     (L1). With a 0 minimum the row is bounded and the items scroll internally. */
  grid-template-rows: minmax(0, 1fr);
  min-height: 0;
}
/* Collapsible side rails -> full-page center work area. */
body.hide-instr .cad-grid { grid-template-columns: 0 1fr 260px; }
body.hide-rail  .cad-grid { grid-template-columns: 320px 1fr 0; }
body.hide-instr.hide-rail .cad-grid { grid-template-columns: 0 1fr 0; }
body.hide-instr .instr-panel { display: none; }
body.hide-rail  .rail { display: none; }

/* Floatable Properties rail (owner 2026-07-16): pin ⇱ pops the rail out of
   its grid column into a draggable card (the column collapses, the panes
   grow); ⇲ docks it back home. Position/state persist (app.js). Props ◨
   still hides it in either mode. */
.rail-float-head {
  display: flex; align-items: center; gap: 6px;
  margin: -8px -10px 0; padding: 4px 8px;
  position: sticky; top: -8px; z-index: 2;
  background: var(--surface-2); border-bottom: 1px solid var(--line);
  user-select: none; touch-action: none;
}
.rfh-grip { color: var(--text-mute); font-size: 13px; letter-spacing: -1px; }
.rfh-title { font: 600 11px ui-monospace, "Segoe UI Mono", monospace; color: var(--text-dim); }
.rfh-pin {
  margin-left: auto; background: none; border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--text-dim);
  cursor: pointer; font-size: 12px; line-height: 1; padding: 2px 6px;
}
.rfh-pin:hover { color: var(--accent); border-color: var(--accent); }
body.rail-float .rail-float-head { cursor: grab; }
body.rail-float .rail-float-head:active { cursor: grabbing; }
body.rail-float .rail-render {
  position: absolute; top: 48px; right: 16px; z-index: 54;
  width: 260px; max-height: calc(100% - 90px);
  border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5);
}
body.rail-float .cad-grid { grid-template-columns: 320px 1fr 0; }
body.hide-instr.rail-float .cad-grid { grid-template-columns: 0 1fr 0; }
.toolstrip .tool-btn.active,
.pane-foot .tool-btn.active { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }

/* Instructions panel */
.panel { display: flex; flex-direction: column; background: var(--surface); border-right: 1px solid var(--line); min-width: 0; min-height: 0; }
.panel-head, .pane-head {
  padding: 6px 12px; font-size: 12px;
  background: var(--surface-2); border-bottom: 1px solid var(--line);
  color: var(--text); font-weight: 600;
  display: flex; align-items: center; justify-content: space-between;
}
.pane-max {
  background: transparent; color: var(--text-mute);
  border: 0; padding: 2px 6px; font-size: 14px; line-height: 1;
  cursor: pointer; border-radius: var(--radius);
}
.pane-max:hover { background: var(--surface-3); color: var(--text); }
/* When the body is in "maximize design" mode, hide the render pane and let
   the design pane fill the column. Vice versa for "maximize render". */
body[data-pane-max="design"] .render-pane { display: none; }
body[data-pane-max="render"] .design-pane { display: none; }
.panel-body, .pane-body { flex: 1; overflow: auto; min-height: 0; }
.placeholder { color: var(--text-mute); font-size: 12px; padding: 12px; margin: 0; }

/* Instructions list */
.instr-section {
  padding: 4px 0; border-bottom: 1px solid var(--line);
}
.instr-section-head {
  padding: 4px 12px; font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.08em;
  background: var(--surface-2);
}
.instr-section-head.pavilion { color: var(--accent); border-left: 3px solid var(--accent); }
.instr-section-head.girdle   { color: var(--warn);   border-left: 3px solid var(--warn); }
.instr-section-head.crown    { color: var(--ok);     border-left: 3px solid var(--ok); }
.instr-row {
  display: grid; grid-template-columns: 64px 60px 1fr;
  padding: 3px 12px;
  font-size: 12px; cursor: pointer;
  font-variant-numeric: tabular-nums;
  border-left: 3px solid transparent;
  gap: 4px;
}
.instr-row:hover { background: var(--surface-2); }
.instr-row.selected { background: var(--surface-3); border-left-color: var(--accent); }
.instr-row .col-tier {
  color: var(--text); font-weight: 600;
  /* Preform (unmodified tier) and any operator-renamed tier (up to 20 chars,
     see the Instructions ▸ Rename field) can be wider than this column —
     without this, unclipped overflow visually overlapped the angle column
     ("grid overlaps" bug report, present at every viewport size since the
     column itself is fixed-width, not a responsive breakpoint issue). */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.instr-row .col-angle { color: var(--text-dim); }
.instr-row .col-instr { color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---------- Center column: 2D over 3D ---------- */
/* Center work area: Design LEFT | divider | Render RIGHT (side-by-side). */
.center-col { display: flex; flex-direction: row; min-width: 0; min-height: 0; background: var(--bg); }
.pane { display: flex; flex-direction: column; flex: 1 1 0; min-height: 0; min-width: 0; border-right: 1px solid var(--line); }
.pane:last-child { border-right: 0; }
.design-pane { flex: var(--split, 1) 1 0; }   /* draggable: --split = design grow ratio */
.pane-divider { flex: 0 0 6px; background: var(--line); cursor: ew-resize; align-self: stretch; }
.pane-divider:hover, .pane-divider.dragging { background: var(--accent); }
/* When one pane is maximized the other is hidden — drop the divider too. */
body[data-pane-max] .pane-divider { display: none; }
.pane-body { background: var(--bg); position: relative; }
.pane-foot {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px; height: 32px;
  background: var(--surface); border-top: 1px solid var(--line);
}

/* 2D top view */
.topview-svg { width: 100%; height: 100%; display: block; background: #08080d; }
.topview-svg polygon { stroke: rgba(0,0,0,0.55); stroke-width: 0.005; }
.topview-svg .girdle-ring { fill: none; stroke: var(--line-2); stroke-width: 0.008; stroke-dasharray: 0.04 0.02; }

/* 3D viewport (Design) + output monitor (Render) */
.design-pane .pane-body, .render-pane .pane-body { min-height: 200px; overflow: hidden; }
/* Canvas fills the pane and is taken OUT of flow, so the pane's height is purely
   flex-driven (never sized by the canvas) and clientHeight is always the true
   visible height the renderer should match. */
/* width/height 100% are LOAD-BEARING, not decoration: a canvas is a replaced
   element, so inset:0 alone does NOT stretch it — it keeps its width/height
   ATTRIBUTE size anchored top-left. If the buffer size ever lags the pane
   (missed observer tick), 100% keeps the display fitted (soft scale) instead
   of overflowing the pane as an offset image (iPad bug 2026-07-23). */
.design-pane .pane-body > canvas,
.render-pane .pane-body > canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* These rules' specificity beats the native [hidden] display:none — without
   this re-assert, a "hidden" canvas stays display:block, sits on top of the
   live canvas, and silently swallows every mouse event (2026-07-16 bug). */
.design-pane .pane-body > canvas[hidden],
.render-pane .pane-body > canvas[hidden] { display: none; }
/* In-pane raytrace sink (float window retired 2026-07-25): square trace
   buffer displayed contain-fit over the beauty canvas. */
.render-pane .raytrace-canvas {
  z-index: 2;
  object-fit: contain;
  background: #0a0a0f;
  /* Smooth upscale now (was image-rendering:pixelated): the camera-pose
     trace is a photographic render at 440px, not the old coarse 2D grid. */
  /* Orbit THROUGH the trace: drags fall to the beauty canvas beneath, whose
     controls own the monitor camera — the engine shows the live PBR while
     aiming and re-traces on settle. */
  pointer-events: none;
}
/* Render pane on/off (owner 2026-07-25): OFF collapses the pane to a slim
   restore strip and Design takes the full center width. The restore strip is
   the pane's only visible child so it always stays re-openable. */
.render-restore { display: none; }
body[data-render-off] .render-pane .pane-head,
body[data-render-off] .render-pane .pane-body,
body[data-render-off] .render-pane .mast-dock-slot,
body[data-render-off] .render-pane .pane-foot { display: none; }
body[data-render-off] .render-pane { flex: 0 0 28px; }
body[data-render-off] .pane-divider { display: none; }
body[data-render-off] .render-restore {
  display: flex; align-items: center; justify-content: center;
  flex: 1; writing-mode: vertical-rl;
  background: var(--surface); color: var(--text-dim);
  border: 0; letter-spacing: 0.08em; font-size: 11px;
}
body[data-render-off] .render-restore:hover { color: var(--accent); background: var(--surface-2); }
/* Cut-bar dock slot in the Render pane (owner 2026-07-25): the mast cluster
   parks here in flow, above the footer. */
.mast-dock-slot {
  flex: 0 0 auto; display: flex; justify-content: center;
  border-top: 1px solid var(--line); background: var(--surface);
  max-height: 45%; overflow: auto;
}
body[data-mast-dock] .mast-strip {
  position: static; margin: 4px auto; max-width: calc(100% - 8px);
  flex-wrap: wrap; box-shadow: none;
}
body[data-mast-dock] .mc-grip { display: none; }

/* ---------- Facet-edit popover (dbl-click a facet, owner 2026-07-25) ---------- */
.facet-pop {
  position: absolute; z-index: 90;
  min-width: 172px; max-width: 240px;
  display: flex; flex-direction: column; gap: 3px;
  background: var(--surface-2); border: 1px solid var(--line-2);
  border-radius: 6px; padding: 7px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}
.facet-pop .fp-title {
  font: 600 11px ui-monospace, "Segoe UI Mono", monospace;
  color: var(--text-dim); padding: 1px 3px 4px;
  border-bottom: 1px solid var(--line); margin-bottom: 2px;
}
.facet-pop .fp-btn {
  background: var(--surface-3); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  font-size: 12px; text-align: left; padding: 5px 8px; cursor: pointer;
}
.facet-pop .fp-btn:hover { border-color: var(--accent); color: var(--accent-hi); }
.facet-pop .fp-row { display: flex; gap: 3px; }
.facet-pop .fp-input {
  flex: 1; min-width: 0;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 4px 6px; font: 600 12px ui-monospace, "Segoe UI Mono", monospace;
}
.facet-pop .fp-input:focus { outline: none; border-color: var(--accent); }
.facet-pop .fp-apply { flex: 0 0 auto; }

/* ---------- Right rail ---------- */
.rail {
  background: var(--surface); border-left: 1px solid var(--line);
  display: flex; flex-direction: column; align-items: stretch;
  padding: 8px 10px 12px;
  gap: 8px;
  min-height: 0;        /* bound to the grid row so overflow-y actually scrolls (L1) */
  overflow-y: auto;
}
.rail-section-head {
  font-size: 10px; color: var(--text-mute);
  text-transform: uppercase; letter-spacing: 0.1em;
  padding: 10px 0 4px;
  border-bottom: 1px solid var(--line);
  font-weight: 700;
}
.rail-section-head:first-child { padding-top: 2px; }
.rail-toggle { display: flex; flex-direction: column; gap: 1px; }
.rail-tab {
  padding: 5px 0; border: 1px solid var(--line);
  background: var(--surface-2); color: var(--text-dim);
  font-size: 11px; font-weight: 600; letter-spacing: 0.04em;
  border-radius: var(--radius);
}
.rail-tab.active { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.rail-tab:hover:not(.active) { color: var(--text); }
.rail-field { display: flex; flex-direction: column; gap: 3px; padding: 2px 0; }
.rail-field label { font-size: 10px; color: var(--text-mute); text-transform: uppercase; letter-spacing: 0.06em; display: flex; justify-content: space-between; align-items: center; }
.rail-field label span { color: var(--text); font-size: 11px; text-transform: none; letter-spacing: 0; font-variant-numeric: tabular-nums; }
.rail-field input[type=range] { width: 100%; accent-color: var(--accent); height: 18px; }
.rail-field input[type=color] {
  width: 100%; height: 24px; padding: 1px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius);
  cursor: pointer;
}
.rail-field .checkbox-row { display: flex; align-items: center; gap: 6px; text-transform: none; letter-spacing: 0; font-size: 12px; color: var(--text-dim); }
.rail-field .checkbox-row input { accent-color: var(--accent); margin: 0; }
.rail-tieractions { display: flex; flex-direction: column; gap: 4px; }
.rail-tieractions .lib-name { font-size: 12px; color: var(--text); font-weight: 600; }
.rail-action {
  padding: 5px 8px; background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius); font-size: 11px; text-align: left;
}
.rail-action:hover { background: var(--surface-3); border-color: var(--line-2); }
.rail-field input,
.rail-field select {
  width: 100%; padding: 4px 6px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius);
  color: var(--text); font: inherit; font-size: 12px; text-align: center;
  font-variant-numeric: tabular-nums;
}
.rail-field select { text-align: left; cursor: pointer; }
.rail-field select:focus { outline: none; border-color: var(--accent); }
.rail-field input:disabled { color: var(--text-mute); }
.rail-slider { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; min-height: 80px; padding: 6px 0; }
.rail-slider label { font-size: 10px; color: var(--text-mute); text-transform: uppercase; letter-spacing: 0.08em; }
.rail-slider input {
  appearance: slider-vertical;
  width: 22px; flex: 1;
  background: transparent;
  accent-color: var(--accent);
}
.rail-row { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; }
.rail-btn {
  padding: 4px 0; background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  font-size: 11px;
}
.rail-btn:disabled { color: var(--text-mute); cursor: not-allowed; opacity: 0.55; }
.rail-btn.danger { background: transparent; color: var(--danger); border-color: var(--danger); font-weight: 700; letter-spacing: 0.08em; }
.rail-btn.danger:disabled { opacity: 0.45; }

/* ---------- Status bar ---------- */
.statusbar {
  display: flex; align-items: center; gap: 8px;
  padding: 0 12px; height: var(--status-h);
  background: var(--surface); border-top: 1px solid var(--line);
  font-size: 11px; color: var(--text-dim);
}
.status-msg.error { color: var(--danger); }
.status-msg.ok    { color: var(--ok); }
.cmd-line {
  width: 320px; background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 2px 8px; font: 11px ui-monospace, "Segoe UI Mono", monospace;
}
.cmd-line:focus { border-color: var(--accent); outline: none; }
.cmd-line.cmd-error { border-color: var(--danger); }
.stat-chip { color: var(--text-mute); }
.stat-chip em { font-style: normal; color: var(--text); margin-left: 4px; font-variant-numeric: tabular-nums; }
.stat-chip.stat-bril strong { color: var(--text-dim); font-weight: 500; }
.stat-chip.stat-bril em { font-weight: 700; }

/* ---------- Library ---------- */
.lib-header h2 { margin: 0 0 4px; font-size: 20px; }
.lib-header { margin-bottom: 14px; }

.lib-controls {
  display: flex; align-items: center; gap: 8px;
  margin: 14px 0 10px; flex-wrap: wrap;
}
.lib-count { color: var(--text-mute); font-size: 12px; }
#libSearch {
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 6px 10px; font: inherit; font-size: 13px;
  min-width: 220px;
}
#libSearch:focus { outline: none; border-color: var(--accent); }
#libSearch:disabled { opacity: 0.5; }

.lib-filters {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 12px; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); margin-bottom: 12px;
  font-size: 12px;
}
.lib-chip { display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px; background: var(--surface-2); border: 1px solid var(--line); border-radius: 12px; cursor: pointer; }
.lib-chip input { accent-color: var(--accent); margin: 0; }
.lib-sep { width: 1px; height: 18px; background: var(--line); }
.lib-rangelabel { color: var(--text-dim); }
.lib-rangelabel span { color: var(--text); font-variant-numeric: tabular-nums; }
.lib-filters input[type=range] { width: 90px; accent-color: var(--accent); }
.lib-filters select { background: var(--surface-2); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius); padding: 3px 6px; font: inherit; font-size: 12px; }

.lib-progress {
  display: flex; align-items: center; gap: 12px; padding: 8px 14px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  margin-bottom: 12px; font-size: 12px;
}
.lib-progress-bar { flex: 1; height: 6px; background: var(--surface-2); border-radius: 3px; overflow: hidden; }
.lib-progress-bar > div { height: 100%; background: var(--accent); transition: width 0.15s ease; }

.lib-samples h3 {
  margin: 18px 0 8px; font-size: 14px; font-weight: 600;
  letter-spacing: 0.02em;
}
.lib-samples .lib-grid { margin: 4px 0 18px; }

.lib-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 10px; margin: 12px 0;
}
.library-card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 10px 12px;
  cursor: pointer; transition: border-color 0.12s ease, background 0.12s ease;
}
.library-card:hover { border-color: var(--accent); background: var(--surface-2); }
.lib-card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.lib-fmt {
  font-size: 10px; font-weight: 700; padding: 1px 6px; border-radius: 3px;
  text-transform: uppercase; letter-spacing: 0.06em;
  background: var(--surface-2); color: var(--text-dim);
  flex-shrink: 0;
}
.lib-fmt-gem { background: rgba(255, 184, 74, 0.15); color: var(--warn); }
.lib-fmt-gcs { background: rgba(74, 127, 255, 0.18); color: var(--accent); }
.lib-fmt-asc { background: rgba(90, 217, 160, 0.15); color: var(--ok); }
.lib-name { font-size: 13px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 1; }
.lib-card-meta { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--text-mute); flex-wrap: wrap; }
.lib-designer { color: var(--text-dim); flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lib-stat { font-variant-numeric: tabular-nums; }

.library-empty { grid-column: 1 / -1; padding: 30px; background: var(--surface); border: 1px dashed var(--line); border-radius: var(--radius); text-align: center; color: var(--text-mute); font-size: 13px; }

.notify-card { max-width: 520px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 16px 18px; margin-top: 24px; }
.notify-card h3 { margin: 0 0 8px; font-size: 14px; }
.notify-card form { display: flex; gap: 8px; margin-top: 10px; }
.notify-card input { flex: 1; padding: 8px 10px; background: var(--surface-2); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius); font: inherit; }
.notify-card input:focus { outline: none; border-color: var(--accent); }
.notify-card button { padding: 8px 14px; background: var(--accent); color: var(--accent-ink); border: 0; border-radius: var(--radius); font-weight: 600; }
.notify-card button:hover { background: var(--accent-hi); }
.roadmap { line-height: 1.9; }

/* ---------- Small screens ---------- */
@media (max-width: 900px) {
  .cad-grid { grid-template-columns: 260px 1fr 72px; }
}
@media (max-width: 700px) {
  .cad-grid { grid-template-columns: 1fr; }
  .center-col { display: none; }
  .rail { display: none; }
}

/* ============================================================
   Zone 1: application menu bar (File / Edit / View / Tools)
   ============================================================ */
.topbar { justify-content: flex-start; gap: 8px; }
.topbar .tabs { margin-left: auto; }
.brand-mark { color: var(--coral); margin-right: 1px; }

.menubar { display: flex; align-items: stretch; height: 100%; }
body:not([data-tab="viewer"]) .menubar { display: none; }   /* menus act on the viewer only */
.menu { position: relative; display: flex; align-items: center; }
.menu-title {
  background: transparent; border: 0; color: var(--text-dim);
  padding: 0 11px; height: 100%; font-size: 12.5px; white-space: nowrap;
}
.menu-title:hover { color: var(--text); background: var(--surface-2); }
.menu.open > .menu-title { color: var(--text); background: var(--surface-2); }
.menu-pop {
  display: none; position: absolute; top: 100%; left: 0; z-index: 1000;
  min-width: 188px; padding: 4px;
  background: var(--surface-2); border: 1px solid var(--line-2);
  border-radius: var(--radius); box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
}
.menu.open > .menu-pop { display: block; }
.menu-item {
  display: block; width: 100%; text-align: left;
  background: transparent; border: 0; color: var(--text);
  padding: 6px 10px; font-size: 12.5px; border-radius: 2px; white-space: nowrap;
}
.menu-item:hover { background: var(--accent); color: var(--accent-ink); }
.menu-divider { height: 1px; margin: 4px 6px; background: var(--line); }

/* ---- Coral accents per Option B (logo handled above; CUT + active camera here) ---- */
.cut-btn:not(:disabled) {
  background: var(--coral); color: var(--coral-ink);
  box-shadow: inset 0 0 0 1px var(--coral-hi);
}
.cut-btn:not(:disabled):hover {
  background: var(--coral-hi);
  box-shadow: inset 0 0 0 1px #fff, 0 0 18px rgba(255, 111, 97, 0.35);
}
.view-buttons button.active {
  background: var(--coral); border-color: var(--coral); color: var(--coral-ink);
}

/* ---- Open-core seam (REPO_SPLIT.md, REVISED 2026-07-27): basic mode ----
   index.html ships <body data-fantasy="absent"> so the private tier's
   controls are hidden from first paint; app.js REMOVES the flag once
   /fantasy/index.js loads. Tier missing (the AGPL build) or ?nofantasy=1 →
   the flag stays and the app runs as a complete planar CAD WITH FULL OPTICS.
   Only fantasy/curved/concave controls carry .fantasy-only (the Fantasy
   button, its menu item, the CSG toggle) — brilliance, light path, raytrace,
   optimizer, tilt sweep, head shadow and dispersion are all free tier and
   are not gated. The gated elements stay in the DOM so public code that
   reads them keeps working. */
body[data-fantasy="absent"] .fantasy-only { display: none !important; }

/* ---- Zone badge: WHICH BUILD AM I LOOKING AT? (zone.js) ----
   Three zones look identical in a browser tab, and on 2026-07-31 a stray
   server on a port served the FULL tree while the address bar implied the free
   one. Colour is the fastest possible read, so the zones are deliberately
   unmistakable rather than tasteful: amber = the working tree you build in,
   green = a generated public preview you must not edit, red = production. */
.zone-badge { font-variant-numeric: tabular-nums; letter-spacing: .02em; }
.zone-local-full {
  background: #4a3410; border-color: #b8791f; color: #ffc766;
}
.zone-local-free {
  background: #10331f; border-color: #2f8f5b; color: #6fe0a4;
}
.zone-live {
  background: #4a1216; border-color: #c0353f; color: #ff8a92;
  font-weight: 700;
}

/* ---- SPEC_6 CA1: at-the-machine cutting mode ----
   Huge, glanceable, high-contrast — for a cutter with wet hands reading a
   tablet propped at the mast (the Doyle/Gordon accessibility requirement).
   Driven by cutting.js's sequence state; EXIT returns to the design view. */
.machine-mode {
  position: fixed; inset: 0; z-index: 300;
  background: #060609;
  display: flex; flex-direction: column;
  color: #fff; user-select: none;
}
.machine-mode .mm-top {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 18px; border-bottom: 1px solid #26263a;
  font-size: clamp(15px, 2.4vw, 22px);
}
.machine-mode .mm-progress { color: var(--coral, #ff6f61); font-weight: 700; font-variant-numeric: tabular-nums; }
.machine-mode .mm-title { color: #9a9aa6; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.machine-mode .mm-exit {
  margin-left: auto; background: transparent; color: #9a9aa6;
  border: 1px solid #3a3a48; border-radius: 6px; padding: 8px 16px;
  font-size: clamp(13px, 2vw, 18px); cursor: pointer; min-height: 48px;
}
.machine-mode .mm-body {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 2vh; padding: 0 4vw;
  text-align: center;
}
.machine-mode .mm-tiername { font-size: clamp(26px, 6vw, 56px); font-weight: 700; letter-spacing: 0.04em; }
.machine-mode .mm-frost { color: #9fd8ff; font-size: 0.6em; vertical-align: middle; }
.machine-mode .mm-angle {
  font-size: clamp(72px, 19vw, 190px); font-weight: 800; line-height: 1;
  font-variant-numeric: tabular-nums; color: #fff;
}
.machine-mode .mm-indices {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 0.4em 0.7em;
  font-size: clamp(24px, 6.5vw, 58px); font-weight: 700;
  font-variant-numeric: tabular-nums; color: var(--coral, #ff6f61);
  max-width: 92vw;
}
.machine-mode .mm-note { font-size: clamp(14px, 2.6vw, 22px); color: #9a9aa6; }
.machine-mode .mm-actions {
  display: flex; gap: 12px; padding: 16px 18px 22px;
}
.machine-mode .mm-actions button {
  flex: 1; min-height: clamp(64px, 10vh, 96px);
  font-size: clamp(18px, 3.6vw, 32px); font-weight: 700;
  border-radius: 10px; border: 1px solid #3a3a48; cursor: pointer;
  background: #16161f; color: #cfd0dc;
}
.machine-mode .mm-actions .mm-next {
  flex: 2.2; background: var(--coral, #ff6f61); color: #1c0f0d; border-color: transparent;
}

/* ============================================================
   Mobile / tablet fit — <=1450px ONLY (owner 2026-07-23).
   Desktop is untouched: .compact-only buttons stay hidden, the
   toolstrip stays a normal in-flow ribbon, the mast cluster
   stays a floating card.
   ============================================================ */
.compact-only { display: none; }
.stone-full-float { display: none; }

@media (max-width: 1450px) {
  .compact-only { display: inline-flex; }

  /* Toolbar ribbon: collapsed by default so everything moves up; the
     ▤ Toolbar button opens it as a DROPDOWN over the workspace (an overlay —
     content underneath does not reflow). */
  .toolstrip { display: none; }
  body[data-toolstrip="open"] .toolstrip {
    display: flex;
    position: absolute; top: 0; left: 0; right: 0; z-index: 220;
    border-bottom: 1px solid var(--line-2);
    box-shadow: 0 14px 28px rgba(0, 0, 0, 0.55);
  }

  /* Mast cluster docks HOME: in flow under the ruler bar, centered, above
     the design/render panes. position:static makes the drag JS's inline
     left/top inert; the drag grip hides with it. */
  .mast-strip {
    position: static;
    margin: 4px auto;
    max-width: calc(100% - 8px);
    flex-wrap: wrap;
  }
  .mc-grip { display: none; }

  /* Floating full-screen button on the stone view */
  .stone-full-float { display: inline-flex; }
}

/* Full-screen stone mode (entered from the mobile buttons; Esc or the same
   button exits). The center column takes the whole window; the design pane
   and divider drop, everything else sits beneath the overlay. */
.stone-full-float {
  position: absolute; right: 10px; top: 10px; z-index: 5;
  padding: 8px 11px; font-size: 16px; line-height: 1;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius);
}
body[data-stone-full] .center-col {
  display: flex; position: fixed; inset: 0; z-index: 240; background: var(--bg);
}
/* Design/Render merge: the interactive stone lives in the DESIGN pane now —
   full-screen keeps Design, drops Render + divider. */
body[data-stone-full] .render-pane,
body[data-stone-full] .pane-divider { display: none; }
body[data-stone-full] .design-pane { border-right: 0; }
body[data-stone-full] .stone-full-float { display: inline-flex; }

/* ============================================================
   Touch gesture ownership (owner 2026-07-23: iPad page-scroll
   fights control drags). Drag surfaces own their gesture — Safari
   must never steal it for page scroll (which strands mid-drag via
   pointercancel). touch-action only affects touch input; desktop
   mice are untouched.
   ============================================================ */
.mc-jog-slider, .mc-step, .mc-grip, .mc-zone,
.ruler-wrap, .pane-divider, .fw-head { touch-action: none; }
.mc-grip, .mc-zone, .mc-step, .ruler-bar, .rail-float-head, .tgroup-label {
  -webkit-user-select: none; user-select: none;
}

@media (max-width: 1450px) {
  /* Lock the shell (owner 2026-07-23 "lock the screen"): the page itself can
     never pan, bounce, or rubber-band — finger drags belong to the controls.
     Panes with internal overflow still scroll; the chain stops at the shell. */
  html { overflow: hidden; overscroll-behavior: none; touch-action: manipulation; }
  body { position: fixed; inset: 0; overflow: hidden; overscroll-behavior: none; }
  .panel-body, .pane-body, .rail { overscroll-behavior: contain; }

  /* Safari's collapsing browser chrome: size the workspace to the DYNAMIC
     viewport so the status bar is never pushed under the toolbar. */
  .workspace { height: calc(100dvh - var(--topbar-h)); }

  /* The floating properties card must never be buried under the toolbar
     dropdown (z 220) — its grab head has to stay reachable. */
  body.rail-float .rail-render { z-index: 230; }
}

/* ============================================================
   Double-tap must NEVER zoom (owner 2026-07-25: rapid-tapping the
   angle/depth steppers zoomed the page). touch-action:manipulation
   keeps pan + two-finger pinch and drops double-tap zoom, app-wide.
   The none-list re-asserts (same specificity, later order) the drag
   surfaces that own their gestures outright. Touch-only; mice unaffected.
   ============================================================ */
.topbar, .topbar *, .workspace, .workspace * { touch-action: manipulation; }
.mc-jog-slider, .mc-step, .mc-grip, .mc-zone,
.ruler-wrap, .pane-divider, .fw-head { touch-action: none; }

/* ============================================================
   Free design library (CC0 catalogue) on the Library tab.
   Thumbnail grid is the default browse mode (thumbnails are how
   cutters choose cuts); .dlib-list serves the readers.
   ============================================================ */
.dlib { margin: 18px 0 26px; }
.dlib-head h3 { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.dlib-cc0 {
  font-size: 11px; font-weight: 600; letter-spacing: .02em;
  padding: 2px 8px; border-radius: 999px;
  background: color-mix(in srgb, var(--accent, #4a9eff) 18%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent, #4a9eff) 45%, transparent);
}
/* Designer collections (CC BY). Warm badge vs. the CC0 library's accent-blue
   one: the two catalogues carry different licences, so they must not read as
   the same thing at a glance. .dcol-credit is the designer's attribution and
   is REQUIRED on every card — CC BY's one condition — so it is styled to be
   legible, not to be decoration that a later tidy-up might delete. */
.dcol + .dcol { margin-top: 26px; }
.dcol-lic {
  font-size: 11px; font-weight: 600; letter-spacing: .02em;
  padding: 2px 8px; border-radius: 999px;
  background: color-mix(in srgb, #e8a054 20%, transparent);
  border: 1px solid color-mix(in srgb, #e8a054 50%, transparent);
}
.dcol-by { font-size: 14px; opacity: .95; margin: 2px 0 6px; letter-spacing: .01em; }
/* Memorial collections read warmer than the CC BY badge and carry a
   dedication in place of a licence link. Given room to breathe on purpose —
   it is the point of the section, not a disclaimer. */
.dcol-mem {
  background: color-mix(in srgb, #b9a06a 20%, transparent);
  border-color: color-mix(in srgb, #b9a06a 50%, transparent);
}
.dcol-dedication {
  margin: 14px 0 6px; padding: 10px 0 10px 14px;
  border-left: 2px solid color-mix(in srgb, #b9a06a 55%, transparent);
  font-size: 13.5px; line-height: 1.6; opacity: .92; font-style: italic;
}
.dcol-dedication div:last-child { font-style: normal; opacity: .8; margin-top: 4px; }
.dcol-credit { font-size: 12px; opacity: .9; font-style: italic; }
.dcol-foot { font-size: 12px; margin-top: 10px; }
.dcol-foot a { color: inherit; }

.dlib-controls {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin: 10px 0 12px;
}
.dlib-controls label { display: flex; align-items: center; gap: 6px; font-size: 13px; }
.dlib-tune { font-size: 12px; }
.dlib-viewtoggle { display: flex; gap: 4px; }
.dlib-grid {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.dlib-card {
  border: 1px solid var(--border, #333); border-radius: 10px;
  overflow: hidden; background: var(--panel, #1b1b1f);
  display: flex; flex-direction: column;
}
.dlib-thumb { width: 100%; aspect-ratio: 1; object-fit: cover; display: block; background: #000; }
.dlib-card-body { padding: 8px 10px 10px; display: flex; flex-direction: column; gap: 6px; }
.dlib-name { font-weight: 600; font-size: 14px; }
.dlib-meta { font-size: 12px; opacity: .75; font-weight: 400; }
.dlib-actions { display: flex; gap: 6px; margin-top: 2px; flex-wrap: wrap; }
.dlib-actions .tool-btn { font-size: 12px; padding: 4px 9px; }
.dlib-off .dlib-thumb { filter: grayscale(.9) brightness(.6); }
.dlib-nogear {
  font-size: 12px; line-height: 1.35; padding: 5px 8px; border-radius: 6px;
  background: color-mix(in srgb, #c8781e 14%, transparent);
  border: 1px solid color-mix(in srgb, #c8781e 40%, transparent);
}
.dlib-list { display: flex; flex-direction: column; gap: 8px; }
.dlib-row {
  display: flex; align-items: center; gap: 12px;
  border: 1px solid var(--border, #333); border-radius: 10px;
  padding: 8px 12px; background: var(--panel, #1b1b1f);
}
.dlib-thumb-s { width: 56px; height: 56px; border-radius: 8px; object-fit: cover; background: #000; flex: none; }
.dlib-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.dlib-row .dlib-actions { flex: none; }
.dlib-info {
  margin-top: 12px; padding: 12px 14px; border-radius: 10px;
  border: 1px solid var(--border, #333); background: var(--panel, #1b1b1f);
  font-size: 13px; line-height: 1.5;
}
.dlib-info-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
