:root {
  --bg: #14171c;
  --panel: #1e232b;
  --panel2: #262c36;
  --line: #39414e;
  --text: #dde3ec;
  --dim: #8a94a6;
  --accent: #4da3ff;
  --accent2: #63d68a;
  --danger: #ff6b6b;
  --tap: 52px;
}
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
.hidden { display: none !important; }
html, body { height: 100%; overscroll-behavior: none; }
body {
  background: var(--bg); color: var(--text);
  font: 15px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  touch-action: manipulation; user-select: none; -webkit-user-select: none;
  overflow: hidden;
}
#app { display: flex; flex-direction: column; height: 100dvh; }

#topbar, #toolbar, #schbar, #pcbbar {
  display: flex; align-items: center; gap: 6px;
  background: var(--panel); padding: 6px 10px; z-index: 5;
  overflow-x: auto; overflow-y: hidden; flex-wrap: nowrap;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
#topbar::-webkit-scrollbar, #toolbar::-webkit-scrollbar,
#schbar::-webkit-scrollbar,
#pcbbar::-webkit-scrollbar { display: none; }
#topbar > *, #toolbar > *, #schbar > *, #pcbbar > * { flex-shrink: 0; }
/* Toolbar and drawer GROUPS.
   `display: contents` means the wrapper generates no box at all: the
   buttons stay direct flex items of the bar, so every phone layout rule
   below still applies exactly as it did before the grouping existed.
   Only the desktop block at the bottom of this file gives the groups a
   box, a heading and a separator. */
.tgroup, .dgroup, #barleft { display: contents; }
.tgroup > *, #barleft > * { flex-shrink: 0; }
/* the collapsible section header is desktop-only chrome: on a phone the
   drawer is one flat scrolling list and every row is already reachable */
.dgh { display: none; }
#topbar { padding-top: calc(6px + env(safe-area-inset-top)); border-bottom: 1px solid var(--line); }
#toolbar, #schbar, #pcbbar { border-bottom: 1px solid var(--line);
  justify-content: center; justify-content: safe center; }
.spacer { flex: 1; }
.divider { width: 1px; height: 30px; background: var(--line); margin: 0 4px; }

/* the document name and the section tabs are desktop-only chrome: a phone
   top bar has no room for either, and gets neither */
#doc-name { display: none; color: var(--dim); font-weight: 600; max-width: 34vw;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
#wstabs { display: none; }

button {
  color: var(--text); background: var(--panel2); border: 1px solid var(--line);
  border-radius: 10px; font-size: 17px; cursor: pointer;
  min-width: 44px; min-height: 44px; touch-action: manipulation;
}
button:active { background: #313a47; }
button.hidden { display: none; }
.tb { min-width: 44px; }
.tb.danger, button.danger { color: var(--danger); }
.tb.accent, button.accent { color: #0b1420; background: var(--accent); border-color: var(--accent); font-weight: 700; }

#mode-switch { display: flex; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.seg { border: 0; border-radius: 0; min-width: 64px; background: var(--panel); color: var(--dim); }
.seg.active { background: var(--accent); color: #0b1420; font-weight: 700; }

#toolbar .tool, #schbar .tool, #pcbbar .tool { min-width: var(--tap); min-height: var(--tap); font-size: 20px; }
#toolbar .tool.active, #schbar .tool.active, #pcbbar .tool.active {
  border-color: var(--accent); color: var(--accent); background: #20304a; }
#schbar .tool, #pcbbar .tool { font-size: 15px; }
#toolbar .tool.accent { font-size: 15px; }
#toolbar .tool.toggle.on { border-color: var(--accent2); color: var(--accent2); background: #1e3a2a; }
#btn-arcseg, #btn-done, #btn-fit, #btn-relxy { font-size: 14px !important; }

#mid { display: flex; flex: 1; overflow: hidden; }
#stage { position: relative; flex: 1; overflow: hidden; background: var(--bg); }

/* Wide screens: the ops sheet becomes a left sidebar that sits IN the
   layout rather than over it — opening it pushes the stage across instead
   of dimming the model behind a backdrop.
   It is hidden until asked for, like the phone drawer: the menu is a
   place you visit, and a permanent 264px column of it was 14% of the
   window spent on rows you read once. The hamburger stays on screen at
   every width and toggles it. */
@media (min-width: 720px) {
  #opsheet {
    position: static;
    width: 280px; min-width: 280px; max-height: none;
    border-top: none; border-right: 1px solid var(--line); border-radius: 0;
    padding: 10px;
  }
  /* the rows are the only thing that may grow, so they are the only thing
     that scrolls. Without this the sidebar simply ran off the bottom of
     the window — the last rows were unreachable at any window height. */
  #drawer-rows { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
}
#c2d, #c3d { position: absolute; inset: 0; width: 100%; height: 100%;
  touch-action: none; display: block; }
#c3d { z-index: 0; }
#c2d { z-index: 1; }
#btn-ctx3d { font-size: 13px !important; }
#c3d.hidden, #c2d.hidden { display: none; }

/* z-index 2: above the canvases (c2d is 1), below overlays/sheets */
#chips { position: absolute; inset: 0; pointer-events: none; overflow: hidden; z-index: 2; }
.chip {
  position: absolute; transform: translate(-50%, -50%);
  background: rgba(30, 41, 56, 0.92); border: 1px solid var(--accent);
  color: var(--accent); border-radius: 14px; padding: 6px 12px;
  font-size: 14px; font-weight: 600; pointer-events: auto; cursor: pointer;
  white-space: nowrap;
}
.chip.pad { border-color: var(--accent2); color: var(--accent2); }

#hint {
  position: absolute; top: 10px; left: 50%; transform: translateX(-50%);
  background: rgba(20, 25, 33, 0.85); color: var(--dim); border-radius: 8px;
  padding: 5px 12px; font-size: 13px; pointer-events: none; white-space: nowrap;
}
#hint:empty { display: none; }

#sheet-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.45); z-index: 8; }
#sheet-backdrop.hidden { display: none; }

.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 9;
  background: var(--panel); border-top: 1px solid var(--line);
  border-radius: 16px 16px 0 0; padding: 12px 14px calc(12px + env(safe-area-inset-bottom));
  max-height: 70dvh; display: flex; flex-direction: column; gap: 10px;
}
.sheet.hidden { display: none; }
.sheet-head { display: flex; align-items: center; gap: 10px; font-weight: 700; }
.sheet-foot { display: flex; gap: 8px; }
.sheet-foot .tb { flex: 1; font-size: 14px; }

#np-value { margin-left: auto; font-size: 22px; color: var(--accent); min-width: 90px; text-align: right; }
#np-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
#np-grid button { min-height: 56px; font-size: 20px; }
#np-grid .wide { grid-column: span 2; }

#design-list, #ops-list { list-style: none; overflow-y: auto; flex: 1; }
/* the designs list opens IN PLACE under its own row — an accordion, not
   an appendix. The drawer menu grew until the old bottom placement put
   the list entirely below a phone's fold: "my designs" looked dead. */
#design-list { flex: none; max-height: 34dvh; }
#design-list li, #ops-list li {
  padding: 12px 10px; border-bottom: 1px solid var(--line); cursor: pointer;
  display: flex; gap: 10px; align-items: baseline;
}
#design-list li.sel, #ops-list li.sel { background: #20304a; border-radius: 8px; }
#design-list li .when, #ops-list li .kind { color: var(--dim); font-size: 12px; margin-left: auto; }
#ops-list li .active-mark { color: var(--accent2); font-weight: 700; }
#ops-list li.body-row { font-weight: 700; background: #1a2027; border-radius: 8px; margin-top: 8px; }
#ops-list li.body-row.sel { background: #24405f; }
#ops-list li.body-row .place { color: var(--dim); font-size: 12px; margin-left: auto; font-weight: 400; }
#ops-list li button.disp {
  min-width: 34px; min-height: 34px; font-size: 14px; padding: 0;
  color: var(--dim); flex-shrink: 0;
}
#ops-list li button.disp.on { color: var(--accent); border-color: var(--accent); }
#ops-list li.body-row button.disp {
  min-width: 34px; min-height: 34px; font-size: 14px; padding: 0;
  color: var(--dim); flex-shrink: 0;
}
#ops-list li.body-row button.disp.on { color: var(--accent); border-color: var(--accent); }
#ops-list li.body-row.body-hidden > span { opacity: 0.4; }
#ops-list li.op-row { padding-left: 22px; }
#ops-list li.op-opts { display: flex; gap: 8px; padding: 8px 10px; cursor: default; }
#ops-list li.op-opts button { flex: 1; min-height: 42px; font-size: 13px; color: var(--dim); }
#ops-list li.op-opts button.on { border-color: var(--accent2); color: var(--accent2); background: #1e3a2a; }

#float3d {
  position: absolute; bottom: 18px; left: 50%; transform: translateX(-50%);
  display: flex; gap: 8px; z-index: 4; max-width: 96vw; overflow-x: auto;
  scrollbar-width: none;
}
#float3d.hidden { display: none; }
#float3d button { font-size: 14px; padding: 0 12px; white-space: nowrap; flex-shrink: 0; }
#btn-face-sketch {
  background: var(--accent); color: #0b1420; border-color: var(--accent);
  font-weight: 700;
}
#float3d button.on { border-color: var(--accent2); color: var(--accent2); background: #1e3a2a; }
#btn-measure-3d.on { border-color: var(--accent2); color: var(--accent2); background: #1e3a2a; }

#toast {
  pointer-events: none;
  position: fixed; bottom: calc(90px + env(safe-area-inset-bottom)); left: 50%;
  transform: translateX(-50%); z-index: 20;
  background: var(--panel2); border: 1px solid var(--line); color: var(--text);
  padding: 10px 16px; border-radius: 10px; font-size: 14px;
  transition: opacity 0.25s; white-space: nowrap;
}
#toast.hidden { opacity: 0; pointer-events: none; }

/* the ops+design drawer: left slide-over on phones (persistent sidebar
   on wide screens keeps its media-query styling) */
@media (max-width: 719.98px) {
  #opsheet {
    left: 0; right: auto; top: 0; bottom: 0;
    width: min(320px, 88vw); max-height: none;
    border-radius: 0 16px 16px 0;
    border-top: none; border-right: 1px solid var(--line);
    padding-top: calc(10px + env(safe-area-inset-top));
  }
}
#design-actions { display: flex; flex-wrap: wrap; gap: 6px; }
#design-actions .tb { flex: 1 0 30%; font-size: 13px; min-height: 40px; }
.drawer-sep {
  display: flex; align-items: center; gap: 8px; margin-top: 4px;
  color: var(--dim); font-size: 12px; text-transform: uppercase;
  letter-spacing: 0.06em;
}
#drawer-version { color: var(--dim); font-size: 11px; text-align: center; padding-top: 4px; }

.body-dot {
  width: 12px; height: 12px; border-radius: 50%;
  display: inline-block; flex-shrink: 0; align-self: center;
  border: 1px solid rgba(255, 255, 255, 0.25);
}
#body-colors { display: flex; gap: 8px; flex-wrap: wrap; padding: 4px 2px; }
#body-colors.hidden { display: none; }
#body-colors .swatch {
  width: 36px; height: 36px; min-width: 36px; min-height: 36px;
  border-radius: 50%; border: 2px solid var(--line); padding: 0;
}

#ops-foot-body { flex-wrap: wrap; }
#ops-foot-body .tb { flex: 1 0 28%; }

#ops-list li.body-row .twirl { border: none; background: transparent; font-size: 16px; }

/* ---------------------------------------------------------- AI chat panel */
#chat-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.45); z-index: 11; }
#chat-backdrop.hidden { display: none; }
#chatpanel {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 12;
  width: min(420px, 100vw);
  background: var(--panel); border-left: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 8px;
  padding: calc(10px + env(safe-area-inset-top)) 12px
           calc(10px + env(safe-area-inset-bottom) + var(--kb, 0px)) 12px;
  transition: padding-bottom 0.12s;
}
#chatpanel.hidden { display: none; }
@media (min-width: 720px) {
  #chatpanel { position: static; width: 320px; min-width: 320px; padding-top: 10px; }
  #chat-backdrop { display: none !important; }
}
#chat-settings { display: flex; flex-direction: column; gap: 6px;
  border: 1px solid var(--line); border-radius: 10px; padding: 10px; }
#chat-settings.hidden { display: none; }
#chat-settings label { color: var(--dim); font-size: 12px;
  display: flex; flex-direction: column; gap: 3px; }
#chat-settings input { background: var(--panel2); border: 1px solid var(--line);
  border-radius: 8px; color: var(--text); font-size: 16px; padding: 8px;
  user-select: text; -webkit-user-select: text; }
#chat-list { flex: 1; min-height: 0; overflow-y: auto;
  -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
  display: flex; flex-direction: column;
  gap: 8px; user-select: text; -webkit-user-select: text; }
.msg { max-width: 88%; padding: 8px 12px; border-radius: 14px;
  font-size: 14px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; }
.msg.u { align-self: flex-end; background: #20304a; border: 1px solid #2c4a74; }
.msg.a { align-self: flex-start; background: var(--panel2); border: 1px solid var(--line); }
.msg.streaming::after { content: "\258c"; opacity: 0.7; animation: blink 1s infinite; }
.msg.stopped { opacity: 0.7; }
@keyframes blink { 50% { opacity: 0.1; } }
.chat-chip { margin-top: 6px; font-size: 12px; min-height: 30px; min-width: 0;
  padding: 2px 10px; border-radius: 999px; color: var(--accent2);
  border-color: var(--accent2); background: #1e3a2a; }
.chat-chip.working { align-self: flex-start; color: var(--accent);
  border: 1px solid var(--accent); background: #20304a; }
.chat-chip.working.hidden { display: none; }
.chat-err { align-self: flex-start; color: var(--danger); font-size: 13px;
  border: 1px solid var(--danger); border-radius: 10px; padding: 8px 12px;
  max-width: 88%; white-space: pre-wrap; word-break: break-word; }
#chat-composer { display: flex; gap: 8px; align-items: flex-end; }
#chat-input { flex: 1; resize: none; background: var(--panel2);
  border: 1px solid var(--line); border-radius: 12px; color: var(--text);
  font-size: 16px; line-height: 1.4; padding: 10px 12px; max-height: 120px;
  user-select: text; -webkit-user-select: text; touch-action: auto;
  font-family: inherit; }
#chat-input:disabled { opacity: 0.5; }
#chat-send { min-width: 46px; min-height: 44px; }

#joints-list:empty::after {
  content: "no joints yet"; color: var(--dim); font-size: 12px;
  display: block; padding: 8px 10px;
}
#drive-ui {
  position: absolute; bottom: 18px; left: 14px; z-index: 4;
  display: flex; gap: 8px;
}
#drive-ui.hidden { display: none; }
#drive-chip {
  font-size: 14px; padding: 0 14px;
  color: var(--accent2); border-color: var(--accent2); background: #1e3a2a;
}
#drive-done { min-width: 46px; color: var(--accent2); border-color: var(--accent2); }

#axis-ui {
  position: absolute; bottom: 18px; left: 14px; z-index: 4;
}
#axis-ui.hidden { display: none; }
#axis-done {
  font-size: 14px; padding: 0 14px;
  color: var(--accent); border-color: var(--accent); background: #20304a;
}

/* live agent activity rows in the chat panel */
.chat-act {
  margin: 1px 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  line-height: 1.5;
  color: #98a0aa !important;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chat-act.pulse::after { content: " \2026"; animation: actpulse 1s infinite; }
@keyframes actpulse { 50% { opacity: 0.15; } }

/* agent render thumbnails in the activity feed */
.chat-act-imgs {
  display: flex;
  gap: 4px;
  margin: 2px 6px;
  overflow-x: auto;
}
.chat-act-imgs img {
  height: 76px;
  border-radius: 6px;
  border: 1px solid #3a3f47;
  background: #14171c;
  cursor: pointer;
}
#imgview {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.92);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
}
#imgview.hidden { display: none; }
#imgview img {
  max-width: 96vw;
  max-height: 92vh;
  border-radius: 8px;
}

/* photo attachments */
#chat-attach { display: flex; gap: 6px; padding: 2px 2px 0; }
#chat-attach.hidden { display: none; }
.chat-attach-thumb { position: relative; }
.chat-attach-thumb img { height: 56px; border-radius: 8px; border: 1px solid var(--line); display: block; }
.chat-attach-thumb button {
  position: absolute; top: -7px; right: -7px;
  width: 20px; height: 20px; border-radius: 10px; border: none;
  background: #b3403f; color: #fff; font-size: 13px; line-height: 20px; padding: 0;
}
#chat-photo { min-width: 44px; min-height: 44px; }
.msg-imgs { display: flex; gap: 4px; margin-top: 6px; flex-wrap: wrap; }
.msg-imgs img { height: 64px; border-radius: 6px; border: 1px solid var(--line); }

/* tap-to-inspect: body structure overlay in the 3D view */
#structover {
  position: fixed;
  left: 10px;
  top: 64px;
  z-index: 9;
  min-width: 156px;
  max-width: 250px;
  max-height: 55vh;
  overflow-y: auto;
  background: rgba(16, 20, 27, 0.62);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 8px;
  font-size: 12.5px;
}
#structover.hidden { display: none; }
.so-head { display: flex; justify-content: space-between; align-items: center;
  gap: 8px; font-weight: 600; margin: 0 2px 5px; }
.so-x { background: none; border: none; color: var(--dim); font-size: 17px;
  padding: 0 4px; line-height: 1; }
.so-row { padding: 5px 7px; border-radius: 8px; color: var(--dim);
  border: 1px solid transparent;
  display: flex; align-items: center; gap: 6px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* the label elides; the trailing control does not shrink away with it */
.so-lbl { flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* which sketches are drawn in 3D, readable down the list rather than one
   selection at a time — dim when off, lit when on, and tappable either way */
.so-eye3d {
  flex: 0 0 auto; min-width: 24px; min-height: 22px; padding: 0 3px;
  border: 1px solid transparent; background: none; border-radius: 6px;
  font-size: 11px; line-height: 1; opacity: 0.32; filter: grayscale(1);
}
.so-eye3d.on { opacity: 1; filter: none; border-color: #2c4a74; background: #1c3350; }
.so-eye3d:hover { opacity: 0.75; background: #232c3a; }
.so-eye3d.on:hover { opacity: 1; background: #24405f; }
.so-row.tap { color: var(--text); }
.so-row.hit { background: #1c3350; color: #cfe4ff; border-color: #2c4a74; }
#structov-row { display: flex; gap: 8px; align-items: center;
  color: var(--dim); font-size: 13px; margin-top: 8px; }

/* nested feature -> sketch rendering */
.op-row.indent { margin-left: 22px; opacity: 0.92; }
.so-row.so-ind { margin-left: 16px; }

/* progressive-construction preview chip */
#preview-chip {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(18px + env(safe-area-inset-bottom));
  z-index: 10;
  background: #3a2f16;
  border: 1px solid #8a6d2b;
  color: #ffd479;
  border-radius: 20px;
  padding: 9px 16px;
  font-size: 13.5px;
}
#preview-chip.hidden { display: none; }

/* design repository sheet */
#repo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px;
  overflow-y: auto;
  min-height: 0;
  color: var(--dim);
}
.repo-card {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.repo-thumb {
  height: 96px;
  border-radius: 8px;
  background: #14171c;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.repo-thumb img { width: 100%; height: 100%; object-fit: cover; }
.repo-title { color: var(--text); font-size: 13.5px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.repo-meta { font-size: 11.5px; color: var(--dim); }
.repo-actions { display: flex; gap: 6px; margin-top: 2px; }
.repo-actions .tb { flex: 1; min-height: 34px; font-size: 13px; }

/* image library + annotation editor */
#img-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 10px;
  overflow-y: auto;
  min-height: 0;
  color: var(--dim);
}
#annoview {
  position: fixed;
  inset: 0;
  background: rgba(8, 10, 14, 0.97);
  z-index: 300;
  overflow: hidden;
  touch-action: none;
}
#annoview.hidden { display: none; }
#anno-tools {
  position: absolute;
  top: calc(8px + env(safe-area-inset-top));
  left: 8px;
  right: 8px;
  display: flex;
  gap: 6px;
  z-index: 2;
}
#anno-tools { flex-wrap: wrap; }
#anno-tools .tb { min-height: 42px; flex: 1 0 20%; font-size: 13px; }
#anno-color { font-size: 20px; }
#anno-tools .tb.on { background: #1c3350; border-color: #2c4a74; color: #cfe4ff; }
#anno-canvas {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 0 0;
}

.sheet-foot { flex-wrap: wrap; }
.sheet-foot .tb { flex: 1 0 28%; }

/* redesigned drawer: list rows instead of button grids */
#drawer-rows { display: flex; flex-direction: column; gap: 4px; }
.drow {
  display: flex; align-items: center; gap: 12px;
  background: var(--panel2); border: 1px solid var(--line);
  border-radius: 12px; color: var(--text);
  min-height: 48px; padding: 0 14px; font-size: 15px; text-align: left;
}
.drow i { font-style: normal; width: 22px; text-align: center; opacity: 0.85; }
.drow em { margin-left: auto; font-style: normal; color: var(--dim); font-size: 13px; }
#drawer-tools { display: flex; gap: 10px; align-items: center; margin-top: 6px; }
/* the * reset zeroes padding, so a label wider than min-width sat flush
   against the button's own border */
#drawer-tools .tb { font-size: 13px; padding: 0 12px; }
.dl-act { margin-left: auto; display: flex; gap: 6px; }
.dl-act .tb { min-height: 34px; min-width: 38px; font-size: 13px; }

/* overlay = model navigator */
#structover { min-width: 226px; max-width: 268px; }
.so-head { gap: 6px; }
#so-body {
  flex: 1; min-width: 0; background: var(--panel2); color: var(--text);
  border: 1px solid var(--line); border-radius: 8px;
  font-size: 13.5px; padding: 7px 8px;
}
#so-bact { display: flex; flex-wrap: nowrap; gap: 4px; margin: 6px 0 2px;
  overflow-x: auto; -webkit-overflow-scrolling: touch; }
#so-bact::-webkit-scrollbar { display: none; }
#so-bact .tb { flex: 0 0 auto; min-width: 46px; min-height: 36px; font-size: 12px; padding: 0 10px; }
#so-oact { display: flex; flex-wrap: wrap; gap: 4px; margin: 6px 0 2px; }
#so-oact .tb { flex: 1 0 22%; min-height: 36px; font-size: 12px; padding: 0 4px; }
#so-bact .tb.on { background: #1c3350; border-color: #2c4a74; color: #cfe4ff; }
#so-list { max-height: 30vh; overflow-y: auto; min-height: 0; }
.so-row.sel { background: #223047; }

.so-sep { display: flex; align-items: center; gap: 8px; margin-top: 8px;
  color: var(--dim); font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.06em; }
.so-sep .tb { margin-left: auto; min-height: 32px; min-width: 40px; font-size: 14px; }
#structover #joints-list { list-style: none; margin: 2px 0; padding: 0; }
#structover #joint-types { display: flex; gap: 4px; }
#structover #joint-types.hidden { display: none; }
#structover #joint-types .tb { flex: 1; min-height: 34px; font-size: 12px; }
#structover .sheet-foot { margin-top: 4px; }
#structover .sheet-foot .tb { min-height: 36px; font-size: 12.5px; }

/* 3D mode: canvas owns the full height; contextual actions live in the overlay */
body.mode3d #hint { display: none; }
/* Sketch chrome is opt-IN per mode. Written positively so a new mode
   inherits nothing: "not 3D" used to mean "the sketch editor", which is
   how a third mode would silently acquire the sketch toolbar and the
   dimension-chip layer. */
#toolbar, #schbar, #pcbbar, #chips { display: none; }
body.mode-sketch #toolbar { display: flex; }
body.mode-sch #schbar { display: flex; }
body.mode-pcb #pcbbar { display: flex; }
#pcbbar .tool.toggle.on { border-color: var(--accent2); color: var(--accent2); background: #1e3a2a; }
#sch-count, #pcb-count { color: var(--dim); font-size: 12px; white-space: nowrap; }
/* tappable: each tap jumps the camera to one open connection */
#pcb-count { cursor: pointer; }
/* the stepped batch's one control: BIG, bottom centre, under the thumb —
   it gets tapped a hundred times in a row while the eyes stay on copper */
#pcb-step {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(20px + env(safe-area-inset-bottom));
  z-index: 20; min-width: 46vw; min-height: 60px;
  font-size: 21px; font-weight: 700; letter-spacing: 0.04em;
  border-radius: 16px; border: 1.5px solid var(--accent2);
  background: rgba(20, 40, 30, 0.22); color: var(--accent2);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
#pcb-step:active { background: #1e3a2a; }
#pcb-step.hidden, body:not(.mode-pcb) #pcb-step { display: none; }
/* the route all verdict, floating just above keep and discard — the
   numbers in view exactly where the decision is made */
#pcb-batchsum {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(92px + env(safe-area-inset-bottom));
  z-index: 20; padding: 8px 14px; border-radius: 10px;
  background: rgba(16, 20, 27, 0.25); border: 1px solid var(--line);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  color: var(--fg); font-size: 13px; line-height: 1.55;
  white-space: pre-line; text-align: center; max-width: 94vw;
}
#pcb-batchsum::first-line { font-weight: 700; font-size: 14.5px; }
#pcb-batchsum.hidden, body:not(.mode-pcb) #pcb-batchsum { display: none; }
/* the step's anatomy, floating just above the button */
#pcb-stepinfo {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(92px + env(safe-area-inset-bottom));
  z-index: 20; padding: 7px 13px; border-radius: 10px;
  background: rgba(16, 20, 27, 0.25); border: 1px solid var(--line);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  color: var(--fg); font-size: 12.5px; line-height: 1.55;
  white-space: pre-line; text-align: center; max-width: 94vw;
}
/* the net's name leads */
#pcb-stepinfo::first-line { font-weight: 700; font-size: 14px; }
#pcb-stepinfo.hidden, body:not(.mode-pcb) #pcb-stepinfo { display: none; }
/* the route decision, made with thumbs: keep right, discard left, both
   big at the bottom. They show when a preview awaits and the batch is
   done, so they never collide with the step button. Retry stays a bar
   chip — it is a knob, not a decision. */
/* ...and the same pair for arranging a body in 3D (#arr-*), because the
   decision has the same shape: this placement, or the one you started
   with. */
#pcb-keep, #pcb-discard, #arr-keep, #arr-discard {
  position: fixed; bottom: calc(20px + env(safe-area-inset-bottom));
  z-index: 20; width: 42vw; min-height: 60px;
  font-size: 20px; font-weight: 700; letter-spacing: 0.04em;
  border-radius: 16px;
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
}
#pcb-keep, #arr-keep {
  right: 5vw; left: auto;
  background: rgba(20, 40, 30, 0.22);
  border: 1.5px solid var(--accent2); color: var(--accent2);
}
#pcb-keep:active, #arr-keep:active { background: #1e3a2a; }
#pcb-discard, #arr-discard {
  left: 5vw; right: auto;
  background: rgba(42, 24, 26, 0.22);
  border: 1.5px solid #c05555; color: #e58f8f;
}
#pcb-discard:active, #arr-discard:active { background: #3a2323; }
#pcb-keep.hidden, #pcb-discard.hidden,
body:not(.mode-pcb) #pcb-keep, body:not(.mode-pcb) #pcb-discard { display: none; }
#arr-keep.hidden, #arr-discard.hidden,
body:not(.mode3d) #arr-keep, body:not(.mode3d) #arr-discard { display: none; }
/* what is being arranged, and how — floating just above the two buttons */
#arr-hint {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(92px + env(safe-area-inset-bottom));
  z-index: 20; padding: 7px 13px; border-radius: 10px;
  background: rgba(16, 20, 27, 0.35); border: 1px solid var(--line);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  color: var(--text); font-size: 12.5px; text-align: center;
  max-width: 92vw; white-space: nowrap; pointer-events: none;
}
#arr-hint.hidden, body:not(.mode3d) #arr-hint { display: none; }
#pcb-net { font-size: 12px !important; color: #ffe27a; border-color: #6b5a2a; background: #2c2617; }
/* one row per element class: swatch, name, on/off */
.lyr { display: flex; align-items: center; gap: 8px; height: 30px; width: 100%;
  background: transparent; border: none; color: var(--dim); font-size: 12px;
  text-align: left; padding: 0 4px; }
.lyr.on { color: var(--text); }
.lyr i { width: 14px; height: 3px; border-radius: 2px; flex: 0 0 auto;
  background: currentColor; opacity: 0.35; }
.lyr.on i { opacity: 1; }
.lyr em { margin-left: auto; font-style: normal; font-size: 11px; opacity: 0.7; }
.lyr-sep { color: var(--dim); font-size: 10px; text-transform: uppercase;
  letter-spacing: 0.06em; padding: 6px 4px 2px; }
body.mode-sketch #chips { display: block; }
.so-head .tb { min-height: 36px; min-width: 40px; font-size: 15px; }
.so-head .tb.on { border-color: var(--accent2); color: var(--accent2); background: #1e3a2a; }


/* 3D tool strip under the top bar */
#toolstrip {
  display: flex;
  gap: 6px;
  padding: 8px 10px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}
#toolstrip::-webkit-scrollbar { display: none; }
#toolstrip .tb { flex-shrink: 0; min-height: 40px; font-size: 13.5px; padding: 0 10px; }
#toolstrip.hidden { display: none; }
#btn-tools { display: none; }
body.mode3d #btn-tools {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
body:not(.mode3d) #toolstrip { display: none; }
#so-bact2 { display: flex; gap: 4px; }
#so-bact2.hidden { display: none; }
#so-bact2 .tb { flex: 1; min-height: 36px; font-size: 12px; }
#so-oact.hidden { display: none; }

/* strip pushes the overlay down instead of fighting it */
body.stripopen.mode3d #structover { top: 124px; }
#structover { max-height: calc(100dvh - 150px); overflow-y: auto; }
#btn-tools.on { border-color: var(--accent2); color: var(--accent2); background: #1e3a2a; }

#btn-done-sketch.hidden { display: none; }

#so-joints-sep.hidden { display: none; }

/* icon buttons: inline SVG, stroke inherits text color */
.tb.icon { display: inline-flex; align-items: center; justify-content: center; }
.tb.icon svg { width: 22px; height: 22px; fill: none; stroke: currentColor;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
#btn-tools { display: none; }
#btn-struct { display: inline-flex; align-items: center; justify-content: center; }
body.mode3d #btn-tools { display: inline-flex; }
#btn-struct.on { border-color: var(--accent2); color: var(--accent2); background: #1e3a2a; }
#toolstrip .tb.icon { min-width: 46px; }
/* a strip button that opens a panel stays lit while that panel is up */
#toolstrip .tb.on { background: #1c3350; border-color: #2c4a74; color: #cfe4ff; }

#tipbox {
  position: fixed;
  transform: translateX(-50%);
  background: rgba(22, 27, 36, 0.96);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 5px 11px;
  font-size: 12.5px;
  color: var(--text);
  z-index: 400;
  pointer-events: none;
  white-space: nowrap;
}
#tipbox.hidden { display: none; }

#btn-plane { color: var(--accent2); border-color: #2c4a3a; font-weight: 700; }
#btn-plane.hidden { display: none; }

/* chooser bars under the 3D tool strip: pick a sketch plane / joint type */
#sketch-planes, #joint-types, #carve-bodies {
  display: flex;
  gap: 6px;
  align-items: center;
  padding: 8px 10px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  color: var(--dim);
}
#sketch-planes.hidden, #joint-types.hidden, #carve-bodies.hidden { display: none; }
#sketch-planes .tb, #joint-types .tb, #carve-bodies .tb { flex: 1; min-height: 40px; }
body:not(.mode3d) #sketch-planes, body:not(.mode3d) #joint-types { display: none; }
/* #carve-bodies doubles as the sketch editor's chooser (import ref) */

#so-oact .tb.on { background: #1e3a2a; border-color: var(--accent2); color: var(--accent2); }

.so-row.warn { color: #e0b25a; }
.so-warn {
  margin: 0 6px 2px 22px;
  font-size: 11px;
  line-height: 1.45;
  color: #e0b25a;
  white-space: normal;
}

#btn-profile.okchip { color: var(--accent2); border-color: #2c4a3a; }
#btn-profile.warnchip { color: #e0b25a; border-color: #5a4a2b; }
#btn-profile.hidden { display: none; }

/* sketch navigator */
#sketchover {
  position: fixed;
  left: 10px;
  top: 124px;
  z-index: 9;
  min-width: 210px;
  max-width: 258px;
  max-height: 46dvh;
  overflow-y: auto;
  background: rgba(16, 20, 27, 0.62);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 8px;
  font-size: 12.5px;
}
#sketchover.hidden { display: none; }
.sv-det { margin: 0 4px 6px 14px; }
.sv-info { color: var(--dim); font-size: 11.5px; margin-bottom: 4px; }
.sv-act { display: flex; gap: 4px; }
.sv-act .tb { flex: 1; min-height: 34px; font-size: 12px; }
body:not(.mode-sketch) #sketchover { display: none; }

.sv-fix { width: 100%; margin-top: 6px; min-height: 40px;
  color: #e0b25a; border-color: #5a4a2b; font-size: 13px; }

/* FreeCAD icon set (LGPL — see icons/LICENSE.md) */
.fcicon {
  width: 27px;
  height: 27px;
  display: block;
  margin: auto;
  pointer-events: none;
}
#toolbar .tool .fcicon { width: 24px; height: 24px; }

/* ƒx parameters sheet + numpad expression editor */
#param-list, #attach-list { overflow-y: auto; flex: 1; display: flex; flex-direction: column; gap: 6px; }
.prow { display: flex; gap: 6px; align-items: stretch; }
.p-name {
  flex: 1.1; min-height: 48px; text-align: left; padding: 6px 10px;
  background: #1a2027; border: 1px solid var(--line); border-radius: 10px;
  color: var(--fg); font-weight: 700; font-size: 14px;
  overflow: hidden; text-overflow: ellipsis;
}
.p-val {
  flex: 1.6; min-height: 48px; padding: 4px 10px; text-align: right;
  background: #141a22; border: 1px solid var(--line); border-radius: 10px;
  color: var(--accent); font-size: 16px;
  display: flex; flex-direction: column; align-items: flex-end; justify-content: center;
}
.p-val small { color: var(--dim); font-size: 11px; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.p-val.err { border-color: #a04040; }
.p-val.err small { color: #e08a8a; }
.p-up, .p-del { min-width: 42px; }
.p-up:disabled { opacity: 0.3; }
.param-empty { color: var(--dim); font-size: 13px; padding: 18px 8px; text-align: center; }
#param-note { color: var(--dim); font-size: 11.5px; padding-top: 6px; }

#np-fx { margin-left: 8px; min-width: 46px; font-style: italic; }
#np-expr { display: flex; flex-direction: column; gap: 8px; }
#np-expr.hidden { display: none; }
#np-grid.hidden { display: none; }
#np-expr-in {
  width: 100%; min-height: 48px; padding: 8px 10px; font-size: 16px;
  font-family: ui-monospace, Menlo, monospace;
  background: #141a22; color: var(--fg);
  border: 1px solid var(--line); border-radius: 10px;
}
#np-expr-chips { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 2px; }
.np-chip {
  flex-shrink: 0; padding: 8px 12px; font-size: 13px; font-weight: 600;
  background: #20304a; color: var(--fg);
  border: 1px solid var(--line); border-radius: 999px;
}
.np-chip-hint { color: var(--dim); font-size: 12px; padding: 6px 2px; }
#np-expr-prev { min-height: 20px; font-size: 14px; color: var(--accent); text-align: right; }
#np-expr-prev.err { color: #e08a8a; font-size: 12px; }
#np-expr-btns { display: flex; gap: 8px; }
#np-expr-btns .tb { flex: 1; min-height: 48px; font-size: 16px; }

/* driven-dimension chips + sketch overlay dims section */
.chip.dim {
  border-color: #78aaff; color: #78aaff;
  font-size: 12.5px; padding: 4px 9px; border-radius: 10px;
}
.chip.err { border-color: #e05a5a; color: #e08a8a; }
.chip.pending { border-color: #e0b25a; color: #e0b25a; min-height: 40px; }
/* alignment constraints read as bars (FreeCAD's H/V markers), not text */
.chip.bar {
  background: transparent; border: none; color: #78aaff;
  font-size: 22px; font-weight: 800; line-height: 1; padding: 8px 10px;
  text-shadow: 0 0 3px rgba(16,20,27,0.95);
}
.chip.bar.err { color: #e05a5a; }
.sv-dimhdr { margin: 8px 4px 2px; font-weight: 700; letter-spacing: 0.04em; }

/* sketch attachment sheet (reuses .prow/.p-name/.p-val from params) */
#attach-bases { display: flex; gap: 6px; padding-bottom: 6px; }
#attach-bases .tb { flex: 1; }
#attach-bases .tb.on { border-color: var(--accent); color: var(--accent); background: #20304a; }
#attach-sub { color: var(--dim); font-weight: 400; font-size: 12px; margin-left: 6px; }
#attach-note { color: var(--dim); font-size: 11.5px; padding-top: 6px; }
#attach-note .attach-warn { color: #e0b25a; padding-top: 4px; }
#attach-list .p-name { flex: 1.5; display: flex; align-items: center; font-weight: 600; font-size: 13px; }

/* joint pose panel: mostly sliders, translucent, top-left under the strip.
   Mutually exclusive with the navigator, which shares that corner. */
#poseover, #animover, #pcblayers, #pcbnet, #pcbgroups, #pcbnets, #pcbsketches {
  position: fixed; left: 10px; top: 64px; z-index: 9;
  width: min(272px, 74vw); max-height: 44dvh; overflow-y: auto;
  background: rgba(16, 20, 27, 0.42);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border: 1px solid var(--line); border-radius: 12px; padding: 5px 7px 7px;
  font-size: 12px;
}
body.stripopen.mode3d #poseover, body.stripopen.mode3d #animover { top: 124px; }
#pcblayers, #pcbnet, #pcbgroups, #pcbnets, #pcbsketches { top: 64px; }
/* the net-rules panel sits right of the layers panel, so both can be open */
#pcbnet, #pcbgroups, #pcbnets, #pcbsketches { left: auto; right: 10px; }
#poseover.hidden, #animover.hidden, #pcblayers.hidden, #pcbnet.hidden,
#pcbgroups.hidden, #pcbnets.hidden, #pcbsketches.hidden { display: none; }
body:not(.mode3d) #poseover, body:not(.mode3d) #animover { display: none; }
body:not(.mode-pcb) #pcblayers, body:not(.mode-pcb) #pcbnet,
body:not(.mode-pcb) #pcbgroups, body:not(.mode-pcb) #pcbnets, body:not(.mode-pcb) #pcbsketches { display: none; }
.pose-top {
  display: flex; align-items: center; gap: 6px; color: var(--dim);
  text-transform: uppercase; letter-spacing: 0.06em; font-size: 10.5px;
  padding-bottom: 2px;
}
.pose-top .tb {
  min-height: 26px; min-width: 30px; font-size: 11px; padding: 0 7px;
  background: transparent;
}
.pose-top #pose-zero, .pose-top #anim-total { margin-left: auto; }
/* capture / play sit on their own row: at 272px the header can't hold both */
.anim-bar { display: flex; gap: 5px; padding: 1px 0 4px; }
.anim-bar .tb { flex: 1; min-height: 32px; font-size: 12px; }
.anim-bar .tb.narrow { flex: 0 0 auto; padding: 0 9px; }
.anim-bar.hidden { display: none; }
.anim-bar .tb.on { background: #3a2230; border-color: #6d3b52; color: #ffd8e6; }
.anim-bar .tb:disabled { opacity: 0.4; }
.anim-row .pose-name { max-width: 34px; }
.anim-row .pose-val:disabled { opacity: 0.45; }
/* the wide hit target on a step row is "jump to this pose" */
.anim-go {
  flex: 1; min-width: 0; min-height: 26px; padding: 0 6px; text-align: left;
  font-size: 11.5px; background: transparent; border-color: transparent;
  color: var(--fg);
}
/* one line per joint: label · slider · value */
.pose-row { display: flex; align-items: center; gap: 5px; height: 32px; }
.pose-name {
  flex: 0 0 auto; max-width: 76px; min-width: 0; min-height: 26px;
  padding: 0 4px; font-size: 11px; color: var(--dim);
  background: transparent; border: none; text-align: left;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pose-val {
  flex: 0 0 auto; min-width: 46px; min-height: 26px; padding: 0 5px;
  font-size: 11.5px; background: transparent;
  color: var(--accent2); border-color: transparent;
}
.pose-expand { padding: 0 2px 6px; }
.pose-sub { display: block; color: var(--dim); font-size: 10.5px; padding: 0 2px 3px; }
.pose-edit { display: flex; gap: 5px; }
.pose-edit .tb { flex: 1; min-height: 32px; font-size: 11.5px; }
.pose-empty { color: var(--dim); padding: 8px 4px; font-size: 11.5px; }
/* the app's first range input — iOS needs the appearance reset; the thumb
   stays finger-sized while the row stays short */
.pose-slider {
  -webkit-appearance: none; appearance: none;
  flex: 1; min-width: 0; height: 30px; margin: 0; background: transparent;
  touch-action: none;
}
.pose-slider::-webkit-slider-runnable-track {
  height: 4px; border-radius: 2px; background: rgba(120, 135, 160, 0.45);
}
.pose-slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 22px; height: 22px; margin-top: -9px; border-radius: 50%;
  background: var(--accent2); border: 1px solid #12301f;
}
.pose-slider::-moz-range-track { height: 4px; border-radius: 2px; background: rgba(120,135,160,0.45); }
.pose-slider::-moz-range-thumb {
  width: 22px; height: 22px; border-radius: 50%; border: 1px solid #12301f;
  background: var(--accent2);
}
.pose-slider:disabled::-webkit-slider-thumb { background: var(--dim); }

/* ---- copy-from-design sheet */
#copy-list { overflow: auto; max-height: 70dvh; }
#copy-list .copy-note { padding: 10px 14px; color: #8a94a6; font-size: 13px; }

/* ---- board bottom status line */
#pcb-status {
  position: fixed; left: 10px; right: 10px; bottom: calc(8px + env(safe-area-inset-bottom));
  z-index: 30; pointer-events: none; text-align: center;
  font-size: 12px; color: #aeb9c9; text-shadow: 0 1px 3px rgba(0,0,0,0.8);
}

/* ==========================================================================
   DESKTOP
   --------------------------------------------------------------------------
   Everything from here down is scoped to >=1024px and to a real pointer.
   Nothing above this line was changed for the desktop work, so the phone
   build renders from exactly the CSS it always did.

   What a mouse and a 1920px window change, in order of how much they hurt:
     1. the four editors were never NAMED — you arrived in one and left it
        by a "back" button. Now they are tabs.
     2. one nowrap scroll strip held 34 board buttons. At 1920px two of
        them were still off the right edge, behind a hidden scrollbar.
        Now the bar wraps into labelled groups and nothing hides.
     3. the drawer showed every row in every section: board rip-up passes
        sat under a sketch. Now each group belongs to a section.
     4. panels were position:fixed at left:10px — i.e. UNDER the sidebar
        they predate. They are stage-relative now.
     5. 44px touch targets and no hover state at all.
   ========================================================================== */
@media (min-width: 1024px) {
  /* ---------------------------------------------------------- top bar */
  #topbar { padding: 6px 12px; gap: 8px; }
  #doc-name { display: block; max-width: 240px; }
  /* One panel, one button to open it. The model tree lives INSIDE that
     panel now, so its own button was a second door onto the same room —
     it stays in the DOM and keeps working at phone widths, where the
     navigators really are separate floating overlays. */
  #btn-menu { order: -2; }
  #btn-struct { display: none; }

  /* the four editors, named and always visible */
  #wstabs {
    display: flex; gap: 2px; padding: 3px;
    background: var(--bg); border: 1px solid var(--line); border-radius: 10px;
  }
  .wst {
    min-width: 86px; min-height: 30px; padding: 0 12px;
    border: none; background: transparent; color: var(--dim);
    border-radius: 7px; font-size: 13px; font-weight: 600;
  }
  .wst:hover { background: var(--panel2); color: var(--text); }
  .wst.on { background: var(--accent); color: #0b1420; }
  .wst.on:hover { background: var(--accent); }
  .wst:disabled { opacity: 0.3; cursor: default; }
  .wst:disabled:hover { background: transparent; color: var(--dim); }
  /* the tabs are the way between sections now */
  #sch-back, #pcb-back { display: none; }
  /* "done" is a sketch action, not a fifth tab — keep it off the group */
  #btn-done-sketch { margin-left: 14px; }

  /* ------------------------------------------------- grouped toolbars */
  /* Groups wrap as whole units. The label is absolutely positioned above
     its own group, which is why the bar carries the extra top padding and
     the generous row-gap: a wrapped second row needs room for its labels. */
  #toolbar, #schbar, #pcbbar, #toolstrip {
    flex-wrap: wrap; overflow: visible;
    justify-content: flex-start; align-items: flex-start;
    gap: 0; row-gap: 20px; padding: 20px 12px 7px;
  }
  #toolbar .tgroup, #schbar .tgroup, #pcbbar .tgroup, #toolstrip .tgroup {
    display: inline-flex; gap: 4px; align-items: center;
    padding: 0 11px; border-left: 1px solid var(--line); position: relative;
  }
  #toolbar > .tgroup:first-child, #schbar > .tgroup:first-child,
  #pcbbar > .tgroup:first-child, #toolstrip > .tgroup:first-child {
    border-left: none; padding-left: 0;
  }
  .tgroup::before {
    content: attr(data-g);
    position: absolute; left: 11px; top: -14px;
    font-size: 9.5px; letter-spacing: 0.09em; text-transform: uppercase;
    color: var(--dim); opacity: 0.75; white-space: nowrap; pointer-events: none;
  }
  #toolbar > .tgroup:first-child::before, #schbar > .tgroup:first-child::before,
  #pcbbar > .tgroup:first-child::before, #toolstrip > .tgroup:first-child::before {
    left: 0;
  }
  /* a group whose every button is contextual collapses instead of leaving
     a labelled hole — "edit" and "make" are empty until something is picked */
  .tgroup:not(:has(> :not(.hidden))) { display: none !important; }
  /* the groups draw the separation now */
  #toolbar .divider, #schbar .divider, #pcbbar .divider { display: none; }

  /* AI, undo and redo are moved by placeBarLeft() into the LEFT of
     whichever mode bar is showing — down where the tools are, instead of
     three icons in the opposite corner from everything they act on. */
  #barleft {
    display: inline-flex; gap: 4px; align-items: center;
    padding-right: 11px; border-right: 1px solid var(--line);
  }
  #topbar #barleft { padding-right: 0; border-right: none; } /* if it is still up there */
  #barleft .tb { min-height: 34px; min-width: 36px; font-size: 15px; padding: 0 10px; }

  /* The 3D operations were behind a toggle because a phone bar cannot hold
     them. A 1920px window can: the strip is simply up, and its toggle —
     which now toggles nothing — goes away. */
  body.mode3d #toolstrip { display: flex !important; }
  body.mode3d #btn-tools { display: none !important; }

  /* desktop control sizing: a mouse does not need a 52px target */
  #toolbar .tool, #schbar .tool, #pcbbar .tool {
    min-width: 34px; min-height: 34px; font-size: 13px; padding: 0 9px;
  }
  #toolbar .tool .fcicon, #pcbbar .tool .fcicon { width: 20px; height: 20px; }
  #toolstrip .tb { min-height: 34px; }
  #toolstrip .tb.icon { min-width: 38px; }
  #toolstrip .fcicon { width: 22px; height: 22px; }
  /* the * reset zeroes padding, so a text label sat flush against its
     own border — "✓ done" rendered as "✓done" */
  #topbar .tb { min-height: 34px; min-width: 36px; font-size: 15px; padding: 0 10px; }

  /* --------------------------------------------------- the side menu */
  #opsheet { width: 292px; min-width: 292px; padding: 10px 10px 8px; }
  /* the design name is in the top bar here, so the sidebar's copy of it
     is just the same words twice; the head keeps only its ✕ */
  #opsheet .sheet-head { font-size: 13px; color: var(--dim); padding: 0 2px 2px;
    min-height: 0; }
  #drawer-title { display: none; }
  #doc-name { cursor: pointer; }
  #doc-name:hover { color: var(--text); }

  /* ---- one left panel: the tree on top, the menu folded up beneath it.
     Two panels stacked in the same corner read as two of the same thing;
     the navigator is the live half (it follows what you tap) and the menu
     is the occasional half, so the live half gets the room and the rest
     collapses. The navigators are MOVED here by placeNav() and moved back
     out below 1024px, where they stay the floating overlays they were. */
  #opsheet #structover, #opsheet #sketchover {
    position: static; left: auto; top: auto; right: auto;
    width: auto; min-width: 0; max-width: none;
    /* Sized by its content and never scrolled on its own: the PANEL
       scrolls, as one document. Giving the tree its own scroll region
       inside the panel's meant it got squeezed by whatever the menu
       wanted and cut a row of buttons in half. */
    flex: 0 0 auto; min-height: 0; max-height: none; overflow: visible;
    background: none; border: none; border-radius: 0;
    -webkit-backdrop-filter: none; backdrop-filter: none;
    padding: 0 0 8px; margin-bottom: 4px;
    border-bottom: 1px solid var(--line);
  }
  /* the panel has one ✕ of its own; the overlays' own closers would be a
     second way to dismiss the same thing */
  #opsheet #so-close, #opsheet #sv-close { display: none; }
  #opsheet #so-list { max-height: none; }
  /* nothing docked to inspect: the menu takes the whole panel */
  body.mode-sch #opsheet #structover, body.mode-pcb #opsheet #structover { display: none; }

  /* One scrollbar for the whole panel, rather than a scroll region per
     section fighting over the height. Overrides the >=720px rule that
     made the rows the only scroller back when they were the only thing
     in here. */
  #opsheet { overflow-y: auto; }
  #drawer-rows { gap: 0; flex: 0 0 auto; overflow: visible; min-height: 0; }
  .dgroup { display: flex; flex-direction: column; gap: 3px; padding-bottom: 6px; }
  .dgh {
    display: flex; align-items: center; gap: 6px;
    background: none; border: none; padding: 6px 4px 4px; width: 100%;
    min-height: 0; min-width: 0; text-align: left;
    font-size: 9.5px; letter-spacing: 0.09em; text-transform: uppercase;
    color: var(--dim); opacity: 0.75;
  }
  .dgh:hover { opacity: 1; color: var(--text); background: none; }
  .dgh::before { content: "\25be"; font-size: 11px; line-height: 1; opacity: 0.8; }
  .dgroup.collapsed .dgh::before { content: "\25b8"; }
  .dgroup.collapsed > :not(.dgh) { display: none !important; }
  .drow { min-height: 36px; font-size: 13.5px; gap: 10px; padding: 0 11px; border-radius: 9px; }
  .drow i { width: 18px; }
  .drow em { font-size: 12px; }
  .drow:hover { background: #2c3542; border-color: #4b566b; }

  /* each group belongs to a section. The tabs replaced the two jump rows. */
  .dgroup[data-sec="jump"] { display: none; }
  body:not(.mode-pcb) .dgroup[data-sec="board"] { display: none; }
  body.mode-pcb .dgroup[data-sec="model"],
  body.mode-sch .dgroup[data-sec="model"] { display: none; }

  /* ------------------------------------------- panels dock to the stage */
  /* These were position:fixed at left:10px, which on a desktop put them
     UNDERNEATH the 264px sidebar — the model tree covered "new design".
     Every one of them is already a child of #stage, so making them
     stage-relative clears the sidebar and the toolbars for free. */
  #structover, #sketchover, #poseover, #animover,
  #pcblayers, #pcbnet, #pcbgroups, #pcbnets, #pcbsketches {
    position: absolute; top: 10px; max-height: calc(100% - 20px);
  }
  #structover, #sketchover, #poseover, #animover, #pcblayers { left: 10px; right: auto; }
  #pcbnet, #pcbgroups, #pcbnets, #pcbsketches { left: auto; right: 10px; }
  /* the tool strip no longer needs to push anything down */
  body.stripopen.mode3d #structover, body.stripopen.mode3d #poseover,
  body.stripopen.mode3d #animover { top: 10px; }
  #structover { min-width: 250px; max-width: 320px; font-size: 12.5px; }
  /* the body actions scroll sideways on a phone because the panel is
     narrow and the screen is short. Here there is height to spare, so
     they wrap and "dup / name / del" stop hiding past the right edge. */
  #so-bact { flex-wrap: wrap; overflow-x: visible; }
  /* the phone gives these a 22% basis so four fill the row; here that
     left the fifth wrapping alone and stretching the whole width */
  #so-oact .tb { flex: 0 1 auto; padding: 0 10px; }
  #sketchover { max-height: calc(100% - 20px); }
  #poseover, #animover, #pcblayers, #pcbnet,
  #pcbgroups, #pcbnets, #pcbsketches { width: 280px; }

  /* ------------------------------------------ sheets become dialogs */
  /* A bottom sheet spanning 1920px to hold two fields is a phone idiom
     stretched past its meaning. #opsheet is excluded: it is the docked
     sidebar here, and is still position:static. */
  .sheet:not(#opsheet) {
    top: 50%; left: 50%; right: auto; bottom: auto;
    transform: translate(-50%, -50%);
    width: min(680px, 90vw); max-height: 84vh;
    border: 1px solid var(--line); border-radius: 14px;
    padding: 14px 16px;
    box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);
  }
  #reposheet, #imgsheet { width: min(940px, 92vw); }
  #numpad { width: min(340px, 90vw); }
  #copy-list { max-height: none; }

  /* ------------------------------------------------- thumb-sized buttons */
  /* route-all's verdict buttons are sized for a thumb at the bottom of a
     phone. A mouse wants them near the work, not 46vw wide. */
  #pcb-step { min-width: 200px; min-height: 46px; font-size: 17px; bottom: 24px; }
  #pcb-keep, #pcb-discard, #arr-keep, #arr-discard {
    width: 170px; min-height: 46px; font-size: 17px; bottom: 24px;
  }
  #pcb-keep, #arr-keep { right: calc(50% - 180px); }
  #pcb-discard, #arr-discard { left: calc(50% - 180px); }
  #pcb-batchsum, #pcb-stepinfo, #arr-hint { bottom: 80px; }

  /* --------------------------------------------------------- hover */
  button:hover { background: #313a47; }
  .tb.accent:hover, button.accent:hover { background: var(--accent); filter: brightness(1.08); }
  .tb.danger:hover, button.danger:hover { background: #3a2626; }
  #toolbar .tool:hover, #schbar .tool:hover, #pcbbar .tool:hover,
  #toolstrip .tb:hover { border-color: #5d687e; }
  .so-row:hover { background: #1e2635; color: var(--text); }
  .lyr:hover { color: var(--text); }
  #design-list li:hover, #ops-list li:hover { background: #232c3a; }
  .repo-card:hover { border-color: #4b566b; }
  button:disabled:hover { background: var(--panel2); }

  /* the canvas says what it is: draw here, orbit there */
  body.mode-sketch #c2d { cursor: crosshair; }
  body.mode-sketch #c2d.grabbing { cursor: grabbing; }
  body.mode3d #c3d { cursor: grab; }
  body.mode-sch #c2d, body.mode-pcb #c2d { cursor: default; }

  /* the AI rail earns a little more room when the window can spare it */
  #chatpanel { width: 360px; min-width: 360px; }
}

/* a hover tooltip is a mouse affordance; the long-press one stays for touch */
@media (hover: hover) and (pointer: fine) {
  #tipbox { font-size: 12px; padding: 4px 10px; }
}
