/* ============================================================
   Reconstrura product site — "Studio"
   The page shares the app's exact palette (reconstrura/gui/theme.py)
   so the marketing site and the product read as one thing.
   Zero external assets. System font stack. WCAG-AA.
   Reduced-motion safe.
   ============================================================ */

:root {
  /* ---- app surfaces — exact values from reconstrura/gui/theme.py ---- */
  --app-void: #080a0e;    /* viewports, inset fields (theme.VOID)     */
  --bg: #0b0d13;          /* window canvas          (theme.BG)        */
  --rail: #0e1117;        /* nav rail               (theme.RAIL)      */
  --panel: #141822;       /* cards                  (theme.PANEL)     */
  --panel-hi: #1b2029;    /* raised / hovered       (theme.PANEL_HI)  */
  --panel-hi2: #222835;   /* pressed / double-raised (theme.PANEL_HI2)*/
  --input: var(--app-void);
  --border: #212734;      /* hairline borders       (theme.BORDER)    */
  --border-hi: #333b4c;   /* emphasized borders     (theme.BORDER_HI) */
  /* the 1px inner top edge that gives every app surface its lift
     without a drop shadow — the product's core depth device */
  --lift: inset 0 1px 0 rgba(255, 255, 255, 0.045);

  /* ---- text ramp (theme.TEXT / TEXT_DIM / MUTED / FAINT) ---- */
  --text: #eef1f7;        /* headings, primary                        */
  --muted: #aeb7c7;       /* body copy          (theme.TEXT_DIM)      */
  --dim: #8b94a6;         /* captions, fine print                     */
  --faint: #7f899c;       /* in-app labels      (theme.MUTED)         */
  --fainter: #5a6273;     /* eyebrows, disabled (theme.FAINT)         */

  /* ---- accent: a single azure with a violet gradient partner ---- */
  --accent: #5b8cff;
  --accent-hi: #83a8ff;
  --accent-lo: #3e6fe0;
  --accent-alt: #9b7bff;  /* the signature sweep's far end            */
  --accent-dim: #24365c;
  /* the app's primary-button gradient, 1:1 */
  --grad-primary: linear-gradient(153deg, var(--accent-hi) 0%,
                                  var(--accent) 55%, var(--accent-lo) 100%);
  /* the azure→violet sweep used for progress and marketing accents */
  --grad-sweep: linear-gradient(90deg, var(--accent), var(--accent-alt));

  /* ---- status (theme.OK / WARN / DANGER) ---- */
  --ok: #34d399;
  --warn: #fbbf24;
  --danger: #fb7185;

  /* page stage — a step darker than the app chrome, so the Studio
     windows read as objects lying on the page rather than holes in it */
  --void: #06070b;
  --void-hi: #0a0c11;

  /* Inter first: it's the app's bundled UI face; the rest is the
     same fallback chain the app uses */
  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
          "Noto Sans", Ubuntu, Cantarell, "DejaVu Sans", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", "Segoe UI Mono", Menlo,
          Consolas, "Liberation Mono", monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  background: var(--void);
  color: var(--text);
  font-family: var(--font);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

a { color: var(--accent-hi); text-decoration: none; }
a:hover { text-decoration: underline; }
img, svg, canvas { max-width: 100%; }

:focus-visible {
  outline: 2px solid var(--accent-hi);
  outline-offset: 3px;
  border-radius: 4px;
}

::selection { background: var(--accent-dim); color: #fff; }

.mono, .num {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

.skip-link {
  position: absolute;
  left: 12px;
  top: -60px;
  z-index: 100;
  padding: 10px 16px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  transition: top 0.2s ease;
}
.skip-link:focus { top: 12px; }

section[id], footer[id], .legal-main article[id] { scroll-margin-top: 84px; }

/* ============================================================
   Buttons — restrained; primary mirrors the app's primary button
   ============================================================ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 13px 26px;
  border-radius: 10px;
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  border: 0;
  cursor: pointer;
  transition: transform 0.16s ease, box-shadow 0.2s ease,
              border-color 0.16s ease, background-color 0.16s ease;
}
.btn:hover { text-decoration: none; }
/* Echoes QPushButton[primary="true"], but stops at --accent rather than the
   app's darker --accent-lo endpoint so dark text remains WCAG-AA throughout. */
.btn-primary {
  background: linear-gradient(153deg, var(--accent-hi), var(--accent));
  color: #071022;
  border: 1px solid rgba(131, 168, 255, 0.55);
  box-shadow:
    var(--lift),
    0 6px 22px rgba(91, 140, 255, 0.30),
    0 2px 6px rgba(0, 0, 0, 0.4);
}
.btn-primary:hover {
  background: linear-gradient(153deg, #9cbaff 0%, var(--accent-hi) 55%,
                              var(--accent) 100%);
  border-color: rgba(255, 255, 255, 0.28);
  transform: translateY(-1px);
  box-shadow:
    var(--lift),
    0 12px 34px rgba(91, 140, 255, 0.40),
    0 3px 10px rgba(0, 0, 0, 0.45);
}
.btn-primary:active {
  transform: translateY(0);
  /* Keep the pressed state above WCAG-AA with the dark accent ink. */
  background: var(--accent);
  border-color: var(--accent);
}
.btn-ghost {
  color: var(--text);
  border: 1px solid var(--border-hi);
  background: rgba(238, 241, 247, 0.035);
  box-shadow: var(--lift);
}
.btn-ghost:hover {
  border-color: rgba(131, 168, 255, 0.45);
  background: rgba(238, 241, 247, 0.075);
  transform: translateY(-1px);
}
.btn-ghost:active { transform: translateY(0); }
.btn-sm { padding: 8px 16px; font-size: 0.9rem; border-radius: 9px; }

/* ============================================================
   Nav — sticky, transparent over the hero, condenses on scroll
   ============================================================ */

.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  transition: background-color 0.3s ease, border-color 0.3s ease,
              box-shadow 0.3s ease;
  border-bottom: 1px solid transparent;
}
.nav.scrolled {
  background: rgba(6, 7, 11, 0.82);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  backdrop-filter: blur(16px) saturate(150%);
  border-bottom-color: rgba(33, 39, 52, 0.9);
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.45);
}
.nav-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: 14px 20px;
  display: flex;
  align-items: center;
  gap: 18px;
  transition: padding 0.3s ease;
}
.nav.scrolled .nav-inner { padding-top: 8px; padding-bottom: 8px; }
.nav-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
  font-weight: 650;
  letter-spacing: 0.02em;
  flex: none;
}
.nav-brand:hover { text-decoration: none; }
.nav-brand .mark {
  display: block;
  width: 28px; height: 28px;
}
.nav-links {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
}
.nav-links a {
  color: var(--muted);
  font-size: 0.92rem;
  padding: 7px 11px;
  border-radius: 8px;
}
.nav-links a:hover {
  color: var(--text);
  background: rgba(231, 234, 241, 0.06);
  text-decoration: none;
}
.nav-ctas { display: flex; align-items: center; gap: 10px; margin-left: 6px; }
.nav-toggle {
  display: none;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 9px;
  color: var(--text);
  width: 40px; height: 40px;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex: none;
}
.nav-toggle svg { display: block; }
.nav-toggle .icon-close { display: none; }
.nav.menu-open .nav-toggle .icon-burger { display: none; }
.nav.menu-open .nav-toggle .icon-close { display: block; }

@media (max-width: 940px) {
  .nav-links {
    display: none;
    position: absolute;
    top: 100%;
    left: 0; right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 10px 14px 16px;
    background: rgba(6, 7, 11, 0.97);
    border-bottom: 1px solid var(--border);
  }
  .nav.menu-open { background: rgba(6, 7, 11, 0.97); }
  .nav.menu-open .nav-links { display: flex; }
  .nav-links a { padding: 12px 14px; font-size: 1rem; }
  .nav-toggle { display: inline-flex; }
  .nav-ctas { margin-left: auto; }
  .nav-ctas .btn-ghost { display: none; }
}
@media (max-width: 400px) {
  .nav-inner { padding-left: 14px; padding-right: 14px; gap: 10px; }
  .nav-ctas .btn-primary.btn-sm { padding: 8px 13px; font-size: 0.84rem; }
  .nav-brand .wordmark { display: none; }
}

/* ============================================================
   Section scaffolding
   ============================================================ */

.section { position: relative; padding: clamp(64px, 10vh, 120px) 20px; }
.section-app { background: var(--bg); }
/* hairline seam between full-width bands, brightest in the middle — a flat
   1px rule across 1400px reads as a table border, this reads as light */
.section-app::before,
.showcase::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 1px;
  background: linear-gradient(90deg, transparent,
              rgba(131, 168, 255, 0.22) 30%, rgba(155, 123, 255, 0.22) 70%,
              transparent);
}
.container { max-width: 1180px; margin: 0 auto; }
.container-narrow { max-width: 880px; margin: 0 auto; }

/* section eyebrow: an accent dot + a short rule, so the label sits on
   something instead of floating */
.kicker {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent-hi);
}
.kicker::before,
.kicker::after {
  content: "";
  width: 26px; height: 1px;
}
.kicker::before {
  background: linear-gradient(90deg, transparent, rgba(131, 168, 255, 0.7));
}
.kicker::after {
  background: linear-gradient(90deg, rgba(131, 168, 255, 0.7), transparent);
}
.section-head { text-align: center; max-width: 820px; margin: 0 auto; }
.section-head .kicker { justify-content: center; }
.section-head h2 {
  margin-top: 16px;
  font-size: clamp(1.9rem, 4.6vw, 2.8rem);
  font-weight: 750;
  letter-spacing: -0.03em;
  line-height: 1.08;
  text-wrap: balance;
  /* a soft top-down light on display type; the app does the same with its
     ExtraBold display role sitting under the window's top highlight */
  background: linear-gradient(180deg, #ffffff 8%, var(--text) 70%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.section-sub {
  margin: 14px auto 0;
  max-width: 58ch;
  color: var(--muted);
  font-size: clamp(0.95rem, 1.5vw, 1.06rem);
}

/* ============================================================
   HERO — copy above, the real product window below
   ============================================================ */

.hero {
  position: relative;
  isolation: isolate;
  background: var(--void);
  padding: clamp(120px, 16vh, 170px) 20px 0;
  overflow: hidden;
}
/* aurora: two offset colour fields in the product's own azure and violet,
   plus a horizon glow the Studio window appears to rise out of */
.hero::before {
  content: "";
  position: absolute;
  inset: -20% -10% auto;
  height: 130%;
  z-index: -2;
  background:
    radial-gradient(46% 38% at 22% 8%, rgba(91, 140, 255, 0.20), transparent 68%),
    radial-gradient(40% 34% at 80% 4%, rgba(155, 123, 255, 0.16), transparent 66%),
    radial-gradient(70% 42% at 50% 0%, rgba(91, 140, 255, 0.10), transparent 72%);
  filter: blur(6px);
  pointer-events: none;
}
/* a faint technical grid, faded out toward the edges — the scene the
   reconstruction is measured in, not decoration for its own sake */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(rgba(131, 168, 255, 0.055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(131, 168, 255, 0.055) 1px, transparent 1px);
  background-size: 64px 64px;
  -webkit-mask-image: radial-gradient(78% 58% at 50% 22%, #000 20%, transparent 78%);
  mask-image: radial-gradient(78% 58% at 50% 22%, #000 20%, transparent 78%);
  pointer-events: none;
}
.hero-inner {
  position: relative;
  max-width: 880px;
  margin: 0 auto;
  text-align: center;
}
.hero-kicker {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 18px;
  color: var(--accent-soft);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
}
.hero-kicker::before {
  content: "";
  width: 26px;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent));
}
.hero-kicker::after {
  content: "";
  width: 26px;
  height: 1px;
  background: linear-gradient(90deg, var(--accent), transparent);
}
.hero-title {
  font-size: clamp(2.9rem, 8vw, 5.4rem);
  line-height: 0.98;
  font-weight: 800;
  letter-spacing: -0.045em;
  text-wrap: balance;
  background: linear-gradient(176deg, #ffffff 4%, #e4eaf6 42%, #9fb0cc 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.hero-def {
  margin: 20px auto 0;
  max-width: 54ch;
  color: var(--muted);
  font-size: clamp(1.02rem, 1.7vw, 1.18rem);
  line-height: 1.62;
  text-wrap: pretty;
}
.hero-def strong { color: var(--text); font-weight: 600; }
.hero-ctas {
  margin-top: 32px;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
}
.hero-trust {
  margin-top: 18px;
  font-size: 0.86rem;
  color: var(--dim);
  letter-spacing: 0.01em;
}
.hero-shot {
  position: relative;
  max-width: 1080px;
  margin: clamp(44px, 7vh, 72px) auto 0;
  padding-bottom: clamp(56px, 9vh, 96px);
}
/* the glow the window casts onto the page */
.hero-shot::before {
  content: "";
  position: absolute;
  left: 8%; right: 8%;
  top: 4%;
  height: 60%;
  z-index: -1;
  background: radial-gradient(60% 50% at 50% 50%,
              rgba(91, 140, 255, 0.28), transparent 70%);
  filter: blur(48px);
  pointer-events: none;
}

/* entrance choreography — subtle */
.rise {
  opacity: 0;
  transform: translateY(16px);
  animation: rise 0.9s cubic-bezier(0.16, 0.68, 0.3, 1) forwards;
}
@keyframes rise {
  to { opacity: 1; transform: translateY(0); }
}
.d1 { animation-delay: 0.1s; }
.d2 { animation-delay: 0.22s; }
.d3 { animation-delay: 0.34s; }
.d4 { animation-delay: 0.46s; }
.d5 { animation-delay: 0.6s; }

/* ============================================================
   Trust strip
   ============================================================ */

.strip {
  position: relative;
  background: linear-gradient(180deg, var(--void-hi), var(--void));
  border-top: 1px solid rgba(33, 39, 52, 0.9);
  border-bottom: 1px solid rgba(33, 39, 52, 0.9);
  padding: 18px 20px;
  box-shadow: var(--lift);
}
.strip-list {
  list-style: none;
  max-width: 1180px;
  margin: 0 auto;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px 34px;
}
.strip-list li {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--muted);
  font-size: 0.9rem;
  white-space: nowrap;
}
.strip-list svg { color: var(--accent-hi); flex: none; }

/* ============================================================
   Features grid
   ============================================================ */

.features-grid {
  margin-top: clamp(36px, 6vh, 60px);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 16px;
}
/* ten cards over four columns leaves a ragged 4/4/2 last row; at the
   four-column breakpoint the final two widen to close it (and the two
   longest blurbs are the ones that get the extra measure) */
@media (min-width: 1100px) {
  .features-grid > .feature:nth-child(9),
  .features-grid > .feature:nth-child(10) { grid-column: span 2; }
}
.feature {
  position: relative;
  overflow: hidden;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 22px 20px;
  box-shadow: var(--lift);
  transition: border-color 0.25s ease, transform 0.25s ease,
              box-shadow 0.25s ease;
}
/* A light source that switches on behind the icon corner on hover.
   Deliberately a FIXED-SIZE SQUARE rather than percentage insets: with
   percentages the box takes the card's aspect ratio, so on the double-width
   cards it became short and wide and the circle got clipped by the box while
   still opaque — a hard horizontal edge instead of a glow. At a fixed 460px
   square the gradient reaches full transparency (70% of a 230px radius) well
   inside its own bounds, so it can never be cut, whatever the card's size. */
.feature::before {
  content: "";
  position: absolute;
  top: -180px;
  left: -180px;
  width: 460px;
  height: 460px;
  background: radial-gradient(circle,
              rgba(91, 140, 255, 0.26), transparent 70%);
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
}
.feature:hover {
  border-color: rgba(131, 168, 255, 0.4);
  transform: translateY(-3px);
  box-shadow: var(--lift), 0 18px 40px rgba(0, 0, 0, 0.45);
}
.feature:hover::before { opacity: 1; }
.feature > * { position: relative; }
.feature-ico {
  width: 40px; height: 40px;
  border-radius: 11px;
  display: grid;
  place-items: center;
  background: linear-gradient(150deg, rgba(91, 140, 255, 0.20),
                              rgba(155, 123, 255, 0.12));
  color: var(--accent-hi);
  box-shadow: 0 0 0 1px rgba(131, 168, 255, 0.24) inset, var(--lift);
  margin-bottom: 14px;
}
.feature-ico svg { display: block; }
.feature h3 {
  font-size: 1.02rem;
  font-weight: 650;
  letter-spacing: -0.01em;
}
.feature p { margin-top: 6px; color: var(--muted); font-size: 0.92rem; }

/* ============================================================
   How it works — 4 steps
   ============================================================ */

/* closing note for the pipeline tour — why there are five stages and not six */
.steps-note {
  max-width: 1080px;
  margin: clamp(30px, 4vh, 44px) auto 0;
  padding: 16px 20px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--panel);
  box-shadow: var(--lift);
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.6;
}
.steps-note strong { color: var(--text); font-weight: 600; }

/* ============================================================
   SHOWCASE — tabs + faithful Studio windows
   ============================================================ */

.showcase {
  position: relative;
  background: var(--void);
  padding: clamp(56px, 10vh, 120px) 16px clamp(72px, 10vh, 130px);
  overflow: hidden;
}

/* ---------- the pipeline rail ----------
   The tour's navigation IS the pipeline: numbered nodes joined by connectors
   that fill in behind you, the same shape as the app's widgets.StepBar. The
   auto-advance timer is the connector filling toward the next stage, so the
   progress indicator and the diagram are the same object. */
.sc-tabs {
  margin: clamp(30px, 5vh, 52px) auto 0;
  max-width: 1080px;
  display: flex;
  align-items: center;
  padding: 0 4px;
}
.sc-tab {
  display: flex;
  align-items: center;
  gap: 11px;
  flex: 1 1 0;
  min-width: 0;
  padding: 0;
  border: 0;
  background: transparent;
  font-family: var(--font);
  text-align: left;
  cursor: pointer;
}
.sc-tab:last-child { flex: 0 0 auto; }
.ts-node {
  position: relative;
  flex: none;
  width: 34px; height: 34px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--panel);
  box-shadow: 0 0 0 1px var(--border-hi) inset, var(--lift);
  color: var(--dim);
  font-size: 0.8rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  transition: background-color 0.3s ease, box-shadow 0.3s ease,
              color 0.3s ease, transform 0.3s ease;
}
.ts-node svg {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.ts-node .ts-ck { display: none; stroke-width: 3; }
.ts-label {
  flex: none;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--dim);
  white-space: nowrap;
  transition: color 0.3s ease;
}
.ts-line {
  position: relative;
  flex: 1 1 0;
  min-width: 12px;
  height: 2px;
  margin: 0 6px;
  border-radius: 1px;
  background: var(--border);
  overflow: hidden;
  transition: background-color 0.4s ease;
}
/* the auto-advance timer, drawn as the connector filling toward the next
   stage (JS sets its duration per panel and restarts it on every change) */
.sc-tab-bar {
  position: absolute;
  top: 0; bottom: 0;
  left: 0; right: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-hi));
  border-radius: 1px;
  opacity: 0;
}
html.js .sc-tab.is-active .sc-tab-bar {
  opacity: 1;
  animation: tab-fill 9s linear forwards;
}
@keyframes tab-fill { from { right: 100%; } to { right: 0%; } }
.sc-tabs.no-auto .sc-tab-bar { display: none; }
#how:hover .sc-tab-bar,
#how:focus-within .sc-tab-bar { animation-play-state: paused; }

.sc-tab:hover .ts-node { color: var(--text); box-shadow: 0 0 0 1px var(--accent-hi) inset, var(--lift); }
.sc-tab:hover .ts-label { color: var(--text); }
.sc-tab:focus-visible { outline: none; }
.sc-tab:focus-visible .ts-node { outline: 2px solid var(--accent-hi); outline-offset: 3px; }

.sc-tab.is-done .ts-node {
  background: rgba(52, 211, 153, 0.18);
  box-shadow: 0 0 0 1px var(--ok) inset;
  color: var(--ok);
}
.sc-tab.is-done .ts-node .ts-ck { display: block; }
.sc-tab.is-done .ts-node .ts-num,
.sc-tab.is-done .ts-node .ts-ico { display: none; }
.sc-tab.is-done .ts-label { color: var(--muted); }
.sc-tab.is-done .ts-line { background: var(--ok); }
.sc-tab.is-done .sc-tab-bar { display: none; }

.sc-tab.is-active .ts-node {
  background: rgba(91, 140, 255, 0.30);
  box-shadow: 0 0 0 1px var(--accent-hi) inset,
              0 0 0 5px rgba(91, 140, 255, 0.14);
  color: #fff;
  transform: scale(1.08);
}
.sc-tab.is-active .ts-label { color: var(--accent-hi); }
html.js .sc-tab.is-active .ts-node {
  animation: node-pop 0.5s cubic-bezier(0.34, 1.4, 0.64, 1) both;
}
@keyframes node-pop {
  0%   { transform: scale(0.88); }
  55%  { transform: scale(1.15); }
  100% { transform: scale(1.08); }
}

/* rail on narrow screens: scrolls sideways rather than wrapping into an
   unreadable stack of half-rows */
@media (max-width: 900px) {
  .sc-tabs {
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 4px;
  }
  .sc-tabs::-webkit-scrollbar { display: none; }
  .sc-tab { flex: 0 0 auto; gap: 8px; }
  .ts-line { flex: 0 0 26px; min-width: 26px; }
  .ts-label { font-size: 0.8rem; }
}
@media (max-width: 560px) {
  .ts-node { width: 28px; height: 28px; font-size: 0.72rem; }
  .ts-line { flex-basis: 18px; min-width: 18px; }
}

/* panels: no-JS shows all of them stacked; JS shows the active one */
.sc-panel { margin-top: clamp(26px, 4vh, 44px); }
html.js .sc-panel { display: none; }
html.js .sc-panel.is-active { display: block; }
html:not(.js) .sc-tabs { display: none; }

/* ---------- the stage copy, swapped with the window ----------
   One block per panel so the existing tab machinery moves it for free. The
   children stagger in on `.play`, which app.js re-adds on every change (and
   never adds under reduced motion, so the copy is simply always visible). */
.tour-copy {
  max-width: 1080px;
  margin: 24px auto 0;
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 18px 44px;
  align-items: start;
}
.tc-eyebrow {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-hi);
}
.tc-main h3 {
  margin-top: 7px;
  font-size: clamp(1.3rem, 2.4vw, 1.72rem);
  font-weight: 700;
  letter-spacing: -0.025em;
}
.tc-main h3 .tc-optional {
  margin-left: 10px;
  vertical-align: 3px;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--dim);
  border: 1px solid var(--border-hi);
  border-radius: 999px;
  padding: 3px 9px;
}
.tc-main p {
  margin-top: 11px;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.62;
}
/* a vertical hairline between the columns rather than a rule floating above
   the right one — the two columns start at different heights, so a top
   border there never lines up with anything on the left */
.tc-side {
  border-left: 1px solid var(--border);
  padding-left: 30px;
}
.tc-tech {
  font-family: var(--mono);
  font-size: 0.73rem;
  color: var(--dim);
  line-height: 1.7;
  overflow-wrap: break-word;
}
.tc-side .window-caption {
  margin: 12px 0 0;
  padding: 0;
  text-align: left;
}
@media (max-width: 820px) {
  .tour-copy { grid-template-columns: minmax(0, 1fr); gap: 18px; }
  .tc-side {
    border-left: 0;
    border-top: 1px dashed var(--border);
    padding-left: 0;
    padding-top: 14px;
  }
}

html.js .sc-panel.play .window-wrap { animation: tour-in 0.55s cubic-bezier(0.16, 0.68, 0.3, 1) both; }
html.js .sc-panel.play .tc-eyebrow  { animation: tour-up 0.5s cubic-bezier(0.16, 0.68, 0.3, 1) both 0.08s; }
html.js .sc-panel.play .tc-main h3  { animation: tour-up 0.5s cubic-bezier(0.16, 0.68, 0.3, 1) both 0.14s; }
html.js .sc-panel.play .tc-main p   { animation: tour-up 0.5s cubic-bezier(0.16, 0.68, 0.3, 1) both 0.20s; }
html.js .sc-panel.play .tc-side     { animation: tour-up 0.5s cubic-bezier(0.16, 0.68, 0.3, 1) both 0.26s; }
@keyframes tour-in {
  from { opacity: 0; transform: translateY(14px) scale(0.988); }
  to   { opacity: 1; transform: none; }
}
@keyframes tour-up {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

.window-wrap {
  position: relative;
  max-width: 1080px;
  margin: 0 auto;
}
.window-caption {
  margin: 16px auto 0;
  text-align: center;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.74rem;
  color: var(--dim);
  letter-spacing: 0.02em;
  padding: 0 10px;
}

/* ============================================================
   The Studio window — 1:1 after reconstrura/gui (theme.py QSS)
   ============================================================ */

.window {
  position: relative;
  border-radius: 12px;
  border: 1px solid var(--border-hi);
  background: var(--bg);
  overflow: hidden;
  box-shadow:
    var(--lift),
    0 0 0 1px rgba(0, 0, 0, 0.5),
    0 40px 110px rgba(0, 0, 0, 0.68),
    0 12px 34px rgba(0, 0, 0, 0.45);
  font-size: 13px;      /* the app's base font size (theme.TYPE.body) */
}

/* OS titlebar */
.titlebar {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 36px;
  padding: 0 6px 0 12px;
  background: var(--input);
  border-bottom: 1px solid var(--border);
}
.tb-mark { width: 16px; height: 16px; flex: none; }
.tb-title {
  color: var(--muted);
  font-size: 0.76rem;
  letter-spacing: 0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tb-controls {
  margin-left: auto;
  display: flex;
  align-items: center;
}
.tb-controls svg {
  width: 38px; height: 30px;
  padding: 8px 12px;
  fill: none;
  stroke: var(--muted);
  stroke-width: 1.6;
  stroke-linecap: round;
}

/* window body: nav rail | content — proportions of the real 1340×860
   StudioWindow (minus the 36px titlebar); content-taller pages still grow */
.app {
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr);
  aspect-ratio: 1340 / 824;
}

/* --- left nav rail (#NavRail, 224px in the app) --- */
.rail {
  background: var(--rail);
  border-right: 1px solid var(--border);
  padding: 17px 11px 11px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.rail-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 0 5px;
  margin-bottom: 18px;
  white-space: nowrap;
}
.rb-mark { width: 22px; height: 22px; flex: none; }
.rail-word { display: flex; flex-direction: column; min-width: 0; }
.rail-name {
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: -0.2px;
  line-height: 1.15;
}
/* widgets.section_label — all-caps, letterspaced, theme.FAINT */
.rail-sub, .rail-sec {
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fainter);
  white-space: nowrap;
}
.rail-sub { line-height: 1.4; }
.rail-sec { padding: 0 7px; margin: 18px 0 4px; }
.rail-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 10px;
  border-radius: 8px;
  color: var(--faint);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  min-width: 0;
}
.rail-item .ri {
  width: 15px; height: 15px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.rail-item.is-active {
  background: rgba(91, 140, 255, 0.13);
  color: #d3e1ff;
  font-weight: 600;
}
/* NavButton.paintEvent: a 3px accent rail on the selected item — what lets
   the eye find the current stage without reading a label */
.rail-item.is-active::before {
  content: "";
  position: absolute;
  left: 0;
  top: 27%;
  width: 3px;
  height: 46%;
  border-radius: 1.5px;
  background: var(--accent-hi);
}
.rail-item.is-disabled { color: var(--fainter); }
.rail-spacer { flex: 1; }
.rail-hr { height: 1px; background: var(--border); margin: 10px 2px; }

/* widgets.Meter — the rail's GPU readout. The bar answers "am I about to
   run out of VRAM?" before the numbers are read. */
.gpu-meter { padding: 0 3px; }
.gm-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 5px;
}
.gm-label {
  flex: 1;
  min-width: 0;
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gm-value {
  flex: none;
  font-size: 9.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.gm-bar {
  height: 4px;
  border-radius: 2px;
  background: #10141b;
  overflow: hidden;
}
.gm-fill { display: block; height: 100%; border-radius: 2px; background: var(--ok); }
.gm-fill.warn { background: var(--warn); }
.gm-fill.hi { background: var(--danger); }

/* --- content column --- */
.app-content {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 13px 16px 9px;
  min-width: 0;
}

/* wizard step bar (widgets.StepBar): numbered nodes joined by a connector
   that fills in behind you — done (green check), current (accent ring +
   halo), upcoming (hollow). Followed by the same hairline the app draws. */
.stepbar {
  display: flex;
  align-items: center;
  height: 34px;
  min-width: 0;
}
.sb-step {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
}
.sb-step:last-child { flex: 0 1 auto; }
.sb-node {
  position: relative;
  flex: none;
  width: 19px; height: 19px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--app-void);
  box-shadow: 0 0 0 1px var(--border-hi) inset;
  font-size: 9.5px;
  font-weight: 700;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.sb-node .sb-ck {
  width: 10px; height: 10px;
  fill: none; stroke: var(--ok); stroke-width: 3;
  stroke-linecap: round; stroke-linejoin: round;
}
.sb-label {
  flex: 0 1 auto;
  min-width: 0;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sb-line {
  flex: 1;
  min-width: 6px;
  height: 2px;
  margin: 0 6px;
  border-radius: 1px;
  background: var(--border);
}
.sb-step.is-done .sb-node {
  background: rgba(52, 211, 153, 0.18);
  box-shadow: 0 0 0 1px var(--ok) inset;
}
.sb-step.is-done .sb-label { color: var(--muted); }
.sb-step.is-done .sb-line { background: var(--ok); }
.sb-step.is-active .sb-node {
  background: rgba(91, 140, 255, 0.30);
  box-shadow:
    0 0 0 1px var(--accent-hi) inset,
    0 0 0 3px rgba(91, 140, 255, 0.16);
  color: #fff;
}
.sb-step.is-active .sb-label { color: var(--accent-hi); }
.stepbar-rule { height: 1px; background: var(--border); }

/* pages */
.page { flex: 1; min-height: 0; min-width: 0; }
.page-col { display: flex; flex-direction: column; gap: 11px; }
.page-split {
  display: grid;
  grid-template-columns: minmax(0, 31fr) minmax(0, 69fr);
  gap: 12px;
}
.split-left, .split-right {
  display: flex;
  flex-direction: column;
  gap: 11px;
  min-width: 0;
}

/* widgets.PageHeader — accent eyebrow, big title, supporting line */
.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 0 2px;
}
.ph-eyebrow {
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--accent-hi);
}
.ph-title {
  margin-top: 3px;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.4px;
  line-height: 1.15;
}
.ph-sub {
  margin-top: 4px;
  color: var(--faint);
  font-size: 11px;
  line-height: 1.5;
  max-width: 64ch;
}
.page-head > .qbtn { flex: none; }

/* cards (QFrame#Card) — depth from the surface ramp plus a hairline and a
   1px top highlight, never from a heavy shadow */
.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 13px 15px 14px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 9px;
  min-width: 0;
  box-shadow: var(--lift);
}
.card-fill { height: 100%; }
/* widgets.title_label(role="cardtitle") — uppercased, letterspaced micro
   header in theme.TEXT_DIM */
.card-title {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
}
.card-hr { height: 1px; background: var(--border); }
/* the hint line under a control (e.g. the iterations recommendation) */
.hint { color: var(--fainter); font-size: 10px; line-height: 1.5; }

/* buttons inside the app (QPushButton) */
.qbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  background: var(--panel-hi);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 12px;
  font-size: 11.5px;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  box-shadow: var(--lift);
}
.qbtn .qi {
  width: 14px; height: 14px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
/* QPushButton[primary="true"] — the diagonal azure sweep */
.qbtn-primary {
  background: var(--grad-primary);
  border: 1px solid rgba(131, 168, 255, 0.55);
  color: #fff;
  font-weight: 600;
  padding: 7px 15px;
}
.qbtn-primary.is-disabled {
  background: var(--accent-dim);
  border-color: transparent;
  color: #8fa3c6;
}
.qbtn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--faint);
  box-shadow: none;
}
.qbtn-sm { padding: 4px 10px; font-size: 11px; }
.qbtn.is-checked {
  background: rgba(91, 140, 255, 0.16);
  border-color: rgba(91, 140, 255, 0.42);
  color: #d3e1ff;
}

/* widgets.SegmentedControl — one setting with N values, rendered as one
   control: a pill track with a sliding selection */
.seg {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex: none;
  padding: 3px;
  background: var(--app-void);
  border: 1px solid var(--border);
  border-radius: 999px;
}
.seg-item {
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--faint);
  white-space: nowrap;
}
.seg-item.is-on {
  background: rgba(91, 140, 255, 0.20);
  box-shadow: 0 0 0 1px rgba(131, 168, 255, 0.35) inset;
  color: #d9e5ff;
}

/* widgets.Toggle / ToggleRow — a switch, for settings that change how the
   product behaves rather than options inside a form */
.tg-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
.tg-text { flex: 1; min-width: 0; font-size: 11.5px; color: var(--text); }
.tg-desc {
  display: block;
  margin-top: 2px;
  font-size: 10px;
  color: var(--faint);
  line-height: 1.45;
}
.toggle {
  position: relative;
  flex: none;
  width: 32px; height: 18px;
  border-radius: 999px;
  background: #12161e;
  border: 1px solid var(--border-hi);
}
.toggle i {
  position: absolute;
  top: 2px; left: 2px;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: #fff;
}
.toggle.on { background: var(--accent); border-color: var(--accent-hi); }
.toggle.on i { left: auto; right: 2px; }

/* widgets.MetricGrid / StatTile — the numbers a run is judged by, as a
   scannable table rather than a sentence that reflows as digits change */
.metrics {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 11px 20px;
}
.tile-v {
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.4px;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
  white-space: nowrap;
}
/* StatTile._fit_value: a compound reading ("18,400 / 40,000") steps down a
   size so it still fits a two-column tile grid */
.tile-v.sm { font-size: 13.5px; }
.tile-v.ok { color: var(--ok); }
.tile-v.warn { color: var(--warn); }
.tile-v.pending { color: var(--fainter); }
.tile-c {
  margin-top: 1px;
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--faint);
}

/* a short vertical hairline separating groups inside a toolbar (_vrule) */
.vrule { width: 1px; height: 16px; background: var(--border); flex: none; }

/* viewer toolbar. Deliberately nowrap: the real app has a wider right pane,
   and a toolbar that wraps to two lines here would steal height from the
   viewport and re-frame the 3D scene. */
.viewbar {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: nowrap;
  min-width: 0;
}
.gbtn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: none;
  padding: 4px 8px;
  border-radius: 7px;
  color: var(--faint);
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
}
.gbtn .qi {
  width: 13px; height: 13px;
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round;
}
.viewbar .check { flex: none; }
.mini-label { flex: none; color: var(--faint); font-size: 10.5px; white-space: nowrap; }
.mini-slider {
  position: relative;
  width: 58px; height: 13px;
  flex: none;
}
.mini-slider .ms-fill {
  position: absolute;
  top: 50%; left: 0;
  width: 30%; height: 4px;
  transform: translateY(-50%);
  border-radius: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-hi));
}
.mini-slider::before {
  content: "";
  position: absolute;
  top: 50%; left: 0; right: 0;
  height: 4px;
  transform: translateY(-50%);
  border-radius: 2px;
  background: var(--border);
}
.mini-slider .ms-fill { z-index: 1; }
.mini-slider .ms-knob {
  position: absolute;
  top: 50%; left: 30%;
  width: 11px; height: 11px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: #f4f6fa;
  z-index: 2;
}
.vb-spacer { flex: 1; }

/* form rows / combos / spins (QComboBox, QSpinBox) */
.form-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.form-label { color: var(--faint); font-size: 11.5px; flex: none; }
.form-muted { color: var(--faint); font-size: 10.5px; line-height: 1.5; }
.combo {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-width: 124px;
  background: var(--app-void);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 5px 8px 5px 10px;
  font-size: 11.5px;
  color: var(--text);
}
.combo.grow { width: 100%; }
.combo .ci, .spin .sp-ch {
  width: 11px; height: 11px; flex: none;
  fill: none; stroke: var(--faint); stroke-width: 2.4; stroke-linecap: round;
  transform: rotate(90deg);
}
.spin {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  min-width: 68px;
  flex: none;
  background: var(--app-void);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px 7px 4px 9px;
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* checkboxes (QCheckBox) */
.check {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 11.5px;
  color: var(--text);
  white-space: nowrap;
  min-width: 0;
}
.check .box {
  width: 14px; height: 14px; flex: none;
  border-radius: 5px;
  border: 1px solid var(--border-hi);
  background: var(--app-void);
  display: grid;
  place-items: center;
}
.check.on .box {
  background: linear-gradient(150deg, var(--accent-hi), var(--accent));
  border-color: rgba(131, 168, 255, 0.6);
}
.check .ck {
  width: 10px; height: 10px;
  fill: none; stroke: #fff; stroke-width: 3.2;
  stroke-linecap: round; stroke-linejoin: round;
}
.check.sm { font-size: 11px; }
.check .dimtext { color: var(--fainter); overflow: hidden; text-overflow: ellipsis; }
/* checkbox labels carrying a parenthetical explanation wrap instead of
   clipping — the side panel is too narrow to hold them on one line */
.check.wrap { white-space: normal; align-items: flex-start; line-height: 1.45; }
.check.wrap .box { margin-top: 1px; }

/* collapsible header (widgets.Collapsible) */
.collapsible {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--faint);
  font-size: 11.5px;
  font-weight: 600;
  padding: 1px 2px;
}
.collapsible .ch {
  width: 11px; height: 11px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round;
}

/* slider + spin row (widgets.SliderSpin) */
.sliderspin {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.ss-label { color: var(--faint); font-size: 11px; flex: none; width: 128px; }
/* SliderSpin._STACK_BELOW = 400px: the studio's side panels are 372px, so
   every slider row there puts its label on its own line rather than
   squeezing the slider down to an undraggable stub */
.split-left .sliderspin { flex-wrap: wrap; row-gap: 4px; }
.split-left .ss-label { width: 100%; }
.hslider { position: relative; height: 15px; width: 90px; flex: none; }
.hslider.grow { flex: 1; width: auto; min-width: 40px; }
.hs-groove {
  position: absolute;
  top: 50%; left: 0; right: 0;
  height: 4px;
  transform: translateY(-50%);
  border-radius: 2px;
  background: var(--border);
  overflow: hidden;
}
.hs-fill {
  display: block;
  height: 100%;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-hi));
}
.hs-knob {
  position: absolute;
  top: 50%;
  width: 13px; height: 13px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: #f4f6fa;
}

/* file picker (widgets.FilePicker) */
.picker { display: flex; align-items: center; gap: 8px; min-width: 0; }
.pk-field {
  flex: 1;
  min-width: 0;
  background: var(--app-void);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 10px;
  font-size: 11.5px;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pk-field.placeholder { color: var(--fainter); }

/* status line (widgets.StatusLabel) */
.statusline {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  color: var(--faint);
  font-size: 11px;
  line-height: 1.55;
  min-width: 0;
}
.statusline .sl-ico {
  width: 15px; height: 15px; flex: none;
  margin-top: 1px;
  fill: none; stroke: currentColor; stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round;
}
.statusline .sl-ico.ok { color: var(--ok); }
.statusline .sl-ico.accent { color: var(--accent); }

/* widgets.EmptyState — says what will appear here and what produces it,
   instead of leaving the pane looking unfinished */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  padding: 20px;
  text-align: center;
}
.es-halo {
  width: 44px; height: 44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: #0e1219;
  box-shadow: 0 0 0 1px var(--border) inset;
  color: var(--faint);
}
.es-halo svg {
  width: 20px; height: 20px;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.es-title { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.es-hint {
  max-width: 34ch;
  font-size: 10.5px;
  line-height: 1.5;
  color: var(--faint);
}

/* run log (QPlainTextEdit — JetBrains Mono, theme.TEXT_DIM) */
.runlog {
  background: var(--app-void);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 9px 12px;
  font-family: var(--mono);
  font-size: 9.5px;
  line-height: 1.8;
  color: var(--muted);
  min-height: 62px;
  overflow: hidden;
}
.runlog > div { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* the app gives the Reconstruct run log all leftover column height */
.split-left .runlog { flex: 1; }
.runlog .lg { color: var(--accent-hi); }
.runlog .ok .lg { color: var(--ok); }

/* 3D viewport (PointCloudViewer / SplatView — theme.INPUT background);
   flex: 1 so it fills the column height like the app's stretching viewer */
.viewport {
  position: relative;
  flex: 1;
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  background: var(--app-void);
  aspect-ratio: 16 / 10;
  min-height: 230px;
}
.viewport canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.static-fallback {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.55;
}
html.js .static-fallback { display: none; }
.vp-train canvas { cursor: grab; touch-action: pan-y; }
.vp-train canvas.dragging { cursor: grabbing; }
.vp-hint {
  position: absolute;
  top: 10px; right: 10px;
  font-size: 0.64rem;
  color: var(--muted);
  background: rgba(8, 10, 14, 0.82);
  border: 1px solid rgba(231, 234, 241, 0.08);
  border-radius: 999px;
  padding: 3px 9px;
}

/* post-training buttons: dim until the run finishes */
.post-row { margin-top: 2px; }
html.js .mock-live .post-btn { opacity: 0.45; transition: opacity 0.4s ease; }
html.js .mock-live.is-done .post-btn { opacity: 1; }

/* app status bar (#StatusBar) — pulse dot, status, progress, %, cancel */
.app-statusbar {
  display: flex;
  align-items: center;
  gap: 11px;
  border-top: 1px solid var(--border);
  padding: 9px 2px 0;
  min-height: 30px;
}
/* _PulseDot: idle vs working should be legible without reading the line */
.asb-dot {
  flex: none;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--fainter);
}
.asb-dot.live {
  background: var(--accent);
  box-shadow: 0 0 0 3px rgba(91, 140, 255, 0.16);
}
html.js .mock-live .asb-dot.live { animation: asb-pulse 1.8s ease-in-out infinite; }
@keyframes asb-pulse {
  0%, 100% { box-shadow: 0 0 0 2px rgba(91, 140, 255, 0.10); }
  50%      { box-shadow: 0 0 0 5px rgba(91, 140, 255, 0.22); }
}
.mock-live.is-done .asb-dot {
  background: var(--fainter);
  box-shadow: none;
  animation: none;
}
.asb-text {
  flex: 1;
  min-width: 0;
  color: var(--faint);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.asb-progress {
  width: 240px;
  height: 7px;
  flex: none;
  background: var(--app-void);
  border: 1px solid var(--border);
  border-radius: 4px;
  overflow: hidden;
}
/* QProgressBar::chunk — the azure→violet sweep */
.asb-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--grad-sweep);
  border-radius: 3px;
  transition: width 0.25s linear;
}
.asb-pct {
  flex: none;
  width: 32px;
  text-align: right;
  color: var(--muted);
  font-size: 10px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.asb-cancel {
  flex: none;
  color: var(--faint);
  font-size: 11px;
  padding: 3px 10px;
  border-radius: 7px;
}
.mock-live.is-done .asb-progress,
.mock-live.is-done .asb-pct,
.mock-live.is-done .asb-cancel { display: none; }

/* ---------- Welcome page ---------- */
.page-welcome {
  position: relative;
  min-height: 420px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--input);
}
.welcome-cloud {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* QFrame#HeroCard — deliberately translucent over the live point cloud, and
   deliberately a vertical RAMP: most see-through at the edges where the cloud
   is, firming up through the middle where the copy sits. A flat alpha low
   enough to show the cloud makes the subtitle unreadable over a bright patch. */
.hero-card {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: min(500px, 90%);
  background: linear-gradient(180deg,
              rgba(11, 13, 19, 0.54) 0%,
              rgba(11, 13, 19, 0.76) 42%,
              rgba(11, 13, 19, 0.70) 78%,
              rgba(11, 13, 19, 0.52) 100%);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  border: 1px solid rgba(255, 255, 255, 0.11);
  border-radius: 20px;
  padding: 30px 36px 26px;
  text-align: center;
}
.hc-mark { width: 42px; height: 42px; margin: 0 auto 10px; display: block; }
.hc-title {
  font-size: 1.75rem;
  font-weight: 800;
  letter-spacing: -1px;
  line-height: 1.05;
}
.hc-sub {
  margin-top: 5px;
  color: var(--muted);
  font-size: 11.5px;
}
/* the five stages as a quiet legend: sets expectations before the first
   click without turning the hero into documentation */
.hc-stages {
  margin-top: 13px;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 5px;
  flex-wrap: wrap;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--faint);
}
.hc-stages i { font-style: normal; opacity: 0.55; }
.hc-btns {
  margin: 20px 0 0;
  display: flex;
  justify-content: center;
  gap: 10px;
}
.hc-hr { margin-top: 20px; height: 1px; background: rgba(255, 255, 255, 0.09); }
.hc-recents-title {
  margin-top: 13px;
  text-align: left;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
}
.hc-recent {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 6px;
  border-radius: 8px;
  color: var(--faint);
  font-size: 11.5px;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
}
.hc-recent .hr-dot {
  width: 12px; height: 12px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2;
}
.hc-recent .hr-dot.ok { color: var(--ok); }
.hr-sep { color: #5a6170; padding: 0 4px; }
html.js .play .w-anim { animation: w-rise 0.7s cubic-bezier(0.16, 0.68, 0.3, 1) both; }
@keyframes w-rise {
  from { opacity: 0; transform: translate(-50%, calc(-50% + 14px)); }
  to   { opacity: 1; transform: translate(-50%, -50%); }
}

/* ---------- Extraction page ---------- */
.scrub-frame {
  position: relative;
  border: 1px solid var(--border);
  border-radius: 9px;
  overflow: hidden;
  background: var(--input);
  aspect-ratio: 16 / 6.4;
  min-height: 120px;
}
.scrub-frame svg { position: absolute; inset: 0; width: 100%; height: 100%; }
/* real capture frame: blurred cover backdrop + contained portrait image
   (shared by the Extraction scrub preview and the Masking overlay pane) */
.scrub-frame .sf-back,
.mask-preview .sf-back {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; filter: blur(22px) brightness(0.45); transform: scale(1.15);
}
.scrub-frame .sf-main,
.mask-preview .sf-main {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain;
}

/* WebGL viewer (viewer.js) overlays a 2D-canvas viewport; once live, the
   canvas fallback underneath is hidden */
.rsv-canvas {
  position: absolute; inset: 0; width: 100%; height: 100%;
  touch-action: pan-y;
}
.viewport.gl-live > canvas:not(.rsv-canvas),
.viewport.gl-live > .static-fallback { opacity: 0; }

/* Welcome background: the real rhododendron cloud, oversized and shifted
   so the subject orbits beside the floating card instead of behind it */
.welcome-gl {
  position: absolute; left: -5%; top: -18%;
  width: 152%; height: 136%;
  opacity: 0.62;
  pointer-events: none;
}
.page-welcome.gl-live > .welcome-cloud { opacity: 0; }
.scrub-time {
  position: absolute;
  bottom: 8px; right: 10px;
  font-family: var(--mono);
  font-size: 0.62rem;
  color: var(--text);
  background: rgba(8, 10, 14, 0.85);
  border-radius: 999px;
  padding: 2px 9px;
}
.marker-strip {
  position: relative;
  height: 8px;
  margin: 0 2px;
}
.marker-strip i {
  position: absolute;
  bottom: 0;
  width: 2px; height: 8px;
  border-radius: 1px;
  background: var(--accent);
  opacity: 0.9;
}
.thumbstrip {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 8px;
}
.thumbstrip img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 7px;
  border: 1px solid var(--border);
}
.thumbstrip i {
  aspect-ratio: 4 / 3;
  border-radius: 7px;
  border: 1px solid var(--border);
  background:
    radial-gradient(90% 80% at 30% 20%, rgba(107, 163, 255, 0.12), transparent 60%),
    linear-gradient(160deg, #232837, #171a22);
}
.thumbstrip i:nth-child(2n) {
  background:
    radial-gradient(90% 80% at 70% 30%, rgba(107, 163, 255, 0.08), transparent 60%),
    linear-gradient(200deg, #202531, #151820);
}
.thumbstrip i:nth-child(3n) {
  background:
    radial-gradient(80% 90% at 50% 70%, rgba(62, 207, 142, 0.06), transparent 65%),
    linear-gradient(180deg, #222734, #161922);
}

/* ---------- Masking page ---------- */
.seg-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.seg-row.grow-first > :first-child { flex: 1; }

/* the Pick / Box / Lasso subject tools, grouped in one inset frame
   (studio.py #ToolGroup) */
.toolgroup {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 3px;
  background: var(--app-void);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.toolgroup .qbtn {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  color: var(--faint);
  padding: 3px 9px;
  font-size: 11px;
}
.toolgroup .qbtn.is-checked {
  background: rgba(91, 140, 255, 0.16);
  color: #d3e1ff;
}

/* widgets.InstanceList — everything masking found, each row independently
   toggleable. Toggling never re-runs a model: the per-instance masks are
   already on disk, so a change only recombines them. */
.instlist { display: flex; flex-direction: column; gap: 6px; }
.inst {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(8, 10, 14, 0.55);
  min-width: 0;
}
.inst-thumb {
  flex: none;
  width: 38px; height: 38px;
  border-radius: 7px;
  background: var(--app-void);
  display: grid;
  place-items: center;
  color: var(--fainter);
  overflow: hidden;
}
.inst-thumb svg {
  width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.inst-thumb img { width: 100%; height: 100%; object-fit: cover; }
.inst-text { flex: 1; min-width: 0; }
.inst-name {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.inst-meta {
  margin-top: 1px;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* "acting on it" is the accented state, whichever verb that is: for a person
   that means Remove; for an isolated subject it means Keep */
.inst-act {
  flex: none;
  min-width: 58px;
  text-align: center;
  padding: 5px 10px;
  border-radius: 8px;
  font-size: 10.5px;
  font-weight: 600;
  border: 1px solid var(--border-hi);
  color: var(--faint);
}
.inst-act.on {
  background: var(--accent);
  border-color: var(--accent-hi);
  color: #fff;
}
.mask-preview {
  position: relative;
  flex: 1;
  border: 1px solid var(--border);
  border-radius: 9px;
  overflow: hidden;
  background: var(--input);
  aspect-ratio: 16 / 9.5;
  min-height: 220px;
}
.mask-preview svg { position: absolute; inset: 0; width: 100%; height: 100%; }
/* overlay tint breathes gently so the masked regions read as an overlay */
html.js .play .mk-tint { animation: mk-breathe 4.5s ease-in-out infinite; }
@keyframes mk-breathe {
  0%, 100% { opacity: 0.5; }
  50%      { opacity: 0.3; }
}

/* ---------- window scale-to-fit ----------
   The Studio windows keep their full desktop layout and the app's real
   aspect ratio at EVERY viewport. Below their 1080px design width they
   are scaled down as one unit, like a screenshot: JS (initWindowFit)
   wraps each .window in a .win-fit, pins the window to the design width
   and applies transform: scale(); the wrapper height is kept in sync.
   Without JS, narrow screens pan the full-size window instead. */
html.js .win-fit > .window { transform-origin: top left; }
html:not(.js) .window-wrap,
html:not(.js) .hero-shot { overflow-x: auto; }
html:not(.js) .window { min-width: 880px; }
@media (max-width: 400px) {
  .btn { padding: 12px 20px; font-size: 0.96rem; width: 100%; }
  .hero-ctas { flex-direction: column; }
  .nav .btn { width: auto; }
  .sc-tab { padding: 8px 11px 10px; font-size: 0.8rem; }
  .showcase { padding-left: 10px; padding-right: 10px; }
}

/* ============================================================
   Pricing
   ============================================================ */

.pricing-wrap {
  margin-top: clamp(36px, 6vh, 56px);
  display: flex;
  justify-content: center;
}
/* A real gradient rim: the azure→violet sweep is the product's signature and
   this is the page's one hero object. Done with two backgrounds rather than a
   z-index:-1 pseudo-element — inside a stacking context the element's own
   background paints BEFORE negative-z children, so a pseudo-element rim would
   cover the panel fill instead of sitting behind it. */
.price-card {
  position: relative;
  max-width: 460px;
  width: 100%;
  border: 1px solid transparent;
  border-radius: 20px;
  background:
    linear-gradient(var(--panel), var(--panel)) padding-box,
    linear-gradient(155deg, rgba(131, 168, 255, 0.8),
                    rgba(155, 123, 255, 0.5) 45%,
                    rgba(33, 39, 52, 0.9) 85%) border-box;
  padding: 36px 32px 30px;
  text-align: center;
  box-shadow:
    var(--lift),
    0 30px 90px rgba(0, 0, 0, 0.55),
    0 0 90px rgba(91, 140, 255, 0.16);
}
.price-badge {
  display: inline-block;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-hi);
  border: 1px solid rgba(131, 168, 255, 0.4);
  border-radius: 999px;
  padding: 5px 14px;
  background: rgba(91, 140, 255, 0.10);
}
.price-num {
  margin-top: 18px;
  font-size: clamp(3rem, 8vw, 4.2rem);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1;
}
.price-terms { margin-top: 8px; color: var(--muted); font-size: 0.9rem; }
.price-list {
  list-style: none;
  margin: 24px auto 0;
  max-width: 320px;
  text-align: left;
}
.price-list li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 0;
  font-size: 0.94rem;
  color: var(--text);
}
.price-list svg { flex: none; color: var(--ok); margin-top: 3px; }
.price-cta { margin-top: 26px; display: flex; flex-direction: column; gap: 10px; }
.price-fine {
  margin-top: 18px;
  font-size: 0.76rem;
  color: var(--dim);
  line-height: 1.6;
}
.price-fine a { color: var(--muted); text-decoration: underline; }

/* ============================================================
   Download
   ============================================================ */

.dl-grid {
  margin-top: clamp(36px, 6vh, 56px);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 16px;
}
.dl-card {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 24px 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  box-shadow: var(--lift);
  transition: border-color 0.25s ease, transform 0.25s ease,
              box-shadow 0.25s ease;
}
.dl-card.is-recommended {
  border-color: rgba(131, 168, 255, 0.5);
  box-shadow: var(--lift), 0 0 30px rgba(91, 140, 255, 0.08);
}
.dl-card:hover {
  border-color: rgba(131, 168, 255, 0.4);
  transform: translateY(-3px);
  box-shadow: var(--lift), 0 18px 40px rgba(0, 0, 0, 0.45);
}
.dl-ico {
  width: 42px; height: 42px;
  border-radius: 11px;
  display: grid;
  place-items: center;
  background: linear-gradient(150deg, rgba(91, 140, 255, 0.20),
                              rgba(155, 123, 255, 0.12));
  color: var(--accent-hi);
  box-shadow: 0 0 0 1px rgba(131, 168, 255, 0.24) inset, var(--lift);
  margin-bottom: 10px;
}
.dl-recommended {
  position: absolute;
  top: 18px;
  right: 16px;
  color: var(--accent-hi);
  border: 1px solid rgba(131, 168, 255, 0.36);
  border-radius: 999px;
  background: rgba(91, 140, 255, 0.1);
  padding: 4px 8px;
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 1;
  text-transform: uppercase;
}
.dl-card h3 { font-size: 1.02rem; font-weight: 650; }
.dl-card p { color: var(--muted); font-size: 0.86rem; flex: 1; }
.dl-card .btn { margin-top: 16px; width: 100%; padding: 11px 18px; font-size: 0.94rem; }
/* Secondary link above a card's button. Reset the flex:1 used by descriptions
   so the primary buttons keep a shared baseline. */
.dl-card .dl-alt {
  flex: 0 0 auto;
  margin-top: 10px;
  text-align: center;
  font-size: 0.78rem;
}
.dl-note {
  margin-top: 22px;
  text-align: center;
  font-family: var(--mono);
  font-size: 0.76rem;
  color: var(--dim);
}
.dl-note code {
  font-family: var(--mono);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 1px 7px;
}
.dl-note .dl-url { overflow-wrap: anywhere; }

.sysreq {
  margin: clamp(40px, 6vh, 60px) auto 0;
  max-width: 880px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 24px 26px;
  box-shadow: var(--lift);
}
.sysreq h3 {
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.sysreq-grid {
  margin-top: 14px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px 24px;
}
.sysreq-item .k { font-size: 0.78rem; color: var(--dim); }
.sysreq-item .v {
  margin-top: 2px;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.88rem;
  color: var(--text);
}

/* ============================================================
   FAQ
   ============================================================ */

.faq-list { margin-top: clamp(32px, 5vh, 48px); }
.faq-item {
  border: 1px solid var(--border);
  border-radius: 13px;
  background: var(--panel);
  margin-bottom: 10px;
  overflow: hidden;
  box-shadow: var(--lift);
  transition: border-color 0.25s ease;
}
.faq-item[open] { border-color: rgba(131, 168, 255, 0.3); }
.faq-item summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 20px;
  font-weight: 600;
  font-size: 0.98rem;
  color: var(--text);
}
.faq-item summary::-webkit-details-marker { display: none; }
/* .faq-item clips overflow for its border-radius, which would swallow the
   default outside focus ring — draw the ring inset so it stays visible. */
.faq-item summary:focus-visible { outline-offset: -3px; }
.faq-item summary:hover { background: rgba(231, 234, 241, 0.03); }
.faq-caret {
  margin-left: auto;
  flex: none;
  color: var(--muted);
  transition: transform 0.25s ease;
}
.faq-item[open] .faq-caret { transform: rotate(180deg); }
.faq-body {
  padding: 0 20px 18px;
  color: var(--muted);
  font-size: 0.93rem;
  line-height: 1.65;
  max-width: 72ch;
}
/* Links embedded in prose must not rely on hue alone (WCAG 1.4.1):
   underline them. Nav/footer/button links are exempt (not inside text). */
.faq-body a, .legal-main a, .steps a { text-decoration: underline; }
.faq-body a { color: var(--accent-hi); }
.faq-body code {
  font-family: var(--mono);
  font-size: 0.84em;
  background: var(--panel-hi);
  border-radius: 5px;
  padding: 1px 6px;
}

/* ============================================================
   Footer
   ============================================================ */

.footer {
  background: var(--void);
  border-top: 1px solid rgba(33, 39, 52, 0.85);
  padding: clamp(44px, 7vh, 70px) 20px 34px;
}
.footer-inner { max-width: 1180px; margin: 0 auto; }
.footer-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 30px;
  flex-wrap: wrap;
}
.footer-brand { display: flex; align-items: center; gap: 11px; color: var(--text); font-weight: 650; }
.footer-brand .mark { width: 34px; height: 34px; }
.footer-tag { margin-top: 10px; color: var(--dim); font-size: 0.86rem; }
.footer-cols { display: flex; gap: clamp(30px, 6vw, 80px); flex-wrap: wrap; }
.footer-col h4 {
  font-size: 0.7rem;
  font-weight: 650;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 12px;
}
.footer-col a {
  display: block;
  color: var(--muted);
  font-size: 0.9rem;
  padding: 4px 0;
}
.footer-col a:hover { color: var(--text); }
.footer-bottom {
  margin-top: 40px;
  padding-top: 20px;
  border-top: 1px solid rgba(33, 39, 52, 0.8);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  color: var(--dim);
  font-size: 0.8rem;
}
.footer-bottom-plain {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
.nav-ctas-end { margin-left: auto; }
.svg-defs { position: absolute; }

/* Static mockup geometry lives in the stylesheet so production can enforce a
   nonce-free CSP without allowing style attributes. */
.width-0 { width: 0; }
.width-8 { width: 8%; }
.width-9 { width: 9%; }
.width-10 { width: 10%; }
.width-12 { width: 12%; }
.width-20 { width: 20%; }
.width-25 { width: 25%; }
.width-26 { width: 26%; }
.width-39 { width: 39%; }
.width-72 { width: 72%; }
.width-100 { width: 100%; }
.left-0 { left: 0; }
.left-4 { left: 4%; }
.left-9 { left: 9%; }
.left-10 { left: 10%; }
.left-13 { left: 13%; }
.left-19 { left: 19%; }
.left-20 { left: 20%; }
.left-24 { left: 24%; }
.left-25 { left: 25%; }
.left-26 { left: 26%; }
.left-28 { left: 28%; }
.left-35 { left: 35%; }
.left-39 { left: 39%; }
.left-41 { left: 41%; }
.left-45 { left: 45%; }
.left-52 { left: 52%; }
.left-57 { left: 57%; }
.left-61 { left: 61%; }
.left-68 { left: 68%; }
.left-72 { left: 72%; }
.left-73 { left: 73%; }
.left-79 { left: 79%; }
.left-85 { left: 85%; }
.left-90 { left: 90%; }
.left-96 { left: 96%; }

/* Purchase completion. */
.success-wrap { max-width: 44rem; margin: 0 auto; padding: 5rem 1.25rem 4rem; }
.success-top { display: flex; justify-content: center; padding: 1.75rem 0; }
.success-top a {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--text);
  text-decoration: none;
  font-weight: 600;
}
.success-top img { width: 2rem; height: 2rem; }
.success-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 2.5rem 2rem;
  text-align: center;
}
.success-badge {
  width: 4rem;
  height: 4rem;
  margin: 0 auto 1.25rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, var(--accent), var(--accent-hi));
  color: #0b1220;
}
.success-badge svg { width: 2rem; height: 2rem; }
.success-card h1 { font-size: 1.9rem; margin: 0 0 0.5rem; }
.success-card p.lead { color: var(--muted); margin: 0 auto 1.5rem; max-width: 32rem; }
.success-context-warning {
  max-width: 30rem;
  box-sizing: border-box;
  margin: 0 auto 1.5rem;
  padding: 0.8rem 0.9rem;
  border: 1px solid rgba(255, 196, 92, 0.42);
  border-radius: 10px;
  background: rgba(255, 196, 92, 0.08);
  color: #ffe0a3;
  text-align: left;
  font-size: 0.86rem;
  line-height: 1.5;
}
.success-context-warning strong { color: #fff0ca; }
.activate { margin: 1.75rem auto 0; max-width: 30rem; text-align: left; }
.activate label { display: block; font-size: 0.85rem; color: var(--muted); margin-bottom: 0.4rem; }
.activate-row { display: flex; gap: 0.6rem; flex-wrap: wrap; }
.activate input {
  flex: 1 1 100%;
  min-width: 0;
  padding: 0.8rem 0.9rem;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: #0b0c10;
  color: var(--text);
  font: inherit;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.activate input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.activate-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; margin-top: 0.65rem; }
.activate-actions .btn { flex: 1 1 10rem; }
.activate .hint { font-size: 0.82rem; color: var(--muted); margin: 0.7rem 0 0; line-height: 1.5; }
.activate .hint.is-error { color: #ffaaa5; }
.activate .hint.is-ready { color: #9de2bd; }
.btn[disabled] { opacity: 0.48; cursor: not-allowed; transform: none; }
.steps { margin: 2rem auto 0; max-width: 32rem; text-align: left; color: var(--muted); font-size: 0.95rem; line-height: 1.7; }
.steps b { color: var(--text); }
.order-ref { margin-top: 2rem; font-size: 0.78rem; color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.success-legal { margin-top: 1.2rem; font-size: 0.82rem; color: var(--muted); }
.success-legal a { margin: 0 0.25rem; }

/* Refund request flow. */
.withdraw-main { max-width: 42rem; margin: 0 auto; padding: 8rem 1.25rem 5rem; }
.withdraw-card { background: var(--panel); border: 1px solid var(--border); border-radius: 16px; padding: 2.25rem 2rem; }
.withdraw-card h1 { font-size: 2rem; margin: 0 0 0.75rem; }
.withdraw-card h2 { font-size: 1.25rem; margin: 0 0 0.65rem; }
.withdraw-lead { color: var(--muted); line-height: 1.65; margin: 0 0 1.5rem; }
.withdraw-fields { display: grid; gap: 1rem; }
.withdraw-field label { display: block; color: var(--text); font-size: 0.9rem; font-weight: 600; margin-bottom: 0.38rem; }
.withdraw-field .label-optional { color: var(--muted); font-weight: 400; }
.withdraw-field input {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: #0b0c10;
  color: var(--text);
  font: inherit;
  padding: 0.78rem 0.85rem;
}
.withdraw-field input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.withdraw-help { display: block; color: var(--muted); font-size: 0.79rem; margin-top: 0.38rem; line-height: 1.45; }
.withdraw-actions { display: flex; gap: 0.7rem; flex-wrap: wrap; margin-top: 1.4rem; }
.withdraw-actions .btn { flex: 1 1 12rem; text-align: center; }
.withdraw-review { margin: 1.2rem 0; background: #0b0c10; border: 1px solid var(--border); border-radius: 11px; padding: 1rem; }
.withdraw-review dl { display: grid; grid-template-columns: minmax(7rem, auto) 1fr; gap: 0.5rem 1rem; margin: 0; }
.withdraw-review dt { color: var(--muted); }
.withdraw-review dd { margin: 0; overflow-wrap: anywhere; }
.withdraw-declaration { font-weight: 600; line-height: 1.6; margin: 1.2rem 0; }
.withdraw-status { min-height: 1.4em; color: var(--muted); font-size: 0.88rem; margin: 0.8rem 0 0; }
.withdraw-status.is-warning { color: #ffe0a3; }
.withdraw-status.is-error { color: #ffaaa5; }
.withdraw-success { border: 1px solid rgba(94, 213, 154, 0.4); background: rgba(94, 213, 154, 0.07); border-radius: 12px; padding: 1.2rem; margin-top: 1.2rem; }
.withdraw-success h2 { color: #9de2bd; }
.withdraw-receipt {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 18rem;
  overflow: auto;
  background: #08090c;
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 0.9rem;
  font-size: 0.78rem;
  line-height: 1.5;
}
.withdraw-direct { margin-top: 1rem; font-size: 0.88rem; line-height: 1.6; }
.withdraw-privacy { border-top: 1px solid var(--border); font-size: 0.8rem; color: var(--muted); line-height: 1.55; margin: 1.5rem 0 0; padding-top: 1rem; }
.bot-field { position: absolute !important; left: -10000px !important; width: 1px !important; height: 1px !important; overflow: hidden !important; }
[hidden] { display: none !important; }
@media (max-width: 560px) {
  .withdraw-main { padding-top: 6.5rem; }
  .withdraw-card { padding: 1.6rem 1.15rem; }
  .withdraw-review dl { grid-template-columns: 1fr; gap: 0.18rem; }
  .withdraw-review dd { margin-bottom: 0.55rem; }
}

/* ============================================================
   Legal pages
   ============================================================ */

.legal-main {
  max-width: 780px;
  margin: 0 auto;
  padding: 130px 20px 80px;
}
.legal-main h1 {
  font-size: clamp(1.8rem, 4.5vw, 2.6rem);
  font-weight: 750;
  letter-spacing: -0.03em;
}
.legal-main h2 {
  margin-top: 2.2em;
  font-size: 1.2rem;
  font-weight: 650;
  letter-spacing: -0.01em;
}
.legal-main h3 { margin-top: 1.6em; font-size: 1.02rem; font-weight: 650; }
.legal-main p, .legal-main li { margin-top: 0.7em; color: var(--muted); font-size: 0.95rem; line-height: 1.7; }
.legal-main ul, .legal-main ol { padding-left: 1.4em; }
.legal-main strong { color: var(--text); }
.legal-main code { overflow-wrap: anywhere; }
.legal-updated { margin-top: 8px; font-family: var(--mono); font-size: 0.76rem; color: var(--dim); }
.legal-document {
  margin-top: 1.5rem;
  padding: 1.2rem;
  overflow: auto;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: #08090c;
  color: var(--muted);
  font: 0.82rem/1.6 var(--mono);
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
.legal-source-component li { margin-top: 1.1em; }
.lawyer-note {
  margin-top: 26px;
  border: 1px solid rgba(240, 180, 85, 0.5);
  background: rgba(240, 180, 85, 0.08);
  border-radius: 12px;
  padding: 14px 18px;
  color: #e8c476;
  font-size: 0.88rem;
  line-height: 1.6;
}
.ph {
  font-family: var(--mono);
  font-size: 0.9em;
  color: #ffd98a;
  background: rgba(240, 180, 85, 0.14);
  border: 1px dashed rgba(240, 180, 85, 0.5);
  border-radius: 5px;
  padding: 0 6px;
  white-space: nowrap;
}
.legal-table-wrap { margin-top: 1em; overflow-x: auto; }
.legal-table {
  border-collapse: collapse;
  width: 100%;
  min-width: 640px;
  font-size: 0.86rem;
}
.legal-table th, .legal-table td {
  border: 1px solid var(--border);
  padding: 10px 12px;
  text-align: left;
  vertical-align: top;
  color: var(--muted);
  line-height: 1.55;
}
.legal-table th {
  background: var(--panel);
  color: var(--text);
  font-weight: 650;
  white-space: nowrap;
}

/* ============================================================
   Scroll reveal (JS adds .is-in; hidden state only when JS present)
   ============================================================ */

html.js .fade-up {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.8s cubic-bezier(0.16, 0.68, 0.3, 1),
              transform 0.8s cubic-bezier(0.16, 0.68, 0.3, 1);
}
html.js .fade-up.is-in { opacity: 1; transform: none; }

/* ============================================================
   Reduced motion — kill all movement, keep the composed frame
   ============================================================ */

/* Forced-colors / high-contrast: gradient-clipped text has no colour of its
   own, so restore a real one before the system palette takes over. */
@media (forced-colors: active) {
  .hero-title, .section-head h2 {
    -webkit-background-clip: border-box;
    background-clip: border-box;
    background: none;
    color: CanvasText;
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001s !important;
  }
  .rise { opacity: 1; transform: none; animation: none !important; }
  html.js .fade-up { opacity: 1; transform: none; transition: none; }
  .btn-primary:hover, .btn-ghost:hover, .feature:hover, .dl-card:hover { transform: none; }
  html.js .play .w-anim { animation: none !important; }
  html.js .play .mk-tint { animation: none !important; }
  html.js .mock-live .asb-dot.live { animation: none !important; }
  /* the live windows collapse to their finished, composed state */
  html.js .mock-live .post-btn { opacity: 1; }
  html.js .sc-tab.is-active .sc-tab-bar { animation: none; opacity: 0; }
  html.js .sc-tab.is-active .ts-node { animation: none; }
  /* app.js never adds .play under reduced motion, so the staged copy is
     already visible; belt and braces in case the class survives a toggle */
  html.js .sc-panel.play .window-wrap,
  html.js .sc-panel.play .tc-eyebrow,
  html.js .sc-panel.play .tc-main h3,
  html.js .sc-panel.play .tc-main p,
  html.js .sc-panel.play .tc-side {
    animation: none !important;
    opacity: 1;
    transform: none;
  }
}

/* --- Dataset contribution (/contribute) ------------------------------- */
[hidden] { display: none !important; }

.contribute-limits {
  display: grid;
  grid-template-columns: minmax(6.5rem, auto) 1fr;
  gap: 0.45rem 1rem;
  margin: 0 0 1.4rem;
  padding: 0.9rem 1rem;
  background: #0b0c10;
  border: 1px solid var(--border);
  border-radius: 11px;
  font-size: 0.9rem;
}
.contribute-limits dt { color: var(--muted); }
.contribute-limits dd { margin: 0; overflow-wrap: anywhere; }
.contribute-asked {
  color: var(--muted);
  line-height: 1.6;
  margin: 0 0 1.3rem;
  padding-left: 0.85rem;
  border-left: 2px solid var(--accent-dim);
}

.contribute-resume {
  border: 1px solid rgba(251, 191, 36, 0.38);
  background: rgba(251, 191, 36, 0.07);
  border-radius: 12px;
  padding: 1.1rem 1.15rem;
  margin-bottom: 1.4rem;
}
.contribute-resume h2 { font-size: 1.05rem; margin: 0 0 0.5rem; color: #ffe0a3; }
.contribute-resume p { margin: 0 0 0.6rem; line-height: 1.6; }

.contribute-drop {
  border: 1.5px dashed var(--border-hi);
  border-radius: 14px;
  background: #0b0c10;
  padding: 2rem 1.25rem;
  text-align: center;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.contribute-drop.is-over {
  border-color: var(--accent);
  background: rgba(91, 140, 255, 0.07);
}
.contribute-drop-head { margin: 0 0 0.3rem; font-weight: 600; color: var(--text); }
.contribute-drop-sub { margin: 0 0 1.1rem; color: var(--muted); font-size: 0.88rem; }
.contribute-drop-actions {
  display: flex;
  gap: 0.6rem;
  justify-content: center;
  flex-wrap: wrap;
}
/* Kept in the layout but visually removed: the buttons above drive them, and
   a display:none input cannot be opened by .click() in every browser. */
.contribute-hidden-input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.contribute-selection { margin-top: 1.2rem; }
.contribute-selection-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  margin: 0 0 0.5rem;
  font-size: 0.9rem;
  color: var(--text);
  font-weight: 600;
}
.btn-link {
  background: none;
  border: 0;
  padding: 0;
  color: var(--accent-hi);
  font: inherit;
  font-weight: 400;
  cursor: pointer;
  text-decoration: underline;
}
.contribute-file-list {
  list-style: none;
  margin: 0;
  padding: 0.55rem 0.7rem;
  max-height: 13rem;
  overflow-y: auto;
  background: #0b0c10;
  border: 1px solid var(--border);
  border-radius: 10px;
  font-size: 0.82rem;
}
.contribute-file-list li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.16rem 0;
}
.contribute-file-path {
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.contribute-file-size { color: var(--fainter); flex: none; }
.contribute-selection-more {
  margin: 0.45rem 0 0;
  font-size: 0.82rem;
  color: var(--fainter);
}

.contribute-note-field { margin-top: 1.3rem; }
.contribute-note-field label {
  display: block;
  color: var(--text);
  font-size: 0.9rem;
  font-weight: 600;
  margin-bottom: 0.38rem;
}
.contribute-note-field textarea {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: #0b0c10;
  color: var(--text);
  font: inherit;
  padding: 0.7rem 0.85rem;
  resize: vertical;
}
.contribute-note-field textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.contribute-agree {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  margin-top: 1.2rem;
  font-size: 0.88rem;
  color: var(--muted);
  line-height: 1.55;
}
.contribute-agree input { margin-top: 0.22rem; flex: none; }

.contribute-progress { margin-top: 0.5rem; }
.contribute-bar {
  height: 9px;
  border-radius: 999px;
  background: var(--panel-hi);
  overflow: hidden;
}
.contribute-bar-fill {
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: var(--grad-sweep);
  transition: width 0.25s ease;
}
.contribute-progress-line {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin: 0.6rem 0 0;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--text);
}
.contribute-progress-detail { color: var(--muted); font-weight: 400; }

@media (max-width: 640px) {
  .contribute-limits { grid-template-columns: 1fr; gap: 0.14rem; }
  .contribute-limits dd { margin-bottom: 0.5rem; }
  .contribute-drop { padding: 1.4rem 1rem; }
}
