/* =====================================================================
   Veris AI — speaking.html only.

   Deliberately a separate stylesheet rather than an append to styles.css:
   index.html and work.html then never download it, styles.css is provably
   unmodified by this build, and Scott's coming professional-tone redesign
   can rework this page without touching the shared sheet. Everything here
   is scoped to .spk-* and consumes the existing :root tokens.

   The one real design problem this solves: the only footage of Scott on
   stage is 9:16 phone video shot from the floor. A 16:9 crop of it keeps a
   narrow horizontal band and decapitates him, so the hero does not crop it
   into landscape at all. On a portrait viewport the clip simply fills the
   background — the aspect it was shot in. On desktop it is anchored right
   at native aspect behind a gradient that resolves to solid ground under
   the headline.
   ===================================================================== */

.spk-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  align-items: center;
  min-height: clamp(34rem, 82vh, 46rem);
  /* Pull up under the transparent sticky header, the way the homepage hero
     does. Without this the header floats over the light page background and
     its white wordmark and links become invisible. */
  margin-top: -76px;
  padding-block: calc(76px + clamp(6rem, 12vw, 9rem)) clamp(3.5rem, 8vw, 6rem);
  border-bottom: 1px solid var(--line-dark);
  background: var(--navy-950);
}

.spk-hero-media {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 0;
}

.spk-hero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Bias hard upward. He stands in the upper two-thirds of the 540x960
     source (head roughly y=170..240) and the lower third is stage skirt
     and hotel carpet.

     This value is NOT free to tune by eye. A percentage object-position
     resolves against the OVERFLOW, not against the frame, so the crop
     window drifts further down the source the more the video has to be
     scaled up. That means the framing degrades as the screen gets WIDER:
     at 34% his head was already cut at 860px, and the earlier desktop
     value of 30% left only 39px of headroom at 1920 and went negative
     past roughly 2100px, which is an ordinary external monitor.

     Below 900px the clip is full-bleed behind the copy, so this value has
     a second job: lift him far enough that his face clears the headline
     rather than sitting behind it. 22% does both. The side-panel layout
     at >=900px, where nothing overlays him, uses 16% instead.

     Re-run `node scripts/hero-framing.mjs` after changing either. */
  object-position: center 22%;
}

.spk-hero-scrim {
  position: absolute;
  inset: 0;
  /* Portrait: the text sits directly over the clip, so this does real work.
     These stops are MEASURED, not eyeballed. The step-and-repeat banner behind
     Scott is near-white, and it lands squarely behind the headline. Compositing
     the scrim over eight real frames sampled across the loop and computing WCAG
     contrast against the actual pixels:

         mid stop 66%  ->  3.83–4.03 : 1   FAILS AA (needs 4.5)
         mid stop 78%  ->  5.97–6.18 : 1   passes with margin

     So 66% was a real accessibility defect, not a close call, and it looked
     fine by eye. Do not lower these to make the clip brighter without
     re-running that measurement. */
  background:
    linear-gradient(
      180deg,
      color-mix(in oklch, var(--navy-950) 90%, transparent) 0%,
      color-mix(in oklch, var(--navy-950) 78%, transparent) 30%,
      color-mix(in oklch, var(--navy-950) 90%, transparent) 66%,
      var(--navy-950) 100%
    );
}

.spk-hero-inner {
  position: relative;
  z-index: 1;
  width: 100%;
}

.spk-hero-copy { max-width: 40rem; }

.spk-hero h1 {
  font-size: var(--step-display);
  letter-spacing: -0.032em;
  text-wrap: balance;
  margin: 0 0 1.35rem;
}

.spk-hero-lead {
  font-size: var(--step-body);
  color: var(--on-dark-2);
  max-width: 34rem;
  text-wrap: pretty;
  margin: 0 0 2rem;
}

/* ---------------------------------------------------------------------
   WCAG 2.2.2 (Level A): the hero loop runs longer than five seconds
   alongside other content, so it needs a visible, keyboard-operable pause
   control. It is a real <button>; its label and state are driven off the
   video's own play/pause events rather than an assumed boolean, so it
   stays honest when a browser silently refuses autoplay.
   --------------------------------------------------------------------- */
.spk-media-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 2.25rem;
  padding: 0.5rem 0.85rem;
  background: color-mix(in oklch, var(--navy-900) 86%, transparent);
  border: 1px solid var(--line-dark);
  border-radius: var(--r-sm);
  color: var(--on-dark-2);
  font-family: var(--font-display);
  font-size: var(--step-micro);
  font-weight: 500;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: color 0.18s var(--ease-out-quart), border-color 0.18s var(--ease-out-quart);
}

.spk-media-toggle:hover {
  color: var(--on-dark);
  border-color: color-mix(in oklch, var(--blue-lit) 40%, transparent);
}

.spk-media-toggle-icon {
  width: 9px;
  height: 11px;
  flex-shrink: 0;
  background: var(--blue-lit);
  /* Paused (the default): a play triangle. */
  clip-path: polygon(0 0, 100% 50%, 0 100%);
}

.spk-media-toggle[data-playing="true"] .spk-media-toggle-icon {
  /* Playing: two pause bars. */
  clip-path: polygon(0 0, 36% 0, 36% 100%, 0 100%, 0 0, 64% 0, 100% 0, 100% 100%, 64% 100%, 64% 0);
}

/* Without JS the loop never starts, so the control would be a lie. */
html:not(.js) .spk-media-toggle { display: none; }

/* ---------------------------------------------------------------------
   Pull-quote
   --------------------------------------------------------------------- */
.spk-quote {
  margin: clamp(2.5rem, 5vw, 4rem) 0 0;
  padding-left: clamp(1.1rem, 2.5vw, 1.9rem);
  border-left: 2px solid var(--blue);
  max-width: 46rem;
}

.spk-quote p {
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.6vw, 2rem);
  font-weight: 600;
  letter-spacing: -0.022em;
  color: var(--ink);
  text-wrap: balance;
  margin: 0 0 0.7rem;
}

.spk-quote cite {
  font-family: var(--font-display);
  font-size: var(--step-micro);
  font-style: normal;
  letter-spacing: 0.04em;
  color: var(--ink-3);
}

/* ---------------------------------------------------------------------
   Clips. 9:16 is very tall, so each video is a fixed-width column beside
   its caption rather than a full-width card, which would push a single
   clip past a thousand pixels of height on desktop.
   --------------------------------------------------------------------- */
.spk-clips {
  display: grid;
  gap: clamp(2.25rem, 4vw, 3.25rem);
  margin: 0;
}

.spk-clip {
  display: grid;
  grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
  gap: clamp(1.25rem, 3vw, 2.25rem);
  align-items: start;
  margin: 0;
  padding-top: clamp(2.25rem, 4vw, 3.25rem);
  border-top: 1px solid var(--line-soft);
}

.spk-clip:first-child { padding-top: 0; border-top: 0; }

.spk-clip-video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 9 / 16;
  background: var(--navy-950);
  /* Colours the fallback text a browser shows when it cannot play the clip.
     Without it that sentence inherits page ink and lands dark on dark. */
  color: var(--on-dark-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  /* The same machined sheen the interface captures carry elsewhere. */
  box-shadow: inset 0 1px 0 color-mix(in oklch, var(--on-dark) 7%, transparent);
}

.spk-clip figcaption h3 {
  font-size: var(--step-h3);
  margin: 0 0 0.6rem;
  text-wrap: balance;
}

.spk-clip figcaption p {
  color: var(--ink-2);
  max-width: 42ch;
  margin: 0 0 0.9rem;
}

.spk-clip-meta {
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--step-micro);
  letter-spacing: 0.05em;
  color: var(--ink-3);
}

/* ---------------------------------------------------------------------
   Credits. Deliberately a hairline list, not a logo wall: two real
   engagements do not make a wall, and the event's mark is theirs, not ours.
   --------------------------------------------------------------------- */
.spk-credits { list-style: none; margin: 0; padding: 0; }

.spk-credit {
  display: grid;
  grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
  gap: clamp(0.75rem, 3vw, 2.5rem);
  padding-block: clamp(1.5rem, 3vw, 2.25rem);
  border-top: 1px solid var(--line-soft);
}

.spk-credit:last-child { border-bottom: 1px solid var(--line-soft); }

.spk-credit-name h3 {
  font-size: var(--step-h3);
  margin: 0 0 0.3rem;
}

.spk-credit-name span {
  font-family: var(--font-display);
  font-size: var(--step-micro);
  letter-spacing: 0.04em;
  color: var(--ink-3);
}

.spk-credit-detail p { color: var(--ink-2); margin: 0; }

/* ---------------------------------------------------------------------
   Organiser bio
   --------------------------------------------------------------------- */
.spk-bio {
  display: grid;
  grid-template-columns: minmax(0, 17rem) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: start;
}

.spk-bio-photo {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border: 1px solid var(--line);
  border-radius: var(--r);
}

.spk-bio-copy h3 {
  font-size: var(--step-h3);
  margin: 0 0 0.6rem;
}

.spk-bio-copy p { color: var(--ink-2); }

.spk-bio-copy h3 ~ h3 { margin-top: 1.75rem; }

.spk-bio-copy .spec-list { margin-top: 0.4rem; }

.spk-bio-note {
  margin-top: 1.5rem;
  padding-top: 1.15rem;
  border-top: 1px solid var(--line-soft);
  font-size: var(--step-small);
  color: var(--ink-3);
}

/* ---------------------------------------------------------------------
   Desktop: stop overlaying the clip, put it beside the copy instead.
   --------------------------------------------------------------------- */
@media (min-width: 900px) {
  /* Cap the panel so an ultrawide monitor stops scaling the portrait clip
     up into an ever-thinner letterbox. Beyond this width the extra space
     is flat --navy-950, which is exactly what the scrim's first stop is,
     so the panel edge stays invisible. */
  .spk-hero-media { left: auto; width: 47%; max-width: 860px; }

  /* Nothing overlays him in the side-panel layout, so he can sit lower in
     the frame and show more of the stage. */
  .spk-hero-video { object-position: center 16%; }

  .spk-hero-scrim {
    background:
      linear-gradient(
        90deg,
        var(--navy-950) 0%,
        color-mix(in oklch, var(--navy-950) 78%, transparent) 30%,
        color-mix(in oklch, var(--navy-950) 38%, transparent) 68%,
        color-mix(in oklch, var(--navy-950) 24%, transparent) 100%
      ),
      linear-gradient(
        180deg,
        color-mix(in oklch, var(--navy-950) 55%, transparent) 0%,
        transparent 26%,
        transparent 74%,
        color-mix(in oklch, var(--navy-950) 55%, transparent) 100%
      );
  }

  .spk-hero-copy { max-width: 32rem; }
}

@media (max-width: 899px) {
  .spk-hero-copy { max-width: none; }
}

@media (max-width: 720px) {
  .spk-clip,
  .spk-credit,
  .spk-bio {
    grid-template-columns: minmax(0, 1fr);
  }
  .spk-clip-video { max-width: 18rem; }
  .spk-bio-photo { max-width: 15rem; }
}

@media (prefers-reduced-motion: reduce) {
  .spk-media-toggle { transition: none; }
}
