/* ==========================================================================
   EMH — visual system
   Direction: "black velvet with violet neon"
   Pure black canvas. Hairline graphite borders instead of shadows.
   Roboto Medium for every headline, Inter for prose, JetBrains Mono for
   machine truth. Violet is punctuation — labels, step numbers, the light on
   the cube — never a painted surface.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
  /* Neutrals */
  --black:      #000000;   /* page canvas + card surfaces. never off-black */
  --hairline:   #292d30;   /* THE structural line. 1px. defines every layer */
  --charcoal:   #737880;   /* inline code, muted labels — 4.7:1 on black, the floor for 11–12px text */
  --iron:       #7e838b;   /* subtle strokes, disabled — kept a step above charcoal */
  --ash:        #a1a4a5;   /* badge labels, icon strokes */
  --smoke:      #abafb4;   /* links, inactive button text */
  --bone:       #f0f0f0;   /* body text, secondary headings */
  --white:      #ffffff;   /* primary headings, hero */

  /* Brand + accents. Violet is punctuation, not paint. */
  --iris:       #9281f7;
  --iris-glow:  #baa7ff;
  --iris-grad:  linear-gradient(to right bottom in oklab, rgb(146,129,247) 0%, rgb(154,84,220) 100%);
  --signal:     #3b9eff;
  --sky:        #70b8ff;
  --pulse:      #3ad389;
  --alarm:      #ff9592;

  /* Surfaces */
  --surface:    linear-gradient(rgb(27,27,27), rgb(3,3,3));

  /* Type */
  --font-sans:    'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --font-display: 'Roboto', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
  --font-mono:    'JetBrains Mono', 'Commit Mono', 'Berkeley Mono', 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Rhythm — 4px base */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px; --s5: 20px;
  --s6: 24px; --s7: 28px; --s8: 32px; --s10: 40px; --s12: 48px;
  --s16: 64px; --s20: 80px; --s24: 96px; --s26: 104px; --s36: 144px;

  /* Reference layout: a 1280px centred column with a 24px gutter — measured
     off resend.com (mx-auto max-w-5xl px-6). The page reads full-screen
     because the hero is viewport-height and the glow bleeds edge to edge,
     not because the content stretches. */
  --max: 1280px;
  --gutter: clamp(20px, 2.4vw, 24px);
  --section: clamp(80px, 9vw, 120px);

  /* Shape — 6px for controls, 16px cards, 24px large panels. Never mixed. */
  --r-control: 6px;
  --r-card: 16px;
  --r-panel: 24px;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --t: 150ms var(--ease);
}

/* --------------------------------------------------------------------------
   2. Reset
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 88px;
}

body {
  background: var(--black);
  color: var(--bone);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.5;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: 'cv02','cv03','cv04','cv11';
  overflow-x: hidden;
}

img, svg { display: block; max-width: 100%; }
a { color: var(--smoke); text-decoration: none; transition: color var(--t); }
a:hover { color: var(--white); }
button, input, textarea, select { font: inherit; color: inherit; }
ul, ol { list-style: none; }

:focus-visible {
  outline: 2px solid var(--iris);
  outline-offset: 2px;
  border-radius: var(--r-control);
}

::selection { background: rgba(146,129,247,0.3); color: var(--white); }

/* --------------------------------------------------------------------------
   3. Type scale
   -------------------------------------------------------------------------- */
.display {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(40px, 6.7vw, 78px);
  line-height: 1.02;
  letter-spacing: -0.032em;
  color: var(--white);
}

/* Roboto Medium in every headline. A grotesque at display size needs the
   tightening a serif refuses — without the negative tracking these read like
   a system dialog, not a headline. */
.h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(32px, 4.8vw, 55px);
  line-height: 1.1;
  letter-spacing: -0.026em;
  color: var(--white);
}

/* Two-tone headline, monochrome: the second half steps down to smoke.
   No gold anywhere on the site. */
.h2 .accent { color: var(--smoke); }

/* The display face runs at every heading level, not just the big ones — the
   small step headings on /contact included. Roboto carries weight 500 here so
   these hold against Inter body copy set at 400. */
.h3 {
  font-family: var(--font-display);
  font-size: 21px;
  line-height: 1.3;
  font-weight: 500;
  letter-spacing: -0.016em;
  color: var(--white);
}

.h4 { font-family: var(--font-display); font-size: 17px; font-weight: 500; color: var(--white); letter-spacing: -0.011em; line-height: 1.35; }

.lede {
  font-size: clamp(16px, 1.4vw, 18px);
  line-height: 1.6;
  color: var(--smoke);
  max-width: 60ch;
}

.body-sm { font-size: 14px; line-height: 1.43; color: var(--smoke); }

.mono {
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.33;
  letter-spacing: 0.025em;
  color: var(--ash);
  text-transform: uppercase;
}

.mono-lc { text-transform: none; letter-spacing: 0; }
.iris { color: var(--iris); }

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

.section { padding-block: var(--section); }
.section--tight { padding-block: var(--s16); }
.section + .section { padding-top: 0; }

.page { position: relative; z-index: 1; }

/* Two fixed layers beneath .page (z-index 1): an ambient violet lift, and the
   mesh on top of it. Fixed, so neither scrolls with the content nor ever shows
   a tile seam. Same z-index, so paint order decides — ::before first, ::after
   over it — and .page keeps every bit of copy above both.

   The lift is why the mesh now reads the whole way down. On its own the mesh
   was violet at a few per cent over pure #000, which resolves to about
   rgb(8,7,14) — visible only inside the hero, where .hero-glow happened to be
   raising the ground under it. Everywhere else the page was flat black and the
   mesh had nothing to sit against. Lifting the canvas first, then laying the
   mesh over it, gives the same reading at the top of the page and at the
   bottom of the footer. Static SVG and two gradients: no canvas, no rAF. */
body::before,
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
body::before {
  background:
    radial-gradient(120vw 90vh at 76% 4%,  rgba(146,129,247,0.058), transparent 62%),
    radial-gradient(105vw 85vh at 8%  96%, rgba(146,129,247,0.042), transparent 64%),
    radial-gradient(90vw  70vh at 96% 62%, rgba(146,129,247,0.030), transparent 66%);
}
body::after {
  background: url('../img/mesh.svg') center / cover no-repeat;
  opacity: 0.09;
}
/* Texture, not information. Anyone who has asked for less of it gets none. */
@media (prefers-reduced-transparency: reduce) {
  body::before, body::after { display: none; }
}

.section-head {
  max-width: 62ch;
  margin-inline: auto;
  margin-bottom: var(--s16);
  text-align: center;
}
/* The violet tile that used to sit above these labels is gone, so the label
   itself has to hold the top of the section: a size up, wider tracking, and
   the accent moved into it rather than lost with the tile. */
.section-head .mono {
  display: block;
  margin-bottom: var(--s5);
  font-size: 13px;
  letter-spacing: 0.15em;
  color: var(--iris-glow);
}
.section-head .lede { margin-inline: auto; }
.section-head .h2 + .lede { margin-top: var(--s5); }

/* Page heads and the hero stay left-aligned — the contrast with the centred
   section heads is what gives the page its hierarchy. */
.page-head .crumb, .page-head .lede { text-align: left; }

/* Section heads come in two shapes. Centred is the default. --left is for a
   section that continues into a rail or a second column, where a centred head
   would float above it. Alternating the two down the page is what gives it a
   rhythm instead of the same block six times over. */
.section-head--left { text-align: left; margin-inline: 0; }
.section-head--left .lede { margin-inline: 0; }

/* FAQ as two columns: the head holds the left while the questions run down the
   right, and stays in view while they do. */
.faq-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
  gap: var(--s12);
  align-items: start;
}
.faq-grid .section-head { margin-bottom: 0; position: sticky; top: 96px; }
@media (max-width: 900px) {
  .faq-grid { grid-template-columns: 1fr; gap: var(--s8); }
  .faq-grid .section-head { position: static; }
}

.rule { height: 1px; background: var(--hairline); border: 0; }

.grid { display: grid; gap: var(--s4); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) {
  .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------------
   5. Controls
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s3) var(--s4);
  height: 40px;
  border: 1px solid var(--hairline);
  border-radius: var(--r-control);
  background: transparent;
  color: var(--white);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.01em;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color var(--t), background var(--t), color var(--t);
}
.btn:hover { border-color: rgba(255,255,255,0.45); color: var(--white); }
.btn:active { background: rgba(255,255,255,0.04); }
.consent .btn:disabled { opacity: 0.5; cursor: not-allowed; }

.btn--lg { height: 48px; padding-inline: var(--s5); font-size: 15px; }

/* Exactly one solid button per view — the primary conversion. */
.btn--solid {
  background: var(--white);
  color: var(--black);
  border-color: var(--white);
}
.btn--solid:hover { background: var(--bone); border-color: var(--bone); color: var(--black); }

.btn--quiet { border-color: transparent; color: var(--smoke); }
.btn--quiet:hover { border-color: var(--hairline); color: var(--white); }

.btn .arrow { transition: transform var(--t); }
.btn:hover .arrow { transform: translateX(2px); }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  color: var(--smoke);
  font-weight: 500;
}
.link-arrow:hover { color: var(--white); }
.link-arrow svg { transition: transform var(--t); }
.link-arrow:hover svg { transform: translateX(3px); }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px var(--s2);
  border: 1px solid var(--hairline);
  border-radius: var(--r-control);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--ash);
  text-transform: uppercase;
  background: var(--black);
}

.dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  flex: none;
  background: var(--pulse);
}
.dot--blue { background: var(--signal); }
.dot--iris { background: var(--iris); }
.dot--red { background: var(--alarm); }
.dot--live { box-shadow: 0 0 0 0 rgba(58,211,137,0.6); animation: pulse 2.4s var(--ease) infinite; }
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(58,211,137,0.5); }
  70%  { box-shadow: 0 0 0 6px rgba(58,211,137,0); }
  100% { box-shadow: 0 0 0 0 rgba(58,211,137,0); }
}

/* --------------------------------------------------------------------------
   6. Header
   -------------------------------------------------------------------------- */
.header {
  position: sticky;
  top: 0;
  z-index: 50;
  border-bottom: 1px solid transparent;
  background: rgba(0,0,0,0.72);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  transition: border-color var(--t), background var(--t);
}
.header.is-stuck { border-bottom-color: var(--hairline); }

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s6);
  height: 64px;
}

/* The wordmark is the logo — no monogram. Size and tracking carry it. */
.brand {
  display: inline-flex;
  align-items: center;
  color: var(--white);
  font-weight: 600;
  font-size: 24px;
  line-height: 1;
  letter-spacing: 0.055em;
  padding-right: 0.055em;   /* balances the trailing letter-space */
}
.brand:hover { color: var(--white); }
.footer .brand { font-size: 21px; }
@media (max-width: 620px) { .brand { font-size: 21px; } }

.nav { display: flex; align-items: center; gap: var(--s5); }
.nav a {
  font-size: 14px;
  font-weight: 400;
  color: var(--bone);
  position: relative;
  padding-block: 4px;
}
.nav a::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--white);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t);
}
.nav a:hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); }
.nav a[aria-current="page"] { color: var(--white); }

.header-actions { display: flex; align-items: center; gap: var(--s3); }

/* Language switch */
.lang {
  display: inline-flex;
  border: 1px solid var(--hairline);
  border-radius: var(--r-control);
  overflow: hidden;
  height: 30px;
}
.lang button {
  border: 0;
  background: transparent;
  color: var(--charcoal);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  padding-inline: var(--s2);
  cursor: pointer;
  transition: color var(--t), background var(--t);
}
.lang button:hover { color: var(--bone); }
.lang button[aria-pressed="true"] { color: var(--white); background: rgba(255,255,255,0.07); }
.lang button + button { border-left: 1px solid var(--hairline); }

/* Mobile menu */
.burger { display: none; width: 36px; height: 36px; align-items: center; justify-content: center;
  border: 1px solid var(--hairline); border-radius: var(--r-control); background: transparent; cursor: pointer; }
.burger span { display: block; width: 14px; height: 1px; background: var(--bone); position: relative; transition: background var(--t); }
.burger span::before, .burger span::after { content: ''; position: absolute; left: 0; width: 14px; height: 1px; background: var(--bone); transition: transform var(--t); }
.burger span::before { top: -4px; }
.burger span::after { top: 4px; }
.burger[aria-expanded="true"] span { background: transparent; }
.burger[aria-expanded="true"] span::before { transform: translateY(4px) rotate(45deg); }
.burger[aria-expanded="true"] span::after { transform: translateY(-4px) rotate(-45deg); }

.mobile-nav {
  display: none;
  border-top: 1px solid var(--hairline);
  background: var(--black);
  padding: var(--s4) 0 var(--s6);
}
.mobile-nav.is-open { display: block; }
/* :not(.btn) keeps the link styling off the CTA — otherwise it would
   override .btn--solid's black-on-white and render invisible. */
.mobile-nav a:not(.btn) {
  display: block;
  padding: var(--s3) 0;
  font-size: 18px;
  color: var(--bone);
  letter-spacing: -0.02em;
  border-bottom: 1px solid var(--hairline);
}
/* The contact page drops the CTA (it would link to itself), so there the last
   nav link ends the panel and its rule would run out into the page. */
.mobile-nav a:not(.btn):last-child { border-bottom: 0; }
.mobile-nav .btn { margin-top: var(--s5); width: 100%; justify-content: center; }

@media (max-width: 880px) {
  .nav, .header-actions .btn { display: none; }
  .burger { display: inline-flex; }
}

/* --------------------------------------------------------------------------
   7. Hero
   -------------------------------------------------------------------------- */
/* The hero fills the viewport and the light bleeds past the column — that,
   not a stretched content width, is what makes the page feel full-screen. */
.hero {
  position: relative;
  display: grid;
  align-items: center;
  padding-block: var(--s16) var(--s20);
  isolation: isolate;
}
@media (min-width: 768px) {
  .hero { min-height: calc(100svh - 64px); }
}
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: var(--s12);
  align-items: center;
  width: 100%;
}
@media (max-width: 980px) {
  .hero-grid { grid-template-columns: 1fr; gap: var(--s12); }
}

/* Atmosphere. Full-bleed, sits behind everything, never intercepts a click. */
.hero-glow {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}
.hero-glow i { position: absolute; display: block; }

/* key light, upper right, behind the object */
.hero-glow .glow-wash {
  top: -30%; right: -18%;
  width: 78vw; height: 110%;
  background:
    radial-gradient(closest-side at 62% 42%, rgba(146,129,247,0.13), transparent 72%),
    radial-gradient(closest-side at 48% 55%, rgba(180,190,210,0.07), transparent 70%);
  filter: blur(30px);
}
/* the low streak the scene throws across the floor */
.hero-glow .glow-streak {
  left: -12%; right: -12%; bottom: 20%;
  height: 2px;
  background: linear-gradient(90deg, transparent 4%, rgba(255,255,255,0.14) 26%,
              rgba(186,167,255,0.42) 52%, rgba(255,255,255,0.10) 74%, transparent 96%);
  filter: blur(2px);
  transform: rotate(-1.4deg);
}
/* soft floor bounce so the bottom edge isn't a hard cut */
.hero-glow .glow-floor {
  left: 10%; right: 0; bottom: 0;
  height: 42%;
  background: radial-gradient(ellipse at 62% 100%, rgba(146,129,247,0.09), transparent 66%);
  filter: blur(40px);
}
@media (max-width: 768px) {
  .hero-glow .glow-wash { width: 130vw; right: -30%; }
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--ash);
  text-transform: uppercase;
  margin-bottom: var(--s6);
}

.hero .display { margin-bottom: var(--s6); max-width: 14ch; }  /* 14ch keeps both EN and SR on two lines */
.hero .lede { margin-bottom: var(--s8); }
.hero-cta { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: center; }

.hero-meta {
  position: relative;
  z-index: 1;                    /* the 3D object must never paint over it */
  margin-top: var(--s10);
  padding-top: var(--s5);
  border-top: 1px solid var(--hairline);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s6) var(--s8);
}
.hero-meta div { display: flex; flex-direction: column; gap: 2px; }

/* Entrance. One choreographed sequence on load, in the hero only: headline,
   lede, buttons and meta rise in turn, the object settles in beside them and
   the meta rule draws itself. Everything below the fold simply appears —
   fading every block in as it scrolls past is what makes a page read as a
   template. */
@keyframes hero-rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes hero-object { from { opacity: 0; transform: translateY(26px) scale(0.965); } to { opacity: 1; transform: none; } }
@keyframes hero-draw { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.hero .display,
.hero .lede,
.hero .hero-cta,
.hero .hero-meta { animation: hero-rise 720ms var(--ease) both; }
.hero .display  { animation-delay: 40ms; }
.hero .lede     { animation-delay: 160ms; }
.hero .hero-cta { animation-delay: 260ms; }
.hero .hero-meta { animation-delay: 400ms; }
.hero .rubik-stage { animation: hero-object 960ms var(--ease) 220ms both; }
/* The rule is drawn, not shown: a pseudo-element in place of the border. */
.hero .hero-meta { border-top: 0; }
.hero .hero-meta::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1px;
  background: var(--hairline);
  transform-origin: left;
  animation: hero-draw 820ms var(--ease) 520ms both;
}
@media (prefers-reduced-motion: reduce) {
  .hero .display, .hero .lede, .hero .hero-cta, .hero .hero-meta,
  .hero .rubik-stage, .hero .hero-meta::before { animation: none; }
}
.hero-meta dt { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--charcoal); }
.hero-meta dd { font-size: 14px; color: var(--bone); }

/* --------------------------------------------------------------------------
   Hero object — interactive Rubik's cube
   Six faces, each a 3x3 grid of stickers, so from outside it reads exactly as
   a real 3x3 cube. Every sticker is black; the violet lives in the sheen
   along each lit edge and in the light behind the object, so it reads as a
   dark premium solid rather than a coloured toy. Mouse hover turns its layers;
   dragging rotates the whole cube and release snaps to a stable view.
   Touch interaction is bounded to the cube, leaving the page free to scroll.
   Pure CSS 3D — no
   canvas, no library. The 26 cubies are built by main.js.
   -------------------------------------------------------------------------- */
.hero-object {
  display: grid;
  gap: var(--s5);
  justify-items: center;
  width: 100%;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.rubik-stage {
  --size: clamp(190px, 21vw, 288px);
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 0.92;
  display: grid;
  place-items: center;
  perspective: 860px;
  perspective-origin: 50% 42%;
  touch-action: pan-y pinch-zoom;
}

/* An unrotated hit surface prevents gaps between 3D faces from losing touch.
   One finger rotates here; native pinch zoom and scrolling beside it remain.
   Do not apply touch-action:none to the full-width stage. */
.rubik-control {
  position: absolute;
  left: 50%; top: 50%;
  width: calc(var(--size) * 1.65);
  height: calc(var(--size) * 1.55);
  max-width: 90%;
  transform: translate(-50%, -50%);
  z-index: 1;
  appearance: none;
  -webkit-appearance: none;
  -webkit-touch-callout: none;
  background: transparent;
  border: 0;
  border-radius: 28px;
  padding: 0;
  cursor: grab;
  touch-action: pinch-zoom;
}
.rubik-control.is-dragging { cursor: grabbing; }
.rubik-control:focus-visible { outline: 2px solid var(--iris); outline-offset: 4px; }

/* Key light behind the object, and a floor for it to sit on. The cube was
   floating in flat black before — nothing reads as expensive when it has no
   ground. The pool is elliptical and sits behind the cube in z, so the contact
   shadow can bite into it. */
.rubik-stage::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    /* key light */
    radial-gradient(circle at 58% 36%, rgba(146,129,247,0.18), transparent 58%),
    /* floor: a wide, shallow pool the object stands in */
    radial-gradient(ellipse 62% 15% at 50% 82%, rgba(126,112,190,0.16), transparent 72%);
  filter: blur(42px);
  pointer-events: none;
}
.rubik-stage::after {
  content: '';
  position: absolute;
  bottom: 12%; left: 50%;
  width: 52%; height: 30px;
  transform: translateX(-50%);
  /* tight and dark at the base, so the contact point is legible */
  background: radial-gradient(ellipse at center, rgba(0,0,0,1), rgba(0,0,0,0.62) 38%, transparent 70%);
  filter: blur(11px);
  pointer-events: none;
}

.rubik {
  /* Must stay a pure length: cubie transforms divide it for translateZ, and
     translateZ() rejects percentages — a % here silently kills the whole
     transform and the cube collapses flat. vw is a length, % is not. */
  --cs: calc(var(--size) / 3);
  /* Zero, and it has to stay zero. An earlier attempt shrank each cubie by
     0.75px a side to stop neighbouring faces being coplanar. That treated the
     symptom: the buried faces are now not drawn at all, so nothing is
     coplanar with them, and any gap here would instead open a seam straight
     through the shell to the background. Kept as a token only so the geometry
     below reads as deliberate. */
  --shim: 0px;
  width: var(--size);
  height: var(--size);
  position: relative;
  transform-style: preserve-3d;
  transform: rotateX(-20deg) rotateY(-28deg);
  will-change: transform;
  pointer-events: none;
}

/* 26 real cubies, so a layer turn moves whole cubies the way an actual cube
   does. Each transform is a full matrix3d carrying both position and
   accumulated orientation. */
.cubie {
  position: absolute;
  width: var(--cs);
  height: var(--cs);
  left: calc(50% - var(--cs) / 2);
  top: calc(50% - var(--cs) / 2);
  transform-style: preserve-3d;
}

/* Each <i> is the FULL cubie face and fully opaque, so the six of them close
   the cubie into a solid box. The sticker is drawn inside it as ::before — the
   groove you see between cubies is painted, not a hole. Previously the faces
   were inset, which left real gaps you could see straight through the cube. */
/* Each <i> is the FULL cubie face and fully opaque, so the six of them close
   the cubie into a solid box. The sticker is drawn inside it as ::before — the
   groove you see between cubies is painted, not a hole. */
/* Each <i> is the FULL cubie face and fully opaque, so the six of them close
   the cubie into a solid box. The tile is drawn inside it as ::before — the
   groove you see between cubies is painted, not a hole. */
/* Faces buried inside the assembled cube. main.js marks them; not drawing
   them takes the cube from 156 quads to 54 and leaves the compositor's
   polygon sorter nothing to split. See the cull() comment in main.js. */
.cubie i.inner { display: none; }

.cubie i {
  position: absolute;
  inset: var(--shim);
  background: #030304;           /* the groove — darker than the tile */
  backface-visibility: hidden;
}

/* Flat tile, and every one of them identical — same black, same hairline, on
   all six faces. No gradients, no specular: earlier attempts at simulated
   gloss read as smudges rather than reflections. Black is lifted just off pure
   #000 so the tiles separate from the groove behind them; the geometry is
   carried by the violet hairlines, which the perspective distorts into the
   shape of the cube. */
.cubie i::before {
  content: '';
  position: absolute;
  inset: 8%;
  border-radius: 16%;
  background: #0c0c10;
  border: 1px solid rgba(146,129,247,0.26);
  /* A hairline of light rather than a painted edge: just enough bleed for the
     line to read as emissive, well short of anything that blooms. */
  box-shadow:
    0 2px 6px -2px rgba(0,0,0,0.85),             /* seats it in the groove */
    0 0 6px -1px rgba(146,129,247,0.26),         /* the line gives off light */
    inset 0 0 5px -3px rgba(168,152,255,0.30);
}

/* face order matches the six <i> children main.js appends */
.cubie i:nth-child(1) { transform: translateZ(calc(var(--cs) / 2 - var(--shim))); }                 /* +Z front  */
.cubie i:nth-child(2) { transform: rotateY(180deg) translateZ(calc(var(--cs) / 2 - var(--shim))); } /* -Z back   */
.cubie i:nth-child(3) { transform: rotateY(90deg)  translateZ(calc(var(--cs) / 2 - var(--shim))); } /* +X right  */
.cubie i:nth-child(4) { transform: rotateY(-90deg) translateZ(calc(var(--cs) / 2 - var(--shim))); } /* -X left   */
.cubie i:nth-child(5) { transform: rotateX(90deg)  translateZ(calc(var(--cs) / 2 - var(--shim))); } /* -Y top    */
.cubie i:nth-child(6) { transform: rotateX(-90deg) translateZ(calc(var(--cs) / 2 - var(--shim))); } /* +Y bottom */


@media (prefers-reduced-motion: reduce) {
  .rubik { transition: none; }
  .dot--live { animation: none; }
  html { scroll-behavior: auto; }
}
@media (max-width: 980px) {
  /* One column: the object goes between the headline and the lede, inside the
     first screen, instead of half-cut below the fold. The text wrapper
     dissolves so its children can be ordered around the object. */
  .hero-grid { gap: var(--s4); }
  .hero-grid > div:first-child { display: contents; }
  .hero .display { order: 1; }
  .hero-object { order: 2; }
  .hero .lede { order: 3; }
  .hero-cta { order: 4; }
  .hero-meta { order: 5; }
  .rubik-stage { --size: clamp(150px, 42vw, 196px); aspect-ratio: 1 / 0.72; perspective: 720px; }
}
@media (max-width: 420px) {
  .rubik-stage { --size: clamp(140px, 44vw, 176px); }
}

/* --------------------------------------------------------------------------
   8. Cards
   -------------------------------------------------------------------------- */
.card {
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  background: var(--black);
  padding: var(--s8);
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  transition: border-color var(--t), background var(--t);
  position: relative;
}
a.card:hover, .card--hover:hover { border-color: rgba(255,255,255,0.24); background: rgba(255,255,255,0.015); }

.card--lift { background: var(--surface); }

.card-icon {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border: 1px solid var(--hairline);
  border-radius: var(--r-control);
  margin-bottom: var(--s2);
  color: var(--bone);
}
.card-icon svg { width: 16px; height: 16px; }

.card p { font-size: 14px; line-height: 1.6; color: var(--smoke); max-width: 54ch; }

.card-list { display: flex; flex-direction: column; gap: 6px; margin-top: var(--s2); }
.card-list li {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--charcoal);
  display: flex;
  gap: var(--s2);
  align-items: baseline;
}
.card-list li::before { content: '—'; color: var(--iron); }

.card-index {
  position: absolute;
  top: var(--s6); right: var(--s7);
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--charcoal);
}

/* Bordered matrix — cells separated by hairlines, no gaps */
.matrix {
  display: grid;
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  overflow: hidden;
}
.matrix > * {
  padding: var(--s7);
  border-right: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
.matrix-3 { grid-template-columns: repeat(3, 1fr); }
.matrix-3 > *:nth-child(3n) { border-right: 0; }
.matrix-3 > *:nth-last-child(-n+3) { border-bottom: 0; }
.matrix-4 { grid-template-columns: repeat(4, 1fr); }
.matrix-4 > *:nth-child(4n) { border-right: 0; }
.matrix-4 > *:nth-last-child(-n+4) { border-bottom: 0; }
.matrix-1 { grid-template-columns: 1fr; }
.matrix-1 > * { border-right: 0; }
.matrix-1 > *:last-child { border-bottom: 0; }
/* The second tier of the stack: known and used, not what we lead with. */
.chips--dim .badge { color: var(--charcoal); }
@media (max-width: 900px) {
  .matrix-3, .matrix-4 { grid-template-columns: repeat(2, 1fr); }
  .matrix > * { border-right: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); }
  .matrix-3 > *:nth-child(2n), .matrix-4 > *:nth-child(2n) { border-right: 0; }
  .matrix-3 > *:nth-last-child(-n+2), .matrix-4 > *:nth-last-child(-n+2) { border-bottom: 0; }
}
@media (max-width: 560px) {
  .matrix-3, .matrix-4 { grid-template-columns: 1fr; }
  .matrix > * { border-right: 0 !important; border-bottom: 1px solid var(--hairline) !important; }
  .matrix > *:last-child { border-bottom: 0 !important; }
}

.stat { display: flex; flex-direction: column; gap: var(--s2); }
.stat b {
  font-family: var(--font-display);
  font-size: clamp(30px, 3.7vw, 41px);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--white);
}
.stat span { font-size: 13px; line-height: 1.5; color: var(--smoke); max-width: 46ch; }

/* --------------------------------------------------------------------------
   Logo strip
   Monochrome marks paired with wordmarks: recognition never depends on the
   drawing alone, and one colour keeps the row cohesive against the black.
   -------------------------------------------------------------------------- */
/* The strip follows the hero directly; the hero's own bottom padding is the gap. */
.hero + .section--tight { padding-top: 0; }
.logos { border-block: 1px solid var(--hairline); padding-block: var(--s12); }
.logos-cap { text-align: center; margin-bottom: var(--s8); }
.logos-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--s6) var(--s10);
}
.logo {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--bone);
  opacity: 0.55;
  transition: opacity var(--t);
}
.logo:hover { opacity: 1; color: var(--bone); }
.logo svg { width: 22px; height: 22px; flex: none; }
.logo span { font-size: 15px; font-weight: 500; letter-spacing: -0.02em; white-space: nowrap; }
@media (max-width: 620px) {
  .logos-row { gap: var(--s5) var(--s6); }
  .logo span { font-size: 13px; }
  .logo svg { width: 18px; height: 18px; }
}

/* --------------------------------------------------------------------------
   9. Code window
   -------------------------------------------------------------------------- */
.window {
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  background: var(--black);
  overflow: hidden;
}
.window-bar {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--hairline);
}
.window-lights { display: flex; gap: 6px; }
.window-lights i { width: 8px; height: 8px; border-radius: 50%; background: var(--hairline); display: block; }
.window-title {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--charcoal);
  margin-left: auto;
}
.window-tabs { display: flex; gap: var(--s1); }
.window-tabs button {
  border: 0;
  background: transparent;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--charcoal);
  padding: 3px var(--s2);
  border-radius: var(--r-control);
  cursor: pointer;
  transition: color var(--t), background var(--t);
}
.window-tabs button:hover { color: var(--bone); }
.window-tabs button[aria-selected="true"] { color: var(--white); background: rgba(255,255,255,0.07); }

.window pre {
  margin: 0;
  padding: var(--s6);
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.65;
  color: var(--bone);
  tab-size: 2;
}
@media (max-width: 560px) { .window pre { font-size: 11.5px; padding: var(--s4); } }
.window pre[hidden] { display: none; }

.tok-key { color: var(--sky); }
.tok-str { color: var(--iris); }
.tok-com { color: var(--charcoal); }
.tok-fn  { color: var(--white); }
.tok-ok  { color: var(--pulse); }
.tok-num { color: var(--iris-glow); }

/* --------------------------------------------------------------------------
   10. Process
   -------------------------------------------------------------------------- */
.steps { display: grid; gap: 0; border-top: 1px solid var(--hairline); }
.step {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr) minmax(0, 1.1fr);
  gap: var(--s6);
  padding-block: var(--s7);
  border-bottom: 1px solid var(--hairline);
  align-items: start;
  transition: background var(--t);
}
.step:hover { background: rgba(255,255,255,0.012); }
.step-no { font-family: var(--font-mono); font-size: 12px; color: var(--iris); padding-top: 4px; }
.step p { font-size: 14px; line-height: 1.6; color: var(--smoke); max-width: 68ch; }
.step-out { display: flex; flex-wrap: wrap; gap: 6px; align-content: start; }
@media (max-width: 860px) {
  .step { grid-template-columns: 56px 1fr; gap: var(--s4); }
  .step-out { grid-column: 2; }
}

/* Process with the object alongside. Steps on the left, the cube in a sticky
   column on the right, assembling as the steps go past. The steps take the
   narrow two-column form here at every width so the deliverables sit under
   the text, and get more height — that height is the scroll the assembly
   runs on. */
.process-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: var(--s16);
  align-items: start;
}
/* Equal rows: each stage's scene plays over its own step, so equal steps
   give every stage the same quarter of the scroll. */
.process-grid .steps { grid-auto-rows: 1fr; }
/* Room under the last step, sized so the sticky object is released at the
   moment Launch completes — 45% of the step at the middle of the screen, the
   object centred there beside it. From then on the section carries the
   object up at the same rate as the step, so the finished product travels
   level with the fourth step instead of standing while the step leaves.
   Object bottom = 50vh + 166px, step bottom then = 50vh + 0.55 × 250px. */
@media (min-width: 980px) {
  .process-grid .steps { padding-bottom: 28px; }
}
.process-grid .step { grid-template-columns: 56px 1fr; gap: var(--s4); padding-block: var(--s12); min-height: 250px; }
.process-grid .step-out { grid-column: 2; }
.step.is-active { background: rgba(255,255,255,0.014); }
.step.is-active .step-no { color: var(--iris-glow); }

.process-object {
  position: sticky;
  /* Centred in the viewport, so the step being read sits level with it and
     the finished product stands in the middle of the screen, not under the
     header. The drawing is ~350px tall; the floor keeps it clear of the
     header on short windows. The object is ~272px tall — 236 of drawing,
     20 of gap, 16 of caption — and it is the drawing that sits on the centre
     line, so the caption hangs just below it. */
  top: clamp(88px, calc(50vh - 106px), 40vh);
  display: grid;
  gap: var(--s5);   /* the caption sits just under the drawing */
  justify-items: center;
}
.blueprint-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 360 / 236;   /* the drawing's own box — no air below it */
  display: grid;
  place-items: center;
}
/* Key light behind the drawing, so it sits in the same air as the hero. It
   arrives with the first stroke: until stage 1 starts (--bp1 is 0) there is
   nothing to light, so the column is dark and uncaptioned — the glow and the
   caption fade in over the first third of Discovery, as the frame is drawn. */
.blueprint-stage::before {
  content: '';
  position: absolute;
  /* Keep the decorative light inside its column horizontally. A negative
     horizontal inset extended the page beyond the viewport on desktop. */
  inset: -10% 0;
  background: radial-gradient(circle at 50% 42%, rgba(146,129,247,0.16), transparent 60%);
  filter: blur(40px);
  opacity: clamp(0, calc(var(--bp1, 0) * 8), 1);
  pointer-events: none;
  transition: filter 700ms var(--ease), opacity 400ms var(--ease);
}
.process-object.is-built .blueprint-stage::before { filter: blur(40px) brightness(1.8); }
.blueprint { position: relative; width: 100%; height: auto; overflow: visible; }

/* Hairlines, always one device pixel, whatever the box is scaled to. */
.blueprint path, .blueprint rect, .blueprint ellipse {
  fill: none;
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Everything drawn carries pathLength="1": dasharray 1 and an offset from 1
   down to 0 draws it from nothing to whole. --bd1..--bd4 (the offsets) and
   --bp1..--bp4 (the progress) come from main.js as plain numbers — a calc()
   mixing a bare number into a length is dropped by Chrome. */
.bp-draw { stroke-dasharray: 1; }
.bp-s1 { stroke: var(--iron); stroke-dashoffset: var(--bd1, 1); transition: stroke 600ms var(--ease); }
.bp-s2 { stroke: var(--ash);  stroke-dashoffset: var(--bd2, 1); transition: stroke 600ms var(--ease); }
.process-object:not([data-stage="1"]) .bp-s1 { stroke: var(--ash); }
.process-object.is-built .bp-s1,
.process-object.is-built .bp-s2 { stroke: var(--bone); }
.bp-dots circle { fill: var(--iron); opacity: var(--bp1, 0); }

/* The product, in four scenes. Everything below keys off --bp1..--bp4, each
   0..1 across its stage. Rules are scoped under .blueprint so they outrank
   the generic fill:none on shapes. */
.bp-product {
  transform-box: fill-box;
  transform-origin: center;
  /* at launch the whole thing lifts a touch */
  transform: translateY(calc(-4px * var(--bp4, 0))) scale(calc(1 + 0.02 * var(--bp4, 0)));
}
/* 01 · the sketch: dashed and a little askew; it straightens and fades as
   the layout takes over in 02 */
.blueprint .bp-sketch rect {
  stroke: var(--iron);
  stroke-dasharray: 3 2;
  transform-box: fill-box;
  transform-origin: center;
  transform: rotate(calc(var(--tilt, 0deg) * (1 - var(--bp2, 0))));
  opacity: calc(var(--bp1, 0) * (1 - var(--bp2, 0)));
}
.blueprint .bp-note {
  fill: var(--ash);
  font-family: var(--font-mono);
  font-size: 8px;
  letter-spacing: 0.03em;
  opacity: calc(var(--bp1, 0) * (1 - var(--bp2, 0)));
}
.blueprint .bp-tags { opacity: var(--bp1, 0); }
.blueprint .bp-tags rect { stroke: var(--hairline); }
.blueprint .bp-tags text { fill: var(--ash); font-family: var(--font-mono); font-size: 7.5px; letter-spacing: 0.08em; text-transform: uppercase; }
/* 02 · the layout */
.blueprint .bp-layout { opacity: var(--bp2, 0); }
.blueprint .bp-layout rect, .blueprint .bp-layout path { stroke: var(--ash); transition: stroke 600ms var(--ease); }
.process-object.is-built .bp-layout rect, .process-object.is-built .bp-layout path { stroke: var(--bone); }
.blueprint .bp-btn { fill: var(--iris); stroke: none; }
.blueprint .bp-btn--phone { opacity: var(--bp2, 0); }   /* arrives with the phone, not before it */
/* the type sample belongs to design; it clears out once the product is live */
.blueprint .bp-type { fill: var(--ash); font-family: var(--font-display); font-weight: 500; font-size: 11px; opacity: calc(var(--bp2, 0) * (1 - var(--bp4, 0))); }
/* 03 · content: bars grow in from the left one after another, surfaces fill,
   a caret blinks at the end of the line being written */
.blueprint .bp-bar {
  fill: var(--ash);
  stroke: none;
  opacity: 0.6;
  transform-box: fill-box;
  transform-origin: left center;
  transform: scaleX(clamp(0, calc(var(--bp3, 0) * 2 - var(--i, 0) * 0.22), 1));
}
.blueprint .bp-fill { fill: rgba(146,129,247,0.07); stroke: none; opacity: clamp(0, calc(var(--bp3, 0) * 2 - var(--i, 0) * 0.22), 1); }
.blueprint .bp-caret { fill: var(--iris-glow); stroke: none; opacity: 0; }
.process-object[data-stage="3"] .bp-caret { opacity: 1; animation: bp-blink 1s steps(2, start) infinite; }
@keyframes bp-blink { to { opacity: 0; } }
.blueprint .bp-log text { fill: var(--ash); font-family: var(--font-mono); font-size: 7.5px; letter-spacing: 0.03em; opacity: clamp(0, calc(var(--bp3, 0) * 2.4 - var(--i, 0) * 0.6 - 0.8), 1); }
.blueprint .bp-log .ok { fill: var(--pulse); }
/* 04 · launch: address and lock, a hand on the button, the confirmation */
.blueprint .bp-launch > * { opacity: var(--bp4, 0); }
.blueprint .bp-url { fill: rgba(255,255,255,0.04); stroke: var(--hairline); }
.blueprint .bp-url-text { fill: var(--smoke); font-family: var(--font-mono); font-size: 7px; letter-spacing: 0.04em; }
.blueprint .bp-lock { stroke: var(--pulse); stroke-width: 1; }
.blueprint .bp-cursor { fill: var(--bone); stroke: var(--black); stroke-width: 0.6; }
.blueprint .bp-toast { fill: rgba(58,211,137,0.12); stroke: rgba(58,211,137,0.5); }
.blueprint .bp-toast-text { fill: var(--pulse); font-family: var(--font-mono); font-size: 7px; letter-spacing: 0.04em; }
/* Live: the same green pulse the site uses for a live dot. */
.bp-live { opacity: 0; transition: opacity 500ms var(--ease); }
.bp-live text { fill: var(--pulse); font-family: var(--font-mono); font-size: 8px; letter-spacing: 0.08em; text-transform: uppercase; }
.bp-live-dot { fill: var(--pulse); }
.bp-live-ring { fill: none; stroke: var(--pulse); stroke-width: 1; transform-box: fill-box; transform-origin: center; animation: bp-pulse 2.4s var(--ease) infinite; }
.process-object.is-built .bp-live { opacity: 1; }
@keyframes bp-pulse {
  0%   { transform: scale(1);   opacity: 0.7; }
  70%  { transform: scale(3.2); opacity: 0; }
  100% { transform: scale(3.2); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .bp-live-ring { animation: none; opacity: 0; }
  .process-object[data-stage="3"] .bp-caret { animation: none; }
}
.process-cap { text-align: center; min-height: 1.4em; opacity: clamp(0, calc(var(--bp1, 0) * 8), 1); transition: opacity 400ms var(--ease); }
.process-cap span[hidden] { display: none; }

@media (max-width: 979px) {
  .process-grid { grid-template-columns: 1fr; }
  .process-object { display: none; }
  .process-grid .step { padding-block: var(--s7); }
}

/* --------------------------------------------------------------------------
   11. Work
   -------------------------------------------------------------------------- */
.work-item {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: var(--s12);
  padding-block: var(--s16);
  border-bottom: 1px solid var(--hairline);
  align-items: center;
}
.work-item:first-of-type { border-top: 1px solid var(--hairline); }
.work-item p { max-width: 64ch; }
.work-item .h3 { max-width: 22ch; }
@media (max-width: 900px) { .work-item { grid-template-columns: 1fr; gap: var(--s8); padding-block: var(--s12); } }

.work-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--s2); }

.result-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s8);
  margin-top: var(--s6);
  padding-top: var(--s5);
  border-top: 1px solid var(--hairline);
}
.result-row div { display: flex; flex-direction: column; gap: 2px; }
.result-row b {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 500;
  color: var(--white);
  line-height: 1;
  letter-spacing: -0.026em;
}
.result-row span { font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--charcoal); }

/* Abstract project visual — hairline schematic instead of a fake screenshot */
.schematic {
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  background: var(--surface);
  padding: var(--s6);
  display: grid;
  gap: var(--s3);
  min-height: 280px;
  align-content: start;
}
.schematic-row { display: flex; gap: var(--s3); align-items: center; }
.schematic-bar { height: 8px; border-radius: 2px; background: var(--hairline); flex: 1; }
.schematic-bar.is-iris { background: linear-gradient(90deg, var(--iris), rgba(146,129,247,0.15)); flex: 0 0 34%; }
.schematic-bar.is-short { flex: 0 0 18%; }
.schematic-box { border: 1px solid var(--hairline); border-radius: var(--r-control); height: 56px; flex: 1; }
.schematic-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s2); }

/* --------------------------------------------------------------------------
   12. Accordion (FAQ)
   -------------------------------------------------------------------------- */
.faq { border-top: 1px solid var(--hairline); }
.faq details { border-bottom: 1px solid var(--hairline); }
.faq summary {
  list-style: none;
  cursor: pointer;
  padding-block: var(--s6);
  display: flex;
  gap: var(--s4);
  align-items: center;
  justify-content: space-between;
  font-size: 16px;
  font-weight: 500;
  color: var(--bone);
  letter-spacing: -0.01em;
  transition: color var(--t);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--white); }
.faq summary::after {
  content: '';
  width: 10px; height: 10px;
  flex: none;
  border-right: 1px solid var(--iron);
  border-bottom: 1px solid var(--iron);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--t);
}
.faq details[open] summary { color: var(--white); }
.faq details[open] summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.faq-body { padding-bottom: var(--s6); max-width: 72ch; }
.faq-body p { font-size: 14px; line-height: 1.7; color: var(--smoke); }
.faq-body p + p { margin-top: var(--s3); }

/* --------------------------------------------------------------------------
   13. CTA band
   -------------------------------------------------------------------------- */
.cta {
  border: 1px solid var(--hairline);
  border-radius: var(--r-panel);
  padding: clamp(32px, 6vw, 80px);
  background: var(--surface);
  text-align: center;
  position: relative;
  overflow: hidden;
}
.cta::before {
  content: '';
  position: absolute;
  top: -40%; left: 50%;
  width: 520px; height: 320px;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at center, rgba(146,129,247,0.14), transparent 68%);
  pointer-events: none;
}
.cta > * { position: relative; }
.cta .display { font-size: clamp(34px, 5.4vw, 64px); margin-bottom: var(--s5); }
.cta .lede { margin-inline: auto; margin-bottom: var(--s8); }
.cta-actions { display: flex; gap: var(--s3); justify-content: center; flex-wrap: wrap; }

/* --------------------------------------------------------------------------
   14. Forms
   -------------------------------------------------------------------------- */
.form { display: grid; gap: var(--s5); }
.field { display: grid; gap: 6px; }
.field label {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ash);
}
.field .req { color: var(--iris); }
.field input, .field textarea, .field select {
  background: var(--black);
  border: 1px solid var(--hairline);
  border-radius: var(--r-control);
  padding: 10px var(--s3);
  font-size: 14px;
  color: var(--white);
  width: 100%;
  transition: border-color var(--t);
  font-family: var(--font-sans);
}
.field textarea { min-height: 132px; resize: vertical; line-height: 1.6; }
.field input::placeholder, .field textarea::placeholder { color: var(--charcoal); }
.field input:hover, .field textarea:hover, .field select:hover { border-color: var(--iron); }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none;
  border-color: var(--iris);
  box-shadow: 0 0 0 3px rgba(146,129,247,0.12);
}
.field select { appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' fill='none'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%236e727a'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center; padding-right: 34px; }
.field select option { background: #0a0a0a; }

.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); }
@media (max-width: 620px) { .field-row { grid-template-columns: 1fr; } }

.check { display: flex; gap: var(--s3); align-items: flex-start; }
.check input { width: 16px; height: 16px; margin-top: 2px; flex: none; accent-color: var(--iris); }
.check label { font-family: var(--font-sans); font-size: 13px; text-transform: none; letter-spacing: 0; color: var(--smoke); line-height: 1.5; }
.check a { color: var(--smoke); text-decoration: underline; text-underline-offset: 2px; }

.form-note { font-size: 12px; color: var(--charcoal); line-height: 1.6; }
.form-status {
  display: none;
  border: 1px solid var(--hairline);
  border-radius: var(--r-control);
  padding: var(--s3) var(--s4);
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--pulse);
  align-items: center;
  gap: var(--s2);
}
.form-status.is-visible { display: flex; }
.form-status.is-error { color: var(--alarm); }
/* Honeypot: off-canvas, not display:none — some bots skip hidden fields. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.turnstile { min-height: 65px; }   /* the widget's box, so the button does not jump when it renders */

/* --------------------------------------------------------------------------
   Cookie consent
   -------------------------------------------------------------------------- */
.consent {
  position: fixed;
  left: var(--gutter);
  bottom: var(--gutter);
  z-index: 60;
  max-width: 400px;
  padding: var(--s5) var(--s6);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  background: var(--black);
  box-shadow: 0 24px 60px -24px rgba(0,0,0,0.9);
}
.consent-text { font-size: 13px; line-height: 1.55; color: var(--smoke); }
.consent-text a { color: var(--bone); text-decoration: underline; text-underline-offset: 2px; }
.consent-actions { display: flex; gap: var(--s2); margin-top: var(--s4); flex-wrap: wrap; }
@media (max-width: 520px) { .consent { left: var(--s3); right: var(--s3); bottom: var(--s3); max-width: none; } }

/* --------------------------------------------------------------------------
   15. Footer
   -------------------------------------------------------------------------- */
.footer { border-top: 1px solid var(--hairline); margin-top: var(--s24); padding-block: var(--s16) var(--s10); }
.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: var(--s10) var(--s6);
}
@media (max-width: 860px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 520px) { .footer-grid { grid-template-columns: 1fr; } }

.footer h5 {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--charcoal);
  font-weight: 400;
  margin-bottom: var(--s4);
}
.footer-links { display: grid; gap: var(--s3); }
.footer-links a, .footer-links span { font-size: 14px; color: var(--smoke); }
/* The contact page has no header nav item to underline any more, so the
   footer carries its "you are here" on its own. */
.footer-links a[aria-current="page"] { color: var(--white); }
.footer-brand p { font-size: 14px; color: var(--smoke); max-width: 34ch; margin-top: var(--s4); }

.legal {
  margin-top: var(--s16);
  padding-top: var(--s5);
  border-top: 1px solid var(--hairline);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3) var(--s6);
  justify-content: space-between;
  align-items: center;
}
.legal p, .legal a { font-family: var(--font-mono); font-size: 11px; color: var(--charcoal); letter-spacing: 0.02em; }
.legal a:hover { color: var(--smoke); }
.legal-ids { display: flex; flex-wrap: wrap; gap: var(--s4); }

/* --------------------------------------------------------------------------
   16. Page header (interior pages)
   -------------------------------------------------------------------------- */
.page-head { padding-top: var(--s20); padding-bottom: var(--s12); border-bottom: 1px solid var(--hairline); }
.page-head .display { font-size: clamp(37px, 5.9vw, 70px); margin-bottom: var(--s5); }
.crumb { font-family: var(--font-mono); font-size: 12px; color: var(--charcoal); margin-bottom: var(--s6); display: flex; gap: var(--s2); }
.crumb a { color: var(--charcoal); }
.crumb a:hover { color: var(--smoke); }

/* Prose (legal pages) */
.prose { max-width: 72ch; }
.prose h2 { font-family: var(--font-display); font-size: 26px; font-weight: 500; color: var(--white); letter-spacing: -0.022em; margin-top: var(--s12); margin-bottom: var(--s4); }
.prose h3 { font-family: var(--font-display); font-size: 18px; font-weight: 500; color: var(--white); letter-spacing: -0.012em; margin-top: var(--s6); margin-bottom: var(--s2); }
.prose p, .prose li { font-size: 15px; line-height: 1.75; color: var(--smoke); }
.prose p + p { margin-top: var(--s4); }
.prose ul { margin: var(--s4) 0; display: grid; gap: var(--s2); }
.prose ul li { padding-left: var(--s5); position: relative; }
.prose ul li::before { content: '—'; position: absolute; left: 0; color: var(--iron); }
.prose a { color: var(--iris); text-decoration: underline; text-underline-offset: 3px; }
.prose a:hover { color: var(--iris-glow); }
.prose code { font-family: var(--font-mono); font-size: 13px; color: var(--charcoal); }
.prose strong { color: var(--bone); font-weight: 500; }

/* --------------------------------------------------------------------------
   17. Utilities + motion
   -------------------------------------------------------------------------- */
.reveal { opacity: 0; transform: translateY(12px); transition: opacity 600ms var(--ease), transform 600ms var(--ease); }
.reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .reveal { opacity: 1; transform: none; transition: none; } }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--white); color: var(--black);
  padding: var(--s2) var(--s4); border-radius: var(--r-control); font-size: 14px;
}
.skip:focus { left: var(--s4); top: var(--s4); color: var(--black); }

.stack-sm { display: grid; gap: var(--s2); }
.stack { display: grid; gap: var(--s4); }
.stack-lg { display: grid; gap: var(--s8); }
.center { text-align: center; }
.mt-8 { margin-top: var(--s8); }
.mt-12 { margin-top: var(--s12); }
.mt-16 { margin-top: var(--s16); }
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
[hidden] { display: none !important; }
