/* OBSCURA OS: the Engineering Suite.

   One working surface: the top bar across, the features to add under it,
   the model's history and variables on the left, the 3D view in the middle,
   the chosen feature's dimensions and the chosen body's measurements on the
   right, a status line across the foot. On a phone the columns stack under
   the view and the page scrolls.

   Every colour is a theme.css token, so the suite follows the colourway and
   the dark mode the rest of the site does. The view reads its own colours
   from the --eng-* tokens below (eng-view.js), and they are hex or tokens
   that are hex, because three.js parses them itself.
*/

:root {
  --eng-view: var(--paper-inset);
  --eng-grid: #dedbd3;
  --eng-grid-major: #c3bfb5;
  --eng-solid: #b3bcc9;
  --eng-solid-selected: var(--accent);
  --eng-edge: #2a2e36;
  --eng-measure: #c2410c;
  --eng-left: 264px;
  --eng-right: 316px;
}
:root[data-theme="dark"] {
  --eng-grid: #25252b;
  --eng-grid-major: #393941;
  --eng-solid: #8a94a4;
  --eng-edge: #0c0e12;
  --eng-measure: #ff7a45;
}

body.eng { margin: 0; background: var(--paper); color: var(--ink); font: var(--text-sm)/1.4 var(--font-sans); }
.eng *, .eng *::before, .eng *::after { box-sizing: border-box; }
.eng button, .eng input, .eng select, .eng textarea { font: inherit; color: inherit; }
.eng-sr { position: absolute !important; top: 0; left: 0; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.eng-grow { flex: 1; }

.eng-app {
  height: 100vh; height: 100dvh;
  display: grid;
  grid-template-columns: var(--eng-left) minmax(0, 1fr) var(--eng-right);
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  grid-template-areas: "top top top" "tools tools tools" "left stage right" "status status status";
}

/* ---------------------------------------------------------------- top bar */

.eng-top { grid-area: top; display: flex; align-items: center; gap: 6px; padding: 6px 10px; background: var(--paper-raised); border-bottom: 1px solid var(--rule); min-width: 0; }
.eng-home { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: var(--radius-md); color: var(--ink-soft); flex: none; }
.eng-home:hover { background: var(--paper-inset); color: var(--ink); }
.eng-home svg { width: 20px; height: 20px; }
.eng-brand { margin: 0 var(--space-1) 0 0; font-size: var(--text-md); font-weight: 650; letter-spacing: -.01em; white-space: nowrap; }
.eng-name { width: 220px; min-width: 0; padding: 6px 8px; border: 1px solid transparent; border-radius: var(--radius-sm); background: transparent; font-size: var(--text-sm); }
.eng-name:hover { border-color: var(--rule); }
.eng-name:focus { border-color: var(--accent); outline: none; background: var(--paper); }
/* The parts of the suite, the menus and the detail are one box in the
   markup so that a phone can scroll them as one row (below); here the box
   is not drawn and they stand in the bar in the order they always had. */
.eng-strip { display: contents; }
.eng-home, .eng-brand { order: -3; }
.eng-top .suite-parts { order: -2; }
.eng-name { order: -1; }
.eng-top .eng-quality { order: 1; }

.eng-menus { display: flex; gap: 2px; }
.eng-menu { position: relative; }
.eng-menu-btn { min-height: 36px; padding: 6px 11px; border: 0; border-radius: var(--radius-sm); background: transparent; font-size: var(--text-sm); font-weight: 500; cursor: pointer; }
.eng-menu-btn:hover, .eng-menu-btn[aria-expanded="true"] { background: var(--paper-inset); }
.eng-menu-list { position: absolute; z-index: 40; top: 100%; left: 0; min-width: 250px; margin-top: 4px; padding: 6px; border-radius: var(--radius-lg); background: var(--paper-raised); box-shadow: 0 0 0 1px var(--rule), 0 14px 36px rgba(16, 16, 24, .18); }
.eng-menu-list[hidden] { display: none; }
.eng-menu-list button { display: flex; width: 100%; align-items: baseline; justify-content: space-between; gap: 16px; min-height: 36px; padding: 8px 11px; border: 0; border-radius: var(--radius-sm); background: transparent; text-align: left; cursor: pointer; }
.eng-menu-list button:hover, .eng-menu-list button:focus-visible { background: var(--paper-inset); outline: none; }
.eng-menu-list button span, .eng-menu-list kbd { font-size: var(--text-2xs); color: var(--ink-faint); }
.eng-menu-list kbd { font-family: var(--font-mono); }
.eng-menu-list hr { border: 0; border-top: 1px solid var(--rule); margin: 6px 4px; }
/* A list is as wide as its longest command, on one line, with the words
   beside it wrapping if they must; and no taller than the window,
   scrolling inside rather than running off its foot (File holds twenty). */
.eng-menu-list { width: max-content; max-width: min(480px, calc(100vw - 20px)); max-height: calc(100vh - 58px); max-height: calc(100dvh - 58px); overflow-y: auto; overscroll-behavior: contain; }
.eng-menu-list button { white-space: nowrap; }
.eng-menu-list button span { white-space: normal; text-align: right; }
.eng-menu-help { width: 340px; padding: 10px 14px 12px; }
.eng-help-h { margin: 8px 0 4px; font-size: 11.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); }
.eng-help-p { margin: 0; font-size: var(--text-xs); color: var(--ink-soft); }
.eng-help-p code { font: var(--text-2xs) var(--font-mono); color: var(--ink); background: var(--paper-inset); padding: 1px 4px; border-radius: var(--radius-sm); }
.eng-keys { margin: 0; font-size: var(--text-xs); }
.eng-keys div { display: flex; justify-content: space-between; gap: 12px; padding: 3px 0; }
.eng-keys dt { color: var(--ink); font-weight: 500; }
.eng-keys dd { margin: 0; color: var(--ink-soft); text-align: right; }

.eng-ib { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; padding: 0; border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink-soft); cursor: pointer; flex: none; }
.eng-ib:hover:not(:disabled) { background: var(--paper-inset); color: var(--ink); }
.eng-ib:disabled { opacity: .35; cursor: default; }
.eng-ib svg { width: 17px; height: 17px; }
.eng-top-ib { width: 36px; height: 36px; }
.eng-top-ib svg { width: 19px; height: 19px; }
.eng-quality { display: inline-flex; align-items: center; gap: 6px; margin-left: 6px; font-size: var(--text-xs); color: var(--ink-soft); }
.eng-quality .eng-in { width: auto; min-height: 34px; }

/* ---------------------------------------------------------------- toolbar */

/* One row that never scrolls sideways: what does not fit is folded into
   More at its end (eng-app.js measures it), so the row can show its menu
   over the view rather than clip it. */
.eng-tools { grid-area: tools; position: relative; z-index: 35; display: flex; gap: 6px; padding: 6px 10px; background: var(--paper-raised); border-bottom: 1px solid var(--rule); min-width: 0; overflow: visible; }
.eng-tools .eng-tgroup[hidden], .eng-tools button[hidden], .eng-tmore[hidden] { display: none; }
.eng-tmore { position: relative; margin-left: auto; flex: none; }
.eng-tmore-btn[aria-expanded="true"] { background: var(--paper-inset); color: var(--ink); }
.eng-tmore-list { position: absolute; top: calc(100% + var(--space-1)); right: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px; width: min(360px, calc(100vw - 20px)); max-height: min(70vh, 560px); overflow-y: auto; padding: var(--space-2); border-radius: var(--radius-lg); background: var(--paper-raised); box-shadow: 0 0 0 1px var(--rule), 0 14px 36px rgba(16, 16, 24, .18); }
.eng-tmore-list[hidden] { display: none; }
.eng-tmore-h { grid-column: 1 / -1; margin: var(--space-2) var(--space-1) 2px; font-size: var(--text-2xs); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); }
.eng-tmore-h:first-child { margin-top: 0; }
.eng-tools .eng-tmore-list button { flex-direction: row; justify-content: flex-start; gap: var(--space-2); min-height: 44px; min-width: 0; padding: 6px 10px; text-align: left; }
.eng-tools .eng-tmore-list svg { flex: none; width: 20px; height: 20px; }
.eng-tgroup { display: flex; gap: 2px; padding-right: 6px; border-right: 1px solid var(--rule); }
.eng-tgroup:last-child { border-right: 0; }
.eng-tools button { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; min-width: 60px; min-height: 52px; padding: 6px 8px; border: 0; border-radius: var(--radius-md); background: transparent; color: var(--ink-soft); font-size: var(--text-2xs); cursor: pointer; }
.eng-tools button:hover { background: var(--paper-inset); color: var(--ink); }
.eng-tools button:active { background: var(--accent-soft); color: var(--accent-strong); }
.eng-tools svg { width: 22px; height: 22px; }
/* One line each, so the buttons on the row are all one height. */
.eng-tools .eng-tgroup button span { white-space: nowrap; }

/* ---------------------------------------------------------------- panels */

.eng-side { background: var(--paper-raised); overflow-y: auto; min-height: 0; scrollbar-width: thin; }
.eng-left { grid-area: left; border-right: 1px solid var(--rule); }
.eng-right { grid-area: right; border-left: 1px solid var(--rule); }
.eng-panel { padding: 10px 10px 14px; }
.eng-panel + .eng-panel { border-top: 1px solid var(--rule); }
/* The panels are filled once the kernel has loaded, and a History that
   grows from nothing pushes the panel under it down the page. Until then
   they hold their place unseen, and arrive already filled: each rises a
   step after the one above it, the right column a step after the left,
   on the site's own entrance (theme.css), so that with motion switched
   down they fade in where they sit and nothing moves. Six steps at most,
   so the whole side is in well inside --dur-5. */
html:not(.eng-ready) .eng-side > * { visibility: hidden; }
.eng-ready .eng-side > * { --os-fade: var(--dur-fade); animation: os-rise-soft var(--dur-4) var(--ease-standard) backwards; animation-delay: var(--eng-step, 0ms); }
.eng-ready .eng-right > * { --eng-step: var(--stagger); }
.eng-ready .eng-side > * + * { --eng-step: calc(var(--stagger) * 2); }
.eng-ready .eng-right > * + * { --eng-step: calc(var(--stagger) * 3); }
.eng-ready .eng-side > * + * + * { --eng-step: calc(var(--stagger) * 4); }
.eng-ready .eng-right > * + * + * { --eng-step: calc(var(--stagger) * 5); }
.eng-ready .eng-side > * + * + * + * { --eng-step: calc(var(--stagger) * 6); }
.eng-ph { display: flex; align-items: center; gap: 8px; margin: 2px 4px 8px; font-size: 11.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); }
.eng-count { font: 11px var(--font-mono); letter-spacing: 0; padding: 1px 6px; border-radius: var(--radius-pill); background: var(--paper-inset); color: var(--ink-soft); }
.eng-hint { margin: 4px; font-size: var(--text-xs); color: var(--ink-faint); }
.eng-empty { padding: 6px 4px; font-size: var(--text-xs); color: var(--ink-faint); list-style: none; }

/* History */
.eng-tree { list-style: none; margin: 0; padding: 0; }
.eng-row { position: relative; display: flex; align-items: center; border-radius: var(--radius-sm); }
.eng-row:hover { background: var(--paper-inset); }
.eng-row.eng-on { background: var(--accent-soft); }
.eng-row-main { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; min-height: 32px; padding: 4px 6px; border: 0; background: transparent; text-align: left; cursor: pointer; border-radius: var(--radius-sm); }
.eng-row-main svg { width: 17px; height: 17px; flex: none; color: var(--ink-soft); }
.eng-on .eng-row-main svg { color: var(--accent-strong); }
.eng-row-n { width: 18px; flex: none; font: 11px var(--font-mono); color: var(--ink-faint); text-align: right; }
.eng-row-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13.5px; }
.eng-on .eng-row-name { color: var(--accent-strong); font-weight: 550; }
.eng-off .eng-row-name { text-decoration: line-through; color: var(--ink-faint); }
.eng-off .eng-row-main svg { opacity: .5; }
.eng-err .eng-row-name { color: var(--danger); }
.eng-flag { display: inline-flex; flex: none; }
.eng-flag svg { width: 15px; height: 15px; }
.eng-flag-err svg { color: var(--danger); }
.eng-flag-warn svg { color: var(--warn); }
/* The row's buttons sit over the end of its name rather than beside it,
   so a name is not cut short by four buttons nobody is pointing at. */
.eng-row-acts { position: absolute; top: 50%; right: 2px; transform: translateY(-50%); display: flex; padding-left: 10px; border-radius: var(--radius-sm); background: var(--paper-inset); opacity: 0; pointer-events: none; transition: opacity var(--dur-2) var(--ease-standard); }
.eng-row.eng-on .eng-row-acts { background: var(--accent-soft); }
.eng-row:hover .eng-row-acts, .eng-row:has(:focus-visible) .eng-row-acts { opacity: 1; pointer-events: auto; }
.eng-row-acts .eng-ib { width: 26px; height: 26px; }
.eng-row-acts .eng-ib svg { width: 15px; height: 15px; }

/* The history as a timeline (eng-tree.js): a handle to drag a row by,
   the rollback marker, folders, and the rows after the marker dimmed. */
.eng-tree-wrap { position: relative; }
.eng-grip { width: 22px; flex: none; align-self: stretch; display: flex; align-items: center; justify-content: flex-end; padding-right: 2px; font: var(--text-2xs) var(--font-mono); color: var(--ink-faint); cursor: grab; touch-action: none; -webkit-user-select: none; user-select: none; }
.eng-dragging, .eng-dragging * { cursor: grabbing; }
.eng-row:hover .eng-grip { color: var(--ink-soft); }
.eng-infolder .eng-grip { width: 34px; }
.eng-after .eng-row-main, .eng-after .eng-grip, .eng-folder.eng-after .eng-folder-main { opacity: .45; }
.eng-rename { flex: 1; min-width: 0; min-height: 28px; padding: 2px 6px; }
.eng-folder { position: relative; display: flex; align-items: center; border-radius: var(--radius-sm); }
.eng-folder:hover { background: var(--paper-inset); }
.eng-folder-main { padding-left: 2px; }
.eng-fold-chev svg { width: 14px; height: 14px; transition: transform var(--dur-2) var(--ease-standard); }
.eng-folder-main[aria-expanded="true"] .eng-fold-chev svg { transform: rotate(90deg); }
.eng-folder .eng-row-name { font-weight: 550; }
.eng-folder:hover .eng-row-acts, .eng-folder:has(:focus-visible) .eng-row-acts { opacity: 1; pointer-events: auto; }
.eng-roll-li { list-style: none; }
.eng-roll { position: relative; display: flex; align-items: center; gap: var(--space-2); min-height: 24px; margin: 0; padding: 0 4px; border-radius: var(--radius-sm); cursor: ns-resize; touch-action: none; outline: none; }
.eng-roll-bar { flex: 1; height: 4px; border-radius: var(--radius-pill); background: var(--rule-strong); }
.eng-roll-up .eng-roll-bar { background: var(--accent); }
.eng-roll:hover .eng-roll-bar, .eng-roll:focus-visible .eng-roll-bar { background: var(--accent-strong); }
.eng-roll:focus-visible { box-shadow: 0 0 0 2px var(--accent); }
.eng-roll-note { flex: none; font-size: var(--text-2xs); color: var(--accent-strong); }
.eng-drop { position: absolute; left: 4px; right: 4px; height: 2px; border-radius: var(--radius-pill); background: var(--accent); pointer-events: none; }
.eng-ctx { position: fixed; z-index: 60; min-width: 220px; padding: 6px; border-radius: var(--radius-lg); background: var(--paper-raised); box-shadow: 0 0 0 1px var(--rule), 0 14px 36px rgba(16, 16, 24, .18); }
.eng-ctx button { display: flex; width: 100%; align-items: baseline; justify-content: space-between; gap: var(--space-4); min-height: 34px; padding: 6px 10px; border: 0; border-radius: var(--radius-sm); background: transparent; font-size: var(--text-xs); text-align: left; cursor: pointer; }
.eng-ctx button:hover:not(:disabled), .eng-ctx button:focus-visible { background: var(--paper-inset); outline: none; }
.eng-ctx button:disabled { color: var(--ink-faint); cursor: default; }
.eng-ctx kbd { font: var(--text-2xs) var(--font-mono); color: var(--ink-faint); }
.eng-ctx hr { border: 0; border-top: 1px solid var(--rule); margin: 4px; }

/* Variables */
.eng-vars { list-style: none; margin: 0 0 8px; padding: 0; }
.eng-var { display: grid; grid-template-columns: 62px auto minmax(0, 1fr) auto auto; align-items: center; gap: 5px; padding: 2px 0; }
.eng-eq { color: var(--ink-faint); font-family: var(--font-mono); }
.eng-var .eng-in { min-height: 30px; padding: 4px 6px; font: 12.5px var(--font-mono); }
.eng-var-val { min-width: 34px; font: var(--text-2xs) var(--font-mono); color: var(--ink-faint); text-align: right; }
.eng-var-val svg { width: 15px; height: 15px; color: var(--danger); vertical-align: middle; }
.eng-var.eng-err .eng-var-expr { border-color: var(--danger); }
.eng-var-cfg .eng-var-expr { border-color: var(--accent-border); background: var(--accent-soft); }
.eng-cfg { margin-top: var(--space-3); }
.eng-cfg-pick { margin: 0 0 var(--space-2); }
.eng-cfg-acts { display: flex; flex-wrap: wrap; gap: 6px; }
.eng-cfg-acts .eng-btn { flex: 1 1 auto; }
.eng-cfg-wrap { overflow-x: auto; margin-bottom: var(--space-3); }
.eng-cfg-table { border-collapse: collapse; font-size: var(--text-xs); }
.eng-cfg-table th, .eng-cfg-table td { padding: 4px 6px; border-bottom: 1px solid var(--rule); text-align: left; vertical-align: middle; }
.eng-cfg-table thead th { font-weight: 600; color: var(--ink-soft); white-space: nowrap; }
.eng-cfg-table .cad-in { min-width: 110px; }
.eng-cfg-th { display: flex; align-items: center; gap: 4px; }
.eng-cfg-table .eng-cfg-sub { padding-top: var(--space-3); font: 600 var(--text-2xs) var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint); }
.eng-cfg-check { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 32px; cursor: pointer; }
.eng-cfg-check input { width: 16px; height: 16px; margin: 0; accent-color: var(--accent); }
.eng-cfg-foot { flex-wrap: wrap; align-items: center; }
.eng-cfg-fmt { display: inline-flex; align-items: center; gap: var(--space-2); margin-left: auto; font-size: var(--text-xs); color: var(--ink-soft); }
.eng-cfg-fmt .cad-in { width: auto; }

/* Fields */
.eng-in { width: 100%; min-height: 32px; padding: 5px 8px; border: 1px solid var(--rule-strong); border-radius: var(--radius-sm); background: var(--paper); font-size: 13.5px; }
.eng-in:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }
select.eng-in { cursor: pointer; }
textarea.eng-in { resize: vertical; line-height: 1.45; }
.eng-mono { font-family: var(--font-mono) !important; font-size: 12.5px !important; }

.eng-props-head { display: flex; gap: 10px; align-items: flex-start; margin: 0 4px 12px; }
.eng-props-head svg { width: 26px; height: 26px; flex: none; color: var(--accent); margin-top: 1px; }
.eng-props-head b { display: block; font-size: 14.5px; }
.eng-props-head span { display: block; font-size: 12.5px; color: var(--ink-soft); }
.eng-field { display: grid; gap: 4px; margin: 0 4px 10px; }
.eng-field > span, .eng-set legend { font-size: 12.5px; color: var(--ink-soft); }
.eng-numrow { display: flex; align-items: center; gap: 8px; }
.eng-numrow .eng-in { font-family: var(--font-mono); font-size: var(--text-xs); }
.eng-numrow output { flex: none; min-width: 0; max-width: 45%; font: var(--text-2xs) var(--font-mono); color: var(--ink-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.eng-numrow output:empty { display: none; }
.eng-numrow output.eng-bad { color: var(--danger); white-space: normal; }
.eng-check { display: flex; align-items: center; gap: 8px; margin: 0 4px 8px; font-size: 13.5px; cursor: pointer; }
.eng-check input { width: 16px; height: 16px; margin: 0; accent-color: var(--accent); }
.eng-set { border: 0; padding: 0; }
.eng-set legend { padding: 0; margin-bottom: 6px; }
.eng-set .eng-check { margin-left: 0; }
.eng-msg { margin: 0 4px 10px; padding: 7px 10px; border-radius: var(--radius-sm); font-size: var(--text-xs); }
.eng-msg:empty { display: none; }
.eng-msg.eng-bad { background: var(--danger-soft); color: var(--danger); }
.eng-msg.eng-warn { background: var(--warn-soft); color: var(--warn); }
.eng-msg .eng-msg-act { display: block; margin-top: 8px; color: var(--ink); }

/* Body */
.eng-h { margin: 0 4px 8px; font-size: 14.5px; }
.eng-facts { margin: 0 4px 12px; }
.eng-facts div { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--rule); font-size: var(--text-xs); }
.eng-facts dt { color: var(--ink-soft); flex: none; }
.eng-facts dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; min-width: 0; }
.eng-facts select.eng-in { max-width: 190px; min-height: 30px; padding: 3px 6px; font-size: 12.5px; }
.eng-acts { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 4px; }
.eng-btn { min-height: 36px; padding: 6px 12px; border: 1px solid var(--rule-strong); border-radius: var(--radius-sm); background: var(--paper); font-size: var(--text-xs); cursor: pointer; }
.eng-btn:hover { background: var(--paper-inset); }
.eng-add { width: 100%; border-style: dashed; color: var(--ink-soft); }

/* ---------------------------------------------------------------- the view */

.eng-stage { grid-area: stage; position: relative; min-width: 0; min-height: 0; background: var(--eng-view); overflow: hidden; }
.eng-view { position: absolute; inset: 0; }
.eng-canvas { display: block; width: 100%; height: 100%; touch-action: none; outline: none; }
.eng-loading { position: absolute; inset: 0; margin: 0; min-height: 0; pointer-events: none; }
noscript .eng-loading, p.eng-loading { display: flex; align-items: center; justify-content: center; font-size: var(--text-sm); color: var(--ink-faint); }
.eng-ready .eng-loading { display: none; }
.eng-viewbar { position: absolute; top: 10px; left: 10px; right: 10px; display: flex; flex-wrap: wrap; gap: 6px; pointer-events: none; }
.eng-vgroup { display: flex; gap: 1px; padding: 3px; border-radius: var(--radius-md); background: var(--paper-raised); box-shadow: 0 0 0 1px var(--rule), 0 4px 14px rgba(16, 16, 24, .08); pointer-events: auto; }
.eng-viewbar button { min-height: 30px; padding: 4px 10px; border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink-soft); font-size: 12.5px; font-weight: 500; cursor: pointer; }
.eng-viewbar button:hover { background: var(--paper-inset); color: var(--ink); }
.eng-viewbar button[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-strong); }
/* The standard view the camera is in (eng-app.js marks it while the
   camera sits square on it), drawn as a pressed choice is. */
.eng-viewbar button[aria-current="true"] { background: var(--accent-soft); color: var(--accent-strong); }
.eng-measure-out { position: absolute; left: 50%; bottom: 14px; transform: translateX(-50%); display: flex; align-items: baseline; gap: 12px; margin: 0; padding: 8px 14px; border-radius: var(--radius-pill); background: var(--paper-raised); box-shadow: 0 0 0 1px var(--rule), 0 6px 18px rgba(16, 16, 24, .12); font-size: var(--text-xs); color: var(--ink-soft); white-space: nowrap; }
.eng-measure-out[hidden] { display: none; }
.eng-measure-out b { font: 600 var(--text-sm) var(--font-mono); color: var(--ink); }
.eng-measure-out span { font: var(--text-2xs) var(--font-mono); }

/* The seldom-changed fields of a feature, folded (eng-props.js). */
.eng-more { margin-top: var(--space-2); border-top: 1px solid var(--rule); }
.eng-more > summary { display: flex; align-items: center; min-height: 36px; cursor: pointer; color: var(--ink-soft); font-size: var(--text-xs); list-style-position: inside; }
.eng-more > summary:hover { color: var(--ink); }
.eng-more > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-sm); }
.eng-more[open] > summary { margin-bottom: var(--space-1); }
@media (max-width: 760px), (pointer: coarse) { .eng-more > summary { min-height: 44px; } }

/* A size taken by the mouse (eng-adjust.js): what is changing, its value
   and how to finish, along the foot of the view. */
.eng-adjust { position: absolute; left: 50%; bottom: 14px; transform: translateX(-50%); display: flex; align-items: baseline; gap: 12px; max-width: calc(100% - 24px); box-sizing: border-box; margin: 0; padding: 8px 14px; border-radius: var(--radius-md); background: var(--paper-raised); box-shadow: 0 0 0 1px var(--rule), 0 6px 18px rgba(16, 16, 24, .12); font-size: var(--text-xs); color: var(--ink-soft); }
.eng-adjust[hidden] { display: none; }
.eng-adjust b { color: var(--ink); font-weight: 600; white-space: nowrap; }
.eng-adjust output { font-family: var(--font-mono); font-size: var(--text-md); font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.eng-adjust output.eng-typed { color: var(--accent-strong); text-decoration: underline; text-underline-offset: 3px; }
.eng-adjust span { font-size: var(--text-2xs); }
.eng-adjusting .eng-view, .eng-adjusting .eng-view canvas { cursor: ew-resize; }
.eng-adjusting .eng-measure-out { display: none; }
/* A number field's name can be dragged to scrub it, with a mouse. */
@media (pointer: fine) { #engProps .eng-num > span:first-child { cursor: ew-resize; user-select: none; } }
.eng-scrubbing, .eng-scrubbing * { cursor: ew-resize !important; user-select: none; }

/* An empty part's start (eng-templates.js), as Foundry's empty drawing. */
.eng-start { position: absolute; top: 50%; left: 50%; width: min(560px, calc(100% - 32px)); box-sizing: border-box; max-height: calc(100% - 16px); overflow-y: auto; padding: 22px 24px; transform: translate(-50%, -50%); border-radius: var(--radius-lg); background: var(--paper-raised); box-shadow: 0 0 0 1px var(--rule), 0 20px 50px -30px rgba(0, 0, 0, 0.4); text-align: center; }
.eng-start[hidden], .eng-sketching .eng-start { display: none; }
/* Over the view cube, which sits in the corner of a phone's short view;
   under a sketch's own bar and the plane chooser. With no keys to press,
   it does not name them. */
.eng-start { z-index: 15; }
@media (pointer: coarse) { .eng-start-keys { display: none; } }
.eng-start .eng-start-head { margin: 0 0 6px; font-family: var(--font-headline); font-weight: 600; font-size: var(--text-xl); line-height: 1.2; color: var(--ink); }
.eng-start p { margin: 0 0 14px; color: var(--ink-soft); font-size: var(--text-sm); line-height: 1.5; }
.eng-start kbd { font-family: var(--font-mono); font-size: var(--text-2xs); padding: 1px 5px; border-radius: var(--radius-sm); background: var(--paper-inset); border: 1px solid var(--rule); }
.eng-start-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.eng-start .ob-example { margin-top: 8px; }

/* ---------------------------------------------------------------- status */

.eng-status { grid-area: status; display: flex; align-items: center; gap: 14px; min-height: 28px; padding: 4px 12px; background: var(--paper-raised); border-top: 1px solid var(--rule); font-size: var(--text-2xs); color: var(--ink-soft); }
/* The site's privacy badge (privacyproof.js, which the search brings)
   sits in the status bar's right end, as Foundry's does, rather than
   over the build message; the bar keeps room for it. On a phone it floats
   just above the bar. */
.eng-status { padding-right: 150px; }
body.eng #ppBadge { left: auto; right: 6px; bottom: 3px; min-height: 22px; padding: 1px 8px; font-size: var(--text-2xs); box-shadow: none; }
.eng-status .eng-bad { color: var(--danger); }
/* The keys for what is chosen (eng-hints.js), as Blender's status bar
   shows them: only where there is room and keys to press. */
.eng-keyhint { display: flex; align-items: center; gap: 14px; white-space: nowrap; color: var(--ink-faint); font-size: var(--text-2xs); }
.eng-keyhint:empty, .eng-adjusting .eng-keyhint { display: none; }
.eng-keyhint kbd { margin-right: 5px; padding: 0 5px; border: 1px solid var(--rule); border-radius: var(--radius-sm); font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--ink-soft); background: var(--paper-inset); }
@media (max-width: 1180px), (pointer: coarse) { .eng-keyhint { display: none; } }
.eng-xyz, .eng-units { font-family: var(--font-mono); color: var(--ink-faint); white-space: nowrap; }
.eng-units { display: inline-flex; align-items: center; gap: var(--space-1); }
.eng-units .eng-in { width: auto; min-height: 24px; padding: 1px 4px; font: inherit; font-size: var(--text-2xs); color: var(--ink-soft); }
#engBuilt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The exact kernel arriving (eng-exact.js): how much of it, beside the status. */
.eng-kload { display: inline-flex; align-items: center; gap: var(--space-2); min-width: 0; white-space: nowrap; font-size: var(--text-2xs); }
.eng-kload > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.eng-kload progress, .eng-kload-act { flex: none; }
.eng-kload[hidden] { display: none; }
.eng-kload progress { width: 96px; height: 6px; accent-color: var(--accent); }
.eng-kload progress[hidden], .eng-kload-act[hidden] { display: none; }
.eng-kload-act { min-height: 24px; padding: 0 var(--space-2); border: 1px solid var(--rule-strong); border-radius: var(--radius-sm); background: var(--paper); color: var(--ink-soft); font: inherit; font-size: var(--text-2xs); cursor: pointer; }
.eng-kload-act:hover { color: var(--ink); }
.eng-kload-act:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
@media (pointer: coarse) { .eng-kload-act { min-height: 44px; } }
/* A feature waiting for it says so in its message, with how far it has come. */
.eng-kwait { display: block; margin-top: var(--space-1); color: var(--ink-soft); }
.eng-msg .eng-kwait .eng-msg-act { display: inline-block; margin: 0 0 0 var(--space-2); }

/* ---------------------------------------------------------------- motion */

/* Everything here is on theme.css's tokens and keyframes, and governed by
   data-motion on <html> as the rest of the site is: with motion switched
   down every entrance below is a fade of --dur-fade, nothing moves under
   the pointer, and nothing loops.

   The hand. Every control answers it: colour settles over --dur-2 rather
   than snapping, and a button pressed on the toolbar, the view bar or the
   cube gives a hair under the finger for --dur-1. The focus ring is the
   site's, on everything the keyboard reaches. */
.eng-tools button, .eng-viewbar button, .eng-menu-btn, .eng-menu-list button, .eng-tmore-list button, .eng-ctx button,
.eng-ib, .eng-btn, .eng-row, .eng-row-main, .eng-folder, .eng-home, .eng-cube-btn, .eng-cube-look, .eng-display, .eng-measure-btn, .eng-link,
.eng-sk-bar button, .eng-sk-chooser button, .eng-body-row, .eng-clash-row, .eng-asm-row, .eng-in, .eng-name {
  transition: background-color var(--dur-2) var(--ease-standard), color var(--dur-2) var(--ease-standard),
    border-color var(--dur-2) var(--ease-standard), box-shadow var(--dur-2) var(--ease-standard), opacity var(--dur-2) var(--ease-standard);
}
.eng-tools button, .eng-viewbar button, .eng-cube-btn, .eng-ib, .eng-sk-bar button { transition-property: background-color, color, border-color, box-shadow, opacity, transform; }
.eng-tools button:active, .eng-viewbar button:active, .eng-cube-btn:active, .eng-ib:active:not(:disabled), .eng-sk-bar button:active { transform: scale(0.96); transition-duration: var(--dur-1); }
.eng-tools svg { transition: transform var(--dur-2) var(--ease-spring); }
:root:not([data-motion="none"]) .eng-tools button:hover svg { transform: translateY(-1px); }
.eng-tools button:focus-visible, .eng-viewbar button:focus-visible, .eng-menu-btn:focus-visible, .eng-ib:focus-visible, .eng-btn:focus-visible,
.eng-row-main:focus-visible, .eng-home:focus-visible, .eng-cube-btn:focus-visible, .eng-cube-look:focus-visible, .eng-display:focus-visible,
.eng-measure-btn:focus-visible, .eng-link:focus-visible, .eng-tmore-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.eng-row-main:focus-visible { outline-offset: -2px; }

/* Menus and the lists that open over the view arrive as the site's do:
   up from eight pixels over --dur-3. Closing is at once, as every menu's
   is. The two boxes that are centred by a transform of their own rise on
   keyframes that keep the centring, or they would have slid in from the
   side as the rise replaced it. */
.eng-menu-list, .eng-tmore-list, .eng-ctx { --os-fade: var(--dur-fade); animation: os-rise-soft var(--dur-3) var(--ease-standard) backwards; }
@keyframes eng-rise-x { from { opacity: 0; transform: translate(-50%, var(--os-rise-sm)); } }
@keyframes eng-rise-xy { from { opacity: 0; transform: translate(-50%, calc(-50% + var(--os-rise))); } }
.eng-measure-out, .eng-adjust { --os-fade: var(--dur-fade); animation: eng-rise-x var(--dur-3) var(--ease-standard) backwards; }
.eng-start { --os-fade: var(--dur-fade); animation: eng-rise-xy var(--dur-4) var(--ease-emph) backwards; }
.eng-start > * { --os-fade: var(--dur-fade); animation: os-rise-soft var(--dur-3) var(--ease-standard) backwards; animation-delay: var(--stagger); }
.eng-start > * + * { animation-delay: calc(var(--stagger) * 2); }
.eng-start > * + * + * { animation-delay: calc(var(--stagger) * 3); }
/* The view bar comes back when a sketch is finished (eng-sketch.css hides
   it while one is open), and fades in rather than appearing. */
.eng-viewbar { --os-fade: var(--dur-fade); animation: os-fade-in var(--dur-3) var(--ease-standard) backwards; }

/* The history. A feature just added rises into its place in the list
   (eng-tree.js marks it; a row drawn again after a build does not move),
   several at once a step apart, and the chosen row's colour settles. */
.eng-row-new { --os-fade: var(--dur-fade); animation: os-rise-soft var(--dur-3) var(--ease-standard) backwards; animation-delay: calc(var(--stagger) * var(--i, 0)); }

/* The Properties panel. A different feature chosen draws its form afresh:
   the heading rises and the fields follow a step after it (eng-props.js
   asks for it only then, not when a choice in the form redraws it). A
   fold opened lets its fields in the same way. */
.eng-props-in > .eng-props-head { --os-fade: var(--dur-fade); animation: os-rise-soft var(--dur-3) var(--ease-standard) backwards; }
.eng-props-in > :not(.eng-props-head) { --os-fade: var(--dur-fade); animation: os-fade-in var(--dur-3) var(--ease-standard) var(--stagger) backwards; }
.eng-more[open] > :not(summary) { --os-fade: var(--dur-fade); animation: os-rise-soft var(--dur-3) var(--ease-standard) backwards; }

/* Figures settle rather than flick: a measurement in its bubble, the
   size being taken by the mouse, and the status line's each new word. */
.eng-measure-out .eng-measure-text b, .eng-said { --os-fade: var(--dur-fade); animation: os-fade-in var(--dur-2) var(--ease-standard) backwards; }

/* A build still running after a moment (eng-app.js puts eng-building on
   <html> then) draws a hairline in the accent along the top of the view,
   breathing slowly, so that the model on show is known to be the old one;
   it fades out when the new one is drawn. With motion switched down the
   line simply stands there. */
.eng-stage::after { content: ""; position: absolute; z-index: 5; top: 0; left: 0; right: 0; height: 2px; background: var(--accent); opacity: 0; pointer-events: none; transition: opacity var(--dur-2) var(--ease-standard); }
.eng-building .eng-stage::after { opacity: 1; animation: ob-breathe var(--dur-sweep) var(--ease-standard) infinite alternate; }

/* ---------------------------------------------------------------- narrower */

@media (max-width: 1180px) {
  :root { --eng-left: 232px; --eng-right: 288px; }
  .eng-name { width: 160px; }
  .eng-tools button { min-width: 54px; }
}
/* A laptop's or a tablet's width: the bar held the suite's name, the
   part's name, six menus and two choices with their words, and at 1024px
   ran 100px past the window, the part's name squeezed to nothing. The
   suite's name and the choices' words are still read out; the menus sit
   closer; the part's name gives way first; and below 980px undo, the
   history and the two choices go on a second row of their own rather than
   off the edge. */
@media (min-width: 761px) and (max-width: 1280px) {
  .eng-brand, .eng-quality > span:first-child { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
  .eng-quality { margin-left: 2px; }
  .eng-menu-btn { padding: 6px 8px; }
  .eng-name { flex: 0 1 160px; min-width: 96px; }
}
@media (min-width: 761px) and (max-width: 980px) {
  .eng-top { flex-wrap: wrap; row-gap: 2px; }
  .eng-top .eng-grow { flex: 1 0 100%; height: 0; }
}

/* A phone, or a narrow window: one column, the view first, the page
   scrolls. Everything a finger presses is at least 44px. */
@media (max-width: 760px) {
  .eng-status { padding-right: 12px; }
  body.eng #ppBadge { right: var(--space-3); bottom: 56px; min-height: 44px; }
  /* The view straight after the toolbar, then what is chosen, then the
     history: the order a finger works in, whatever the order in the page. */
  .eng-app { display: flex; flex-direction: column; height: auto; }
  .eng-top { order: 1; } .eng-tools { order: 2; } .eng-stage { order: 3; }
  .eng-right { order: 4; } .eng-left { order: 5; } .eng-status { order: 6; }
  /* Two rows, not four: the mark, the part's name, Undo, Redo and the
     history; then the two parts of the suite, the menus and the detail in
     one row that scrolls sideways. The name of the suite is the mark's
     own label. Wrapped, the bar was two hundred pixels and the toolbar
     under it seventy more before the part was seen. */
  .eng-top { flex-wrap: wrap; gap: 0 4px; padding: 6px 8px 0; position: sticky; top: 0; z-index: 36; }
  .eng-top .eng-grow, .eng-brand { display: none; }
  .eng-top-ib { order: 0; }
  .eng-home, .eng-top-ib, .eng-menu-btn { min-width: 44px; min-height: 44px; }
  .eng-name { flex: 1 1 0; width: auto; border-color: var(--rule); min-height: 44px; }
  .eng-strip {
    display: flex; align-items: center; gap: 6px; order: 5; flex: 1 1 100%; min-width: 0;
    margin: 0 -8px; padding: 2px 8px; overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
  }
  .eng-strip::-webkit-scrollbar { display: none; }
  .eng-strip > *, .eng-strip .eng-menu { flex: none; }
  .eng-strip .eng-quality { margin-left: 0; }
  .eng-quality .eng-in { min-height: 44px; }
  .eng-quality span { display: none; }
  /* A menu opens over the toolbar (the bar is above it), and one longer
     than the screen, Help with its keys, scrolls inside itself. */
  .eng-menu-list { position: fixed; left: 10px; right: 10px; top: auto; min-width: 0; width: auto; max-height: calc(100svh - 112px); overflow-y: auto; overscroll-behavior: contain; }
  .eng-menu-help { width: auto; }
  .eng-menu-list button { min-height: 44px; }
  .eng-tools { padding: 2px 8px; }
  .eng-tools button { min-height: 44px; min-width: 54px; padding: 2px 6px; gap: 1px; }
  .eng-tools svg { width: 18px; height: 18px; }
  .eng-stage { height: 58vh; height: 58svh; min-height: 300px; }
  .eng-viewbar { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; pointer-events: auto; left: 0; right: 0; top: 0; padding: 4px 8px; }
  .eng-vgroup { flex: none; }
  .eng-viewbar button { min-height: 44px; min-width: 44px; padding: 4px 8px; }
  .eng-side { overflow: visible; border: 0; }
  .eng-right { border-bottom: 1px solid var(--rule); }
  .eng-ib, .eng-row-acts .eng-ib { width: 44px; height: 44px; }
  .eng-row-acts { position: static; transform: none; padding: 0; background: transparent; opacity: 1; pointer-events: auto; }
  .eng-row-main, .eng-in, .eng-btn, .eng-var .eng-in, .eng-facts select.eng-in { min-height: 44px; }
  .eng-check { min-height: 44px; }
  .eng-var { grid-template-columns: 70px auto minmax(0, 1fr) auto auto; }
  .eng-status { position: sticky; bottom: 0; }
  .eng-xyz { display: none; }
  .eng-adjust { flex-wrap: wrap; justify-content: center; row-gap: 2px; }
  .eng-start { padding: 16px; }
  .eng-start .eng-start-head { font-size: var(--text-lg); }
  .eng-start p { font-size: var(--text-xs); margin-bottom: 10px; }
  .eng-start .btn { min-height: 44px; }
  .eng-start-row { display: grid; grid-template-columns: 1fr 1fr; }
  .eng-measure-out { white-space: normal; flex-wrap: wrap; justify-content: center; max-width: calc(100% - 20px); border-radius: var(--radius-lg); }
}
@media (max-width: 760px), (pointer: coarse) {
  /* A finger: the part's name, the units, the rows that open a section,
     the marker and the handles are all at least 44px. */
  .eng-name, .eng-units .eng-in, .eng-rename { min-height: 44px; }
  .eng-name { min-width: 44px; }
  .eng-an summary, .eng-mass summary { box-sizing: border-box; min-height: 44px; padding-block: 12px; }
  .eng-roll { min-height: 44px; }
  .eng-grip { width: 44px; justify-content: center; }
  .eng-ctx button, .eng-tmore-list button { min-height: 44px; }
}
@media (pointer: coarse) {
  .eng-ib, .eng-row-acts .eng-ib, .eng-top-ib { width: 44px; height: 44px; }
  .eng-row-acts { position: static; transform: none; padding: 0; background: transparent; opacity: 1; pointer-events: auto; }
  .eng-row-main, .eng-menu-list button, .eng-viewbar button, .eng-menu-btn { min-height: 44px; }
}

/* The lock screen (theme.css draws it) quotes one expression. */
.pro-lock-gets code { font: 13.5px var(--font-mono); color: var(--ink); background: var(--paper-inset); padding: 1px 5px; border-radius: var(--radius-sm); }

/* The tour (pro-code/eng-coach.js), drawn as the Photo Editor's is: a
   card beside each stop with that part outlined. */
.eng-coach { position: fixed; z-index: 90; width: min(300px, calc(100vw - 16px)); box-sizing: border-box; padding: 12px 14px; border-radius: var(--radius-md); background: var(--paper); color: var(--ink); box-shadow: 0 0 0 1px var(--accent), 0 14px 36px -10px rgba(0,0,0,.45); font-size: var(--text-xs); line-height: 1.45; }
.eng-coach h2 { margin: 0 0 4px; font-size: var(--text-sm); font-weight: 600; color: var(--ink); }
.eng-coach p { margin: 0 0 10px; color: var(--ink-soft); }
.eng-coach .eng-coach-n { margin: 0 0 4px; font-size: var(--text-2xs); color: var(--accent-strong); }
.eng-coach-row { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 6px; }
.eng-coach-row .eng-coach-go { background: var(--accent-strong); border-color: var(--accent-strong); color: var(--paper); }
.eng-coach-row .eng-coach-go:hover { background: var(--accent); border-color: var(--accent); }
.eng-coach-row .eng-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.eng-coach-target { outline: 2px solid var(--accent) !important; outline-offset: -2px; }
