@font-face {
  font-family: "Anybody";
  src: url("/fonts/anybody-var-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 50% 150%;
  font-display: swap;
}

@font-face {
  font-family: "Mona Sans";
  src: url("/fonts/mona-sans-var-latin.woff2") format("woff2");
  font-weight: 200 900;
  font-stretch: 75% 125%;
  font-display: swap;
}

:root {
  --umbra: #16161c;
  --lux: #f2ede4;
  --umbra-soft: #a9a59f; /* secondary text on umbra, 7.3:1 */
  --lux-soft: #5a575f;   /* secondary text on lux, 6.1:1 */
  --lux-dim: #7f7c83;    /* unlit headline words on lux, 3.5:1 (large text) */
  --margin: clamp(20px, 3.4vw, 56px);
  --display: "Anybody", "Arial Narrow", sans-serif;
  --text: "Mona Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --ease-out: cubic-bezier(0.16, 0.84, 0.24, 1);
  --wm-stretch: 150%;
  --wm-bottom: calc(var(--margin) * 0.7);
  /* scroll + layout state, written by site.js; the defaults are the no-JS page */
  --p: 0;
  --q: 0;
  --cap: 0;
  --ring: 0;
  --c: 1;
  --orbit: 1;
  /* no-JS fallback; site.js measures the real fit ("mbra" is about 4em wide at 150%) */
  --wm-size: calc((50vw - var(--margin)) / 4.1);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  background: var(--umbra);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--umbra);
  color: var(--lux);
  font: 400 1.125rem/1.55 var(--text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* film grain over everything, static so it costs nothing while scrolling */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 50;
  pointer-events: none;
  background: url("/assets/grain.svg") repeat;
  opacity: 0.07;
}

h1,
h2,
h3,
p {
  margin: 0;
}

a {
  color: inherit;
}

:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 4px;
  border-radius: 2px;
}

.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 60;
  padding: 10px 16px;
  background: var(--lux);
  color: var(--umbra);
  font-weight: 500;
  text-decoration: none;
  transform: translateY(-160%);
}

.skip:focus {
  transform: none;
}

/* ---------- navigation ----------
   over the opening scene it has no background and inverts against both tones;
   over normal content it becomes a solid bar in that section's tone and gets out
   of the way while reading (site.js sets data-mode, data-tone, data-hidden) */

.nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: max(14px, env(safe-area-inset-top)) var(--margin) 14px;
  color: var(--lux);
  mix-blend-mode: difference;
  transition: transform 0.45s var(--ease-out), background-color 0.25s linear;
}

.nav[data-mode="solid"] {
  mix-blend-mode: normal;
  background: var(--nav-bg);
  color: var(--nav-fg);
  box-shadow: 0 1px 0 var(--nav-line);
}

.nav[data-tone="lux"] {
  --nav-bg: var(--lux);
  --nav-fg: var(--umbra);
  --nav-line: rgb(22 22 28 / 0.1);
}

.nav[data-tone="umbra"] {
  --nav-bg: var(--umbra);
  --nav-fg: var(--lux);
  --nav-line: rgb(242 237 228 / 0.1);
}

.nav[data-hidden="true"]:not(:focus-within) {
  transform: translate3d(0, -110%, 0);
}

.brand {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 12px;
  padding: 8px 0;
  text-decoration: none;
}

.brand-mark {
  width: 22px;
  height: 22px;
  fill: currentColor;
}

.brand-name {
  font: 400 1rem/1 var(--display);
  font-stretch: 150%;
  letter-spacing: 0.01em;
}

.nav nav {
  display: flex;
  gap: clamp(18px, 3vw, 44px);
}

.nav nav a {
  padding: 10px 0;
  font: 450 0.9375rem/1 var(--text);
  text-decoration: none;
  white-space: nowrap;
  background: linear-gradient(currentColor, currentColor) 0 calc(100% - 6px) / 0 1px no-repeat;
  transition: background-size 0.4s var(--ease-out);
}

.nav nav a:hover {
  background-size: 100% 1px;
}

/* ---------- the scene: hero + the terminator sweep ---------- */

.scene {
  position: relative;
  height: 100vh;
  height: 100svh;
}

.js .scene {
  height: 260vh;
  height: 260svh;
}

.scene-frame {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.layer {
  position: absolute;
  inset: 0;
}

.layer-umbra {
  background: var(--umbra);
  color: var(--lux);
}

/* the lit side: a mask sliding in from the left with its content counter-sliding,
   so the reveal is two composited transforms and never repaints */
.layer-lux {
  overflow: hidden;
  background: var(--lux);
  color: var(--umbra);
  transform: translate3d(calc((var(--q) - 1) * 100%), 0, 0);
}

.layer-lux-inner {
  position: absolute;
  inset: 0;
  transform: translate3d(calc((1 - var(--q)) * 100%), 0, 0);
}

.hero-media {
  position: absolute;
  inset: 0;
  animation: rise-from-dark 1.8s ease-out 0.1s both;
}

.hero-stage {
  position: absolute;
  inset: 0;
  transform: scale(calc(1 - var(--p) * 0.08));
}

/* site.js sizes the video so the sphere clears the type on every screen shape;
   the fallback is a plain cover fit */
.hero-video {
  position: absolute;
  left: var(--vx, 0px);
  top: var(--vy, 0px);
  width: var(--vw, 100%);
  height: var(--vh, 100%);
  object-fit: cover;
  opacity: calc(1 - var(--p) * 2.4);
  /* fades the frame edge and any codec colour drift into the page background */
  -webkit-mask-image: radial-gradient(circle at var(--mask-x, 50%) var(--mask-y, 46%), #000 calc(var(--sr, 30vh) * 1.8), transparent calc(var(--sr, 30vh) * 2.6));
  mask-image: radial-gradient(circle at var(--mask-x, 50%) var(--mask-y, 46%), #000 calc(var(--sr, 30vh) * 1.8), transparent calc(var(--sr, 30vh) * 2.6));
}

/* without JS there are no video sources: show the poster frame as a plain image */
html:not(.js) .hero-video {
  display: none;
}

html:not(.js) .hero-stage {
  background: url("/media/sphere-landscape-poster.webp") 50% 50% / cover no-repeat;
}

/* as the render fades, the flat mark takes its place: same centre, same radius,
   the logo's 12% ring. Half covered by the lit side, it becomes the logo. */
.hero-ring {
  position: absolute;
  left: calc(var(--sx, 50vw) - var(--sr, 30vh));
  top: calc(var(--sy, 46vh) - var(--sr, 30vh));
  width: calc(var(--sr, 30vh) * 2);
  height: calc(var(--sr, 30vh) * 2);
  overflow: visible;
  color: var(--lux);
}

/* traced clockwise from twelve o'clock by growing the dash from nothing;
   1772 = the circle's circumference (2 x pi x 282) */
.hero-ring {
  opacity: clamp(0, calc(var(--ring) * 200), 1);
}

.hero-ring circle {
  stroke-dasharray: calc(1772 * var(--ring)) 3544;
  transform: rotate(-90deg);
  transform-box: fill-box;
  transform-origin: center;
}

.lede {
  position: absolute;
  left: var(--margin);
  top: 40%;
  max-width: min(25ch, var(--lede-max, 25ch));
  font-size: clamp(1.125rem, 1.45vw, 1.375rem);
  line-height: 1.45;
  text-wrap: pretty;
  opacity: calc(1 - var(--p) * 5);
  animation: fade-in 1.2s ease-out 1.1s both;
}

.video-toggle {
  position: absolute;
  right: var(--margin);
  top: 40%;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--umbra-soft);
  font: 450 0.875rem/1 var(--text);
  cursor: pointer;
  opacity: calc(1 - var(--p) * 5);
  animation: fade-in 1.2s ease-out 1.3s both;
}

.video-toggle[hidden] {
  display: none;
}

.video-toggle:hover {
  color: var(--lux);
}

.video-toggle-icon {
  width: 10px;
  height: 12px;
  border-left: 3px solid currentColor;
  border-right: 3px solid currentColor;
}

.video-toggle[data-state="paused"] .video-toggle-icon {
  width: 0;
  height: 0;
  border-width: 6px 0 6px 10px;
  border-style: solid;
  border-color: transparent transparent transparent currentColor;
}

/* narrow or tall screens: the lede and the video control stack above the wordmark */
.hero-stacked .lede {
  top: auto;
  right: var(--margin);
  bottom: calc(var(--wm-bottom) + var(--wm-h, 12vw) + 24px);
  max-width: 30ch;
  font-size: 1.0625rem;
}

.hero-stacked .video-toggle {
  top: auto;
  left: var(--margin);
  right: auto;
  bottom: calc(var(--wm-bottom) + var(--wm-h, 12vw) + 24px + var(--lede-h, 5em) + 4px);
}

/* the wordmark is split at the terminator: "Luci" ends on the centre line, "mbra" starts on it */
.wordmark {
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--wm-bottom);
  display: grid;
  grid-template-columns: 1fr 1fr;
  font-family: var(--display);
  font-size: var(--wm-size);
  font-weight: 170;
  font-stretch: var(--wm-stretch);
  line-height: 0.78;
  letter-spacing: -0.005em;
  white-space: nowrap;
}

.wordmark-a {
  text-align: right;
}

.wordmark-b {
  text-align: left;
}

.wordmark-half {
  animation: wax 1.9s var(--ease-out) 0.35s both;
}

.caption {
  position: absolute;
  bottom: calc(var(--wm-bottom) + var(--wm-h, 12vw) + 18px);
  width: calc(50% - 20px);
  font-size: 1rem;
  opacity: var(--cap);
}

.caption i {
  font-style: normal;
  font-family: var(--display);
  font-stretch: 150%;
  font-weight: 400;
}

.caption-a {
  left: 0;
  padding-right: 4px;
  text-align: right;
}

.caption-b {
  right: 0;
  padding-left: 4px;
  text-align: left;
}

@keyframes wax {
  from {
    font-stretch: 50%;
    opacity: 0;
  }
  35% {
    opacity: 1;
  }
  to {
    font-stretch: var(--wm-stretch);
    opacity: 1;
  }
}

@keyframes rise-from-dark {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
}

/* ---------- lit sections ---------- */

.statement,
.cycle {
  background: var(--lux);
  color: var(--umbra);
}

.statement {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 24px;
  row-gap: 48px;
  padding: clamp(96px, 16vh, 200px) var(--margin) clamp(72px, 11vh, 144px);
}

.statement h2 {
  grid-column: 1 / span 10;
  font: 280 clamp(2.5rem, 6.4vw, 7rem) / 0.98 var(--display);
  font-stretch: 118%;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

/* each word takes the light as the reader reaches it (site.js sets --lit per word) */
.statement .word {
  color: var(--umbra);
  color: color-mix(in oklab, var(--umbra) calc(var(--lit, 1) * 100%), var(--lux-dim));
}

.statement p {
  grid-column: 7 / span 5;
  max-width: 38ch;
  color: var(--lux-soft);
}

.cycle {
  padding: clamp(56px, 9vh, 112px) var(--margin) clamp(120px, 20vh, 240px);
}

.cycle-head {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 24px;
  row-gap: 24px;
  align-items: end;
  margin-bottom: clamp(56px, 9vh, 104px);
}

.cycle-head h2 {
  grid-column: 1 / span 7;
  font: 300 clamp(2rem, 4.2vw, 4.5rem) / 1 var(--display);
  font-stretch: 125%;
  letter-spacing: -0.015em;
}

.cycle-head p {
  grid-column: 9 / span 4;
  max-width: 34ch;
  color: var(--lux-soft);
}

/* the four phases sit on one orbit line, drawn as the reader moves through them */
.phases {
  --glyph: 56px;
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: 24px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.phases::before {
  content: "";
  position: absolute;
  top: calc(var(--glyph) / 2);
  left: 0;
  right: 0;
  height: 1px;
  background: rgb(22 22 28 / 0.28);
  transform: scaleX(var(--orbit));
  transform-origin: left center;
}

.phase {
  position: relative;
  padding-right: clamp(8px, 2vw, 32px);
}

.phase-glyph {
  display: block;
  width: var(--glyph);
  height: var(--glyph);
  margin-bottom: 32px;
  overflow: visible;
  background: var(--lux);
  border-radius: 50%;
  box-shadow: 0 0 0 10px var(--lux);
}

.phase-ring {
  fill: none;
  stroke: currentColor;
  stroke-width: 7;
}

.phase-lit {
  fill: currentColor;
  transition: opacity 0.6s var(--ease-out);
}

/* with JS, a phase lights when the orbit reaches it; without JS all are lit */
.js .phase:not(.is-lit) .phase-lit {
  opacity: 0;
}

.phase h3 {
  margin-bottom: 12px;
  font: 400 clamp(1.5rem, 2.1vw, 2rem) / 1 var(--display);
  font-stretch: 140%;
}

.phase p {
  max-width: 30ch;
  font-size: 1rem;
  color: var(--lux-soft);
}

/* ---------- night falls again ---------- */

.contact {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  background: var(--umbra);
  color: var(--lux);
}

/* the last of the daylight, sliding off to the right as night follows from the left */
.contact-day {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--lux);
  pointer-events: none;
  transform: translate3d(calc(var(--c) * 100%), 0, 0);
}

.contact-inner {
  position: relative;
  flex: 1;
  padding: clamp(112px, 18vh, 200px) var(--margin) clamp(48px, 8vh, 96px);
}

.contact h2 {
  margin-bottom: 16px;
  font: 300 clamp(2rem, 4.2vw, 4.5rem) / 1 var(--display);
  font-stretch: 125%;
  letter-spacing: -0.015em;
}

.contact-inner p {
  color: var(--umbra-soft);
}

.contact-mail {
  display: inline-block;
  margin-top: clamp(32px, 6vh, 72px);
  font: 200 clamp(1.75rem, 7.4vw, 8.5rem) / 1 var(--display);
  font-stretch: 112%;
  letter-spacing: -0.02em;
  text-decoration: none;
  background: linear-gradient(currentColor, currentColor) 0 100% / 0 2px no-repeat;
  transition: background-size 0.6s var(--ease-out);
  overflow-wrap: anywhere;
}

.contact-mail:hover,
.contact-mail:focus-visible {
  background-size: 100% 2px;
}

/* the closing signature: the wordmark as a new moon, drawn in outline.
   A pointer lights the letters it passes over, like a torch. */
.signature {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  padding-bottom: calc(var(--margin) * 0.5);
  font-family: var(--display);
  font-size: var(--wm-size);
  font-weight: 170;
  font-stretch: var(--wm-stretch);
  line-height: 0.78;
  letter-spacing: -0.005em;
  white-space: nowrap;
  color: transparent;
  -webkit-text-stroke: 1px rgb(242 237 228 / 0.42);
  background: radial-gradient(circle at var(--mx, -100vw) var(--my, 50%), var(--lux) 0, var(--lux) 7vw, rgb(242 237 228 / 0) 17vw) no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  user-select: none;
}

.signature .wordmark-a {
  text-align: right;
}

.signature .wordmark-b {
  text-align: left;
}

.footer {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 24px var(--margin) max(24px, env(safe-area-inset-bottom));
  border-top: 1px solid rgb(242 237 228 / 0.14);
  font-size: 0.875rem;
  color: var(--umbra-soft);
}

.footer-mark {
  width: 18px;
  height: 18px;
  fill: var(--lux);
}

.footer a {
  margin-left: auto;
  padding: 10px 0;
  text-decoration: none;
}

.footer a:hover {
  color: var(--lux);
}

/* ---------- small screens ---------- */

@media (max-width: 860px) {
  .statement {
    row-gap: 32px;
    padding-bottom: 56px;
  }

  .statement h2,
  .statement p,
  .cycle-head h2,
  .cycle-head p {
    grid-column: 1 / -1;
  }

  .cycle {
    padding-top: 40px;
    padding-bottom: 104px;
  }

  .cycle-head {
    margin-bottom: 48px;
  }

  .phases {
    grid-template-columns: 1fr;
    row-gap: 40px;
  }

  .phases::before {
    top: 0;
    bottom: 0;
    left: calc(var(--glyph) / 2);
    right: auto;
    width: 1px;
    height: auto;
    transform: scaleY(var(--orbit));
    transform-origin: center top;
  }

  .phase {
    display: grid;
    grid-template-columns: var(--glyph) 1fr;
    column-gap: 24px;
    padding-right: 0;
  }

  .phase-glyph {
    grid-row: span 2;
    margin-bottom: 0;
  }

  .phase h3 {
    align-self: center;
    margin-bottom: 8px;
  }

  .phase p {
    grid-column: 2;
  }
}

@media (max-width: 640px) {
  :root {
    --wm-stretch: 116%;
  }

  .nav nav {
    gap: 20px;
  }

  .nav nav a {
    font-size: 0.875rem;
  }

  .wordmark,
  .signature {
    font-weight: 240;
  }

  .caption {
    font-size: 0.875rem;
  }

  .contact {
    min-height: 70vh;
    min-height: 70svh;
  }

  .contact-inner {
    padding-top: 104px;
  }
}

@media (max-width: 379px) {
  .nav nav a:first-child {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-media,
  .lede,
  .video-toggle,
  .wordmark-half {
    animation: none;
  }

  .hero-stage {
    transform: none;
  }

  .nav,
  .nav nav a,
  .contact-mail,
  .phase-lit {
    transition: none;
  }
}

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

/* ---------- 404 ---------- */

.not-found main {
  display: grid;
  place-content: center;
  justify-items: start;
  gap: 20px;
  min-height: 100vh;
  min-height: 100svh;
  padding: var(--margin);
}

.not-found-mark {
  width: 56px;
  height: 56px;
  margin-bottom: 12px;
  fill: var(--lux);
}

.not-found h1 {
  font: 300 clamp(2rem, 5vw, 4rem) / 1 var(--display);
  font-stretch: 125%;
}

.not-found p {
  color: var(--umbra-soft);
}

.not-found a {
  font-weight: 500;
  text-underline-offset: 4px;
}
