/* home/quote.css: the dark pull quote of index.html. Owned by quote.
   One breath of quiet between the busy sections, and the page's only scroll
   scrubbed text: home/quote.js splits the quote into words and writes one
   number, --h-quote-p (0 to 1), on the section as you scroll through. Every
   word's light and the brain's brightness are worked out from it here. */

.dark-quote {
  position: relative;
  /* clip, not hidden: hidden makes a scroll container, which captures CSS
     scroll timelines and kills sticky (base pitfall 5). */
  overflow: hidden;
  overflow: clip;
  background: #111111;
  padding: 9.5rem 5vw;
}

/* ── The brain ──────────────────────────────────────────────────────────────
   Desktop: a 16:9 frame behind the right half, set a little past the edge so
   the brain sits clear of most of the type. An oval mask dissolves the
   frame's edges into the ground (it replaced four gradient bands). */
.dark-quote__bg {
  position: absolute;
  top: 50%;
  right: -7%;
  width: min(64%, 1060px);
  aspect-ratio: 16 / 9;
  translate: 0 -50%;
  pointer-events: none;
  z-index: 0;
  opacity: 0.5;
  -webkit-mask-image: radial-gradient(ellipse 50% 60% at 54% 54%, #000 68%, transparent 100%);
  mask-image: radial-gradient(ellipse 50% 60% at 54% 54%, #000 68%, transparent 100%);
}
.dark-quote__bg img,
.dark-quote__bg video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The film fades in over the still once its first frame is on screen, so
   the swap is a dissolve, never a cut. */
.h-quote-film {
  opacity: 0;
  transition: opacity 0.6s var(--h-ease);
}
.h-quote-ready .h-quote-film { opacity: 1; }

/* ── The quote ──────────────────────────────────────────────────────────── */
.dark-quote__inner {
  max-width: var(--max-w);
  margin: 0 auto;
  position: relative;
  z-index: 1;
}

.dark-quote__text {
  margin: 0 0 3rem;
  font-family: 'Bebas Neue', var(--display);
  font-size: clamp(2.8rem, 5.5vw, 6rem);
  font-weight: 400;
  color: #ffffff;
  line-height: 1;
  letter-spacing: 0.01em;
}
.dark-quote__text p { margin: 0; }
/* The phone's extra break (after "given"): wider screens keep the three
   original lines. */
.h-quote-br { display: none; }
.dark-quote__text em {
  color: var(--teal);
  font-style: normal;
  white-space: nowrap;
}

/* The scrub. Word i of n lights while the progress passes i/(n+k) to
   (i+k)/(n+k): a soft wave about k words wide moving in reading order, so a
   wheel notch glides instead of stepping. Unlit words keep 3:1 on the
   ground (large text), so the line is legible at every position. */
.h-quote-on [data-h-quote-text] {
  --h-quote-k: 2.6;
  --h-quote-lo: 0.34;
}
.h-quote-on .h-quote-w {
  --h-quote-lit: clamp(0, (var(--h-quote-p, 1) * (var(--h-quote-n, 15) + var(--h-quote-k)) - var(--h-quote-i, 0)) / var(--h-quote-k), 1);
  opacity: calc(var(--h-quote-lo) + (1 - var(--h-quote-lo)) * var(--h-quote-lit));
}
/* "become one." waits in the same grey as every unlit word and turns blue as
   it lights: the payoff lands last. (Without color-mix it simply stays blue.) */
.h-quote-on .dark-quote__text em .h-quote-w {
  color: color-mix(in srgb, var(--teal) calc(var(--h-quote-lit) * 100%), #ffffff);
}
/* The brain warms with the words: dim while the line is still dark, full
   when the last word lands. */
.h-quote-on .dark-quote__bg {
  opacity: calc(0.22 + 0.34 * var(--h-quote-p, 1));
}

/* ── The attribution: a signature, not a label. The name leads, the post
   follows; the middle dot stays in the markup for reading without styles. */
.dark-quote__attr {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.3rem 0.85rem;
  font-family: var(--sans);
  font-size: 0.98rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.64);
}
.h-quote-name {
  font-family: var(--display);
  font-weight: 600;
  letter-spacing: 0.005em;
  color: rgba(255, 255, 255, 0.92);
}
.h-quote-sep { display: none; }

/* ── Tablet and phone: the type fills the column, so the brain gets its own
   place above the quote instead of sitting behind it. It enters first, dim,
   and warms as the words below it light. */
@media (max-width: 900px) {
  .dark-quote { padding: 1rem 6vw 5rem; }
  .dark-quote__bg {
    position: relative;
    top: auto;
    right: auto;
    translate: none;
    width: min(140vw, 760px);
    margin: 0 0 calc(-1 * min(12vw, 72px)) calc(50% - min(70vw, 380px));
    -webkit-mask-image: radial-gradient(ellipse 46% 52% at 55% 54%, #000 62%, transparent 100%);
    mask-image: radial-gradient(ellipse 46% 52% at 55% 54%, #000 62%, transparent 100%);
  }
  /* Three lines while the first one fits the column... */
  .dark-quote__text { font-size: calc(88vw / 12.7); margin-bottom: 2.4rem; }
}
@media (max-width: 600px) {
  /* ...then four: a short opener, then three lines sized to run the full
     width (the longest, "the only honest response", is 8.78em). */
  .h-quote-br { display: inline; }
  .dark-quote__text { font-size: calc(88vw / 9.1); }
  .dark-quote__attr { font-size: 0.92rem; gap: 0.15rem 0.85rem; }
  .h-quote-name { flex-basis: 100%; }
}

/* Reduced motion: the whole quote, the still frame, nothing moves. */
@media (prefers-reduced-motion: reduce) {
  .h-quote-on .h-quote-w { opacity: 1; }
  .h-quote-on .dark-quote__text em .h-quote-w { color: inherit; }
  .h-quote-on .dark-quote__bg { opacity: 0.5; }
  .h-quote-film { transition: none; }
}
@media print {
  .h-quote-w { opacity: 1 !important; }
  .dark-quote__text em .h-quote-w { color: inherit !important; }
}
