/* daylight noise: the brand site's skin. Always the panels' black with gold (until 6 Oct 2026 it was GIF GIF GIF's
   cream by day; the user: "make it black always"). Behind the whole home page is its screen (.sky): black, gold,
   white pixel type. The mark is Space Mono Bold Italic (brand/). */

:root {
  --bg: rgb(12, 11, 9);
  --ink: rgb(238, 236, 228);
  --dim: rgb(163, 160, 148);
  --hair: rgb(42, 38, 30);
  --on: rgb(12, 11, 9);
  --screen: #0c0b09;
  --gold: #d4af37;
  --gold-hi: #f0d878;
  --gold-line: rgba(212, 175, 55, 0.45);
  --maxw: 1080px;
  --gutter: clamp(1rem, 4vw, 2rem);
  color-scheme: dark;
}

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

html { scroll-behavior: smooth; overflow-x: clip; touch-action: manipulation; }   /* manipulation: no double-tap zoom while spinning a model; pinch still zooms */   /* so body's own clip, below, stays on body */
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: "Poppins", system-ui, sans-serif;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;                  /* a model swung out past the side of the page is cut at its edge, and nothing scrolls sideways */
}

::selection { background: var(--gold); color: var(--screen); }

h1, h2, h3 { font-weight: 500; line-height: 1.25; }
h2 { font-size: clamp(1.6rem, 3.6vw, 2.4rem); margin-bottom: 1.2rem; }
h3 { font-size: 1rem; font-weight: 600; }
a { color: var(--ink); }
a:hover { font-style: italic; }
a:focus-visible, button:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
cite, i, em { font-style: italic; }

.module-name, .stage-title, .hello-link, .bench a, .bench-title {
  font-family: "Space Mono", ui-monospace, monospace; font-style: italic; font-weight: 700;
}

.skip {
  position: absolute; left: -9999px; top: 0.5rem; z-index: 100;
  background: var(--ink); color: var(--on); padding: 0.5rem 1rem; text-decoration: none;
}
.skip:focus { left: 0.5rem; }

/* ---------- the sky: the screen, fixed behind the whole page (main.js draws it, the mark scrolling in it) ---------- */
.sky {
  position: fixed; left: 0; top: 0; z-index: -2; pointer-events: none;
  width: 100%; height: 100vh; height: 100lvh;   /* lvh: a phone's toolbar coming and going doesn't resize it */
  background: var(--screen);
}
.sky::after, .mark::after {
  content: ""; position: absolute; inset: 0;
  background: repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.22) 0 1px, transparent 1px 3px);
}
#screen, #mark { display: block; width: 100%; height: 100%; image-rendering: pixelated; }

/* ---------- going to a module (main.js): its name taken into the screen, the page fading off the sky ----------
   Once the name has risen to where the module's page has its own, it moves to a layer of its own with the
   scanlines, and the module's page (module.css) holds the screen and that layer over itself and lets them go.
   Nothing else moves, coming back here or arriving from anywhere else. The opt-in to view transitions is in
   index.html's head. */
.mark {
  position: fixed; left: 0; top: 0; z-index: -2; pointer-events: none;   /* after the sky in the page, so in front of it */
  width: 100%; height: 100vh; height: 100lvh; display: none;
}
.leaving body > :not(.sky):not(.mark) { opacity: 0; transition: opacity 0.3s; }
/* Each part of the page is its own layer from the start, so the fade is only that layer's opacity. Made layers as
   the fade began, Safari left bits of the page drawn where they were (the lede's plain words, the email, the ends of
   the cards' rules) after the rest had gone (the user, 7 Oct 2026). The modules go under the rest, so a model swung
   out over the lede or the section after it stays behind their words, as when they shared one layer. */
.stage, .intro, .section { position: relative; z-index: 1; will-change: opacity; }
#modules { z-index: 0; }
.leaving .sky, .leaving .mark { z-index: 2; transition: z-index 0s 0.3s; }   /* and once it's faded, the sky over anything left */
.handed .mark { display: block; view-transition-name: signal-name; }
.handed .sky { view-transition-name: signal; }
.handed .sky::after { display: none; }      /* the name's layer has the scanlines now */
::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none; }
::view-transition-old(root) { display: none; }   /* the page left never shows through this one */

/* ---------- arriving from a module page (homeward.js) ----------
   The first frame is the module page in the screen's golds, and main.js's datamosh drags it out and heals it into
   the sky and the mark. Over it the browser holds the module page itself (.homecoming: the one view transition that
   shows the page left), and main.js clips this page to the blocks it has taken, a few more each frame, so the two
   pages mosh into each other. The hold is the longest it can take; main.js lets go as the last block goes. The
   words come in over it. */
.arriving body > :not(.sky):not(.mark) { opacity: 0; }
.arrived body > :not(.sky):not(.mark) { transition: opacity 0.6s; }
.homecoming::view-transition-old(root) { display: block; animation: hold 2s both; mix-blend-mode: normal; }
.homecoming::view-transition-new(root) { mix-blend-mode: normal; }
@keyframes hold { to { opacity: 1; } }

/* ---------- the header: room in the sky for the mark ---------- */
.stage {                          /* --mark-at: how far down it main.js draws the mark: low, so the first line follows it */
  position: relative; height: min(68vh, 720px); min-height: 320px; --mark-at: 0.72;
}
.stage-title {                     /* the mark as text until the screen draws it, then for screen readers only */
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: clamp(2.6rem, 10vw, 7rem); color: var(--gold); text-align: center;
}
.live .stage-title, .vh {
  clip: rect(0 0 0 0); clip-path: inset(50%); width: 1px; height: 1px; overflow: hidden; white-space: nowrap;
}
.vh { position: absolute; }        /* there for screen readers, not seen */

/* ---------- words that blip into other words (main.js) ---------- */
[data-alt] { position: relative; white-space: nowrap; }   /* relative: the real word, hidden (.vh) while it blips, stays in it */
.glitch { position: relative; display: inline-block; }   /* the stand-in: its room holds the width, its three cuts tear */
.glitch .cut { position: absolute; left: 0; top: 0; white-space: nowrap; display: none; }
.glitch.tearing .room { visibility: hidden; }
.glitch.tearing .cut { display: block; }
/* a link's underline doesn't reach into an inline-block, so a module name's is drawn on its stand-in again, and tears with it */
.module-name a .glitch > span, .bench a .glitch > span { text-decoration: underline 2px var(--gold-line); }
.module-name a:hover .glitch > span, .bench a:hover .glitch > span { text-decoration-color: var(--gold-hi); }

/* words over the sky get a little of the page's black round them */
.intro, .section { text-shadow: 0 0 2px var(--bg), 0 0 8px var(--bg); }

/* ---------- intro ---------- */
.intro {
  max-width: var(--maxw); margin: 0 auto; text-align: center;
  padding: clamp(1rem, 3vh, 2rem) var(--gutter) clamp(3rem, 8vh, 5rem);
}
.lede { max-width: 900px; margin: 0 auto; font-size: clamp(1.2rem, 2.8vw, 1.7rem); line-height: 1.4; text-wrap: balance; }

/* ---------- sections ---------- */
.section {
  max-width: var(--maxw); margin: 0 auto;
  padding: clamp(3.5rem, 9vh, 6.5rem) var(--gutter);
  border-top: 2px solid var(--hair);
}
.intro + .section { border-top: 0; }   /* no line under the lede */
.section-sub { max-width: 620px; color: var(--dim); margin-bottom: 1.8rem; }

/* ---------- links that go somewhere: the module names and the address, gold and underlined; a module name has an arrow after ---------- */
.module-name a, .hello-link a, .bench a {
  color: var(--gold);
  text-decoration: underline 2px var(--gold-line); text-underline-offset: 0.22em;
}
.module-name a:hover, .hello-link a:hover, .bench a:hover { color: var(--gold-hi); text-decoration-color: var(--gold-hi); }
.go {                              /* inline-block, so the underline stops before it */
  display: inline-block; margin-left: 0.4em; font-style: normal;
  transition: transform 0.2s ease-out;
}
a:hover .go, a:focus-visible .go { transform: translateX(0.3em); }
@media (prefers-reduced-motion: reduce) { .go { transition: none; } }

/* ---------- modules: each one a big stage, its model filling it (its panel until the model's up), its name underneath ---------- */
.module { margin-top: 1rem; text-align: center; }
.module + .module { margin-top: clamp(3rem, 7vh, 5rem); padding-top: clamp(3rem, 7vh, 5rem); border-top: 2px dashed var(--hair); }
.module-art {
  --stage: calc(min(70vh, 680px) - 3.2rem);   /* every stage one height, so every panel is drawn 3U at one scale */
  position: relative; height: var(--stage); min-height: calc(380px - 3.2rem);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.module-panel { position: relative; z-index: 1; display: block; max-width: 100%; background: var(--screen); border: 2px solid var(--hair); }
.module-panel:hover { border-color: var(--gold); }
.module-panel img { display: block; width: auto; max-width: 100%; height: auto; max-height: calc(var(--stage) - 1.8rem); }
.module-model { position: absolute; inset: 0; cursor: grab; }   /* the model stands on the page itself */
.module-model:active { cursor: grabbing; }
/* The canvas overhangs its stage by 30% of it on every side (OVER in main.js), so a model turned swings out
   over the page instead of being cut off. It draws behind the words (above the sky) and takes no clicks; the stage
   takes the drag. */
.module-model canvas {
  position: absolute; z-index: -1; pointer-events: none;
  left: -30%; top: -30%; width: 160%; height: 160%;
}
.module-name { font-size: clamp(2rem, 4.4vw, 3rem); line-height: 1.15; margin-top: clamp(1rem, 2.5vh, 1.6rem); }
.module-kind { font-size: 1.05rem; font-weight: 500; color: var(--ink); margin-top: 0.3rem; }
.module-hp { font-size: 0.75rem; letter-spacing: 0.06em; color: var(--dim); margin-top: 0.15rem; }   /* under the line, small: the user, 9 Oct 2026, wanted the width below the subtitle (until then it led, in white) */

.bench {                           /* the way to the bench (and back from it): a link the size of a module's line */
  margin-top: 3rem; padding: 1.4rem 1.4rem 1.2rem;
  border: 2px dashed var(--hair);
  color: var(--dim); font-size: 0.95rem; text-align: center;
}
.bench a { font-size: clamp(1.3rem, 3vw, 1.8rem); line-height: 1.3; }
.bench-sub { display: block; margin-top: 0.4rem; }

/* ---------- the bench (bench/index.html): the same cards as the home page's, smaller, in a grid ---------- */
.stage-short { height: min(44vh, 460px); min-height: 260px; --mark-at: 0.62; }   /* less sky: the mark smaller */
.stage-home { position: absolute; inset: 0; }   /* the mark in the sky goes home */
.bench-title { font-size: clamp(2.4rem, 6vw, 3.8rem); line-height: 1.1; color: var(--gold); margin-bottom: 0.8rem; }
.intro-sub { font-size: clamp(1.02rem, 2vw, 1.2rem); line-height: 1.45; color: var(--dim); max-width: 640px; margin: 0 auto; text-wrap: balance; }
.shelf {
  --u: min(280px, 52vw);           /* every panel's 3U height: every panel drawn at one scale, and a 20 HP one two to a phone */
  display: grid; align-items: start;
  grid-template-columns: repeat(auto-fill, minmax(calc(var(--u) * 0.79 + 4px), 1fr));   /* a 20 HP panel and its border */
  gap: clamp(2.4rem, 6vh, 3.6rem) clamp(0.75rem, 2.5vw, 1.5rem);
}
.shelf .module, .shelf .module + .module { margin: 0; padding: 0; border: 0; }
.shelf .module-art { height: auto; min-height: 0; }
.shelf .module-panel img { height: var(--u); width: auto; max-width: none; max-height: none; }
.shelf .module-name { font-size: clamp(1.05rem, 1.9vw, 1.35rem); margin-top: 0.8rem; white-space: nowrap; }   /* one line: main.js takes the name from there */
.shelf .module-kind { font-size: 0.88rem; line-height: 1.4; }
.cursor {
  display: inline-block; width: 0.55em; height: 1.05em; margin-left: 0.35em; vertical-align: -0.15em;
  background: var(--gold); animation: blink 1.1s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .cursor { animation: none; } }

/* ---------- the name ---------- */
.split {
  display: grid; grid-template-columns: 1fr 1.3fr;
  gap: clamp(1.5rem, 4vw, 4rem); align-items: start;
}
.prose { color: var(--dim); font-size: 1.02rem; }
.prose p + p { margin-top: 1rem; }
.prose cite, .prose i { color: var(--ink); }

/* ---------- hello ---------- */
.section-hello { text-align: center; }
.section-hello .section-sub { margin-left: auto; margin-right: auto; }
.hello-link { font-size: clamp(1.15rem, 3vw, 1.6rem); overflow-wrap: anywhere; }
.hello-link + .section-sub { margin-top: 2.6rem; }   /* the YouTube/Instagram line sits apart from the address */
.hello-link + .hello-link { margin-top: 0.7rem; }


/* ---------- narrow ---------- */
@media (max-width: 900px) {
  .split { grid-template-columns: 1fr; }
  .module-art { --stage: calc(min(64vh, 560px) - 3.2rem); }
}
@media (max-width: 620px) {
  .stage { height: 44vh; min-height: 280px; --mark-at: 0.6; }   /* a phone's mark is two lines across the screen: less sky above it */
  .stage-short { height: 30vh; min-height: 200px; --mark-at: 0.6; }   /* and the bench's one line */
  .module-art { --stage: 120vw; min-height: 0; }   /* a phone is narrow: every stage the same, so the models keep one scale, and tall, as 3U sets that scale (PHONE_BOX in main.js) */
}
