@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-latin.woff2") format("woff2");
}

/* Fraunces (SIL OFL 1.1, see fonts/OFL-Fraunces.txt): variable opsz 9–144, wght 100–900. */
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/fraunces-latin.woff2") format("woff2");
}

:root {
  color-scheme: dark;
  --background: #060606;
  --foreground: #efe2c8;
  --accent: #457cfd;
  --hairline: rgb(239 226 200 / 22%);
  /* Name and ASCII glyph colours (the canvas reads --ascii and --ascii-glow). */
  --name-color: var(--foreground);
  --ascii: #f3e9d6;
  --ascii-glow: rgb(243 233 214 / 22%);
  --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
  --font-display: "Fraunces", Georgia, serif;
  --gutter: clamp(24px, 5vw, 72px);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  background: var(--background);
  color: var(--foreground);
  font-family: var(--font-mono);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

/* ---------- Stage ---------- */

.stage {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.specimen {
  position: absolute;
  inset: 0;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none; /* long-press charges a shockwave, not a context callout */
  opacity: 0;
  transition: opacity 0.6s ease;
}
.specimen.is-live {
  opacity: 1;
}
.specimen canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.scanlines {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(to bottom, transparent 0 2px, rgb(0 0 0 / 18%) 2px 3px);
  mix-blend-mode: multiply;
}

/* ---------- Cursor (text caret held in brackets) ---------- */

.specimen-cursor {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 10;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.18s;
  color: var(--foreground);
}
.specimen-cursor[data-active="true"] {
  opacity: 1;
}
.cursor-core {
  position: absolute;
  width: 8px;
  height: 12px;
  left: -4px;
  top: -6px;
  background: currentColor;
  transition: transform 0.2s;
  animation: cursor-type 2.4s ease-in-out infinite;
}
.cursor-orbit {
  position: absolute;
  width: 26px;
  height: 26px;
  left: -13px;
  top: -13px;
  border-inline: 1px solid var(--hairline);
  transition: transform 0.3s;
}
/* Holding charges a shockwave: the brackets spread and warm toward the accent. */
.specimen-cursor[data-pressed="true"] .cursor-core {
  transform: scale(calc(1.15 + var(--charge, 0) * 0.5));
}
.specimen-cursor[data-pressed="true"] .cursor-orbit {
  transform: scaleX(calc(1 + var(--charge, 0) * 1.8));
  border-color: color-mix(in oklab, var(--hairline), var(--accent) calc(var(--charge, 0) * 90%));
}
@media (hover: hover) and (pointer: fine) {
  .specimen.is-live {
    cursor: none; /* only once the drawn cursor exists */
  }
}
@media (hover: none) {
  .specimen-cursor {
    display: none;
  }
}

/* ---------- Name ---------- */

/* The name and the opening lockup share one face and pinned optical sizes
   ("von" morphs to its small cut in flight, see intro-choreo.js), so the
   flying words land as exact copies of the live name. Kerning is
   off because the live name is set letter by letter. */
.name,
.signature-lockup {
  font-family: var(--font-display);
  font-kerning: none;
  font-variation-settings: "opsz" 144;
}
.name [data-name-word="1"] {
  font-variation-settings: "opsz" 24;
}

.name {
  position: absolute;
  inset: 0;
  margin: 0;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0;
  pointer-events: none;
  mix-blend-mode: difference;
  user-select: none;
}
.js .stage:not([data-phase="done"]) .name {
  opacity: 0;
}
.name [data-name-word] {
  position: absolute;
  display: block;
  white-space: nowrap;
}
.name i {
  --ink: 0;
  display: inline-block;
  font-style: normal;
  font-weight: calc(500 - var(--ink) * 380);
  letter-spacing: calc(var(--ink) * 0.04em);
  transform: var(--pull, translate(0)) /* cursor stretch, from name-letters.js */ translateY(calc(var(--ink) * -0.04em)) skewX(calc(var(--ink) * -6deg));
  opacity: calc(1 - var(--ink) * 0.35);
  color: color-mix(in oklab, var(--name-color), var(--accent) calc(var(--ink) * 100%));
}

/* Frame composition: sizes track the viewport and are capped by height so the
   three words never collide on short, wide screens. */
.name [data-name-word="0"] {
  left: var(--gutter);
  top: 9%;
  font-size: min(17vw, 8.9vw + 40px, 17vh);
}
.name [data-name-word="1"] {
  right: calc(var(--gutter) * 1.4);
  top: 47%;
  font-size: max(18px, min(6.4vw, 2.2vw + 6px, 4vh));
}
.name [data-name-word="2"] {
  right: var(--gutter);
  bottom: calc(12% + env(safe-area-inset-bottom, 0px));
  font-size: min(21vw, 10.6vw + 48px, 20vh);
}

/* ---------- Opening signature ---------- */
/* Static layout only; the motion is a Web Animations timeline in intro.js. */

.signature {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 50;
  place-items: center;
  background: var(--background);
  color: var(--foreground);
  pointer-events: none;
}
.js .signature {
  display: grid;
}
.js .signature[hidden] {
  display: none;
}
.signature-ribbons {
  position: absolute;
  inset: 0;
  display: flex;
}
.signature-ribbons span {
  flex: 1;
  margin-right: -1px;
  background: var(--background);
  transform-origin: left;
}
.signature-ribbons span:nth-child(even) {
  transform-origin: right;
}
.signature-lockup {
  position: relative;
  height: 3em;
  font-size: clamp(44px, 6vw, 96px);
  line-height: 1;
  font-weight: 500;
  visibility: hidden;
}
.is-ready .signature-lockup {
  visibility: visible;
}
.signature-word {
  position: absolute;
  display: flex;
  top: 0;
  left: 0;
  height: 1em;
  transform-origin: top left;
  white-space: nowrap;
}
.signature-tail {
  display: inline-flex;
}
.signature-rings {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
/* The lowercase v sets the width so "on" sits snugly once it shows; the
   capital overlays it for the [WVH] row, where the tail is still hidden. */
.signature-v {
  position: relative;
}
.signature-lowercase {
  opacity: 0;
}
.signature-capital {
  position: absolute;
  top: 0;
  left: 0;
}
.signature-bracket {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: center;
}

@keyframes cursor-type {
  50% { opacity: 0.7; }
}

@media (prefers-reduced-motion: reduce) {
  .name i { transform: none; }
  .specimen,
  .specimen-cursor,
  .cursor-core,
  .cursor-orbit { transition: none; }
  .cursor-core { animation: none; }
}
