/* yumankind.com — a story told with one light.
   Dark ground, one warm light and one cold light that crossfade, and text. The light's position,
   size and brightness are keyed to body[data-light]; story.js flips that key to whichever chapter
   is on screen, and the transitions below do the animating.

   Readability rule: the text block sits in the upper half of the screen (see .text), and every
   chapter's light is placed below it, or in the half the text is not in. The core never sits under
   a line of type. Moves between chapters are small and slow so the light drifts rather than jumps. */

:root {
  --bg: #05070a;
  --text: #f2f4f7;
  --muted: #8b96a5;
  --dim: #55606e;
  --line: #1a2029;
  --accent: #ffbb22;
  --warm-core: #fff6d6;
  --warm-mid: #ffbb22;
  --warm-edge: rgba(255, 140, 20, 0);
  --cold-core: #eaf6ff;
  --cold-mid: #6fa9ff;
  --cold-edge: rgba(60, 110, 255, 0);
  /* Light state, overridden per chapter. x/y in viewport %, s is a scale factor on a 60vmax disc. */
  --lx: 50%; --ly: 62%; --ls: .04; --warm: 1; --cold: 0; --core: 1; --hw: 1; --hc: 0;
  --ease: cubic-bezier(.4, 0, .2, 1);
  --dur: 2.4s;
  color-scheme: dark;
}
/* Wide gamut: push the core past sRGB so it reads as light, not paint. */
@supports (color: color(display-p3 1 1 1)) {
  :root { --warm-core: color(display-p3 1 0.97 0.86); --warm-mid: color(display-p3 1 0.74 0.16); --cold-core: color(display-p3 0.93 0.97 1); }
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html { background: var(--bg); scroll-behavior: smooth; }
body {
  margin: 0; background: var(--bg); color: var(--text);
  font: 17px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, sans-serif;
  -webkit-font-smoothing: antialiased; overflow-x: hidden;
}
a { color: inherit; text-decoration: none; }
img { display: block; }

/* ── the stage ──────────────────────────────────────────────────────────────── */
.stage {
  position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden;
  /* Let HDR content render above SDR white where the browser gates it (Chromium). */
  dynamic-range-limit: no-limit;
}
.light {
  position: absolute; left: var(--lx); top: var(--ly);
  width: 60vmax; height: 60vmax; margin: -30vmax 0 0 -30vmax; border-radius: 50%;
  transform: scale(var(--ls));
  will-change: transform, opacity;
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease), left var(--dur) var(--ease), top var(--dur) var(--ease);
}
/* The gradients are sampled every 4% from the same falloff the HDR images use (three Gaussians and a
   soft cut at 72%), so there is no stop where the eye can catch a kink. sRGB interpolation on purpose:
   oklab greys the yellow into olive. Generated by the snippet in scripts/make-hdr.sh; edit the curve
   there, not the numbers here. */
.light.warm {
  background: radial-gradient(circle,
    rgba(255, 246, 214, 1.000) 0%, rgba(255, 242, 202, 0.974) 4%, rgba(255, 232, 173, 0.909) 8%, rgba(255, 219, 134, 0.834) 12%,
    rgba(255, 206, 93, 0.762) 16%, rgba(255, 194, 58, 0.694) 20%, rgba(255, 187, 37, 0.627) 24%, rgba(255, 187, 34, 0.562) 28%,
    rgba(255, 186, 33, 0.502) 32%, rgba(255, 184, 33, 0.447) 36%, rgba(255, 180, 31, 0.400) 40%, rgba(255, 174, 30, 0.358) 44%,
    rgba(255, 168, 28, 0.322) 48%, rgba(255, 161, 26, 0.290) 52%, rgba(255, 155, 24, 0.259) 56%, rgba(255, 149, 22, 0.213) 60%,
    rgba(255, 144, 21, 0.152) 64%, rgba(255, 141, 20, 0.084) 68%, rgba(255, 140, 20, 0.000) 72%);
  opacity: var(--warm);
}
.light.cold {
  background: radial-gradient(circle,
    rgba(234, 246, 255, 1.000) 0%, rgba(226, 241, 255, 0.974) 4%, rgba(206, 228, 255, 0.909) 8%, rgba(179, 211, 255, 0.834) 12%,
    rgba(151, 194, 255, 0.762) 16%, rgba(127, 179, 255, 0.694) 20%, rgba(113, 170, 255, 0.627) 24%, rgba(111, 169, 255, 0.562) 28%,
    rgba(110, 168, 255, 0.502) 32%, rgba(108, 165, 255, 0.447) 36%, rgba(103, 160, 255, 0.400) 40%, rgba(97, 153, 255, 0.358) 44%,
    rgba(90, 145, 255, 0.322) 48%, rgba(83, 137, 255, 0.290) 52%, rgba(76, 129, 255, 0.259) 56%, rgba(70, 121, 255, 0.213) 60%,
    rgba(64, 115, 255, 0.152) 64%, rgba(61, 111, 255, 0.084) 68%, rgba(60, 110, 255, 0.000) 72%);
  opacity: var(--cold);
}
/* The HDR glow, two ways.
   Safari and Firefox: an HDR <picture> inside each disc, blended plus-lighter over the gradient. They
   keep HDR headroom through the blend, the disc's opacity and its transform.
   Chromium: clamps to SDR under any of those, so it gets .hdr instead: a plain <img> of the PNG (real
   alpha, so no black square), sized and placed with width/left/top from the same variables, and
   shrunk (--hw / --hc) rather than faded where a chapter dims the light.
   Both are hidden unless the display reports HDR; on SDR the gradient alone is the light. */
.light picture, .light img, .hdr { display: none; }
@media (dynamic-range: high) {
  html:not(.chromium) .light picture { display: block; position: absolute; inset: 0; }
  html:not(.chromium) .light img { display: block; width: 100%; height: 100%; mix-blend-mode: plus-lighter; border-radius: 50%; }
  html.chromium .hdr {
    display: block; position: absolute;
    width: calc(60vmax * var(--ls) * var(--hs)); height: calc(60vmax * var(--ls) * var(--hs));
    left: calc(var(--lx) - 30vmax * var(--ls) * var(--hs)); top: calc(var(--ly) - 30vmax * var(--ls) * var(--hs));
    transition: width var(--dur) var(--ease), height var(--dur) var(--ease), left var(--dur) var(--ease), top var(--dur) var(--ease);
  }
  html.chromium .hdr.warm { --hs: var(--hw); }
  html.chromium .hdr.cold { --hs: var(--hc); }
}
.core {
  position: absolute; left: var(--lx); top: var(--ly); width: 4px; height: 4px; margin: -2px 0 0 -2px;
  border-radius: 50%; background: #fff; opacity: var(--core);
  box-shadow: 0 0 10px 3px #fff, 0 0 40px 14px var(--warm-mid);
  transition: opacity var(--dur) var(--ease), left var(--dur) var(--ease), top var(--dur) var(--ease);
}
@media (dynamic-range: high) { .core { box-shadow: 0 0 12px 4px #fff, 0 0 60px 20px var(--warm-mid); } }
/* The point breathes while it is alone on screen; once the story moves it just glows. */
body[data-light="point"] .core { animation: breathe 4s ease-in-out infinite; }
@keyframes breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.35); } }

/* ── the light, chapter by chapter ───────────────────────────────────────────
   The 4px core is the "point of light": it shows on the first slide and again on "far", where the
   light is small and distant. Under a large glow a sharp dot reads as an artifact, so elsewhere it is 0.
   Text lives around 42% of the height for centred chapters. The light stays at 66–72% below it,
   except "far", where it shrinks and climbs above the words, and "back", where it returns. Side
   chapters put the words in one half and the light in the other. */
body[data-light="point"]    { --lx: 50%; --ly: 64%; --ls: .05; --warm: .9;  --cold: 0;   --core: 1; --hw: 1; --hc: 0; }
body[data-light="wish"]     { --lx: 50%; --ly: 70%; --ls: .42; --warm: .95; --cold: 0;   --core: 0; --hw: 1; --hc: 0; }
body[data-light="make"]     { --lx: 46%; --ly: 70%; --ls: .55; --warm: 1;   --cold: 0;   --core: 0; --hw: 1; --hc: 0; }
body[data-light="find"]     { --lx: 54%; --ly: 68%; --ls: .6;  --warm: .85; --cold: .2;  --core: 0; --hw: 1; --hc: 0.5; }
body[data-light="far"]      { --lx: 50%; --ly: 16%; --ls: .14; --warm: .8;  --cold: .1;  --core: .6; --hw: 1; --hc: 0.4; }
body[data-light="back"]     { --lx: 50%; --ly: 70%; --ls: .9;  --warm: 1;   --cold: 0;   --core: 0; --hw: 1; --hc: 0; }
body[data-light="hands"]    { --lx: 70%; --ly: 58%; --ls: .8;  --warm: 1;   --cold: 0;   --core: 0; --hw: 1; --hc: 0; }
body[data-light="machines"] { --lx: 30%; --ly: 56%; --ls: .9;  --warm: .3;  --cold: .9;  --core: 0; --hw: 0.6; --hc: 1; }
body[data-light="wall"]     { --lx: 50%; --ly: 82%; --ls: .28; --warm: 0;   --cold: .45; --core: 0; --hw: 0; --hc: 0.8; }
body[data-light="between"]  { --lx: 50%; --ly: 76%; --ls: .75; --warm: .7;  --cold: 0;   --core: 0; --hw: 0.9; --hc: 0; }
body[data-light="apps"]     { --lx: 50%; --ly: -8%; --ls: 1.7; --warm: .55; --cold: .05; --core: 0; --hw: 0.8; --hc: 0; }
body[data-light="footer"]   { --lx: 50%; --ly: -12%; --ls: 1.2; --warm: .12; --cold: 0;  --core: 0; --hw: 0.5; --hc: 0; }

/* ── chrome ─────────────────────────────────────────────────────────────────── */
.top {
  position: fixed; inset: 0 0 auto 0; z-index: 5; display: flex; justify-content: space-between; align-items: center;
  padding: 1.1rem 1.5rem; padding-top: max(1.1rem, env(safe-area-inset-top));
}
.brand { display: flex; align-items: center; gap: .7rem; font-weight: 600; letter-spacing: -.01em; font-size: .95rem; }
.brand img { height: 24px; width: auto; }
.skip { font-size: .85rem; color: var(--muted); transition: opacity .4s; }
.skip:hover { color: var(--text); }
body.at-end .skip { opacity: 0; pointer-events: none; }

.controls { position: fixed; left: 1.5rem; bottom: 1.4rem; z-index: 5; transition: opacity .4s; }
.play {
  display: inline-flex; align-items: center; gap: .55rem; padding: .5rem .9rem .5rem .75rem;
  border: 1px solid rgba(255, 255, 255, .14); border-radius: 999px; background: rgba(5, 7, 10, .5);
  color: var(--text); font: 500 .82rem/1 inherit; font-family: inherit; cursor: pointer; backdrop-filter: blur(8px);
  transition: border-color .2s;
}
.play:hover { border-color: rgba(255, 255, 255, .35); }
.play .ic-pause { display: none; }
body.playing .play .ic-pause { display: block; }
body.playing .play .ic-play { display: none; }
body.at-end .controls { opacity: 0; pointer-events: none; }

.dots { position: fixed; right: 1.2rem; top: 50%; z-index: 5; display: flex; flex-direction: column; gap: .55rem; transform: translateY(-50%); transition: opacity .4s; }
.dots a { width: 5px; height: 5px; border-radius: 50%; background: rgba(255, 255, 255, .2); transition: background .3s, transform .3s; }
.dots a.on { background: var(--accent); transform: scale(1.5); }
body.at-end .dots { opacity: 0; pointer-events: none; }
@media (max-width: 720px) { .dots { display: none; } .skip { display: none; } }

/* ── chapters ───────────────────────────────────────────────────────────────── */
main { position: relative; z-index: 1; }
.chapter {
  min-height: 100svh; display: grid; place-items: center; padding: 6rem 1.5rem;
  scroll-snap-align: start;
}
/* Centred text rides high: the light lives underneath it. Side text stays at mid height. */
.text { max-width: 46rem; text-align: center; transform: translateY(-14vh); }
.text.left { text-align: left; justify-self: start; margin-left: max(1.5rem, 8vw); transform: none; }
.text.right { text-align: right; justify-self: end; margin-right: max(1.5rem, 8vw); transform: none; }
.chapter h1, .chapter h2 {
  margin: 0; font-weight: 600; letter-spacing: -.035em; line-height: 1.05;
  font-size: clamp(2.2rem, 6.2vw, 4.6rem);
  text-shadow: 0 2px 40px rgba(0, 0, 0, .6);
  text-wrap: balance;
}


/* Phones: the side chapters have no side to spare. Words go high and centred, light goes low. */
@media (max-width: 720px) {
  .text.left, .text.right { text-align: center; justify-self: center; margin: 0; transform: translateY(-14vh); }
  body[data-light="hands"]    { --lx: 50%; --ly: 72%; --ls: .6; --hw: 1; --hc: 0; }
  body[data-light="machines"] { --lx: 50%; --ly: 74%; --ls: .6; --hw: 0.6; --hc: 1; }
}
.sub { margin: 1.4rem 0 0; font-size: clamp(1.05rem, 1.6vw, 1.35rem); color: var(--muted); text-shadow: 0 1px 24px rgba(0, 0, 0, .7); transition: color var(--dur) var(--ease); }
/* When the light is behind the words, grey on yellow is mud: the subtitle goes white for those chapters. */
body[data-light="between"] .sub { color: var(--text); }

/* Text reveals as its chapter arrives. Only with scripting: without it every line is simply there. */
.js .line { opacity: 0; transform: translateY(18px); transition: opacity 1.2s var(--ease), transform 1.2s var(--ease); }
.js .chapter.on .line { opacity: 1; transform: none; }
.js .chapter.on .line:nth-child(2) { transition-delay: .4s; }

/* ── apps ───────────────────────────────────────────────────────────────────── */
.apps { min-height: 100svh; display: flex; flex-direction: column; justify-content: center; align-items: center; padding: 7rem 1.5rem 5rem; scroll-snap-align: start; }
.label {
  margin: 0 0 2.2rem; font: 500 .8rem/1 ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: .16em; text-transform: uppercase; color: var(--muted);
}
.label.soon { margin-top: 4rem; color: var(--dim); }
/* The name, once, at the head of the apps. */
.brandmark { display: flex; flex-direction: column; align-items: center; gap: 1.1rem; }
.brandmark img { height: 66px; width: auto; filter: drop-shadow(0 6px 30px rgba(0, 0, 0, .5)); }
.brandmark span { font-size: clamp(2.4rem, 6.2vw, 4.6rem); font-weight: 600; letter-spacing: -.035em; line-height: 1; text-shadow: 0 2px 40px rgba(0, 0, 0, .6); }
.tagline { margin: 1.1rem 0 3.5rem; font-size: clamp(1.05rem, 1.6vw, 1.3rem); color: var(--text); text-shadow: 0 1px 24px rgba(0, 0, 0, .7); }
.grid { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 2rem 2.2rem; max-width: 60rem; }
.grid li > a, .grid li > .still { display: flex; flex-direction: column; align-items: center; gap: .8rem; width: 8.5rem; text-align: center; }
.grid img {
  width: 72px; height: 72px; border-radius: 20px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .55), 0 0 0 1px rgba(255, 255, 255, .06);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
.grid li > a:hover img { transform: translateY(-4px) scale(1.04); box-shadow: 0 18px 40px rgba(0, 0, 0, .6), 0 0 0 1px rgba(255, 255, 255, .14), 0 0 40px rgba(255, 187, 34, .18); }
.grid span { font-size: .82rem; color: var(--muted); line-height: 1.3; }
.grid li > a:hover span { color: var(--text); }
.lab img { filter: saturate(.4) brightness(.75); }
.lab li > a:hover img { filter: none; }
.still { cursor: default; }
@media (max-width: 560px) { .grid { gap: 1.6rem 1rem; } .grid li > a, .grid li > .still { width: 6.6rem; } .grid img { width: 60px; height: 60px; border-radius: 17px; } }

/* ── footer ─────────────────────────────────────────────────────────────────── */
footer { position: relative; z-index: 1; max-width: 60rem; margin: 0 auto; padding: 4rem 1.5rem 3rem; border-top: 1px solid var(--line); font-size: .92rem; color: var(--muted); }
.cols { display: grid; grid-template-columns: 1fr 1fr; gap: 2.5rem; margin-bottom: 2.5rem; }
@media (max-width: 720px) { .cols { grid-template-columns: 1fr; } }
footer h3 { margin: 0 0 .6rem; font: 500 .75rem/1 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: .14em; text-transform: uppercase; color: var(--dim); }
footer p { margin: 0 0 .9rem; }
footer a { color: var(--text); border-bottom: 1px solid var(--line); }
footer a:hover { color: var(--accent); border-color: var(--accent); }
.socials { display: flex; gap: 1.1rem; }
.note { font-size: .85rem; color: var(--dim); }
details { border-top: 1px solid var(--line); }
details:last-of-type { border-bottom: 1px solid var(--line); }
summary { cursor: pointer; list-style: none; padding: .95rem 0; font-weight: 500; color: var(--text); display: flex; justify-content: space-between; }
summary::-webkit-details-marker { display: none; }
summary::after { content: "+"; color: var(--dim); font-weight: 400; }
details[open] summary::after { content: "–"; }
.doc { max-width: 44rem; padding: 0 0 1.4rem; }
.doc h4 { margin: 1.3rem 0 .3rem; font-size: .92rem; font-weight: 600; color: var(--text); }
.doc p { margin: 0 0 .5rem; }
.stamp { font: 500 .72rem ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--dim); letter-spacing: .04em; }
.fine { margin: 2rem 0 0; font-size: .8rem; color: var(--dim); }
.fine a { color: var(--muted); border: 0; }

/* ── motion preferences ─────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .light, .core, .js .line, .grid img, .sub { transition-duration: .01s; }
  body[data-light="point"] .core { animation: none; }
  .controls { display: none; }
}
