/* ═══════════════════════════════════════════════════════════════════════════
   ALPHA6 — ADVANCED VIDEO PRODUCTION  (light theme)
   1. Tokens          5. Timeline scrubber
   2. Reset & base    6. Captions & finale
   3. Nav & hero      7. Content sections
   4. Stage / monitor 8. Viewer, responsive, a11y
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─────────────────────────── 1. Tokens ─────────────────────────── */
:root {
  /* Dark, near-violet base — the page now matches the footage instead of
     framing it. Same ramp as the Game Development page. */
  --paper: #07070d;
  /* page base */
  --paper-2: #0c0c16;
  /* alternating sections and raised cards */
  --paper-3: #171826;
  /* tracks, wells and form inputs */
  --ink: #eef0f6;
  /* primary text */
  --ink-soft: #9096ab;
  /* muted text */
  --stage: #0b0d11;
  /* the monitor interior; must stay matched to the canvas clear in script.js */
  --accent: #7c5cff;
  /* violet — the through-line of the gradient headlines */
  --accent-2: #17c9b8;
  /* teal, lifted from #00b3a4 so it still reads against near-black */
  /* Hairlines are light-on-dark now; a dark rule is invisible here. */
  --line: rgba(238, 240, 246, 0.16);
  --line-soft: rgba(238, 240, 246, 0.08);

  /* Headline gradient — deep royal blue into violet. Defined once here so
     every gradient headline on the page stays in step. */
  --grad: linear-gradient(100deg, #195fc7 0%, #4a5fbe 45%, #7a6fd0 100%);

  --display: "Century Gothic", "CenturyGothic", "URW Gothic", "Poppins",
    "Avant Garde", "Futura", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --gut: clamp(1.25rem, 4vw, 4rem);
  --nav-h: 4.5rem;
}

/* ─────────────────────────── 2. Reset & base ─────────────────────────── */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  /* Native anchor offset, so a hard link (page.html#contact) also lands right */
  scroll-padding-top: calc(var(--nav-h) + 1rem);
  /* `clip` rather than `hidden`: hidden turns the element into a scroll
     container, which breaks position:sticky inside it and fights Lenis. clip
     just crops the overflow. Backstop only — real overflow is fixed at source
     (see the min-width:0 rules on the contact form). */
  overflow-x: clip;
}

body {
  margin: 0;
  background: var(--paper);
  /* Lifted from 0.08: the wash that tinted a paper background is barely
     perceptible over near-black. */
  background-image:
    radial-gradient(ellipse at 12% 8%, rgba(124, 92, 255, 0.16) 0%, transparent 45%),
    radial-gradient(ellipse at 88% 62%, rgba(23, 201, 184, 0.12) 0%, transparent 45%);
  background-attachment: fixed;
  color: var(--ink);
  font-family: var(--display);
  font-size: clamp(0.95rem, 0.9rem + 0.25vw, 1.05rem);
  line-height: 1.6;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
}

html.lenis,
html.lenis body {
  height: auto;
}

.lenis.lenis-smooth {
  scroll-behavior: auto !important;
}

/* Interim guard while the overflow source is confirmed. `main` is the only
   normal-flow wrapper, so clipping here catches anything in the document flow
   without affecting the fixed-position nav, loader or viewer overlay. */
main {
  overflow-x: clip;
  max-width: 100%;
}

/* Belt and braces for browsers predating overflow:clip (iOS < 16). Applied to
   the sections rather than a scroll container so position:sticky still works. */
.section,
.contact-layout,
.foot-new,
.foot-grid,
.role-cards,
.cta-banner {
  max-width: 100%;
}

.is-locked,
.is-locked body {
  overflow: hidden;
}

h1,
h2,
h3 {
  margin: 0;
  font-weight: 700;
}

p,
ul {
  margin: 0;
}

ul {
  padding: 0;
  list-style: none;
}

a {
  color: inherit;
}

svg {
  width: 1em;
  height: 1em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.mono {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.rule {
  display: inline-block;
  width: 1.75rem;
  height: 1px;
  margin-right: 0.75rem;
  vertical-align: 0.2em;
  background: var(--accent);
}

/* Reusable gradient text. background-clip paints the glyphs, so the fill has
   to be transparent — and any flat text-shadow would land on top of the
   clipped gradient and smear it, which is why the separation is a
   drop-shadow filter instead (see .caption__title span below). */
.grad-text {
  background-image: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

/* ─── Buttons ─── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.85rem 1.6rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.45s var(--ease), border-color 0.45s var(--ease), color 0.45s var(--ease);
}

.btn svg {
  width: 0.85em;
  height: 0.85em;
  transition: transform 0.45s var(--ease);
}

.btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  font-weight: 600;
}

.btn--primary:hover {
  background: #9377ff;
  border-color: #9377ff;
}

.btn--ghost:hover {
  border-color: var(--ink);
}

.btn--full {
  width: 100%;
  margin-top: 1.5rem;
}

.btn--sm {
  padding: 0.6rem 1.15rem;
  font-size: 0.8125rem;
}

.btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

#exploreBtn:hover svg {
  transform: translateY(2px);
}

/* ─────────────────────────── Preloader ─────────────────────────── */
.loader {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  background: var(--paper);
  transition: opacity 0.9s var(--ease), visibility 0.9s;
}

.loader.is-done {
  opacity: 0;
  visibility: hidden;
}

.loader__inner {
  width: min(20rem, 70vw);
  text-align: center;
}

.loader__label {
  margin-bottom: 1.25rem;
}

.loader__bar {
  height: 2px;
  background: var(--paper-3);
  overflow: hidden;
  border-radius: 2px;
}

.loader__fill {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--accent);
  transition: width 0.35s linear;
}

.loader__count {
  margin-top: 1rem;
  color: var(--ink);
}

.loader__error {
  max-width: 26rem;
  margin: 1.25rem auto 0;
  color: var(--accent);
  font-size: 0.625rem;
  line-height: 1.7;
  text-transform: none;
  letter-spacing: 0.06em;
  word-break: break-all;
}

.protocol-note {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 120;
  padding: 1rem var(--gut);
  background: var(--accent);
  color: #fff;
  text-align: center;
}

.protocol-note .mono {
  color: rgba(255, 255, 255, 0.85);
}

/* ─────────────────────────── 3. Nav & hero ─────────────────────────── */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  width: 100%;
  height: var(--nav-h);
  padding: 0 var(--gut);
  background: rgba(7, 7, 13, 0.9);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line-soft);
}

.nav__mark {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-decoration: none;
}

.nav__logo-img {
  width: auto;
  height: 4rem;
  object-fit: contain;
  display: block;
  flex: none;
}

/* Absolutely centred on the viewport rather than flexed into the middle: the
   logo and the CTA are different widths, so any flow-based centring puts the
   links off-centre by half that difference. Taken out of flow, the two
   flanking items still space-between correctly around them. */
.nav__links {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 1.6rem;
}

.nav__links a {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  text-decoration: none;
  transition: color 0.35s var(--ease);
}

.nav__links a:hover {
  color: var(--ink);
}

/* Out of flow, the strip can no longer push the logo and CTA apart — it has
   to shrink before it reaches either of them. */
@media (max-width: 1200px) {
  .nav__links {
    gap: 1.1rem;
  }

  .nav__links a {
    font-size: 0.625rem;
  }
}

@media (max-width: 980px) {
  .nav__links {
    gap: 0.85rem;
  }

  .nav__links a {
    font-size: 0.5625rem;
    letter-spacing: 0.1em;
  }
}

/* The Book-a-seat CTA. Stated explicitly so it can never be collapsed by an
   inherited rule. The links are now absolutely positioned, so space-between
   puts the logo left and this right on its own. */
.nav__cta {
  display: inline-flex;
  flex: none;
  margin-left: auto;
  white-space: nowrap;
  /* Colour comes from `.btn--primary` above — every filled button shares the
     violet accent, so there is one place to change the action colour. */
}

.hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 100svh;
  padding: calc(var(--nav-h) + 2rem) var(--gut) 5rem;
}

.hero__inner {
  width: min(74rem, 100%);
}

.hero__eyebrow {
  margin-bottom: clamp(1.25rem, 3.5vh, 2.5rem);
}

.hero__title {
  font-size: clamp(2.6rem, 9.5vw, 8.5rem);
  font-weight: 700;
  line-height: 0.92;
  letter-spacing: -0.035em;
}

.hero__line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.04em;
}

.hero__line>span {
  display: block;
}

.hero__line:nth-child(3)>span {
  color: var(--accent);
}

.hero__sub {
  max-width: 34rem;
  margin-top: clamp(1.25rem, 3.5vh, 2.25rem);
  color: var(--ink-soft);
  font-size: clamp(1rem, 0.95rem + 0.4vw, 1.2rem);
  font-weight: 300;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: clamp(1.5rem, 4vh, 2.5rem);
}

.hero__stats {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.5rem, 5vw, 3.5rem);
  margin-top: clamp(2rem, 6vh, 3.5rem);
  padding-top: 1.75rem;
  border-top: 1px solid var(--line-soft);
}

.hero__stats b {
  display: block;
  font-size: clamp(1.25rem, 2.2vw, 1.75rem);
  font-weight: 600;
}

.hero__stats span {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.625rem;
}

.hero__scroll {
  position: absolute;
  right: var(--gut);
  bottom: 2rem;
  font-size: 0.625rem;
  writing-mode: vertical-rl;
}

.hero__scroll::after {
  content: "";
  display: block;
  width: 1px;
  height: 2.5rem;
  margin: 0.75rem auto 0;
  background: linear-gradient(var(--ink-soft), transparent);
}

/* ─────────────────────────── 4. Stage / monitor ─────────────────────────── */
/* The pinned pane is the only thing covering the viewport while the frames
   scrub, so any strip it fails to cover exposes the page behind it — on this
   theme that is the body's violet/teal radial wash, which reads as a coloured
   band under the footage. */
.sequence {
  position: relative;
  height: 950svh;
  background: var(--stage);
}

/* `svh` is the SMALLEST viewport height — the height with the mobile URL bar
   showing. The moment that bar retracts the visible area grows past 100svh
   and a gap opens along the bottom. `dvh` tracks the live height, so the
   sticky pane always fills the screen; the `svh` line above it stays as the
   fallback for engines without `dvh`, and the two are identical on desktop
   where there is no retracting chrome. */
.sequence__sticky {
  position: sticky;
  top: 0;
  height: 100svh;
  height: 100dvh;
  overflow: hidden;
  background: var(--stage);
}

/* Full-bleed: the footage owns the whole viewport while the section is
   pinned, and the light page resumes underneath it. */
.stage {
  position: absolute;
  inset: 0;
}

.stage__monitor {
  position: absolute;
  inset: 0;
}

.frames {
  display: block;
  width: 100%;
  height: 100%;
}

/* Scrim only where copy sits, so text stays legible without dulling the shot */
.stage__gloss {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(11, 13, 17, 0.55) 0%, transparent 18%),
    linear-gradient(to top, rgba(11, 13, 17, 0.85) 0%, rgba(11, 13, 17, 0.35) 26%, transparent 48%);
}

/* ─── HUD framing guides ─── */
.hud {
  position: absolute;
  inset: calc(var(--nav-h) * 0.9) var(--gut) 2rem;
  pointer-events: none;
  opacity: 0;
}

.hud__bracket {
  position: absolute;
  width: 20px;
  height: 20px;
  border: 1px solid rgba(255, 255, 255, 0.26);
}

.hud__bracket--tl {
  top: 0;
  left: 0;
  border-right: 0;
  border-bottom: 0;
}

.hud__bracket--tr {
  top: 0;
  right: 0;
  border-left: 0;
  border-bottom: 0;
}

.hud__bracket--bl {
  bottom: 0;
  left: 0;
  border-right: 0;
  border-top: 0;
}

.hud__bracket--br {
  bottom: 0;
  right: 0;
  border-left: 0;
  border-top: 0;
}

.hud__thirds {
  position: absolute;
  inset: 0;
  opacity: 0.3;
}

.hud__thirds span {
  position: absolute;
  background: rgba(255, 255, 255, 0.3);
}

.hud__thirds span:nth-child(1) {
  left: 33.33%;
  top: 0;
  width: 1px;
  height: 100%;
}

.hud__thirds span:nth-child(2) {
  left: 66.66%;
  top: 0;
  width: 1px;
  height: 100%;
}

.hud__thirds span:nth-child(3) {
  top: 33.33%;
  left: 0;
  height: 1px;
  width: 100%;
}

.hud__thirds span:nth-child(4) {
  top: 66.66%;
  left: 0;
  height: 1px;
  width: 100%;
}

/* ─────────────────────────── 5. Timeline scrubber ─────────────────────────── */
/* Overlaid on the footage like a player scrubber. The scroll position IS the
   playhead, which is the craft this course teaches. */
.timeline {
  position: absolute;
  left: var(--gut);
  right: var(--gut);
  bottom: 1.4rem;
  pointer-events: none;
}

.timeline__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.5rem;
}

.timeline__meta p {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.625rem;
  color: rgba(242, 245, 247, 0.6);
}

.timeline__meta b {
  color: #f2f5f7;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.timeline__meta em {
  font-style: normal;
  opacity: 0.6;
}

.timeline__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
  background: var(--accent);
  animation: rec 1.6s ease-in-out infinite;
}

@keyframes rec {

  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.25;
  }
}

.timeline__tracks {
  position: relative;
  padding: 0.4rem;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 0.4rem;
  background: rgba(11, 13, 17, 0.55);
  backdrop-filter: blur(8px);
}

.timeline__row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.timeline__row+.timeline__row {
  margin-top: 0.3rem;
}

.timeline__label {
  flex: none;
  width: 1.5rem;
  font-size: 0.5625rem;
  color: rgba(242, 245, 247, 0.45);
}

.timeline__track {
  position: relative;
  flex: 1;
  height: 1.25rem;
  border-radius: 0.2rem;
  background: rgba(255, 255, 255, 0.07);
  overflow: hidden;
}

.timeline__clip {
  position: absolute;
  top: 0;
  height: 100%;
  display: flex;
  align-items: center;
  padding: 0 0.5rem;
  border-radius: 0.2rem;
  background: rgba(124, 92, 255, 0.28);
  box-shadow: inset 0 0 0 1px rgba(124, 92, 255, 0.5);
  font-family: var(--mono);
  font-size: 0.5rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #cdc0ff;
  white-space: nowrap;
  overflow: hidden;
}

.timeline__progress {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 0%;
  background: rgba(255, 255, 255, 0.16);
}

.timeline__track--audio {
  height: 0.85rem;
}

.timeline__wave {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(90deg,
      transparent 0 2px, rgba(242, 245, 247, 0.3) 2px 3px,
      transparent 3px 5px, rgba(242, 245, 247, 0.16) 5px 6px);
  mask-image: linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent);
}

.timeline__playhead {
  position: absolute;
  top: 0.3rem;
  bottom: 0.3rem;
  left: calc(2.5rem + (100% - 3rem) * var(--p, 0));
  width: 2px;
  background: var(--accent);
  border-radius: 2px;
}

.timeline__playhead::before {
  content: "";
  position: absolute;
  top: -3px;
  left: 50%;
  width: 9px;
  height: 9px;
  transform: translateX(-50%) rotate(45deg);
  background: var(--accent);
  border-radius: 1px;
}

/* ─────────────────────────── 6. Captions & finale ─────────────────────────── */
.captions {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.caption {
  position: absolute;
  /* Sits well clear of the timeline scrubber at the bottom of the monitor.
     Raised from 6-9rem so the headline never collides with the footage's own
     on-screen text. */
  bottom: clamp(9rem, 24vh, 14rem);
  /* Wide enough to carry the longest single line ("FROM BEGINNER", ~9.4em in
     this face) at the type sizes below. The headline deliberately runs wider
     than the body copy underneath it. */
  width: min(70rem, 62vw);
  opacity: 0;
  color: #f2f5f7;
}

.caption--left {
  left: var(--gut);
}

.caption--right {
  right: var(--gut);
  text-align: right;
}

.caption__eyebrow {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.7rem;
  color: #b8a4ff;
}

.caption__eyebrow::before {
  content: "";
  width: 0.9rem;
  height: 1px;
  background: var(--accent);
}

.caption--right .caption__eyebrow {
  flex-direction: row-reverse;
}

.caption__title {
  /* Caps + heavy weight + tight leading: the headline reads as a title card
     rather than body copy sitting on the footage.
     The 6vw slope is the binding constraint, not the 7rem ceiling — at 62vw
     of box and ~9.4em for the longest line, anything steeper overflows on
     mid-size laptops (1440px) before the ceiling ever engages. */
  font-size: clamp(3rem, 6vw, 7rem);
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  /* Three stacked shadows instead of a scrim box: a tight dark halo hugging
     the glyph edges, then two progressively wider soft ones. This separates
     the type from busy footage without drawing a visible rectangle. */
  text-shadow:
    0 1px 3px rgba(0, 0, 0, 0.95),
    0 4px 18px rgba(0, 0, 0, 0.85),
    0 8px 46px rgba(0, 0, 0, 0.7);
  /* Last-resort guard: never let a word bleed off the monitor edge. */
  overflow-wrap: break-word;
}

/* The coloured spans inside a headline use -webkit-background-clip:text with a
   transparent fill. Paint order is background → text-shadow → glyphs, so a
   text-shadow lands on top of the clipped gradient and replaces it with a dark
   smear. drop-shadow works off the rendered alpha instead, so the gradient
   shows through and still gets separation from the footage. */
.caption__title span {
  text-shadow: none;
  filter:
    drop-shadow(0 1px 3px rgba(0, 0, 0, 0.95)) drop-shadow(0 4px 18px rgba(0, 0, 0, 0.8));
}

.caption__body {
  margin-top: 1.1rem;
  /* The box is now sized for the headline; hold the body copy to a readable
     measure rather than letting it run the full 70rem. */
  max-width: 34rem;
  color: rgba(242, 245, 247, 0.75);
  font-size: clamp(1rem, 1.2vw, 1.25rem);
  font-weight: 300;
  line-height: 1.55;
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.95),
    0 2px 12px rgba(0, 0, 0, 0.9),
    0 4px 30px rgba(0, 0, 0, 0.75);
}

.caption--right .caption__body {
  margin-left: auto;
}

.finale {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(1.5rem, 4vh, 2.5rem);
  padding: var(--gut);
  text-align: center;
  opacity: 0;
  pointer-events: none;
  color: #f2f5f7;
  background: radial-gradient(70% 60% at 50% 50%, rgba(11, 13, 17, 0.86), rgba(11, 13, 17, 0.55) 70%, rgba(11, 13, 17, 0.25));
}

.finale.is-live {
  pointer-events: auto;
}

.finale__title {
  font-size: clamp(2rem, 6.5vw, 5.5rem);
  font-weight: 700;
  line-height: 0.98;
  letter-spacing: -0.035em;
}

.finale__line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.04em;
}

.finale__line>span {
  display: block;
}

/* .finale__line:nth-child(3)>span {
  color: #ff8a5c; Removed so "Your" stays white
} */

.finale__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: center;
}

.finale .btn--ghost {
  color: #f2f5f7;
  border-color: rgba(255, 255, 255, 0.25);
}

.finale .btn--ghost:hover {
  border-color: #f2f5f7;
}

/* ─────────────────────────── 7. Content sections ─────────────────────────── */
/* NOTE: `content-visibility: auto` + `contain-intrinsic-size: auto 60rem` were
   removed here. They told the browser to skip layout for off-screen sections
   and substitute a 60rem placeholder height, so the document position of
   #contact resolved badly wrong on a fresh page load — the anchor landed in
   the wrong place on the first click and only corrected on the second, once
   the browser had actually laid those sections out and cached real sizes. */
.section {
  padding: clamp(4.5rem, 12vh, 9rem) var(--gut);
  /* Anchor offset so the fixed nav never covers a section heading */
  scroll-margin-top: calc(var(--nav-h) + 1rem);
}

.section--alt {
  background: var(--paper-2);
}

/* Every section heading shares the same 70rem content column the card grids
   below it use, so heading, lede, cards and chips all hang off one left edge.
   Stated once here rather than per-section id, so no section can be missed —
   `.section` itself keeps its full-bleed width because `.section--alt` paints
   a background stripe that has to run edge to edge. */
.section>.section__head {
  max-width: 70rem;
  margin-inline: auto;
  margin-bottom: clamp(2.5rem, 7vh, 4.5rem);
}

/* The head box is 70rem now, so hold its own copy to a readable measure
   rather than letting the lede run the full width. */
.section>.section__head>* {
  max-width: 48rem;
}

/* Kept for any head outside a .section wrapper. */
.section__head {
  max-width: 48rem;
  margin-bottom: clamp(2.5rem, 7vh, 4.5rem);
}

/* Eyebrow runs teal — label and rule together. `.rule` reads `--accent`
   (violet) by default, so both need stating. The live-projects card sets its
   own eyebrow colour inline and still overrides this. */
.section__eyebrow {
  margin-bottom: 1.25rem;
  color: var(--accent-2);
}

.section__eyebrow .rule {
  background: var(--accent-2);
}

.section__title {
  font-size: clamp(1.75rem, 4.2vw, 3.25rem);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.03em;
}

.section__lede {
  margin-top: 1.25rem;
  color: var(--ink-soft);
  font-weight: 300;
}

.ticks {
  display: grid;
  gap: 0.55rem;
}

.ticks li {
  position: relative;
  padding-left: 1.35rem;
  color: var(--ink-soft);
  font-size: 0.875rem;
  font-weight: 300;
  line-height: 1.5;
}

.ticks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 0.35rem;
  height: 0.35rem;
  border-radius: 50%;
  background: var(--accent-2);
}

/* ─── Marquee ─── */
.marquee {
  width: 100%;
  overflow: hidden;
  background: var(--paper-2);
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  padding: 1rem 0;
}

.marquee__track {
  display: flex;
  width: max-content;
}

.marquee__group {
  display: flex;
  align-items: center;
  gap: 2rem;
  padding-right: 2rem;
  animation: scroll 20s linear infinite;
  font-family: var(--display);
  font-weight: 600;
  font-size: 1rem;
  color: var(--ink-soft);
}

.marquee__dot {
  width: 4px;
  height: 4px;
  background: var(--accent);
  border-radius: 50%;
  flex-shrink: 0;
}

@keyframes scroll {
  0% {
    transform: translateX(0);
  }

  100% {
    transform: translateX(-100%);
  }
}

/* ─── Journey ─── */
#journey {
  padding-top: clamp(2rem, 5vh, 4rem);
}

/* Same 70rem container as #skills and #tariff. Full-bleed, the three cards run
   ~575px each on a 1920 screen — the tick lists never wrap and the numerals
   sit marooned in empty space. */
.stages {
  max-width: 70rem;
  margin-inline: auto;
}

#journey .section__lede {
  max-width: 34rem;
}

/* No `align-items: start`: start-aligned, each card shrinks to its own content
   and the three end at different heights because the tick lists differ in
   length. The grid default of `stretch` squares them off. */
.stages {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1.5rem;
}

/* A drop shadow separates a white card from a paper page; over near-black it
   is invisible. Every raised surface takes a hairline border instead — which
   also means recolouring that border on hover cannot change the card's box
   size and nudge its row-mates. */
.stage-card {
  padding: 1.5rem;
  border: 1px solid var(--line-soft);
  border-radius: 1rem;
  background: var(--paper-2);
  transition: transform 0.4s var(--ease), border-color 0.4s var(--ease),
    background 0.4s var(--ease);
}

.stage-card:hover {
  transform: translateY(-4px);
  border-color: var(--accent-2);
  background: var(--paper-3);
}

.stage-card__n {
  font-size: 3rem;
  font-weight: 800;
  line-height: 1;
  color: var(--accent);
  letter-spacing: -0.05em;
  font-family: var(--display);
}

.stage-card__tag {
  margin-top: 1.1rem;
  color: var(--accent-2);
  font-weight: 600;
}

/* Was 1.25rem below the title — sitting the list right under it makes the
   heading read as a label for the ticks rather than a separate block. */
.stage-card__title {
  margin: 0.35rem 0 0.7rem;
  font-size: 1.25rem;
  letter-spacing: -0.02em;
}

/* ─── Verticals ─── */
.verticals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1.25rem;
}

.verticals li {
  padding: clamp(1.5rem, 3vw, 2rem);
  background: var(--paper-2);
  border: 1px solid var(--line-soft);
  border-radius: 1rem;
  display: flex;
  flex-direction: column;
  transition: transform 0.4s var(--ease), background 0.4s var(--ease), border-color 0.4s var(--ease);
}

.verticals li:hover {
  transform: translateY(-4px);
  background: var(--paper-3);
  border-color: var(--line);
}

.verticals__icon {
  width: 2.75rem;
  height: 2.75rem;
  background: rgba(124, 92, 255, 0.14);
  border-radius: 0.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.25rem;
  margin-bottom: 1.25rem;
}

.verticals h3 {
  font-size: 1.0625rem;
  letter-spacing: -0.01em;
}

.verticals p {
  margin-top: 0.5rem;
  color: var(--ink-soft);
  font-size: 0.875rem;
  font-weight: 300;
}

.chips {
  margin-top: 2.5rem;
  max-width: 70rem;
  margin-inline: auto;
}

/* Matches the section eyebrows — teal, with the same leading rule. Drawn as a
   pseudo-element so no `<span class="rule">` is needed in the markup. */
.chips__label {
  margin-bottom: 0.9rem;
  color: var(--accent-2);
}

.chips__label::before {
  content: "";
  display: inline-block;
  width: 1.75rem;
  height: 1px;
  margin-right: 0.75rem;
  vertical-align: 0.2em;
  background: var(--accent-2);
}

.chips ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.chips li {
  padding: 0.4rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.8125rem;
  font-weight: 300;
}

/* ─── Why / technical ─── */
/* The reference page runs this section inside a ~70rem centred container.
   Left full-bleed, each column is ~870px on a 1920 screen — wide enough that
   the body copy never wraps, so the divider lines run on into empty space to
   the right of the text. Scoped to #skills so no other section moves. */
#skills .skills-layout {
  max-width: 70rem;
  margin-inline: auto;
}

/* `align-items: start` is load-bearing for the sticky panel below: a stretched
   grid item is as tall as its row, and a sticky element that already fills its
   container has nowhere to travel. Start-aligned, the card is only as tall as
   its own content. (This was `center` before.) */
/* The gutter was clamp(2rem, 5vw, 4rem) — 64px on a desktop, which left the
   dead channel between the divider lines and the card. Tightened so the lines
   run up close to the card edge the way the reference page does. */
.skills-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.5rem, 3vw, 2.75rem);
  align-items: start;
}

/* The confidence panel holds while the discipline list scrolls past it, so
   both halves of the argument stay on screen together. Travel comes from the
   list being the taller column — six rows against one card. */
.skills-layout>.bars {
  position: sticky;
  top: calc(var(--nav-h) + 1.5rem);
}

@media (max-width: 860px) {
  .skills-layout {
    grid-template-columns: 1fr;
  }

  /* Stacked, there is no second column to scroll against — a pinned card
     would just hover over the list it is meant to sit beside. */
  .skills-layout>.bars {
    position: static;
  }
}

/* Rows carry their own vertical padding, so a grid gap here would double up
   the spacing between the divider and the next number. */
.why {
  display: grid;
  gap: 0;
}

.why li {
  display: flex;
  gap: clamp(1.25rem, 2vw, 2rem);
  align-items: flex-start;
  padding: 1.25rem 0;
  border-bottom: 1px solid var(--line-soft);
}

.why li:first-child {
  padding-top: 0;
}

.why li:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

/* Fixed width keeps every heading on the same left edge, whatever the number.
   Display face rather than the inherited `mono`, to match the reference. */
.why__n {
  flex: none;
  width: 1.5rem;
  font-family: var(--display);
  font-size: 0.875rem;
  letter-spacing: 0;
  color: var(--accent-2);
  font-weight: 700;
  margin-bottom: 0;
  padding-top: 0.3rem;
}

.why h3 {
  font-size: 1.125rem;
  letter-spacing: -0.01em;
}

.why li>div>p:last-child {
  margin-top: 0.4rem;
  color: var(--ink-soft);
  font-size: 0.875rem;
  font-weight: 300;
  line-height: 1.5;
}

/* ─── Skill bars ─── */
/* `position: relative` + a stacking context: as the sticky card travels it
   passes over content below it, and without this it can render underneath. */
/* Kept deliberately compact: the card is the shorter column, and the height
   it doesn't use is the travel the sticky panel gets while the list on the
   left scrolls past it. A taller card = less travel. */
.bars {
  position: relative;
  z-index: 1;
  background: var(--paper-2);
  border: 1px solid var(--line-soft);
  padding: clamp(1.5rem, 3vw, 2.125rem);
  border-radius: 1.5rem;
}

.bars__title {
  font-size: 1.5rem;
  font-weight: 800;
  letter-spacing: -0.02em;
}

/* Also overrides `mono`: the reference runs this as a plain sentence-case
   line, not a spaced uppercase eyebrow. */
.bars__sub {
  margin: 0.4rem 0 1.5rem;
  font-family: var(--display);
  font-size: 0.9375rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
}

.bars ul {
  display: grid;
  gap: 0.875rem;
}

/* Label and value share the top line; the track spans the full width beneath
   them. Placement is explicit rather than automatic: in the markup the track
   sits BETWEEN the label and the value, and because it spans 1/-1 it opens a
   new row — auto-placement then drops the percentage onto a third line under
   the bar. Pinning all three to a row/column fixes the order regardless of
   source order. */
.bars li {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 0 1rem;
}

.bars__k {
  grid-column: 1;
  grid-row: 1;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--ink);
}

/* Overrides the `mono` class on this element: the reference sets the figure in
   the display face, not the uppercase mono used for eyebrows. */
.bars__v {
  grid-column: 2;
  grid-row: 1;
  font-family: var(--display);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  text-transform: none;
  color: var(--accent-2);
  font-weight: 700;
  font-size: 0.875rem;
}

.bars__track {
  grid-column: 1 / -1;
  grid-row: 2;
  margin-top: 0.5rem;
  height: 5px;
  border-radius: 6px;
  background: var(--paper-3);
  overflow: hidden;
}

.bars__track i {
  display: block;
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  border-radius: 6px;
}

/* ─── Live projects ─── */
.live-card {
  background: linear-gradient(135deg, #4a2f9e, #00b3a4);
  color: #fff;
  border-radius: 1.5rem;
  padding: clamp(2.5rem, 6vw, 4.5rem);
  box-shadow: 0 20px 50px rgba(0, 179, 164, 0.15);
  max-width: 58rem;
  margin: 0 auto;
}

.clients {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-content: center;
}

.clients li {
  padding: 0.5rem 1rem;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.15);
  font-size: 0.8125rem;
  font-weight: 500;
  color: #fff;
  backdrop-filter: blur(4px);
}

/* ─── Why Alpha6 Cards ─── */
.why-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  gap: 1.5rem;
}

.why-cards li {
  padding: clamp(1.5rem, 3vw, 2.25rem);
  background: var(--paper-2);
  border: 1px solid var(--line-soft);
  border-radius: 1.25rem;
}

.why-cards h3 {
  font-size: 1.125rem;
  margin: 0.5rem 0;
  letter-spacing: -0.01em;
}

.why-cards p {
  color: var(--ink-soft);
  font-size: 0.875rem;
  font-weight: 300;
}

/* ─── Levels ─── */
/* Same 70rem container as the skills section: full-bleed, the three cards run
   ~575px each on a 1920 screen, which is what made the headers and chips read
   oversized rather than any one type size being wrong. */
.levels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: 1.5rem;
  align-items: stretch;
  max-width: 70rem;
  margin-inline: auto;
  margin-top: 3.5rem;
}

#tariff .section__head {
  max-width: 44rem;
}

.level {
  display: flex;
  flex-direction: column;
  border-radius: 1rem;
  background: var(--paper-2);
  border: 1px solid var(--line-soft);
  overflow: hidden;
}

.level--featured {
  box-shadow: 0 20px 50px -20px rgba(123, 92, 240, 0.35);
}

/* `relative` anchors the Most-popular badge; `overflow: hidden` crops the
   pinwheel so it reads as a corner motif rather than a floating circle. */
.level__head {
  position: relative;
  overflow: hidden;
  padding: 1.5rem;
  color: #fff;
}

/* The rotating motif. A repeating conic gradient gives the radiating blades;
   the radial mask punches out the hub so it reads as a pinwheel rather than a
   filled pie. Rotation is a compositor-only transform, so six of these on
   screen cost nothing. */
.level__head::after {
  content: "";
  position: absolute;
  top: -3rem;
  right: -3rem;
  width: 11rem;
  height: 11rem;
  border-radius: 50%;
  background: repeating-conic-gradient(from 0deg,
      rgba(255, 255, 255, 0.16) 0deg 15deg,
      rgba(255, 255, 255, 0) 15deg 30deg);
  -webkit-mask-image: radial-gradient(circle, transparent 24%, #000 25%);
  mask-image: radial-gradient(circle, transparent 24%, #000 25%);
  animation: level-spin 34s linear infinite;
  pointer-events: none;
}

@keyframes level-spin {
  to {
    transform: rotate(360deg);
  }
}

.level__head--1 {
  background: linear-gradient(145deg, #00b3a4, #008c80);
}

.level__head--2 {
  background: linear-gradient(145deg, #7b5cf0, #4a2f9e);
}

.level__head--3 {
  background: linear-gradient(145deg, #3273dc, #1d4d8a);
}

/* The numeral carries the level, so the pill background comes off and the `b`
   in the markup is promoted to display size. `relative` + z-index keeps the
   line above the rotating motif behind it. */
.level__tag {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  margin-bottom: 0.35rem;
  padding: 0;
  background: none;
  border-radius: 0;
  font-family: var(--display);
  font-size: 0.8125rem;
  letter-spacing: 0.12em;
  color: rgba(255, 255, 255, 0.9);
}

.level__tag b {
  font-size: 2rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
  color: #fff;
}

/* Out of the tag line and pinned to the corner, so a long card name can never
   push it around. */
.level__badge {
  position: absolute;
  top: 1.1rem;
  right: 1.1rem;
  margin-left: 0;
  padding: 0.3rem 0.7rem;
  background: var(--accent-2);
  border-radius: 999px;
  color: #fff;
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  white-space: nowrap;
}

.level__name {
  position: relative;
  z-index: 1;
  font-size: 1.25rem;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: #fff;
}

.level__sub {
  position: relative;
  z-index: 1;
  margin-top: 0.25rem;
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  color: rgba(255, 255, 255, 0.85);
}

.level__price {
  position: relative;
  z-index: 1;
  margin-top: 1.25rem;
  font-size: 1.625rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: #fff;
}

/* Overrides the `mono` class: the reference sets the duration as plain
   sentence-case text, not a spaced uppercase eyebrow. */
.level__price span {
  font-family: var(--display);
  font-size: 0.8125rem;
  letter-spacing: 0;
  text-transform: none;
  color: rgba(255, 255, 255, 0.75);
  font-weight: 400;
}

.level__body {
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  flex: 1;
}

.module+.module {
  margin-top: 1.25rem;
}

/* Module headings take the card's own accent instead of flat ink — it's what
   separates the groups at a glance now that the chips are quieter. */
.module__h {
  margin-bottom: 0.6rem;
  font-family: var(--display);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--accent-2);
}

.level--featured .module__h {
  color: #a78bff;
}

.module-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.module-chips li {
  padding: 0.3rem 0.65rem;
  background: rgba(238, 240, 246, 0.04);
  border: 1px solid var(--line-soft);
  border-radius: 0.4rem;
  font-size: 0.8125rem;
  color: var(--ink-soft);
}

.level__outcome {
  margin-top: 1.5rem;
  margin-bottom: 1.25rem;
  padding: 1rem;
  background: rgba(238, 240, 246, 0.03);
  border: 1px dashed var(--line);
  border-radius: 0.75rem;
  font-size: 0.8125rem;
  color: var(--ink-soft);
  line-height: 1.6;
}

.level__outcome b {
  color: var(--ink);
}

.level__body .btn {
  margin-top: auto;
}

.levels__note {
  margin-top: 2rem;
  text-transform: none;
  letter-spacing: 0.06em;
  line-height: 1.8;
}

.outcomes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: 1.25rem;
  margin-top: clamp(2.5rem, 6vh, 4rem);
}

.outcomes li {
  padding: 1.5rem;
  border-top: 2px solid var(--accent);
}

.outcomes h3 {
  font-size: 1.0625rem;
  letter-spacing: -0.01em;
}

.outcomes p {
  margin-top: 0.4rem;
}

/* ─── CTA & footer ─── */
.cta {
  text-align: center;
}

.cta__title {
  margin-top: 1.25rem;
  font-size: clamp(2rem, 5.5vw, 4rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.035em;
}

.cta__lede {
  max-width: 38rem;
  margin: 1.25rem auto 0;
  color: var(--ink-soft);
  font-weight: 300;
}

.cta__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: center;
  margin-top: 2rem;
}

.cta__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 2rem;
  max-width: 60rem;
  margin: clamp(3rem, 8vh, 5rem) auto 0;
  padding-top: 2.5rem;
  border-top: 1px solid var(--line-soft);
  text-align: left;
}

.cta__k {
  margin-bottom: 0.5rem;
}

.cta__v {
  font-size: 0.9375rem;
  font-weight: 300;
  line-height: 1.6;
}

.cta__v a {
  color: var(--accent);
  text-decoration: none;
}

.foot {
  padding: clamp(3rem, 8vh, 4.5rem) var(--gut) 2.5rem;
  background: var(--paper-2);
  border-top: 1px solid var(--line-soft);
}

.foot__top {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  gap: 2rem;
  padding-bottom: 2.5rem;
}

.foot__blurb {
  max-width: 30rem;
  color: var(--ink-soft);
  font-weight: 300;
}

.foot__blurb a {
  color: var(--accent);
  text-decoration: none;
}

.foot__nav {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  align-content: start;
}

.foot__nav a {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  text-decoration: none;
}

.foot__nav a:hover {
  color: var(--ink);
}

.foot__note {
  padding-top: 2rem;
  border-top: 1px solid var(--line-soft);
  font-size: 0.625rem;
}

/* ─────────────────────────── 8. Viewer ─────────────────────────── */
/* The 3D stage stays dark — a lit studio is how you actually inspect a camera. */
.viewer {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--stage);
  color: #f2f5f7;
  opacity: 0;
}

.viewer__stage {
  position: absolute;
  inset: 0;
}

.viewer__stage canvas {
  display: block;
  touch-action: none;
}

.viewer__ui {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 1.5rem var(--gut);
  pointer-events: none;
}

.viewer__top,
.viewer__bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.viewer__bottom {
  align-items: flex-end;
}

.viewer__ui .btn {
  pointer-events: auto;
  color: #f2f5f7;
  border-color: rgba(255, 255, 255, 0.2);
}

.viewer__ui .btn:hover {
  border-color: #f2f5f7;
}

.viewer .mono {
  color: rgba(242, 245, 247, 0.62);
}

.viewer__part {
  min-height: 1.25rem;
  font-size: 0.75rem;
  transition: opacity 0.35s var(--ease);
}

.viewer__part[data-state="idle"] {
  opacity: 0.55;
}

.viewer__hint {
  font-size: 0.625rem;
  opacity: 0.5;
  text-align: right;
}

.viewer__loading {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  transition: opacity 0.5s var(--ease);
}

.viewer__loading.is-hidden {
  opacity: 0;
}

/* ─────────────────────────── Responsive ─────────────────────────── */
@media (max-width: 860px) {
  :root {
    --nav-h: 3.5rem;
  }

  .sequence {
    height: 580svh;
  }

  .nav__links {
    display: none;
  }

  /* Links collapse on mobile but the CTA stays — tighten it so it doesn't
     crowd the logo on narrow phones. */
  .nav__cta {
    padding: 0.5rem 1rem;
    font-size: 0.75rem;
    margin-left: auto;
    white-space: nowrap;
  }

  .hero__scroll {
    display: none;
  }

  .hero__title {
    font-size: clamp(2.4rem, 12vw, 4.5rem);
  }

  .hero__stats {
    gap: 1.25rem 2rem;
  }

  .hero__stats li {
    flex: 1 1 7rem;
  }

  .hero__actions .btn {
    flex: 1 1 100%;
  }

  /* NOTE: the old `.bars li { grid-template-columns: 1fr auto }` and
     `.bars__track { grid-column: 1 / -1; order: 3 }` overrides lived here.
     The desktop layout now uses that same two-column / full-width-track
     shape, so the overrides were redundant and have been removed. */

  .finale__actions .btn {
    flex: 1 1 100%;
  }

  .viewer__hint {
    display: none;
  }

  .cta__grid {
    text-align: center;
  }

  /* On a phone the 12vh slope in `.section` resolves near 100px while the
     content is narrow, so every section-to-section run reads as dead space.
     One flat 2.5rem rhythm for the whole page instead. Sections carrying an
     inline padding value in the markup keep it — inline still wins. */
  .section {
    padding-top: 2.5rem;
    padding-bottom: 2.5rem;
  }

  /* Id selectors, so they outrank the rule above and need restating to come
     down with everything else. */
  #journey {
    padding-top: 2.5rem;
  }

  .foot-new {
    padding-top: 2.5rem;
  }

  /* Same rhythm where the spacing came from a margin rather than padding. */
  .verticals,
  .why-cards {
    margin-block: 2rem;
  }

  /* Must match the `.section > .section__head` selector above, not the bare
     class — an id-free descendant selector at (0,2,0) outranks (0,1,0)
     regardless of source order, so a bare `.section__head` here would be
     silently ignored and the desktop clamp would apply on phones. */
  .section>.section__head {
    margin-bottom: 2rem;
  }

  /* Flex sizes each role card to its own label, so "Freelance / Studio Pro"
     comes out wider than "Content Creator" and the stack reads ragged. Equal
     grid tracks give one width for all four. `min-width: 0` releases the 14rem
     floor, which would otherwise overflow a narrow phone. */
  .role-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: 0.75rem;
  }

  .role-card {
    min-width: 0;
  }

  /* MOST POPULAR badge: on desktop this sits fine in the corner because the
     card is wide. Stacked to a narrow phone-width column, the absolute
     position had nothing keeping it clear of the tag text — dropping it back
     into normal flow lets it wrap onto its own line under the tag. */
  .level__tag {
    flex-wrap: wrap;
    row-gap: 0.4rem;
  }

  .level__badge {
    position: static;
    display: inline-block;
  }

  /* Both force a full-viewport recomposite on every scroll frame — the
     difference between 60fps and visible stutter on a phone. */
  .nav {
    backdrop-filter: none;
    background: var(--paper);
  }

  .timeline__tracks {
    backdrop-filter: none;
    background: rgba(11, 13, 17, 0.8);
  }
}

/* ── Portrait phones: full view without letterboxing ──────── */
@media (max-width: 860px) and (orientation: portrait) {
  .hud__thirds {
    opacity: 0.4;
  }

  .timeline__meta {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.25rem;
  }

  .timeline__clip {
    font-size: 0.4375rem;
    padding: 0 0.35rem;
  }

  .timeline__tracks {
    background: rgba(11, 13, 17, 0.35);
  }

  .caption,
  .caption--left,
  .caption--right {
    top: auto;
    /* Dropped from 26svh: that left a dead band between the body copy and the
       timeline scrubber. This sits the block just above the scrubber and lets
       the type grow into the reclaimed space. */
    bottom: 15svh;
    left: var(--gut);
    right: var(--gut);
    width: auto;
    text-align: left;
  }

  .caption--right .caption__eyebrow {
    flex-direction: row;
  }

  /* 9.5vw left the poster reading small against a full-bleed frame. 11.5vw is
     the ceiling the copy allows: the longest authored line is "WIN THE RELEASE."
     at ~7.3em, and at 11.5vw that still clears the gutters down to a 320px
     phone. Steeper wraps it and breaks the three-line shape the <br>s in the
     markup exist to guarantee. */
  .caption__title {
    font-size: clamp(2.2rem, 11.5vw, 4rem);
    line-height: 0.92;
  }

  .caption__body {
    max-width: none;
    font-size: clamp(0.9rem, 3.6vw, 1.05rem);
    line-height: 1.5;
  }
}

/* Short phones: tighten so the scrubber and copy still fit 640px. */
@media (max-width: 860px) and (orientation: portrait) and (max-height: 720px) {
  .timeline__row:nth-child(2) {
    display: none;
  }

  .caption {
    bottom: 16svh;
  }

  .caption__title {
    font-size: clamp(2rem, 10vw, 3.25rem);
  }

  .caption__body {
    font-size: 0.875rem;
    line-height: 1.45;
  }
}

@media (max-width: 460px) {
  .timeline__row:nth-child(2) {
    display: none;
  }

  /* audio track is decoration */
}

/* ─────────────────────────── Accessibility ─────────────────────────── */
@media (prefers-reduced-motion: reduce) {

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  .hud,
  .timeline {
    display: none;
  }

  .sequence {
    height: auto;
  }

  .sequence__sticky {
    position: static;
    height: auto;
    overflow: visible;
  }

  .stage {
    position: static;
  }

  .stage__monitor {
    position: relative;
    aspect-ratio: 16 / 9;
  }

  .stage__gloss {
    display: none;
  }

  .captions {
    position: static;
    display: grid;
    gap: 3rem;
    width: 100%;
    margin-top: 3rem;
    padding: 0 var(--gut);
  }

  .caption,
  .caption--left,
  .caption--right {
    position: static;
    width: auto;
    opacity: 1;
    text-align: left;
    color: var(--ink);
  }

  .caption__title,
  .caption__body {
    text-shadow: none;
  }

  .caption__title span {
    filter: none;
  }

  .caption__body {
    color: var(--ink-soft);
  }

  .finale {
    position: static;
    gap: 2rem;
    padding: 5rem var(--gut) 0;
    opacity: 1;
    pointer-events: auto;
    background: none;
    color: var(--ink);
  }

  .bars__track i {
    width: var(--pct, 0%) !important;
  }
}

:where(a, button):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* ─────────────────────────── Role Cards ─────────────────────────── */
.role-cards {
  display: flex;
  gap: 1.5rem;
  justify-content: center;
  flex-wrap: wrap;
  max-width: 60rem;
  margin: 0 auto;
  padding: 0 var(--gut);
}

.role-card {
  display: flex;
  align-items: center;
  gap: 1rem;
  background: var(--paper-2);
  padding: 0.8rem 1.25rem;
  border-radius: 0.8rem;
  border: 1px solid var(--line-soft);
  min-width: 14rem;
}

.role-card__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  background: rgba(74, 158, 255, 0.14);
  border-radius: 0.5rem;
  font-size: 1.2rem;
}

.role-card:nth-child(2) .role-card__icon {
  background: rgba(23, 201, 184, 0.14);
}

.role-card:nth-child(3) .role-card__icon {
  background: rgba(124, 92, 255, 0.14);
}

.role-card:nth-child(4) .role-card__icon {
  background: rgba(255, 196, 92, 0.12);
}

.role-card__text h4 {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--ink);
}

.role-card__text p {
  margin: 0;
  font-size: 0.75rem;
  color: var(--ink-soft);
}

/* ─────────────────────────── CTA Banner ─────────────────────────── */
.cta-banner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 4rem 2rem;
  background: var(--paper-2);
  border-radius: 1.5rem;
  margin: 0 auto;
  max-width: 60rem;
}

.cta-banner__eyebrow {
  font-family: var(--display);
  font-weight: 600;
  color: var(--accent-2);
  margin-bottom: 1rem;
}

.cta-banner__title {
  font-size: clamp(2rem, 5vw, 3.5rem);
  line-height: 1.1;
  margin-bottom: 1rem;
}

.cta-banner__title span {
  color: #a78bff;
}

.cta-banner__lede {
  font-size: 1.1rem;
  color: var(--ink-soft);
  max-width: 40rem;
  margin: 0 auto 2rem;
}

.cta-banner__actions {
  display: flex;
  gap: 1rem;
  justify-content: center;
  flex-wrap: wrap;
}

/* ─────────────────────────── Contact Section ─────────────────────────── */
.contact-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4rem;
  max-width: 70rem;
  margin: 0 auto;
  padding: 0 var(--gut);
}

/* Grid children default to min-width:auto, which lets a wide descendant (the
   course <select>) stretch the column. */
.contact-layout>* {
  min-width: 0;
}

@media (max-width: 768px) {
  .contact-layout {
    grid-template-columns: 1fr;
  }
}

.contact-info {
  display: flex;
  flex-direction: column;
}

.contact-methods {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  margin-top: 2rem;
}

.contact-item {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
}

.contact-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  background: rgba(23, 201, 184, 0.14);
  border-radius: 0.5rem;
  font-size: 1.2rem;
  flex-shrink: 0;
}

.contact-k {
  font-size: 0.75rem;
  color: var(--ink-soft);
  margin-bottom: 0.25rem;
}

.contact-v {
  font-weight: 500;
}

/* ─── Map card ─── */
/* Deliberately the same shell as `.contact-form-card` below — white, 1rem
   radius, the same soft shadow — so the two columns read as a matched pair
   rather than a map dropped beside a form.

   `flex: 1` is what squares the bottom edges off: `.contact-info` is already
   a flex column, so the map absorbs whatever height is left after the heading
   and the address block, which is roughly the height of the form beside it.
   `min-height` is the floor for the case where the form is the shorter of the
   two (a short viewport, or the column stacked on a phone). */
.contact-map {
  position: relative;
  flex: 1;
  min-height: 22rem;
  margin-top: 2rem;
  /* The padding is the white frame; the iframe takes its own smaller radius
     inside it, which is what makes the map read as mounted in the card rather
     than as the card itself. */
  padding: 0.5rem;
  background: #fff;
  border-radius: 1rem;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.05);
  overflow: hidden;
}

/* Absolute rather than `height: 100%`: a percentage height inside a parent
   that only has `min-height` resolves to `auto`, and an <iframe> with no
   resolved height falls back to the HTML default of 150px. Pinning it to the
   padded box sidesteps that entirely. */
.contact-map iframe {
  position: absolute;
  inset: 0.5rem;
  display: block;
  width: calc(100% - 1rem);
  height: calc(100% - 1rem);
  border: 0;
  border-radius: 0.65rem;
  /* Google's default map saturation fights the page palette slightly. */
  filter: saturate(0.9);
}

@media (max-width: 768px) {
  .contact-map {
    min-height: 18rem;
    margin-top: 1.5rem;
  }
}

.contact-form-card {
  background: var(--paper-2);
  border: 1px solid var(--line-soft);
  padding: 2.5rem;
  border-radius: 1rem;
  /* Anchor offset: #contact-form is a link target, keep it clear of the nav */
  scroll-margin-top: calc(var(--nav-h) + 1rem);
}

.contact-form-card h3 {
  font-size: 1.5rem;
  margin-bottom: 0.5rem;
}

.contact-form-card p {
  color: var(--ink-soft);
  font-size: 0.9rem;
  margin-bottom: 2rem;
}

.c-form {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  /* Same reason as the inputs: without this the group inherits its child's
     intrinsic width instead of shrinking to the column. */
  min-width: 0;
}

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
  min-width: 0;
}

@media (max-width: 500px) {
  .form-row {
    grid-template-columns: 1fr;
  }
}

.c-form label {
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.c-form input,
.c-form select,
.c-form textarea {
  width: 100%;
  /* A <select> reports an intrinsic min-width equal to its widest option, and
     flex/grid children default to min-width:auto — so the long course names in
     the dropdown were forcing the whole page wider than the phone and creating
     a horizontal swipe. min-width:0 lets width:100% actually win. */
  min-width: 0;
  padding: 0.8rem 1rem;
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  font-family: inherit;
  font-size: 0.95rem;
  color: var(--ink);
  background: var(--paper);
}

/* Placeholders inherit the input colour otherwise, which on dark reads as a
   filled-in value rather than a prompt. */
.c-form ::placeholder {
  color: var(--ink-soft);
  opacity: 0.7;
}

.c-form input:focus,
.c-form select:focus,
.c-form textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--paper-3);
}

.form-note {
  font-size: 0.75rem !important;
  text-align: center;
  margin-top: 0.5rem !important;
  margin-bottom: 0 !important;
}

/* ─────────────────────────── Footer ─────────────────────────── */
/* No top margin: the contact section already closes with its own bottom
   padding and the footer opens with 4rem of its own, so a margin on top of
   that just rendered as a dead strip of page background between the two. */
.foot-new {
  background: var(--paper-2);
  padding: 4rem var(--gut) 2rem;
  margin-top: 0;
}

.foot-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: 3rem;
  max-width: 70rem;
  margin: 0 auto 3rem;
}

@media (max-width: 900px) {
  .foot-grid {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 500px) {
  .foot-grid {
    grid-template-columns: 1fr;
  }
}

.foot-brand p {
  color: var(--ink-soft);
  font-size: 0.95rem;
  line-height: 1.5;
}

.foot-col h4 {
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  color: var(--ink);
  margin-bottom: 1.5rem;
}

.foot-col a,
.foot-col p {
  display: block;
  color: var(--ink-soft);
  text-decoration: none;
  margin-bottom: 0.8rem;
  font-size: 0.9rem;
}

.foot-col a:hover {
  color: var(--accent);
}

.foot-bottom {
  max-width: 70rem;
  margin: 0 auto;
  padding-top: 2rem;
  border-top: 1px solid var(--line-soft);
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
}

.foot-bottom p {
  margin: 0;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

/* ─────────────────────────── Verticals & Why Cards ─────────────────────────── */
/* 70rem to match #journey, #skills and #tariff, and no `padding: 0 var(--gut)`
   of its own — the section already supplies the gutter, so the extra inset was
   pushing the cards in from the heading's left edge. At 75rem centred against
   a gutter-aligned head the two started ~350px apart on a 1920 screen. */
.verticals,
.why-cards {
  display: grid;
  gap: 1rem;
  max-width: 70rem;
  margin: 2.5rem auto 0;
  padding: 0;
}

.verticals {
  grid-template-columns: repeat(4, 1fr);
}

.why-cards {
  grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 1024px) {
  .verticals {
    grid-template-columns: repeat(3, 1fr);
  }

  .why-cards {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 768px) {
  .verticals {
    grid-template-columns: repeat(2, 1fr);
  }

  .why-cards {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 480px) {
  .verticals {
    grid-template-columns: 1fr;
  }
}

.verticals li,
.why-cards li {
  background: var(--paper-2);
  padding: 1.5rem;
  border-radius: 1rem;
  border: 1px solid var(--line-soft);
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
}

.verticals__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  background: rgba(74, 158, 255, 0.14);
  border-radius: 0.5rem;
  font-size: 1.2rem;
}

.verticals li:nth-child(2) .verticals__icon,
.why-cards li:nth-child(2) .verticals__icon {
  background: rgba(124, 92, 255, 0.14);
}

.verticals li:nth-child(3) .verticals__icon,
.why-cards li:nth-child(3) .verticals__icon {
  background: rgba(151, 137, 255, 0.13);
}

.verticals li:nth-child(4) .verticals__icon,
.why-cards li:nth-child(4) .verticals__icon {
  background: rgba(255, 196, 92, 0.12);
}

.verticals li:nth-child(5) .verticals__icon,
.why-cards li:nth-child(5) .verticals__icon {
  background: rgba(74, 158, 255, 0.14);
}

.verticals li:nth-child(6) .verticals__icon,
.why-cards li:nth-child(6) .verticals__icon {
  background: rgba(23, 201, 184, 0.14);
}

.verticals li:nth-child(7) .verticals__icon,
.why-cards li:nth-child(7) .verticals__icon {
  background: rgba(255, 122, 122, 0.12);
}

.verticals li:nth-child(8) .verticals__icon,
.why-cards li:nth-child(8) .verticals__icon {
  background: rgba(74, 158, 255, 0.14);
}

.verticals h3,
.why-cards h3 {
  font-size: 1.1rem;
  color: var(--ink);
  margin: 0;
}

.verticals p,
.why-cards p {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin: 0;
  line-height: 1.5;
}

/* ═══════════════════════════════════════════════════════════════════════════
   iOS: THE SIDEWAYS SWIPE
   ───────────────────────────────────────────────────────────────────────────
   Two boxes here are much wider than the screen and rely on an ancestor's
   `overflow: hidden` to crop them:

     .marquee__track   width: max-content -> several thousand px in a strip
     #frames           GSAP scales it to 1.06 on entry and 1.05 at the finale

   Both are transform-animated, so WebKit promotes each to its own compositing
   layer — and WebKit has a long-standing bug where `overflow: hidden` on an
   ancestor fails to clip a composited descendant. Blink clips correctly, which
   is why this only shows on iPhones.

   `contain: paint` states the clip as a containment guarantee rather than a
   paint-time hint, which WebKit honours on composited layers. Safari 15.4+. */
.sequence__sticky,
.marquee {
  contain: paint;
}

/* ═══════════════════════════════════════════════════════════════════════════
   HUD: FRAMING OVERLAY OFF
   ───────────────────────────────────────────────────────────────────────────
   Both the rule-of-thirds grid and the four corner brackets read as rendering
   artefacts rather than as a viewfinder overlay — thin pale lines sitting on
   top of the footage, which people take for a glitch rather than a device.

   `display: none` rather than deleting the rules: the markup keeps the spans,
   so switching the overlay back on is one line. Anything else inside `.hud`
   (the REC readout and progress bar on the cinematography build) is untouched,
   which is why this hides the two children rather than `.hud` itself. */
.hud__thirds,
.hud__bracket {
  display: none;
}

/* ═══════════════════════════════════════════════════════════════════════════
   NAV LOCKUP
   ───────────────────────────────────────────────────────────────────────────
   Uses the brand logo icon (favicon.png) beside the two-line wordmark.
   Height-driven with width auto so the artwork keeps its own aspect ratio.
   This is the ONLY place logo sizing is set — the fixed height that used to
   sit in the nav section is gone so these breakpoints actually apply.
   ═══════════════════════════════════════════════════════════════════════════ */
.nav__mark {
  gap: 0.75rem;
}

.nav__logo-img {
  width: auto;
  height: 4rem;
  max-height: calc(var(--nav-h) - 0.5rem);
  object-fit: contain;
  display: block;
  flex: none;
}

/* Grid rather than two blocks, so the baseline gap is a single value and the
   pair centres against the logo icon. */
.nav__name {
  display: grid;
  gap: 0.1rem;
  line-height: 1.05;
}

.nav__name b {
  font-size: 1.125rem;
  font-weight: 700;
  color: #fff;
  letter-spacing: -0.01em;
}

/* Mono, tracked out and small — the same treatment as every other eyebrow on
   the page, so the descriptor reads as a label rather than a second title. */
.nav__name em {
  font-family: var(--mono);
  font-style: normal;
  font-size: 0.52rem;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  white-space: nowrap;
}

/* --nav-h drops to 3.5rem at this breakpoint. */
@media (max-width: 860px) {
  .nav__logo-img {
    height: 3rem;
  }
}

/* Narrow phones: the CTA needs the width more than the logo does. */
@media (max-width: 460px) {
  .nav__name em {
    display: none;
  }

  .nav__logo-img {
    height: 2.7rem;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   SEO CONTENT
   ═══════════════════════════════════════════════════════════════════════════ */
.seo-card {
  background: var(--paper-2);
  max-width: 1000px;
  width: 100%;
  margin: 0 auto;
  border-radius: 12px;
  border: 1px solid var(--line-soft);
  display: flex;
  flex-direction: row;
  align-items: center;
  padding: 4rem 3rem;
  gap: 3rem;
  box-sizing: border-box;
}

@media (max-width: 768px) {
  .seo-card {
    flex-direction: column;
    padding: 2rem;
  }
}

.seo-left {
  flex: 1.2;
}

.seo-pill {
  display: inline-block;
  background-color: rgba(23, 201, 184, 0.15);
  color: var(--accent-2);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.35rem 0.8rem;
  border-radius: 20px;
  margin-bottom: 1.5rem;
}

.seo-title {
  color: var(--ink);
  font-size: 1.8rem;
  font-weight: 500;
  line-height: 1.2;
  margin-bottom: 1.25rem;
  font-family: 'Poppins', sans-serif;
}

.seo-text {
  color: var(--ink-soft);
  font-size: 1rem;
  line-height: 1.7;
  font-weight: 400;
  max-width: 400px;
}

.seo-right {
  flex: 1;
  border: 1px solid var(--line-soft);
  background-color: var(--paper-3);
  border-radius: 12px;
  padding: 2.5rem 2rem;
}

.seo-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem 1rem;
  list-style: none;
  padding: 0;
  margin: 0;
}

@media (max-width: 600px) {
  .seo-list {
    grid-template-columns: 1fr;
  }
}

.seo-list li {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.seo-list li span {
  color: var(--ink);
  font-size: 1rem;
  font-weight: 500;
  line-height: 1.4;
}

.seo-check {
  width: 28px;
  height: 28px;
  background-color: var(--paper-2);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line-soft);
  flex-shrink: 0;
  position: relative;
}

.seo-check::after {
  content: '';
  position: absolute;
  width: 16px;
  height: 16px;
  background-color: var(--accent);
  border-radius: 50%;
  z-index: 1;
}

.seo-check svg {
  width: 10px;
  height: 10px;
  color: #ffffff;
  z-index: 2;
  stroke-width: 4px;
}