/* ── THE HERO CAROUSEL ───────────────────────────────────────────────────────
   src/views/hero-carousel.js + public/js/hero-carousel.js. Arian's hero
   (hero-carousel.tsx), ported, then set the way he asked for it: a row of
   thumbnails of the Codes' extended worlds — with rounded corners, centred —
   and behind everything the world in focus, large and exactly as the file
   is: "no color Hues over it". Then: "make it so the background picture shows
   blurry and the actual content stay in focus", so it is drawn out of focus
   and nothing else. The words take the picture's tone. Then, pushed down to
   the second screen: "the photos are horizontal and skinny, they need to be
   enlarged, cropped as well to the main point and make them maybe a square
   … make the blur less too" — so the thumbnails are squares cut around each
   world's focal point (the view says where), far larger, and the world
   behind is half as blurred.

   Every size is a ratio of the stage. The script measures the stage and
   writes the numbers here (--hc-w, --hc-full, …); until it does — and with
   scripts off — the same ratios are taken from the viewport, which is what
   the stage is on the front page. The ratios:
     the thumbnail in focus .40 of the stage's height (120–440px), square
     (--hc-tar; on a phone .72 of the width) · the rest half its size · gap
     .04 of its width · the row's middle just under the stage's (.54), so
     the headline above it clears the bar · headline .067 · labels .0103 ·
     gutter .017 of the width · rail .2 of the width. */
.hc {
  --hc-ar: 2.25;   /* the pictures' shape: the world behind is drawn in it */
  --hc-tar: 1;     /* the thumbnails' */
  --hc-n: 1;
  --hc-w: 100vw;
  --hc-pad: max(16px, 1.7vw);
  --hc-gap: 12px;
  /* Where the whole row fits the stage it stands centred and still (1);
     where it does not, the thumbnail in focus stands in the middle (0). */
  --hc-fit: 1;
  --hc-full: min(clamp(120px, 40svh, 440px),
    calc((100vw - 2 * var(--hc-pad) - (var(--hc-n) - 1) * var(--hc-gap)) / (var(--hc-tar) * (1 + (var(--hc-n) - 1) / 2))));
  --hc-fullw: calc(var(--hc-full) * var(--hc-tar));
  --hc-step: calc(var(--hc-fullw) / 2 + var(--hc-gap));
  --hc-row: calc(var(--hc-fullw) + (var(--hc-n) - 1) * var(--hc-step));
  --hc-top: calc(54% - var(--hc-full) / 2);
  --hc-label: max(10px, 1.03svh);
  --hc-title: max(24px, 6.7svh);
  --hc-headpad: 2.8svh;
  --hc-railw: 20vw;
  --hc-railb: max(14px, 2.2svh);
  /* How far out of focus the world behind is drawn: a share of the picture's
     height as it is drawn (it covers the stage, so it is at least as tall as
     the stage, and taller on a wide, short one). It was .024; Arian: "lower
     the blur on the very top hero section by 25%" (.018), then "make the blur
     less too. its too blurry" — half that. */
  --hc-blur: clamp(3px, calc(max(100svh, 100vw / var(--hc-ar)) * .009), 18px);
  /* The spring the component runs on (stiffness 260, damping 34, mass .9)
     is over-damped: it settles without a bounce, which this curve matches. */
  --hc-spring: cubic-bezier(.22, .9, .3, 1);
  --hc-settle: .62s;
  position: relative; isolation: isolate; overflow: hidden;
  width: 100%; height: 100%; min-height: 24rem;
  user-select: none; -webkit-user-select: none;
  outline: none;
  transition: color .5s ease-out, background-color .5s ease-out;
}
@media (max-width: 900px) {
  .hc { --hc-fit: 0; --hc-full: min(clamp(120px, 40svh, 440px), calc(72vw / var(--hc-tar))); }
}
/* The words take the tone of the world behind them: RESET's, GROUND's and
   DETOX's are pale, CALM's, RELEASE's and BALANCE's deep — measured when the
   picture was filed, then read again by the script from the very part of it
   the words stand on (the headline and the rail each read their own). The
   ground only shows until the picture arrives. */
.hc[data-tone="light"] { color: #121218; background-color: #e6e8ec; --hc-ring: rgba(18, 18, 24, .14); }
.hc[data-tone="dark"] { color: #fff; background-color: #08080c; --hc-ring: rgba(255, 255, 255, .24); }
.hc__head[data-hc-tone="light"], .hc__rail[data-hc-tone="light"] { color: #121218; }
.hc__head[data-hc-tone="dark"], .hc__rail[data-hc-tone="dark"] { color: #fff; }
.hc__rail { transition: color .5s ease-out; }
.hc:focus-visible { outline: 1px solid currentColor; outline-offset: -1px; }

/* ── Background: the world in focus, blurred and otherwise as the file is ─
   The one coming in fades in on top of the one going out, which stays whole
   underneath until it is covered, so nothing between them shows through. */
.hc__bgs { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
.hc__bg { position: absolute; inset: 0; opacity: 0; transition: opacity 0s linear .7s; }
.hc__bg.is-active { z-index: 1; opacity: 1; transition: opacity .7s ease-out; }
.hc__bg picture { position: absolute; inset: 0; display: block; }
/* A world on a flat colour (views/hero-carousel.js, ground): painted. */
.hc__bg--flat { background: var(--hc-paint); }
/* Blurred and nothing else — no hue, no wash — so the thumbnails and the
   words in front of it are the only sharp things on the stage. A blur thins
   out towards a picture's edges, so the picture reaches past the stage by
   twice the blur on every side, and the stage's edge only ever shows it
   whole. (rhythm.css holds anything named __bg to its box's width, and it
   loads last, so this is written one class stronger.) It settles into place
   as it arrives and comes to rest at its true size. */
.hc__bg .hc__bgimg {
  position: absolute; top: calc(var(--hc-blur) * -2); left: calc(var(--hc-blur) * -2);
  display: block; width: calc(100% + var(--hc-blur) * 4); height: calc(100% + var(--hc-blur) * 4); max-width: none;
  object-fit: cover;
  filter: blur(var(--hc-blur));
  transform: scale(1.04); transition: transform 0s linear .7s;
}
.hc__bg.is-active .hc__bgimg { transform: none; transition: transform 1.6s cubic-bezier(.22, 1, .36, 1); }

/* ── The headline, just above the row ────────────────────────────────────── */
.hc__heads { position: absolute; inset: 0 0 auto 0; z-index: 2; height: var(--hc-top); }
/* The number and name, and under them one line of what the Code is — all
   of it on the left, where the worlds are calm (their shapes stand right of
   middle), so the small type is never set on the busiest part of a picture. */
.hc__head {
  position: absolute; left: var(--hc-pad); right: var(--hc-pad); bottom: var(--hc-headpad);
  display: flex; flex-direction: column; align-items: flex-start; gap: calc(var(--hc-label) * 1.3);
  opacity: 0; pointer-events: none;
  transition: opacity .18s ease-out;
}
.hc__head.is-active { opacity: 1; pointer-events: auto; transition: opacity .3s ease-out; }
/* On a narrow screen a world's shape stands just right of middle (RESET's
   disc reaches in from the edge), so the small type keeps to the left. */
@media (max-width: 900px) {
  .hc__head { right: auto; max-width: 50%; }
  .hc__meta { column-gap: calc(var(--hc-label) * 1.6); }
}
/* rhythm.css sizes every h2 (0,3,1, and it loads last); this one is sized
   by the stage, so it is written one class stronger. */
.hc .hc__heads .hc__head .hc__title {
  margin: 0;
  font-family: var(--font-display); font-weight: 300; text-transform: uppercase;
  font-size: var(--hc-title); line-height: .92; letter-spacing: .04em;
}
.hc__titlelink { display: block; color: inherit; text-decoration: none; }
.hc__titlelink:focus-visible { outline: 1px solid currentColor; outline-offset: 6px; }
/* Each line wipes up from behind its own edge. */
.hc__line { display: block; overflow: hidden; padding-bottom: .04em; }
.hc__line > span { display: inline-block; vertical-align: top; transform: translateY(110%); transition: transform 0s linear .2s; }
.hc__head.is-active .hc__line > span { transform: none; transition: transform .62s cubic-bezier(.22, 1, .36, 1) calc(var(--i, 0) * 70ms); }
/* The Code's number leads, in the numeral face and the Code's own gradient —
   the one its collector card wears, lighter end first. */
.hc__line--lead { font-family: var(--font-mark); font-weight: 400; font-size: .82em; letter-spacing: .06em; }
.hc__line--lead > span, .hc__now {
  background-image: linear-gradient(135deg, var(--hc-ra, currentColor), var(--hc-rb, currentColor));
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}
.hc .hc__credit, .hc .hc__meta {
  margin: 0; font-family: var(--font-ui); font-size: var(--hc-label); line-height: 1.5;
  letter-spacing: .14em; text-transform: uppercase;
}
.hc__info { display: flex; flex-wrap: wrap; align-items: baseline; gap: .35rem calc(var(--hc-label) * 3); }
.hc__credit { opacity: 0; transition: opacity .2s; }
.hc__head.is-active .hc__credit { opacity: .9; transition: opacity .5s .1s; }
.hc__meta { display: flex; flex-wrap: wrap; gap: .35rem calc(var(--hc-label) * 2.4); }
.hc__meta span { white-space: nowrap; opacity: 0; transform: translateY(6px); transition: opacity .2s, transform 0s .2s; }
.hc__head.is-active .hc__meta span { opacity: .9; transform: none; transition: opacity .45s, transform .45s; transition-delay: calc(120ms + var(--i, 0) * 60ms); }

/* ── The row: one shared top edge, the thumbnail in focus twice the size ── */
.hc__strip { position: absolute; inset-inline: 0; top: var(--hc-top); z-index: 2; height: var(--hc-full); }
.hc__track {
  display: flex; align-items: flex-start; gap: var(--hc-gap);
  width: max-content;
  /* Centred whole where it fits; otherwise centred on the one in focus. */
  transform: translateX(calc(
    var(--hc-fit) * (var(--hc-w) - var(--hc-row)) / 2 +
    (1 - var(--hc-fit)) * (var(--hc-w) / 2 - var(--hc-index, 0) * var(--hc-step) - var(--hc-fullw) / 2)));
  transition: transform var(--hc-settle) var(--hc-spring);
}
.hc:not(.is-fit) .hc__strip { touch-action: pan-y; }
.hc.is-slide .hc__track { cursor: grab; }
.hc.is-dragging .hc__track { transition: none; cursor: grabbing; }
/* Rounded, the way the files sit in a folder, and edged with a hairline in
   the tone of the world behind, so a pale thumbnail holds its shape on a pale
   world. The corners scale with the thumbnail. */
.hc__card {
  position: relative; flex: none; display: block; overflow: hidden;
  width: calc(var(--hc-fullw) / 2); height: calc(var(--hc-full) / 2);
  border-radius: calc(var(--hc-full) * .03);
  transition: width var(--hc-settle) var(--hc-spring), height var(--hc-settle) var(--hc-spring), border-radius var(--hc-settle) var(--hc-spring);
  -webkit-user-drag: none;
}
.hc__card.is-active { width: var(--hc-fullw); height: var(--hc-full); border-radius: calc(var(--hc-full) * .06); }
.hc__card::after { content: ''; position: absolute; inset: 0; border: 1px solid var(--hc-ring); border-radius: inherit; pointer-events: none; transition: border-color .5s; }
.hc__card picture, .hc__cardimg { display: block; width: 100%; height: 100%; max-width: none; pointer-events: none; }
.hc__cardimg { object-fit: cover; }
/* The thumbnails not in focus sit back a touch without going grey. */
.hc__dim { position: absolute; inset: 0; background: #000; opacity: .1; transition: opacity var(--hc-settle) var(--hc-spring); }
.hc__card.is-active .hc__dim { opacity: 0; }
.hc__card:focus-visible { outline: 1px solid currentColor; outline-offset: 3px; }

/* ── Position rail ───────────────────────────────────────────────────────── */
.hc__rail { position: absolute; left: var(--hc-pad); bottom: var(--hc-railb); z-index: 2; width: var(--hc-railw); }
.hc .hc__count {
  display: flex; justify-content: space-between; margin: 0;
  font-family: var(--font-ui); font-size: var(--hc-label); line-height: 1.4;
  letter-spacing: .14em; font-variant-numeric: tabular-nums; opacity: .9;
}
.hc__line-rail { position: relative; height: 1px; margin-top: .5rem; background: color-mix(in srgb, currentColor 25%, transparent); }
.hc__seg {
  position: absolute; top: -.5px; height: 2px;
  background: linear-gradient(90deg, var(--hc-ra, currentColor), var(--hc-rb, currentColor));
  width: calc(100% / var(--hc-n, 1));
  left: calc(100% * var(--hc-index, 0) / var(--hc-n, 1));
  transition: left var(--hc-settle) var(--hc-spring);
}

/* Scrubbed by the page (hero-carousel.js): the row, the thumbnails, the
   worlds and the rail follow the scroll frame by frame, so nothing eases on
   its own, and each world arrives at its true size. */
.hc.is-scrub .hc__track, .hc.is-scrub .hc__card, .hc.is-scrub .hc__seg, .hc.is-scrub .hc__bg, .hc.is-scrub .hc__dim { transition: none; }
.hc.is-scrub .hc__bg .hc__bgimg { transform: none; transition: none; }
/* Scrubbed, every thumbnail keeps its full size and the script places and
   scales it (from its top-left corner) — moving what is drawn, never
   redrawing it. Its corners scale with it: full size .06, half size .03. */
.hc.is-scrub .hc__track { position: relative; display: block; width: 100%; height: var(--hc-full); transform: none; }
.hc.is-scrub .hc__card, .hc.is-scrub .hc__card.is-active {
  position: absolute; left: 0; top: 0;
  width: var(--hc-fullw); height: var(--hc-full); border-radius: calc(var(--hc-full) * .06);
  transform-origin: 0 0; will-change: transform;
}
.hc.is-scrub .hc__seg { will-change: transform; }

/* Nothing slides into place on the first paint: the script measures, then
   lets the motion in. */
.hc:not(.is-ready) .hc__track, .hc:not(.is-ready) .hc__card, .hc:not(.is-ready) .hc__seg { transition: none; }

@media (prefers-reduced-motion: reduce) {
  .hc, .hc__bg, .hc__bg.is-active, .hc__bg .hc__bgimg, .hc__bg.is-active .hc__bgimg, .hc__head, .hc__line > span,
  .hc__credit, .hc__meta span, .hc__track, .hc__card, .hc__dim, .hc__seg { transition: none !important; }
  .hc__bg .hc__bgimg { transform: none; }
}
