/* The opening and the live model. Loaded after style.css and stages.css, so
   these rules win at equal specificity.

   1. Hero: the human's cinematic loop full-bleed on black, the copy small at
      the lower left, clear of the module in the loop.
   2. Live model: a pinned section on black. The loop fades to black as the
      hero scrolls away and the real-time module comes up in a soft spotlight
      that has no edge anywhere. No 3D canvas sits over the loop. */

/* 1. Hero ---------------------------------------------------------------- */

.hero {
  position: relative;
  height: 100vh;
  min-height: 720px;
  background: #000;
  overflow: hidden;
}

.hero-film,
#hero-film {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  /* The loop's lower edge melts into the black instead of cutting it: the
     module sits clear of the band that fades. */
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 68%, rgba(0, 0, 0, 0.55) 86%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 68%, rgba(0, 0, 0, 0.55) 86%, transparent 100%);
  /* The script fades the loop to black as the hero scrolls away. */
  opacity: 1;
  transition: opacity 0.12s linear;
}

/* Copy: left-aligned in the lower-left third, out of the module's way. It also
   starts clear of the chapter list at every width where the list shows (human,
   2026-10-29), so the list's own gutter is the floor for its left edge. */

.hero-copy {
  position: absolute;
  left: max(var(--ch-gutter, 0px), clamp(56px, 6.5vw, 128px));
  bottom: 12vh;
  z-index: 2;
  width: min(38vw, 620px);
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  pointer-events: none;
  animation: hero-copy-in 1s var(--ease) 0.1s both;
}

@keyframes hero-copy-in {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.hero-title {
  margin: 0;
  font-weight: 700;
  line-height: 0.95;
  letter-spacing: -0.045em;
}

.hero-sub {
  margin: 18px 0 0;
  font-size: 18px;
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: #a1a1a6;
}

.hero-authors {
  margin: 26px 0 0;
  font-size: 16px;
  line-height: 1.55;
  letter-spacing: 0;
  color: var(--muted-dark);
}

.hero-authors a {
  color: var(--fg-dark);
  pointer-events: auto;
  transition: color 0.3s var(--ease);
}

.hero-authors a:hover {
  color: var(--accent);
}

.hero-affil {
  margin: 1px 0 0;
  font-size: 16px;
  line-height: 1.55;
  color: var(--muted-dark);
}

/* The Paper button is the loudest thing on the screen. */

.hero-copy .pill--large {
  margin-top: 34px;
  padding: 17px 42px;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: #000;
  background: var(--accent);
  box-shadow: 0 0 60px rgba(35, 230, 255, 0.22);
  pointer-events: auto;
}

.hero-copy .pill--large:hover {
  filter: brightness(1.1);
}

.hero-copy .pill--large:focus-visible {
  outline: 2px solid rgba(245, 245, 247, 0.9);
  outline-offset: 4px;
}

/* 2. Live model ---------------------------------------------------------- */

.model {
  position: relative;
  height: 300vh;
  background: #000;
  --appear: 0;
}

.model-pin {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  background: #000;
  isolation: isolate;
}

/* The spotlight's light on the air: the same soft cyan pool as the part views
   and the System Introduction section (human, 2026-10-28), centred on the
   module and fading to nothing well inside the pinned frame's own edges, so
   neither the light nor a mask edge ever reads as a line (human, 2026-10-28).
   No disc, no floor. */
.model-glow {
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: var(--appear);
  pointer-events: none;
  background: radial-gradient(
    ellipse 56% 62% at 62% 47%,
    #1c5a68 0%,
    #0d2b33 46%,
    #03090b 78%,
    #000 100%
  );
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 16%, #000 84%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0%, #000 16%, #000 84%, transparent 100%);
}

/* The frosted-glass, button-like invitation under the model (human,
   2026-10-28), centred on the page (human, 2026-10-29): a small pill, a
   translucent white ring, blurred glass behind it. It fades in once the model
   is up and goes on the first click into a part. */
.model-hint {
  position: absolute;
  left: 50%;
  bottom: 8vh;
  z-index: 3;
  transform: translateX(-50%);
  padding: 13px 24px;
  border: 1px solid rgba(255, 255, 255, 0.17);
  border-radius: 980px;
  background: rgba(255, 255, 255, 0.075);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  backdrop-filter: blur(16px) saturate(150%);
  color: rgba(245, 245, 247, 0.94);
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.005em;
  white-space: nowrap;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.7s var(--ease), background-color 0.25s var(--ease),
    border-color 0.25s var(--ease);
}

.model.is-hint .model-hint {
  opacity: 1;
  pointer-events: auto;
}

.model-hint:hover {
  background: rgba(255, 255, 255, 0.13);
  border-color: rgba(255, 255, 255, 0.28);
}

#hero-stage {
  position: absolute;
  inset: 0;
  z-index: 1;
}

#hero-stage canvas {
  opacity: var(--appear);
  /* Nothing but the light: the canvas edge never shows as an edge. */
  background: transparent;
}

/* Part labels: plain text with one fine line to the part, no box ---------- */

#hero-stage .part-label {
  color: var(--fg-dark);
  transition: opacity 0.28s var(--ease);
}

/* The script fades every name out as the pinned frame leaves the window. */
#hero-stage .part-label.is-on {
  opacity: var(--label-fade, 1);
}

#hero-stage .part-label__title {
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.008em;
  color: #f5f5f7;
}

/* The cyan prompt under a hovered part's name: the human's words for the click,
   a chevron after them, no box, no background. Only the part under the pointer
   carries it; the quiet names the turn brings up never do. The script keeps it
   in the label's flow, so the label's height is measured with it. */
#hero-stage .part-prompt {
  display: table;  /* shrink to its text, so the chevron follows the words */
  margin-top: 4px;
  padding-right: 12px;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: 0.02em;
  color: var(--accent);
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'><path d='M3 1.4 5.7 4 3 6.6' fill='none' stroke='%2323e6ff' stroke-width='1.1' stroke-linecap='round' stroke-linejoin='round'/></svg>") no-repeat right 2px center;
  background-size: 8px 8px;
  opacity: 0;
  transform: translateY(-2px);
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease);
}

#hero-stage .part-prompt.is-on {
  opacity: 1;
  transform: none;
}

/* The names the turn brings up one after another: softer than a hovered
   part's name, on one quiet column, so the screen reads as the module and its
   parts, never as text over the model. */

#hero-stage .part-label--soft {
  transition: opacity 0.7s var(--ease);
}

#hero-stage .part-label--soft .part-label__title {
  font-size: 18px;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: rgba(245, 245, 247, 0.82);
}

#hero-stage .part-line {
  background: #86868b;
  transition: opacity 0.28s var(--ease);
}

#hero-stage .part-line--soft {
  transition: opacity 0.7s var(--ease);
}

#hero-stage .part-line.is-on {
  opacity: calc(0.45 * var(--label-fade, 1));
}

/* A hovered part's name takes the quiet column's place at once: two names for
   one part on one screen reads as a mistake. */
#hero-stage.is-part .part-label--soft,
#hero-stage.is-part .part-line--soft {
  transition-duration: 0.14s;
}

/* Cursor: the module offers a drag, a part offers a click, a running drag
   shows itself. */

#hero-stage.is-grab canvas {
  cursor: grab;
}

#hero-stage.is-part canvas {
  cursor: pointer;
}

#hero-stage.is-grabbing canvas,
#hero-stage.is-part.is-grabbing canvas {
  cursor: grabbing;
}

@media (prefers-reduced-motion: reduce) {
  .hero-copy {
    animation: none;
  }

  .hero-film,
  #hero-film,
  #hero-stage canvas,
  #hero-stage .part-label,
  #hero-stage .part-line {
    transition: none;
  }

  #hero-stage .part-prompt {
    transition: none;
  }

  .model-hint {
    transition: none;
  }
}

/* Narrower desktop windows: the loop's module reaches further left in the
   frame there, so the title steps down to stay clear of it and of the chapter
   list the copy now starts beside (human, 2026-10-29). */

@media (max-width: 1639px) {
  .hero-title {
    font-size: clamp(72px, 5.6vw, 104px);
  }
}
