/* CyberFreezeDev: white lab spec sheet.
   Layout: left-aligned 12-column grid; each page opens on a 3D "render stage"
   (matte objects on a white studio floor); content below reads like an
   engineering document: sticky section heading on the left, body on the right.
   Index pages read like a parts index: one row per entry, mono metadata. */
/* The hidden attribute always wins over component display rules (grid, flex). */
[hidden] { display: none !important; }
/* Size-matched fallback faces. The Google Fonts stylesheet loads without blocking
   paint, so the first frame uses these. Widths and vertical metrics were measured
   against the real fonts in Chromium (13 Oct 2026), one face per weight band
   because Schibsted widens with weight (a request for 520 renders the 600 file,
   750 the 800 file), so the swap does not rewrap titles or buttons. */
@font-face { font-family: "Schibsted Fallback"; src: local("Arial"), local("ArialMT"), local("Liberation Sans"); font-weight: 1 400; size-adjust: 102.3%; ascent-override: 95.8%; descent-override: 25.4%; line-gap-override: 0%; }
@font-face { font-family: "Schibsted Fallback"; src: local("Arial"), local("ArialMT"), local("Liberation Sans"); font-weight: 401 500; size-adjust: 103.8%; ascent-override: 94.4%; descent-override: 25.1%; line-gap-override: 0%; }
@font-face { font-family: "Schibsted Fallback"; src: local("Arial Bold"), local("Arial-BoldMT"), local("Liberation Sans Bold"); font-weight: 501 600; size-adjust: 100.1%; ascent-override: 97.9%; descent-override: 26.0%; line-gap-override: 0%; }
@font-face { font-family: "Schibsted Fallback"; src: local("Arial Bold"), local("Arial-BoldMT"), local("Liberation Sans Bold"); font-weight: 601 700; size-adjust: 102.0%; ascent-override: 96.0%; descent-override: 25.5%; line-gap-override: 0%; }
@font-face { font-family: "Schibsted Fallback"; src: local("Arial Bold"), local("Arial-BoldMT"), local("Liberation Sans Bold"); font-weight: 701 1000; size-adjust: 104.1%; ascent-override: 94.1%; descent-override: 25.0%; line-gap-override: 0%; }
@font-face { font-family: "Plex Mono Fallback"; src: local("Courier New"), local("CourierNewPSMT"), local("Liberation Mono"); size-adjust: 100%; ascent-override: 103%; descent-override: 28%; line-gap-override: 0%; }
/* Schibsted Grotesk (400 to 800) and IBM Plex Mono 400 and 500, served from
   public/fonts (SIL Open Font License 1.1, licence files beside the fonts) instead of Google
   Fonts, so no third party connection sits in front of first paint. Latin and Latin Extended
   subsets, declared per weight exactly as Google serves them (one variable file for
   Schibsted, so 520 still renders as 600; the rupee sign is in Latin Extended). */
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400; font-display: swap; src: url(/fonts/ibm-plex-mono-400-latin-ext.woff2?v=1) format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400; font-display: swap; src: url(/fonts/ibm-plex-mono-400-latin.woff2?v=1) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap; src: url(/fonts/ibm-plex-mono-500-latin-ext.woff2?v=1) format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap; src: url(/fonts/ibm-plex-mono-500-latin.woff2?v=1) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Schibsted Grotesk"; font-style: normal; font-weight: 400; font-display: swap; src: url(/fonts/schibsted-grotesk-latin-ext.woff2?v=1) format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Schibsted Grotesk"; font-style: normal; font-weight: 400; font-display: swap; src: url(/fonts/schibsted-grotesk-latin.woff2?v=1) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Schibsted Grotesk"; font-style: normal; font-weight: 500; font-display: swap; src: url(/fonts/schibsted-grotesk-latin-ext.woff2?v=1) format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Schibsted Grotesk"; font-style: normal; font-weight: 500; font-display: swap; src: url(/fonts/schibsted-grotesk-latin.woff2?v=1) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Schibsted Grotesk"; font-style: normal; font-weight: 600; font-display: swap; src: url(/fonts/schibsted-grotesk-latin-ext.woff2?v=1) format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Schibsted Grotesk"; font-style: normal; font-weight: 600; font-display: swap; src: url(/fonts/schibsted-grotesk-latin.woff2?v=1) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Schibsted Grotesk"; font-style: normal; font-weight: 700; font-display: swap; src: url(/fonts/schibsted-grotesk-latin-ext.woff2?v=1) format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Schibsted Grotesk"; font-style: normal; font-weight: 700; font-display: swap; src: url(/fonts/schibsted-grotesk-latin.woff2?v=1) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Schibsted Grotesk"; font-style: normal; font-weight: 800; font-display: swap; src: url(/fonts/schibsted-grotesk-latin-ext.woff2?v=1) format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Schibsted Grotesk"; font-style: normal; font-weight: 800; font-display: swap; src: url(/fonts/schibsted-grotesk-latin.woff2?v=1) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
:root {
  --paper: #ffffff;
  --floor: #f4f3f8;        /* studio floor / quiet panels */
  --ink: #15121f;          /* graphite with a violet bias */
  --graphite: #4b475a;     /* secondary text */
  --mist: #6b6779;         /* captions (5.5:1 on white, 4.9:1 on --floor, 4.7:1 on --violet-wash) */
  --rule: #e6e4ee;         /* hairlines */
  --rule-strong: #cfcbdb;  /* input borders, table heads */
  --violet: #5b2bd1;       /* logo violet: links, focus, live signals */
  --violet-deep: #4320a3;
  --violet-wash: #f1ecff;
  --live: #0a7d55;         /* product status: live (5.1:1 on white) */
  --beta: #9a5d00;         /* product status: beta (5.3:1 on white) */

  --font-sans: "Schibsted Grotesk", "Schibsted Fallback", "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --font-mono: "IBM Plex Mono", "Plex Mono Fallback", ui-monospace, "Cascadia Mono", Consolas, monospace;

  /* Type scale: 1.25 ratio from 17px body */
  --t-xs: .8125rem;  --t-s: .9375rem;  --t-m: 1.0625rem;  --t-l: 1.3125rem;
  --t-xl: 1.75rem;   --t-2xl: 2.375rem; --t-3xl: clamp(2.5rem, 4.6vw, 4rem);

  --gutter: clamp(16px, 4vw, 40px);
  --max: 1240px;
  --radius: 6px;
  --header-h: 68px;
  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-padding-top: 88px; scroll-padding-bottom: 76px; }
body {
  margin: 0; background: var(--paper); color: var(--ink);
  font-family: var(--font-sans); font-size: var(--t-m); line-height: 1.6;
  font-feature-settings: "ss01", "cv11"; text-rendering: optimizeLegibility;
  overflow-x: clip;
}
img, svg, video, canvas { max-width: 100%; display: block; }
a { color: var(--violet); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--violet-deep); }
:focus-visible { outline: 2px solid var(--violet); outline-offset: 3px; border-radius: 2px; }
code, kbd, .mono { font-family: var(--font-mono); font-size: .92em; }
h1, h2, h3, h4 { font-family: var(--font-sans); color: var(--ink); line-height: 1.12; margin: 0; text-wrap: balance; letter-spacing: -.02em; }
h1 { font-size: var(--t-3xl); font-weight: 750; letter-spacing: -.035em; line-height: 1.04; }
h2 { font-size: var(--t-2xl); font-weight: 700; }
h3 { font-size: var(--t-l); font-weight: 650; letter-spacing: -.01em; }
p { margin: 0; text-wrap: pretty; }
.skip { position: absolute; left: -9999px; top: 8px; background: var(--ink); color: var(--paper); padding: 8px 12px; z-index: 100; }
.skip:focus { left: 8px; }
#main:focus { outline: 0; }
/* Visually hidden, still read by screen readers. */
.vh { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); }

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: env(safe-area-inset-top, 0px); z-index: 50;
  background: rgba(255, 255, 255, .94); backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--rule);
}
.site-header .wrap { display: flex; align-items: center; gap: 28px; min-height: var(--header-h); }
.brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink); text-decoration: none; font-weight: 750; font-size: 1.125rem; letter-spacing: -.02em; }
.brand:hover { color: var(--ink); }
.brand img { width: 30px; height: 30px; }
.nav { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.nav > ul { list-style: none; display: flex; gap: 2px; margin: 0; padding: 0; }
.nav-item { position: relative; }
.nav-link {
  display: inline-flex; align-items: center; gap: 6px; padding: 9px 12px; border-radius: var(--radius);
  color: var(--ink); text-decoration: none; font-size: var(--t-s); font-weight: 520; background: none; border: 0; font-family: inherit; cursor: pointer;
}
.nav-link:hover, .nav-item.open > .nav-link { background: var(--floor); color: var(--ink); }
.nav-link:focus-visible { outline-offset: 0; }
.nav-link[aria-current="page"] { color: var(--violet); }
.nav-caret { width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-2px) rotate(45deg); opacity: .55; transition: transform .15s; }
.nav-item.open > .nav-link .nav-caret { transform: translateY(1px) rotate(225deg); }
.mega {
  position: absolute; top: calc(100% + 10px); left: -12px; min-width: 560px; padding: 10px;
  background: var(--paper); border: 1px solid var(--rule); border-radius: 10px;
  box-shadow: 0 1px 0 rgba(21, 18, 31, .04), 0 24px 48px -24px rgba(21, 18, 31, .28);
  display: none; grid-template-columns: 1fr 1fr; gap: 0 4px;
}
.nav-item:nth-last-child(-n+2) > .mega { left: auto; right: -12px; }
.nav-item.open > .mega { display: grid; }
.mega a { display: grid; gap: 2px; padding: 10px 12px; border-radius: var(--radius); color: var(--ink); text-decoration: none; }
.mega a:hover, .mega a:focus-visible { background: var(--floor); }
.mega a:focus-visible { outline-offset: -2px; }
.mega a strong { font-size: var(--t-s); font-weight: 620; }
.mega a span { font-family: var(--font-mono); font-size: .75rem; color: var(--graphite); line-height: 1.45; }
.mega .mega-all { grid-column: 1 / -1; border-top: 1px solid var(--rule); border-radius: 0 0 var(--radius) var(--radius); margin-top: 6px; padding-top: 12px; font-size: var(--t-s); font-weight: 600; color: var(--violet); }
.header-cta { margin-left: 8px; }
.menu-toggle { display: none; margin-left: auto; background: none; border: 1px solid var(--rule-strong); border-radius: var(--radius); padding: 8px 14px; font: inherit; font-size: var(--t-s); font-weight: 560; color: var(--ink); cursor: pointer; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  padding: 12px 20px; border-radius: var(--radius); border: 1px solid var(--ink);
  background: var(--ink); color: var(--paper); font: inherit; font-size: var(--t-s); font-weight: 600;
  text-decoration: none; cursor: pointer; transition: background .15s, border-color .15s, color .15s;
}
.btn:hover { background: var(--violet); border-color: var(--violet); color: var(--paper); }
.btn:focus-visible { outline-offset: 3px; }
.btn:disabled { opacity: .6; cursor: progress; }
.btn.ghost { background: transparent; color: var(--ink); border-color: var(--rule-strong); }
.btn.ghost:hover { border-color: var(--ink); background: transparent; color: var(--ink); }
.btn.small { padding: 8px 14px; }
.btn-row { display: flex; flex-wrap: wrap; gap: 12px; }

/* ---------- Render stage (3D header) ---------- */
.stage { position: relative; border-bottom: 1px solid var(--rule); overflow: hidden; background: var(--paper); }
.stage::after { /* studio floor: white cyclorama fading into a light floor */
  content: ""; position: absolute; inset: auto 0 0 0; height: 38%;
  background: linear-gradient(to bottom, rgba(244, 243, 248, 0), var(--floor));
  pointer-events: none; z-index: 0;
}
.stage .wrap {
  position: relative; z-index: 2; display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(24px, 3vw, 40px); align-items: center; padding-block: clamp(28px, 4vw, 56px);
}
.stage-copy { display: grid; gap: 20px; align-content: center; justify-items: start; }
.stage-copy .lede { font-size: 1.1875rem; color: var(--graphite); max-width: 26.9em; line-height: 1.5; }
.stage-copy .btn-row { margin-top: 4px; }
.stage-canvas { position: relative; aspect-ratio: 5 / 4; min-height: 280px; }
.stage-canvas canvas { position: absolute; inset: 0; width: 100% !important; height: 100% !important; }
.stage-canvas .still { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.stage-canvas[data-ready] .still { opacity: 0; transition: opacity .6s; }
/* Inner pages: the canvas takes the wider column and runs to the right edge of
   the window, so the subject reads as a product render, not a thumbnail. */
.stage.compact .wrap { padding-block: clamp(16px, 2.2vw, 28px); min-height: clamp(420px, 56vh, 560px); }
.stage.compact .stage-copy { padding-block: 16px; }
.stage.compact .stage-canvas {
  aspect-ratio: auto; align-self: stretch; min-height: clamp(380px, 50vh, 520px);
  margin-right: calc(-1 * var(--gutter) - max(0px, (100vw - var(--max)) / 2));
}
/* H1 steps down with length (class set in stage.ejs) so long titles stay at 3 or 4 lines. */
.stage h1.h1-m { font-size: clamp(2.25rem, 3.7vw, 3.375rem); }
.stage h1.h1-l { font-size: clamp(2rem, 3.1vw, 2.875rem); letter-spacing: -.03em; line-height: 1.07; }
.stage h1.h1-xl { font-size: clamp(1.875rem, 2.75vw, 2.5rem); letter-spacing: -.025em; line-height: 1.08; }
.crumbs { display: flex; flex-wrap: wrap; gap: 4px 6px; font-size: var(--t-xs); color: var(--mist); list-style: none; margin: 0; padding: 0; }
.crumbs a { color: var(--graphite); text-decoration: none; }
.crumbs a:hover { color: var(--violet); text-decoration: underline; }
.crumbs li + li::before { content: "/"; margin-right: 6px; color: var(--rule-strong); }
.status { display: inline-flex; align-items: center; gap: 8px; font-size: var(--t-xs); font-weight: 600; color: var(--live); line-height: 1.3; }
.status::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; box-shadow: 0 0 0 4px color-mix(in srgb, currentColor 16%, transparent); flex: none; }
.status.beta { color: var(--beta); }

/* ---------- Document body ---------- */
.doc { padding-block: clamp(36px, 5vw, 72px) clamp(48px, 6vw, 88px); }
.doc-section { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: 20px 48px; padding-block: clamp(28px, 3.4vw, 44px); border-top: 1px solid var(--rule); }
.doc-section:first-child { border-top: 0; padding-top: 0; }
.doc-section > header { position: sticky; top: 96px; align-self: start; display: grid; gap: 10px; }
.doc-section > header:empty { display: none; }
.doc-section > header h2 { font-size: var(--t-xl); }
.doc-section > header p { color: var(--graphite); font-size: var(--t-s); max-width: 23.23em; }
.doc-section > div { min-width: 0; }
/* Text measures are in em, not ch: ch follows the "0" of whichever font is showing, so
   a ch width would change when the web font swaps in. 1ch of Schibsted 400 = .6113em. */
.prose { display: grid; gap: 14px; max-width: 41.57em; color: var(--ink); }
.prose p, .prose li { color: #2b2838; }
.prose ul, .prose ol { margin: 0; padding-left: 1.2em; display: grid; gap: 6px; }
.prose li::marker { color: var(--violet); }
.prose strong { font-weight: 650; }
.prose code { background: var(--floor); border: 1px solid var(--rule); border-radius: 4px; padding: .05em .3em; font-size: .86em; }

.points { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); gap: 28px 32px; }
.point { display: grid; gap: 8px; align-content: start; padding-top: 16px; border-top: 2px solid var(--ink); }
.point h3 { font-size: var(--t-m); font-weight: 650; }
.point .prose, .point p { color: var(--graphite); font-size: var(--t-s); }

.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; counter-reset: step; border-bottom: 1px solid var(--rule); }
.steps li { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: 16px; padding-block: 18px; border-top: 1px solid var(--rule); counter-increment: step; }
.steps li::before { content: counter(step, decimal-leading-zero); font-family: var(--font-mono); font-size: var(--t-s); color: var(--violet); padding-top: 2px; }
.steps h3 { font-size: var(--t-m); margin-bottom: 4px; }
.steps .prose, .steps p { color: var(--graphite); font-size: var(--t-s); }

/* Spec sheet: the subject's own detail. Mono for data only. */
.specs { border: 1px solid var(--rule); border-radius: 10px; overflow: hidden; }
.specs-title { padding: 14px 18px; border-bottom: 1px solid var(--rule); background: var(--floor); font-size: var(--t-s); font-weight: 650; display: flex; justify-content: space-between; gap: 12px; }
.specs-title span { font-family: var(--font-mono); font-weight: 400; color: var(--mist); font-size: var(--t-xs); }
.specs dl { margin: 0; display: grid; grid-template-columns: minmax(120px, 2fr) minmax(0, 5fr); }
.specs dt, .specs dd { margin: 0; padding: 12px 18px; border-top: 1px solid var(--rule); font-size: var(--t-s); }
.specs dl > dt:first-of-type, .specs dl > dt:first-of-type + dd { border-top: 0; }
.specs dt { color: var(--graphite); }
.specs dd { font-family: var(--font-mono); font-size: .875rem; color: var(--ink); overflow-wrap: anywhere; }

/* Tables scroll inside their frame on narrow screens, never the page; the row label stays pinned. */
.table-wrap { overflow-x: auto; border: 1px solid var(--rule); border-radius: 10px; overscroll-behavior-x: contain; max-width: 100%; }
.table-wrap:focus-visible { outline-offset: 2px; }
/* Edge shadow while more columns sit off to the right; it scrolls away at the end. */
.table-wrap.is-scrollable {
  background:
    linear-gradient(to left, var(--paper) 40%, rgba(255, 255, 255, 0)) right center / 32px 100% no-repeat local,
    linear-gradient(to left, rgba(21, 18, 31, .14), rgba(21, 18, 31, 0)) right center / 12px 100% no-repeat scroll;
}
.table-hint { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--mist); margin-bottom: 8px; }
table { border-collapse: separate; border-spacing: 0; width: 100%; font-size: var(--t-s); min-width: 560px; }
th, td { text-align: left; padding: 12px 16px; border-top: 1px solid var(--rule); vertical-align: top; }
thead th { border-top: 0; background: var(--floor); font-weight: 650; border-bottom: 1px solid var(--rule-strong); }
thead th + th, tbody td { border-left: 1px solid var(--rule); }
tbody tr:first-child > * { border-top: 0; }
tbody th[scope="row"] { font-weight: 620; }
td.num, th.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; }
.table-note { font-size: var(--t-xs); color: var(--mist); margin-top: 10px; }
.page-updated { margin-top: 24px; font-family: var(--font-mono); }

.quote { display: grid; gap: 14px; padding: 28px; border-left: 3px solid var(--violet); background: var(--floor); border-radius: 0 10px 10px 0; margin: 0; }
.quote blockquote { margin: 0; font-size: var(--t-l); line-height: 1.45; letter-spacing: -.01em; }
.quote figcaption { font-size: var(--t-s); color: var(--graphite); }

/* Link list (features, related): index rows in two columns, arrow on the right. */
.link-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); gap: 0 32px; }
.link-list a { position: relative; display: grid; gap: 4px; align-content: start; padding: 16px 32px 16px 0; border-top: 1px solid var(--rule); color: var(--ink); text-decoration: none; }
.link-list a strong { font-weight: 640; }
.link-list a span { color: var(--graphite); font-size: var(--t-s); }
.link-list a:hover strong { color: var(--violet); }
.link-list a:focus-visible { outline-offset: -2px; }
.link-list .ix-go { position: absolute; right: 6px; top: 22px; }

.faq details { border-top: 1px solid var(--rule); }
.faq details:last-child { border-bottom: 1px solid var(--rule); }
.faq summary { cursor: pointer; padding: 16px 36px 16px 0; font-weight: 600; list-style: none; position: relative; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; position: absolute; right: 6px; top: 13px; font-family: var(--font-mono); font-size: 1.2rem; color: var(--violet); }
.faq summary:hover { color: var(--violet-deep); }
.faq summary:focus-visible { outline-offset: -2px; }
.faq details[open] summary::after { content: "\2212"; }
.faq .prose { padding-bottom: 18px; color: var(--graphite); }

/* Closing call to action: one dark plate at the end of a page. */
.cta-band {
  margin-top: clamp(32px, 4vw, 48px); padding: clamp(28px, 4.5vw, 52px); border-radius: 12px;
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 24px 40px; align-items: center;
  background: var(--ink); color: var(--paper);
}
.cta-band h2 { font-size: var(--t-xl); color: var(--paper); }
.cta-band p { color: #c9c5d6; margin-top: 8px; max-width: 35.46em; }
.cta-band a:not(.btn) { color: #cbb8ff; }
.cta-band .btn { background: var(--paper); color: var(--ink); border-color: var(--paper); }
.cta-band .btn:hover { background: var(--violet); border-color: var(--violet); color: var(--paper); }
.cta-band .btn:focus-visible { outline-color: #cbb8ff; }

/* ---------- Listing / index pages ---------- */
.index-doc { padding-top: clamp(28px, 4vw, 56px); }
.index-toc { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px 24px; padding-bottom: 18px; margin-bottom: clamp(24px, 3vw, 36px); border-bottom: 1px solid var(--rule); }
.index-toc ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 6px; }
.index-toc a { display: inline-flex; align-items: baseline; gap: 8px; padding: 6px 10px; border: 1px solid var(--rule); border-radius: var(--radius); color: var(--ink); text-decoration: none; font-size: var(--t-s); }
.index-toc a:hover { border-color: var(--ink); }
.index-toc a span { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--mist); }
.index-count { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--mist); }
.index-group + .index-group { margin-top: clamp(36px, 4.5vw, 56px); }
.index-head { display: grid; gap: 6px; margin-bottom: 14px; }
.index-head h2 { font-size: var(--t-xl); }
.index-head p { color: var(--graphite); font-size: var(--t-s); max-width: 39.12em; }
.index-rows { list-style: none; margin: 0; padding: 0; border-top: 2px solid var(--ink); }
.index-row {
  display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 6fr) minmax(200px, 2fr) 18px; gap: 6px 32px; align-items: baseline;
  padding: 18px 4px; border-bottom: 1px solid var(--rule); color: var(--ink); text-decoration: none; transition: background .15s;
}
.index-row:hover { background: var(--floor); color: var(--ink); }
.index-row:hover strong { color: var(--violet); }
.index-row:focus-visible { outline-offset: -2px; border-radius: 0; }
.no-meta .index-row { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr) 18px; }
.no-meta .ix-meta { display: none; }
.ix-name { display: grid; gap: 3px; }
.ix-name strong { font-size: 1.1875rem; font-weight: 650; letter-spacing: -.012em; line-height: 1.3; }
.ix-note { font-family: var(--font-mono); font-size: .8125rem; color: var(--graphite); line-height: 1.45; }
.ix-sum { color: var(--graphite); font-size: var(--t-s); line-height: 1.55; }
.ix-meta { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--mist); text-align: right; overflow-wrap: break-word; }
.ix-meta .status { font-family: var(--font-sans); }
.ix-go { display: inline-block; width: 8px; height: 8px; border-top: 1.5px solid currentColor; border-right: 1.5px solid currentColor; transform: rotate(45deg); color: var(--mist); justify-self: end; align-self: center; transition: transform .15s, color .15s; }
.index-row:hover .ix-go, .link-list a:hover .ix-go { color: var(--violet); transform: translateX(3px) rotate(45deg); }

/* Glossary: A to Z term index. */
.index-toc.az ul { gap: 4px; }
.index-toc.az a { min-width: 34px; justify-content: center; font-family: var(--font-mono); padding: 5px 8px; }
.az-group { display: grid; grid-template-columns: 72px minmax(0, 1fr); gap: 0 24px; border-top: 2px solid var(--ink); padding-top: 4px; }
.az-group + .az-group { margin-top: 28px; }
.az-letter { font-family: var(--font-mono); font-weight: 500; font-size: var(--t-xl); color: var(--violet); padding-top: 12px; letter-spacing: 0; }
.az-terms { margin: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); gap: 0 40px; }
.az-terms > div { padding: 14px 0; border-bottom: 1px solid var(--rule); display: grid; gap: 4px; align-content: start; }
.az-terms dt a { font-weight: 650; color: var(--ink); text-decoration: none; }
.az-terms dt a:hover { color: var(--violet); text-decoration: underline; }
.az-terms dd { margin: 0; color: var(--graphite); font-size: var(--t-s); }

/* ---------- Forms ---------- */
.form { display: grid; grid-template-columns: 1fr 1fr; gap: 18px 20px; max-width: 760px; }
.form .full { grid-column: 1 / -1; }
.field { display: grid; gap: 6px; min-width: 0; }
.field label, .fieldset legend { font-size: var(--t-s); font-weight: 600; }
.fieldset { border: 0; padding: 0; margin: 0; }
.fieldset legend { padding: 0; margin-bottom: 6px; }
.field .hint { font-size: var(--t-xs); color: var(--mist); font-weight: 400; }
input, select, textarea {
  width: 100%; font: inherit; font-size: var(--t-s); color: var(--ink); background: var(--paper);
  border: 1px solid var(--rule-strong); border-radius: var(--radius); padding: 11px 12px;
}
input:hover, select:hover, textarea:hover { border-color: #b3aec4; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--violet); outline-offset: 0; border-color: var(--violet); }
textarea { min-height: 140px; resize: vertical; }
.choice-row { display: flex; flex-wrap: wrap; gap: 8px; }
.choice-row label { display: inline-flex; align-items: center; gap: 8px; border: 1px solid var(--rule-strong); border-radius: var(--radius); padding: 9px 14px; font-weight: 500; cursor: pointer; }
.choice-row input { width: auto; accent-color: var(--violet); }
.choice-row input:focus { outline: 0; }
.choice-row label:has(input:focus-visible) { outline: 2px solid var(--violet); outline-offset: 2px; }
.choice-row label:has(input:checked) { border-color: var(--violet); background: var(--violet-wash); }
.form-message { grid-column: 1 / -1; font-size: var(--t-s); min-height: 1.4em; }
.form-message.ok { color: var(--live); }
.form-message.err { color: #b42318; }
.form [aria-invalid="true"] { border-color: #b42318; }
.hp { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }

/* ---------- Footer ---------- */
.site-footer { border-top: 1px solid var(--rule); background: var(--floor); padding-block: 56px 32px; font-size: var(--t-s); }
.footer-grid { display: grid; grid-template-columns: minmax(0, 2.2fr) repeat(4, minmax(0, 1fr)); gap: 32px; }
.footer-grid h2 { font-size: var(--t-xs); font-family: var(--font-mono); font-weight: 500; color: var(--mist); margin-bottom: 14px; letter-spacing: 0; }
.footer-grid ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.footer-grid a { color: var(--ink); text-decoration: none; }
.footer-grid a:hover { color: var(--violet); text-decoration: underline; }
.footer-about { display: grid; gap: 14px; align-content: start; color: var(--graphite); max-width: 24.45em; }
.footer-about .brand { color: var(--ink); }
.footer-about a:not(.brand) { color: var(--ink); }
.footer-meta { margin-top: 40px; padding-top: 20px; border-top: 1px solid var(--rule-strong); display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; color: var(--mist); font-size: var(--t-xs); }
.footer-meta a { color: var(--graphite); }
.social { display: flex; gap: 6px 14px; flex-wrap: wrap; }

/* ---------- Floating WhatsApp + consent ---------- */
.wa-float {
  position: fixed; right: 18px; bottom: calc(18px + env(safe-area-inset-bottom, 0px)); z-index: 60;
  display: inline-flex; align-items: center; gap: 10px; padding: 11px 16px; border-radius: 999px;
  background: var(--ink); color: var(--paper); text-decoration: none; font-size: var(--t-s); font-weight: 600;
  box-shadow: 0 12px 30px -12px rgba(21, 18, 31, .5);
}
.wa-float:hover { background: #0f7a40; color: var(--paper); }
.wa-float:focus-visible { outline-offset: 3px; }
.wa-float svg { width: 20px; height: 20px; }
.consent {
  position: fixed; left: 18px; bottom: calc(18px + env(safe-area-inset-bottom, 0px)); z-index: 70; max-width: 420px;
  background: var(--paper); border: 1px solid var(--rule); border-radius: 12px; padding: 18px;
  box-shadow: 0 24px 48px -24px rgba(21, 18, 31, .35); display: grid; gap: 12px; font-size: var(--t-s);
}
.consent[hidden] { display: none; }
.consent p { color: var(--graphite); }

/* ---------- Home ---------- */
.home-stage .stage-canvas { aspect-ratio: 1 / 1; min-height: 320px; }
.home-stage h1 { font-size: clamp(2.4rem, 4.4vw, 3.9rem); }
.figures { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); border-top: 1px solid var(--rule); }
.figures > div { padding: 22px 0; display: grid; gap: 4px; }
.figures dt { font-size: var(--t-xs); color: var(--graphite); }
.figures dd { margin: 0; font-family: var(--font-mono); font-size: var(--t-m); }
.product-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 0 32px; }
.product-row a { display: grid; gap: 10px; align-content: start; padding-block: 24px; border-top: 2px solid var(--ink); color: var(--ink); text-decoration: none; }
.product-row a p { color: var(--graphite); font-size: var(--t-s); }
.product-row a:hover h3 { color: var(--violet); }

/* ---------- Responsive ---------- */
@media (max-width: 1100px) {
  .site-header .wrap { gap: 16px; }
  .nav-link { padding: 9px 9px; }
}
@media (max-width: 980px) {
  .nav { display: none; }
  .menu-toggle { display: inline-flex; }
  .site-header.menu-open .nav {
    display: grid; align-content: start; position: absolute; top: 100%; left: 0; right: 0; padding: 8px var(--gutter) 24px;
    background: var(--paper); border-bottom: 1px solid var(--rule); max-height: calc(100vh - var(--header-h)); max-height: calc(100dvh - var(--header-h)); overflow: auto;
    box-shadow: 0 24px 40px -28px rgba(21, 18, 31, .35);
  }
  .site-header.menu-open .nav > ul { display: grid; }
  .nav-item { border-bottom: 1px solid var(--rule); }
  .nav-link { width: 100%; justify-content: space-between; padding: 14px 4px; font-size: var(--t-m); }
  .nav-link:hover, .nav-item.open > .nav-link { background: none; }
  .mega { position: static; min-width: 0; box-shadow: none; border: 0; padding: 0 0 10px; grid-template-columns: 1fr; }
  .mega a { padding: 9px 8px; }
  .header-cta { margin: 16px 0 0; justify-self: start; }
  body:has(.site-header.menu-open) .wa-float { display: none; }
  .stage .wrap, .stage.compact .wrap { grid-template-columns: minmax(0, 1fr); gap: 0; min-height: 0; padding-block: 0 28px; }
  .stage-canvas, .stage.compact .stage-canvas {
    order: -1; aspect-ratio: auto; height: clamp(250px, 56vw, 460px); min-height: 0; max-height: none; width: auto;
    margin-inline: calc(-1 * var(--gutter));
  }
  .stage.compact .stage-copy { padding-block: 4px 0; }
  .home-stage .stage-canvas { aspect-ratio: 4 / 3; min-height: 0; max-height: none; }
  .doc-section { grid-template-columns: minmax(0, 1fr); }
  .doc-section > header { position: static; }
  .doc-section > header p { max-width: 36.68em; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .footer-about { grid-column: 1 / -1; }
  .cta-band { grid-template-columns: minmax(0, 1fr); }
  .index-row, .no-meta .index-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) 18px; }
  .index-row .ix-meta { grid-column: 1 / 3; grid-row: 2; text-align: left; }
  .index-row .ix-meta:empty { display: none; }
  .index-row .ix-go { grid-column: 3; grid-row: 1; }
}
@media (max-width: 640px) {
  .stage-canvas, .stage.compact .stage-canvas { height: clamp(250px, 72vw, 320px); }
  .stage-copy { gap: 14px; }
  .stage-copy .lede { font-size: var(--t-m); }
  .stage h1, .stage h1.h1-m { font-size: clamp(2rem, 9vw, 2.5rem); }
  .stage h1.h1-l { font-size: clamp(1.75rem, 7.6vw, 2.125rem); }
  .stage h1.h1-xl { font-size: clamp(1.625rem, 7vw, 1.9rem); }
  .index-row, .no-meta .index-row { grid-template-columns: minmax(0, 1fr) 14px; gap: 6px 12px; padding-block: 16px; }
  .index-row .ix-sum, .index-row .ix-meta { grid-column: 1; grid-row: auto; }
  .index-row .ix-go { grid-column: 2; grid-row: 1; }
  .az-group { grid-template-columns: minmax(0, 1fr); }
  .az-letter { padding-top: 10px; }
  /* Pin the row label while the rest of the table scrolls inside its frame. */
  .table-wrap tbody th[scope="row"], .table-wrap thead th:first-child { position: sticky; left: 0; z-index: 1; background: var(--paper); box-shadow: 1px 0 0 var(--rule); }
  .table-wrap thead th:first-child { background: var(--floor); }
  .table-wrap tbody th[scope="row"] { min-width: 120px; max-width: 150px; }
  th, td { padding: 10px 12px; }
}
@media (max-width: 560px) {
  .form { grid-template-columns: minmax(0, 1fr); }
  .specs dl { grid-template-columns: minmax(0, 1fr); }
  .specs dd { border-top: 0; padding-top: 0; }
  .doc-section > header h2, .index-head h2 { font-size: 1.5rem; }
  .footer-meta { flex-direction: column; }
  /* WhatsApp shrinks to a 48px button, and the page leaves room for it at the end. */
  .wa-float span { display: none; }
  .wa-float { padding: 0; width: 48px; height: 48px; justify-content: center; right: 14px; bottom: calc(14px + env(safe-area-inset-bottom, 0px)); }
  .site-footer { padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px)); }
  .consent { left: 10px; right: 10px; bottom: calc(10px + env(safe-area-inset-bottom, 0px)); max-width: none; padding: 16px; }
  body:has(.consent:not([hidden])) .wa-float { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
.linklike { background: none; border: 0; padding: 0; font: inherit; color: var(--graphite); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.linklike:hover { color: var(--violet); }

/* Home: verbatim Google review quotes */
.review-band { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: 20px; align-items: start; }
.review-band .quote blockquote { font-size: var(--t-m); }
.review-band .quote figcaption a { color: var(--violet); }
.review-source { grid-column: 2; font-size: var(--t-s); }
@media (max-width: 980px) { .review-source { grid-column: auto; } }

/* ---------- QA pass r3 ---------- */
.nw, .nowrap { white-space: nowrap; }

/* Inline render figures: a small 3D canvas in a section's heading column,
   captioned like a figure in an engineering document. */
.render-fig { margin: 14px 0 0; display: grid; gap: 8px; }
.render-canvas { position: relative; display: block; width: 100%; height: clamp(220px, 22vw, 300px); border: 1px solid var(--rule); border-radius: 10px; background: linear-gradient(to bottom, var(--paper) 55%, var(--floor)); overflow: hidden; }
.render-canvas canvas { position: absolute; inset: 0; width: 100% !important; height: 100% !important; }
.render-fig figcaption { font-family: var(--font-mono); font-size: .75rem; line-height: 1.45; color: var(--mist); max-width: 40ch; }
.render-fig figcaption span { color: var(--violet); margin-right: 6px; }
@media (max-width: 980px) {
  .render-fig { margin-top: 6px; max-width: 560px; }
  .render-canvas { height: clamp(200px, 52vw, 280px); }
}

/* Home product cards: a small render on each card, and one badge line for all. */
.product-row a { gap: 8px; }
.product-row .card-render { height: 190px; border: 0; border-radius: 0; margin: -8px 0 6px; background: linear-gradient(to bottom, var(--paper) 50%, var(--floor)); }
.product-row .status, .product-row .tag { min-height: 1.3em; }
.tag { display: inline-flex; align-items: center; font-family: var(--font-mono); font-size: var(--t-xs); color: var(--graphite); line-height: 1.3; }
.points.three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 760px) { .points.three { grid-template-columns: minmax(0, 1fr); } }
.home-steps { margin-top: 20px; }
.section-links { display: flex; flex-wrap: wrap; gap: 8px 24px; margin-top: 18px; font-size: var(--t-s); font-weight: 600; }

/* Capabilities grid where each item opens its feature page. */
.cap-grid .point h3 a { color: var(--ink); text-decoration: none; display: inline-flex; align-items: center; gap: 10px; }
.cap-grid .point h3 a:hover { color: var(--violet); }
.cap-grid .point h3 .ix-go { width: 7px; height: 7px; }
.cap-grid .point h3 a:hover .ix-go { color: var(--violet); transform: translateX(3px) rotate(45deg); }

/* Mega menu: every title and note pair sits at the top of its cell. */
.mega { align-items: start; }
.mega a { align-content: start; }

/* Inner page heroes: the copy column is top aligned, so the breadcrumb sits
   at the same height on every content and listing page. */
.stage.compact .wrap { align-items: stretch; }
.stage.compact .stage-copy { align-self: start; align-content: start; padding-top: 28px; }
.stage.short-stage .wrap { min-height: clamp(340px, 42vh, 420px); }
.stage.short-stage .stage-canvas { min-height: clamp(300px, 38vh, 380px); }

/* Leave room for the floating WhatsApp button at the end of a page. */
.site-footer { padding-bottom: 88px; }
.index-doc { padding-bottom: clamp(64px, 7vw, 104px); }

/* Case study rows: a framed capture of the client's live site. */
.index-row.has-shot { grid-template-columns: 220px minmax(0, 3fr) minmax(0, 6fr) 18px; align-items: start; }
.index-row.has-shot .ix-meta { display: none; }
.ix-shot { display: grid; border: 1px solid var(--rule-strong); border-radius: 8px; overflow: hidden; background: var(--paper); box-shadow: 0 18px 30px -24px rgba(21, 18, 31, .45); }
.ix-shot-bar { display: flex; align-items: center; gap: 4px; padding: 5px 8px; background: var(--floor); border-bottom: 1px solid var(--rule); }
.ix-shot-bar i { width: 6px; height: 6px; border-radius: 50%; background: var(--rule-strong); }
.ix-shot-bar span { font-family: var(--font-mono); font-size: .625rem; color: var(--mist); margin-left: 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ix-shot img { width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover; object-position: top; }

@media (max-width: 980px) {
  .stage.compact .stage-copy { padding-top: 4px; }
  .index-row.has-shot { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) 18px; }
  .index-row.has-shot .ix-shot { grid-column: 1 / 3; max-width: 420px; }
}
@media (max-width: 640px) {
  .index-row.has-shot { grid-template-columns: minmax(0, 1fr) 14px; }
  .index-row.has-shot .ix-shot { grid-column: 1; }
  /* The hero canvas sits flush under the header on phones: no extra band above it. */
  .stage .wrap, .stage.compact .wrap { padding-top: 0; }
}
@media (max-width: 600px) {
  .figures { grid-template-columns: 1fr 1fr; column-gap: 16px; }
  .figures > div { padding: 14px 0; gap: 2px; border-bottom: 1px solid var(--rule); }
  .figures > div:last-child { grid-column: 1 / -1; border-bottom: 0; }
}
/* Contact: on phones and small tablets the form comes first, not a decorative render. */
@media (max-width: 767px) {
  .contact-stage .stage-canvas { display: none; }
  .contact-stage .wrap { padding-top: 20px; }
}
@media (max-width: 560px) {
  .site-footer { padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px)); }
}
.wa-float { transition: opacity .2s, transform .2s; }
.wa-float.is-away { opacity: 0; transform: translateY(16px); pointer-events: none; visibility: hidden; transition: opacity .2s, transform .2s, visibility 0s .2s; }
@media (max-width: 640px) {
  /* A slightly shorter hero canvas on phones keeps the title nearer the top. */
  .stage-canvas, .stage.compact .stage-canvas { height: clamp(236px, 66vw, 300px); }
}

/* ---------- QA pass r5 ---------- */
/* WhatsApp: a round icon button at every width (48px, 44px on wide screens).
   Pinned 8px from the edge it sits in the page margin at 1280px and wider,
   clear of the content column. */
.wa-float { padding: 0; width: 48px; height: 48px; justify-content: center; right: 12px; bottom: calc(16px + env(safe-area-inset-bottom, 0px)); }
.wa-float span { display: none; }
.wa-float svg { width: 22px; height: 22px; }
@media (min-width: 1100px) { .wa-float { width: 44px; height: 44px; right: 8px; } .wa-float svg { width: 20px; height: 20px; } }

/* Quotes: one size everywhere (the home review cards set it). Two quotes in a
   row read as one block, with no section rule between them. */
.quote blockquote { font-size: var(--t-m); line-height: 1.6; letter-spacing: 0; white-space: pre-line; }
.doc-section.kind-quote + .doc-section.kind-quote { border-top: 0; padding-top: 0; }

/* The FAQ already closes on a rule, so the section after it does not add a second one. */
#faq + .doc-section { border-top-color: transparent; }

/* Footer bottom links: a 24px tall target. */
.footer-meta .social a, .footer-meta .linklike { display: inline-flex; align-items: center; min-height: 24px; }

/* Inline field errors on forms (set by site.js). */
.field-error { font-size: var(--t-xs); color: #b42318; margin: 0; }

@media (max-width: 980px) {
  /* Mobile menu: items align with the 16px gutter, the page behind is dimmed
     and does not scroll, and a tap on the dimmed page closes the menu. */
  .nav-link { padding-inline: 0; }
  .mega a { padding-inline: 0; }
  .mega .mega-all { padding-inline: 0; }
  html:has(.site-header.menu-open), html:has(.site-header.menu-open) body { overflow: hidden; }
  body:has(.site-header.menu-open)::after {
    content: ""; position: fixed; inset: 0; z-index: 45; background: rgba(21, 18, 31, .38);
  }
}
@media (max-width: 767px) {
  /* Related pages on phones: titles only, so the end of a long page stays short. */
  #related .link-list a span { display: none; }
  #related .link-list a { padding-block: 12px; }
}
@media (max-width: 600px) {
  /* Two column tables fit a phone without scrolling sideways. */
  table.cols-2 { min-width: 0; }
  /* Comparison tables (three or more text columns) stack: one card per row,
     the row label on top, then each option as "label: value". */
  .table-wrap.stack { overflow: visible; border: 0; border-radius: 0; }
  table.stack { min-width: 0; }
  table.stack thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  table.stack, table.stack tbody { display: block; }
  table.stack tbody tr { display: block; border: 1px solid var(--rule); border-radius: 10px; overflow: hidden; }
  table.stack tbody tr + tr { margin-top: 12px; }
  table.stack tbody th[scope="row"] { display: block; position: static; min-width: 0; max-width: none; box-shadow: none; background: var(--floor); border: 0; border-bottom: 1px solid var(--rule); }
  table.stack td { display: block; border: 0; border-top: 1px solid var(--rule); }
  table.stack th[scope="row"] + td { border-top: 0; }
  table.stack td[data-label]::before { content: attr(data-label); display: block; font-family: var(--font-mono); font-size: var(--t-xs); color: var(--mist); margin-bottom: 2px; }
  table.stack td.num { text-align: left; }
}
/* Fields in one form row keep their inputs level when only one shows an error. */
.form .field { align-content: start; }

/* ---------- Posters (r6) ---------- */
/* Every render stage opens on its poster (public/img/render, made by npm run
   posters). The poster is scaled and centred so the subject fills the scene's
   own `fill` of the canvas width or `fillH` of its height, whichever binds
   (the same rule the live camera fit uses), with the narrow-canvas fill below
   600px. The inline vars come from the poster manifest: --sw/--sh are the
   subject's size as a fraction of the 16:9 frame, --fw/--fh (--fwm/--fhm
   narrow) the fill the scene wants. scene-gl.js maps the live camera onto
   this same box, so the live canvas fades in exactly over the poster. */
.stage-canvas, .render-canvas { container-type: size; overflow: hidden; }
.stage-canvas .poster, .render-canvas .poster {
  position: absolute; left: 50%; top: 50%; width: 100%; height: auto; max-width: none;
  transform: translate(-50%, -50%); pointer-events: none; user-select: none;
}
@supports (width: 1cqw) {
  .stage-canvas .poster, .render-canvas .poster {
    --kw: var(--fw); --kh: var(--fh);
    width: min(calc(var(--kw) / var(--sw) * 100cqw), calc(var(--kh) / var(--sh) * 177.7778cqh));
  }
  @container (max-width: 599px) {
    .stage-canvas .poster, .render-canvas .poster { --kw: var(--fwm); --kh: var(--fhm); }
  }
}
.stage-canvas canvas.live, .render-canvas canvas.live { opacity: 0; transition: opacity .6s ease; }
.stage-canvas[data-ready] canvas.live, .render-canvas[data-ready] canvas.live { opacity: 1; }
.stage-canvas[data-done] .poster, .render-canvas[data-done] .poster { visibility: hidden; }

/* ---- Glance layer: icon, title and one line first; the full text behind
   "Read more" (still in the page for search engines and screen readers). ---- */
.ic { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; flex: none; }
.glance-lead { font-size: var(--t-l); line-height: 1.45; color: var(--ink); max-width: 34em; margin: 0; }
.glance-lead a { color: var(--violet); }

details.more { margin-top: 2px; }
details.more > summary { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; list-style: none; color: var(--violet); font-size: var(--t-s); font-weight: 600; padding: 4px 0; border-radius: 4px; }
details.more > summary::-webkit-details-marker { display: none; }
details.more > summary::after { content: ""; width: 7px; height: 7px; border-right: 1.6px solid currentColor; border-bottom: 1.6px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform .2s ease; }
details.more[open] > summary::after { transform: translateY(1px) rotate(-135deg); }
details.more > summary:hover { color: var(--violet-deep); }
details.more > .prose { margin-top: 8px; color: var(--graphite); font-size: var(--t-s); }
.glance-lead + details.more > .prose { font-size: var(--t-m); }
details.more[open] > .prose { animation: more-in .28s ease both; }
@keyframes more-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

.glance-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr)); gap: 16px; }
.glance-grid.even { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.gcard { position: relative; display: grid; gap: 10px; align-content: start; padding: 20px; border: 1px solid var(--rule); border-radius: 10px; background: var(--paper); }
.gcard h3 { font-size: var(--t-m); font-weight: 650; line-height: 1.3; }
.gcard h3 a { color: var(--ink); text-decoration: none; display: inline-flex; align-items: center; gap: 10px; }
.gcard h3 a::before { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.gcard.has-link:hover { border-color: var(--violet); }
.gcard.has-link:hover h3 a { color: var(--violet); }
.gcard h3 .ix-go { width: 7px; height: 7px; }
.gcard.has-link details.more { position: relative; z-index: 1; }
.gcard-line { margin: 0; color: var(--graphite); font-size: var(--t-s); line-height: 1.5; }
.gcard-ic { width: 46px; height: 46px; display: grid; place-items: center; border-radius: 12px; background: var(--violet-wash); color: var(--violet); }
.gcard-n { font-family: var(--font-mono); font-size: var(--t-s); }

.timeline { list-style: none; margin: 0; padding: 0; position: relative; display: grid; }
.timeline::before, .timeline::after { content: ""; position: absolute; left: 22px; top: 23px; bottom: 23px; width: 2px; background: var(--rule); }
.timeline::after { background: var(--violet); transform-origin: top; transform: scaleY(var(--fill, 1)); }
.tstep { position: relative; display: grid; grid-template-columns: 46px minmax(0, 1fr); gap: 18px; padding-bottom: 26px; }
.tstep:last-child { padding-bottom: 0; }
.tnode { position: relative; z-index: 1; width: 46px; height: 46px; display: grid; place-items: center; border-radius: 50%; border: 2px solid var(--violet); background: var(--violet-wash); color: var(--violet); font-family: var(--font-mono); font-size: var(--t-s); }
.tbody { display: grid; gap: 6px; align-content: start; padding-top: 10px; }
.tbody h3 { font-size: var(--t-m); font-weight: 650; }
.tnum { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--violet); margin-right: 4px; }

/* Motion (html.anim is set by site.js only when IntersectionObserver exists
   and the visitor has not asked for reduced motion). */
.anim .gcard-ic .ic, .anim .tnode .ic { stroke-dasharray: 70; stroke-dashoffset: 0; }
.anim .gcard:not(.in) .gcard-ic .ic, .anim .tstep:not(.in) .tnode .ic { stroke-dashoffset: 70; }
.anim .gcard .gcard-ic .ic, .anim .tstep .tnode .ic { transition: stroke-dashoffset 1.1s cubic-bezier(.6, 0, .2, 1) var(--d, 0s); }
.anim .gcard-ic { transition: transform .5s cubic-bezier(.2, .8, .2, 1) var(--d, 0s), background-color .3s; }
.anim .gcard:not(.in) .gcard-ic { transform: scale(.7); }
.anim .tstep .tnode { transition: background-color .4s, border-color .4s, color .4s; }
.anim .tstep:not(.in) .tnode { background: var(--paper); border-color: var(--rule-strong); color: var(--mist); }
.anim .gcard.has-link:hover .gcard-ic { background: var(--violet); color: #fff; }
.anim .timeline::after { transition: transform .15s linear; }

@media (max-width: 760px) {
  .glance-grid.even { grid-template-columns: minmax(0, 1fr); }
  .glance-lead { font-size: var(--t-m); }
}

/* Glance sections stack (heading above, content full width) unless they
   carry a figure, which keeps the two column layout beside it. */
.doc-section.glance:not(.has-fig) { grid-template-columns: minmax(0, 1fr); gap: 18px; }
.doc-section.glance:not(.has-fig) > header { position: static; max-width: 46em; }
.doc-section.glance:not(.has-fig) > header p { max-width: 40em; }

/* Tiles: listings, related pages, child pages. Icon, title, one short note. */
.tile-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 230px), 1fr)); gap: 14px; }
.tile-grid > li { display: grid; }
.tile { display: grid; grid-template-rows: auto auto 1fr auto; gap: 8px; align-content: start; padding: 18px; border: 1px solid var(--rule); border-radius: 10px; background: var(--paper); color: var(--ink); text-decoration: none; transition: border-color .2s, transform .2s, box-shadow .2s; }
.tile strong { font-size: var(--t-m); font-weight: 650; line-height: 1.3; }
.tile-note { color: var(--graphite); font-size: var(--t-s); line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.tile-meta { font-family: var(--font-mono); font-size: var(--t-xs); color: var(--mist); }
.tile-ic { width: 42px; height: 42px; display: grid; place-items: center; border-radius: 11px; background: var(--violet-wash); color: var(--violet); margin-bottom: 4px; transition: background-color .2s, color .2s; }
.tile:hover { border-color: var(--violet); transform: translateY(-2px); box-shadow: 0 14px 28px -22px rgba(67, 32, 163, .55); }
.tile:hover strong { color: var(--violet); }
.tile:hover .tile-ic { background: var(--violet); color: #fff; }
.tile:focus-visible { outline-offset: 2px; }
.tile.has-shot .ix-shot { margin: -18px -18px 6px; border: 0; border-bottom: 1px solid var(--rule); border-radius: 10px 10px 0 0; box-shadow: none; }
.listing .tile-grid, .tile-grid.wide { grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); }
.glance-row { display: flex; align-items: flex-start; gap: 16px; }
.glance-row .gcard-ic { margin-top: 2px; }
.glance-row + details.more { margin-left: 0; }
.glance-row:has(.gcard-ic) + details.more { margin-left: 62px; }
.doc-section.glance .faq { max-width: 860px; }
.doc-section.glance.kind-specs .specs { max-width: 860px; }

@media (max-width: 760px) {
  /* Phones: a card is a compact row (icon left, words right), so a section
     of five reads in one screen instead of five. */
  .gcard { grid-template-columns: 42px minmax(0, 1fr); column-gap: 14px; row-gap: 4px; padding: 14px 16px; border-radius: 9px; }
  .gcard > .gcard-ic { grid-row: 1 / span 3; width: 42px; height: 42px; border-radius: 11px; }
  .gcard > :not(.gcard-ic) { grid-column: 2; }
  .glance-grid { gap: 10px; }
  .tile-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .tile { padding: 14px; gap: 6px; }
  .tile .tile-ic { width: 36px; height: 36px; border-radius: 10px; }
  .tile strong { font-size: var(--t-s); }
  .tile-note { font-size: var(--t-xs); }
  .tile.has-shot .ix-shot { margin: -14px -14px 4px; }
  .glance-row:has(.gcard-ic) + details.more { margin-left: 0; }
}
/* Home: product cards and the review link in the stacked (glance) layout. */
.glance .product-row { gap: 16px; }
.glance .product-row a { border: 1px solid var(--rule); border-radius: 10px; padding: 18px; transition: border-color .2s, transform .2s, box-shadow .2s; }
.glance .product-row a:hover { border-color: var(--violet); transform: translateY(-2px); box-shadow: 0 14px 28px -22px rgba(67, 32, 163, .55); }
.glance .product-row .card-render { margin: -10px -10px 4px; }
.glance .review-source { grid-column: auto; }
.home-timeline { margin-top: 22px; }
.table-wrap.clipped tbody tr:nth-child(n+4) { display: none; }
.specs.clipped dt:nth-of-type(n+4), .specs.clipped dd:nth-of-type(n+4) { display: none; }
.table-wrap.clipped, .specs.clipped { -webkit-mask-image: linear-gradient(to bottom, #000 75%, transparent); mask-image: linear-gradient(to bottom, #000 75%, transparent); }
.show-all { margin-top: 10px; background: var(--paper); border: 1px solid var(--rule-strong); border-radius: 999px; padding: 7px 16px; font: inherit; font-size: var(--t-s); font-weight: 600; color: var(--violet); cursor: pointer; }
.show-all:hover { border-color: var(--violet); }
