/* ============================================================
   Void Notes
   A single vertical descent: hyperreal shader at the top,
   literal pixels at the bottom. Six phase zones, one theme,
   one accent, zero corner radius everywhere.
   ============================================================ */

:root {
  --ink: #13140d;
  --ink-soft: #1b1c15;
  --paper: #e4e3d7;
  --muted: #c7c8b8;
  --dim: #919283;
  --line: rgba(199, 200, 184, 0.22);
  --lime: #bfce7f;
  --lime-deep: #576421;

  /* Pixel aesthetic: no radius anywhere, on purpose. */
  --radius: 0px;

  --mono: 'Source Code Pro', 'Courier New', monospace;
  --sans: 'Inter Display', Inter, 'Noto Sans CJK SC', Arial, sans-serif;
  /* Bytesized is a 1-bit pixel face: it only ever spells the name. */
  --pixel: 'Bytesized', var(--mono);

  /* Per-phase quantization. Driven by [data-phase] on <body>. */
  --q-border: 1px;
  --q-gap: 14px;
  --q-track: 0.02em;

  /* Black hole transform, per phase. */
  --bh-scale: 1;
  --bh-x: 0%;
  --bh-y: 0%;
  --bh-ease: cubic-bezier(0.22, 0.66, 0.16, 1);
}

* { box-sizing: border-box; }

/* Self-hosted so the name renders the same everywhere, including
   on networks that cannot reach fonts.gstatic.com. */
@font-face {
  font-family: 'Bytesized';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('./assets/fonts/bytesized-latin.woff2') 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;
}
html { scroll-behavior: smooth; background: var(--ink); }
body {
  margin: 0;
  min-width: 320px;
  color: var(--paper);
  background: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.5;
  overflow-x: hidden;
}
a { color: inherit; text-decoration: none; }
button, input { font: inherit; }
button { color: inherit; }
img { display: block; max-width: 100%; }
code, pre { font-family: var(--mono); }

.particle-mark {
  position: relative;
  isolation: isolate;
  aspect-ratio: 1;
}
.particle-mark canvas,
.particle-mark .particle-fallback {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.particle-mark canvas {
  z-index: 1;
  touch-action: none;
}
.particle-mark .particle-fallback {
  z-index: 0;
  transition: opacity 360ms ease;
}
.particle-mark[data-particle-state="ready"] .particle-fallback { opacity: 0; }
.particle-mark[data-particle-state="fallback"] canvas { display: none; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Grain sits on a fixed, contained layer so it never repaints on scroll. */
.noise {
  position: fixed;
  inset: 0;
  z-index: 50;
  pointer-events: none;
  opacity: 0.045;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.75'/%3E%3C/svg%3E");
  mix-blend-mode: soft-light;
  contain: strict;
}

/* ------------------------------------------------------------
   PHASE ZONES
   Each zone quantizes a little harder than the one above it.
   Text is never SVG-filtered (that only blurs it). Chunkiness
   comes from real geometry: thicker rules, wider tracking,
   snapped gaps, and finally literal canvas dots.
   ------------------------------------------------------------ */
[data-phase-zone="0"] { --q-border: 1px; --q-gap: 14px; --q-track: 0.02em; }
[data-phase-zone="1"] { --q-border: 1px; --q-gap: 16px; --q-track: 0.04em; }
[data-phase-zone="2"] { --q-border: 2px; --q-gap: 20px; --q-track: 0.07em; }
[data-phase-zone="3"] { --q-border: 3px; --q-gap: 24px; --q-track: 0.11em; }
[data-phase-zone="4"] { --q-border: 4px; --q-gap: 32px; --q-track: 0.16em; }
[data-phase-zone="5"] { --q-border: 4px; --q-gap: 32px; --q-track: 0.2em; }

/* A grid overlay that coarsens with depth, so the page itself
   feels like it is resolving onto a lower-resolution raster. */
[data-phase-zone]::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  background-image:
    linear-gradient(rgba(233, 232, 226, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(233, 232, 226, 0.05) 1px, transparent 1px);
  background-size: 8px 8px;
  transition: opacity 600ms ease, background-size 600ms ease;
}
[data-phase-zone="1"]::before { opacity: 0.35; background-size: 12px 12px; }
[data-phase-zone="2"]::before { opacity: 0.5;  background-size: 18px 18px; }
[data-phase-zone="3"]::before { opacity: 0.62; background-size: 26px 26px; }
[data-phase-zone="4"]::before { opacity: 0.72; background-size: 36px 36px; }
[data-phase-zone="5"]::before { opacity: 0.5;  background-size: 48px 48px; }

/* ------------------------------------------------------------
   BLACK HOLE STAGE
   One fixed viewport-sized box for the whole document. It shrinks
   and climbs as phases advance, ending as a speck in the pixel sky.
   Nothing above it in the tree may ever have a CSS filter, or
   the fixed positioning would collapse into that ancestor.

   The box matches the viewport exactly. A square box (max(100vw,100vh))
   makes the shader compose for a 1:1 frame while only the middle strip
   is on screen, which crops the top and bottom off the accretion disc.
   ------------------------------------------------------------ */
.bh-stage {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: 0;
  pointer-events: none;
  /* Scale about the shader's actual singularity, not the box centre.
     The shader puts the hole at screen-UV (0.12, -0.03), which is
     (50% + 6vh, 50% + 1.5vh) of the frame, so a centre origin would
     drift the hole away from the point it is shrinking toward. */
  transform-origin: calc(50% + 6vh) calc(50% + 1.5vh);
  transform: translate(var(--bh-x), var(--bh-y)) scale(var(--bh-scale));
  transition:
    transform 1100ms var(--bh-ease),
    top 1100ms var(--bh-ease),
    left 1100ms var(--bh-ease),
    width 1100ms var(--bh-ease),
    height 1100ms var(--bh-ease),
    transform-origin 1100ms var(--bh-ease);
  will-change: transform;
}

/* Phase 5 hands the hole over to the pixel scene, which reopens it huge in
   its own palette. --bh-handoff is driven by the scene's own render loop,
   so this fade and that hole's growth run off one clock: the shader is gone
   by the time the pixel hole has grown out of its shadow. Driving it from a
   phase class instead would make them two unrelated animations that merely
   happen to overlap. Defaults to 0, so the shader stays visible if the
   script never runs. */
.bh-stage { opacity: calc(1 - var(--bh-handoff, 0)); }
.visual-frame {
  position: absolute;
  inset: 0;
  overflow: hidden;
  /* Exactly the page background, so the box itself contributes no seam. */
  background: var(--ink);
}

/* Edge fade, concentric with the singularity. Only armed once the stage
   starts shrinking: at phase 0 the box is exactly the viewport, so no edge
   can show and the hero must stay full-bleed.

   closest-side means the stops resolve against the frame's own half-extents,
   so every edge midpoint reaches full --ink and the corners clamp past it.
   That makes the whole border the page colour at any scale, with no
   per-phase radius tuning. */
.visual-frame::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: radial-gradient(
    ellipse closest-side at calc(50% + 6vh) calc(50% + 1.5vh),
    transparent 0,
    transparent 34%,
    rgba(9, 10, 10, 0.55) 68%,
    var(--ink) 88%,
    var(--ink) 100%);
  opacity: 0;
  transition: opacity 900ms var(--bh-ease);
}
body:not([data-phase="0"]) .visual-frame::after { opacity: 1; }

/* Portrait starts full-height. Once the descent begins, the stage itself
   morphs to a 16:9 landscape frame so the compact hole uses the same
   composition as desktop instead of remaining a shrunken portrait strip. */
@media (max-aspect-ratio: 1 / 1) {
  body[data-phase="0"] .bh-stage { transform-origin: 50% calc(50% + 1.5vh); }
  body[data-phase="0"] .visual-frame::after {
    background: radial-gradient(
      ellipse closest-side at 50% calc(50% + 1.5vh),
      transparent 0,
      transparent 34%,
      rgba(9, 10, 10, 0.55) 68%,
      var(--ink) 88%,
      var(--ink) 100%);
  }
  body:not([data-phase="0"]) .bh-stage {
    top: 21.875vh;
    left: calc(50vw - 50vh);
    width: 100vh;
    height: 56.25vh;
    transform-origin: calc(50% + 3.375vh) calc(50% + 0.84375vh);
  }
  body:not([data-phase="0"]) .visual-frame::after {
    background: radial-gradient(
      ellipse closest-side at calc(50% + 3.375vh) calc(50% + 0.84375vh),
      transparent 0,
      transparent 34%,
      rgba(9, 10, 10, 0.55) 68%,
      var(--ink) 88%,
      var(--ink) 100%);
  }
}
#black-hole {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.visual-vignette {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 50%, transparent 16%, rgba(4, 5, 5, 0.05) 40%, rgba(4, 5, 5, 0.82) 100%);
}
/* Only the hero phase lets the pointer reach the shader; below
   that the page content owns the cursor. */
body[data-phase="0"] .bh-stage { pointer-events: none; }
body[data-phase="0"] #black-hole { pointer-events: auto; cursor: crosshair; }

/* Fixed, not inside .bh-stage: the stage is scaled by a transform and
   would shrink this caption along with the shader. */
.bh-hint {
  position: fixed;
  left: 50%;
  bottom: 26px;
  z-index: 11;
  margin: 0;
  transform: translateX(-50%);
  pointer-events: none;
  color: rgba(233, 232, 226, 0.4);
  font: 400 10px/1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: opacity 500ms ease;
}
body:not([data-phase="0"]) .bh-hint { opacity: 0; }

/* Phase choreography. The stage box is now the viewport, so these
   percentages are viewport percentages: x of width, y of height.
   They move the singularity itself, since transform-origin sits on it. */
body[data-phase="0"] { --bh-scale: 1;    --bh-x: 0%;   --bh-y: 0%; }
body[data-phase="1"] { --bh-scale: 0.46; --bh-x: 23%;  --bh-y: -21%; }
body[data-phase="2"] { --bh-scale: 0.3;  --bh-x: -29%; --bh-y: -25%; }
body[data-phase="3"] { --bh-scale: 0.2;  --bh-x: 25%;  --bh-y: -29%; }
/* The last two phases share one horizontal anchor. In phase 5 the shader is
   parked inside the pixel sky; phase 4 lifts and enlarges it on that same
   right-side rail after the scene edge has revealed it. */
body[data-phase="4"] { --bh-scale: 0.12; --bh-x: 17%;  --bh-y: -27%; }
body[data-phase="5"] { --bh-scale: 0.07; --bh-x: 17%;  --bh-y: -20%; }

/* Portrait: half the horizontal swing, or the hole spends most of the
   descent hanging off the side of a narrow screen. */
@media (max-aspect-ratio: 1 / 1) {
  body[data-phase="1"] { --bh-x: calc(12vw - 3.375vh); --bh-y: -20.34375vh; }
  body[data-phase="2"] { --bh-x: calc(-15vw - 3.375vh); --bh-y: -24.34375vh; }
  body[data-phase="3"] { --bh-x: calc(13vw - 3.375vh); --bh-y: -28.34375vh; }
  body[data-phase="4"] { --bh-scale: 0.09; --bh-x: calc(36vw - 3.375vh); --bh-y: -26.34375vh; }
  body[data-phase="5"] { --bh-scale: 0.06; --bh-x: calc(36vw - 3.375vh); --bh-y: -19.34375vh; }
}

/* ------------------------------------------------------------
   HEADER
   One line at desktop, 68px tall.
   ------------------------------------------------------------ */
.site-header {
  position: fixed;
  top: 0;
  left: 50%;
  z-index: 12;
  height: 68px;
  width: min(1380px, calc(100% - 48px));
  display: flex;
  align-items: center;
  gap: 48px;
  transform: translateX(-50%);
  pointer-events: none;
}
.site-header > * { pointer-events: auto; }
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font: 500 13px/1 var(--mono);
  letter-spacing: 0.13em;
}
.wordmark-mark { display: inline-flex; align-items: flex-end; gap: 2px; height: 19px; }
.wordmark-mark span { display: block; width: 4px; background: var(--lime); }
.wordmark-mark span:nth-child(1) { height: 11px; opacity: 0.65; }
.wordmark-mark span:nth-child(2) { height: 19px; }
.wordmark-mark span:nth-child(3) { height: 7px; opacity: 0.42; }
.desktop-nav { display: flex; gap: 34px; margin-left: auto; }
.desktop-nav a, .footer-links a {
  color: #9b9e98;
  font: 400 12px/1 var(--mono);
  letter-spacing: 0.08em;
  transition: color 220ms ease;
}
.desktop-nav a:hover, .footer-links a:hover { color: var(--lime); }
.header-actions { display: flex; align-items: center; }
.menu-toggle { display: none; border: 0; background: transparent; padding: 8px; cursor: pointer; }
.menu-line { width: 23px; height: 2px; background: var(--paper); display: block; }
.menu-line + .menu-line { margin-top: 6px; }
.mobile-menu { display: none; }

/* ------------------------------------------------------------
   SHARED TYPE
   ------------------------------------------------------------ */
h1, h2, h3, h4 { margin: 0; font-weight: 500; }
h1 {
  margin-bottom: 24px;
  font-size: clamp(2.9rem, 6.6vw, 5.6rem);
  line-height: 1.02;
  letter-spacing: 0;
}
h1 em { color: var(--lime); font-style: normal; }
h2 {
  max-width: 820px;
  font-size: clamp(2.4rem, 5.4vw, 4.9rem);
  line-height: 1.04;
  letter-spacing: 0;
}
h2 span { color: var(--dim); }
.eyebrow {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 24px;
  color: var(--muted);
  font: 400 10px/1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.eyebrow-rule { width: 34px; height: 1px; background: var(--lime); }
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 46px;
  padding: 0 22px;
  border: 1px solid var(--paper);
  border-radius: var(--radius);
  white-space: nowrap;
  font: 400 12px/1 var(--mono);
  letter-spacing: 0.06em;
  transition: transform 140ms ease, background 200ms ease, color 200ms ease;
}
.button-primary { color: var(--ink); background: var(--lime); border-color: var(--lime); }
.button-primary:hover { background: #e4ff85; }
.button-quiet { color: var(--paper); background: transparent; border-color: var(--line); }
.button-quiet:hover { border-color: var(--paper); background: rgba(233, 232, 226, 0.06); }
.button:active { transform: translateY(1px); }
.text-link {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 7px;
  border-bottom: 2px solid var(--lime);
  color: var(--lime);
  font: 400 12px/1 var(--mono);
  letter-spacing: 0.06em;
  transition: gap 180ms ease;
}
.text-link:hover { gap: 20px; }

.site-main { position: relative; z-index: 1; }
[data-phase-zone] {
  position: relative;
  isolation: isolate;
  width: 100%;
  padding-inline: clamp(20px, 6vw, 96px);
}
[data-phase-zone] > * { position: relative; z-index: 1; }

/* ------------------------------------------------------------
   PHASE 0 / HERO
   Asymmetric: copy left, shader breathing on the right.
   Max 3 text elements plus CTAs. Fits one viewport.
   ------------------------------------------------------------ */
.hero {
  min-height: 100dvh;
  display: flex;
  align-items: center;
  padding-top: 68px;
  padding-bottom: 64px;
}
.hero-copy { width: min(600px, 54vw); }
.hero-lede {
  max-width: 420px;
  margin: 0 0 34px;
  color: #a7aca4;
  font-size: 15px;
  line-height: 1.75;
}
.hero-actions { display: flex; flex-wrap: wrap; gap: 14px; }

/* ------------------------------------------------------------
   PHASE 1 / PROJECTS
   Cards are thrown out of the hole, hold, then get pulled back.
   Transform deltas are measured in JS and handed over as vars.
   ------------------------------------------------------------ */
.projects { padding-block: clamp(120px, 17vh, 210px); }
.projects-head { margin-bottom: clamp(48px, 7vw, 88px); }

.orbit-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--q-gap);
  perspective: 1200px;
}
.proj {
  position: relative;
  min-height: 330px;
  /* Ejected resting state. */
  opacity: 1;
  transform: none;
  transition:
    opacity 700ms ease,
    transform 1000ms var(--bh-ease);
  transition-delay: var(--eject-delay, 0ms);
}
.orbit-grid > .proj:nth-child(1) { grid-column: span 7; margin-top: 0; }
.orbit-grid > .proj:nth-child(2) { grid-column: span 5; margin-top: clamp(42px, 7vw, 96px); }

.proj-plane {
  --pointer-x: 50%;
  --pointer-y: 50%;
  --card-rx: 0deg;
  --card-ry: 0deg;
  --card-shadow-x: 10px;
  --card-shadow-y: 12px;
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: inherit;
  height: 100%;
  padding: 26px;
  overflow: hidden;
  border: var(--q-border) solid var(--line);
  border-radius: var(--radius);
  color: inherit;
  background: var(--ink-soft);
  box-shadow: var(--card-shadow-x) var(--card-shadow-y) 0 rgba(216, 243, 106, 0);
  transform: rotateX(var(--card-rx)) rotateY(var(--card-ry)) translateZ(0);
  transform-style: preserve-3d;
  will-change: transform;
  transition:
    transform 180ms ease-out,
    border-color 180ms ease,
    box-shadow 180ms ease;
}
.proj-plane::before,
.proj-plane::after {
  content: "";
  position: absolute;
  z-index: 0;
  pointer-events: none;
  background: rgba(216, 243, 106, 0.78);
  opacity: 0;
  transition: opacity 140ms ease;
}
.proj-plane::before {
  top: calc(var(--pointer-y) - 18px);
  left: var(--pointer-x);
  width: 1px;
  height: 36px;
}
.proj-plane::after {
  top: var(--pointer-y);
  left: calc(var(--pointer-x) - 18px);
  width: 36px;
  height: 1px;
}
.proj-plane > * {
  position: relative;
  z-index: 1;
  transform: translateZ(20px);
}
.proj-plane:hover,
.proj-plane:focus-visible,
.proj-plane.is-tracking {
  border-color: rgba(216, 243, 106, 0.72);
  box-shadow: var(--card-shadow-x) var(--card-shadow-y) 0 rgba(216, 243, 106, 0.18);
}
.proj-plane:hover::before,
.proj-plane:hover::after,
.proj-plane:focus-visible::before,
.proj-plane:focus-visible::after,
.proj-plane.is-tracking::before,
.proj-plane.is-tracking::after { opacity: 1; }
.proj-plane:active { transform: rotateX(0deg) rotateY(0deg) translateY(2px); }
.proj-plane:focus-visible {
  outline: 2px solid var(--paper);
  outline-offset: 4px;
}
.proj-lime { color: var(--ink); }
.proj-lime .proj-plane {
  border-color: var(--lime);
  background: var(--lime);
}
.proj-lime .proj-plane::before,
.proj-lime .proj-plane::after { background: rgba(9, 10, 10, 0.7); }
.proj-lime .proj-plane:hover,
.proj-lime .proj-plane:focus-visible,
.proj-lime .proj-plane.is-tracking {
  border-color: var(--ink);
  box-shadow: var(--card-shadow-x) var(--card-shadow-y) 0 rgba(9, 10, 10, 0.3);
}
.proj-outline .proj-plane { background: transparent; }

.proj-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font: 400 10px/1 var(--mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.proj-kind { color: var(--lime); }
.proj-lime .proj-kind { color: var(--ink); }
.proj-ver { color: var(--dim); }
.proj-lime .proj-ver { color: rgba(9, 10, 10, 0.6); }
.proj h3 {
  font-size: clamp(1.7rem, 2.7vw, 2.6rem);
  line-height: 1;
  letter-spacing: 0;
}
.proj p {
  margin: 0;
  max-width: 42ch;
  color: #a7aca4;
  font-size: 13.5px;
  line-height: 1.75;
}
.proj-lime p { color: rgba(9, 10, 10, 0.72); }
.proj-coord {
  margin-top: auto;
  padding: 10px 12px;
  border: 1px solid var(--line);
  color: #c9cec4;
  font-size: 11.5px;
  letter-spacing: 0.02em;
  word-break: break-all;
}
.proj-lime .proj-coord { border-color: rgba(9, 10, 10, 0.3); color: rgba(9, 10, 10, 0.82); }
.proj-link, .proj-note {
  align-self: flex-start;
  font: 400 11px/1 var(--mono);
  letter-spacing: 0.08em;
}
.proj-link {
  display: inline-flex;
  gap: 9px;
  padding-bottom: 5px;
  border-bottom: 1px solid rgba(233, 232, 226, 0.4);
  color: var(--paper);
  transition: gap 180ms ease, color 180ms ease;
}
.proj-link:hover { gap: 15px; color: var(--lime); }
.proj-lime .proj-link { color: var(--ink); border-color: rgba(9, 10, 10, 0.5); }
.proj-lime .proj-link:hover { color: var(--ink); }
.proj-note { color: var(--dim); }
.proj-lime .proj-note { color: rgba(9, 10, 10, 0.6); }

/* Collapsed inside the singularity. --cx / --cy are the measured
   offsets from the card's own centre to the hole's centre. */
.orbit-grid.is-armed .proj {
  opacity: 0;
  transform: translate(var(--cx, 0px), var(--cy, 0px)) scale(0.04);
}
.orbit-grid.is-absorbed .proj {
  opacity: 0;
  transform: translate(var(--cx, 0px), var(--cy, 0px)) scale(0.04) rotate(28deg);
  transition:
    opacity 620ms ease,
    transform 820ms cubic-bezier(0.7, 0, 0.84, 0);
}

/* Dependency cascade, shifted left: Kedge sits on top of Khromia, mirroring
   how the bridge library stacks on the components it delegates to. A tall
   side ledger on the right carries the live Minecraft world and Cynic.
   Rotations use the standalone `rotate` property so the eject/absorb
   transforms and hover tilt on .proj-plane keep composing untouched. */
.orbit-lower {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(250px, 4fr);
  gap: var(--q-gap);
  align-items: stretch;
  margin-top: clamp(64px, 9vw, 128px);
}
.orbit-stack .proj { min-height: 300px; }
.orbit-stack .proj:nth-child(1) {
  position: relative;
  z-index: 3;
  width: min(78%, 520px);
}
.orbit-stack .proj:nth-child(2) {
  position: relative;
  z-index: 2;
  width: min(78%, 520px);
  margin-left: auto;
  margin-top: clamp(-96px, -7vw, -60px);
}
.orbit-stack .proj:nth-child(1) .proj-plane { rotate: -1.3deg; }
.orbit-stack .proj:nth-child(2) .proj-plane { rotate: 1deg; }
.orbit-stack .proj:hover,
.orbit-stack .proj:focus-within { z-index: 5; }

.proj-side .proj-plane {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 30px;
  min-height: 100%;
  background: transparent;
}
.side-item {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.side-item + .side-item {
  padding-top: 28px;
  border-top: 1px solid var(--line);
}
.proj-side h3 { font-size: clamp(1.4rem, 2vw, 1.9rem); }
.proj-side .proj-coord { margin-top: 0; }

.mc-status {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  color: var(--dim);
  font: 400 11px/1.4 var(--mono);
  letter-spacing: 0.04em;
}
.mc-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #4a4f46;
}
.mc-dot[data-state="online"] {
  background: var(--lime);
  box-shadow: 0 0 0 0 rgba(216, 243, 106, 0.5);
  animation: mc-pulse 2.4s ease-out infinite;
}
.mc-dot[data-state="pending"] { background: #8a9084; }
.mc-dot[data-state="offline"] { background: #7a4a4a; }
@keyframes mc-pulse {
  0% { box-shadow: 0 0 0 0 rgba(216, 243, 106, 0.45); }
  70% { box-shadow: 0 0 0 9px rgba(216, 243, 106, 0); }
  100% { box-shadow: 0 0 0 0 rgba(216, 243, 106, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .mc-dot[data-state="online"] { animation: none; }
}

/* ------------------------------------------------------------
   PHASE 2 / KODEHEAD
   One product identity and three uneven capability rows.
   ------------------------------------------------------------ */
.kodehead-showcase { padding-block: clamp(110px, 15vh, 190px); }
.product-focus {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(260px, 0.65fr);
  align-items: center;
  gap: clamp(44px, 8vw, 132px);
  margin-bottom: clamp(64px, 9vw, 120px);
}
.product-focus-copy p {
  max-width: 52ch;
  margin: 28px 0 34px;
  color: #a7aca4;
  font-size: 14px;
  line-height: 1.85;
}
.kodehead-identity {
  justify-self: end;
  width: min(100%, 380px);
  margin: 0;
}
.kodehead-identity .particle-mark {
  width: 100%;
  box-shadow: 18px 18px 0 rgba(216, 243, 106, 0.13);
}
.kodehead-identity figcaption {
  margin-top: 18px;
  color: var(--muted);
  font: 400 10px/1.4 var(--mono);
  letter-spacing: var(--q-track);
  text-transform: uppercase;
}
.capability-rows {
  display: grid;
  grid-template-columns: 5fr 4fr 3fr;
  align-items: start;
  gap: var(--q-gap);
}
.capability-rows article {
  min-height: 150px;
  padding: 22px 0 0;
  border-top: var(--q-border) solid rgba(233, 232, 226, 0.3);
}
.capability-rows article:nth-child(2) { margin-top: 36px; }
.capability-rows article:nth-child(3) { margin-top: 72px; }
.capability-rows h3,
.component-ledger h3 {
  margin-bottom: 14px;
  color: var(--lime);
  font: 500 11px/1 var(--mono);
  letter-spacing: var(--q-track);
  text-transform: uppercase;
}
.capability-rows p,
.component-ledger p {
  margin: 0;
  color: #afb4aa;
  font-size: 13px;
  line-height: 1.75;
}

/* ------------------------------------------------------------
   PHASE 3 / KHROMIA
   An asymmetric component ledger beside the real Gradle entry.
   ------------------------------------------------------------ */
.khromia { padding-block: clamp(110px, 15vh, 190px); }
.khromia h2 { margin-bottom: clamp(54px, 8vw, 104px); }
.khromia-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(300px, 0.75fr);
  gap: clamp(42px, 8vw, 128px);
  align-items: start;
}
.component-ledger { display: grid; }
.component-ledger article {
  display: grid;
  grid-template-columns: minmax(120px, 0.45fr) minmax(0, 1fr);
  gap: 24px;
  padding: 24px 0;
  border-top: var(--q-border) solid var(--line);
}
.component-ledger h3 { margin: 3px 0 0; }
.component-ledger p { font-family: var(--mono); font-size: 12px; }
.install { display: grid; gap: 18px; }
.install-label {
  margin: 0;
  color: var(--muted);
  font: 400 10px/1 var(--mono);
  letter-spacing: var(--q-track);
  text-transform: uppercase;
}
.install-code {
  margin: 0;
  padding: 22px;
  overflow-x: auto;
  border: var(--q-border) solid var(--line);
  background: #1b1c15;
  color: #c9cec4;
  font-size: 12.5px;
  line-height: 1.8;
}
.install-quickstart {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px 14px;
  margin: 0;
  color: var(--muted);
  font: 400 10px/1.6 var(--mono);
  letter-spacing: var(--q-track);
  text-transform: uppercase;
}
.install-quickstart code {
  color: var(--lime);
  font-size: 11px;
  letter-spacing: 0;
  text-transform: none;
  overflow-wrap: anywhere;
}

/* ------------------------------------------------------------
   PHASE 4 / DOT MATRIX
   The headline is drawn as real dots on a canvas.
   ------------------------------------------------------------ */
.matrix {
  display: grid;
  justify-items: center;
  gap: 26px;
  padding-block: clamp(120px, 17vh, 200px);
  text-align: center;
}
.dot-headline {
  display: block;
  width: min(100%, 940px);
  height: auto;
  image-rendering: pixelated;
}
.matrix-copy {
  max-width: 52ch;
  margin: 14px 0 0;
  color: #a7aca4;
  font-size: 14px;
  line-height: 1.9;
}
.matrix-links {
  display: flex;
  flex-wrap: wrap;
  gap: 18px 40px;
  margin-top: 34px;
}

/* ------------------------------------------------------------
   PHASE 4 / WHOIS
   The portrait resolves from 112 pixels, the name is set in a
   1-bit face, and the transcript below is typed onto real glass.
   ------------------------------------------------------------ */
.whois {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: clamp(24px, 4vw, 56px);
  width: min(100%, 1120px);
  margin-top: 52px;
  text-align: left;
}
.whois-portrait {
  display: grid;
  justify-items: start;
  gap: 12px;
  margin: 0;
}
.whois-frame {
  position: relative;
  display: block;
  width: clamp(128px, 15vw, 184px);
  aspect-ratio: 1;
  overflow: hidden;
  border: var(--q-border) solid var(--line);
  background: var(--ink-soft);
}
.whois-face {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: opacity 300ms ease;
}
.whois-face-sharp { z-index: 0; }
.whois-face-pixel {
  z-index: 1;
  image-rendering: pixelated;
}
.whois-frame:hover .whois-face-pixel { opacity: 0; }
.whois-scan {
  position: absolute;
  inset: 0;
  z-index: 2;
  overflow: hidden;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(3, 16, 10, 0.32) 0 1px,
    transparent 1px 3px
  );
}
.whois-scan::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 24%;
  background: linear-gradient(to bottom, transparent, rgba(191, 206, 127, 0.18), transparent);
  animation: whois-sweep 5.6s linear infinite;
}
@keyframes whois-sweep {
  from { transform: translateY(-110%); }
  to { transform: translateY(520%); }
}
.whois-portrait figcaption {
  color: var(--dim);
  font: 400 10px/1.4 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.whois-copy {
  display: grid;
  gap: 0;
  min-width: 0;
}
.whois-tag {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 18px;
  color: var(--muted);
  font: 400 10px/1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.whois-rule { width: 34px; height: 1px; background: var(--lime); }
.whois-name {
  margin: 0;
  color: var(--paper);
  font-family: var(--pixel);
  font-size: clamp(56px, 9vw, 104px);
  font-weight: 400;
  line-height: 0.94;
  letter-spacing: 0.04em;
  text-transform: none;
  text-shadow: 4px 4px 0 rgba(216, 243, 106, 0.16);
}
.whois-role {
  margin: 16px 0 0;
  color: var(--lime);
  font: 400 12px/1.5 var(--mono);
  letter-spacing: var(--q-track);
}
.whois-copy .matrix-copy {
  max-width: 60ch;
  margin-top: 22px;
  text-align: left;
}
.whois-facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--q-gap);
  width: min(100%, 1120px);
  margin: 46px 0 0;
  padding-top: 26px;
  border-top: var(--q-border) solid var(--line);
  text-align: left;
}
.whois-facts div {
  display: grid;
  gap: 8px;
  min-width: 0;
}
.whois-facts dt {
  color: var(--dim);
  font: 400 10px/1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.whois-facts dd {
  margin: 0;
  color: var(--paper);
  font: 400 12.5px/1.5 var(--mono);
  letter-spacing: 0.02em;
  overflow-wrap: anywhere;
}
/* The screen: real glass, drawn by crt.js. Before the module
   runs — or without WebGL — the transcript below is the screen. */

/* The stage is the untransformed box crt.js measures against: it
   keeps its layout size while the set inside it grows toward the
   viewport on the way in and shrinks again on the way out. The
   three custom properties are written from JS; without them the
   set simply sits still. */
.crt-stage {
  width: min(100%, 900px);
  margin-top: clamp(40px, 6vw, 64px);
  padding-block: clamp(18px, 5vh, 72px);
  text-align: left;
}
/* Lifted, the set has to clear its own section — and the section
   has to clear the ones after it, or the shade stops short. */
.crt-stage.is-lifted { z-index: 6; }
[data-phase-zone]:has(.crt-stage.is-lifted) { z-index: 6; }
/* Fixed, and behind the set: the room dims while the glass is open. */
.crt-shade {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: var(--crt-open, 0);
  background:
    radial-gradient(120% 90% at 50% 50%, rgba(3, 8, 5, 0.34) 0%, rgba(3, 8, 5, 0.86) 78%),
    rgba(3, 8, 5, 0.2);
  transition: opacity 120ms linear;
}
.crt {
  transform: translateY(var(--crt-lift, 0px)) scale(var(--crt-scale, 1));
  transform-origin: 50% 50%;
  will-change: transform;
}
.crt-bezel {
  position: relative;
  aspect-ratio: 16 / 10;
  min-height: 250px;
  overflow: hidden;
  border: var(--q-border) solid rgba(199, 200, 184, 0.26);
  background: #07100b;
  box-shadow: 0 26px 64px -34px rgba(141, 240, 180, 0.34);
}
/* Wide open, the phosphor spills into the darkened room. */
.crt-stage.is-lifted .crt-bezel {
  box-shadow:
    0 26px 64px -34px rgba(141, 240, 180, 0.34),
    0 0 calc(70px * var(--crt-open, 0)) rgba(141, 240, 180, calc(0.34 * var(--crt-open, 0)));
}
.crt-bezel::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  box-shadow:
    inset 0 0 46px rgba(0, 0, 0, 0.62),
    inset 0 0 0 1px rgba(199, 200, 184, 0.1);
}
.crt-glass {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: block;
  width: 100%;
  height: 100%;
}
.crt[data-crt-state="fallback"] .crt-glass { display: none; }
.crt-transcript {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: auto;
  padding: clamp(16px, 3vw, 32px);
  color: #8df0b4;
  font: 400 clamp(10px, 1.4vw, 13px)/1.75 var(--mono);
  white-space: pre-wrap;
  background: #03100a;
}
.crt-transcript p { margin: 0; min-height: 1.75em; }
.crt-transcript i { font-style: normal; }
.crt-transcript [data-crt-tone="amber"] { color: #ffba5e; }
.crt-transcript [data-crt-tone="paper"] { color: #eafff3; }
.crt-transcript [data-crt-tone="dim"] { color: #5f9c78; }
/* Once the glass is live the transcript stays for assistive tech. */
.crt[data-crt-state="ready"] .crt-transcript {
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.crt-panel {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 14px;
}
.crt-label {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  color: var(--dim);
  font: 400 10px/1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.crt-led {
  width: 6px;
  height: 6px;
  background: #8df0b4;
  box-shadow: 0 0 8px rgba(141, 240, 180, 0.75);
  animation: crt-led 2.4s steps(2, end) infinite;
}
@keyframes crt-led {
  0%, 68% { opacity: 1; }
  69%, 100% { opacity: 0.32; }
}
.crt-replay {
  padding: 9px 16px;
  border: var(--q-border) solid var(--line);
  border-radius: var(--radius);
  background: transparent;
  color: var(--lime);
  font: 400 11px/1 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 180ms ease, color 180ms ease, border-color 180ms ease;
}
.crt-replay:hover {
  border-color: var(--lime);
  background: var(--lime);
  color: var(--ink);
}
.crt-replay:focus-visible {
  outline: 2px solid var(--lime);
  outline-offset: 3px;
}
.crt[data-crt-state="fallback"] .crt-replay { display: none; }
.stack-index {
  position: relative;
  isolation: isolate;
  width: min(100%, 1120px);
  margin-top: 96px;
  padding-bottom: clamp(34px, 5vw, 72px);
  scroll-margin-top: 88px;
  text-align: left;
}
.stack-index::before {
  content: "";
  position: absolute;
  inset: 24% -3vw -56px;
  z-index: 0;
  pointer-events: none;
  opacity: 0.32;
  background-image:
    repeating-conic-gradient(rgba(233, 232, 226, 0.08) 0 25%, transparent 0 50%),
    repeating-conic-gradient(rgba(216, 243, 106, 0.05) 0 25%, transparent 0 50%);
  background-position: 0 0, 14px 14px;
  background-size: 28px 28px, 56px 56px;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.12) 30%, #000 100%);
  mask-image: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 0.12) 30%, #000 100%);
}
.stack-index > * { position: relative; z-index: 1; }
.stack-intro {
  display: grid;
  gap: 22px;
  max-width: 720px;
}
.stack-intro h3 {
  margin: 0;
  color: var(--paper);
  font-size: 52px;
  line-height: 1.02;
  letter-spacing: 0;
}
.stack-intro h3 span {
  color: var(--lime);
  text-shadow: 4px 4px 0 rgba(216, 243, 106, 0.12);
}
.stack-intro p {
  max-width: 58ch;
  margin: 0;
  color: #a7aca4;
  font-size: 14px;
  line-height: 1.85;
}
.stack-map {
  position: relative;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  align-items: start;
  gap: 46px 28px;
  margin-top: 70px;
}
.stack-cluster {
  --stack-pixel: 2px;
  --stack-rule: var(--line);
  position: relative;
  grid-column: span 7;
  min-width: 0;
  min-height: 170px;
  padding: 24px 20px 22px;
  cursor: pointer;
  outline: none;
  background: var(--ink);
  transition: background-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}
.stack-cluster::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  background-color: var(--stack-rule);
  transform-origin: left;
  transition: height 140ms ease;
}
.stack-cluster::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  width: calc(var(--stack-pixel) * 3);
  height: calc(var(--stack-pixel) * 3);
  pointer-events: none;
  background:
    linear-gradient(var(--ink) 0 0) 100% 100% / calc(var(--stack-pixel) * 2) var(--stack-pixel) no-repeat,
    linear-gradient(var(--ink) 0 0) 100% 100% / var(--stack-pixel) calc(var(--stack-pixel) * 2) no-repeat;
}
.stack-cluster[data-stack-depth="2"] {
  --stack-pixel: 4px;
}
.stack-cluster[data-stack-depth="2"]::before {
  -webkit-mask-image: repeating-linear-gradient(90deg, #000 0 44px, transparent 44px 48px);
  mask-image: repeating-linear-gradient(90deg, #000 0 44px, transparent 44px 48px);
}
.stack-cluster[data-stack-depth="3"] {
  --stack-pixel: 6px;
}
.stack-cluster[data-stack-depth="3"]::before {
  -webkit-mask-image: repeating-linear-gradient(90deg, #000 0 28px, transparent 28px 34px);
  mask-image: repeating-linear-gradient(90deg, #000 0 28px, transparent 28px 34px);
}
.stack-cluster[data-stack-depth="4"] {
  --stack-pixel: 8px;
}
.stack-cluster[data-stack-depth="4"]::before {
  -webkit-mask-image: repeating-linear-gradient(90deg, #000 0 20px, transparent 20px 28px);
  mask-image: repeating-linear-gradient(90deg, #000 0 20px, transparent 20px 28px);
}
.stack-cluster:hover,
.stack-cluster:focus-visible {
  --stack-rule: rgba(216, 243, 106, 0.68);
  background: #12150e;
  box-shadow: calc(var(--stack-pixel) * -1) var(--stack-pixel) 0 rgba(216, 243, 106, 0.08);
  transform: translateY(calc(var(--stack-pixel) * -0.5));
}
.stack-cluster:hover::before,
.stack-cluster:focus-visible::before {
  height: 3px;
}
.stack-cluster:focus-visible { outline: 1px solid rgba(216, 243, 106, 0.55); }
.stack-cluster.is-selected {
  --stack-rule: var(--lime);
  background-color: #202414;
  background-image: repeating-conic-gradient(rgba(216, 243, 106, 0.055) 0 25%, transparent 0 50%);
  background-size: calc(var(--stack-pixel) * 4) calc(var(--stack-pixel) * 4);
  box-shadow: calc(var(--stack-pixel) * -1) var(--stack-pixel) 0 rgba(216, 243, 106, 0.14);
  transform: translateY(calc(var(--stack-pixel) * -0.5));
}
.stack-cluster.is-selected::before {
  height: 4px;
}
.stack-cluster:nth-child(2) {
  grid-column: 8 / -1;
  margin-top: 52px;
}
.stack-cluster:nth-child(3) {
  grid-column: 2 / span 5;
  margin-top: 12px;
}
.stack-cluster:nth-child(4) {
  grid-column: 7 / -1;
  margin-top: 48px;
  min-height: 190px;
}
.stack-cluster h4 {
  margin: 0 0 14px;
  color: var(--paper);
  font-size: 20px;
  line-height: 1.2;
  letter-spacing: 0;
  transition: color 180ms ease;
}
.stack-cluster[data-stack-depth="3"] h4,
.stack-cluster[data-stack-depth="4"] h4 {
  font-family: var(--mono);
  font-size: 18px;
  font-weight: 500;
}
.stack-cluster p {
  max-width: 50ch;
  margin: 0 0 18px;
  color: #92978f;
  font-size: 13px;
  line-height: 1.75;
}
.stack-cluster code {
  display: block;
  overflow-wrap: anywhere;
  color: var(--lime);
  font: 400 11px/1.8 var(--mono);
  letter-spacing: 0;
  font-variant-ligatures: none;
}
.stack-cluster[data-stack-depth="3"] code { letter-spacing: 0.035em; }
.stack-cluster[data-stack-depth="4"] code { letter-spacing: 0.07em; }
.stack-cluster.is-selected h4 { color: var(--lime); }

/* A chronological proof of work, kept as rows so the section stays editorial. */
.field-log {
  width: min(100%, 1120px);
  margin-top: clamp(92px, 12vw, 160px);
  scroll-margin-top: 88px;
  text-align: left;
}
.field-log-head {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 32px;
  padding-top: 24px;
  border-top: 2px solid var(--line);
}
.field-log-head h3 {
  color: var(--paper);
  font-size: clamp(2rem, 4vw, 3.4rem);
  line-height: 1;
}
.field-log-head p {
  max-width: 42ch;
  margin: 16px 0 0;
  color: #92978f;
  font-size: 13px;
  line-height: 1.75;
}
.field-log-head .text-link { flex: 0 0 auto; margin-bottom: 2px; }
.field-log-list {
  margin-top: 34px;
  border-top: 1px solid var(--line);
}
.field-entry {
  display: grid;
  grid-template-columns: minmax(112px, 0.25fr) minmax(0, 1fr) minmax(132px, 0.28fr);
  align-items: start;
  gap: 28px;
  padding: 24px 0;
  border-bottom: 1px solid var(--line);
  color: inherit;
  transition: background-color 180ms ease, border-color 180ms ease, transform 180ms ease;
}
.field-entry:hover,
.field-entry:focus-visible {
  border-bottom-color: rgba(216, 243, 106, 0.65);
  background: rgba(216, 243, 106, 0.045);
  transform: translateX(8px);
}
.field-entry:focus-visible { outline: 1px solid var(--paper); outline-offset: 5px; }
.field-entry time,
.field-entry-action {
  color: var(--muted);
  font: 400 10px/1.4 var(--mono);
  letter-spacing: 0.12em;
}
.field-entry h4 {
  margin: 0 0 8px;
  color: var(--paper);
  font-size: 19px;
  line-height: 1.2;
}
.field-entry p {
  max-width: 58ch;
  margin: 0;
  color: #a7aca4;
  font-size: 13px;
  line-height: 1.75;
}
.field-entry-action {
  justify-self: end;
  color: var(--lime);
  letter-spacing: 0.04em;
  text-align: right;
}
.field-entry-action span { margin-left: 7px; }
.has-field-log-motion .field-entry {
  opacity: 0;
  transform: translateY(18px);
}
.has-field-log-motion .field-entry.is-visible {
  opacity: 1;
  transform: translateY(0);
  transition-delay: 80ms;
}

/* ------------------------------------------------------------
   PHASE 5 / PIXEL SCENE
   Message stars fall toward the restored pixel black hole above the planet.
   The observer remains the entry point for the conversation layer.
   ------------------------------------------------------------ */
.scene {
  --scene-seam: clamp(60px, 8vh, 82px);
  position: relative;
  min-height: 100dvh;
  display: grid;
  align-content: end;
  justify-items: center;
  gap: 22px;
  padding-block: 0 clamp(48px, 8vh, 90px);
  overflow: visible;
  cursor: crosshair;
}
.scene.is-hole-hover { cursor: pointer; }
.scene [hidden] { display: none !important; }
.scene::after {
  content: '';
  position: absolute;
  inset: calc(-1 * var(--scene-seam)) 0 auto;
  z-index: 1;
  height: var(--scene-seam);
  pointer-events: none;
  background: rgba(9, 10, 10, 0.015);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 18%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 18%, transparent 100%);
}
.scene-canvas {
  position: absolute;
  top: calc(-1 * var(--scene-seam));
  right: 0;
  bottom: auto;
  left: 0;
  z-index: 0;
  width: 100%;
  height: calc(100% + var(--scene-seam));
  display: block;
  image-rendering: pixelated;
  pointer-events: none;
}
.star-message-canvas {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  display: block;
  cursor: crosshair;
  image-rendering: pixelated;
}
.star-hit-layer {
  position: absolute;
  inset: 0;
  z-index: 3;
  overflow: hidden;
  pointer-events: none;
}
.star-hit-target {
  position: absolute;
  top: 0;
  left: 0;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 0;
  outline: 0;
  background: transparent;
  cursor: pointer;
  pointer-events: auto;
  will-change: transform;
}
.star-hit-target:hover,
.star-hit-target:focus-visible {
  border: 1px solid rgba(216, 243, 106, 0.7);
  background:
    linear-gradient(var(--lime), var(--lime)) 2px 2px / 4px 1px no-repeat,
    linear-gradient(var(--lime), var(--lime)) 2px 2px / 1px 4px no-repeat,
    linear-gradient(var(--lime), var(--lime)) calc(100% - 6px) calc(100% - 3px) / 4px 1px no-repeat,
    linear-gradient(var(--lime), var(--lime)) calc(100% - 3px) calc(100% - 6px) / 1px 4px no-repeat;
}
.star-composer,
.figure-dialogue,
.star-tooltip {
  position: absolute;
  z-index: 7;
  border: 1px solid #667037;
  border-radius: 0;
  background: rgba(8, 10, 9, 0.97);
  color: var(--paper);
  box-shadow: 8px 8px 0 rgba(216, 243, 106, 0.1);
  cursor: default;
}
.star-composer {
  width: min(330px, calc(100vw - 24px));
  padding: 14px;
}
.star-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 26px;
  margin-bottom: 12px;
  border-bottom: 2px solid #343a24;
}
.star-panel-head p {
  margin: 0;
  color: var(--lime);
  font: 500 10px/1 var(--mono);
  letter-spacing: 0.14em;
}
.star-icon-button {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-left: 1px solid #343a24;
  border-radius: 0;
  background: transparent;
  color: #aeb3aa;
  font: 400 19px/1 var(--sans);
  cursor: pointer;
}
.star-icon-button:hover,
.star-icon-button:focus-visible {
  outline: 0;
  color: var(--ink);
  background: var(--lime);
}
.star-composer textarea {
  width: 100%;
  min-height: 76px;
  max-height: 140px;
  display: block;
  resize: vertical;
  padding: 11px;
  border: 1px solid #30362d;
  border-radius: 0;
  outline: 0;
  background: #050706;
  color: var(--paper);
  caret-color: var(--lime);
  font: 400 13px/1.65 var(--sans);
  letter-spacing: 0;
}
.star-composer textarea:focus { border-color: var(--lime); }
.star-colors {
  display: flex;
  gap: 12px;
  margin: 14px 0;
  padding: 0;
  border: 0;
}
.star-colors label {
  position: relative;
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  cursor: pointer;
}
.star-colors input {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}
.star-swatch {
  width: 12px;
  height: 12px;
  display: block;
  border: 2px solid #13140d;
  outline: 1px solid #4b5048;
}
.star-swatch-lime { background: #bfce7f; }
.star-swatch-gold { background: #f7b84e; }
.star-swatch-ice { background: #88d9ff; }
.star-swatch-rose { background: #ff6f91; }
.star-swatch-violet { background: #ba9cff; }
.star-colors input:checked + .star-swatch {
  width: 18px;
  height: 18px;
  outline: 2px solid var(--paper);
  outline-offset: 2px;
}
.star-colors input:focus-visible + .star-swatch { outline-color: var(--lime); }
.star-composer-foot {
  min-height: 32px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.star-composer-foot output {
  color: #747a72;
  font: 400 10px/1 var(--mono);
  letter-spacing: 0;
}
.star-submit,
.figure-dialogue-form button {
  min-width: 70px;
  min-height: 32px;
  padding: 0 14px;
  border: 1px solid var(--lime);
  border-radius: 0;
  background: var(--lime);
  color: var(--ink);
  font: 600 11px/1 var(--sans);
  letter-spacing: 0;
  cursor: pointer;
}
.star-submit:hover,
.figure-dialogue-form button:hover { background: #e5ff84; }
.star-submit:disabled,
.figure-dialogue-form button:disabled { opacity: 0.45; cursor: wait; }
.star-tooltip {
  width: min(292px, calc(100vw - 24px));
  padding: 12px 14px;
  pointer-events: auto;
  box-shadow: 5px 5px 0 rgba(216, 243, 106, 0.08);
}
.star-tooltip-head {
  min-height: 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 7px;
}
.star-tooltip-head > p {
  margin: 0;
  color: var(--lime);
  font: 500 9px/1 var(--mono);
  letter-spacing: 0.12em;
}
.star-tooltip-head .star-icon-button {
  width: 24px;
  height: 24px;
  flex: 0 0 24px;
}
.star-tooltip [data-star-tooltip-messages] {
  max-height: 170px;
  overflow: auto;
}
.star-tooltip [data-star-tooltip-messages] p {
  display: grid;
  grid-template-columns: 7px 1fr;
  gap: 9px;
  align-items: start;
  margin: 0;
  padding: 7px 0;
  border-top: 1px solid #242824;
  color: #c5c8c1;
  font: 400 12px/1.55 var(--sans);
  letter-spacing: 0;
  overflow-wrap: anywhere;
}
.star-tooltip [data-star-tooltip-messages] p > span:first-child {
  width: 5px;
  height: 5px;
  margin-top: 6px;
}
.star-tooltip-add {
  width: 100%;
  min-height: 32px;
  margin-top: 10px;
  border: 1px solid var(--lime);
  border-radius: 0;
  background: var(--lime);
  color: var(--ink);
  font: 600 11px/1 var(--sans);
  letter-spacing: 0;
  cursor: pointer;
}
.star-tooltip-add:hover,
.star-tooltip-add:focus-visible {
  border-color: var(--lime);
  background: #e5ff84;
  outline: 1px solid var(--paper);
  outline-offset: 2px;
}
.figure-dialogue {
  width: min(370px, calc(100vw - 24px));
  padding: 14px;
}
.figure-dialogue-drag-handle {
  cursor: grab;
  touch-action: none;
  user-select: none;
}
.figure-dialogue.is-dragging,
.figure-dialogue.is-dragging .figure-dialogue-drag-handle {
  cursor: grabbing;
}
.figure-dialogue-drag-handle .star-icon-button { cursor: pointer; }
.figure-dialogue::after {
  content: '';
  position: absolute;
  top: calc(var(--bubble-tip-y, 50%) - 6px);
  left: -7px;
  width: 12px;
  height: 12px;
  border-left: 1px solid #667037;
  border-bottom: 1px solid #667037;
  background: #080a09;
  transform: rotate(45deg);
}
.figure-dialogue.is-left-of-figure::after {
  right: -7px;
  left: auto;
  border: 0;
  border-top: 1px solid #667037;
  border-right: 1px solid #667037;
}
.figure-dialogue-log {
  max-height: 230px;
  overflow: auto;
  padding-right: 4px;
  scrollbar-width: thin;
  scrollbar-color: #4c5430 #080a09;
}
.figure-dialogue-log p {
  width: fit-content;
  max-width: 92%;
  box-sizing: border-box;
  margin: 0 0 10px;
  padding: 9px 10px;
  border-left: 2px solid #4b542c;
  background: #10130e;
  color: #c6cac1;
  font: 400 12px/1.65 var(--sans);
  letter-spacing: 0;
  overflow-wrap: anywhere;
}
.figure-dialogue-log p span { display: block; }
.figure-dialogue-log .figure-question {
  margin-left: auto;
  border-left-color: #5d665f;
  background: #171b18;
  color: var(--paper);
}
.figure-dialogue-log .figure-reply { border-left-color: var(--lime); }
.figure-dialogue-log .figure-reaction { border-left-color: #f7b84e; }
.figure-dialogue-log .figure-reply.is-streaming {
  overflow: hidden;
  will-change: width, height;
}
.figure-dialogue-log .figure-reply.is-streaming::after {
  content: '';
  width: 5px;
  height: 9px;
  display: inline-block;
  margin-left: 5px;
  background: var(--lime);
  vertical-align: -1px;
  animation: figure-stream-pulse 0.8s steps(2, end) infinite;
}
@keyframes figure-stream-pulse {
  50% { opacity: 0.2; }
}
.figure-dialogue-form {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid #30362d;
}
.figure-dialogue-form input {
  min-width: 0;
  height: 34px;
  padding: 0 10px;
  border: 1px solid #30362d;
  border-radius: 0;
  outline: 0;
  background: #050706;
  color: var(--paper);
  caret-color: var(--lime);
  font: 400 12px/1 var(--sans);
  letter-spacing: 0;
}
.figure-dialogue-form input:focus { border-color: var(--lime); }
.star-status {
  position: absolute;
  right: 18px;
  bottom: 18px;
  z-index: 8;
  max-width: min(360px, calc(100% - 36px));
  margin: 0;
  padding: 10px 13px;
  border-left: 3px solid var(--lime);
  background: #11140e;
  color: var(--paper);
  font: 400 12px/1.5 var(--sans);
  letter-spacing: 0;
}
.scene-caption {
  position: relative;
  z-index: 4;
  margin: 0;
  pointer-events: none;
  color: rgba(233, 232, 226, 0.55);
  font: 400 11px/1 var(--mono);
  letter-spacing: 0.42em;
  text-transform: uppercase;
}

/* ------------------------------------------------------------
   FOOTER
   ------------------------------------------------------------ */
.site-footer {
  position: relative;
  z-index: 1;
  min-height: 120px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 24px;
  padding: 34px clamp(20px, 6vw, 96px);
  border-top: 4px solid var(--line);
  background: var(--ink);
  color: var(--dim);
}
.site-footer p { margin: 0; font: 400 10px/1.4 var(--mono); letter-spacing: 0.08em; }
.footer-links { display: flex; gap: 24px; }

/* ------------------------------------------------------------
   RESPONSIVE
   Every multi-column layout collapses explicitly.
   ------------------------------------------------------------ */
@media (max-width: 980px) {
  .hero-copy { width: min(600px, 74vw); }
  .orbit-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .orbit-grid > .proj:nth-child(n) { grid-column: span 1; margin-top: 0; }
  .orbit-lower { grid-template-columns: 1fr; }
  .proj-side .proj-plane { min-height: 0; }
  .product-focus { grid-template-columns: minmax(0, 1fr) minmax(220px, 0.55fr); }
  .khromia-layout { grid-template-columns: 1fr; }
}

@media (max-width: 680px) {
  body { font-size: 15px; }
  .site-header { height: 60px; width: calc(100% - 28px); gap: 20px; }
  .desktop-nav { display: none; }
  .menu-toggle { display: block; margin-left: auto; }
  .mobile-menu {
    position: fixed;
    top: 60px; right: 14px; left: 14px;
    display: grid;
    max-height: 0;
    overflow: hidden;
    background: rgba(9, 10, 10, 0.97);
    border-bottom: 0 solid var(--line);
    transition: max-height 300ms ease;
  }
  .mobile-menu.is-open { max-height: 210px; border-bottom-width: 2px; }
  .mobile-menu a {
    padding: 17px 16px;
    border-bottom: 1px solid var(--line);
    color: #adb1a9;
    font: 400 12px/1 var(--mono);
    letter-spacing: 0.08em;
  }
  .hero { padding-top: 60px; }
  .hero-copy { width: 100%; }
  .hero-lede { max-width: 100%; font-size: 14px; }
  .hero-actions { gap: 10px; }
  .button { width: 100%; }
  .orbit-grid { grid-template-columns: 1fr; }
  .orbit-grid > .proj:nth-child(n) { grid-column: span 1; min-height: 0; }
  .orbit-lower { grid-template-columns: 1fr; }
  .orbit-stack .proj { min-height: 0; }
  .orbit-stack .proj:nth-child(1),
  .orbit-stack .proj:nth-child(2) { width: min(100%, 460px); }
  .orbit-stack .proj:nth-child(2) { margin-top: -52px; }
  .product-focus { grid-template-columns: 1fr; gap: 42px; }
  .kodehead-identity { justify-self: start; width: min(72vw, 280px); }
  .capability-rows { grid-template-columns: 1fr; }
  .capability-rows article { min-height: 0; }
  .capability-rows article:nth-child(2),
  .capability-rows article:nth-child(3) { margin-top: 0; }
  .component-ledger article { grid-template-columns: 1fr; gap: 6px; }
  .install-code { padding: 16px; font-size: 11.5px; }
  .matrix { padding-block: 110px 150px; }
  .whois {
    grid-template-columns: 1fr;
    gap: 26px;
    margin-top: 38px;
  }
  .whois-name { font-size: clamp(44px, 15vw, 68px); }
  .whois-copy .matrix-copy { margin-top: 18px; }
  .whois-facts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-top: 34px;
  }
  .crt-bezel {
    aspect-ratio: 5 / 6;
    min-height: 0;
  }
  .crt-panel { gap: 12px; }
  .stack-index { margin-top: 72px; padding-bottom: 28px; }
  .stack-index::before { inset-inline: -20px; }
  .stack-intro h3 { font-size: 34px; line-height: 1.08; }
  .stack-intro h3 span { text-shadow: 3px 3px 0 rgba(216, 243, 106, 0.12); }
  .stack-map { grid-template-columns: 1fr; gap: 34px; margin-top: 52px; }
  .stack-cluster,
  .stack-cluster:nth-child(2),
  .stack-cluster:nth-child(3),
  .stack-cluster:nth-child(4) {
    grid-column: 1;
    margin-top: 0;
    min-height: 0;
    padding-inline: 16px;
  }
  .field-log { margin-top: 84px; }
  .field-log-head { display: block; }
  .field-log-head .text-link { margin-top: 22px; }
  .field-entry {
    grid-template-columns: 1fr;
    gap: 10px;
    padding-block: 22px;
  }
  .field-entry-action { justify-self: start; text-align: left; }
  .site-footer { justify-content: flex-start; gap: 18px; }
  .footer-links { width: 100%; justify-content: space-between; gap: 14px; }
  .scene-caption { letter-spacing: 0.28em; font-size: 10px; }
  .star-composer,
  .figure-dialogue {
    top: auto !important;
    right: 12px;
    bottom: 18px;
    left: 12px !important;
    width: auto;
    max-height: calc(100dvh - 36px);
  }
  .figure-dialogue::after { display: none; }
  .figure-dialogue-drag-handle {
    cursor: default;
    touch-action: auto;
  }
  .figure-dialogue-log { max-height: min(230px, 36dvh); }
  .star-tooltip { max-width: calc(100vw - 24px); }
}

/* ------------------------------------------------------------
   REDUCED MOTION
   The descent still reads, it just stops moving.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .bh-stage { transition: none; }
  .proj-plane { transform: none !important; will-change: auto; }
  .orbit-grid.is-armed .proj,
  .orbit-grid.is-absorbed .proj { opacity: 1; transform: none; }
  .star-hit-target { will-change: auto; }
  .crt { transform: none !important; will-change: auto; }
  .crt-shade { display: none; }
}

@media (hover: none) {
  .proj-plane::before,
  .proj-plane::after { display: none; }
}

@media (prefers-reduced-transparency: reduce) {
  .scene::after {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}
