/* Self-hosted fonts (SIL OFL 1.1; licences in /fonts). */
@font-face {
  font-family: "Jost";
  font-style: normal;
  font-weight: 300 500;
  font-display: swap;
  src: url("fonts/jost-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;
}
@font-face {
  font-family: "Jost";
  font-style: normal;
  font-weight: 300 500;
  font-display: swap;
  src: url("fonts/jost-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/geist-mono-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;
}
@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/geist-mono-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --bg: #0a0a0b;
  --fg: #ebe9e4;
  --fg-2: #a3a19b;
  --fg-3: #807f7a;
  --line: rgba(235, 233, 228, 0.1);

  --sans: "Jost", "Futura", "Century Gothic", ui-sans-serif, system-ui, sans-serif;
  --mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --gutter: clamp(20px, 4.5vw, 64px);
  --max: 1440px;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --draw: cubic-bezier(0.65, 0, 0.35, 1);

  color-scheme: dark;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

::selection { background: var(--fg); color: var(--bg); }

a { color: inherit; text-decoration: none; }

:focus-visible { outline: 1px solid var(--fg); outline-offset: 4px; }

.wrap {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline:
    max(var(--gutter), env(safe-area-inset-left))
    max(var(--gutter), env(safe-area-inset-right));
}

/* Particle field behind the page (JS sets its height to the page's, so it
   scrolls with the content); a fine grain over everything. */
.particles {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  width: 100%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.6s ease;
}
.particles.is-on { opacity: 1; }

body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* One screen: bar, stage, base. */
.page {
  position: relative;
  z-index: 1;
  overflow: clip; /* the rise-in must not briefly extend the page and flash a scrollbar */
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
  min-height: 100svh;
}

/* ---------- Bar ---------- */

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 80px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  font-size: 12px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
}

.brand-mark {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.1;
  stroke-linejoin: round;
}

.bar-link {
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg-2);
  transition: color 0.4s;
}
.bar-link:hover { color: var(--fg); }

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

.stage {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 24px;
  padding-block: 0 clamp(32px, 5vh, 56px);
}

.intro {
  grid-column: 1 / span 6;
  grid-row: 1;
  align-self: end;
  position: relative;
  z-index: 1;
}

.intro h1 {
  margin: 0;
  font-weight: 300;
  font-size: clamp(34px, 2.9vw + 1rem, 64px);
  line-height: 1.08;
  letter-spacing: -0.02em;
}

.thesis {
  max-width: 27em;
  margin: clamp(20px, 2.4vw, 32px) 0 0;
  font-size: clamp(15px, 1.05vw, 16.5px);
  color: var(--fg-2);
}

/* ---------- Base ---------- */

.base { padding-bottom: 28px; }

.legend {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px 24px;
  margin: 0;
  padding: 22px 0 30px;
  border-top: 1px solid var(--line);
}
.legend div { display: flex; align-items: baseline; gap: 16px; }
.legend dt {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--fg-3);
}
.legend dd {
  margin: 0;
  font-size: 15px;
  letter-spacing: 0.01em;
}

.colophon {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px 24px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.colophon a {
  text-transform: none;
  letter-spacing: 0.04em;
  transition: color 0.4s;
}
.colophon a:hover { color: var(--fg); }
.colophon-end { display: flex; flex-wrap: wrap; gap: 8px 24px; }

.motion-toggle {
  appearance: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  cursor: pointer;
  transition: color 0.4s;
}
.motion-toggle:hover { color: var(--fg); }

/* ---------- FIG. 1 ---------- */

.fig { margin: 0; color: var(--fg); }

.fig-hero {
  --hair: 1.5px;
  --beat: 0.36s;
  --off: 0.5s;
  --dur: 1.3s;
  grid-column: 6 / -1;
  grid-row: 1;
  align-self: center;
  justify-self: end;
  width: min(100%, calc(100vh - 290px));
  width: min(100%, calc(100svh - 290px));
  min-width: 0;
}

.fig-frame { position: relative; }

.fig svg { display: block; width: 100%; height: auto; overflow: visible; }

/* Live mode: the particle field draws FIG. 1; the SVG keeps the layout.
   If the GPU context is lost, the SVG returns (was-live) without replaying. */
.fig-hero.is-live svg { visibility: hidden; }
.fig-hero.is-live figcaption { animation-delay: 3.6s; }
.fig-hero:not(.is-live) .fig-label { display: none; }
.fig-hero.was-live figcaption,
.fig-hero.was-live svg * { animation: none; }

.fig-label {
  position: absolute;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1;
  letter-spacing: 0.04em;
  color: var(--fg-2);
  transform: translateY(-90%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 1.4s ease;
}
.labels-on .fig-label { opacity: 1; }

.fig path { fill: none; stroke: currentColor; }
.fig .ink { stroke-dasharray: 1; }

.fig .g-con { opacity: 0.26; }
.fig .g-con path { stroke-width: calc(var(--hair) * 0.8); }
.fig .g-obj { opacity: 0.94; }
.fig .g-obj path { stroke-width: var(--hair); }
.fig .g-hatch { opacity: 0.5; }
.fig .g-hatch path { stroke-width: calc(var(--hair) * 0.6); }
.fig .g-note { opacity: 0.6; }
.fig .g-note path { stroke-width: calc(var(--hair) * 0.6); }
.fig .g-pts circle { fill: currentColor; }

.fig text {
  font-family: var(--mono);
  font-size: 17px;
  letter-spacing: 0.04em;
  fill: currentColor;
}

.fig figcaption {
  margin-top: 4px;
  text-align: center;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.22em;
  color: var(--fg-3);
}

/* ---------- Small screens (and phones in landscape) ---------- */

@media (max-width: 900px), (max-height: 500px) {
  .stage { grid-template-columns: minmax(0, 1fr); row-gap: 28px; padding-bottom: 48px; }
  .fig-hero {
    --hair: 2.4px;
    grid-column: 1;
    grid-row: 1;
    justify-self: center;
    width: min(100%, 520px, calc(100vh - 120px));
    width: min(100%, 520px, calc(100svh - 120px));
  }
  .fig text { font-size: 26px; }
  .intro { grid-column: 1; grid-row: 2; }
  .legend { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Short desktop windows: keep the SVG fallback's numerals legible. */
@media (min-width: 901px) and (min-height: 501px) and (max-height: 820px) {
  .fig text { font-size: 26px; }
}

@media (max-width: 520px) {
  .fig-hero { --hair: 3px; }
  .fig text { font-size: 34px; }
  .legend { grid-template-columns: minmax(0, 1fr); }
  .colophon { flex-direction: column; }
}

/* ---------- Motion ---------- */

.k0 { --k: 0; } .k1 { --k: 1; } .k5 { --k: 5; } .k6 { --k: 6; }
.k8 { --k: 8; } .k9 { --k: 9; } .k13 { --k: 13; } .k15 { --k: 15; }
.k17 { --k: 17; } .k18 { --k: 18; } .k19 { --k: 19; }
.long { --dur: 2.4s; }

.g-hatch > :nth-child(2) { --j: 1; }  .g-hatch > :nth-child(3) { --j: 2; }
.g-hatch > :nth-child(4) { --j: 3; }  .g-hatch > :nth-child(5) { --j: 4; }
.g-hatch > :nth-child(6) { --j: 5; }  .g-hatch > :nth-child(7) { --j: 6; }
.g-hatch > :nth-child(8) { --j: 7; }  .g-hatch > :nth-child(9) { --j: 8; }
.g-hatch > :nth-child(10) { --j: 9; } .g-hatch > :nth-child(11) { --j: 10; }
.g-hatch > :nth-child(12) { --j: 11; }

@media (prefers-reduced-motion: no-preference) {
  .rise { animation: rise 1.6s var(--ease) both; }
  .bar.rise { animation-delay: 0.1s; }
  .intro h1.rise { animation-delay: 0.25s; }
  .intro .thesis.rise { animation-delay: 0.45s; }
  .base.rise { animation-delay: 0.7s; }

  /* The figure draws itself in construction order:
     axes, circle, compass arcs, points, hexagon, edges, hatching, notation. */
  .fig .ink {
    animation: draw var(--dur) var(--draw) both;
    animation-delay: calc(var(--off) + var(--beat) * var(--k, 0) + var(--j, 0) * 45ms);
  }
  .fig .ext-x, .fig .ext-y {
    transform-box: fill-box;
    transform-origin: center;
    animation: var(--axis) 1.8s var(--draw) both;
    animation-delay: calc(var(--off) + var(--beat) * var(--k, 0));
  }
  .fig .ext-x { --axis: ext-x; }
  .fig .ext-y { --axis: ext-y; }
  .fig .fadein {
    animation: appear 1s ease both;
    animation-delay: calc(var(--off) + var(--beat) * var(--k, 0));
  }
  .fig .g-con {
    animation: settle 2.4s ease both;
    animation-delay: calc(var(--off) + var(--beat) * 19);
  }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}
@keyframes appear {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes draw {
  from { stroke-dashoffset: 1; }
  to { stroke-dashoffset: 0; }
}
@keyframes ext-x {
  from { transform: scaleX(0); }
  to { transform: none; }
}
@keyframes ext-y {
  from { transform: scaleY(0); }
  to { transform: none; }
}
@keyframes settle {
  from { opacity: 0.42; }
  to { opacity: 0.26; }
}

/* ---------- Print ---------- */

@media print {
  :root { --bg: #fff; --fg: #111; --fg-2: #333; --fg-3: #555; --line: rgba(0, 0, 0, 0.2); }
  body::after, .particles, .fig-label, .motion-toggle { display: none !important; }
  .fig-hero.is-live svg { visibility: visible; }
  .page { min-height: 0; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ---------- 404 ---------- */

.nf {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 24px;
  min-height: 100vh;
  min-height: 100svh;
}
.nf p {
  margin: 0;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.2em;
  color: var(--fg-3);
}
.nf h1 {
  margin: 0;
  font-weight: 300;
  font-size: clamp(32px, 4vw, 56px);
  line-height: 1.1;
  letter-spacing: -0.02em;
}
.nf a {
  font-size: 12px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg-2);
  transition: color 0.4s;
}
.nf a:hover { color: var(--fg); }
