/* =================================================================
   STRATOS LASER — Instant Quote page.
   All shared tokens (surfaces, hairline triad, text scale, the steel-blue
   accent, fonts, motion) come from /tokens.css — the one design system the
   store and part builder also consume. This sheet keeps only page-local
   values and legacy aliases for its own selectors. Nav + footer live in
   /chrome.css.
   ================================================================= */

:root {
  /* legacy aliases -> the shared system (tokens.css) */
  --black: var(--bg);
  --white: var(--fg);
  --offwhite: var(--fg);
  --gray-900: var(--panel);
  --gray-800: var(--panel-2);
  --gray-700: var(--panel-3);
  --slate: #20242a;
  --gray-500: var(--fg-3);
  --gray-400: var(--fg-2);
  /* old single-weight hairlines -> the triad's middle + top weights */
  --line: var(--line-2);
  --line-strong: var(--line-3);

  --track: 0.02em;
  --track-sm: 0.02em;
  --maxw: 1180px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }
/* solid accent, dark ink — the old --accent-soft was 10% alpha, invisible
   over dark inputs (operator 2026-09-03: highlight "doesn't show") */
::selection { background: var(--accent); color: #0b0c0e; }

body {
  font-family: var(--font);
  background: var(--black);
  color: var(--white);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }

/* ---------------------------- TYPOGRAPHY ---------------------------- */
.eyebrow {
  /* store idiom: small letterspaced mono, tinted with the one accent */
  text-transform: uppercase;
  letter-spacing: .16em;
  font: 600 10.5px var(--mono);
  color: var(--accent);
  text-shadow: 0 0 14px var(--accent-glow);
  margin-bottom: 18px;
}
.eyebrow--center { text-align: center; }

.section__title {
  text-transform: uppercase;
  letter-spacing: -1px;   /* SpaceX negative tracking on display type */
  font-weight: 700;
  font-size: clamp(28px, 5vw, 52px);
  line-height: 1.05;
  text-align: center;
}

.section__lead {
  text-align: center;
  color: var(--gray-400);
  max-width: 620px;
  margin: 22px auto 0;
  font-size: 17px;
  font-weight: 300;
}

.eyebrow--center + .section__title { margin-top: 0; }

/* ---------------------------- LAYOUT ---------------------------- */
 html, body { overflow-x: clip; }   /* clip, not hidden: keeps sticky alive */

.container {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 28px;
}
.container--narrow { max-width: 720px; }
.center { text-align: center; }

.section {
  padding: clamp(72px, 12vh, 140px) 0;
  /* no border-top: sections share one background colour and the sec-bg
     scrims fade every image to var(--bg) at both edges, so the renders ARE
     the separators (operator 2026-08-30: "let the images be the separator") */
  position: relative;                 /* anchors the section video background */
  overflow: hidden;
}

/* ---- section video backgrounds ----
   Real part footage running behind a section, dialled right down so it reads
   as texture rather than content. The scrim does two jobs: it holds contrast
   under the copy, and it fades the clip into the page colour at the top and
   bottom edges so sections blend instead of showing a hard video seam.
   Playback is gated by an IntersectionObserver (script.js) — decoding five
   1440p streams at once would cost more than the whole page. */
.sec-bg {
  position: absolute; inset: 0; overflow: hidden;
  pointer-events: none; z-index: 0;
}
.sec-bg video, .sec-bg img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  opacity: .22; filter: saturate(.5) contrast(1.06);
}
.sec-bg::after {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(ellipse at 50% 50%, rgba(6,7,8,.45) 0%, rgba(6,7,8,.86) 72%),
    linear-gradient(180deg, var(--bg) 0%, rgba(6,7,8,0) 16%,
                    rgba(6,7,8,0) 84%, var(--bg) 100%);
}

/* ---- a part standing off to one side ----
   An upright part is tall and narrow, so washing it across the whole section
   wastes it. Anchored to one edge it can run at real opacity and read as an
   object in the room rather than wallpaper; the gradient dissolves it toward
   the copy so nothing competes with the text. Sides alternate down the page. */
.sec-bg--side { left: auto; right: -2%; width: min(27%, 380px); }
.sec-bg--side.is-left { right: auto; left: -2%; }
.sec-bg--side video, .sec-bg--side img {
  object-fit: cover; object-position: 50% 50%; opacity: .42;
}
/* dissolve hard toward the copy: on a 1600-wide viewport the container edge is
   already inside this column, so the part has to be gone before it gets there */
.sec-bg--side::after {
  background:
    linear-gradient(90deg, var(--bg) 0%, var(--bg) 34%, rgba(6,7,8,.45) 62%,
                    rgba(6,7,8,0) 100%),
    linear-gradient(180deg, var(--bg) 0%, rgba(6,7,8,0) 14%,
                    rgba(6,7,8,0) 86%, var(--bg) 100%);
}
.sec-bg--side.is-left::after {
  background:
    linear-gradient(270deg, var(--bg) 0%, var(--bg) 34%, rgba(6,7,8,.45) 62%,
                    rgba(6,7,8,0) 100%),
    linear-gradient(180deg, var(--bg) 0%, rgba(6,7,8,0) 14%,
                    rgba(6,7,8,0) 86%, var(--bg) 100%);
}
@media (max-width: 1100px) { .sec-bg--side { display: none; } }
/* A section can ask for its part to read louder than the default texture: more
   of the image, and a scrim that only protects the middle where the copy is. */
.sec-bg--strong video, .sec-bg--strong img { opacity: .46; filter: saturate(.62) contrast(1.04); }
.sec-bg--strong::after {
  background:
    radial-gradient(ellipse at 50% 50%, rgba(6,7,8,.62) 0%, rgba(6,7,8,.30) 58%,
                    rgba(6,7,8,.10) 100%),
    linear-gradient(180deg, var(--bg) 0%, rgba(6,7,8,0) 13%,
                    rgba(6,7,8,0) 87%, var(--bg) 100%);
}
/* The graded trio reads too dim under the default strong veil (operator
   2026-08-27: "as the background it should be slightly grayed out but not
   by that much"). Quote section only — the other strong sections keep the
   shared treatment. */
#quoteBg img { opacity: .64; filter: saturate(.8) contrast(1.05); }
#quoteBg::after {
  background:
    radial-gradient(ellipse at 50% 50%, rgba(6,7,8,.46) 0%, rgba(6,7,8,.18) 58%,
                    rgba(6,7,8,.05) 100%),
    linear-gradient(180deg, var(--bg) 0%, rgba(6,7,8,0) 13%,
                    rgba(6,7,8,0) 87%, var(--bg) 100%);
}
/* Form-less sections show their renders nearly full-strength (operator
   2026-08-28: "the backgrounds ... need to be less hidden or grayed out,
   unless there is a form on the section there is no reason"). The quote
   and request sections carry forms, so they keep their stronger veils. */
.section--process .sec-bg--strong img, .section--process .sec-bg--strong video,
.section--cap .sec-bg--strong img, .section--cap .sec-bg--strong video {
  opacity: .78; filter: saturate(.9) contrast(1.04);
}
.section--process .sec-bg--strong::after,
.section--cap .sec-bg--strong::after {
  background:
    radial-gradient(ellipse at 50% 50%, rgba(6,7,8,.28) 0%, rgba(6,7,8,.10) 58%,
                    rgba(6,7,8,0) 100%),
    linear-gradient(180deg, var(--bg) 0%, rgba(6,7,8,0) 13%,
                    rgba(6,7,8,0) 87%, var(--bg) 100%);
}
.section--contact .sec-bg img, .section--contact .sec-bg video {
  opacity: .60; filter: saturate(.85) contrast(1.05);
  /* Pan the cover-crop DOWN the clip. The section is ~502 tall with its copy
     occupying 132-370; the see-sawing part sweeps 262 (+/-131 about its own
     centre), so a centred crop drags the shaft straight through the lead
     paragraph. The whole sweep stays visible for any pan between 29% and 71%
     — 33% is the low end of that, which drops the part under the copy and
     leaves only the rising end crossing behind the buttons. Only bites where
     the crop actually overflows vertically: on narrow screens cover scales by
     height instead and this is a no-op. */
  object-position: 50% 33%;
}
.section--contact .sec-bg::after {
  background:
    radial-gradient(ellipse at 50% 50%, rgba(6,7,8,.34) 0%, rgba(6,7,8,.14) 60%,
                    rgba(6,7,8,.02) 100%),
    linear-gradient(180deg, var(--bg) 0%, rgba(6,7,8,0) 14%,
                    rgba(6,7,8,0) 86%, var(--bg) 100%);
}

/* keep every section's own content above its backdrop */
.section > .container { position: relative; z-index: 1; }
@media (prefers-reduced-motion: reduce) { .sec-bg video { opacity: .12; } }
/* #quote fills exactly ONE screen like the hero: a flex-centered viewport box
   (nav-aware padding), with the internal rhythm compressing on short screens
   (vh-aware clamps) so the idle state — title → toggle → dropzone → CTA —
   always lands whole in the first view. Once a conversion result opens the
   section grows past the fold, as a working surface must. */
.section--quote {
  background: var(--bg);
  box-sizing: border-box;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: calc(var(--nav-h) + clamp(16px, 3vh, 40px)) 0 clamp(22px, 4vh, 56px);
}
.section--quote .eyebrow { margin-bottom: clamp(6px, 1.5vh, 18px); }
.section--quote .section__lead { margin-top: clamp(8px, 1.6vh, 22px); }
/* header block reads from the left; everything in this section does now */
.section--quote .eyebrow,
.section--quote .section__title { text-align: left; }
.section--quote .section__lead { text-align: left; margin-left: 0; margin-right: auto; }
/* the console reads left-to-right: the commit button hangs on the card's
   left edge, full-width so it reads as the card's own bottom rail */
.section--quote .quote-cta { margin-top: clamp(12px, 2.5vh, 32px); text-align: left; }
.section--quote #cadCta .btn { width: 100%; justify-content: center; }

/* ---- the quote CONSOLE (ground-up redo, operator 2026-08-30) ----
   Idle state is a two-column stage: LEFT the action (header, drop card, two
   quiet path rows), RIGHT the always-on pipeline rail. The conversion
   result (#conv) and the drawing-spec panel sit OUTSIDE the split as full-
   width surfaces — #conv's breakout-centering math needs a page-centred
   parent, which is also why both moved out of #tab-cad. */
.qsplit {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 360px);
  gap: clamp(32px, 5vw, 96px);
  align-items: start;
  width: 100%;
}
.qmain { min-width: 0; }
.qrail {
  border-left: 1px solid var(--line);
  padding-left: clamp(20px, 2.4vw, 34px);
  /* optically level with the title, not the eyebrow */
  margin-top: clamp(20px, 4vh, 44px);
}
.qrail__title {
  text-transform: uppercase;
  letter-spacing: var(--track);
  font: 600 11px var(--mono);
  color: var(--accent);
  margin-bottom: 20px;
}
.qrail .pipeline { margin-bottom: 18px; }
.qrail__note {
  color: var(--gray-500);
  font-size: 12px;
  line-height: 1.6;
}

/* ---- HOME variant (data-iq-handoff): the console slimmed to a single left
   column — the drop hands off to /instant-quote, so the pipeline rail and
   commit button live THERE and the family render owns the right of the
   band (operator 2026-08-30). */
body[data-iq-handoff] .qsplit { display: block; }
body[data-iq-handoff] .qmain { max-width: 640px; }
body[data-iq-handoff] #cadCta { display: none; }
/* the conversion machinery stays in the home DOM only so the shared
   script binds — it must NEVER render here; quoting lives on /instant-quote */
body[data-iq-handoff] #conv,
body[data-iq-handoff] #specHost,
body[data-iq-handoff] #filelist,
body[data-iq-handoff] #result { display: none !important; }
/* the family render shows WHOLE and untouched (operator 2026-08-30: no
   zooming, no cropping), anchored RIGHT so the console owns the left. The
   host is painted the render's OWN background black (#010102, sampled from
   the file — the page's --bg #060708 is lighter and read as a grey strip),
   so any space the photo doesn't reach extends it invisibly. */
body[data-iq-handoff] #quoteBg { background: #010102; }
body[data-iq-handoff] #quoteBg img {
  object-fit: contain;
  object-position: 100% 50%;
  /* "slightly smaller so it fits": 92% height, right-anchored — the freed
     margin is the render's own black, so the photo just gains clean air
     around it and the console gains clearance on the left */
  height: 92%;
  margin-top: 2.5%;
}
body[data-iq-handoff] #quoteBg::after {
  background:
    linear-gradient(180deg, var(--bg) 0%, rgba(6,7,8,0) 13%,
                    rgba(6,7,8,0) 87%, var(--bg) 100%);
}

/* ==================== /instant-quote WORKBENCH ====================
   The tool page is an APPLICATION surface, deliberately unlike the
   marketing site (operator 2026-08-30): blueprint-grid ground, a
   workspace bar naming where you are and who you are, and a fixed
   two-panel bench. All scoped to body[data-iq-tool]; the landing page
   never sees any of it. */
/* same ground as the home page — no texture (operator 2026-08-30: "get rid
   of the graph paper background ... make it CLEAN, same theme as home") */
body[data-iq-tool] { background: var(--bg); }
/* the header is the locator (home design language — display title + lead);
   this quiet mono line beneath it carries who is signed in + the way back */
.iq-meta {
  margin-top: 16px;
  font: 500 11.5px var(--mono);
  letter-spacing: var(--track-sm);
  color: var(--gray-500);
  display: flex; gap: 22px; align-items: center;
}
.iq-meta a { color: var(--gray-400); text-decoration: none;
  text-transform: uppercase; }
.iq-meta a:hover { color: var(--white); }

/* the page runs WIDE (operator 2026-08-30: "can take up more width by all
   means") — the sheet of numbers earns it */
body[data-iq-tool] .container { max-width: min(1560px, 94vw); }
/* the whole idle console fits ONE viewport (operator 2026-08-30: "all in
   view without having to scroll") — compressed vertical rhythm */
body[data-iq-tool] .section--quote {
  min-height: 0;
  display: block;
  padding: calc(var(--nav-h) + clamp(14px, 2.5vh, 28px)) 0 clamp(28px, 4vh, 48px);
}
body[data-iq-tool] .section__title { font-size: clamp(26px, 4vw, 44px); }
body[data-iq-tool] .section__lead { margin-top: 10px; font-size: 15.5px; }
body[data-iq-tool] .iq-meta { margin-top: 10px; }

/* HOW THE NUMBER IS MADE as a horizontal STEPPER band under the header:
   idle it narrates the flow; during a conversion setStage() lights these
   same rows in place (operator 2026-08-30 restructure). */
body[data-iq-tool] .qrail {
  border: 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 12px 0;
  margin-top: clamp(10px, 1.8vh, 20px);
  display: flex; align-items: center; gap: clamp(20px, 3vw, 44px);
}
body[data-iq-tool] .qrail__title { margin: 0; flex-shrink: 0; }
body[data-iq-tool] .qrail__note { display: none; }
body[data-iq-tool] .pipeline {
  display: flex; align-items: center;
  gap: clamp(16px, 2.4vw, 40px);
  margin: 0; flex: 1; min-width: 0;
}
body[data-iq-tool] .pl {
  display: flex; align-items: center; gap: 8px;
  margin: 0; white-space: nowrap; font-size: 11px;
}
body[data-iq-tool] .pl__label em { display: none; }
body[data-iq-tool] .pl[hidden] { display: none; }

/* the working area */
.workbench { margin-top: clamp(10px, 1.8vh, 20px); }
body[data-iq-tool] .tabpanel { max-width: none; }
/* IDLE: the drop surface is the stage — one large cinematic panel over a
   dimmed catalog render, copy centred, nothing else competing */
body[data-iq-tool] .dropzone {
  margin-top: 0;
  min-height: clamp(180px, 25vh, 280px);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  text-align: center;
  /* the default part on the drop surface (operator 2026-08-30): a dogbone
     + spiral with slot rings on either end — rendered for this panel from
     renders/prototypes/2026-08-30_iq_dropzone/iq_dropslots.py */
  background:
    linear-gradient(rgba(2, 3, 4, .44), rgba(2, 3, 4, .68)),
    url("/media/round8/stills/iq_dropslots_1920.png?v=4") center / cover,
    #010102;
}
body[data-iq-tool] .dropzone[hidden] { display: none; }
body[data-iq-tool] .dropzone__icon { float: none; margin: 0 0 16px; }
body[data-iq-tool] .dropzone__title { font-size: 18px; }
body[data-iq-tool] .dropzone__note {
  text-align: center; margin-left: auto; margin-right: auto;
}
body[data-iq-tool] #cadCta { text-align: center; }
body[data-iq-tool] #cadCta .btn { width: auto; min-width: 320px; }
body[data-iq-tool] #filelist { max-width: 560px; margin-left: auto; margin-right: auto; }
/* the conv surface: flat in the flow, no divider */
body[data-iq-tool] .conv {
  width: auto; margin: 0; border-top: 0; padding-top: 0;
}
body[data-iq-tool] #specHost .conv { margin-top: 0; }
/* the tool page's requirements band mirrors home: card LEFT, render right */
body[data-iq-tool] .section--req .reqcard { margin-left: 0; margin-right: auto; }
body[data-iq-tool] .section--req .sec-bg--strong img { transform: none; }
body[data-iq-tool] .section--req .sec-bg--strong::after {
  background:
    linear-gradient(270deg, rgba(6,7,8,0) 42%, rgba(6,7,8,.5) 72%, rgba(6,7,8,.72) 100%),
    linear-gradient(180deg, var(--bg) 0%, rgba(6,7,8,0) 13%,
                    rgba(6,7,8,0) 87%, var(--bg) 100%);
}

/* the doors at the foot of the page */
body[data-iq-tool] .qpaths { margin-top: clamp(10px, 1.6vh, 18px); }
/* idle has nothing to continue TO — the commit button appears with files
   (the PDF flow needs it; a dead disabled button costs a viewport row) */
body[data-iq-tool] #tab-cad:has(#filelist[hidden]) #cadCta { display: none; }
body[data-iq-tool] .qpaths .toggle__btn { padding-top: 9px; padding-bottom: 9px; }
body[data-iq-tool] .dropzone__note { margin-top: 5px; font-size: 11.5px; }

/* ---- workbench MODEL STATE (operator 2026-08-30: the dropped model
   should "make more sense and not be as cheap" and sit comfortably above
   the NO DESIGN YET band). The stage frames the viewer as an instrument:
   corner ticks like the dropzone, a vignette grounding the part instead
   of a flat black void, and typography pulled from the workbench kit. ---- */
body[data-iq-tool] .conv__previewwrap {
  position: relative;
  border-color: var(--line);
  background:
    radial-gradient(ellipse at 50% 42%, rgba(127, 160, 204, .06) 0%,
                    rgba(0, 0, 0, 0) 58%),
    #050607;
}
body[data-iq-tool] .conv__previewwrap::before,
body[data-iq-tool] .conv__previewwrap::after {
  content: ""; position: absolute; width: 16px; height: 16px;
  border: 0 solid rgba(127, 160, 204, .5);
  pointer-events: none; z-index: 6;
}
body[data-iq-tool] .conv__previewwrap::before {
  top: -1px; left: -1px; border-top-width: 2px; border-left-width: 2px; }
body[data-iq-tool] .conv__previewwrap::after {
  bottom: -1px; right: -1px; border-bottom-width: 2px; border-right-width: 2px; }
body[data-iq-tool] .conv__preview,
body[data-iq-tool] .conv__preview--3d { background: transparent; }
/* the dims chip reads like the workspace bar's tag, not a floating orphan */
body[data-iq-tool] .dims3d {
  top: 14px; left: 14px;
  background: rgba(8, 9, 12, .88);
  border: 1px solid rgba(127, 160, 204, .35);
  font-family: var(--mono);
}
/* choice mode: the part is the subject — give the frame air, then a clear
   decision row that matches the band below it */
body[data-iq-tool] .conv--choice .conv__previewwrap {
  border: 1px solid var(--line);
  /* the stage is very wide; an extreme letterbox makes the width-fit camera
     stand far back and the part arrive small. A saner frame = closer camera. */
  max-width: 980px; margin: 0 auto; width: 100%;
}
body[data-iq-tool] .conv__choice { gap: 16px; }
body[data-iq-tool] .conv__choicebtns { display: flex; gap: 14px; flex-wrap: wrap; }
body[data-iq-tool] .conv__choicebtns .btn {
  height: 48px; padding: 0 34px; font-size: 12px; letter-spacing: .12em;
  border-radius: 0;
}
body[data-iq-tool] .conv__restart {
  font: 500 11.5px var(--mono);
  letter-spacing: var(--track-sm);
  text-transform: uppercase;
  color: var(--gray-400);
}
body[data-iq-tool] .conv__restart:hover { color: var(--white); }
/* ---- tool page information view (operator 2026-08-30): model starts as a
   MINI picture on the left, geometry + estimate fill the margins; clicking
   the model collapses the info and expands the viewer full width ---- */
body[data-iq-tool] #conv:not(.iq-expanded) .conv__output {
  grid-template-columns: minmax(280px, 400px) minmax(0, 1fr);
  align-items: start;
}
body[data-iq-tool] #conv:not(.iq-expanded) .conv__preview,
body[data-iq-tool] #conv:not(.iq-expanded) .conv__preview--3d {
  height: 360px; min-height: 0;
}
/* mini = a picture: the canvas is inert, one click means "expand" */
body[data-iq-tool] #conv:not(.iq-expanded) .conv__preview--3d canvas { pointer-events: none; }
body[data-iq-tool] #conv:not(.iq-expanded) .conv__previewwrap { cursor: zoom-in; }
body[data-iq-tool] #conv:not(.iq-expanded) .conv__previewhdr .viewtoggle,
body[data-iq-tool] #conv:not(.iq-expanded) .conv__previewhdr .wallctl,
body[data-iq-tool] #conv:not(.iq-expanded) .conv__previewhdr .spinctl,
body[data-iq-tool] #conv:not(.iq-expanded) .conv__previewfoot { display: none; }
body[data-iq-tool] #conv:not(.iq-expanded) .conv__previewhdr {
  border-bottom: 0; position: absolute; inset: 0 0 auto 0; z-index: 5;
}
/* both affordances wear the HOME ghost-button clothes (operator 2026-08-30:
   "button style needs to be same as home page") */
.iq-modelhint, .iq-collapse {
  font-weight: 700; font-size: 11px; letter-spacing: .1em;
  text-transform: uppercase; font-family: inherit;
  color: var(--white);
  background: rgba(6, 7, 8, .72);
  border: 1px solid rgba(255, 255, 255, .28);
  padding: 10px 18px;
}
.iq-modelhint {
  position: absolute; left: 50%; bottom: 14px; transform: translateX(-50%);
  z-index: 6; pointer-events: none;
}
.iq-collapse { margin-left: auto; cursor: pointer;
  transition: border-color .2s, background .2s; }
.iq-collapse:hover { border-color: var(--white); background: rgba(255,255,255,.06); }
/* expanded: the model owns the page — ANIMATED (operator 2026-08-30): the
   grid tracks tween (track counts match, so grid-template-columns
   interpolates), the viewer height tweens, the info column fades and
   collapses; viewer3d's ResizeObserver refits the canvas every frame */
body[data-iq-tool] #conv .conv__output {
  transition: grid-template-columns .55s var(--ease), gap .55s var(--ease);
}
body[data-iq-tool] .conv__preview,
body[data-iq-tool] .conv__preview--3d {
  transition: height .55s var(--ease);
}
body[data-iq-tool] .conv__meta {
  transition: opacity .3s ease;
  min-width: 0; overflow: hidden;
}
body[data-iq-tool] .iq-expanded .conv__output {
  grid-template-columns: minmax(0, 1fr) 0px; gap: 0;
}
body[data-iq-tool] .iq-expanded .conv__meta { opacity: 0; pointer-events: none; }
body[data-iq-tool] .iq-expanded .conv__preview,
body[data-iq-tool] .iq-expanded .conv__preview--3d { height: min(72vh, 820px); }
/* expanded model = the only thing on screen: stepper and doors yield too */
body.iq-model-expanded .qrail,
body.iq-model-expanded .qpaths { display: none; }
/* fully-expanded model: give the stage the whole viewport width
   (operator 2026-08-31) */
body[data-iq-tool].iq-model-expanded .container {
  max-width: min(1860px, 98vw);
}

/* THE SHEET (operator 2026-08-30 restructure): model card | geometry |
   estimate as three top-aligned columns of one flat spec sheet, the unit
   price as the page's big stat, and a proper action bar under the numbers */
body[data-iq-tool] .conv__meta {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px clamp(36px, 4vw, 72px);
  align-content: start;
}
body[data-iq-tool] .conv__meta .iqspan { grid-column: 1 / -1; }
/* the number the page exists for */
body[data-iq-tool] .iqest-total {
  border-bottom: 0;
  display: block;
  margin-top: 18px;
}
body[data-iq-tool] .iqest-total dt {
  display: block; margin-bottom: 6px;
  color: var(--gray-400);
}
body[data-iq-tool] .iqest-total dd {
  display: block;
  font: 700 clamp(26px, 2.4vw, 36px) var(--mono);
  letter-spacing: -1px;
  color: var(--white);
}
.iqest-note { color: var(--gray-500); font-size: 11.5px; margin-top: 10px; line-height: 1.6; }
/* action bar: quiet utilities left, the commit on the right */
body[data-iq-tool] .iqspan .conv__actions {
  display: flex; flex-direction: row; align-items: center;
  gap: 14px; flex-wrap: wrap;
  border-top: 1px solid var(--line);
  margin-top: 22px; padding-top: 22px;
}
body[data-iq-tool] .iqspan .conv__actions .btn { width: auto; margin: 0; height: 46px; padding: 0 28px; }
body[data-iq-tool] .iqspan .conv__actions #toQuoteBtn { margin-left: auto; min-width: 260px; }
@media (max-width: 1180px) {
  body[data-iq-tool] .conv__meta { grid-template-columns: 1fr; }
  body[data-iq-tool] #conv:not(.iq-expanded) .conv__output { grid-template-columns: 1fr; }
}
body[data-iq-tool] .conv__metatitle {
  text-transform: uppercase; letter-spacing: var(--track);
  font: 600 11px var(--mono); color: var(--accent);
  margin-bottom: 14px;
}
body[data-iq-tool] .specs > div {
  display: flex; justify-content: space-between; align-items: baseline;
  border-bottom: 1px solid var(--line);
  padding: 7px 0; margin: 0;
}
body[data-iq-tool] .specs dt {
  text-transform: uppercase; letter-spacing: var(--track-sm);
  font-size: 10.5px; color: var(--gray-400);
}
body[data-iq-tool] .specs dd { font-family: var(--mono); font-size: 13px; }

/* ---- /instant-quote access swap: html.iq-denied (set by the page's gate)
   hides the console and shows the request-access panel instead ---- */
.iq-deny { display: none; }
html.iq-denied .iq-deny { display: block; }
html.iq-denied .section--quote:not(.iq-deny),
html.iq-denied .section--result { display: none; }
.iq-deny { padding-top: calc(var(--nav-h) + clamp(48px, 10vh, 110px)); }
.iq-deny .eyebrow, .iq-deny .section__title { text-align: left; }
.iq-deny .section__lead { text-align: left; margin-left: 0; }
.iq-deny .hero__actions { margin-top: 32px; }

/* the two doors under the drop card: full-width hairline rows, not tabs */
.qpaths { margin-top: clamp(14px, 2.6vh, 26px); border-top: 1px solid var(--line); }
.qpaths .toggle__btn {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: "name arrow" "sub arrow";
  row-gap: 4px;
  align-items: center;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line);
  padding: clamp(12px, 2vh, 18px) 6px;
  cursor: pointer;
  transition: background .25s ease;
}
.qpaths .toggle__btn:hover { background: rgba(127, 160, 204, .05); }
.qpath__name {
  grid-area: name;
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  color: var(--fg);
}
.qpath__sub {
  grid-area: sub;
  color: var(--gray-400);
  font-size: 12.5px;
  font-weight: 300;
}
.qpath__arrow {
  grid-area: arrow;
  color: var(--gray-400);
  font-size: 18px;
  padding-left: 18px;
  transition: transform .25s var(--ease), color .25s;
}
.qpaths .toggle__btn:hover .qpath__arrow {
  transform: translateX(5px);
  color: var(--accent);
}

/* the requirements band is a slim strip holding just the card — the form
   itself lives in the slide-up DRAWER below (operator 2026-08-30: "not be on
   the page ... something that slides up as a temporary widget"). */
.section--req { background: var(--bg); padding: clamp(48px, 8vh, 88px) 0; }
.section--req .reqcard { margin-top: 0; }

/* ---- requirements DRAWER: a bottom sheet, SpaceX-clean ----
   Fixed overlay: dark scrim + a square hairline panel that slides up from
   the bottom edge. openReqForm()/closeReqForm() (script.js) toggle
   `.is-open`; scrim click, the x, and Esc all close. The panel scrolls
   internally past 86vh, the page behind is scroll-locked. */
.req-drawer { position: fixed; inset: 0; z-index: 300;
  display: flex; align-items: flex-end; justify-content: center; }
.req-drawer[hidden] { display: none; }
.req-drawer__scrim { position: absolute; inset: 0;
  background: rgba(3, 4, 5, .68);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  opacity: 0; transition: opacity .35s ease; }
.req-drawer__panel { position: relative;
  width: min(1180px, 100vw); max-height: 86vh; overflow-y: auto;
  background: #0b0c0e; border: 1px solid var(--line); border-bottom: 0;
  padding: 30px clamp(20px, 4vw, 48px) 40px;
  transform: translateY(103%); transition: transform .5s var(--ease); }
.req-drawer.is-open .req-drawer__scrim { opacity: 1; }
.req-drawer.is-open .req-drawer__panel { transform: none; }
.req-drawer__head { display: flex; justify-content: space-between;
  align-items: flex-start; margin-bottom: clamp(12px, 2vh, 20px);
  padding-bottom: 14px; border-bottom: 1px solid var(--line); }
.req-drawer__head .eyebrow { margin-bottom: 8px; }
.req-drawer__title { text-transform: uppercase; font-weight: 700;
  letter-spacing: -0.5px; font-size: 22px; line-height: 1.1; }
.req-drawer__close { background: none; border: none; color: var(--gray-400);
  font-size: 30px; line-height: 1; cursor: pointer; padding: 0 4px; }
.req-drawer__close:hover { color: var(--white); }
body.req-drawer-open { overflow: hidden; }
@media (prefers-reduced-motion: reduce) {
  .req-drawer__scrim, .req-drawer__panel { transition: none; }
}

/* form sizing inside the drawer (was the in-band `.section--req .form`
   block; rescoped when the form moved into the drawer, 2026-08-30) */
.req-drawer .form__intro { margin-bottom: clamp(10px, 2vh, 26px); font-size: 15px; }
.req-drawer .form__group--disc .form__grouphead { padding: clamp(9px, 1.5vh, 14px) 16px; }
.req-drawer .form__group--disc .field { padding-left: 16px; padding-right: 16px; }
.req-drawer .field input,
.req-drawer .field select,
.req-drawer .field textarea { font-size: 14.5px; }
.req-drawer .field__label { font-size: 12.5px; }
.req-drawer .field { margin-top: clamp(7px, 1.4vh, 16px); }
/* the contact grid's gap owns its spacing — stray .field margins (6px on
   the first-of-type, 10px on the rest) tipped Name and Work email out of
   line with each other (operator 2026-09-03) */
.req-drawer .form__grid--contact .field { margin-top: 0; }
.req-drawer .field__label { margin-bottom: clamp(4px, 0.8vh, 7px); }
.req-drawer .field input,
.req-drawer .field select,
.req-drawer .field textarea { padding: clamp(5px, 1vh, 11px) 13px; }
.req-drawer .field textarea { min-height: 0; }
.req-drawer .checks { gap: clamp(4px, 0.8vh, 10px); }
.req-drawer .form .quote-cta { margin: clamp(14px, 2.4vh, 30px) auto 0;
  max-width: var(--req-w); }
.req-drawer .form .quote-cta .btn { width: 100%; justify-content: center; }
.req-drawer .form { --req-w: 760px; }
.req-drawer .form__grid { display: block; max-width: var(--req-w); margin: 0 auto;
  border: 1px solid var(--line); background: rgba(8, 10, 12, .78); }
/* the bordered-box treatment is for the spec ACCORDION only — the contact
   fields stand on their own (operator 2026-09-03: "get rid of the box
   surrounding all of them") */
.req-drawer .form__grid--contact { border: 0; background: none; }
@media (max-height: 820px) {
  /* short screens: the intro repeats the reqcard's message — drop it, and
     tighten the checkbox lists so the drawer needs less scroll */
  .req-drawer .form__intro { display: none; }
  .req-drawer .check { font-size: 12.5px; }
  .req-drawer .field__hint { display: none; }
}

/* WIDE drawer = two panes (operator 2026-09-03: "styled more neatly and use
   up more space"). The required path — notes, contact, send — reads down the
   LEFT; the optional spec accordion fills the RIGHT, stretching to match so
   the sheet reads as one composed surface instead of a strip down the
   middle. Pure grid re-placement of the same six form children — the markup
   (and the generated instant-quote page, which shares it) is untouched;
   under 1020px the base single-column flow above still applies. */
@media (min-width: 1020px) {
  .req-drawer .form--req {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto auto auto;
    grid-template-areas:
      "notes   opthead"
      "notes   opt"
      "chead   opt"
      "contact opt"
      "cta     opt";
    column-gap: clamp(32px, 4vw, 52px);
  }
  .req-drawer .form--req > .field--notes { grid-area: notes;
    display: flex; flex-direction: column;
    max-width: none; margin: 0; }
  .req-drawer .form--req > .field--notes textarea { flex: 1;
    /* the one element that gives on short windows, so the sheet itself
       never has to scroll — the spec box has its own scroll, everything
       else is fixed-height */
    min-height: clamp(120px, 26vh, 220px); }
  .req-drawer .form--req > p.form__more:nth-of-type(1) { grid-area: opthead;
    margin-top: 0; }
  .req-drawer .form--req > .form__grid:not(.form__grid--contact) {
    grid-area: opt; max-width: none; margin: 0; align-self: stretch; }
  .req-drawer .form--req > p.form__more:nth-of-type(2) { grid-area: chead; }
  .req-drawer .form--req > .form__grid--contact { grid-area: contact;
    max-width: none; margin: 0; }
  .req-drawer .form--req > .quote-cta { grid-area: cta;
    max-width: none; margin-left: 0; margin-right: 0; }
  /* the two column headers sit on the same optical line */
  .req-drawer .form--req > .field--notes .field__label,
  .req-drawer .form--req > p.form__more { margin-left: 0; margin-right: 0; }
  /* ONLY the spec accordion scrolls (operator 2026-09-03: "the only part of
     the form that should be scrollable is the expandable sections"): the box
     caps at what fits the sheet (86vh minus the head + paddings) and scrolls
     internally when opened groups outgrow it, so notes / contact / Send
     never move. The panel's own overflow-y:auto stays purely as a
     short-window safety net — with the box capped it does not engage at
     normal desktop heights. */
  .req-drawer .form--req > .form__grid:not(.form__grid--contact) {
    overflow-y: auto; max-height: calc(86vh - 220px);
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: #3a4048 transparent;
  }
}
/* one shared canvas below the hero — the background renders separate the
   sections, not colour bands (operator 2026-08-30) */
.section--process {
  background: var(--bg);
  /* operator 2026-08-31: no viewport-height stretching - the icon rows
     carry the section's presence and the padding stays tight, otherwise
     the leftover space pools as black above and below the content */
  /* Asymmetric ON PURPOSE, and it is what makes the section look symmetric.
     The accordion reserves room under its last row for the tallest hover
     reveal, so the space below the content is that reservation PLUS this
     padding, while the space above is this padding alone. script.js sizes the
     reservation to whatever makes the two equal (operator 2026-09-01: "the
     same top margin as bottom margin"), so this pair stays deliberately
     lopsided — change the top value and the bottom follows automatically. */
  padding: clamp(40px, 6vh, 64px) 0 clamp(6px, 1vh, 12px);
}
.section--cap { background: var(--bg); }
.section--result { background: var(--bg); }

/* ---------------------------- BUTTONS ---------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  padding: 13px 30px;
  border: 1px solid var(--white);
  background: transparent;
  color: var(--white);
  cursor: pointer;
  transition: background .22s ease, color .22s ease, border-color .22s ease, opacity .22s ease;
  white-space: nowrap;
}
.btn--solid { background: var(--white); color: var(--black); }
.btn--solid:hover { background: transparent; color: var(--white); }
.btn--ghost:hover { background: var(--white); color: var(--black); }
.btn--lg { padding: 16px 40px; font-size: 14px; }
.btn:disabled { opacity: .35; cursor: not-allowed; }
.btn:disabled:hover { background: var(--white); color: var(--black); }

/* ---------------------------- NAV ----------------------------
   The nav is the SHARED site shell now — one markup, one stylesheet
   (/chrome.css) across store, instant quote and part builder. */

/* ---------------------------- HERO ---------------------------- */
/* ---- pinned scroll-bend hero -------------------------------------------
   Track length is ABSOLUTE px, not vh: the feel the operator specified is
   degrees-of-bend per wheel notch, which is a pixel quantity. 4500px of
   scroll carries the FULL 180 deg left bend, i.e. 4 deg per 100px notch -
   the coarse end of the operator's "2-4 degree ... for every one scroll",
   chosen because 3 deg/notch would need 6000px of pinned scroll for the
   full range. --hero-span must match HERO_SPAN in script.js. */
/* the pin-track is gone (operator 2026-08-29): the hero is one plain
   viewport-tall section and the SLIDER owns the bend */
/* HOME renders at 110% by default (operator 2026-08-31: "125% ... i love
   how it looks but its just a tad too big"). CSS zoom scales the page the
   way browser zoom does; viewport-height elements are compensated below so
   the hero still fills exactly one screen. */
body[data-iq-handoff] { zoom: 1.1; }
body[data-iq-handoff] .hero {
  height: calc(100vh / 1.1); height: calc(100svh / 1.1);
  min-height: calc(100vh / 1.1); min-height: calc(100svh / 1.1);
}

.hero {
  height: 100vh; height: 100svh;
  margin-top: calc(-1 * var(--nav-h));
  /* the whole hero is a bend handle (operator 2026-09-01), so it says so:
     grab anywhere and drag sideways. touch-action keeps a horizontal drag from
     being stolen by the browser's scroll gesture while leaving vertical
     scrolling alone. */
  cursor: grab;
  touch-action: pan-y;
}
.hero.is-bending { cursor: grabbing; }
/* the copy and the CTAs keep their own pointers — they are still clickable */
.hero__content, .hero__actions a, .hero__bend { cursor: auto; }
.hero__actions a { cursor: pointer; }
.hero {
  position: relative;
  overflow: hidden;
  /* full viewport, pulled up under the translucent sticky nav so the video
     runs behind it (the nav goes clear at the top of the page — script.js) */
  margin-top: calc(-1 * var(--nav-h));
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: calc(var(--nav-h) + 28px) 28px 0;
  /* dark fallback canvas behind the video while it loads */
  background:
    radial-gradient(ellipse at 50% 30%, rgba(40,44,50,.5) 0%, rgba(6,7,8,0) 60%),
    linear-gradient(180deg, var(--bg) 0%, #08090b 50%, var(--bg) 100%);
}
.hero__vid {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  /* Centred and at native scale. `cover` crops to the viewport rather than
     distorting, so the part never stretches; no transform, because magnifying
     the clip is exactly what throws away the resolution it was rendered at. */
  object-fit: cover;
  object-position: 50% 50%;
}
.hero__overlay {
  position: absolute; inset: 0;
  /* legibility vignette behind the centred display type, plus a fade to the
     page background at the foot so the quote section blends in seamlessly */
  background:
    radial-gradient(ellipse at 50% 44%, rgba(0,0,0,.38) 0%, rgba(0,0,0,0) 68%),
    linear-gradient(180deg, rgba(6,7,8,.35) 0%, rgba(6,7,8,.12) 45%, rgba(6,7,8,.7) 82%, var(--bg) 100%);
  pointer-events: none;
}
/* nav floats clear over the video until the page scrolls (script.js) */
.nav { transition: background .35s var(--ease), border-color .35s var(--ease); }
.nav.nav--clear { background: transparent; backdrop-filter: none; border-bottom-color: transparent; }
.hero__content { position: relative; z-index: 2; max-width: 820px; }
.hero__title {
  text-transform: uppercase;
  font-weight: 700;
  letter-spacing: -1px;   /* negative tracking on display type */
  font-size: clamp(40px, 7.2vw, 78px);
  line-height: 0.98;
  margin-bottom: 26px;
}
.hero__sub {
  color: var(--gray-400);
  font-size: clamp(16px, 2vw, 19px);
  font-weight: 300;
  max-width: 600px;
  margin: 0 auto 38px;
}

/* traced laser kerf under the hero title — the store hero's signature detail,
   as a self-contained draw-in (no JS): gradient stroke wipes in left-to-right
   with a soft glow, then holds */
.hero__kerf { width: min(420px, 70vw); height: 22px; margin: -6px auto 24px; overflow: visible; }
.hero__kerf .k-glow { stroke: var(--accent); stroke-width: 4.5; opacity: .22;
  filter: blur(3px); fill: none; stroke-linecap: round; }
.hero__kerf .k-line { stroke: url(#heroKerfGrad); stroke-width: 1.8; fill: none; stroke-linecap: round; }
.hero__kerf .k-glow, .hero__kerf .k-line {
  stroke-dasharray: 1; stroke-dashoffset: 1;
  animation: heroKerf 1s var(--ease) .35s forwards;
}
.hero__kerf .k-tip { fill: #eaf3ff; opacity: 0; animation: heroKerfTip 1s var(--ease) .35s forwards; }
@keyframes heroKerf { to { stroke-dashoffset: 0; } }
@keyframes heroKerfTip {
  0% { opacity: 0; transform: translateX(0); }
  12% { opacity: .9; }
  88% { opacity: .9; }
  100% { opacity: 0; transform: translateX(404px); }
}
@media (prefers-reduced-motion: reduce) {
  .hero__kerf .k-glow, .hero__kerf .k-line { animation: none; stroke-dashoffset: 0; }
  .hero__kerf .k-tip { animation: none; opacity: 0; }
}
.hero__actions {
  display: flex;
  gap: 16px;
  justify-content: center;
  flex-wrap: wrap;
}
.hero__actions.center { justify-content: center; }

.hero__bend {
  position: absolute;
  bottom: 26px; left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  width: min(560px, 72vw);
}
/* SHORT viewports (incl. ctrl+ browser zoom, which shrinks the CSS
   viewport): a fixed 100svh hero runs out of room and the centered CTA
   block collided with the bend slider (operator 2026-08-31). Let the hero
   grow past the viewport, reserve the slider's band, and step the display
   type down. */
@media (max-height: 640px) {
  .hero { height: auto; }
  body[data-iq-handoff] .hero { height: auto; }  /* beats the /1.1 zoom calc */
  .hero__content { padding-bottom: 110px; }
  .hero__title { font-size: clamp(34px, 6vw, 60px); }
}
.hero__bend-label {
  font: 600 10.5px var(--mono);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--white);
  text-shadow: 0 1px 4px rgba(0, 0, 0, .9);
}
#bendSlider {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 26px;               /* fat hit area, thin visual */
  background: transparent; cursor: ew-resize;
}
#bendSlider::-webkit-slider-runnable-track {
  height: 2px; border-radius: 1px;
  background: linear-gradient(90deg, rgba(127,160,204,.25),
              rgba(234,243,255,.75) 50%, rgba(127,160,204,.25));
}
#bendSlider::-moz-range-track {
  height: 2px; border-radius: 1px;
  background: linear-gradient(90deg, rgba(127,160,204,.25),
              rgba(234,243,255,.75) 50%, rgba(127,160,204,.25));
}
#bendSlider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 16px; height: 16px; margin-top: -7px;
  border-radius: 50%;
  background: var(--white);
  border: 1px solid rgba(127,160,204,.8);
  box-shadow: 0 0 14px var(--accent-glow), 0 1px 5px rgba(0,0,0,.7);
  transition: box-shadow .18s;
}
#bendSlider::-moz-range-thumb {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--white);
  border: 1px solid rgba(127,160,204,.8);
  box-shadow: 0 0 14px var(--accent-glow), 0 1px 5px rgba(0,0,0,.7);
}
#bendSlider:hover::-webkit-slider-thumb,
#bendSlider:active::-webkit-slider-thumb {
  box-shadow: 0 0 22px var(--accent-glow), 0 1px 5px rgba(0,0,0,.7);
}
/* the copy vanishes the moment the slider is engaged (binary, smooth) and
   returns when it is released near straight */
.hero__content { will-change: opacity; transition: opacity .45s var(--ease, ease); }


/* ---------------------------- TABS (vestigial) ----------------------------
   The visible toggle row died in the 2026-08-30 console redo — the dropzone
   IS the CAD path and the other two doors are .qpaths rows (still
   .toggle__btn/data-tab, so script.js's handler is unchanged). Only the
   panel show/hide contract remains. */
.tabpanel { display: none; }
.tabpanel.is-active { display: block; }

/* ---------------------------- DROPZONE ----------------------------
   2026-08-30 console redo: a solid hairline card in the left column (the
   old full-width dashed void read as generic SaaS), left-aligned, with
   laser-tick corners that light on dragover. */
.dropzone {
  position: relative;
  border: 1px solid var(--line-strong);
  background: rgba(8, 10, 12, .72);
  padding: clamp(22px, 3.6vh, 38px) clamp(20px, 2.5vw, 34px);
  text-align: left;
  transition: border-color .2s ease, background .2s ease;
  cursor: pointer;
  margin-top: clamp(14px, 2.6vh, 28px);
}
/* corner ticks: top-left + bottom-right, quiet accent that answers a drag */
.dropzone::before, .dropzone::after {
  content: ""; position: absolute; width: 16px; height: 16px;
  border: 0 solid rgba(127, 160, 204, .55);
  transition: border-color .2s ease;
  pointer-events: none;
}
.dropzone::before { top: -1px; left: -1px; border-top-width: 2px; border-left-width: 2px; }
.dropzone::after { bottom: -1px; right: -1px; border-bottom-width: 2px; border-right-width: 2px; }
.dropzone.is-dragover {
  border-color: var(--accent);
  background: rgba(127, 160, 204, .08);
}
.dropzone.is-dragover::before, .dropzone.is-dragover::after {
  border-color: var(--accent);
}
.dropzone__input {
  position: absolute; inset: 0;
  opacity: 0; cursor: pointer;
}
.dropzone__icon {
  float: right;
  font-size: 20px;
  color: var(--accent);
  border: 1px solid var(--line-strong);
  width: 40px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  margin-left: 18px;
}
.dropzone__title {
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  font-weight: 600;
  font-size: 16px;
  margin-bottom: clamp(6px, 1.2vh, 10px);
}
.dropzone__hint { color: var(--gray-400); font-size: 14px; margin-bottom: clamp(8px, 1.4vh, 14px); }
.dropzone__formats {
  color: var(--gray-500);
  font-size: 11.5px;
  letter-spacing: var(--track-sm);
  text-transform: uppercase;
}
.link { color: var(--white); text-decoration: underline; }

.dropzone__note {
  margin-top: clamp(8px, 1.4vh, 14px);
  text-align: left;
  color: var(--gray-500);
  font-size: 12px;
  line-height: 1.6;
  max-width: 560px;
}

.filelist { list-style: none; margin: 22px 0 0; }
.filelist li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border: 1px solid var(--line);
  padding: 12px 16px;
  margin-bottom: 8px;
  font-size: 14px;
}
.filelist .file__remove {
  background: none; border: none; color: var(--gray-400);
  cursor: pointer; font-size: 18px; line-height: 1;
}
.filelist .file__remove:hover { color: var(--white); }

.quote-cta { text-align: center; margin-top: 36px; }
.quote-cta__hint { color: var(--gray-400); font-size: 13.5px; margin: 28px 0 13px; }
.quote-cta__alt { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.builder-hint { color: var(--gray-400); font-size: 14px; line-height: 1.6; max-width: 620px; margin: 0 auto 6px; text-align: center; }
/* third option: "tell us your requirements" card, sits below the two methods */
/* The requirements pitch reads as a SECTION, not a boxed card (operator
   2026-08-26: "re style ... to fit more with the images and styling of the
   website"). Same eyebrow / title / lead rhythm as #quote and #process, and
   no border, so the j-tip backdrop carries the block instead of being
   fenced off behind a rectangle. */
/* the card rides RIGHT so the J-tip render owns the left half of the band
   (operator 2026-08-30 de-centering pass). object-position cannot move a
   cover-fit image horizontally when it already spans the full width, so the
   shift is a translate; the scrim's right-side gradient hides the vacated
   edge AND seats the card on dark ground — the left half carries the part,
   the right half carries the words, nothing reads as empty black. */
.reqcard { max-width: 640px; margin: 0 0 0 auto; padding: 0; border: 0; text-align: left; }
.section--req .sec-bg--strong img {
  opacity: .72; filter: saturate(.85) contrast(1.05);
  transform: translateX(-14%);
}
.section--req .sec-bg--strong::after {
  background:
    linear-gradient(90deg, rgba(6,7,8,0) 42%, rgba(6,7,8,.5) 72%, rgba(6,7,8,.72) 100%),
    radial-gradient(ellipse at 30% 50%, rgba(6,7,8,.22) 0%, rgba(6,7,8,.10) 60%, rgba(6,7,8,0) 100%),
    linear-gradient(180deg, var(--bg) 0%, rgba(6,7,8,0) 13%,
                    rgba(6,7,8,0) 87%, var(--bg) 100%);
}
.reqcard .section__lead { text-align: left; margin-left: 0; margin-right: 0;
                          margin-bottom: clamp(20px, 3.4vh, 34px); }
.reqcard .section__title { text-align: left; }
.reqcard__lead { font-size: 19px; font-weight: 600; color: var(--white); margin: 0 0 9px; }
.reqcard__sub { color: var(--gray-400); font-size: 14px; line-height: 1.6; max-width: 500px; margin: 0 auto 22px; }
/* requirements inquiry / RFQ modal */
.rfq-modal { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,.74); padding: 22px; }
.rfq-modal[hidden] { display: none; }
.rfq-modal__box { position: relative; width: 100%; max-width: 540px; max-height: 86vh; overflow-y: auto; background: #0b0c0e; border: 1px solid var(--line); padding: 36px 34px; }
.rfq-modal__close { position: absolute; top: 12px; right: 16px; background: none; border: none; color: var(--gray-400); font-size: 26px; line-height: 1; cursor: pointer; }
.rfq-modal__close:hover { color: var(--white); }
.rfq-modal__title { font-size: 21px; font-weight: 700; letter-spacing: .01em; color: var(--white); margin: 0 0 10px; }
.rfq-modal__text { color: var(--gray-400); font-size: 14px; line-height: 1.6; margin: 0 0 22px; }
.rfq-list { border: 1px solid var(--line); margin: 0 0 24px; }
.rfq-row { display: flex; justify-content: space-between; gap: 16px; padding: 11px 15px; font-size: 13.5px; }
.rfq-row + .rfq-row { border-top: 1px solid var(--line); }
.rfq-row__k { color: var(--gray-400); white-space: nowrap; }
.rfq-row__v { color: var(--white); text-align: right; }
.rfq-modal__actions { display: flex; gap: 12px; flex-wrap: wrap; }
.rfq-modal__actions .btn { flex: 1; justify-content: center; min-width: 140px; text-align: center; }
.rfq-done { text-align: center; }
.rfq-done__badge { width: 52px; height: 52px; margin: 0 auto 16px; border: 1px solid var(--line); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 22px; color: #3fbf6a; }

/* ---------------------------- CONVERSION PANEL ---------------------------- */
/* The conversion panel breaks out of the 880px tab column so the model view
   gets real width; it stays centered on the page. */
.conv {
  margin-top: 40px;
  border-top: 1px solid var(--line);
  padding-top: 36px;
  /* breakout-centering WITHOUT left/transform: symmetric negative margins
     off the (already centered) parent — nothing can override it, and no
     transform means no containing-block surprises (the old translateX
     version rendered the drop viewer hard-right, operator 2026-07-30) */
  width: min(1440px, calc(100vw - 64px));
  position: relative;
  margin-left: calc((100% - min(1440px, 100vw - 64px)) / 2);
  margin-right: calc((100% - min(1440px, 100vw - 64px)) / 2);
}
.spinner {
  width: 26px; height: 26px;
  border: 2px solid var(--line);
  border-top-color: var(--white);
  border-radius: 50%;
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.conv__output {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 28px;
  align-items: stretch;   /* preview and sidebar always share one height */
}
.conv__previewwrap {
  border: 1px solid var(--line);
  background: var(--black);
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.conv__previewhdr {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 26px;                /* operator 2026-08-31: controls need room */
  padding: 14px 20px;
  border-bottom: 1px solid var(--line);
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  font-size: 11px;
  color: var(--gray-400);
}
.conv__legend { display: flex; align-items: center; gap: 14px; }
.dot { display: inline-block; width: 9px; height: 9px; margin-right: 5px; vertical-align: middle; }
.dot--cut { background: #3fbf6a; }
.dot--open { background: #d8b06a; }
.dot--bound { background: var(--offwhite); opacity: .6; }

/* Zoomable preview viewport */
.conv__preview {
  position: relative;
  flex: 1 1 auto;              /* fills the wrap; grows if the sidebar is taller */
  min-height: clamp(420px, 58vh, 720px);
  overflow: hidden;
  background: var(--black);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.conv__preview.is-grabbing { cursor: grabbing; }
.conv__preview[hidden] { display: none; }        /* [hidden] must beat display:flex */
.conv__preview--3d { cursor: default; }
.conv__preview--3d canvas { position: absolute; inset: 0; }

/* 2D flat / 3D model switch in the preview header */
.viewtoggle { display: inline-flex; gap: 0; }
.viewtoggle__btn {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--gray-400);
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  font-size: 11px;
  font-weight: 600;
  padding: 5px 14px;
  cursor: pointer;
  transition: all .2s ease;
}
.viewtoggle__btn + .viewtoggle__btn { border-left: none; }
.viewtoggle__btn.is-active {
  border-color: var(--white);
  color: var(--black);
  background: var(--white);
}
.viewtoggle__btn:disabled { opacity: .4; cursor: not-allowed; }

/* Wall-thickness control (3D bore display) in the preview header */
.wallctl {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--gray-400);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
}
.wallctl input {
  width: 74px;
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--line);
  color: var(--white);
  font-family: var(--mono);
  font-size: 12px;
  padding: 4px 6px;
  text-align: right;
}
.wallctl input:focus { outline: none; border-color: var(--accent-line); }
/* auto-rotate toggle in the CAD preview header (mirrors .wallctl / .spec__prevopt) */
.spinctl {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--gray-400);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  cursor: pointer;
  user-select: none;
}
.spinctl input { accent-color: #3fbf6a; cursor: pointer; }

/* ---------------------------- DRAWING SPEC (PDF) ----------------------------
   Customer-facing: a clean engineering card — quiet labels, mono values,
   underline inputs that only reveal themselves on hover/focus. */
#specPanel {
  border: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(255,255,255,0.025), rgba(255,255,255,0) 140px);
  padding: 22px 30px 22px;
}
.spec__hdr {
  display: flex;
  align-items: baseline;
  gap: 18px;
  flex-wrap: wrap;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
}
.spec__src { color: var(--gray-500); font-size: 11px; font-family: var(--mono); }
.spec__block { margin-bottom: 15px; }
.spec__block h4 {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 11px;
  font-weight: 600;
  color: var(--gray-400);
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  gap: 4px;
}
.spec__idrow { display: flex; flex-wrap: wrap; gap: 18px 36px; }
.spec__idrow label {
  display: flex;
  flex-direction: column;
  gap: 5px;
  color: var(--gray-500);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 600;
}
.spec__idrow input, .spec__table input {
  background: transparent;
  border: none;
  border-bottom: 1px solid transparent;
  color: var(--offwhite);
  font-family: var(--mono);
  font-size: 14px;
  padding: 3px 2px;
  width: 96px;
  transition: border-color .18s ease, background .18s ease;
}
.spec__idrow input:hover, .spec__table input:hover {
  border-bottom-color: var(--line);
}
.spec__idrow input:focus, .spec__table input:focus {
  outline: none;
  border-bottom-color: var(--accent-line);
  background: rgba(255,255,255,0.03);
}
.spec__table {
  border-collapse: collapse;
  min-width: 520px;
}
.spec__table th {
  color: var(--gray-500);
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 600;
  padding: 6px 14px 6px 2px;
  text-align: left;
  border-bottom: 1px solid var(--line);
}
.spec__table td {
  padding: 3px 14px 3px 2px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.spec__table tbody tr { transition: background .15s ease; }
.spec__table tbody tr:hover { background: rgba(255,255,255,0.025); }
.spec__table td:first-child input {
  width: 42px;
  color: var(--gray-400);
  font-weight: 700;
}
.spec__table td:last-child { border-bottom: none; }
.spec__findings { margin: 4px 0 22px; }
.spec__finding {
  font-family: var(--mono);
  font-size: 12px;
  padding: 4px 0;
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.spec__finding--error { color: #cf7f7f; }
.spec__finding--warning { color: #d8b06a; }
.spec__finding--ok { color: #3fbf6a; }
/* one-click fix offered inside a finding line */
.spec__fix {
  background: transparent;
  border: 1px solid currentColor;
  border-radius: 3px;
  color: inherit;
  font-family: var(--mono);
  font-size: 10.5px;
  padding: 2px 9px;
  cursor: pointer;
  white-space: nowrap;
}
.spec__fix:hover { background: rgba(255, 255, 255, 0.08); }
/* section-type + placement pickers, pinned (derived) start cells,
   inline parameter groups on feature rows */
.spec__table select {
  background: transparent;
  border: none;
  border-bottom: 1px solid transparent;
  color: var(--offwhite);
  font-family: var(--mono);
  font-size: 12.5px;
  padding: 3px 2px;
  cursor: pointer;
}
.spec__table select:hover { border-bottom-color: var(--line); }
.spec__table select option {
  background: #121316;
  color: var(--offwhite);
}
.spec__table input:disabled { color: var(--gray-500); }
/* feature tables (below Sections): kind title + compact numeric columns */
.spec__feattitle {
  color: var(--gray-500);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 600;
  margin: 12px 0 2px;
}
.spec__table--feat { min-width: 0; }
.spec__table--feat input { width: 72px; }
.spec__table--feat td:first-child input { width: 42px; }
.spec__actions { flex-direction: row !important; gap: 12px; flex-wrap: wrap; }
.spec__actions .btn { width: auto; }
.spec__rowbtn {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--gray-500);
  font-size: 10px;
  font-family: var(--mono);
  padding: 2px 9px;
  margin-left: 10px;
  cursor: pointer;
  letter-spacing: 0.04em;
  transition: all .18s ease;
}
.spec__rowbtn:hover { color: var(--black); background: var(--white); border-color: var(--white); }
.spec__table .spec__rowbtn { margin-left: 4px; opacity: 0; }
.spec__table tr:hover .spec__rowbtn { opacity: 1; }
/* the file-section upload chip is a primary affordance — always visible */
.spec__table .spec__filepick {
  opacity: 1;
  margin-left: 0;
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ================= spec editor — refined dark data UI =================
   An elevated charcoal panel on the black page (depth), clean borderless data
   rows, tracked micro-labels, a quiet mono index column, and precise cut-green
   accents. Generous spacing so it reads as a professional spec sheet, not a raw
   HTML table. Scoped to #specBody. */
#specBody {
  --wk-text: #f3f4f5;
  --wk-muted: #969aa2;
  --wk-faint: #565b63;
  --wk-line: rgba(255, 255, 255, 0.12);
  --wk-line-soft: rgba(255, 255, 255, 0.055);
  --wk-line-strong: rgba(255, 255, 255, 0.22);
  --wk-green: #3fbf6a;       /* the section's cut green — matches the guide */
  --wk-green-soft: rgba(40, 220, 90, 0.13);
  --wk-danger: #cf7f7f;
  --wk-sans: -apple-system, "Segoe UI", Arial, Helvetica, sans-serif;
  --wk-mono: var(--mono);
  --wk-chev: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%239a9a9a' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  color: var(--wk-text);
  font-family: var(--wk-sans);
  overflow-x: auto;
}

/* --- each part-section divided by a hairline so the composition of the part
   reads at a glance — the same flat, divided language as the "measured" guide
   panel beside it (no boxed card, sits directly on #specPanel) --- */
#specBody .spec__block { margin: 0 0 26px; padding: 0; }
#specBody .spec__idrow { margin-bottom: 20px; }
#specBody .spec__block:not(.spec__idrow) {
  border-top: 1px solid var(--wk-line);
  padding-top: 24px;
  margin-top: 8px;
}
#specBody .spec__block:last-child { margin-bottom: 2px; }
#specBody .spec__block h4 {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--wk-muted);
  font-family: var(--wk-sans);
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  margin: 0 0 14px;
}
#specBody .spec__feattitle {
  color: var(--wk-muted);
  font-family: var(--wk-sans);
  font-weight: 600;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  margin: 20px 0 7px;
}

/* --- Part # / tube stock: labels above inputs, uniform grid --- */
#specBody .spec__idrow {
  display: flex;
  flex-wrap: wrap;
  gap: 18px 20px;
}
#specBody .spec__idrow label {
  display: flex;
  flex-direction: column;
  gap: 7px;
  flex: 0 0 auto;
  width: 128px;
  color: var(--wk-muted);
  font-family: var(--wk-sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: none;
}
#specBody .spec__idrow input { width: 100%; }

/* --- inputs: quiet mono wells (matches the guide's mono type), green focus --- */
#specBody input,
#specBody select {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid transparent;
  border-radius: 5px;
  color: var(--wk-text);
  font-family: var(--wk-mono);
  font-variant-numeric: tabular-nums;
  font-size: 12.5px;
  padding: 7px 8px;
  transition: background .14s ease, border-color .14s ease, box-shadow .14s ease;
}
#specBody input:hover, #specBody select:hover { background: rgba(255, 255, 255, 0.06); }
#specBody input:focus, #specBody select:focus {
  outline: none;
  background: rgba(0, 0, 0, 0.35);
  border-color: var(--wk-green);
  box-shadow: 0 0 0 3px var(--wk-green-soft);
}
#specBody input:disabled {
  background: transparent;
  color: var(--wk-faint);
  border-color: transparent;
  box-shadow: none;
  cursor: default;
}
#specBody select {
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  font-family: var(--wk-sans);
  font-size: 12px;
  background-image: var(--wk-chev);
  background-repeat: no-repeat;
  background-position: right 8px center;
  padding-right: 22px;
}
#specBody select option { background: #121316; color: var(--wk-text); }
#specBody input[type="checkbox"] {
  width: 15px; height: 15px; padding: 0;
  accent-color: var(--wk-green);
  background: none; border: none; box-shadow: none;
  vertical-align: middle; cursor: pointer;
}

/* --- tables: a clean, flat data list with hairline dividers (matches the
   guide's divided rows — no boxed container) --- */
#specBody .spec__table {
  border-collapse: collapse;
  width: 100%;
  min-width: 0;
  margin-top: 2px;
}
#specBody .spec__table thead th {
  color: var(--wk-faint);
  font-family: var(--wk-sans);
  font-weight: 600;
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 7px 9px 9px;
  text-align: left;
  white-space: nowrap;
  border-bottom: 1px solid var(--wk-line);
}
#specBody .spec__table tbody td {
  padding: 4px 7px;
  border-bottom: 1px solid var(--wk-line-soft);
  vertical-align: middle;
}
#specBody .spec__table tbody tr:last-child td { border-bottom: none; }
#specBody .spec__table tbody tr { transition: background .12s ease; }
#specBody .spec__table tbody tr:hover { background: rgba(255, 255, 255, 0.022); }
#specBody .spec__table input { width: 74px; }
#specBody .spec__table select.spec__place { width: 116px; }
/* the Sec/label column reads as a quiet mono index */
#specBody .spec__table td:first-child input {
  width: 42px;
  color: var(--wk-muted);
  font-weight: 600;
  font-family: var(--wk-mono);
  font-size: 12px;
  text-align: center;
  background: transparent;
}
/* the multi-column feature tables run compact; a genuinely wide one scrolls
   inside the worksheet instead of clipping */
#specBody .spec__table--feat { width: auto; min-width: 0; }
#specBody .spec__table--feat input { width: 52px; }
#specBody .spec__table--feat td:first-child input { width: 34px; }
#specBody .spec__table--feat select.spec__place { width: 88px; font-size: 12px; }
#specBody .spec__table--feat thead th,
#specBody .spec__table--feat tbody td { padding: 4px 7px; }
#specBody .spec__td-open select.spec__openend { width: 100px; }
#specBody .spec__td-derived {
  color: var(--wk-muted);
  font-variant-numeric: tabular-nums;
  font-size: 12.5px;
  white-space: nowrap;
  padding-left: 3px;
}
#specBody .spec__td-match { text-align: center; }
#specBody .spec__td-open { white-space: nowrap; }

/* --- buttons: ghost mono chips with a green hover (matches the guide) --- */
#specBody .spec__rowbtn {
  background: transparent;
  border: 1px solid var(--wk-line-strong);
  color: var(--wk-muted);
  border-radius: 4px;
  font-family: var(--wk-mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 4px 10px;
  margin-left: 10px;
  cursor: pointer;
  transition: all .14s ease;
}
#specBody .spec__rowbtn:hover {
  background: var(--wk-green-soft);
  border-color: var(--wk-green);
  color: var(--wk-green);
}
/* the delete ✕ stays quiet until row hover, then reads danger */
#specBody .spec__table .spec__rowbtn {
  opacity: 0; margin-left: 0; padding: 3px 8px; border-color: transparent;
}
#specBody .spec__table tr:hover .spec__rowbtn { opacity: .55; }
#specBody .spec__table .spec__rowbtn:hover {
  opacity: 1;
  background: rgba(255, 107, 107, 0.12);
  border-color: var(--wk-danger);
  color: var(--wk-danger);
}
#specBody .spec__filepick {
  opacity: 1 !important;
  max-width: 230px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- the "add … at … in +" bar in the Features heading --- */
#specBody .spec__atbar {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: 14px;
  font-family: var(--wk-sans);
  font-size: 12px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--wk-muted);
}
#specBody .spec__atbar input, #specBody .spec__atbar select { padding: 6px 8px; }
#specBody .spec__atkind { width: 130px; }
#specBody .spec__atpos { width: 66px; }
#specBody .spec__atadd { margin-left: 0; padding: 6px 11px; }

#specBody .spec__empty {
  color: var(--wk-faint);
  font-family: var(--wk-sans);
  font-size: 12.5px;
  padding: 10px 2px;
}

/* condensed two-column layout: data left, diagram right — the whole spec
   reads without scrolling on a normal screen */
.spec__cols {
  display: flex;
  gap: 40px;
  align-items: flex-start;
  flex-wrap: wrap;
}
/* the tables can outgrow the column (unified sections table) — scroll
   inside the column instead of spilling over the guide */
.spec__coldata { flex: 1 1 560px; min-width: 520px; overflow-x: auto; }

/* spec guide — one minimal HTML/SVG figure per term */
.spec__guide { flex: 0 1 380px; min-width: 300px; max-width: 430px; }
.spec__gcard {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 7px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.spec__gcard:last-child { border-bottom: none; }
.spec__gfig {
  flex: 0 0 150px;
  height: 64px;
  color: var(--gray-500);
}
.spec__gfig text {
  fill: var(--gray-500);
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.06em;
}
.spec__gfig .gf-cut { stroke: #3fbf6a; stroke-width: 3; stroke-linecap: round; }
.spec__gfig .gf-faint { opacity: 0.3; }
.spec__gfig .gf-dim { stroke: currentColor; stroke-width: 1; fill: none; }
.spec__gfig .gf-arr { fill: currentColor; }
.spec__gfig .gf-rev {
  stroke: currentColor;
  stroke-width: 1;
  stroke-dasharray: 3 3;
  opacity: 0.6;
  --o: 0.6;
}
/* the guide figures trace themselves in the first time they scroll into view:
   the green cut lines draw like the laser making them (pathLength="1" +
   per-line --i stagger), then the dimension callouts fade up. JS puts figures
   in .gfx-wait on load and flips to .gfx-run on intersection; without JS (or
   under reduced motion) nothing is ever hidden. */
.spec__gfig.gfx-wait .gf-cut { stroke-dasharray: 1; stroke-dashoffset: 1; }
.spec__gfig.gfx-wait .gf-dim, .spec__gfig.gfx-wait .gf-arr,
.spec__gfig.gfx-wait .gf-rev, .spec__gfig.gfx-wait text { opacity: 0; }
.spec__gfig.gfx-run .gf-cut {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: gfTrace 0.5s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
  animation-delay: calc(var(--i, 0) * 0.22s);
}
.spec__gfig.gfx-run .gf-dim, .spec__gfig.gfx-run .gf-arr,
.spec__gfig.gfx-run .gf-rev, .spec__gfig.gfx-run text {
  opacity: 0;
  animation: gfFade 0.35s ease forwards;
  animation-delay: 0.6s;
}
@keyframes gfTrace { to { stroke-dashoffset: 0; } }
@keyframes gfFade { to { opacity: var(--o, 1); } }
.spec__gfig .gf-num { fill: #3fbf6a; font-size: 12px; }
.spec__gterm {
  font-family: var(--mono);
  font-weight: 700;
  font-size: 11.5px;
  color: #3fbf6a;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  margin-bottom: 2px;
}
.spec__gdesc {
  font-size: 12px;
  color: var(--gray-500);
  line-height: 1.5;
}
.d-foot {
  color: var(--gray-500);
  font-size: 12px;
  line-height: 1.55;
  max-width: 620px;
  margin-top: 4px;
}
.d-foot b { color: var(--gray-400); }

/* 3D pattern preview under the tables */
.spec__preview { margin: 4px 0 18px; }
.spec__preview3d { min-height: clamp(320px, 42vh, 460px); }
.spec__prevnote { color: var(--gray-500); font-size: 11px; font-family: var(--mono); text-transform: none; letter-spacing: 0; }
.spec__prevhdr-right { display: inline-flex; align-items: center; gap: 14px; }
.spec__prevopt {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--gray-400);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  cursor: pointer;
  user-select: none;
}
.spec__prevopt input { accent-color: #3fbf6a; cursor: pointer; }
.spec__preview:fullscreen {
  display: flex;
  flex-direction: column;
  background: var(--black);
}
.spec__preview:fullscreen .spec__preview3d {
  flex: 1;
  min-height: 0;
  height: auto;
}

/* the "▾ Specifications" dropdown lives in the model's control bar, fullscreen only */
.spec__secbtn { display: none; }
#specPanel:fullscreen .spec__secbtn {
  display: inline-flex;
  align-items: center;
  background: transparent;
  border: 1px solid var(--line-strong);
  color: var(--offwhite);
  font-family: var(--mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  padding: 4px 10px;
  border-radius: 5px;
  cursor: pointer;
  white-space: nowrap;
  transition: all .15s ease;
}
#specPanel:fullscreen .spec__secbtn:hover { background: var(--white); color: var(--black); border-color: var(--white); }
.spec__cutdepth {
  width: 92px; height: 4px; vertical-align: middle; margin: 0 2px 0 6px;
  accent-color: #3fbf6a; cursor: pointer;
}

/* Whole-panel fullscreen: builder tables (left) + live 3D model (right),
   both on screen at once — fixes the laptop "can't fit specs AND model".
   The guide is hidden to give the model room; Esc exits. */
#specPanel:fullscreen {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  grid-template-columns: 1fr;
  grid-template-areas: "hdr" "view";
  height: 100vh;
  padding: 0;
  box-sizing: border-box;
  background: var(--black);
  overflow: hidden;
  position: relative; /* anchor the specifications dropdown */
}
#specPanel:fullscreen > .spec__hdr { grid-area: hdr; margin: 0; padding: 10px 18px; }
#specPanel:fullscreen > .spec__preview {
  grid-area: view; margin: 0; height: 100%;
  display: flex; flex-direction: column; min-height: 0;
}
#specPanel:fullscreen .spec__preview3d { flex: 1; min-height: 0; height: auto; }
#specPanel:fullscreen #specGuide { display: none; }
/* findings / actions / error are edited through the dropdown, not shown loose */
#specPanel:fullscreen > #specFindings,
#specPanel:fullscreen > .spec__actions,
#specPanel:fullscreen > #specError { display: none; }

/* the "▾ Specifications" dropdown: a floating, scrollable, fully-editable panel
   of every section, opened from the model's control bar, over the model */
#specPanel:fullscreen > .spec__cols { display: none; }
#specPanel:fullscreen.spec--specs-open > .spec__cols {
  display: block;
  position: absolute;
  z-index: 20;
  top: 92px;
  left: 14px;
  width: min(680px, 52vw);
  max-height: calc(100vh - 108px);
  overflow: auto;
  background: #0b0c0e;
  padding: 6px 18px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.65);
}
#specPanel:fullscreen.spec--specs-open #specBody { border: none; }
.conv__preview svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  -webkit-user-drag: none;
  user-drag: none;
}
.conv__preview.is-loading { cursor: default; }
.conv__loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  color: var(--gray-400);
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  font-size: 12px;
}
/* stage-accurate conversion progress: the fill tracks real pipeline stages */
.conv__bar {
  width: min(340px, 60vw);
  height: 4px;
  background: rgba(255, 255, 255, 0.12);
  border-radius: 2px;
  overflow: hidden;
}
.conv__bar i {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: 2px;
  box-shadow: 0 0 10px var(--accent-glow);
  transition: width 0.3s ease;
}

.conv__previewfoot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 9px 14px;
  border-top: 1px solid var(--line);
}
.conv__zoomhint {
  font-size: 10px;
  color: var(--gray-500);
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
}
.conv__zoombtns { display: flex; gap: 6px; }
.iconbtn {
  width: 28px; height: 28px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--white);
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
  transition: background .18s ease, color .18s ease;
}
.iconbtn:hover { background: var(--white); color: var(--black); }

/* Live pipeline tracker */
.pipeline { list-style: none; margin-bottom: 28px; }
.pl {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 8px 0;
  font-size: 12px;
  color: var(--gray-500);
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  transition: color .2s ease;
}
/* display:flex above defeats the hidden attribute -- restore it (the Translate
   row only appears when a native .sldprt actually goes through translation) */
.pl[hidden] { display: none; }
.pl__icon {
  width: 17px; height: 17px;
  border-radius: 50%;
  border: 1.5px solid var(--line-strong);
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
}
.pl__label em {
  display: block;
  font-style: normal;
  font-size: 9px;
  color: var(--gray-500);
  letter-spacing: var(--track);
}
.pl[data-state="active"] { color: var(--white); }
.pl[data-state="active"] .pl__icon {
  border-color: var(--white);
  border-top-color: transparent;
  animation: spin .8s linear infinite;
}
.pl[data-state="done"] { color: var(--white); }
.pl[data-state="done"] .pl__icon { background: #3fbf6a; border-color: #3fbf6a; }
.pl[data-state="done"] .pl__icon::after { content: "✓"; color: #000; font-size: 11px; font-weight: 700; }
.pl[data-state="error"] .pl__icon { background: #a05252; border-color: #a05252; }
.pl[data-state="error"] .pl__icon::after { content: "!"; color: #fff; font-size: 11px; font-weight: 700; }
.pl[data-state="soon"]::after {
  content: "SOON";
  margin-left: auto;
  font-size: 9px;
  border: 1px solid var(--line);
  padding: 2px 6px;
  color: var(--gray-500);
  letter-spacing: var(--track-sm);
}

.profiles__summary {
  font-size: 13px;
  color: var(--gray-400);
  margin-bottom: 12px;
  line-height: 1.5;
}
.profiles__summary strong { color: var(--white); font-family: var(--mono); }
.profiles__summary .warn { color: #d8b06a; }
.profiles {
  list-style: none;
  max-height: 220px;
  overflow-y: auto;
  margin-bottom: 22px;
  border: 1px solid var(--line);
}
.profiles:empty { display: none; }
.profiles li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}
.profiles li:last-child { border-bottom: none; }
.profiles__chip {
  width: 11px; height: 11px; border-radius: 2px; flex: none;
}
.profiles__name { color: var(--gray-400); text-transform: uppercase; letter-spacing: var(--track-sm); font-size: 11px; }
.profiles__len { margin-left: auto; font-family: var(--mono); font-size: 12px; }

.conv__actions { display: flex; flex-direction: column; }

/* minimal post-drop chooser: hide the pipeline/geometry chrome, leave only the
   model and the two paths forward */
.conv--choice .conv__previewhdr,
.conv--choice .conv__previewfoot,
.conv--choice .conv__meta { display: none; }
.conv--choice .conv__output { grid-template-columns: 1fr; }
/* chooser mode strips #quote to title -> model -> two buttons ("nothing else
   above the buttons"), and the model window yields so the WHOLE section keeps
   fitting one viewport: height = viewport minus the remaining fixed overhead,
   floored for usability, capped for taste */
.quote--choice .eyebrow,
.quote--choice .section__lead,
.quote--choice .qpaths,
.quote--choice .qrail,
.quote--choice .dropzone,
.quote--choice .dropzone__note { display: none; }
/* chooser mode collapses the split so the model spans the page */
.quote--choice .qsplit { display: block; }
.conv--choice .conv__preview {
  min-height: 0;
  /* overhead above/below the model partly scales with the viewport (section
     padding, choice margins are vh-clamped) — subtract both parts */
  height: clamp(240px, calc(100svh - 300px - 8vh), 640px);
}
.conv__choice { display: flex; flex-direction: column; align-items: center; gap: 12px; margin-top: clamp(12px, 2vh, 22px); }
/* the two ways forward, styled like the STORE's buttons (operator,
   2026-07-30: "up to date and aligned with the rest of the store") */
.conv__choicebtns .btn {
  height: 44px; padding: 0 26px; font-size: 11.5px; letter-spacing: .1em;
  font-weight: 700; border-radius: var(--r-sm, 4px);
  border: 1px solid var(--line-2, rgba(255,255,255,.18));
}
.conv__choicebtns .btn--solid { background: var(--fg, #fff); color: #000; border-color: transparent; }
.conv__choicebtns .btn--solid:hover { background: #fff; color: #000; }
.conv__choicebtns .btn--ghost { color: var(--fg, #fff); background: transparent; font-weight: 600; }
.conv__choicebtns .btn--ghost:hover { background: rgba(255,255,255,.05); border-color: var(--line-3, rgba(255,255,255,.35)); color: var(--fg, #fff); }
.conv__choicebtns { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
.conv__restart {
  background: none; border: none; cursor: pointer;
  color: var(--gray-500); font-size: 12px;
  letter-spacing: var(--track-sm); text-transform: uppercase;
}
.conv__restart:hover { color: var(--offwhite); }
.conv__saved {
  margin-top: 12px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--gray-400);
  word-break: break-all;
  line-height: 1.5;
}

.conv__metatitle {
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  font-size: 13px;
  font-weight: 700;
  margin-bottom: 16px;
}
.specs { margin-bottom: 22px; }
.specs > div {
  display: flex;
  justify-content: space-between;
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
}
.specs dt { color: var(--gray-400); font-size: 13px; text-transform: uppercase; letter-spacing: var(--track-sm); }
.specs dd { font-family: var(--mono); font-size: 14px; }
.conv__meta .btn { width: 100%; margin-top: 10px; }

.conv__error {
  border: 1px solid #a05252;
  background: rgba(192,57,43,.12);
  color: #cf7f7f;
  padding: 16px 20px;
  font-size: 14px;
  text-align: center;
}

/* ---------------------------- FORM ---------------------------- */
.form__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 28px;
}
.form__group {
  border: 1px solid var(--line);
  padding: 24px;
}
.form__group--full { grid-column: 1 / -1; }

/* ---- collapsible spec groups (the requirements form) ----
   The header is a real <button> with aria-expanded, not a <details>: the body
   has to stay laid out while it animates, and a closed <details> hides its
   own content in a way that cannot be transitioned in the browsers this ships
   to. `inert` on the closed body keeps it out of the tab order all the same. */
.form__group--disc { padding: 0; border: 0; border-top: 1px solid var(--line);
  background: none; transition: background .18s; }
.form__group--disc:first-child { border-top: 0; }
.form__group--disc.is-open { background: rgba(255, 255, 255, .022); }
.form__grouphead {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  gap: 12px; background: none; border: 0; cursor: pointer; text-align: left;
  padding: 14px 18px; color: var(--gray-400);
  font: 600 12px/1.2 inherit; letter-spacing: var(--track-sm);
  text-transform: uppercase; transition: color .15s;
}
.form__grouphead:hover { color: var(--white); }
.form__grouphead:focus-visible { outline: 2px solid var(--accent, #7fa0cc); outline-offset: -2px; }
.form__group--disc.is-open .form__grouphead { color: var(--white); }
.form__chev { flex: none; width: 10px; height: 6px; stroke: currentColor; stroke-width: 1.6;
  fill: none; stroke-linecap: round; stroke-linejoin: round; transition: transform .26s ease; }
.form__group--disc.is-open .form__chev { transform: rotate(180deg); }
/* 0fr -> 1fr is the one height animation that needs no measuring, so the
   group can grow by whatever its contents happen to be */
.form__groupbody { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .26s ease; }
.form__group--disc.is-open .form__groupbody { grid-template-rows: 1fr; }
.form__groupinner { overflow: hidden; min-height: 0; }
.form__group--disc .form__groupinner > :last-child { padding-bottom: 18px; }
.form__group--disc .field { padding-left: 18px; padding-right: 18px; }
.form__group--disc .field:first-of-type { margin-top: 0; }

/* the free-text box: the one thing open by default, so it gets the room */
.field--notes { max-width: var(--req-w, 760px); margin: 0 auto; }
.field--notes textarea { min-height: 122px; }
.form__more { max-width: var(--req-w, 760px);
  margin: clamp(14px, 2.2vh, 26px) auto clamp(6px, .9vh, 10px);
  color: var(--gray-500, #7a7a7a); font: 600 10.5px/1 inherit;
  letter-spacing: var(--track-sm); text-transform: uppercase; }
.form__group legend {
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  font-size: 12px;
  font-weight: 600;
  color: var(--gray-400);
  padding: 0 8px;
}
.field { display: block; margin-top: 16px; }
.field:first-of-type { margin-top: 6px; }
.field__label {
  display: block;
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  font-size: 11px;
  color: var(--gray-400);
  margin-bottom: 7px;
}
.field__hint { display: block; font-size: 11px; color: var(--gray-500); margin-top: 5px; }

.field input,
.field select,
.field textarea {
  width: 100%;
  background: var(--black);
  border: 1px solid var(--line);
  color: var(--white);
  padding: 11px 13px;
  font-family: var(--font);
  font-size: 14px;
  transition: border-color .2s ease;
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent-line);
}
.field select[multiple] { padding: 6px; }
.field textarea { resize: vertical; }
.field input::placeholder,
.field textarea::placeholder { color: var(--gray-500); }
.field input[type="file"] { padding: 9px; font-size: 12px; color: var(--gray-400); }
.form__intro { color: var(--gray-400); font-size: 14px; line-height: 1.6; max-width: 660px; margin: 0 auto 26px; text-align: center; }
.checks { display: grid; gap: 10px; margin-top: 8px; }
.check { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--white); cursor: pointer; user-select: none; line-height: 1.3; }
.check input[type="checkbox"] { width: 15px; height: 15px; padding: 0; margin: 0; accent-color: var(--white); flex: 0 0 auto; }

/* ---------------------------- RESULT ---------------------------- */
.result__grid {
  display: grid;
  grid-template-columns: 360px 1fr;
  gap: 32px;
  margin-top: 50px;
}
.result__pricecard {
  border: 1px solid var(--line-strong);
  padding: 36px 30px;
  text-align: center;
  background: var(--black);
}
.result__label {
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  font-size: 11px;
  color: var(--gray-400);
}
.result__price {
  font-family: var(--mono);
  font-size: 44px;
  font-weight: 700;
  margin: 12px 0 6px;
  letter-spacing: -1px;
}
.result__sub { color: var(--gray-400); font-size: 14px; margin-bottom: 26px; }
.result__pricecard .btn { width: 100%; }
.result__disclaimer { color: var(--gray-500); font-size: 11px; margin-top: 16px; }

.result__breakdown { border: 1px solid var(--line); padding: 32px; }
.result__bdtitle {
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 20px;
}
.breakdown { list-style: none; }
.breakdown li {
  display: flex;
  justify-content: space-between;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
  font-size: 15px;
}
.breakdown li em { color: var(--gray-500); font-style: normal; font-size: 12px; }
.breakdown__meta {
  display: flex;
  gap: 40px;
  margin-top: 24px;
}
.breakdown__meta strong { display: block; font-family: var(--mono); font-size: 20px; margin-top: 4px; }

/* ---------------------------- STEPS ----------------------------
   2026-08-30 de-centering pass: header left, corners as a vertical
   hover-accordion right. Collapsed = the corner name + a plus; hover or
   keyboard focus expands the mechanism title and one-sentence body (the
   grid-template-rows 0fr->1fr trick animates height without JS). Touch
   devices get every corner expanded — there is no hover to find. */
.section--process .container {
  display: grid;
  grid-template-columns: minmax(280px, .8fr) minmax(440px, 1.2fr);
  gap: clamp(42px, 7.5vw, 140px);
  align-items: center;
  width: 100%;                /* keep max-width centering as a flex child */
}
/* 2026-08-31 spread pass, dialed to 12.5% (operator revised off 25%):
   the split sections run a container 12.5% wider than --maxw so the left
   block sits further left and the right block further right; the bigger
   column gaps keep each half hugging its own edge */
.section--process .container,
.section--quote .container,
.section--req .container,
.section--cap .container {
  max-width: min(calc(var(--maxw) * 1.125), calc(100vw - 56px));
}
.prochead .eyebrow, .prochead .section__title { text-align: left; }
.steps {
  list-style: none;
  display: flex;
  flex-direction: column;
  margin-top: 0;
  /* script.js sets min-height = collapsed height + the TALLEST reveal, so a
     hover only slides the rows below it inside pre-reserved space and the
     section itself never changes height (operator 2026-08-30). It also pads
     the list down so the middle row lines up with the heading — which is why
     the rule below owns the top line instead of this box: a border here sits
     ABOVE that padding and stayed put while the rows moved down (operator
     2026-09-01, "the top bouncary line for the speed section was not moved
     down"). The line is the first row's own edge, so it travels with it. */
}
.step:first-child { border-top: 1px solid var(--line); }
.step {
  padding: clamp(26px, 3.6vh, 40px) 12px;
  border-bottom: 1px solid var(--line);
  outline: none;
  cursor: default;
  position: relative;
}
/* hover accent rail growing from the row's centerline */
.step::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 2px;
  height: 0;
  background: var(--accent);
  transition: height .4s var(--ease), top .4s var(--ease);
}
.step:hover::before, .step:focus::before { top: 14%; height: 72%; }
.step:hover, .step:focus { background: rgba(127, 160, 204, .04); }
/* the slot holds a triangle corner (SPEED / COST / QUALITY), not an index -
   it is the collapsed face of the row. 2026-08-31 icon pass (operator: big
   type was too much for three words; design carries the height instead):
   each row's icon is the triangle itself with THAT corner's vertex marked */
.step__num {
  display: flex;
  align-items: center;
  gap: 20px;
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  font-weight: 600;
  font-size: 18px;
  line-height: 1;
  transition: transform .4s var(--ease);
}
.step__tri {
  flex: none;
  width: 46px;
  height: 42px;
}
.step__tri .tri-out {
  fill: none;
  stroke: rgba(127, 160, 204, .38);
  stroke-width: 1.5;
  transition: stroke .35s;
}
.step__tri .tri-dot {
  fill: var(--accent);
  transform-box: fill-box;
  transform-origin: center;
  transition: transform .35s var(--ease);
}
.step:hover .step__tri .tri-out,
.step:focus .step__tri .tri-out { stroke: var(--accent); }
.step:hover .step__tri .tri-dot,
.step:focus .step__tri .tri-dot { transform: scale(1.45); }
.step__num::after {
  content: "+";
  margin-left: auto;
  align-self: center;
  font: 300 26px var(--mono);
  color: var(--gray-400);
  transition: transform .35s var(--ease), color .35s;
}
.step:hover .step__num, .step:focus .step__num { transform: translateX(10px); }
.step:hover .step__num::after,
.step:focus .step__num::after { transform: rotate(45deg); color: var(--accent); }
.step__reveal {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows .45s var(--ease), opacity .4s ease;
}
.step__inner { overflow: hidden; }
.step:hover .step__reveal,
.step:focus .step__reveal { grid-template-rows: 1fr; opacity: 1; }
.step__title {
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  font-size: 17px;
  font-weight: 600;
  margin: 18px 0 10px;
  color: var(--accent);
}
.step__body {
  color: var(--gray-400);
  font-size: 15px;
  font-weight: 300;
  padding-bottom: 4px;
  max-width: 58ch;
}
/* revealed copy aligns under the word, past the icon column */
.step__inner { padding-left: 66px; }
@media (hover: none) {
  .step__reveal { grid-template-rows: 1fr; opacity: 1; }
  .step__num::after { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .step__reveal { transition: none; }
  .step__num::after { transition: none; }
}

/* ---------------------------- CAPABILITIES ----------------------------
   2026-08-30 compaction: a two-column spec sheet. Header + patterns +
   quality lines left, 2x2 stat cards right, envelope strip full-width
   below. Cards answer hover so the sheet reads alive, not printed. */
.section--cap .container {
  display: grid;
  grid-template-columns: minmax(300px, .9fr) minmax(420px, 1.1fr);
  gap: clamp(34px, 5.5vw, 110px);
  align-items: center;
}
.caphead .eyebrow, .caphead .section__title { text-align: left; }
.caphead .section__lead { text-align: left; margin-left: 0; }
.caphead .cap__patline, .caphead .cap__quality {
  text-align: left; line-height: 1.9;
}
.caphead .cap__patline { margin-top: 26px; }
.caphead .cap__quality { margin-top: 10px; }
.cap__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--line);
  margin-top: 0;
  border: 1px solid var(--line);
}
.cap__card {
  background: var(--gray-900);
  padding: clamp(20px, 3vh, 30px) 20px;
  text-align: left;
  transition: background .3s ease;
}
.cap__card:hover { background: rgba(127, 160, 204, .07); }
.cap__stat { font-family: var(--mono); font-size: clamp(22px, 2.6vw, 30px); font-weight: 700; letter-spacing: -1px; }
.cap__label {
  text-transform: uppercase;
  letter-spacing: var(--track-sm);
  font-size: 11px;
  color: var(--gray-400);
  margin-top: 4px;
}

/* ---- capabilities: envelope strip + pattern/quality lines ----
   2026-08-28, condensed same day (operator: "condensed into a much smaller
   page" after the premium build-out). One hairline lattice: the envelope
   strip fuses onto .cap__grid via its 1px gap so stats + ranges read as a
   single spec sheet; cut patterns and quality collapse to two quiet
   centred lines instead of card grids. */
.cap__env {
  grid-column: 1 / -1;          /* full width beneath both columns */
  margin-top: clamp(10px, 2vh, 22px);
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
.cap__cell {
  background: var(--gray-900);
  padding: 14px 18px;
  display: flex; flex-direction: column; gap: 4px;
}
.cap__cell span {
  text-transform: uppercase; letter-spacing: var(--track-sm);
  font-size: 10.5px; color: var(--gray-400);
}
.cap__cell b { font-family: var(--mono); font-size: 13px; font-weight: 500; }
.cap__patline, .cap__quality {
  text-align: center; text-transform: uppercase;
  letter-spacing: var(--track-sm); font-size: 11.5px;
  color: var(--gray-400); line-height: 2.1;
}
.cap__patline b { color: var(--fg); font-weight: 600; }

/* ---------------------------- CONTACT ---------------------------- */
.section--contact { text-align: center; }
.section--contact .hero__actions { margin-top: 34px; }

/* ---------------------------- SCROLL REVEAL ----------------------------
   2026-08-30: sections below the hero rise in as they enter the viewport
   (script.js tags .rise / .rise-in via IntersectionObserver; skipped
   entirely under prefers-reduced-motion). Accordion rows and stat cards
   stagger by sibling index through --rise-d. */
.rise {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .7s var(--ease) var(--rise-d, 0s),
              transform .7s var(--ease) var(--rise-d, 0s);
}
.rise-in { opacity: 1; transform: none; }

/* ---------------------------- FOOTER ----------------------------
   The footer is the SHARED site shell now (.sfoot in /chrome.css). */

/* ---------------------------- RESPONSIVE ---------------------------- */
@media (max-width: 920px) {
  .qsplit { display: block; }
  .qrail { border-left: none; border-top: 1px solid var(--line);
    padding-left: 0; padding-top: 22px; margin-top: 30px; }
  .section--process .container, .section--cap .container { display: block; }
  .steps { margin-top: 40px; }
  .section--cap .cap__grid { margin-top: 36px; }
  .cap__env { margin-top: 20px; }
  .cap__env { grid-template-columns: repeat(2, 1fr); }
  .cap__cell:last-child { grid-column: 1 / -1; }
  .reqcard { margin-right: auto; }
  .result__grid { grid-template-columns: 1fr; }
  .conv__output { grid-template-columns: 1fr; }
  .form__grid { grid-template-columns: 1fr; }
  .nav__links { display: none; }
}
@media (max-width: 520px) {
  .breakdown__meta { flex-direction: column; gap: 18px; }
  .footer__inner { flex-direction: column; gap: 10px; text-align: center; }
}

/* ---------- Cutting-program build panel ---------- */
.conv__build {
  margin-top: 14px;
  border: 1px solid var(--line);
  padding: 12px 14px;
}
.conv__buildhdr {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}
.conv__buildstage {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.conv__buildverdict {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  padding: 3px 10px;
  border: 1px solid var(--line-strong);
}
.conv__buildverdict.is-ok { color: #7fff9e; border-color: #7fff9e; }
.conv__buildverdict.is-bad { color: #ff8a7f; border-color: #ff8a7f; }
.conv__buildlog {
  margin: 0;
  max-height: 180px;
  overflow-y: auto;
  font-family: var(--mono);
  font-size: 10.5px;
  line-height: 1.55;
  color: var(--gray-400);
  white-space: pre-wrap;
  word-break: break-all;
}

/* ---- 3D dims overlay (top-left of the converted-part preview) ---- */
.conv__preview--3d { position: relative; }
.dims3d { position: absolute; top: 10px; left: 10px; z-index: 5;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  max-width: min(340px, 85%);
  font: 400 10.5px var(--mono); color: var(--gray-400);
  background: rgba(4,6,9,.8); border: 1px solid var(--line);
  border-radius: 3px; padding: 7px 11px; }
.dims3d__hdr { display: inline-flex; gap: 7px; align-items: center;
  text-transform: uppercase; letter-spacing: .12em; font-size: 9.5px;
  color: var(--gray-400); cursor: pointer; }
.dims3d__hdr input { accent-color: var(--accent); width: 12px; height: 12px; }
.dims3d__seg { display: inline-flex; border: 1px solid var(--line);
  border-radius: 2px; overflow: hidden; }
.dims3d__seg button { background: transparent; border: 0; color: var(--gray-500);
  font: 600 9.5px var(--mono); letter-spacing: .06em; padding: 3px 9px; cursor: pointer; }
.dims3d__seg button.is-on { color: var(--offwhite); background: rgba(255,255,255,.08); }

/* ---- "dims" overlay on the converted-part model ----
   The shared store/dimensions.js draws leader lines + labels into an
   .dim-overlay SVG over #convPreview3d. Each page that mounts that overlay
   carries its own copy of these rules (builder.css does the same, scoped
   under #partBuilder) — the module ships behaviour, not styling. */
.dim-overlay .dim-line { stroke: #eaf0f6; stroke-width: 1.5; fill: none; stroke-linecap: round; }
.dim-overlay .dim-arrow { fill: #eaf0f6; }
.dim-overlay .dim-lead { stroke: rgba(234,240,246,.7); stroke-width: 1.1; fill: none; }
.dim-overlay .dim-ext { stroke: rgba(234,240,246,.45); stroke-width: 1; stroke-dasharray: 2.5 2.5; }
.dim-overlay .dim-label { fill: #f4f7fb; font-family: var(--mono); font-size: 11px; letter-spacing: .02em; }
.dim-overlay .dim-label-bg { fill: rgba(4,6,9,.82); stroke: rgba(255,255,255,.16); stroke-width: 1; }
/* A callout is a control: clicking it flies the camera to that measurement. The
   overlay stays pointer-events:none THROUGHOUT — a label that were a hit target
   would swallow the pointerdown and a rotate-drag starting on it could not orbit
   — so dimensions.js hit-tests in JS and marks the hovered label .is-hot. */
.dim-overlay .dim-label-g--hit .dim-label,
.dim-overlay .dim-label-g--hit .dim-label-bg { transition: fill var(--dur) var(--ease), stroke var(--dur) var(--ease); }
.dim-overlay .dim-label-g--hit.is-hot .dim-label-bg { fill: rgba(6,10,16,.94); stroke: var(--accent); }
.dim-overlay .dim-label-g--hit.is-hot .dim-label { fill: #fff; }
.dim-overlay.dim-hl .dim-line, .dim-overlay.dim-hl .dim-ext, .dim-overlay.dim-hl .dim-lead { stroke: #b9cee2; }
.dim-overlay.dim-hl .dim-arrow { fill: #b9cee2; }
.dim-overlay.dim-hl .dim-label { fill: #eaf3ff; }
/* the badge sits under the dims control, not over it */
.dim-badge { position: absolute; left: 12px; top: 54px; z-index: 4; display: flex;
  flex-wrap: wrap; gap: 6px; max-width: 60%; }
.dim-badge span { font-family: var(--mono); font-size: 10.5px; color: var(--offwhite);
  background: rgba(0,0,0,.66); border: 1px solid var(--line); border-radius: 2px;
  padding: 4px 8px; letter-spacing: .02em; }
.dim-hint { position: absolute; left: 50%; bottom: 12px; transform: translateX(-50%); z-index: 4;
  font-family: var(--mono); font-size: 10.5px; color: var(--accent); background: rgba(0,0,0,.7);
  border: 1px solid var(--accent-line); border-radius: 999px; padding: 5px 12px;
  letter-spacing: .04em; white-space: nowrap; }

/* ---- #quote rotating backdrop + drop focus ----
   Two video layers crossfade between round-5 clips (script.js cues them); the
   still underneath is the base frame and the reduced-motion fallback. When a
   file drops, .quote--focus dims and stills the whole backdrop — the model is
   the content now — and the frame/vignette on the 3D stage carries the style
   the footage gave up. */
.sec-bg--rotate img,
.sec-bg--rotate .qbg__vid {
  transition: opacity 1.6s ease, filter .9s ease;
}
.sec-bg--rotate .qbg__vid { position: absolute; inset: 0; opacity: 0; }
/* the reel reads as content, not texture: strong level, one clip at a time */
.sec-bg--rotate .qbg__vid.is-live { opacity: .46; }
/* the still is only the opening frame: once footage is rolling it bows out —
   left underneath it doubles every clip into a muddy multiple exposure */
.sec-bg--rotate.is-rolling img { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .sec-bg--rotate .qbg__vid { display: none; } }

.section--quote.quote--focus .sec-bg img,
.section--quote.quote--focus .sec-bg video {
  opacity: .05;
  filter: saturate(.15) contrast(1) blur(5px);
}

/* the drop commits: the box settles inward and eases out instead of vanishing */
.dropzone.is-committing {
  border-color: var(--white);
  transform: scale(.97);
  opacity: 0;
  transition: transform .34s cubic-bezier(.4, 0, .2, 1), opacity .3s ease .04s,
              border-color .12s ease;
}

/* the working panel arrives as one piece */
.conv--enter { animation: convIn .62s cubic-bezier(.22, .9, .3, 1) both; }
@keyframes convIn {
  from { opacity: 0; transform: translateY(16px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

/* the 3D stage: a quiet accent frame + vignette so the focused view still has
   presence, and a single expanding ring the moment the model takes over */
.quote--choice .conv__preview--3d {
  border: 1px solid rgba(127,160,204, .26);
  box-shadow: 0 24px 80px rgba(0, 0, 0, .55), inset 0 0 140px rgba(6, 7, 8, .38);
}
.conv__preview--3d.is-revealed { animation: tvIn .9s cubic-bezier(.22, .9, .3, 1) both; }
@keyframes tvIn {
  from { opacity: 0; transform: scale(.982); }
  to   { opacity: 1; transform: none; }
}
.conv__preview--3d.is-revealed::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border: 1px solid rgba(127,160,204, .6);
  animation: tvRing 1.25s ease-out .1s both;
}
@keyframes tvRing {
  from { opacity: .85; transform: scale(.988); }
  to   { opacity: 0;   transform: scale(1.035); }
}
@media (prefers-reduced-motion: reduce) {
  .conv--enter, .conv__preview--3d.is-revealed { animation: none; }
  .conv__preview--3d.is-revealed::after { display: none; }
}


}
