1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189
/* adom-step — Fusion 360-feel STEP viewer styles */

/* Adom brand fonts — Familjen Grotesk (headlines), Satoshi (body),
   JetBrains Mono (code / brand row). Per gallia/skills/brand:
   "Do NOT use Inter, Arial, Helvetica, or system fonts as primary."
   Without these @font-face blocks the browser silently falls back
   to system sans-serif and the app looks off-brand. */
@font-face {
  font-family: 'Familjen Grotesk';
  src: url('https://adom.inc/fonts/familjen-grotesk/familjen-grotesk-latin-700-normal.woff2') format('woff2');
  font-weight: 700; font-display: swap;
}
@font-face {
  font-family: 'Familjen Grotesk';
  src: url('https://adom.inc/fonts/familjen-grotesk/familjen-grotesk-latin-600-normal.woff2') format('woff2');
  font-weight: 600; font-display: swap;
}
@font-face {
  font-family: 'Familjen Grotesk';
  src: url('https://adom.inc/fonts/familjen-grotesk/familjen-grotesk-latin-500-normal.woff2') format('woff2');
  font-weight: 500; font-display: swap;
}
@font-face {
  font-family: 'Satoshi';
  src: url('https://adom.inc/fonts/satoshi/satoshi-400-normal.woff2') format('woff2');
  font-weight: 400; font-display: swap;
}
@font-face {
  font-family: 'Satoshi';
  src: url('https://adom.inc/fonts/satoshi/satoshi-500-normal.woff2') format('woff2');
  font-weight: 500; font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('https://cdn.jsdelivr.net/npm/@fontsource/jetbrains-mono@5/files/jetbrains-mono-latin-400-normal.woff2') format('woff2');
  font-weight: 400; font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('https://cdn.jsdelivr.net/npm/@fontsource/jetbrains-mono@5/files/jetbrains-mono-latin-500-normal.woff2') format('woff2');
  font-weight: 500; font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('https://cdn.jsdelivr.net/npm/@fontsource/jetbrains-mono@5/files/jetbrains-mono-latin-600-normal.woff2') format('woff2');
  font-weight: 600; font-display: swap;
}

:root {
  /* Brand-skill palette: Adom Teal #00B8B1 is the primary accent, never cyan. */
  --bg: #1a1d22;
  --bg-soft: #20242b;
  --bg-elev: #272c34;
  --border: #353b45;
  --border-soft: #2c313a;
  --text: #e6e8eb;
  --text-dim: #9aa0a8;
  --accent: #00b8b1;                       /* brand teal */
  --accent-bright: #8fd3d4;                /* brand teal-light, hover */
  --accent-cta: #0061ef;                   /* brand blue-dark, CTAs */
  --accent-soft: rgba(0, 184, 177, 0.14);
  --measure: #00b8b1;                      /* unified with brand */
  --inspect: #f5be50;                      /* amber, distinct from accent */
  --warn: #ff7043;
  --shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
  --row-h: 24px;

  /* z-index ladder per human-ui-patterns §1d. Use these tokens, never raw numbers. */
  --z-hud:           50;     /* draggable HUDs (measure, section, inspect) */
  --z-toolbar:       80;     /* fixed header / footer */
  --z-floating-menu: 200;    /* topbar, context menu, dropdowns */
  --z-toast:         400;
  --z-modal:         600;
  --z-tooltip:       99999;  /* always on top */
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  /* Body text = Satoshi (Adom brand standard). System fonts are
     fallbacks for the brief moment before WOFF2 fonts swap in. */
  font: 13px/1.4 'Satoshi', -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  overflow: hidden;
}

/* Babylon Inspector mounts in non-embed mode (its own resizable side
   panel using stock Babylon UI). We don't position it ourselves —
   forcing widths/heights via CSS breaks the section-header click
   targets and chevron icons. Just let the Inspector own its real estate. */

/* Canonical Adom app-header — see gallia/skills/adom-app-header/SKILL.md.
   Single row, 44 px tall. Identical across every Adom app. */
header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 44px;
  padding: 0 16px;
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--bg);
  border-bottom: 1px solid var(--border-muted);
  z-index: var(--z-floating-menu);
  user-select: none;
  font-family: 'Familjen Grotesk', sans-serif;
}
header .brand {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--accent);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: default;
  flex-shrink: 0;
  outline: none;
}
header .brand:hover .app-name { text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 3px; }
header .brand:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
header .brand svg.logo { width: 16px; height: 16px; flex-shrink: 0; stroke: currentColor; fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
header .brand .app-name { color: var(--accent); }
header .brand .app-subtitle { color: var(--text2, #7d8590); font-weight: 500; }
header .brand .sep { color: var(--text3, #484f58); font-weight: 400; }
header .vsep {
  width: 1px;
  height: 18px;
  background: var(--border);
  flex-shrink: 0;
}
header .subject {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex: 1 1 auto;
  cursor: default;
}
header .subject-name {
  color: var(--text);
  font-family: 'Familjen Grotesk', sans-serif;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
header .subject-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text2, #7d8590);
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  white-space: nowrap;
  flex-shrink: 0;
}
header .subject-meta .sep { color: var(--text3, #484f58); }
@media (max-width: 720px) {
  header .subject-meta { display: none; }
}
header .state-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 8px;
  border-radius: 10px;
  font-family: 'Familjen Grotesk', sans-serif;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.3px;
  text-transform: none;
  flex-shrink: 0;
  cursor: default;
  background: var(--elevated, #1c2128);
  color: var(--text2, #7d8590);
  border: 1px solid var(--border);
}
header .state-pill[data-source-type="kicad-library"] {
  background: rgba(0, 184, 177, 0.15);
  color: var(--accent);
  border-color: var(--accent);
}
header .state-pill[data-source-type="local-file"] {
  background: rgba(245, 190, 80, 0.12);
  color: var(--inspect);
  border-color: var(--inspect);
}
header .state-pill[data-source-type="upload"] {
  background: rgba(143, 211, 212, 0.15);
  color: var(--accent-bright);
  border-color: var(--accent-bright);
}

/* --- Interactive hover-popover (movable into; carries clickable links) --- */
header .hover-popover {
  position: absolute;
  top: calc(100% + 6px);
  left: 16px;
  background: var(--elevated, #1c2128);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.5);
  padding: 12px 14px;
  min-width: 300px;
  max-width: 420px;
  font-family: 'Satoshi', sans-serif;
  font-size: 12px;
  color: var(--text);
  z-index: 99999;
  opacity: 0;
  transform: translateY(-2px);
  pointer-events: none;
  transition: opacity 120ms ease, transform 120ms ease;
}
header .hover-popover.show {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
header .hover-popover.compact { min-width: 220px; left: 120px; right: auto; }
header .hover-popover .popover-title {
  font-family: 'Familjen Grotesk', sans-serif;
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 8px;
}
header .hover-popover .popover-row {
  display: flex;
  gap: 12px;
  padding: 3px 0;
  align-items: baseline;
}
header .hover-popover .popover-row .k {
  color: var(--text3, #484f58);
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  text-transform: lowercase;
  width: 64px;
  flex-shrink: 0;
}
header .hover-popover .popover-row .v {
  color: var(--text);
  font-family: 'Satoshi', sans-serif;
  font-size: 12px;
  flex: 1;
  word-break: break-word;
}
header .hover-popover .popover-actions {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border-muted, #21262d);
  display: flex;
  gap: 12px;
}
header .hover-popover .popover-link {
  color: var(--accent);
  text-decoration: none;
  font-family: 'Familjen Grotesk', sans-serif;
  font-size: 12px;
  font-weight: 600;
}
header .hover-popover .popover-link:hover { text-decoration: underline; }

.app {
  position: fixed;
  top: 44px;
  left: 0;
  right: 0;
  bottom: 0;
  /* Single column — canvas fills the entire viewport so the outline can
     float on top of it, Fusion 360 Browser-style. */
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: 1fr;
  background: var(--bg);
}

/* ---- Outline (Fusion 360 Browser-style floating panel) ----
   Translucent dark glass that sits over the canvas. The 3D scene shows
   through underneath so the outline never feels like it's stealing real
   estate from the model. Collapsible via the chevron in the header
   (slides off-screen) — collapsed state reveals a slim vertical
   expand-tab at the canvas's left edge. */

.sidebar {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 280px;
  /* Light Fusion 360-feel — nearly transparent. The 3D scene reads
     clearly through the panel; outline rows stay legible via the
     text-shadow rule below. No solid panel, no heavy border. */
  background: transparent;
  border-right: none;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  z-index: 50;  /* above the canvas, below modals/tooltips */
  transition: transform 200ms cubic-bezier(0.4, 0.0, 0.2, 1);
}
/* Outline row legibility against any scene — soft dark text-shadow on
   every row label so light pads / silver caps don't wash out the text.
   Cheap (no full-screen blur) and matches Fusion's approach. */
.sidebar .sb-tree .tree-row,
.sidebar .sb-title,
.sidebar .sb-source,
.sidebar .sb-search,
.sidebar .sb-chip {
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.85), 0 0 4px rgba(0, 0, 0, 0.55);
}
.sidebar.collapsed {
  transform: translateX(-100%);
  pointer-events: none;
}

/* Expand tab — only shown when the outline is collapsed. Sits at the
   canvas's left edge as a slim vertical strip with a chevron pointing
   inward (❯). Same translucent glass treatment as the panel itself so
   the visual language stays consistent. */
.outline-expander {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  width: 22px;
  height: 64px;
  background: rgba(20, 24, 30, 0.82);
  backdrop-filter: blur(8px) saturate(1.2);
  -webkit-backdrop-filter: blur(8px) saturate(1.2);
  border: 1px solid var(--border);
  border-left: none;
  border-radius: 0 6px 6px 0;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 14px;
  font-family: inherit;
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 51;
  padding: 0;
  transition: background 120ms ease, color 120ms ease;
}
.outline-expander:hover {
  background: rgba(0, 184, 177, 0.18);
  color: var(--accent);
}
body.outline-collapsed .outline-expander {
  display: flex;
}

.sidebar .sb-header {
  padding: 10px 12px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sidebar .sb-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}

.sidebar .sb-title {
  font-weight: 600;
  letter-spacing: 0.02em;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-dim);
}

/* Collapse chevron — sits at the right end of the title row. Same hit-zone
   target sizing as the tree-row icons so it feels consistent. */
.sidebar .sb-collapse {
  width: 22px;
  height: 22px;
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 12px;
  font-family: inherit;
  border-radius: 4px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.sidebar .sb-collapse:hover {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent);
}
.sidebar .sb-title .count {
  font-weight: 400;
  color: var(--text-dim);
  font-size: 11px;
}

.sidebar .sb-search {
  width: 100%;
  /* Translucent input so the scene still shows behind it. Faint focus
     accent + text shadow keeps the placeholder legible. */
  background: rgba(20, 24, 30, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.10);
  color: var(--text);
  padding: 5px 8px;
  border-radius: 4px;
  font-size: 12px;
  outline: none;
}
.sidebar .sb-search:focus {
  background: rgba(20, 24, 30, 0.65);
  border-color: var(--accent);
}

.sidebar .sb-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 2px;
}
.sidebar .sb-chip {
  background: rgba(20, 24, 30, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.10);
  color: var(--text-dim);
  padding: 3px 8px;
  font-size: 11px;
  border-radius: 10px;
  cursor: pointer;
  font-family: inherit;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.sidebar .sb-chip:hover {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent);
}
.sidebar .sb-chip.active {
  background: var(--accent-soft);
  color: var(--accent);
  border-color: var(--accent);
}
.sidebar .sb-chip .count {
  font-size: 10px;
  opacity: 0.7;
  font-weight: 400;
}

.sidebar .sb-source {
  font-size: 11px;
  color: var(--text-dim);
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}

.sidebar .sb-tree {
  flex: 1 1 auto;
  overflow-y: overlay;       /* WebKit: thumb floats over content, no width loss */
  overflow-y: auto;          /* fallback for browsers without `overlay` */
  padding: 4px 0;
  min-height: 0;
  /* Firefox thin overlay-style scrollbar — track stays invisible. */
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
}
/* WebKit / Blink: 6px-wide overlay scrollbar that fades in on hover/scroll.
   Tracks are transparent so the canvas keeps showing through; the thumb is
   a soft white tint that mirrors Fusion 360's Browser scrollbar. */
.sidebar .sb-tree::-webkit-scrollbar {
  width: 6px;
  height: 6px;
  background: transparent;
}
.sidebar .sb-tree::-webkit-scrollbar-track {
  background: transparent;
}
.sidebar .sb-tree::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.10);
  border-radius: 3px;
  transition: background 150ms ease;
}
.sidebar:hover .sb-tree::-webkit-scrollbar-thumb,
.sidebar .sb-tree:hover::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.28);
}
.sidebar .sb-tree::-webkit-scrollbar-thumb:active {
  background: rgba(255, 255, 255, 0.42);
}
.sidebar .sb-tree::-webkit-scrollbar-corner {
  background: transparent;
}

.tree-row {
  display: flex;
  align-items: center;
  height: 28px;             /* bumped from 24 — bigger hit targets */
  padding-right: 8px;
  user-select: none;
  cursor: default;
  font-size: 12px;
  color: var(--text);
  white-space: nowrap;
}
.tree-row:hover {
  background: var(--accent-soft);
}
.tree-row.selected {
  background: var(--accent-soft);
}
.tree-row.dimmed {
  opacity: 0.35;
}

/* "Find in outline" flash — used after right-click in the 3D viewer to
   draw the user's eye to the row that just got revealed. */
@keyframes treeRowFlash {
  0%   { background: rgba(0, 184, 177, 0); }
  20%  { background: rgba(0, 184, 177, 0.55); }
  100% { background: rgba(0, 184, 177, 0); }
}
.tree-row.flash {
  animation: treeRowFlash 1.4s ease-out;
}
.tree-row.hidden-vis {
  color: var(--text-dim);
}

/* Tree-row icons: bigger hit targets, always-visible, brand-teal active.
   Per human-ui-patterns §1a all three carry data-tooltip explaining what
   they do; per the same skill, hit zones are at least 24×24 so a real
   pointer (not a sub-pixel mouse) can land them. */
.tree-row .caret,
.tree-row .eye,
.tree-row .iso {
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
  border-radius: 4px;
  margin-right: 1px;
}
.tree-row .caret {
  color: var(--text-dim);
  font-size: 12px;       /* VS-Code-style ❯ chevron — slim glyph, rotates 90° via .open */
  font-weight: 600;
  line-height: 1;
  transition: transform 120ms ease;
  transform-origin: 50% 50%;
}
.tree-row .caret.has-children {
  cursor: pointer;
}
.tree-row .caret.has-children.open {
  transform: rotate(90deg);  /* expanded → chevron points down, matching VS Code Explorer */
}
.tree-row .caret.has-children:hover {
  background: var(--accent-soft);
  color: var(--accent);
}
.tree-row .caret.leaf {
  cursor: default;        /* no fake-button affordance for leaf rows */
  visibility: hidden;     /* keep the slot for alignment, hide the glyph */
}
.tree-row .eye {
  color: var(--accent);
  font-size: 14px;
}
.tree-row .eye:hover {
  background: var(--accent-soft);
}
.tree-row.hidden-vis .eye { color: var(--text-dim); }
.tree-row .eye.mixed { color: var(--inspect); }

.tree-row .iso {
  color: var(--text-dim);
  font-size: 12px;
  /* always visible (not hover-only) so users discover the affordance */
}
.tree-row .iso:hover {
  color: var(--accent);
  background: var(--accent-soft);
}

.tree-row .label {
  margin-left: 4px;
  text-overflow: ellipsis;
  overflow: hidden;
  flex: 1 1 auto;
  min-width: 0;
}

.tree-row .child-count {
  font-size: 10px;
  color: var(--text-dim);
  margin-left: 6px;
  flex-shrink: 0;
}
.tree-row.material-group .label {
  font-weight: 500;
}
.tree-row .mat-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  margin-right: 6px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  flex-shrink: 0;
}

.tree-row .pin-side {
  font-size: 10px;
  padding: 1px 6px;
  border-radius: 8px;
  margin-left: 6px;
  flex-shrink: 0;
  font-family: ui-monospace, monospace;
  letter-spacing: 0.02em;
}
.tree-row .pin-side[data-side="front"] { background: rgba(143, 211, 212, 0.18); color: var(--accent-bright); }
.tree-row .pin-side[data-side="right"] { background: rgba(0, 184, 177, 0.18);   color: var(--accent); }
.tree-row .pin-side[data-side="back"]  { background: rgba(100, 171, 255, 0.18); color: #64ABFF; }
.tree-row .pin-side[data-side="left"]  { background: rgba(245, 190, 80, 0.18);  color: var(--inspect); }

/* Tree row badges — small monochrome SVG status icons that sit between
   the label and the child-count. Each badge inherits its tint from a
   per-kind data-attribute so a row can carry several at once (pin-1
   star + chipsmith-synthesized sparkle, for example). Per
   gallia/skills/human-ui-patterns playbooks/icons-and-displays.md §4b
   we use SVGs not Unicode emoji: same stroke weight, same 12px box,
   currentColor so the row's text color drives them.

   Hover/tooltip on each badge is set via data-tooltip in JS so users
   discover what they mean without a legend. */
.tree-row .tree-badges {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-left: 4px;
  flex-shrink: 0;
}
.tree-row .tree-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  border-radius: 3px;
  line-height: 0;
}
.tree-row .tree-badge svg {
  width: 12px;
  height: 12px;
  display: block;
}
.tree-row .tree-badge[data-kind="pin1"]   { color: var(--inspect); background: rgba(245, 190, 80, 0.20); }
.tree-row .tree-badge[data-kind="synth"]  { color: var(--accent);  background: rgba(0, 184, 177, 0.18); }
.tree-row .tree-badge[data-kind="locked"] { color: var(--text-dim); background: rgba(255,255,255,0.08); }
.tree-row .tree-badge[data-kind="redet"]  { color: #64ABFF;        background: rgba(100,171,255,0.18); }

/* ---- Canvas + HUD ---- */

.canvas-wrap {
  position: relative;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}

#renderContainer {
  width: 100%;
  height: 100%;
  position: absolute;
  inset: 0;
  outline: none;
}
#renderContainer canvas {
  width: 100% !important;
  height: 100% !important;
  display: block;
  outline: none;
}

.toolbar {
  position: absolute;
  top: 10px;
  /* Outline floats over the left 280px of the canvas; nudge the toolbar
     past it. When the outline is collapsed (body.outline-collapsed), drop
     back to the canvas edge. The transition matches the outline's slide. */
  left: 290px;
  display: flex;
  gap: 6px;
  align-items: center;
  z-index: var(--z-toolbar);
  transition: left 200ms cubic-bezier(0.4, 0.0, 0.2, 1);
}
body.outline-collapsed .toolbar {
  left: 36px;  /* clear of the expand-tab (22px wide) + breathing room */
}
.tb-sep {
  width: 1px;
  height: 22px;
  background: var(--border);
  margin: 0 2px;
}
.tb-input {
  width: 64px;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 5px 6px;
  font-size: 12px;
  border-radius: 4px;
  font-family: ui-monospace, monospace;
  outline: none;
}
.tb-input:focus { border-color: var(--accent); }
.tb-input.disabled,
.tb-input[aria-disabled="true"] { opacity: 0.4; color: var(--text-dim); }
.tb-btn {
  background: rgba(39, 44, 52, 0.92);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 6px 10px;
  font-size: 12px;
  border-radius: 4px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: inherit;
}
.tb-btn:hover { background: var(--bg-elev); }
/* Icon-only variant — square 30x30 button. Inline custom SVG (not
   Unicode emoji per human-ui-patterns icons-and-displays §4b). Tooltips
   carry the label + behaviour. */
.tb-btn.icon {
  width: 30px;
  height: 30px;
  padding: 0;
  line-height: 1;
  justify-content: center;
  gap: 0;
}
.tb-btn.icon svg {
  width: 18px;
  height: 18px;
  display: block;
}
.tb-btn.active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
.tb-btn.measure.active { border-color: var(--measure); color: var(--measure); background: rgba(29, 233, 182, 0.12); }
.tb-btn.section.active { border-color: var(--warn); color: var(--warn); background: rgba(255, 112, 67, 0.12); }
.tb-btn.disabled,
.tb-btn[aria-disabled="true"] {
  opacity: 0.4;
  cursor: not-allowed;
  color: var(--text-dim);
}
.tb-btn.disabled:hover,
.tb-btn[aria-disabled="true"]:hover { background: rgba(39, 44, 52, 0.92); }

.tb-corner {
  position: absolute;
  bottom: 10px;
  right: 10px;
  display: flex;
  gap: 6px;
  z-index: var(--z-toolbar);
  align-items: center;
}

/* ---- Drop zone overlay ---- */

.dropzone {
  position: absolute;
  inset: 0;
  background: rgba(26, 29, 34, 0.85);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: var(--z-modal);
  pointer-events: none;
}
body.dragging .dropzone { display: flex; }
.dropzone .dz-card {
  border: 2px dashed var(--accent);
  border-radius: 12px;
  padding: 32px 64px;
  font-size: 18px;
  color: var(--accent);
  background: rgba(79, 195, 247, 0.06);
  text-align: center;
  letter-spacing: 0.02em;
}
.dropzone .dz-sub {
  font-size: 13px;
  color: var(--text-dim);
  margin-top: 8px;
}

/* ---- Measure HUD ---- */

.measure-hud {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 280px;
  background: rgba(32, 36, 43, 0.96);
  border: 1px solid var(--measure);
  border-radius: 6px;
  box-shadow: var(--shadow);
  z-index: var(--z-hud);
  display: none;
  font-size: 12px;
  overflow: hidden;
}
.measure-hud.open { display: block; }
.measure-hud .mh-head {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: rgba(29, 233, 182, 0.08);
}
.measure-hud .mh-title {
  color: var(--measure);
  font-weight: 600;
  letter-spacing: 0.04em;

  font-size: 11px;
}
.measure-hud .mh-close {
  cursor: pointer;
  color: var(--text-dim);
  font-size: 14px;
  padding: 0 4px;
}
.measure-hud .mh-close:hover { color: var(--text); }
.measure-hud .mh-snap {
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  background: rgba(0, 184, 177, 0.04);
}
.measure-hud .mh-snap-label {
  color: var(--text-dim);
}
.measure-hud .mh-snap-kind {
  font-family: ui-monospace, monospace;
  font-weight: 600;
  color: var(--text-dim);
  text-transform: capitalize;
}
.measure-hud .mh-snap-kind[data-kind="edge"]   { color: var(--measure); }
.measure-hud .mh-snap-kind[data-kind="face"]   { color: var(--measure); }
.measure-hud .mh-snap-kind[data-kind="vertex"] { color: var(--measure); }
.measure-hud .mh-snap-kind[data-kind="body"]   { color: var(--measure); }
.measure-hud .mh-snap-kind[data-kind="point"]  { color: var(--text-dim); }

.measure-hud .mh-filters {
  padding: 6px 8px;
  border-bottom: 1px solid var(--border);
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
}
.measure-hud .mb-filter {
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 3px 8px;
  font-size: 11px;
  border-radius: 3px;
  cursor: pointer;
}
.measure-hud .mb-filter.active {
  background: rgba(29, 233, 182, 0.16);
  border-color: var(--measure);
  color: var(--measure);
}
.measure-hud .mh-body {
  padding: 8px 10px;
}
.measure-hud .mh-row {
  display: grid;
  grid-template-columns: 70px 1fr;
  gap: 4px 10px;
  padding: 3px 0;
  align-items: baseline;
}
.measure-hud .mh-row .lbl {
  color: var(--text-dim);
  font-size: 11px;
}
.measure-hud .mh-row .val {
  font-family: ui-monospace, monospace;
  font-size: 12px;
}
.measure-hud .mh-sep {
  border-top: 1px solid var(--border);
  margin: 6px 0;
}
.measure-hud .mh-distance {
  color: var(--measure);
  font-weight: 600;
  font-size: 14px;
}
.measure-hud .mh-secondary {
  color: var(--text-dim);
  font-size: 11px;
}
.measure-hud .mh-hint {
  padding: 6px 10px;
  font-size: 11px;
  color: var(--text-dim);
  border-top: 1px solid var(--border);
}

/* ---- Inspect HUD (amber) ---- */

.inspect-card {
  position: fixed;
  background: rgba(32, 36, 43, 0.97);
  border: 1px solid var(--inspect);
  border-radius: 6px;
  box-shadow: var(--shadow);
  z-index: calc(var(--z-hud) + 10);
  display: none;
  width: 260px;
  pointer-events: none;
  font-size: 12px;
  overflow: hidden;
}
.inspect-card.open { display: block; }
.inspect-card.pinned {
  pointer-events: auto;
  border-color: var(--warn);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.6);
}
.inspect-card .ic-head {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  background: rgba(245, 190, 80, 0.08);
}
.inspect-card .ic-name {
  color: var(--inspect);
  font-weight: 600;
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.inspect-card .ic-path {
  font-size: 10px;
  color: var(--text-dim);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.inspect-card .ic-body {
  padding: 6px 10px;
  display: grid;
  grid-template-columns: 70px 1fr;
  gap: 3px 10px;
  font-size: 11px;
}
.inspect-card .ic-body .lbl { color: var(--text-dim); }
.inspect-card .ic-body .val { font-family: ui-monospace, monospace; }
.inspect-card .swatch {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 2px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  vertical-align: middle;
  margin-right: 6px;
}
.inspect-card .ic-foot {
  padding: 4px 10px;
  font-size: 10px;
  color: var(--text-dim);
  border-top: 1px solid var(--border);
  text-align: center;
}

/* ---- Section HUD ---- */

.section-hud {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 260px;
  background: rgba(32, 36, 43, 0.96);
  border: 1px solid var(--warn);
  border-radius: 6px;
  box-shadow: var(--shadow);
  z-index: var(--z-hud);
  display: none;
  font-size: 12px;
  overflow: hidden;
}
.section-hud.open { display: block; }
.section-hud .sh-head {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: rgba(255, 112, 67, 0.08);
}
.section-hud .sh-title {
  color: var(--warn);
  font-weight: 600;
  letter-spacing: 0.04em;

  font-size: 11px;
}
.section-hud .sh-close {
  cursor: pointer;
  color: var(--text-dim);
  font-size: 14px;
  padding: 0 4px;
}
.section-hud .sh-row {
  display: grid;
  grid-template-columns: 24px 24px 1fr 24px 24px;
  gap: 4px;
  padding: 6px 8px;
  align-items: center;
  border-bottom: 1px solid var(--border-soft);
}
.section-hud .sh-row .axis {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 11px;
  border-radius: 3px;
  padding: 2px 6px;
}
.section-hud .sh-row .axis.x { background: rgba(255, 80, 80, 0.18); color: #ff8080; }
.section-hud .sh-row .axis.y { background: rgba(80, 200, 80, 0.18); color: #80e080; }
.section-hud .sh-row .axis.z { background: rgba(80, 140, 255, 0.18); color: #80a8ff; }
.section-hud .sh-row input[type=number] {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 2px 4px;
  font-size: 11px;
  border-radius: 3px;
  font-family: ui-monospace, monospace;
}
.section-hud .sh-row .x-btn,
.section-hud .sh-row .flip-btn {
  cursor: pointer;
  color: var(--text-dim);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 2px 4px;
  font-size: 11px;
}
.section-hud .sh-row .x-btn:hover { color: var(--warn); }
.section-hud .sh-actions {
  padding: 6px 8px;
  display: flex;
  gap: 6px;
  border-top: 1px solid var(--border);
}
.section-hud .sh-actions .btn {
  flex: 1;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 4px 8px;
  font-size: 11px;
  border-radius: 3px;
  cursor: pointer;
}
.section-hud .sh-actions .btn:hover { background: var(--bg-elev); }

/* ---- Toast / status footer ---- */

.toast {
  position: absolute;
  bottom: 10px;
  left: 10px;
  z-index: var(--z-toast);
  background: rgba(32, 36, 43, 0.96);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 6px 10px;
  font-size: 12px;
  color: var(--text-dim);
  box-shadow: var(--shadow);
  display: none;
}
.toast.open { display: block; }
.toast.ok { border-color: var(--measure); color: var(--measure); }
.toast.err { border-color: var(--warn); color: var(--warn); }

/* ---- Loading splash ---- */

.splash {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  z-index: 1;
  color: var(--text-dim);
  font-size: 14px;
  gap: 12px;
}
.splash .spinner {
  width: 28px;
  height: 28px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 1s linear infinite;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ---- Context menu ---- */

.ctx-menu {
  position: fixed;
  background: rgba(32, 36, 43, 0.97);
  border: 1px solid var(--border);
  border-radius: 4px;
  box-shadow: var(--shadow);
  z-index: var(--z-floating-menu);
  min-width: 160px;
  padding: 4px 0;
  font-size: 12px;
  display: none;
}
.ctx-menu.open { display: block; }
.ctx-menu .ctx-item {
  padding: 5px 14px;
  cursor: pointer;
  white-space: nowrap;
}
.ctx-menu .ctx-item:hover { background: var(--accent-soft); color: var(--accent); }
.ctx-menu .ctx-sep {
  border-top: 1px solid var(--border);
  margin: 4px 0;
}