:root{
  --bg-0:#1b1e23;
  --bg-1:#22262c;
  --bg-2:#2a2f37;
  --bg-3:#333944;
  --border:#3b414c;
  --text-0:#e8eaed;
  --text-1:#a7adb8;
  --text-2:#6d7480;
  --accent:#5b8def;
  --accent-dim:#3a5fa8;
  /* The accent at a whisper -- the background behind a tool that is running.
     Solid --accent-dim is still used where a control is a filled button. */
  --accent-soft:rgba(91,141,239,.16);
  --danger:#e35b5b;
  --ok:#4caf7d;
  --warn:#e0a94c;
  --overlay-bg:rgba(24,27,32,.92);
  /* Body-text links. NOT --accent: that is tuned for buttons and solid fills,
     and at #5b8def it measures only 3.23:1 on the light theme's background --
     below the 4.5:1 WCAG AA needs for normal text. These two are picked per
     theme to clear it: 7.93:1 here, 6.41:1 in light. Before this existed the
     legal pages had no link colour at all and fell back to the browser
     defaults -- #0000EE unvisited (1.78:1) and #551A8B once visited, which is
     what made them unreadable on a dark background. */
  --link:#8ab4f8;
  --link-hover:#b3cffb;
  --radius:6px;
  /* Icon size preference (Preferences > Icon size). Every icon box, and the
     button/label that has to grow with it, is written as
     calc(<base>px * var(--icon-scale)) so one number moves all of them --
     see src/iconSize.js, which overwrites this on <html> at load. Declared
     here so the stylesheet still renders correctly at 1x on its own. */
  --icon-scale:1;
  font-family: "Segoe UI", -apple-system, BlinkMacSystemFont, sans-serif;
}

:root[data-theme="light"]{
  --bg-0:#eef0f3;
  --bg-1:#ffffff;
  --bg-2:#f5f6f8;
  --bg-3:#e6e9ee;
  --border:#d7dbe1;
  --text-0:#1b1e23;
  --text-1:#565e6b;
  --text-2:#8791a0;
  --accent:#3b6fd6;
  --accent-dim:#5a86e0;
  --accent-soft:rgba(59,111,214,.12);
  --danger:#d3453f;
  --ok:#2f9e63;
  --warn:#c98a2c;
  --overlay-bg:rgba(255,255,255,.9);
  --link:#1550b8;
  --link-hover:#0f3f96;
}

*{box-sizing:border-box;}
html,body{height:100%;margin:0;background:var(--bg-0);color:var(--text-0);font-size:13px;overflow:hidden;}
/* Site pages scale up on big monitors; --page-zoom comes from page-zoom.js
   (1 everywhere it isn't loaded). Deliberately NOT the editor's plain <body>. */
body.home-body,body.docs-body,body.dashboard-body,body.auth-body{zoom:var(--page-zoom, 1);}

#app{height:100%;display:flex;flex-direction:column;}

/* ---------- Top bar ---------- */
/* Height is 44px until the icon-size preference pushes the Undo/Redo buttons
   past what a 44px bar can hold, then it grows exactly in step with them
   (30px button + 14px of breathing room is where the original 44 came from).
   max(), not a plain calc: shrinking icons should not drag the brand, the
   document title and the account button up into a cramped bar with them. */
#topbar{
  height:max(44px, calc(30px * var(--icon-scale) + 14px));flex:0 0 auto;
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:14px;
  background:var(--bg-1);border-bottom:1px solid var(--border);padding:0 12px;
  -webkit-app-region:drag;
}
.topbar-left{display:flex;align-items:center;gap:14px;min-width:0;}
.topbar-right{display:flex;align-items:center;justify-content:flex-end;gap:10px;min-width:0;}
/* Extra right-side padding/margin (vs the 6px on every other side) so the
   hover highlight box actually reaches past the logo image to cover the
   (TM) badge overlaid outside it -- otherwise the badge visibly pokes out
   past the highlight's right edge on hover. */
.brand{font-weight:600;font-size:14px;display:flex;align-items:center;gap:8px;color:var(--text-0);text-decoration:none;border-radius:var(--radius);padding:4px 10px 4px 6px;margin:-4px -10px -4px -6px;flex-shrink:0;}
.brand:hover{background:var(--bg-3);color:var(--text-0);}
.brand-logo{height:30px;width:auto;display:block;flex-shrink:0;}
/* The wordmark PNG is white text for the dark theme -- swap in the
   black-text variant in light mode so it stays readable (the blue/orange
   logomark itself is unchanged between the two files). */
:root[data-theme="light"] .brand-logo{content:url(logo-full-light.png);}

/* Trademark badge next to every CoreShape wordmark -- the logo is a raster
   PNG (no editable text layer), so the (TM) mark is overlaid in CSS via a
   wrapper around the <img> rather than baked into the image asset. */
.brand-logo-wrap{position:relative;display:inline-flex;flex-shrink:0;}
.brand-tm{
  position:absolute;top:0;right:-4px;font-size:6px;font-weight:700;
  color:var(--text-2);line-height:1;user-select:none;pointer-events:none;
}
.top-actions{display:flex;align-items:center;gap:6px;}
.tb-btn{
  background:transparent;border:1px solid transparent;color:var(--text-1);
  padding:6px 10px;border-radius:var(--radius);cursor:pointer;font-size:12px;
}
.tb-btn:hover{background:var(--bg-3);color:var(--text-0);border-color:var(--border);}
.tb-btn:active{background:var(--accent-dim);}
.tb-sep{flex:0 0 1px;height:22px;background:var(--border);margin:0 4px;}
.doc-title-group{
  justify-self:center;display:flex;align-items:baseline;gap:8px;min-width:0;max-width:100%;
}
.doc-title{
  color:var(--text-2);font-size:12px;padding:4px 8px;border-radius:var(--radius);
  cursor:default;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;
  -webkit-app-region:no-drag;
}
.doc-title:hover{background:var(--bg-3);color:var(--text-1);}
.last-saved{
  color:var(--text-3, var(--text-2));font-size:11px;white-space:nowrap;opacity:0.7;
  -webkit-app-region:no-drag;
}
.view-only-badge{
  background:rgba(224,169,76,.18);color:#e0a94c;font-size:11px;font-weight:600;
  padding:3px 9px;border-radius:999px;white-space:nowrap;-webkit-app-region:no-drag;
}
.view-only-badge.hidden{display:none;}

.user-profile{
  display:flex;align-items:center;gap:8px;background:transparent;border:1px solid transparent;
  border-radius:999px;padding:4px 10px 4px 4px;cursor:pointer;-webkit-app-region:no-drag;
}
.user-profile:hover{background:var(--bg-3);border-color:var(--border);}
.user-avatar{
  width:24px;height:24px;flex-shrink:0;border-radius:50%;background:var(--accent);color:#fff;
  display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;
}
.user-name{color:var(--text-0);font-size:12.5px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:140px;}
.user-plan{
  font-size:10.5px;font-weight:700;letter-spacing:.02em;text-transform:uppercase;
  padding:3px 8px;border-radius:999px;flex-shrink:0;
}
.user-plan.hidden{display:none;}
.user-plan-free{background:var(--bg-3);color:var(--text-1);}
.user-plan-standard{background:color-mix(in srgb, var(--accent) 18%, transparent);color:var(--accent);}
.user-plan-pro{background:color-mix(in srgb, #e0a94c 20%, transparent);color:#e0a94c;}
.doc-title-input{
  background:var(--bg-0);border:1px solid var(--accent);color:var(--text-0);
  font-size:12px;font-family:inherit;padding:2px 5px;border-radius:4px;width:160px;outline:none;
}

.tb-icon-btn{
  width:calc(30px * var(--icon-scale));height:calc(30px * var(--icon-scale));
  display:flex;align-items:center;justify-content:center;
  background:transparent;border:1px solid transparent;color:var(--text-1);
  padding:calc(5px * var(--icon-scale));border-radius:var(--radius);cursor:pointer;
}
/* These two never had a size of their own -- the <i> was left inline and the
   svg inside it fell back to whatever the flex box gave it. That's fine at a
   fixed 30px button but doesn't scale, so state it, the way every other icon
   context here already does. */
.tb-icon-btn i{
  width:calc(18px * var(--icon-scale));height:calc(18px * var(--icon-scale));
  display:block;flex:0 0 auto;
}
.tb-icon-btn:hover:not(:disabled){background:var(--bg-3);color:var(--text-0);}
.tb-icon-btn:disabled{opacity:.3;cursor:not-allowed;}

.tb-menu-section{padding:6px 10px;}
.tb-menu-row{display:flex;align-items:center;justify-content:space-between;gap:14px;font-size:12px;color:var(--text-1);cursor:default;}
/* A settings label with a small "i" beside it. The badge is a real <button>
   so it is reachable by keyboard and, on a touchscreen, by tapping -- a
   hover-only tooltip would be invisible on the phones this particular setting
   is most likely to be read on. */
.tb-label-info{display:inline-flex;align-items:center;gap:6px;position:relative;}
.tb-info{
  width:14px;height:14px;flex:0 0 auto;border-radius:50%;padding:0;
  border:1px solid var(--border);background:var(--bg-0);color:var(--text-2);
  font:700 9px/1 inherit;font-family:inherit;
  display:inline-flex;align-items:center;justify-content:center;cursor:help;
}
.tb-info:hover, .tb-info:focus{background:var(--accent);border-color:var(--accent);color:#fff;outline:none;}
.tb-info::after{
  content:attr(data-tip);
  /* Anchored by its RIGHT edge, so it opens leftward into the menu rather
     than outward past the screen. The Preferences menu sits at the right of
     the toolbar, so left-anchoring pushed the tooltip off-screen entirely on
     a narrow window. */
  position:absolute;right:0;top:calc(100% + 8px);z-index:60;
  width:min(250px, 62vw);padding:8px 10px;border-radius:6px;
  background:var(--bg-0);border:1px solid var(--border);color:var(--text-1);
  font:400 11px/1.45 inherit;font-family:inherit;text-align:left;
  white-space:normal;box-shadow:0 8px 24px rgba(0,0,0,.4);
  opacity:0;visibility:hidden;pointer-events:none;transition:opacity .12s ease;
}
.tb-info:hover::after, .tb-info:focus::after{opacity:1;visibility:visible;}

.tb-menu-row select, .tb-menu-row input[type="number"]{
  background:var(--bg-0);border:1px solid var(--border);color:var(--text-0);
  padding:4px 6px;border-radius:4px;font-size:12px;width:70px;font-family:inherit;
}
.tb-menu-row input[type="range"]{width:100px;}
/* Live readout beside a slider. Fixed width and tabular figures so the row
   doesn't shuffle sideways as the number changes while you drag. */
.tb-menu-value{
  flex:0 0 auto;width:38px;text-align:right;color:var(--text-2);
  font-size:11px;font-variant-numeric:tabular-nums;
}
/* The one slider row that carries a readout needs the extra room taken out of
   the slider, not added to the menu's width. */
.tb-menu-row.has-value input[type="range"]{width:78px;}
.tb-menu-sep{height:1px;background:var(--border);margin:4px 6px;}
.tb-menu-kbd{margin-left:auto;padding-left:16px;color:var(--text-2);font-size:10.5px;}

.seg-toggle{display:flex;background:var(--bg-0);border:1px solid var(--border);border-radius:6px;padding:2px;}
.seg-toggle button{
  background:transparent;border:none;color:var(--text-1);padding:4px 10px;border-radius:4px;
  font-size:11.5px;cursor:pointer;
}
.seg-toggle button.active{background:var(--accent);color:#fff;}

/* ---------- Sketch + Create toolbar ---------- */
#tool-toolbar{
  flex:0 0 auto;display:flex;align-items:flex-start;gap:0;
  background:var(--bg-1);border-bottom:1px solid var(--border);
  padding:4px 8px;overflow-x:auto;
}
.tt-group{display:flex;flex-direction:column;flex:0 0 auto;}
/* The group headers are the toolbar's only structure once the icons get
   busier, so they are set a step larger and wider-tracked than a caption
   would normally be, and the separators carry more air than the 1px line
   alone implies. */
.tt-label{font-size:calc(9px * var(--icon-scale));letter-spacing:.14em;color:var(--text-1);font-weight:700;padding:0 3px 3px;opacity:.85;}
.tt-row{display:flex;gap:1px;}
/* flex:0 0 1px, not width:1px -- the ribbon overflows horizontally on narrow
   windows, and a shrinkable 1px flex item is the first thing the layout
   crushes to zero, silently deleting every group divider. */
.tt-sep{flex:0 0 1px;align-self:stretch;background:var(--border);margin:2px 9px;}
.tt-hint{font-size:calc(9px * var(--icon-scale));color:var(--text-2);padding:3px 2px 0;max-width:220px;line-height:1.25;}

.constraint-btn{
  width:calc(24px * var(--icon-scale));height:calc(24px * var(--icon-scale));flex:0 0 auto;display:flex;align-items:center;justify-content:center;
  background:transparent;border:1px solid var(--border);color:var(--text-1);
  border-radius:6px;cursor:pointer;font-size:12px;font-weight:600;
}
.constraint-btn:hover:not(:disabled){background:var(--bg-3);color:var(--text-0);border-color:var(--accent);}
.constraint-btn:disabled{opacity:.3;cursor:not-allowed;}
.constraint-btn.active{background:var(--accent-dim);color:#fff;border-color:var(--accent);}
.constraint-btn i{width:calc(14px * var(--icon-scale));height:calc(14px * var(--icon-scale));display:block;}

/* Wrapper participates in the parent .tt-row as if unwrapped (display:contents),
   so its buttons sit inline with "Create Sketch" until toggled fully hidden. */
.sketch-draw-tools{display:contents;}
.tt-hide{display:none !important;}

.tool-btn{
  width:100%;display:flex;flex-direction:column;align-items:center;gap:2px;
  background:transparent;border:1px solid transparent;color:var(--text-1);
  padding:5px 1px;border-radius:var(--radius);cursor:pointer;margin-bottom:2px;
}
.tool-btn span{font-size:calc(8.5px * var(--icon-scale));line-height:1.1;text-align:center;}
.tool-btn i{width:calc(18px * var(--icon-scale));height:calc(18px * var(--icon-scale));display:block;}
.tool-btn:hover:not(:disabled){background:var(--bg-3);color:var(--text-0);}
.tool-btn.active{background:var(--accent-dim);color:#fff;border-color:var(--accent);}
.tool-btn:disabled{opacity:.3;cursor:not-allowed;}

.icon-svg{width:100%;height:100%;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;}

/* 48px with 1px side padding leaves the same 44px for the label as the old
   50px/2px did -- the 2px saved per button is pure outer whitespace, so the
   ribbon fits without any label getting tighter. */
#tool-toolbar .tool-btn{width:calc(48px * var(--icon-scale));flex:0 0 auto;margin-bottom:0;}

/* Ribbon icons only -- 22px instead of 18px (+22%), because the glyphs now
   carry filled volumes that need the room, and the buttons already reserved
   it as padding. Dropdown menu items and the constraint strip keep 18px:
   those sit beside 12px text, where 22px would tower over the label. */
/* The taller glyph is paid for out of the button's own padding rather than
   out of the ribbon's height: 22px icons in 3px padding come to within a
   couple of pixels of what 18px icons in 5px padding did. */
#tool-toolbar .tool-btn{padding:3px 1px;}
/* :not(.feat-lock) is load-bearing, and the Plan feature locks section below
   explains why at length: a padlock badge is also an `i` inside this button,
   and a selector that sizes "the button's icon" will size the padlock to
   match unless it says otherwise. That bug has now happened twice -- once
   with `.tool-btn i` at 18px, and again here, where the added #tool-toolbar
   (1,1,1) outranks the `.tool-btn i.feat-lock` (0,2,1) rule meant to hold the
   lock at 9px. It parked a 22px padlock on top of the tool's glyph. */
#tool-toolbar .tool-btn i:not(.feat-lock){width:calc(22px * var(--icon-scale));height:calc(22px * var(--icon-scale));}
/* Stated again at this specificity so the lock's size cannot lose that fight
   to anything scoped to #tool-toolbar in future. */
#tool-toolbar .tool-btn i.feat-lock{width:calc(9px * var(--icon-scale));height:calc(9px * var(--icon-scale));}
/* Heavier line for the same reason -- 1.6 reads as hairline next to a filled
   face, and the thin strokes were the first thing to disappear on Sweep,
   Loft, Fillet, Chamfer, Shell, Mirror and Union. */
#tool-toolbar .tool-btn .icon-svg{stroke-width:1.85;}

/* Colour is spent only where it says something: the toolbar stays
   monochrome at rest, turns accent under the pointer, and keeps the solid
   accent fill for the tool that is actually running. */
#tool-toolbar .tool-btn:hover:not(:disabled){background:var(--bg-3);color:var(--accent);}
#tool-toolbar .tool-btn.active{background:var(--accent-soft);border-color:var(--accent);color:var(--accent);}

/* Three buttons carry a long unbreakable word: "CoreShape" (43px),
   "Printability" (39px) and "Simulator" (36px). None can hyphenate, so at the
   standard 48px (44px of label) they spill over their neighbours. 60px gives
   the label 56px, which clears the widest of them and keeps each on one line.
   (The padlock used to eat 11px of that column too, until it was taken out of
   the label's flow -- see the .feat-lock corner rule above. The width is
   still needed for the words alone.) */
/* Selectors qualified with #tool-toolbar: a bare #id (0,1,0,0) loses to the
   #tool-toolbar .tool-btn rule above it (0,1,1,0) and the width silently
   stays 48px. */
#tool-toolbar #btn-ai-builder,
#tool-toolbar #btn-printability,
#tool-toolbar #btn-simulate{width:calc(60px * var(--icon-scale));}

/* Small corner tag for a feature that's real but still new -- an absolute-
   positioned badge rather than extra button text, since the ribbon's own
   buttons are already tight on width/height (see .tool-btn span above) and
   a 4th line of text wouldn't fit. */
#btn-simulate{position:relative;}
.tool-beta-badge{
  position:absolute;top:1px;right:1px;
  font-size:calc(6px * var(--icon-scale));line-height:1;font-weight:700;letter-spacing:.2px;
  color:#fff;background:var(--accent);padding:1px 3px;border-radius:3px;
  pointer-events:none;
}

.tt-dropdown{position:relative;}
.tt-menu{
  /* fixed (not absolute) so it escapes #tool-toolbar's overflow-x:auto clipping,
     which forces overflow-y:auto too per spec. Position set from JS on open. */
  position:fixed;z-index:30;min-width:130px;
  background:var(--bg-2);border:1px solid var(--border);border-radius:8px;padding:4px;
  display:flex;flex-direction:column;gap:1px;box-shadow:0 8px 20px rgba(0,0,0,.35);
}
.tt-menu.hidden{display:none;}

/* The file input behind File > Import. Never shown -- it exists only so the
   Import menu items have something to .click(). Hidden by its own rule rather
   than a `hidden` class because this stylesheet has no global .hidden: every
   one is element-scoped (.tt-menu.hidden, #feature-panel.hidden, ...), so a
   bare class="hidden" matched nothing and the Choose File control rendered
   across the page under the ribbon. */
#import-file-input{display:none;}
.tt-menu-item{
  display:flex;align-items:center;gap:8px;width:100%;text-align:left;
  background:transparent;border:none;color:var(--text-1);padding:7px 8px;border-radius:6px;
  cursor:pointer;font-size:12px;
}
.tt-menu-item i{width:calc(18px * var(--icon-scale));height:calc(18px * var(--icon-scale));display:block;flex:0 0 auto;}

/* A flyout opened FROM a menu row (File > Import), positioned beside its
   parent menu rather than under the toolbar button. Still a .tt-menu, which
   is what makes closeAllMenus() close it too -- a submenu that outlived the
   menu it belongs to would hang over the viewport with nothing to close it. */
.tt-menu-item.has-submenu{padding-right:6px;}
.tt-submenu-arrow{margin-left:auto;padding-left:14px;color:var(--text-2);font-size:10px;}
.tt-menu-item.has-submenu.open{background:var(--bg-3);color:var(--text-0);}
.tt-menu-item.has-submenu.open .tt-submenu-arrow{color:var(--text-0);}
.tt-menu-item i svg{width:100%;height:100%;fill:none;stroke:currentColor;stroke-width:1.6;}
.tt-menu-item:hover{background:var(--bg-3);color:var(--text-0);}
.tt-menu-item.active{background:var(--accent-dim);color:#fff;}

/* ---------- Layout ---------- */
#main{flex:1;display:flex;min-height:0;}

/* ---------- Viewport ---------- */
#viewport-wrap{flex:1;position:relative;min-width:0;background:var(--bg-0);}
#viewport{position:absolute;inset:0;}
#viewport canvas{display:block;}

#viewcube-wrap{
  position:absolute;top:14px;right:16px;display:flex;flex-direction:column;align-items:center;gap:6px;
}
#viewcube-canvas{
  width:96px;height:96px;cursor:grab;
}
#vc-home{
  align-self:flex-start;background:var(--overlay-bg);border:1.5px solid var(--border);color:var(--text-0);
  width:calc(32px * var(--icon-scale));height:calc(32px * var(--icon-scale));border-radius:7px;cursor:pointer;line-height:1;
  position:absolute;top:-6px;left:-6px;display:flex;align-items:center;justify-content:center;
}
#vc-home i{width:calc(20px * var(--icon-scale));height:calc(20px * var(--icon-scale));display:block;}
#vc-home i svg{stroke-width:2.2;}
#vc-home:hover{background:var(--bg-3);color:var(--text-0);border-color:var(--accent);}
#mini-nav{
  display:flex;gap:2px;background:var(--overlay-bg);border:1px solid var(--border);
  border-radius:8px;padding:3px;backdrop-filter:blur(4px);
}
.nav-btn{
  background:transparent;border:none;color:var(--text-1);padding:5px 9px;
  border-radius:6px;font-size:11px;cursor:pointer;
}
.nav-btn:hover{background:var(--bg-3);color:var(--text-0);}
.nav-btn.active{background:var(--accent-dim);color:#fff;}

#planes-toggle-btn{
  position:absolute;bottom:68px;right:16px;display:flex;align-items:center;gap:6px;
  background:var(--overlay-bg);border:1px solid var(--border);color:var(--text-1);
  padding:6px 10px;border-radius:8px;font-size:11px;cursor:pointer;backdrop-filter:blur(4px);
}
#planes-toggle-btn i{width:calc(16px * var(--icon-scale));height:calc(16px * var(--icon-scale));display:block;}
#planes-toggle-btn:hover{background:var(--bg-3);color:var(--text-0);}
#planes-toggle-btn.active{background:var(--accent-dim);color:#fff;border-color:var(--accent);}
#planes-toggle-btn.hidden{display:none;}

/* Third in the viewport's bottom-right stack, above #planes-toggle-btn (68px)
   and #dim-toggle-btn (34px). Same chrome as both. */
#box-select-btn{
  position:absolute;bottom:102px;right:16px;display:flex;align-items:center;gap:6px;
  background:var(--overlay-bg);border:1px solid var(--border);color:var(--text-1);
  padding:6px 10px;border-radius:8px;font-size:11px;cursor:pointer;backdrop-filter:blur(4px);
}
#box-select-btn:hover{background:var(--bg-3);color:var(--text-0);}
#box-select-btn.active{background:var(--accent-dim);color:#fff;border-color:var(--accent);}
#box-select-btn.hidden{display:none;}

#dim-toggle-btn{
  position:absolute;bottom:34px;right:16px;display:flex;align-items:center;gap:6px;
  background:var(--overlay-bg);border:1px solid var(--border);color:var(--text-1);
  padding:6px 10px;border-radius:8px;font-size:11px;cursor:pointer;backdrop-filter:blur(4px);
}
#dim-toggle-btn:hover{background:var(--bg-3);color:var(--text-0);}
#dim-toggle-btn.active{background:var(--accent-dim);color:#fff;border-color:var(--accent);}
#dim-toggle-btn.hidden{display:none;}

#status-bar{
  position:absolute;bottom:0;left:0;right:0;height:26px;display:flex;align-items:center;gap:16px;
  background:var(--overlay-bg);border-top:1px solid var(--border);padding:0 12px;
  font-size:11px;color:var(--text-2);
}
#status-mode{color:var(--accent);font-weight:600;}
#status-coords{font-variant-numeric:tabular-nums;}
#status-hint{margin-left:auto;color:var(--text-2);}

#context-panel{
  position:absolute;top:56px;left:50%;transform:translateX(-50%);
  background:var(--bg-2);border:1px solid var(--border);border-radius:8px;
  padding:12px 14px;min-width:260px;box-shadow:0 8px 24px rgba(0,0,0,.4);
  z-index:20;
}
#context-panel.hidden{display:none;}
#context-title{font-weight:600;margin-bottom:8px;font-size:12px;color:var(--text-0);}
#context-body{display:flex;flex-direction:column;gap:8px;margin-bottom:10px;}
#context-actions{display:flex;gap:8px;justify-content:flex-end;}
.cta{background:var(--accent);border:none;color:#fff;padding:6px 14px;border-radius:6px;cursor:pointer;font-size:12px;}
.cta:hover{background:#6f9bf5;}
/* The app's secondary button: the quiet option sitting next to a .cta.
   Shared by every dialog that has such a pair, so they cannot drift apart --
   the upgrade card was previously left out entirely and rendered as a raw
   browser-default button next to a themed one. */
#context-actions button:not(.cta),
.upgrade-actions button:not(.cta){background:transparent;border:1px solid var(--border);color:var(--text-1);padding:6px 14px;border-radius:6px;cursor:pointer;font-size:12px;}
#context-actions button:not(.cta):hover,
.upgrade-actions button:not(.cta):hover{background:var(--bg-3);color:var(--text-0);}

.field-row{display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:12px;color:var(--text-1);}
.field-row input[type=number], .field-row input[type=text], .field-row select{
  width:110px;background:var(--bg-0);border:1px solid var(--border);color:var(--text-0);
  padding:4px 6px;border-radius:4px;font-size:12px;
}
.field-row input[type=checkbox]{width:16px;height:16px;}

.plane-axis-btns{display:flex;gap:4px;}
.plane-axis-btn{
  background:var(--bg-0);border:1px solid var(--border);color:var(--text-1);
  padding:4px 9px;border-radius:4px;font-size:11px;cursor:pointer;
}
.plane-axis-btn:hover{background:var(--bg-3);color:var(--text-0);}
.plane-axis-btn.active{background:var(--accent-dim);color:#fff;border-color:var(--accent);}

/* ---------- Feature panel (top-left; face-based feature editing e.g. Extrude) ---------- */
#feature-panel{
  position:absolute;top:14px;left:14px;
  background:var(--bg-2);border:1px solid var(--border);border-radius:8px;
  padding:12px 14px;min-width:240px;box-shadow:0 8px 24px rgba(0,0,0,.4);
  z-index:20;
}
#feature-panel.hidden{display:none;}
#feature-panel-title{font-weight:600;margin-bottom:6px;font-size:12px;color:var(--text-0);}
#feature-panel-hint{font-size:11px;color:var(--text-2);margin-bottom:8px;line-height:1.4;}
#feature-panel-count{font-size:11.5px;color:var(--accent);font-weight:600;margin-bottom:10px;}
#feature-panel-body{display:flex;flex-direction:column;gap:8px;margin-bottom:10px;}
.fp-switch-link{background:none;border:none;color:var(--accent);font-size:12px;font-weight:600;text-align:left;padding:2px 0;cursor:pointer;}
.fp-switch-link:hover{text-decoration:underline;}
#feature-panel-actions{display:flex;gap:8px;justify-content:flex-end;}
#feature-panel-actions button:not(.cta){background:transparent;border:1px solid var(--border);color:var(--text-1);padding:6px 14px;border-radius:6px;cursor:pointer;font-size:12px;}
#feature-panel-actions button:not(.cta):hover{background:var(--bg-3);}
#feature-panel-actions .cta:disabled{opacity:.4;cursor:not-allowed;}
#feature-panel.text-mode{min-width:300px;}
/* Small inline spinner for tool panels while the CAD kernel computes
   (e.g. a sweep preview/commit). */
.fp-spinner{
  display:inline-block;width:11px;height:11px;box-sizing:border-box;
  border:2px solid var(--border);border-top-color:var(--accent);
  border-radius:50%;vertical-align:-2px;margin-right:6px;
  animation:fp-spin .7s linear infinite;
}
@keyframes fp-spin{to{transform:rotate(360deg);}}

/* ---------- AI Builder sidebar ---------- */
/* A flex sibling of #viewport-wrap, never an overlay: opening it genuinely
   narrows the viewport (which resizes itself via its ResizeObserver) so the
   panel cannot cover any part of the model. */
/* Collapsed state is width:0 rather than a negative margin. Both animate, but
   width:0 means the flex row genuinely reclaims every pixel -- with a negative
   margin the panel still participated in layout and the viewport did not get
   all of its space back on close. .ai-inner keeps its full width so the
   contents do not reflow while the panel slides. */
.ai-panel{
  flex:0 0 auto;position:relative;display:flex;min-width:0;overflow:hidden;
  background:var(--bg-1);border-left:1px solid var(--border);
  width:0;opacity:0;
  transition:width .22s ease, opacity .22s ease;
}
.ai-panel.is-open{width:var(--ai-w, 360px);opacity:1;}
.ai-panel[hidden]{display:none;}
.ai-grip{
  position:absolute;left:-3px;top:0;bottom:0;width:6px;cursor:col-resize;z-index:2;
}
.ai-grip:hover{background:var(--accent-dim);}
.ai-inner{display:flex;flex-direction:column;flex:1;min-width:0;width:var(--ai-w, 360px);}

.ai-header{
  display:flex;align-items:center;gap:6px;padding:8px 10px;
  border-bottom:1px solid var(--border);flex:0 0 auto;
}
.ai-title{flex:1;font-size:12px;font-weight:700;color:var(--text-0);letter-spacing:.03em;}
.ai-icon-btn{
  width:22px;height:22px;display:flex;align-items:center;justify-content:center;
  background:transparent;border:1px solid var(--border);border-radius:4px;
  color:var(--text-1);cursor:pointer;font-size:12px;line-height:1;padding:0;
}
.ai-icon-btn:hover:not(:disabled){background:var(--bg-3);color:var(--text-0);}
.ai-icon-btn:disabled{opacity:.4;cursor:default;}

/* Intelligence level, between the header and the meter it feeds. Sits above
   the allowance bar on purpose: picking Low is a decision about how fast that
   bar fills, so the two read as one control. */
.ai-quality{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:6px 10px;border-bottom:1px solid var(--border);flex:0 0 auto;
}
.ai-quality-label{font-size:10px;color:var(--text-2);letter-spacing:.04em;text-transform:uppercase;}
.ai-quality-btns{display:flex;border:1px solid var(--border);border-radius:5px;overflow:hidden;}
.ai-quality-btn{
  min-width:44px;padding:3px 9px;background:transparent;border:0;
  color:var(--text-2);cursor:pointer;font-size:11px;font-weight:600;line-height:1.5;
}
.ai-quality-btn + .ai-quality-btn{border-left:1px solid var(--border);}
.ai-quality-btn:hover:not(.is-on){background:var(--bg-3);color:var(--text-1);}
.ai-quality-btn.is-on{background:var(--accent);color:#fff;}

/* Both rows start with class="hidden" in aiPanel.js and are revealed once the
   server says the live provider is answering. There is no global .hidden rule
   in this stylesheet -- every use is scoped like this -- so without these two
   selectors the class is inert and an empty meter/toggle shows regardless. */
.ai-quality.hidden,.ai-budget.hidden{display:none;}

/* Daily AI allowance meter, directly under the panel header. */
.ai-budget{padding:7px 10px;border-bottom:1px solid var(--border);flex:0 0 auto;}
.ai-budget-row{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:5px;}
.ai-budget-label{font-size:10px;color:var(--text-2);letter-spacing:.04em;text-transform:uppercase;}
.ai-budget-pct{
  font-size:11px;font-weight:600;color:var(--text-1);
  font-family:ui-monospace,Menlo,Consolas,monospace;
}
.ai-budget-track{height:4px;border-radius:2px;background:var(--bg-3);overflow:hidden;}
.ai-budget-fill{
  height:100%;width:0;border-radius:2px;background:var(--accent);
  transition:width .25s ease;
}
.ai-budget-warn .ai-budget-fill{background:var(--warn, #d98324);}
.ai-budget-warn .ai-budget-pct{color:var(--warn, #d98324);}
.ai-budget-full .ai-budget-fill{background:var(--danger, #c0392b);}
.ai-budget-full .ai-budget-pct{color:var(--danger, #c0392b);}
/* Live provider, but the server reported no usage -- an explicit unknown
   rather than a hidden meter. See setBudgetUnavailable() in aiPanel.js. */
.ai-budget-unknown .ai-budget-pct{color:var(--text-2);}
.ai-budget-unknown .ai-budget-track{opacity:.45;}

.ai-log{flex:1;overflow-y:auto;padding:10px;display:flex;flex-direction:column;gap:8px;min-height:0;}
.ai-msg{display:flex;}
.ai-msg-body{
  font-size:12px;line-height:1.5;padding:7px 10px;border-radius:8px;max-width:92%;
  white-space:pre-wrap;word-break:break-word;
}
.ai-msg-user{justify-content:flex-end;}
.ai-msg-user .ai-msg-body{background:var(--accent-dim);color:#fff;}
.ai-msg-assistant .ai-msg-body{background:var(--bg-2);color:var(--text-1);}

/* The plan, shown before it runs. */
.ai-plan{
  border:1px solid var(--border);border-left:2px solid var(--accent);
  border-radius:6px;padding:7px 9px;background:var(--bg-2);
}
.ai-plan-title{
  font-size:10px;font-weight:700;color:var(--text-2);
  letter-spacing:.05em;text-transform:uppercase;margin-bottom:3px;
}
.ai-plan-summary{font-size:12px;line-height:1.45;color:var(--text-1);}
.ai-plan-count{font-size:10px;color:var(--text-2);margin-top:4px;}

.ai-op{display:flex;gap:8px;align-items:flex-start;padding:2px 2px 2px 4px;}
.ai-op-dot{
  width:6px;height:6px;border-radius:50%;background:var(--accent);
  flex:0 0 auto;margin-top:6px;
}
.ai-op-fail .ai-op-dot{background:#e35b5b;}
.ai-op-body{min-width:0;}
.ai-op-name{font-size:11.5px;color:var(--text-1);line-height:1.4;}
.ai-op-detail{font-size:10px;color:var(--text-2);font-family:ui-monospace,Menlo,Consolas,monospace;word-break:break-word;}
.ai-op-fail .ai-op-detail{color:#e08a8a;}

.ai-thinking{
  display:flex;align-items:center;gap:8px;padding:6px 12px;flex:0 0 auto;
  font-size:11.5px;color:var(--text-2);border-top:1px solid var(--border);
}
.ai-thinking.hidden{display:none;}
.ai-spinner{
  width:11px;height:11px;box-sizing:border-box;flex:0 0 auto;
  border:2px solid var(--border);border-top-color:var(--accent);border-radius:50%;
  animation:fp-spin .7s linear infinite;
}

.ai-composer{display:flex;gap:6px;padding:8px;border-top:1px solid var(--border);flex:0 0 auto;align-items:flex-end;}
.ai-input{
  flex:1;min-width:0;resize:none;font:inherit;font-size:12px;line-height:1.4;
  background:var(--bg-0);border:1px solid var(--border);border-radius:6px;
  color:var(--text-0);padding:6px 8px;
}
.ai-input:focus{outline:none;border-color:var(--accent);}
.ai-send,.ai-stop{
  flex:0 0 auto;padding:7px 12px;border-radius:6px;border:1px solid transparent;
  font-size:12px;cursor:pointer;
}
.ai-send{background:var(--accent);color:#fff;}
.ai-stop{background:#e35b5b;color:#fff;}
.ai-send.hidden,.ai-stop.hidden{display:none;}
.ai-send:disabled{background:var(--bg-3);color:var(--text-2);cursor:default;}

.ai-footer{
  display:flex;justify-content:space-between;gap:8px;padding:5px 10px 7px;
  font-size:10px;color:var(--text-2);flex:0 0 auto;
}
.ai-tokens{font-family:ui-monospace,Menlo,Consolas,monospace;}
/* Green dot when a real model is answering, so it's never ambiguous whether
   the built-in planner or Claude produced a result. */
.ai-provider-live::before{
  content:'';display:inline-block;width:6px;height:6px;border-radius:50%;
  background:#4caf7d;margin-right:5px;vertical-align:middle;
}

@media (prefers-reduced-motion: reduce){
  .ai-panel{transition:none;}
}

/* ---------- 3D Printability sidebar ---------- */
/* Same layout contract as the AI panel: a flex sibling of #viewport-wrap that
   collapses to width:0, never an overlay, so the viewport genuinely reclaims
   the space and the model is never covered. Its own class prefix rather than
   reusing .ai-* so neither module's styling can move the other. */
.pr-panel{
  flex:0 0 auto;position:relative;display:flex;min-width:0;overflow:hidden;
  background:var(--bg-1);border-left:1px solid var(--border);
  width:0;opacity:0;
  transition:width .22s ease, opacity .22s ease;
}
.pr-panel.is-open{width:var(--pr-w, 360px);opacity:1;}
.pr-panel[hidden]{display:none;}
.pr-grip{position:absolute;left:-3px;top:0;bottom:0;width:6px;cursor:col-resize;z-index:2;}
.pr-grip:hover{background:var(--accent-dim);}
.pr-inner{display:flex;flex-direction:column;flex:1;min-width:0;width:var(--pr-w, 360px);}

.pr-header{
  display:flex;align-items:center;gap:6px;padding:8px 10px;
  border-bottom:1px solid var(--border);flex:0 0 auto;
}
.pr-title{flex:1;font-size:12px;font-weight:700;color:var(--text-0);letter-spacing:.03em;}
.pr-icon-btn{
  width:22px;height:22px;display:flex;align-items:center;justify-content:center;
  background:transparent;border:1px solid var(--border);border-radius:4px;
  color:var(--text-1);cursor:pointer;font-size:12px;line-height:1;
}
.pr-icon-btn:hover{background:var(--bg-3);color:var(--text-0);}

.pr-body{flex:1;min-height:0;overflow-y:auto;padding:10px;display:flex;flex-direction:column;gap:10px;}
.pr-intro{font-size:11.5px;color:var(--text-2);line-height:1.5;}
.pr-intro p{margin:0 0 8px;}

.pr-progress{height:4px;border-radius:2px;background:var(--bg-3);overflow:hidden;}
.pr-progress-fill{height:100%;background:var(--accent);transition:width .15s linear;}

.pr-score{display:flex;align-items:center;gap:12px;padding:12px;border-radius:8px;border:1px solid var(--border);}
.pr-score-num{font-size:34px;font-weight:800;line-height:1;font-variant-numeric:tabular-nums;}
.pr-score-verdict{font-size:13px;font-weight:700;color:var(--text-0);}
.pr-score-sub{font-size:10.5px;color:var(--text-2);margin-top:2px;}
.pr-score-great{border-color:var(--ok);}
.pr-score-great .pr-score-num{color:var(--ok);}
.pr-score-good{border-color:var(--ok);}
.pr-score-good .pr-score-num{color:var(--ok);}
.pr-score-fair{border-color:var(--warn);}
.pr-score-fair .pr-score-num{color:var(--warn);}
.pr-score-poor{border-color:var(--danger);}
.pr-score-poor .pr-score-num{color:var(--danger);}

.pr-metrics{display:flex;flex-direction:column;gap:1px;}
.pr-metric{display:flex;justify-content:space-between;gap:10px;font-size:11.5px;padding:4px 2px;border-bottom:1px solid var(--border);}
.pr-metric-label{color:var(--text-2);}
.pr-metric-value{color:var(--text-0);font-weight:600;text-align:right;font-variant-numeric:tabular-nums;}

.pr-section-title{font-size:9px;letter-spacing:.09em;font-weight:700;color:var(--text-2);margin-top:4px;}

.pr-suggestions{display:flex;flex-direction:column;gap:6px;}
.pr-suggestion{display:flex;gap:7px;font-size:11.5px;line-height:1.45;color:var(--text-1);}
.pr-sev-dot{width:7px;height:7px;border-radius:50%;flex:0 0 auto;margin-top:4px;background:var(--text-2);}
.pr-sev-high .pr-sev-dot{background:var(--danger);}
.pr-sev-medium .pr-sev-dot{background:var(--warn);}
.pr-sev-ok .pr-sev-dot{background:var(--ok);}

.pr-orient-caption{font-size:10px;color:var(--text-2);line-height:1.4;margin:-2px 0 2px;}
.pr-orientations{display:flex;flex-direction:column;gap:1px;}
.pr-orient{display:flex;align-items:center;gap:8px;font-size:11px;padding:4px 6px;border-radius:5px;color:var(--text-1);}
.pr-orient-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.pr-orient-detail{color:var(--text-2);font-size:10px;flex:0 0 auto;}
.pr-orient-score{font-weight:700;font-variant-numeric:tabular-nums;flex:0 0 auto;width:24px;text-align:right;}
.pr-orient-best{background:var(--bg-3);color:var(--text-0);}
.pr-orient-current .pr-orient-name{font-weight:700;}

.pr-settings{font-size:11.5px;color:var(--text-1);border-top:1px solid var(--border);padding-top:8px;}
.pr-settings summary{cursor:pointer;color:var(--text-2);font-size:11px;}
.pr-fields{display:flex;flex-direction:column;gap:5px;margin-top:8px;}
.pr-field{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--text-2);}
.pr-field span:first-child{flex:1;}
.pr-field input{
  width:64px;background:var(--bg-0);border:1px solid var(--border);color:var(--text-0);
  padding:3px 5px;border-radius:4px;font-size:11px;
}
.pr-field input:focus{outline:none;border-color:var(--accent);}
.pr-field-suffix{width:22px;color:var(--text-2);font-size:10px;}
.pr-settings-hint{font-size:10px;color:var(--text-2);margin-top:6px;}

.pr-note{font-size:10px;color:var(--text-2);line-height:1.4;border-top:1px solid var(--border);padding-top:8px;}

.pr-footer{padding:8px;border-top:1px solid var(--border);flex:0 0 auto;}
.pr-run{
  width:100%;padding:8px;border-radius:6px;border:none;
  background:var(--accent);color:#fff;font-size:12px;cursor:pointer;
}
.pr-run:hover:not(:disabled){background:#6f9bf5;}
.pr-run:disabled{background:var(--bg-3);color:var(--text-2);cursor:default;}

@media (prefers-reduced-motion: reduce){
  .pr-panel{transition:none;}
}

/* ---------- Part Simulator workspace ---------- */
/* Same layout contract as the AI and printability panels: a flex sibling of
   #viewport-wrap that collapses to width:0, never an overlay, so the CAD
   workspace stays visible and usable next to a study. */
.sim-panel{
  flex:0 0 auto;position:relative;display:flex;min-width:0;overflow:hidden;
  background:var(--bg-1);border-left:1px solid var(--border);
  width:0;opacity:0;transition:width .22s ease, opacity .22s ease;
}
.sim-panel.is-open{width:var(--sim-w, 400px);opacity:1;}
.sim-panel[hidden]{display:none;}
.sim-grip{position:absolute;left:-3px;top:0;bottom:0;width:6px;cursor:col-resize;z-index:2;}
.sim-grip:hover{background:var(--accent-dim);}
.sim-inner{display:flex;flex-direction:column;flex:1;min-width:0;width:var(--sim-w, 400px);}

.sim-header{display:flex;align-items:center;gap:6px;padding:8px 10px;border-bottom:1px solid var(--border);flex:0 0 auto;}
.sim-title{flex:1;font-size:12px;font-weight:700;color:var(--text-0);letter-spacing:.03em;}
.sim-beta-badge{
  margin-left:6px;font-size:9px;font-weight:700;letter-spacing:.03em;
  color:#fff;background:var(--accent);padding:1px 5px;border-radius:3px;vertical-align:1px;
}
.sim-quick{
  background:var(--accent);border:none;color:#fff;padding:4px 10px;border-radius:5px;
  font-size:11px;cursor:pointer;
}
.sim-quick:hover{background:#6f9bf5;}
.sim-icon-btn{
  width:22px;height:22px;display:flex;align-items:center;justify-content:center;
  background:transparent;border:1px solid var(--border);border-radius:4px;
  color:var(--text-1);cursor:pointer;font-size:12px;line-height:1;
}
.sim-icon-btn:hover{background:var(--bg-3);color:var(--text-0);}

.sim-steps{display:flex;gap:2px;padding:6px 8px;border-bottom:1px solid var(--border);overflow-x:auto;flex:0 0 auto;}
.sim-step{
  flex:0 0 auto;background:transparent;border:1px solid transparent;color:var(--text-2);
  font-size:10px;padding:3px 7px;border-radius:10px;cursor:pointer;white-space:nowrap;
}
.sim-step:hover{background:var(--bg-3);color:var(--text-0);}
.sim-step.is-done{color:var(--ok);}
.sim-step.is-current{background:var(--accent-dim);color:#fff;border-color:var(--accent);}

.sim-body{flex:1;min-height:0;overflow-y:auto;padding:10px;display:flex;flex-direction:column;gap:8px;}
.sim-section-title{font-size:9px;letter-spacing:.09em;font-weight:700;color:var(--text-2);margin-top:4px;}
.sim-desc{font-size:11.5px;color:var(--text-1);line-height:1.45;}
.sim-note{font-size:11px;color:var(--text-2);line-height:1.45;}
.sim-note.sim-warn{color:var(--warn);}
.sim-error{font-size:11px;color:var(--danger);}
.sim-error-box{
  font-size:11.5px;color:var(--text-0);background:rgba(227,91,91,.12);
  border:1px solid var(--danger);border-radius:6px;padding:8px 10px;line-height:1.5;
}
.sim-assumptions{margin:0;padding-left:16px;font-size:11px;color:var(--text-2);line-height:1.5;}
.sim-empty{font-size:11px;color:var(--text-2);font-style:italic;}

.sim-field{display:flex;align-items:center;gap:8px;font-size:11.5px;color:var(--text-1);}
.sim-field-label{flex:1;min-width:0;}
.sim-field-hint{font-size:10px;color:var(--text-2);}
.sim-field select,.sim-field input[type=number],.sim-field input[type=text]{
  width:150px;background:var(--bg-0);border:1px solid var(--border);color:var(--text-0);
  padding:4px 6px;border-radius:4px;font-size:11.5px;
}
.sim-field select:focus,.sim-field input:focus{outline:none;border-color:var(--accent);}
.sim-field input[type=range]{width:150px;}

.sim-props{display:flex;flex-direction:column;gap:1px;}
.sim-prop{display:flex;justify-content:space-between;gap:10px;font-size:11px;padding:3px 2px;border-bottom:1px solid var(--border);color:var(--text-2);}
.sim-prop-v{color:var(--text-0);font-weight:600;font-variant-numeric:tabular-nums;text-align:right;}

.sim-list{display:flex;flex-direction:column;gap:3px;}
.sim-list-row{display:flex;align-items:center;gap:6px;background:var(--bg-0);border:1px solid var(--border);border-radius:5px;padding:5px 8px;}
.sim-list-name{flex:1;font-size:11px;color:var(--text-1);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.sim-x{background:transparent;border:none;color:var(--text-2);cursor:pointer;font-size:11px;padding:0 2px;}
.sim-x:hover{color:var(--danger);}

.sim-btn{
  background:transparent;border:1px solid var(--border);color:var(--text-1);
  padding:6px 12px;border-radius:6px;cursor:pointer;font-size:11.5px;align-self:flex-start;
}
.sim-btn:hover:not(:disabled){background:var(--bg-3);color:var(--text-0);}
.sim-btn:disabled{opacity:.45;cursor:not-allowed;}
.sim-btn-primary{background:var(--accent);border-color:var(--accent);color:#fff;}
.sim-btn-primary:hover:not(:disabled){background:#6f9bf5;color:#fff;}

.sim-progress{height:5px;border-radius:3px;background:var(--bg-3);overflow:hidden;margin-top:6px;}
.sim-progress-fill{height:100%;width:0;background:var(--accent);transition:width .15s linear;}
.sim-progress-label{font-size:10px;color:var(--text-2);margin-top:4px;font-variant-numeric:tabular-nums;}

.sim-headline{display:flex;align-items:center;gap:12px;padding:12px;border-radius:8px;border:1px solid var(--border);}
.sim-headline-num{font-size:30px;font-weight:800;line-height:1;font-variant-numeric:tabular-nums;}
.sim-headline-title{font-size:12.5px;font-weight:700;color:var(--text-0);}
.sim-headline-sub{font-size:10.5px;color:var(--text-2);margin-top:3px;line-height:1.45;}
.sim-ok{border-color:var(--ok);} .sim-ok .sim-headline-num{color:var(--ok);}
.sim-warn{border-color:var(--warn);} .sim-warn .sim-headline-num{color:var(--warn);}
.sim-bad{border-color:var(--danger);} .sim-bad .sim-headline-num{color:var(--danger);}

.sim-metrics{display:grid;grid-template-columns:1fr 1fr;gap:6px;}
.sim-metric{background:var(--bg-0);border:1px solid var(--border);border-radius:6px;padding:7px 9px;}
.sim-metric-label{font-size:9.5px;color:var(--text-2);letter-spacing:.04em;}
.sim-metric-value{font-size:13px;color:var(--text-0);font-weight:700;font-variant-numeric:tabular-nums;margin-top:2px;}

.sim-legend{margin:2px 0 4px;}
.sim-legend-bar{height:10px;border-radius:3px;border:1px solid var(--border);}
.sim-legend-labels{display:flex;justify-content:space-between;font-size:9.5px;color:var(--text-2);margin-top:3px;font-variant-numeric:tabular-nums;}

.sim-planned{display:flex;flex-direction:column;gap:4px;}
.sim-planned-row{display:flex;flex-direction:column;gap:2px;background:var(--bg-0);border:1px solid var(--border);border-radius:5px;padding:6px 8px;}
.sim-planned-name{font-size:11px;color:var(--text-1);font-weight:600;}
.sim-planned-why{font-size:10px;color:var(--text-2);line-height:1.4;}

.sim-probe{display:flex;flex-direction:column;gap:6px;}
.sim-probe-fields{display:flex;gap:6px;}
.sim-probe-field{display:flex;flex-direction:column;gap:2px;font-size:10px;color:var(--text-2);flex:1;}
.sim-probe-field input{width:100%;box-sizing:border-box;background:var(--bg-0);border:1px solid var(--border);color:var(--text-0);padding:3px 5px;border-radius:4px;font-size:11px;}
.sim-probe-out{font-size:11px;color:var(--text-1);line-height:1.5;}

.sim-custom,.sim-solveinfo{border-top:1px solid var(--border);padding-top:8px;display:flex;flex-direction:column;gap:6px;}
.sim-custom summary,.sim-solveinfo summary{cursor:pointer;font-size:11px;color:var(--text-2);}

.sim-chart{width:100%;height:auto;display:block;margin-bottom:4px;}
.sim-chart-title{font-size:10px;color:var(--text-2);margin-top:6px;}
.sim-chart-axis{stroke:var(--border);stroke-width:1;}
.sim-chart-grid{stroke:var(--border);stroke-width:.5;opacity:.5;}
.sim-chart-line{fill:none;stroke:var(--accent);stroke-width:1.6;}
.sim-chart-tick,.sim-chart-label,.sim-chart-empty{fill:var(--text-2);font-size:8px;}

.sim-footer{display:flex;gap:6px;padding:8px;border-top:1px solid var(--border);flex:0 0 auto;}
.sim-nav{
  flex:1;background:transparent;border:1px solid var(--border);color:var(--text-1);
  padding:7px;border-radius:6px;cursor:pointer;font-size:11.5px;
}
.sim-nav:hover:not(:disabled){background:var(--bg-3);color:var(--text-0);}
.sim-nav:disabled{opacity:.4;cursor:not-allowed;}
.sim-nav-primary{background:var(--accent);border-color:var(--accent);color:#fff;}
.sim-nav-primary:hover:not(:disabled){background:#6f9bf5;color:#fff;}

@media (prefers-reduced-motion: reduce){ .sim-panel{transition:none;} }

/* ---------- Plan feature locks ---------- */
/* A small padlock icon sitting right next to a locked control's own label,
   colored by which plan it needs -- blue for Standard, orange for Pro.
   Rendered only for an account that's actually below that tier: for an
   account that already has access there is nothing to upgrade to, so the
   icon would be permanent noise. */
/* Sized to match the label text it sits beside, not the big toolbar icon
   above it: a ribbon .tool-btn label is 8.5px and a dropdown item is 12px.
   Written as `i.feat-lock` inside each context on purpose -- `.tool-btn i`
   and `.tt-menu-item i` set an 18px block for the tool's own glyph and, being
   more specific than a bare `.feat-lock`, silently won that fight. That is
   what left the padlock rendering at full icon size, wider than the label it
   sat next to, overflowing the fixed 50px button and pushing its icon and
   text off centre. */
.feat-lock,
.tool-btn i.feat-lock{
  display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;
  width:calc(9px * var(--icon-scale));height:calc(9px * var(--icon-scale));cursor:pointer;
}
.tt-menu-item i.feat-lock{
  display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;
  width:calc(12px * var(--icon-scale));height:calc(12px * var(--icon-scale));cursor:pointer;
}
.feat-lock[data-tier="standard"]{color:var(--accent);}
.feat-lock[data-tier="pro"]{color:var(--warn);}
.feat-lock:hover{filter:brightness(1.3);}
/* The label span becomes a tiny inline-flex row once it's carrying a lock
   icon, so the icon sits BESIDE the text instead of wrapping under it. That
   matters specifically for a ribbon .tool-btn, whose icon and label stack in
   a flex COLUMN -- an ordinary sibling badge would land on its own line
   below the label rather than next to it; a dropdown .tt-menu-item is
   already a row, so this is a no-op there beyond the small gap. */
.tool-btn span.has-lock,.tt-menu-item span.has-lock{display:inline-flex;align-items:center;gap:2px;}
/* A ribbon button is a fixed 50px, so the longest label plus a lock does not
   fit on one line ("CoreShape AI" needs 55px). Capping the label at the
   button's width lets the TEXT wrap while the lock stays beside it, rather
   than the label spilling out over the neighbouring button. */
.tool-btn span.has-lock{max-width:100%;}

/* On a RIBBON button the padlock must not sit in the label's flow.
   .has-lock lays the span out as a row -- [text][gap][lock] -- and centring
   that row centres text+lock as a unit, which pushes the text itself off
   centre by half the lock's width plus the gap. Measured: exactly 5.5px left
   of the icon above it on all three locked buttons, against 0 on an unlocked
   one, which is what made those logos read as crooked against their labels.
   Taking the lock out of the flow lets the text centre under the icon on its
   own, and costs nothing elsewhere: a dropdown .tt-menu-item is a left-
   aligned row where an inline lock is exactly right, so it keeps the rule
   above. */
#tool-toolbar .tool-btn{position:relative;}
#tool-toolbar .tool-btn span.has-lock{display:block;}
/* Top-LEFT corner. Measured on a locked ribbon button (60 x 41): the icon
   occupies x 21-39 / y 6-24 and the label runs x 3.5-56.5 / y 25-35 -- the
   label fills the whole bottom line, so there is no gap beside it and a lock
   parked at bottom-right lands squarely ON the text. The free space is the
   two top corners flanking the icon. Left rather than right because
   .tool-beta-badge already owns top-right (see #btn-simulate), and a lock
   sharing that slot would collide the moment a button carried both. */
#tool-toolbar .tool-btn i.feat-lock{position:absolute;left:2px;top:2px;}

/* Same chrome and same slot as #dim-toggle-btn (they can never both be
   visible -- see app.html), so a view-only document's call to action reads as
   one of the viewport's own controls rather than something pasted on top of
   it. Amber to match .view-only-badge: the two say the same thing, at
   opposite corners of the viewport. */
#view-only-upgrade{
  position:absolute;bottom:34px;right:16px;display:flex;align-items:center;gap:6px;
  background:var(--overlay-bg);border:1px solid #e0a94c;color:#e0a94c;
  padding:6px 10px;border-radius:8px;font-size:11px;font-weight:600;
  cursor:pointer;backdrop-filter:blur(4px);
}
#view-only-upgrade:hover{background:rgba(224,169,76,.18);}
#view-only-upgrade.hidden{display:none;}

#upgrade-overlay{
  position:fixed;inset:0;z-index:10000;display:flex;align-items:center;justify-content:center;
  background:rgba(0,0,0,.5);
}
#upgrade-overlay.hidden{display:none;}
.upgrade-card{
  background:var(--bg-1);border:1px solid var(--border);border-radius:8px;
  padding:20px 22px;max-width:340px;text-align:center;box-shadow:0 12px 40px rgba(0,0,0,.45);
}
.upgrade-card h3{margin:0 0 8px;font-size:15px;color:var(--text-0);}
.upgrade-card p{margin:0 0 16px;font-size:12.5px;color:var(--text-1);line-height:1.5;}
.upgrade-card .upgrade-actions{display:flex;gap:8px;justify-content:center;}
/* inline-flex, not inline-block: the row stretches both controls to the same
   height, and an inline-block's text would sit at the top of that stretch
   while the neighbouring button's stays centred. */
.upgrade-card a.cta{text-decoration:none;display:inline-flex;align-items:center;justify-content:center;}

/* Loft's ordered profile list. A loft's pick order *is* its shape, so the
   panel shows the sequence rather than just a count. */
.fp-order-list{margin:6px 0 2px;display:flex;flex-direction:column;gap:2px;}
.fp-order-item{
  font-size:11px;color:var(--text-1);background:var(--bg-0);
  border:1px solid var(--border);border-radius:3px;padding:3px 6px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.fp-order-empty{font-size:11px;color:var(--text-2);font-style:italic;padding:3px 2px;}
/* Rotation row in the sketch Text panel: slider to find the angle, number box
   to nail an exact one. The number is narrow so the slider gets the space --
   dragging is the common action. */
.text-panel-rot{display:flex;align-items:center;gap:6px;width:150px;}
.text-panel-rot-slider{flex:1;min-width:0;}
.text-panel-rot-number{
  width:48px;flex:0 0 auto;background:var(--bg-0);border:1px solid var(--border);
  color:var(--text-0);padding:3px 4px;border-radius:4px;font-size:11.5px;
  font-variant-numeric:tabular-nums;
}
.text-panel-rot-number:focus{outline:none;border-color:var(--accent);}
.text-panel-height-input{
  width:80px;background:var(--bg-0);border:1px solid var(--border);
  color:var(--text-0);padding:3px 6px;border-radius:4px;font-size:11.5px;
  font-variant-numeric:tabular-nums;
}
.text-panel-height-input:focus{outline:none;border-color:var(--accent);}
.text-panel-label{font-size:12px;color:var(--text-1);margin-bottom:4px;}
.text-panel-input{
  width:100%;box-sizing:border-box;resize:vertical;min-height:64px;
  background:var(--bg-0);border:1px solid var(--border);color:var(--text-0);
  padding:8px;border-radius:4px;font-size:13px;font-family:inherit;margin-bottom:2px;
}

/* ---------- Keyboard & Mouse config panel (centered) ---------- */
#keymap-panel{
  position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);
  background:var(--bg-2);border:1px solid var(--border);border-radius:10px;
  padding:18px 20px;width:460px;max-width:90%;box-shadow:0 12px 32px rgba(0,0,0,.45);
  z-index:25;
}
#keymap-panel.hidden{display:none;}
#keymap-title{font-weight:700;font-size:14px;color:var(--text-0);margin-bottom:14px;}
.keymap-columns{display:grid;grid-template-columns:1fr 1fr;gap:20px;}
.keymap-section-title{font-size:10px;letter-spacing:.06em;color:var(--text-2);font-weight:700;margin-bottom:8px;}
.keymap-row{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:5px 0;font-size:12px;color:var(--text-1);border-bottom:1px solid var(--border);
}
.keymap-row:last-of-type{border-bottom:none;}
.keymap-key{
  background:var(--bg-0);border:1px solid var(--border);border-radius:4px;
  padding:2px 8px;font-size:11px;color:var(--text-0);font-variant-numeric:tabular-nums;
  min-width:28px;text-align:center;cursor:pointer;
}
.keymap-key:hover{border-color:var(--accent);color:var(--accent);}
.keymap-key.listening{border-color:var(--accent);color:var(--accent);background:var(--bg-3);}
.keymap-hint{font-size:10.5px;color:var(--text-2);margin-top:10px;line-height:1.4;}
.keymap-reset-btn{
  margin-top:12px;background:transparent;border:1px solid var(--border);color:var(--text-1);
  padding:6px 12px;border-radius:6px;cursor:pointer;font-size:11.5px;
}
.keymap-reset-btn:hover{background:var(--bg-3);color:var(--text-0);}
#keymap-actions{display:flex;justify-content:flex-end;margin-top:16px;}

@media (max-width: 560px){
  .keymap-columns{grid-template-columns:1fr;}
}

/* ---------- Live dimension label while sketching ---------- */
#dim-label{
  position:absolute;transform:translate(-50%, -130%);pointer-events:none;
  background:var(--overlay-bg);border:1px solid var(--accent);color:var(--text-0);
  padding:3px 8px;border-radius:5px;font-size:11.5px;font-variant-numeric:tabular-nums;
  white-space:nowrap;z-index:15;
}
#dim-label.hidden{display:none;}

/* ---------- Persistent per-entity dimensions (after committing a sketch entity) ---------- */
#entity-dim-layer{position:absolute;inset:0;pointer-events:none;z-index:14;}
.entity-dim-label{
  position:absolute;transform:translate(-50%, -50%);pointer-events:auto;cursor:pointer;
  background:var(--overlay-bg);border:1px solid var(--border);color:var(--text-1);
  padding:2px 7px;border-radius:5px;font-size:11px;font-variant-numeric:tabular-nums;
  white-space:nowrap;
}
.entity-dim-label:hover{border-color:var(--accent);color:var(--text-0);}
.entity-dim-input{
  background:var(--bg-0);border:1px solid var(--accent);color:var(--text-0);
  font-size:11px;font-family:inherit;padding:1px 4px;border-radius:3px;width:88px;outline:none;
}
/* Stored line-to-line/point-to-line distance dimensions (Dimension tool) --
   draggable to reposition, on top of the plain entity-dim-label look. */
.dim-annotation-label{cursor:grab;}
.dim-annotation-label:active{cursor:grabbing;}
/* Selected (clicked once) and ready for Delete. The green matches
   DIM_SELECTED_COLOR in sketchMode.js, which recolours the same dimension's
   witness lines and arrowheads in the viewport, so the label and the geometry
   it belongs to light up together. */
.dim-annotation-label.selected{
  border-color:var(--ok);color:var(--text-0);
  box-shadow:0 0 0 1px var(--ok);
}

/* ---------- Side panel ---------- */
#sidepanel{
  width:250px;flex:0 0 250px;background:var(--bg-1);border-left:1px solid var(--border);
  display:flex;flex-direction:column;overflow-y:auto;
}
/* margin-top:auto pins this to the bottom of #sidepanel's flex column, so it
   sits under the panel sections however tall they grow, and travels with the
   content once the panel scrolls rather than covering it. */
#report-bug-btn{
  margin-top:auto;display:flex;align-items:center;justify-content:center;gap:7px;
  padding:9px 10px;background:transparent;border:none;border-top:1px solid var(--border);
  color:var(--text-2);font:inherit;font-size:11.5px;font-weight:600;cursor:pointer;
  flex:0 0 auto;
}
#report-bug-btn svg{width:14px;height:14px;flex:none;}
#report-bug-btn:hover{background:var(--bg-3);color:var(--text-0);}

#bug-overlay{
  position:fixed;inset:0;z-index:10000;display:flex;align-items:center;justify-content:center;
  background:rgba(0,0,0,.55);padding:20px;
}
#bug-overlay.hidden{display:none;}
.bug-card-modal{
  background:var(--bg-1);border:1px solid var(--border);border-radius:10px;
  padding:22px 24px;max-width:520px;width:100%;box-shadow:0 16px 50px rgba(0,0,0,.5);
  max-height:calc(100vh / var(--page-zoom, 1) - 40px);overflow-y:auto;
}
.bug-card-modal h3{margin:0 0 8px;font-size:16px;color:var(--text-0);}
.bug-modal-sub{margin:0 0 14px;font-size:12.5px;line-height:1.5;color:var(--text-1);}
.bug-card-modal textarea{
  width:100%;background:var(--bg-0);border:1px solid var(--border);border-radius:6px;
  color:var(--text-0);font:inherit;font-size:13px;padding:10px;resize:vertical;line-height:1.5;
}
.bug-card-modal textarea:focus{outline:none;border-color:var(--accent);}
.bug-modal-row{display:flex;justify-content:flex-end;margin-top:4px;}
.bug-char-count{font-size:11px;color:var(--text-2);}
#bug-email-row{margin-top:10px;}
#bug-email-row.hidden{display:none;}
#bug-email-row label{display:block;font-size:11.5px;color:var(--text-2);margin-bottom:4px;}
#bug-email-row input{
  width:100%;background:var(--bg-0);border:1px solid var(--border);border-radius:6px;
  color:var(--text-0);font:inherit;font-size:13px;padding:8px 10px;
}
#bug-email-row input:focus{outline:none;border-color:var(--accent);}
.bug-modal-note{margin:12px 0 0;font-size:11.5px;line-height:1.5;color:var(--text-2);}
.bug-modal-msg{display:none;margin-top:12px;font-size:12.5px;border-radius:6px;padding:9px 11px;}
.bug-modal-msg.show{display:block;}
.bug-modal-msg.is-error{background:rgba(229,83,75,.14);color:#e5534b;}
.bug-modal-msg.is-success{background:rgba(76,175,110,.14);color:#4caf6e;}
.bug-modal-actions{display:flex;gap:8px;justify-content:flex-end;margin-top:16px;}
.bug-modal-actions button{
  font:inherit;font-size:12.5px;padding:8px 16px;border-radius:6px;cursor:pointer;
  background:var(--bg-3);border:1px solid var(--border);color:var(--text-1);
}
.bug-modal-actions button:hover{color:var(--text-0);}
.bug-modal-actions .cta{background:var(--accent);border-color:var(--accent);color:#fff;}
.bug-modal-actions .cta:disabled{opacity:.55;cursor:not-allowed;}

.panel-section{border-bottom:1px solid var(--border);padding:8px 10px;}
.panel-header{font-size:10px;letter-spacing:.08em;color:var(--text-2);font-weight:700;margin-bottom:6px;}
#browser-tree{display:flex;flex-direction:column;gap:1px;}
.tree-node{
  display:flex;align-items:center;gap:6px;padding:4px 6px;border-radius:4px;cursor:pointer;
  font-size:12px;color:var(--text-1);
}
.tree-node:hover{background:var(--bg-3);}
.tree-node.selected{background:var(--accent-dim);color:#fff;}
.tree-node .tn-icon{width:14px;text-align:center;color:var(--text-2);}
.tree-node .tn-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.tree-node .tn-vis{opacity:.6;cursor:pointer;padding:2px;display:flex;}
.tree-node .tn-vis:hover{opacity:1;}
.tree-node .tn-vis i{width:calc(14px * var(--icon-scale));height:calc(14px * var(--icon-scale));display:block;}
/* Bodies that touch but couldn't be fused -- flex:0 0 auto so the badge
   never squeezes the name's ellipsis out of the row. */
.tree-node .tn-warn{
  flex:0 0 auto;width:13px;height:13px;border-radius:50%;
  background:#e3a13b;color:#1b1200;font-size:9.5px;font-weight:700;
  display:flex;align-items:center;justify-content:center;cursor:help;
}
.tree-group-title{font-size:10px;color:var(--text-2);margin:6px 0 2px 2px;font-weight:600;}

.empty-hint{color:var(--text-2);font-size:11px;font-style:italic;}
.prop-row{display:flex;align-items:center;justify-content:space-between;font-size:12px;color:var(--text-1);margin-bottom:6px;}
.prop-row input[type=number]{width:90px;background:var(--bg-0);border:1px solid var(--border);color:var(--text-0);padding:3px 5px;border-radius:4px;}
.prop-group-title{font-size:10.5px;color:var(--text-2);font-weight:700;margin:8px 0 4px;}

/* ---------- Timeline ---------- */
#timeline-wrap{
  height:34px;flex:0 0 34px;background:var(--bg-1);border-top:1px solid var(--border);
  display:flex;align-items:center;gap:8px;padding:0 12px;overflow-x:auto;
}
.timeline-label{font-size:9px;letter-spacing:.08em;color:var(--text-2);font-weight:700;flex:0 0 auto;}
#timeline{display:flex;align-items:center;gap:2px;flex:1;overflow-x:auto;height:100%;}
.tl-item{
  flex:0 0 auto;display:flex;flex-direction:row;align-items:center;gap:4px;
  padding:2px 7px;border-radius:5px;cursor:pointer;border:1px solid transparent;
}
.tl-item:hover{background:var(--bg-3);}
.tl-item.selected{background:var(--accent-dim);border-color:var(--accent);}
.tl-icon{width:15px;height:15px;border-radius:3px;background:var(--bg-3);display:flex;align-items:center;justify-content:center;color:var(--text-1);font-size:9px;flex:0 0 auto;}
.tl-name{font-size:10.5px;color:var(--text-2);white-space:nowrap;}
.tl-arrow{width:8px;height:1px;background:var(--border);flex:0 0 auto;}
.tl-empty{color:var(--text-2);font-size:11px;font-style:italic;}

/* ---------- 2D Drawing workspace (src/drawing/) ---------- */
/* A full takeover of the same screen area #tool-toolbar + #main occupy, not
   a side panel alongside them -- see panel.js's open()/close(), which toggle
   these three `.hidden` states together. Neither #tool-toolbar nor #main had
   a `.hidden` rule before this feature (every other `.hidden` user in this
   file -- .tt-menu.hidden, #feature-panel.hidden, etc -- already has its own
   scoped one; there is no bare `.hidden{display:none}`), so both are added
   here rather than assumed. */
#tool-toolbar.hidden{display:none;}
#main.hidden{display:none;}
/* Freezes the ribbon + 3D viewport while a dialog that opted into
   setViewportLocked(true) (currently just Create 2D Drawing) is open. The
   dialog itself (#context-panel) lives inside #viewport-wrap too, so its
   pointer-events are re-enabled explicitly rather than being caught by the
   same blanket rule -- but filter is a compositing effect a child can't
   opt back out of, so the dim-and-desaturate look is applied only to the
   canvas/ribbon directly, never to #viewport-wrap as a whole. */
#app.viewport-locked #tool-toolbar,
#app.viewport-locked #viewport-wrap{pointer-events:none;}
#app.viewport-locked #context-panel{pointer-events:auto;}
#app.viewport-locked #tool-toolbar,
#app.viewport-locked #viewport,
#app.viewport-locked #viewcube-wrap{filter:saturate(.7) brightness(.92);}

.dwg-workspace{flex:1;display:flex;flex-direction:column;min-height:0;}
.dwg-workspace.hidden{display:none;}

.dwg-toolbar{
  flex:0 0 auto;display:flex;align-items:center;gap:6px;
  background:var(--bg-1);border-bottom:1px solid var(--border);
  padding:6px 10px;
}
.dwg-tb-btn{
  background:transparent;border:1px solid transparent;color:var(--text-1);
  padding:6px 10px;border-radius:var(--radius);cursor:pointer;font-size:12px;white-space:nowrap;
}
.dwg-tb-btn:hover:not(:disabled){background:var(--bg-3);color:var(--text-0);}
.dwg-tb-btn:disabled{opacity:.35;cursor:not-allowed;}
.dwg-tb-btn.active{background:var(--accent-dim);color:#fff;border-color:var(--accent);}
/* Right-click menu inside the drawing canvas (see panel.js showCtxMenu). */
.dwg-ctx-menu{
  position:absolute;z-index:60;min-width:180px;padding:4px;
  background:var(--bg-2);border:1px solid var(--border);border-radius:var(--radius);
  box-shadow:0 8px 24px rgba(0,0,0,.45);display:flex;flex-direction:column;
}
.dwg-ctx-menu.hidden{display:none;}
.dwg-ctx-item{
  background:none;border:none;color:var(--text-1);text-align:left;
  padding:7px 10px;border-radius:4px;cursor:pointer;font-size:12.5px;white-space:nowrap;
}
.dwg-ctx-item:hover{background:var(--bg-3);color:var(--text-0);}
/* Brief flash when a typed custom scale can't be parsed. */
.dwg-input-error{outline:2px solid #e35b5b;}
.dwg-icon-btn{padding:6px 11px;font-size:14px;line-height:1;font-weight:700;}
.dwg-tb-close{color:var(--text-1);font-weight:600;}
.dwg-tb-sep{flex:0 0 1px;align-self:stretch;background:var(--border);margin:2px 4px;}
.dwg-doc-name{font-size:12.5px;font-weight:700;color:var(--text-0);white-space:nowrap;}

.dwg-insert-wrap{position:relative;}
.dwg-insert-menu{
  position:absolute;top:100%;left:0;margin-top:4px;z-index:30;min-width:140px;
  background:var(--bg-2);border:1px solid var(--border);border-radius:8px;padding:4px;
  display:flex;flex-direction:column;gap:1px;box-shadow:0 8px 20px rgba(0,0,0,.35);
}
.dwg-insert-menu.hidden{display:none;}
.dwg-insert-item{
  display:block;width:100%;text-align:left;background:transparent;border:none;
  color:var(--text-1);padding:7px 8px;border-radius:6px;cursor:pointer;font-size:12px;
}
.dwg-insert-item:hover{background:var(--bg-3);color:var(--text-0);}

.dwg-body{flex:1;display:flex;min-height:0;}

.dwg-tree{
  width:200px;flex:0 0 auto;background:var(--bg-1);border-right:1px solid var(--border);
  overflow-y:auto;padding:10px 4px;
}
.dwg-tree-title{font-size:9px;letter-spacing:.08em;color:var(--text-2);font-weight:700;padding:0 6px 6px;}
.dwg-tree-node{
  font-size:12px;color:var(--text-1);padding:5px 6px;border-radius:6px;cursor:default;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.dwg-tree-doc{font-weight:700;color:var(--text-0);}
.dwg-tree-sheet{color:var(--text-1);}
.dwg-tree-view{cursor:pointer;}
.dwg-tree-view:hover{background:var(--bg-3);color:var(--text-0);}
.dwg-tree-view.is-selected{background:var(--accent-dim);color:#fff;}
.dwg-tree-empty{font-size:11px;color:var(--text-2);font-style:italic;padding:5px 6px;white-space:normal;}

.dwg-canvas-wrap{
  flex:1;min-width:0;position:relative;overflow:hidden;
  background:var(--bg-3);cursor:grab;
}
.dwg-canvas-wrap:active{cursor:grabbing;}
.dwg-svg{width:100%;height:100%;display:block;}

.dwg-props{
  width:230px;flex:0 0 auto;background:var(--bg-1);border-left:1px solid var(--border);
  overflow-y:auto;padding:12px;
}
.dwg-props-title{font-size:12px;font-weight:700;color:var(--text-0);margin-bottom:10px;}
.dwg-field{display:block;margin-bottom:10px;}
.dwg-field-label{display:block;font-size:10.5px;color:var(--text-2);margin-bottom:3px;}
.dwg-field select,.dwg-tb-input{
  width:100%;box-sizing:border-box;background:var(--bg-0);border:1px solid var(--border);
  color:var(--text-0);padding:6px 7px;border-radius:6px;font-size:12px;font-family:inherit;
}
textarea.dwg-tb-input{resize:vertical;min-height:44px;}
.dwg-props-pos{font-size:11px;color:var(--text-2);margin-bottom:12px;font-variant-numeric:tabular-nums;}
.dwg-props-delete{
  width:100%;background:transparent;border:1px solid var(--border);color:#e35b5b;
  padding:7px;border-radius:6px;cursor:pointer;font-size:12px;
}
.dwg-props-delete:hover{background:rgba(227,91,91,.12);border-color:#e35b5b;}

/* The sheet itself is always real paper -- white with black linework -- no
   matter which app theme is active, matching every technical drawing tool
   this feature is modelled on (Fusion, SolidWorks, ...) and satisfying the
   "professional" requirement literally: it has to look right on export too. */
.dwg-paper{fill:#ffffff;stroke:none;}
.dwg-border{fill:none;stroke:#000;stroke-width:.35;}
/* Model/view line weight roughly doubled (.35->.7) -- at normal editing
   zoom the old weight read as hairline-thin and was easy to lose against
   the white paper, especially for hidden-line dashes and anything near the
   dimension lines drawn on top of it. */
.dwg-line{fill:none;stroke:#000;stroke-width:.7;stroke-linejoin:round;stroke-linecap:round;}
.dwg-view-hit{fill:transparent;}
.dwg-view-outline{fill:none;stroke:var(--accent);stroke-width:.5;stroke-dasharray:2.2,1.4;vector-effect:non-scaling-stroke;}
/* Free-standing text boxes on the sheet (see render.js renderAnnotation). */
.dwg-annotation-text{font:600 5px "Segoe UI",sans-serif;fill:#000;white-space:pre;user-select:none;}
.dwg-annotation-hit{fill:transparent;cursor:move;}
.dwg-annotation-outline{fill:none;stroke:var(--accent);stroke-width:.5;stroke-dasharray:2,1.4;vector-effect:non-scaling-stroke;pointer-events:none;}
.dwg-line-hidden{stroke-dasharray:2,1.4;}
/* Invisible click target for an edge -- much wider than the visible line
   itself (which is why this is a separate stroked path, not just clicking
   .dwg-line) so hitting a line no longer takes pixel-perfect aim. */
.dwg-edge-hit{fill:none;stroke:transparent;stroke-width:6;pointer-events:stroke;cursor:pointer;}
.dwg-edge-selected{stroke:var(--accent);stroke-width:1;}
.dwg-tb-border{fill:#fff;stroke:#000;stroke-width:.45;}
.dwg-tb-rule{stroke:#000;stroke-width:.2;}
.dwg-tb-label{font:600 2.8px "Segoe UI",sans-serif;fill:#333;letter-spacing:.15px;}
.dwg-tb-value{font:700 3.3px "Segoe UI",sans-serif;fill:#000;}
/* Footer credit in the bottom-right margin strip -- quiet enough not to
   compete with the title block right above it. */
.dwg-sheet-mark{font:600 3px "Segoe UI",sans-serif;fill:#555;letter-spacing:.2px;}
.dwg-dim-line{stroke:#000;stroke-width:.5;}
.dwg-dim-ext{stroke:#000;stroke-width:.4;}
.dwg-dim-arrow{fill:#000;}
/* Dimension values are the thing you actually read off a drawing, so they
   are deliberately the largest, heaviest text on the sheet -- roughly
   double the original 3.1px and full bold. The white halo (paint-order
   stroke) keeps them legible where a value sits on top of model linework. */
.dwg-dim-text{
  font:700 6px "Segoe UI",sans-serif;fill:#000;user-select:none;
  paint-order:stroke;stroke:#fff;stroke-width:1.2;stroke-linejoin:round;
}
.dwg-dim-hit{fill:none;stroke:transparent;stroke-width:6;pointer-events:stroke;cursor:pointer;}
.dwg-dim.is-selected .dwg-dim-line,.dwg-dim.is-selected .dwg-dim-ext{stroke:var(--accent);}
.dwg-dim.is-selected .dwg-dim-arrow{fill:var(--accent);}
.dwg-dim.is-selected .dwg-dim-text{fill:var(--accent);}

/* scrollbars */
::-webkit-scrollbar{width:9px;height:9px;}
::-webkit-scrollbar-track{background:transparent;}
::-webkit-scrollbar-thumb{background:var(--bg-3);border-radius:5px;}
::-webkit-scrollbar-thumb:hover{background:var(--border);}

/* ---------- Section View (src/sectionView.js) ----------
   Top-LEFT, same card as #feature-panel (identical background/border/radius/
   shadow/offset), so it reads as one of the app's feature menus rather than a
   separate kind of thing.

   Unlike the pick tools it shares that corner with, Section View is a mode you
   stay in -- it can legitimately be open at the same time as a tool panel. The
   offset below is set from JS (see sectionView.js) to the feature panel's
   MEASURED height, so the two stack exactly instead of covering each other,
   and it is 0 whenever no tool panel is showing. A hard-coded offset would be
   a guess: the feature panel is three rows tall for Shell and ten for Hole. */
.sec-panel{
  position:absolute;top:calc(14px + var(--sec-stack-offset,0px));left:14px;
  background:var(--bg-2);border:1px solid var(--border);border-radius:8px;
  padding:12px 14px;width:236px;box-shadow:0 8px 24px rgba(0,0,0,.4);
  z-index:20;display:flex;flex-direction:column;gap:8px;
  /* No `transition:top` here. It looked nicer, but a transition only advances
     while the page is compositing -- and in a non-compositing view (the in-app
     preview pane is one) it never progresses past its start value, leaving the
     panel pinned at the OLD position forever while the variable behind it is
     perfectly correct. A panel that jumps is fine; one that silently stops
     moving is not. Same family of quirk as the rAF notes elsewhere. */
}
.sec-panel.hidden{display:none;}
.sec-title{font-weight:600;font-size:12px;color:var(--text-0);}
.sec-hint{font-size:11px;color:var(--text-2);line-height:1.4;}
.sec-row{display:flex;align-items:center;justify-content:space-between;gap:8px;}
.sec-label{font-size:11.5px;color:var(--text-1);}
.sec-row input[type=number]{
  width:92px;background:var(--bg-1);border:1px solid var(--border);border-radius:5px;
  color:var(--text-0);font-size:12px;padding:4px 6px;
}
/* Segmented X/Y/Z picker -- one control, three states, so the current section
   axis is readable at a glance instead of being buried in a <select>. */
.sec-seg{display:flex;border:1px solid var(--border);border-radius:6px;overflow:hidden;}
.sec-seg-btn{
  background:var(--bg-1);border:none;color:var(--text-1);
  font-size:11.5px;font-weight:600;padding:4px 12px;cursor:pointer;
}
.sec-seg-btn + .sec-seg-btn{border-left:1px solid var(--border);}
.sec-seg-btn:hover{background:var(--bg-3);color:var(--text-0);}
.sec-seg-btn.active{background:var(--accent);color:#fff;}
.sec-range{width:100%;accent-color:var(--accent);}
.sec-btn{
  background:var(--bg-1);border:1px solid var(--border);border-radius:6px;
  color:var(--text-1);font-size:11.5px;padding:5px 8px;cursor:pointer;text-align:center;
}
.sec-btn:hover{background:var(--bg-3);color:var(--text-0);}
.sec-close{margin-top:2px;}
.sec-check{display:flex;align-items:center;gap:7px;font-size:11.5px;color:var(--text-1);cursor:pointer;}
.sec-check input{accent-color:var(--accent);}

/* ---------- Measure (src/measureTool.js) ----------
   The floating number that sits next to what was measured, so the answer is
   where you are looking rather than only in the panel across the screen.
   Centered on its own anchor point via translate(-50%,-50%), and
   pointer-events:none so it can never swallow a click meant for the geometry
   underneath it. */
.msr-label{
  position:absolute;transform:translate(-50%,-50%);
  background:rgba(20,23,28,.92);border:1px solid var(--accent);border-radius:5px;
  color:#fff;font:600 12px "Segoe UI",sans-serif;padding:3px 7px;white-space:nowrap;
  pointer-events:none;z-index:22;box-shadow:0 3px 10px rgba(0,0,0,.45);
}
.msr-label.hidden{display:none;}
/* Readout inside #feature-panel: one headline number, then the breakdown. */
.msr-headline{font:700 17px "Segoe UI",sans-serif;color:var(--accent);margin:2px 0 6px;}
.msr-row{display:flex;justify-content:space-between;gap:10px;font-size:11.5px;color:var(--text-1);padding:2px 0;}
.msr-row span:last-child{color:var(--text-0);font-weight:600;}
.msr-note{font-size:11px;color:var(--text-2);line-height:1.4;}
