/* Hero: Norman's face rendered live on a full-bleed canvas (hero-gl.js, hero-shaders.js).
   Scrolling turns the face into a UI/UX anime redraw, then an AI model, then splits it into all three,
   then blows it apart. hero.js shows the matching .hero-slide for each stage. */
.hero-track { height: 810vh; }
.hero { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden; isolation: isolate; background: var(--ink); touch-action: pan-y; }
/* Stage backgrounds, stacked so UI and AI cover UX. hero.js clips UI and AI along the face's dividers. */
.hero-bgs { position: absolute; inset: 0; z-index: 0; opacity: var(--bg-o, 1); pointer-events: none; }
.hero-bg { position: absolute; inset: 0; background: center / cover no-repeat; }
.hero-bg-ux { background-image: url('../img/hero/bg-ux.webp?v=20261104b'); }
.hero-bg-ui { background-image: url('../img/hero/bg-ui.webp?v=20261104b'); clip-path: inset(0 0 0 100%); }
/* Falling magenta characters, drawn by hero-matrix.js and dimmed so the face stays in front. */
.hero-bg-ai { background: #000; clip-path: inset(0 0 0 100%); }
.hero-bg-ai canvas { display: block; width: 100%; height: 100%; opacity: 0.6; }
/* What the glass name refracts. Covered by .hero-bgs, which shows the same picture. */
.hero-name-backdrop { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; }
.hero-canvas { position: absolute; z-index: 1; inset: 0; width: 100%; height: 100%; }
.hero-fallback { position: absolute; z-index: 1; left: 50%; top: 0; height: 100%; width: auto; max-width: none; transform: translateX(-50%); opacity: 0; animation: hero-fallback-in 0.9s 3.5s forwards; }
/* Only for browsers without WebGL. Waits so the name still comes first. */
@keyframes hero-fallback-in { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .hero-fallback { opacity: 1; animation: none; } }
.hero.has-gl .hero-fallback { display: none; }

.hero-slide { position: absolute; inset: 0; z-index: 2; display: flex; flex-direction: column; justify-content: flex-end; padding: 0 var(--gutter) clamp(20px, 3.4vh, 40px); pointer-events: none; opacity: var(--o, 0); visibility: hidden; }
.hero-slide.is-on { visibility: visible; }
/* UX, UI and AI: the slide adds no stacking layer, so the eyebrow can sit behind the portrait while the big word stays in
   front of it. Opacity moves to the children for the same reason; hero.js folds the slide's opacity into the eyebrow's. */
.hero-slide-stack { z-index: auto; opacity: 1; }
.hero-slide-stack .hero-word { position: relative; z-index: 2; opacity: var(--o, 0); }
.hero-slide a { pointer-events: auto; }

/* Dark floor under the type so it reads over the shoulders. */
.hero::after { content: ''; position: absolute; inset: auto 0 0; height: 24%; z-index: 1; pointer-events: none; background: linear-gradient(to top, rgba(0, 0, 0, 0.72), transparent); }

/* The name sits behind the head on two lines, in the vertical center: the canvas above it is transparent around the portrait.
   Set in Nebula, always in capitals. */
.hero-name { position: absolute; z-index: 0; inset: 50% 0 auto; font-family: 'Nebula', var(--body); font-size: min(13.94vw, 32.2vh); font-weight: 400; line-height: 0.66; text-align: center; text-transform: uppercase; white-space: nowrap; transform: translateY(-50%); scale: var(--name-s, 1); opacity: calc(var(--o, 0) * var(--name-out, 1)); pointer-events: none; }

.hero-name-fx { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; pointer-events: none; }
.hero-name > span { display: block; color: rgba(255, 255, 255, 0.85); }
/* The glass comes from the refraction alone (hero-glass-name.js), so the library's light gradient over the letters is removed. */
.hero-name .slgf-layout[data-ready="true"] > .slgf-letters { background: none; }
.hero-word { font-family: 'Nebula', var(--body); font-size: 24.5vw; font-weight: 400; letter-spacing: normal; line-height: 0.82; margin-left: 0.01em; -webkit-text-stroke: 0.022em currentColor; }
.hero-word-ux { color: var(--text); }
/* Nebula capitals sit low in their line, so the word pulls up to meet its eyebrow. */
.hero-note + .hero-word { margin-top: -0.215em; }
.hero-word-ui { color: var(--ui); }
.hero-word-ai { color: var(--ai); }
/* Eyebrow anchored to the top left of the screen on wide screens, clear of the nav on the right and starting above the
   head. Tall screens stack it on top of the big word instead. Monument is always in capitals. */
.hero-stack { display: inline-grid; align-self: flex-start; }
.hero-note { position: absolute; z-index: 0; top: calc(clamp(20px, 3.4vh, 40px) + 60px); left: var(--gutter); width: 40vw; font-family: 'Monument', var(--body); font-size: min(4.4vw, 7vh); font-weight: 400; line-height: 1.05; text-transform: uppercase; }

/* Final split: hero.js slides UX and AI in toward UI, each staying on its own side of the dividers. */
.hero-trio { position: relative; height: 1em; font-family: 'Nebula', var(--body); font-size: 11vw; font-weight: 400; letter-spacing: normal; line-height: 1; -webkit-text-stroke: 0.022em currentColor; }
.hero-trio span { position: absolute; left: 0; bottom: 0; white-space: nowrap; will-change: transform; }

/* Selection frame around the head, placed from the face position by hero.js.
   UI stage: a design tool selection with handles. AI stage: a detection box. */
.face-box { position: absolute; z-index: 1; left: 0; top: 0; border: 1.5px solid var(--box, var(--ui)); pointer-events: none; opacity: var(--o, 0); will-change: transform; }
.face-box i { position: absolute; width: 11px; height: 11px; background: #000; border: 1.5px solid var(--box, var(--ui)); }
.face-box i:nth-child(1) { left: -6px; top: -6px; } .face-box i:nth-child(2) { right: -6px; top: -6px; }
.face-box i:nth-child(3) { left: -6px; bottom: -6px; } .face-box i:nth-child(4) { right: -6px; bottom: -6px; }
.face-box b { position: absolute; left: -1.5px; bottom: 100%; margin-bottom: 7px; padding: 3px 9px; background: var(--box, var(--ui)); color: #000; font-size: 13px; font-weight: 600; white-space: nowrap; }

.hero-cue { align-self: center; width: 1px; height: 54px; margin-bottom: 10px; background: linear-gradient(to bottom, transparent, #fff); transform-origin: top; animation: cue 1.9s var(--ease) infinite; }
@keyframes cue { from { transform: scaleY(0); } 60% { transform: scaleY(1); } to { transform: scaleY(1); opacity: 0; } }

/* Same shape test as layout() in hero-gl.js. On tall screens the head is wider than the name and would hide it,
   so the name sits at the top, overlapped by the crown of the head. */
@media (max-aspect-ratio: 20/23) {
  /* The 2.5vw keeps the name's middle where the head overlaps it. */
  .hero-name { top: calc(8vh + 2.5vw); transform: none; }
  /* The middle of each background is dark, so narrow screens show the part with the lights. */
  .hero-bg { background-position: 14% center; }
  /* Stacked over the T-shirt here, so it stays in front of the portrait. */
  .hero-note { position: relative; top: auto; left: auto; z-index: 2; width: calc(100vw - 2 * var(--gutter)); margin-bottom: 0.1em; font-size: 4.65vw; }
  .hero-note-long { font-size: 4.65vw; }
  /* A deeper floor, because the eyebrows sit on the white T-shirt on tall screens. */
  .hero::after { height: 42%; background: linear-gradient(to top, rgba(0, 0, 0, 0.92) 55%, transparent); }
}
@media (max-width: 720px) {
  /* Low enough that the top of the head overlaps ORTIZ. */
  .hero-name { top: calc(12.5vh + 2.5vw); }
  .hero-word { font-size: 40vw; }
  .hero-note { font-size: clamp(30px, 9.3vw, 72px); }
  .hero-note-long { font-size: 8.2vw; }
  .hero-trio { font-size: 9.5vw; }
  .hero-cue { display: none; }
}
