/* hero.css — the hero as a place, not a backdrop.
 *
 * One container, `[data-hero-scene]`, whose height is locked here. Every
 * layer initHero() injects is absolutely positioned inside it, so the scene
 * can never shift the page it is dropped into.
 *
 * Three planes, and the plane an object sits on is how you read its depth:
 *
 *   background  the sky, the rising sun, the far motes
 *   midground   the pale far ridge, and the deep weather behind the headline
 *   headline    the headline, oversized, bleeding off both edges, with its
 *               second line cut by the near ridge
 *   foreground  weather crossing in front of the headline, the near ridge
 *               with the ten lit windows on it, the nearest band, the copy
 *
 * Back to front by z-index:
 *   .hero__sky 0   .hero__stars 1   .hero__clouds--far 2
 *   .hero__ridge--far 3            .hero__word 4
 *   .hero__clouds--near 5          .hero__ridge 6
 *   .hero__ground 7   .hero__note 8   .hero__cue 9
 *
 * With no script the container still paints sky, sun, far ridge and ground, so
 * the section reads as a horizon rather than a gap.
 *
 * The sky ramp ends on the same value the OS wallpaper opens with, which is
 * what makes the hero hand off into the desktop instead of butting against it.
 */

[data-hero-scene] {
  --hero-ink: var(--ink, #17151F);
  --hero-paper: var(--paper, #F6F1E7);
  --hero-violet: var(--violet, #6D5BD0);
  --hero-plum: var(--plum, #3A2F63);
  --hero-glow: #FFF3D6;
  --hero-serif: var(--serif, "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif);
  --hero-mono: var(--mono, ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace);

  /* The two ridgelines, authored once here and read back by hero.js so the
     windows can stand on the exact silhouette that gets drawn. */
  --far-profile:
    0% 52%, 10% 44%, 20% 50%, 30% 36%, 40% 42%, 50% 28%, 60% 34%,
    70% 22%, 80% 30%, 90% 38%, 100% 44%;
  --near-profile:
    0% 68%, 10% 60%, 20% 66%, 30% 52%, 40% 58%, 50% 44%, 60% 50%,
    70% 38%, 80% 46%, 90% 54%, 100% 60%;

  position: relative;
  isolation: isolate;
  display: block;
  min-height: 100vh;
  min-height: 100svh;
  overflow-x: hidden;
  overflow-x: clip;
  overflow-y: hidden;
  background: #221C42;
  color: var(--hero-glow);
  font-family: var(--hero-serif);
  contain: layout paint;
}

/* ══ the sky ═══════════════════════════════════════════════════════════════
   Layered backgrounds, no child elements: it survives script failure and
   costs nothing to scroll past. */

.hero__sky {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    /* the sun's bloom — wide, low, and deliberately soft */
    radial-gradient(circle 26vmax at 78% 57%,
      rgba(255, 243, 214, .2) 0%, rgba(255, 243, 214, 0) 62%),
    /* the disc, cresting the far ridge with a real edge to it */
    radial-gradient(circle 5.4vmax at 78% 62%,
      var(--hero-glow) 0 82%, rgba(255, 243, 214, .4) 91%, rgba(255, 243, 214, 0) 100%),
    /* paper tooth, so the sky is printed rather than computed */
    repeating-linear-gradient(74deg,
      rgba(23, 21, 31, .04) 0 1px, rgba(23, 21, 31, 0) 1px 4px),
    /* the ramp: plum zenith down to the desktop's opening colour */
    linear-gradient(180deg,
      #1C1738 0%, #33295C 12%, #4E3F89 25%, #6A5AB8 37%, #8A79D0 47%,
      #AC9BE0 55%, #C9BAEA 63%, #E2D8F6 71%, #EFE6FF 88%, #EFE6FF 100%);
}

/* ══ far motes ════════════════════════════════════════════════════════════ */

.hero__stars {
  position: absolute;
  inset: 0 0 46%;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.2s ease .1s;
}
.is-ready .hero__stars { opacity: 1; }
.hero__stars svg { width: 100%; height: 100%; display: block; }

/* ══ the far ridge — the midground that makes a near ridge mean anything ══ */

.hero__ridge--far {
  position: absolute;
  left: -8%;
  width: 116%;
  bottom: 0;
  height: 56%;
  z-index: 3;
  pointer-events: none;
  background: linear-gradient(180deg,
    #7B69C4 0%, #6353AC 26%, #463A80 66%, #2E2552 100%);
  clip-path: polygon(var(--far-profile), 100% 100%, 0% 100%);
  opacity: .82;
}
@media (max-width: 760px) {
  .hero__ridge--far { height: 62%; }
}

/* ══ weather ══════════════════════════════════════════════════════════════ */

.hero__clouds {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}
.hero__clouds--near { z-index: 5; }

.hero__cloud {
  position: absolute;
  left: var(--cx);
  top: var(--cy);
  margin: 0;
  translate: -50% -50%;
  scale: var(--cs, 1);
  opacity: 0;
  animation: hero-fade 1.6s var(--cd, 0s) ease forwards;
}
.hero__cloud svg {
  display: block;
  width: var(--cw, 260px);
  height: auto;
  overflow: visible;
  animation: hero-drift var(--drift, 70s) linear infinite alternate;
  animation-delay: var(--ddelay, 0s);
}

@keyframes hero-drift {
  from { translate: -3% 0; }
  to   { translate: 3% 0; }
}
@keyframes hero-fade { to { opacity: var(--cop, .9); } }

/* ══ the headline, as a spatial object ════════════════════════════════════
   Two lines of one oversized word, set past both edges of the frame. Near
   weather crosses its shoulder and the near ridge cuts its baseline, so the
   type is inside the scene rather than printed on top of it. */

.hero__word {
  position: absolute;
  z-index: 4;
  left: 50%;
  top: 41%;
  width: 106%;
  margin: 0;
  translate: -50% 0;
  text-align: center;
  font-family: var(--hero-serif);
  font-weight: 700;
  font-size: clamp(3.4rem, 12.6vw, 11.6rem);
  line-height: .84;
  letter-spacing: -.04em;
  white-space: nowrap;
  color: rgba(255, 243, 214, .2);
  -webkit-text-stroke: 2px rgba(255, 243, 214, .46);
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.4s ease .18s;
}
.is-ready .hero__word { opacity: 1; }

.hero__word-line { display: block; }
.hero__word-line + .hero__word-line {
  font-style: italic;
  color: rgba(255, 243, 214, .34);
  -webkit-text-stroke-color: rgba(255, 243, 214, .62);
  translate: 3.5% .05em;
}

/* ══ the near ridge, and the ten lit windows on it ════════════════════════ */

.hero__ridge {
  position: absolute;
  left: -8%;
  width: 116%;
  bottom: 0;
  height: 56%;
  z-index: 6;
  pointer-events: none;
}
/* The hill is a clipped pseudo-element, not the layer the windows live in —
   clipping the parent would eat the doors standing on its silhouette. */
.hero__ridge::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    #2E2552 0%, #221B40 30%, #171130 68%, #100B23 100%);
  clip-path: polygon(var(--near-profile), 100% 100%, 0% 100%);
}
.hero__ridge::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(255, 243, 214, .5) 0%, rgba(255, 243, 214, .12) 1.4%, rgba(255, 243, 214, 0) 4.2%);
  clip-path: polygon(var(--near-profile), 100% 100%, 0% 100%);
}

.hero__worlds {
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.hero__door {
  position: absolute;
  left: var(--x);
  top: var(--y);
  translate: -50% -100%;
  display: grid;
  justify-items: center;
  gap: .3em;
  scale: var(--ds, 1);
  opacity: 0;
  animation: hero-lit 1.1s var(--dd, 0s) ease forwards;
}
@keyframes hero-lit { to { opacity: 1; } }

/* the world, drawn in its own accent, stood on the hill beside its window */
.hero__mark {
  display: block;
  width: clamp(16px, 1.95vw, 28px);
  height: auto;
  color: var(--accent, var(--hero-glow));
  filter: drop-shadow(0 1px 1px rgba(10, 8, 20, .85));
}

/* the building. Dark shell, one lit pane in the world's own accent — so the
   ten windows on the hill are legibly ten different businesses. */
.hero__house {
  display: block;
  width: clamp(24px, 2.9vw, 40px);
  height: auto;
  overflow: visible;
  filter: drop-shadow(0 1px 2px rgba(6, 4, 14, .7));
}
.hero__shell { fill: #0C0819; }
.hero__pane {
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--accent, #FFF3D6) 65%, transparent));
}
/* three panes in ten breathe, out of phase. Nothing else on the hill moves. */
.hero__door:nth-child(3n) .hero__pane {
  animation: hero-breathe 7.5s ease-in-out infinite 1.2s;
}
.hero__door:nth-child(4n) .hero__pane {
  animation: hero-breathe 11s ease-in-out infinite .4s;
}
@keyframes hero-breathe {
  50% { filter: drop-shadow(0 0 13px 3px color-mix(in srgb, var(--accent, #FFF3D6) 80%, transparent)); }
}

/* the accessible name for a window you can only see */
.hero__vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ══ the nearest band ═════════════════════════════════════════════════════
   Almost silhouette. It is what makes the two ridges behind it read as far. */

.hero__ground {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 12%;
  z-index: 7;
  pointer-events: none;
  background: linear-gradient(180deg,
    #0A0715 0%, #070510 46%, rgba(7, 5, 16, .5) 74%, rgba(7, 5, 16, 0) 100%);
  filter: drop-shadow(0 -3px 0 rgba(255, 243, 214, .16));
  clip-path: polygon(
    0% 30%, 5% 16%, 10% 26%, 15% 8%, 21% 22%, 27% 5%, 33% 18%,
    39% 3%, 45% 17%, 51% 2%, 57% 15%, 63% 4%, 69% 21%, 75% 10%,
    81% 25%, 87% 15%, 93% 29%, 100% 21%, 100% 100%, 0% 100%);
}

/* ══ supporting copy ══════════════════════════════════════════════════════ */

.hero__note {
  position: absolute;
  z-index: 8;
  left: 50%;
  bottom: 7%;
  width: min(46ch, 82vw);
  translate: -50% 0;
  margin: 0;
  text-align: center;
  pointer-events: none;
}
.hero__note p { margin: 0; }
.hero__note-lede {
  font-size: clamp(.98rem, .55rem + 1vw, 1.32rem);
  line-height: 1.5;
  letter-spacing: -.005em;
  color: rgba(255, 243, 214, .86);
  text-wrap: balance;
  text-shadow: 0 1px 10px rgba(8, 6, 15, .9);
}
.hero__note-lede b {
  font-weight: 700;
  font-style: italic;
  color: var(--hero-glow);
}
.hero__note-sub {
  margin-top: .7em;
  font-family: var(--hero-mono);
  font-size: clamp(.58rem, .26rem + .3vw, .68rem);
  letter-spacing: .24em;
  text-transform: uppercase;
  color: rgba(255, 243, 214, .46);
}

/* ══ the way out ══════════════════════════════════════════════════════════ */

.hero__cue {
  position: absolute;
  z-index: 9;
  left: 50%;
  bottom: 1%;
  translate: -50% 0;
  display: grid;
  justify-items: center;
  gap: .35rem;
  font-family: var(--hero-mono);
  font-size: .58rem;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: rgba(255, 243, 214, .4);
  pointer-events: none;
}
.hero__cue-chevron {
  display: block;
  width: 14px;
  height: 8px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  rotate: 45deg;
  animation: hero-nod 2.6s ease-in-out infinite;
}
@keyframes hero-nod {
  0%, 100% { translate: 0 0; opacity: .4; }
  50%      { translate: 0 4px; opacity: 1; }
}

/* ══ parallax plumbing ═══════════════════════════════════════════════════
   hero.js writes --px (page scroll) and --mx/--my (pointer lean) on the
   container. Every rule below consumes them in `transform` only: no layout,
   no repaint, one composited property per node, and the rates are ordered so
   near things travel further than far things. */

[data-hero-scene] > :is(
  .hero__stars, .hero__clouds, .hero__ridge--far,
  .hero__word, .hero__ridge, .hero__ground
) {
  will-change: transform;
  transform:
    translate3d(
      calc(var(--mx, 0px) * var(--pxs, 1)),
      calc(var(--my, 0px) * var(--pys, 1) + var(--px, 0px) * var(--pxs, 1) * -1),
      0);
}

.hero__stars       { --pxs: .04; --pys: .03; }
.hero__clouds--far { --pxs: .10; --pys: .05; }
.hero__ridge--far  { --pxs: .07; --pys: .04; }
.hero__word        { --pxs: .05; --pys: .07; }
.hero__clouds--near{ --pxs: .20; --pys: .09; }
.hero__ridge       { --pxs: .03; --pys: .12; }
.hero__ground      { --pxs: .01; --pys: .16; }

/* ══ reduced motion ═══════════════════════════════════════════════════════
   The scene is a drawing, so stopping the motion costs nothing: no drift, no
   breathing, no nod, no lean. hero.js also stops writing parallax. Nothing is
   hidden by the animation — every layer is fully legible at its end state. */

@media (prefers-reduced-motion: reduce) {
  .hero__cloud,
  .hero__door { animation: none; opacity: 1; }
  .hero__cloud { opacity: var(--cop, .9); }
  .hero__cloud svg,
  .hero__pane,
  .hero__cue-chevron { animation: none; }
  .hero__stars,
  .hero__word { transition: none; opacity: 1; }
  [data-hero-scene] > :is(
    .hero__stars, .hero__clouds, .hero__ridge--far,
    .hero__word, .hero__ridge, .hero__ground
  ) { transform: none; }
}

/* ══ narrow viewports ══════════════════════════════════════════════════════
   The headline stops being a poster and becomes a caption; the near ridge
   rises to take the frame. A recomposed scene, not a crop. */

@media (max-width: 760px) {
  .hero__word {
    top: 34%;
    width: 118%;
    font-size: clamp(3rem, 20vw, 7rem);
    line-height: .86;
  }
  .hero__note { width: min(38ch, 88vw); }
  .hero__cue { display: none; }
}

@media (max-width: 420px) {
  .hero__ridge { height: 50%; }
  .hero__note-lede { font-size: .92rem; }
  .hero__note-sub { letter-spacing: .14em; }
}
