:root {
  --navy-950: #020713;
  --navy-900: #061225;
  --navy-850: #0a1a31;
  --navy-800: #0d2542;
  --navy-700: #17395f;
  --gold: #f5c518;
  --gold-soft: #ffe176;
  --white: #ffffff;
  --ice: #f2f5f9;
  --text: #f7f9fc;
  --muted: #aeb9c8;
  --ink: #071427;
  --line: rgba(205, 219, 238, .17);
  --line-dark: rgba(7, 20, 39, .13);
  --shadow: 0 24px 70px rgba(0, 0, 0, .3);
  --radius: 18px;
  --max: 1180px;
  --header: 72px;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  overflow-x: hidden;
  color: var(--text);
  background: var(--navy-950);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
body.menu-open { overflow: hidden; }
body.menu-open::before {
  position: fixed;
  z-index: 99;
  inset: var(--header) 0 0;
  content: "";
  background: rgba(2, 7, 19, .56);
  backdrop-filter: blur(2px);
}
img, video { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
button, input, textarea, select { color: inherit; font: inherit; }
button { cursor: pointer; }
h1, h2, h3, h4, p { margin-top: 0; }
h1, h2, h3, h4 {
  margin-bottom: 0;
  color: inherit;
  font-weight: 900;
  letter-spacing: -.045em;
  line-height: 1.02;
}
h1 { max-width: 880px; font-size: clamp(3.15rem, 6vw, 5.9rem); }
h2 { font-size: clamp(2.15rem, 4vw, 3.85rem); }
h3 { font-size: clamp(1.15rem, 2vw, 1.55rem); letter-spacing: -.025em; }
p { margin-bottom: 1rem; }
.wrap { width: min(var(--max), calc(100% - 44px)); margin-inline: auto; }
.narrow { max-width: 780px; }
.section { position: relative; padding: clamp(64px, 7vw, 96px) 0; }
.section-tight { padding: clamp(42px, 5vw, 68px) 0; }
.section-dark { background: var(--navy-900); border-block: 1px solid var(--line); }
.section-ice { color: var(--ink); background: var(--ice); }
.section-pitch {
  isolation: isolate;
  overflow: hidden;
  background:
    linear-gradient(90deg, rgba(2, 15, 9, .92), rgba(3, 35, 19, .73) 53%, rgba(1, 13, 8, .92)),
    url("../img/pitch-overhead-v1.webp") center 52% / cover no-repeat;
}
.section-pitch::after {
  position: absolute;
  z-index: -1;
  inset: 0;
  content: "";
  background: linear-gradient(180deg, var(--navy-950), transparent 18% 82%, var(--navy-950));
  pointer-events: none;
}
.skip-link {
  position: fixed;
  z-index: 999;
  top: -80px;
  left: 12px;
  padding: 10px 16px;
  color: var(--ink);
  background: var(--gold);
  font-weight: 900;
}
.skip-link:focus { top: 12px; }
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  color: var(--gold);
  font-size: .69rem;
  font-weight: 900;
  letter-spacing: .16em;
  line-height: 1.3;
  text-transform: uppercase;
}
.eyebrow::before { width: 28px; height: 2px; content: ""; background: currentColor; }
.lead {
  max-width: 650px;
  margin-bottom: 0;
  color: #c5ceda;
  font-size: clamp(1rem, 1.45vw, 1.2rem);
  line-height: 1.65;
}
.section-ice .lead, .section-ice .muted { color: #41516a; }
.muted { color: var(--muted); }
.section-heading {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(250px, .56fr);
  gap: 32px;
  align-items: end;
  margin-bottom: 32px;
}
.section-heading > p { justify-self: end; max-width: 470px; margin: 0; color: var(--muted); }
.section-heading.compact { display: block; max-width: 760px; }
.actions { display: flex; flex-wrap: wrap; gap: 11px; margin-top: 27px; }
.btn, .nav-cta {
  display: inline-flex;
  min-height: 46px;
  align-items: center;
  justify-content: center;
  padding: 0 21px;
  border: 1px solid transparent;
  border-radius: 4px;
  font-size: .75rem;
  font-weight: 900;
  letter-spacing: .07em;
  line-height: 1;
  text-align: center;
  text-transform: uppercase;
  transition: transform .2s ease, background .2s ease, color .2s ease, border-color .2s ease;
}
.btn:hover, .nav-cta:hover { transform: translateY(-2px); }
.btn-primary, .nav-cta { color: var(--ink); background: var(--gold); box-shadow: 0 12px 30px rgba(245, 197, 24, .18); }
.btn-primary:hover, .nav-cta:hover { background: var(--gold-soft); }
.btn-secondary { color: var(--white); background: rgba(3, 13, 27, .4); border-color: rgba(255, 255, 255, .29); }
.btn-secondary:hover { border-color: var(--gold); }
.section-ice .btn-secondary { color: var(--ink); border-color: var(--line-dark); background: white; }

/* Shared navigation */
.site-header {
  position: fixed;
  z-index: 100;
  inset: 0 0 auto;
  height: var(--header);
  color: var(--ink);
  background: rgba(250, 252, 255, .96);
  border-bottom: 1px solid var(--line-dark);
  box-shadow: 0 8px 30px rgba(0, 8, 25, .08);
  backdrop-filter: blur(18px);
}
.nav-wrap { display: flex; height: 100%; align-items: center; gap: 20px; }
.brand { display: inline-flex; width: 174px; height: 48px; flex: none; align-items: center; }
.brand-logo { width: 100%; height: 100%; object-fit: contain; object-position: left center; }
.site-nav { display: flex; min-width: 0; align-items: center; gap: clamp(14px, 1.55vw, 23px); margin-left: auto; }
.site-nav a {
  position: relative;
  color: #26364d;
  font-size: .69rem;
  font-weight: 850;
  letter-spacing: .035em;
  white-space: nowrap;
  text-transform: uppercase;
}
.site-nav a:hover, .site-nav a[aria-current="page"] { color: #020d20; }
.site-nav a[aria-current="page"]::after {
  position: absolute;
  right: 0;
  bottom: -12px;
  left: 0;
  height: 2px;
  content: "";
  background: var(--gold);
}
.site-nav-mobile-cta { display: none; }
.nav-toggle { display: none; margin-left: auto; width: 44px; height: 44px; border: 1px solid var(--line-dark); background: transparent; font-size: 0; }
.nav-toggle::before, .nav-toggle::after {
  display: block;
  width: 20px;
  height: 2px;
  margin: 6px auto;
  content: "";
  background: var(--ink);
  transition: transform .2s ease;
}
.nav-toggle[aria-expanded="true"]::before { transform: translateY(4px) rotate(45deg); }
.nav-toggle[aria-expanded="true"]::after { transform: translateY(-4px) rotate(-45deg); }

/* Homepage hero */
.home-hero {
  position: relative;
  min-height: 680px;
  padding-top: var(--header);
  overflow: hidden;
  isolation: isolate;
  background: var(--navy-950) url("../img/stadium-hero-v2.webp") center / cover no-repeat;
}
.home-hero::before {
  position: absolute;
  z-index: -1;
  inset: 0;
  content: "";
  background:
    linear-gradient(90deg, rgba(2, 7, 19, .97) 0%, rgba(2, 7, 19, .77) 42%, rgba(2, 7, 19, .2) 78%),
    linear-gradient(0deg, var(--navy-950), transparent 35%);
}
.home-hero::after {
  position: absolute;
  top: var(--header);
  left: 0;
  width: 12vw;
  height: 2px;
  content: "";
  background: var(--gold);
}
.home-hero-inner {
  display: grid;
  min-height: 608px;
  grid-template-columns: minmax(0, 1fr) minmax(350px, .72fr);
  align-items: center;
  gap: 28px;
  padding: 58px 0 36px;
}
.home-hero-copy { position: relative; z-index: 4; }
.home-hero h1 { max-width: 700px; font-size: clamp(3.5rem, 5.8vw, 5.65rem); }
.home-hero h1 span { color: var(--gold); }
.home-hero .lead { max-width: 580px; margin-top: 20px; }
.hero-roster {
  position: relative;
  height: 485px;
  perspective: 1000px;
}
.hero-player {
  position: absolute;
  right: 4%;
  bottom: 28px;
  width: min(61%, 274px);
  height: 415px;
  padding: 7px;
  opacity: 0;
  color: var(--ink);
  background: linear-gradient(145deg, #f2f5f8, #91a3b7);
  border: 1px solid rgba(255, 255, 255, .75);
  border-radius: 20px 4px 20px 4px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, .45);
  transform: translateX(55px) scale(.9);
  transition: opacity .55s ease, transform .65s ease;
}
.hero-player.is-active { z-index: 3; opacity: 1; transform: none; }
.hero-player.is-next { z-index: 2; opacity: .58; transform: translate(58px, 13px) rotate(4deg) scale(.91); }
.hero-player img { width: 100%; height: 338px; object-fit: cover; object-position: center 50%; border-radius: 14px 2px 10px 2px; background: var(--navy-900); }
.hero-player footer { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 6px 4px; }
.hero-player small { display: block; color: #57687b; font-size: .56rem; font-weight: 900; letter-spacing: .11em; text-transform: uppercase; }
.hero-player strong { display: block; margin-top: 1px; font-size: .78rem; text-transform: uppercase; }
.hero-player footer img { width: 30px; height: 30px; border-radius: 7px; object-fit: cover; }
.hero-controls { position: absolute; z-index: 5; right: 6%; bottom: 0; display: flex; gap: 6px; }
.hero-control { width: 25px; height: 3px; padding: 0; border: 0; background: rgba(255,255,255,.3); }
.hero-control.is-active { background: var(--gold); }

/* Reusable layouts and cards */
.two-col { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(28px, 5vw, 72px); align-items: center; }
.three-col { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.four-col { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.feature-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 13px; }
.ui-card {
  min-width: 0;
  padding: 25px;
  background: linear-gradient(145deg, rgba(13, 37, 66, .9), rgba(5, 18, 36, .96));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 15px 44px rgba(0, 0, 0, .14);
}
.section-ice .ui-card { background: white; border-color: var(--line-dark); box-shadow: 0 12px 38px rgba(5, 22, 47, .08); }
.ui-card .number {
  display: inline-grid;
  width: 34px;
  height: 34px;
  place-items: center;
  margin-bottom: 25px;
  color: var(--gold);
  background: rgba(245, 197, 24, .08);
  border: 1px solid rgba(245, 197, 24, .32);
  border-radius: 7px;
  font-size: .69rem;
  font-weight: 900;
}
.ui-card p { margin: 11px 0 0; color: var(--muted); font-size: .88rem; }
.section-ice .ui-card p { color: #506078; }
.card-link { transition: transform .2s ease, border-color .2s ease; }
.card-link:hover { border-color: rgba(245, 197, 24, .5); transform: translateY(-4px); }
.editorial-card {
  position: relative;
  min-height: 390px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--navy-850);
}
.editorial-card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.editorial-card::after { position: absolute; inset: 0; content: ""; background: linear-gradient(0deg, rgba(2,8,18,.96), rgba(2,8,18,.04) 72%); }
.editorial-card-copy { position: absolute; z-index: 2; right: 0; bottom: 0; left: 0; padding: 25px; }
.editorial-card-copy p { margin: 8px 0 0; color: #c5cfdb; font-size: .86rem; }
.app-showcase {
  position: relative;
  display: grid;
  min-height: 480px;
  grid-template-columns: .9fr 1.1fr;
  align-items: center;
  overflow: hidden;
  background: radial-gradient(circle at 76% 42%, #1c4d7d, transparent 37%), linear-gradient(140deg, #0b284a, #051329 70%);
  border: 1px solid var(--line);
  border-radius: 24px;
}
.app-showcase-copy { position: relative; z-index: 2; padding: clamp(32px, 5vw, 66px); }
.app-showcase-copy p { max-width: 460px; margin: 17px 0 0; color: var(--muted); }
.app-showcase-visual { position: relative; align-self: stretch; overflow: hidden; }
.app-showcase-visual img { position: absolute; width: min(55%, 310px); right: 17%; bottom: -13%; filter: drop-shadow(0 32px 40px rgba(0,0,0,.45)); transform: rotate(3deg); }
.app-screen-stack { overflow: visible; perspective: 1200px; }
.app-screen-stack img {
  width: min(43%, 250px);
  right: 25%;
  bottom: -15%;
  border: 1px solid rgba(255, 255, 255, .25);
  border-radius: 22px;
  box-shadow: 0 28px 48px rgba(0, 0, 0, .42);
  filter: none;
  transform-origin: center bottom;
}
.app-screen-stack img:nth-child(1) { z-index: 1; right: 48%; bottom: -11%; transform: rotate(-10deg) scale(.88); }
.app-screen-stack img:nth-child(2) { z-index: 2; right: 5%; bottom: -11%; transform: rotate(10deg) scale(.88); }
.app-screen-stack img:nth-child(3) { z-index: 3; right: 26%; bottom: -15%; transform: rotate(1deg); }
.fact-strip { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); background: var(--line); border: 1px solid var(--line); gap: 1px; }
.fact { padding: 25px; background: var(--navy-900); }
.fact strong { display: block; color: var(--gold); font-size: 1.5rem; }
.fact span { color: var(--muted); font-size: .75rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.app-feature-cards .ui-card { min-height: 245px; }
.app-screen-track {
  display: flex;
  gap: 22px;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-inline: contain;
  padding: 8px 5px 20px;
  scroll-snap-type: x mandatory;
  touch-action: pan-x;
  /* Full-height screenshots repaint on every scroll frame far more
     expensively than a text card — this promotes the scroller to its own
     compositor layer instead of redrawing the main thread each frame. */
  will-change: scroll-position;
  contain: layout paint;
}
.app-screen-track figure {
  display: grid;
  flex: 0 0 30%;
  min-width: 280px;
  grid-template-columns: minmax(0, 1fr);
  gap: 18px;
  margin: 0;
  scroll-snap-align: start;
}
.app-screen-track figure > img {
  width: 100%;
  max-height: 610px;
  object-fit: cover;
  object-position: top;
  border: 1px solid var(--line-dark);
  border-radius: 25px;
  box-shadow: 0 24px 55px rgba(5, 22, 47, .2);
}
.app-screen-track figcaption { display: grid; gap: 5px; }
.app-screen-track figcaption strong { font-size: 1.05rem; }
.app-screen-track figcaption span { color: #4b5b71; font-size: .86rem; line-height: 1.55; }

/* Scenarios and languages */
.scenario-track, .language-track, .testimonial-track, .work-track {
  display: flex;
  gap: 14px;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-inline: contain;
  padding: 2px 2px 16px;
  scroll-snap-type: x mandatory;
  scrollbar-color: rgba(245,197,24,.45) transparent;
  scrollbar-width: thin;
  touch-action: pan-x;
  will-change: scroll-position;
  contain: layout paint;
}
.scenario {
  position: relative;
  min-height: 330px;
  flex: 0 0 330px;
  overflow: hidden;
  border-radius: var(--radius);
  scroll-snap-align: start;
}
.scenario img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.scenario::after { position: absolute; inset: 0; content: ""; background: linear-gradient(0deg, rgba(2,8,18,.98), rgba(2,8,18,.02) 72%); }
.scenario div { position: absolute; z-index: 2; right: 0; bottom: 0; left: 0; padding: 23px; }
.scenario p { margin: 7px 0 0; color: #c5cfdb; font-size: .85rem; }
.language-card {
  position: relative;
  flex: 0 0 200px;
  overflow: hidden;
  color: var(--ink);
  background: linear-gradient(145deg,#f4f7fa,#93a5b8);
  border-radius: 16px 3px 16px 3px;
  scroll-snap-align: start;
}
.language-card > img { width: 100%; aspect-ratio: 2 / 3; object-fit: contain; object-position: center; background: #f6f4ef; }
.language-card footer { display: flex; align-items: center; justify-content: space-between; padding: 13px; }
.language-card small { display: block; color: #5a6877; font-size: .56rem; font-weight: 900; letter-spacing: .11em; text-transform: uppercase; }
.language-card strong { display: block; margin-top: 2px; font-size: .82rem; text-transform: uppercase; }
.language-card footer img { width: 31px; height: 31px; border-radius: 7px; object-fit: cover; }
.scroll-hint { margin: 3px 0 0; color: var(--muted); font-size: .75rem; }

/* PDFs */
.edition-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 15px; }
.edition-card {
  display: grid;
  min-width: 0;
  grid-template-columns: 42% 1fr;
  gap: 17px;
  align-items: center;
  padding: 17px;
  color: var(--ink);
  background: white;
  border: 1px solid var(--line-dark);
  border-radius: var(--radius);
  box-shadow: 0 15px 42px rgba(4, 20, 42, .08);
  transition: transform .2s ease, box-shadow .2s ease;
}
.edition-card:hover { transform: translateY(-4px); box-shadow: 0 20px 48px rgba(4,20,42,.13); }
.edition-card > img { width: 100%; height: auto; aspect-ratio: 2 / 3; object-fit: contain; border-radius: 7px; }
.edition-card span { color: #68778a; font-size: .69rem; font-weight: 900; letter-spacing: .08em; text-transform: uppercase; }
.edition-card h3 { margin: 6px 0 11px; }
.edition-card b { color: #997600; font-size: .72rem; letter-spacing: .04em; text-transform: uppercase; }
.pdf-feature { display: grid; grid-template-columns: .82fr 1.18fr; gap: clamp(30px, 5vw, 76px); align-items: center; }
.cover-fan { position: relative; min-height: 460px; }
.cover-fan img { position: absolute; bottom: 5%; left: 24%; width: 44%; max-width: 230px; border-radius: 8px; box-shadow: var(--shadow); transform: rotate(-3deg); }
.cover-fan img:nth-child(2) { left: 39%; bottom: 8%; transform: rotate(7deg); }
.cover-fan-three img { left: 13%; width: 39%; transform: rotate(-8deg); }
.cover-fan-three img:nth-child(2) { z-index: 2; left: 32%; bottom: 5%; transform: rotate(1deg); }
.cover-fan-three img:nth-child(3) { z-index: 1; left: 51%; bottom: 8%; transform: rotate(9deg); }
.tick-list { display: grid; gap: 11px; margin: 24px 0; padding: 0; list-style: none; }
.tick-list li { display: flex; gap: 11px; color: #c8d1dd; }
.section-ice .tick-list li { color: #3e4d62; }
.tick-list li::before { color: var(--gold); content: "✓"; font-weight: 900; }

/* Founder, video and testimonials */
.story-grid { display: grid; grid-template-columns: 1.05fr .95fr; gap: clamp(30px, 6vw, 84px); align-items: center; }
.story-video-shell { position: relative; overflow: hidden; border-radius: 2px; }
.story-video {
  width: 100%;
  aspect-ratio: 16 / 10;
  background: #020713;
  object-fit: cover;
  object-position: center 12%;
}
.story-video-shell::after { position: absolute; inset: 0; content: ""; pointer-events: none; border: 1px solid rgba(255,255,255,.16); }
.video-cover {
  position: absolute;
  z-index: 2;
  inset: 0;
  width: 100%;
  padding: 0;
  overflow: hidden;
  background: #020713;
  border: 0;
}
.video-cover[hidden] { display: none; }
.video-cover > img { width: 100%; height: 100%; object-fit: cover; object-position: center 10%; }
.video-cover > span {
  position: absolute;
  top: 50%;
  left: 50%;
  display: grid;
  width: 62px;
  height: 62px;
  place-items: center;
  color: var(--ink);
  background: var(--gold);
  border: 4px solid rgba(255,255,255,.8);
  border-radius: 50%;
  box-shadow: 0 15px 40px rgba(0,0,0,.42);
  transform: translate(-50%, -50%);
}
.story-copy p { max-width: 540px; margin-top: 17px; color: var(--muted); }
.testimonial {
  min-height: 250px;
  flex: 0 0 315px;
  padding: 25px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: linear-gradient(145deg, rgba(13,37,66,.88), rgba(5,18,36,.96));
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.testimonial-actions { display: flex; justify-content: center; margin-top: 18px; }
.testimonial::before { color: var(--gold); content: "“"; font: 3.4rem/1 Georgia, serif; }
.testimonial blockquote { margin: 10px 0 28px; font-size: 1.05rem; font-weight: 750; line-height: 1.45; }
.player-id { display: flex; align-items: center; gap: 10px; }
.avatar { display: grid; width: 36px; height: 36px; place-items: center; color: var(--ink); background: var(--gold); border-radius: 50%; font-size: .67rem; font-weight: 900; }
.player-id strong, .player-id small { display: block; }
.player-id small { color: var(--muted); font-size: .72rem; }

/* Studio and services */
.studio-panel {
  position: relative;
  display: grid;
  min-height: 380px;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  overflow: hidden;
  background: var(--navy-850);
  border: 1px solid var(--line);
  border-radius: 24px;
}
.studio-panel img { width: 100%; height: 100%; min-height: 380px; object-fit: cover; }
.studio-panel-copy { padding: clamp(30px, 5vw, 62px); }
.studio-panel-copy p { margin: 15px 0 0; color: var(--muted); }
.service-split { display: grid; grid-template-columns: .85fr 1.15fr; gap: clamp(34px, 6vw, 80px); align-items: center; }
.service-image { min-height: 420px; width: 100%; object-fit: cover; border-radius: 2px; mask-image: linear-gradient(to right, #000 82%, transparent); }
.about-studio-cover {
  width: 100%;
  min-height: 430px;
  object-fit: cover;
  object-position: center 22%;
  border-radius: 2px;
  mask-image: linear-gradient(to right, #000 84%, transparent);
}
.work-item {
  flex: 0 0 330px;
  overflow: hidden;
  color: var(--ink);
  background: white;
  border: 1px solid var(--line-dark);
  border-radius: var(--radius);
  scroll-snap-align: start;
}
.work-item > img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; background: #e7ecf2; }
.work-body { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; padding: 19px; }
.work-body p { margin: 6px 0 0; color: #657389; font-size: .8rem; }
.status { flex: none; padding: 5px 8px; color: #715800; background: #fff5c5; border-radius: 50px; font-size: .59rem; font-weight: 900; text-transform: uppercase; }
.process { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); background: var(--line); border: 1px solid var(--line); gap: 1px; }
.process > div { padding: 25px; background: var(--navy-900); }
.process b { display: block; margin-bottom: 44px; color: var(--gold); }
.process p { margin: 9px 0 0; color: var(--muted); font-size: .84rem; }

/* Internal page heroes */
.page-hero {
  position: relative;
  display: grid;
  min-height: 510px;
  align-items: center;
  padding: calc(var(--header) + 45px) 0 52px;
  overflow: hidden;
  isolation: isolate;
  background-position: center;
  background-size: cover;
}
.page-hero::before {
  position: absolute;
  z-index: -1;
  inset: 0;
  content: "";
  background: linear-gradient(90deg, rgba(2,7,19,.97), rgba(2,7,19,.74) 49%, rgba(2,7,19,.12) 82%), linear-gradient(0deg, var(--navy-950), transparent 40%);
}
.page-hero h1 { max-width: 760px; font-size: clamp(3rem, 5.25vw, 5rem); }
.page-hero .lead { margin-top: 18px; }
.hero-app, .hero-waitlist { background-image: url("../img/hero-app-v1.webp"); }
.hero-pdfs { background-image: url("../img/hero-pdfs-v1.webp"); }
.hero-services { background-image: url("../img/web-studio-v2.webp"); }
.hero-journey { background-image: url("../img/player-journey-v1.webp"); background-position: center 42%; }
.hero-testimonials { background-image: url("../img/hero-testimonials-v1.webp"); }
.hero-about { background-image: url("../img/hero-about-v1.webp"); }
.hero-contact { background-image: url("../img/hero-contact-v1.webp"); }
.hero-spanish { background-image: url("../img/hero_spanish.webp"); }
.hero-german { background-image: url("../img/hero_german.webp"); }
.hero-french { background-image: url("../img/hero_french.webp"); }
.hero-italian { background-image: url("../img/hero_italian.webp"); }
.hero-portuguese { background-image: url("../img/hero_portuguese.webp"); }
.hero-polish { background-image: url("../img/hero_polish.webp"); }
.edition-hero-copy { max-width: 680px; }
.price { display: flex; align-items: center; gap: 14px; margin-top: 20px; }
.price strong { color: var(--gold); font-size: 2.3rem; }
.price span { color: #c7d0dc; font-size: .76rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; }

/* Journey */
.journey-image {
  min-height: 390px;
  margin-bottom: 30px;
  background: url("../img/player-journey-v1.webp") center 43% / cover no-repeat;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.career-track { position: relative; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; padding-top: 30px; }
.career-track::before { position: absolute; top: 14px; right: 4%; left: 4%; height: 2px; content: ""; background: rgba(245,197,24,.65); }
.career-stop { position: relative; min-height: 185px; padding: 21px; background: rgba(3,16,31,.87); border: 1px solid var(--line); border-radius: 13px; }
.career-stop::before { position: absolute; top: -23px; left: 23px; width: 11px; height: 11px; content: ""; background: var(--gold); border: 4px solid #0b3c21; border-radius: 50%; }
.career-stop span { display: block; margin-bottom: 25px; color: var(--gold); font-size: .67rem; font-weight: 900; letter-spacing: .12em; }
.career-stop p { margin: 9px 0 0; color: #c7d0dc; font-size: .82rem; }
.journey-mobile { display: none; }
.journey-mobile-image-window {
  height: 230px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 14px 14px 0 0;
}
.journey-mobile-image-window img {
  width: 180%;
  max-width: none;
  height: 100%;
  object-fit: cover;
  object-position: center 43%;
  transform: translateX(var(--journey-offset, 0px));
  transition: transform .08s linear;
  will-change: transform;
}
.journey-mobile-track {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-inline: contain;
  padding-bottom: 14px;
  scroll-snap-type: x mandatory;
  touch-action: pan-x;
}
.journey-mobile-track .career-stop {
  min-height: 175px;
  flex: 0 0 85vw;
  border-radius: 0 0 14px 14px;
  scroll-snap-align: start;
}
.journey-mobile-track .career-stop::before { display: none; }

/* Forms */
.contact-layout { display: grid; grid-template-columns: .75fr 1.25fr; gap: 18px; align-items: stretch; }
.contact-card { padding: clamp(25px, 4vw, 40px); background: var(--navy-900); border: 1px solid var(--line); border-radius: var(--radius); }
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
.field { display: grid; gap: 7px; min-width: 0; }
.field.full { grid-column: 1 / -1; }
.field label { font-size: .74rem; font-weight: 850; letter-spacing: .04em; text-transform: uppercase; }
.field input, .field select, .field textarea {
  width: 100%;
  min-height: 48px;
  padding: 12px 13px;
  color: var(--text);
  background: #07172b;
  border: 1px solid var(--line);
  border-radius: 6px;
  outline: none;
}
.field textarea { min-height: 150px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--gold); box-shadow: 0 0 0 3px rgba(245,197,24,.1); }
.form-note, .form-status { margin: 10px 0 0; color: var(--muted); font-size: .76rem; }
.form-status { min-height: 1.4em; color: var(--gold-soft); }
.form-status a { text-decoration: underline; }

/* CTA and footer */
.cta-band { padding: 0 0 clamp(60px, 8vw, 100px); }
.cta-band.cta-spaced { padding-top: clamp(52px, 6vw, 82px); }
.cta-panel {
  display: grid;
  min-height: 220px;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 30px;
  padding: clamp(34px, 5vw, 58px);
  color: var(--ink);
  background: var(--gold);
  border-radius: 24px 5px 24px 5px;
}
.cta-panel h2 { max-width: 770px; }
.cta-panel .btn { color: white; background: var(--ink); }
.site-footer { padding: 50px 0 22px; background: #01050c; border-top: 1px solid var(--line); }
.footer-grid { display: grid; grid-template-columns: 1.3fr .85fr .85fr; gap: 40px; padding-bottom: 36px; }
.footer-brand .brand { width: 186px; padding: 4px 8px; background: white; border-radius: 5px; }
.footer-brand p { max-width: 340px; margin: 13px 0 0; color: var(--muted); font-size: .84rem; }
.footer-col { display: grid; align-content: start; gap: 9px; }
.footer-col strong { margin-bottom: 5px; font-size: .75rem; letter-spacing: .1em; text-transform: uppercase; }
.footer-col a { width: fit-content; color: var(--muted); font-size: .83rem; }
.footer-col a:hover { color: var(--gold); }
.social-link { display: inline-flex; align-items: center; gap: 8px; }
.social-link img { width: 18px; height: 18px; object-fit: contain; }
.footer-bottom { display: flex; justify-content: space-between; gap: 20px; padding-top: 19px; color: #7f8b9a; border-top: 1px solid var(--line); font-size: .75rem; }
.footer-bottom div { display: flex; gap: 18px; }

/* Motion and accessibility */
.reveal { opacity: 0; transform: translateY(18px); transition: opacity .55s ease, transform .55s ease; }
.reveal.in { opacity: 1; transform: none; }

/* Cards inside horizontally-swiped carousels never got a fade-in: the
   IntersectionObserver that adds .in only fires once a card scrolls into
   view, so a card the user has just swiped to sits at opacity:0 for another
   .55s after landing — reads as "the next card isn't there". Scroll-triggered
   reveal only makes sense for vertical scrolling, so carousel items just
   show immediately instead. */
.feature-cards .reveal,
.scenario-track .reveal,
.testimonial-track .reveal,
.work-track .reveal,
.edition-grid .reveal {
  opacity: 1;
  transform: none;
  transition: none;
}
:focus-visible { outline: 3px solid var(--gold); outline-offset: 3px; }

@media (max-width: 1050px) {
  .site-nav {
    position: fixed;
    z-index: 101;
    top: var(--header);
    right: 0;
    bottom: 0;
    width: min(390px, 100%);
    height: auto;
    display: grid;
    align-content: start;
    gap: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 20px 24px max(24px, env(safe-area-inset-bottom));
    background: #fbfcfe;
    border-left: 1px solid var(--line-dark);
    box-shadow: -20px 20px 50px rgba(0,0,0,.18);
    visibility: hidden;
    transform: translateX(105%);
    transition: transform .25s ease, visibility 0s linear .25s;
  }
  .site-nav.open {
    visibility: visible;
    transform: none;
    transition: transform .25s ease;
  }
  .site-nav a { padding: 14px 2px; border-bottom: 1px solid var(--line-dark); font-size: .84rem; }
  .site-nav .site-nav-mobile-cta {
    display: inline-flex;
    min-height: 46px;
    justify-content: center;
    margin-top: 22px;
    padding: 0 20px;
    color: var(--ink);
    background: var(--gold);
    border: 0;
    border-radius: 4px;
    font-size: .75rem;
  }
  .site-nav a[aria-current="page"]::after { display: none; }
  .nav-toggle { display: block; }
  .nav-cta { margin-left: auto; }
  .home-hero-inner { grid-template-columns: minmax(0, 1fr) 340px; }
  .feature-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .edition-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .career-track { grid-template-columns: repeat(5, 220px); overflow-x: auto; padding-bottom: 15px; scroll-snap-type: x mandatory; }
  .career-stop { scroll-snap-align: start; }
}

@media (max-width: 760px) {
  :root { --header: 62px; }
  body { font-size: 14px; }
  .wrap { width: min(var(--max), calc(100% - 28px)); }
  .section { padding: 52px 0; }
  .section-tight { padding: 38px 0; }
  h1 { font-size: clamp(2.75rem, 12vw, 3.7rem); }
  h2 { font-size: clamp(2rem, 9.5vw, 2.85rem); }
  .lead { font-size: .95rem; }
  .brand { width: 143px; height: 42px; }
  .nav-cta { display: none; }
  .site-nav { top: var(--header); }
  .section-heading { display: block; margin-bottom: 24px; }
  .section-heading > p { margin-top: 13px; }
  .actions { margin-top: 22px; }
  .btn { min-height: 44px; padding-inline: 17px; }

  .home-hero { min-height: 620px; }
  .home-hero-inner { display: block; min-height: 558px; padding: 54px 0 24px; }
  .home-hero-copy { max-width: 92%; }
  .home-hero h1 { max-width: 9ch; font-size: clamp(2.8rem, 13vw, 3.65rem); line-height: .95; }
  .home-hero .lead { max-width: 30rem; margin-top: 15px; font-size: .9rem; line-height: 1.5; }
  .home-hero .actions .btn-secondary { display: none; }
  .hero-roster { position: absolute; right: 8px; bottom: 2px; width: 180px; height: 265px; opacity: .94; }
  .hero-player { right: 0; bottom: 9px; width: 168px; height: 246px; padding: 5px; border-radius: 14px 3px 14px 3px; }
  .hero-player img { height: 194px; border-radius: 10px 2px 7px 2px; }
  .hero-player footer { padding: 7px 3px 2px; }
  .hero-player footer img { width: 23px; height: 23px; }
  .hero-player small { font-size: .45rem; }
  .hero-player strong { font-size: .62rem; }
  .hero-player.is-next { opacity: 0; }
  .hero-controls { display: none; }

  .two-col, .story-grid, .studio-panel, .service-split, .pdf-feature, .contact-layout { grid-template-columns: 1fr; }
  .three-col, .four-col { grid-template-columns: 1fr; }
  .feature-cards {
    display: flex;
    gap: 11px;
    overflow-x: auto;
    padding: 2px 2px 13px;
    scroll-snap-type: x mandatory;
  }
  .feature-cards .ui-card { flex: 0 0 82vw; scroll-snap-align: start; }
  .app-feature-cards .ui-card { min-height: 235px; }
  .app-showcase { min-height: 455px; display: block; }
  .app-showcase-copy { width: 78%; padding: 28px 24px; }
  .app-showcase-copy h2 { font-size: 2.35rem; }
  .app-showcase-copy p { font-size: .84rem; }
  .app-showcase-visual { position: absolute; right: 0; bottom: 0; width: 47%; height: 72%; }
  .app-showcase-visual img { width: 145px; right: -4px; bottom: -7%; }
  .app-screen-stack { right: -8px; width: 59%; height: 76%; overflow: visible; }
  .app-screen-stack img { width: 126px; border-radius: 13px; }
  .app-screen-stack img:nth-child(1) { right: 45%; bottom: -5%; transform: rotate(-10deg) scale(.82); }
  .app-screen-stack img:nth-child(2) { right: -2%; bottom: -5%; transform: rotate(10deg) scale(.82); }
  .app-screen-stack img:nth-child(3) { right: 22%; bottom: -8%; transform: rotate(1deg); }
  .fact-strip { grid-template-columns: repeat(3, minmax(0,1fr)); }
  .fact { padding: 17px 10px; }
  .fact strong { font-size: 1.15rem; }
  .fact span { font-size: .54rem; line-height: 1.3; }
  .app-screen-track { gap: 14px; }
  .app-screen-track figure { min-width: 0; flex-basis: 78vw; }
  .app-screen-track figure > img { max-height: 560px; border-radius: 20px; }
  .scenario { flex-basis: 82vw; min-height: 300px; }
  .language-card { flex-basis: 173px; }
  .edition-grid { display: flex; overflow-x: auto; gap: 12px; padding-bottom: 14px; scroll-snap-type: x mandatory; }
  .edition-card { flex: 0 0 86vw; scroll-snap-align: start; }
  .cover-fan { min-height: 330px; }
  .cover-fan img { left: 18%; width: 47%; }
  .cover-fan img:nth-child(2) { left: 42%; }
  .cover-fan-three img { left: 8%; width: 43%; }
  .cover-fan-three img:nth-child(2) { left: 30%; }
  .cover-fan-three img:nth-child(3) { left: 53%; }
  .story-grid { gap: 25px; }
  .story-video { aspect-ratio: 4 / 3; object-position: center 8%; }
  .testimonial { flex-basis: 82vw; }
  .about-studio-cover { min-height: 280px; mask-image: linear-gradient(to bottom, #000 82%, transparent); }
  .studio-panel img { min-height: 250px; }
  .studio-panel-copy { padding: 28px 24px; }
  .service-image { min-height: 280px; mask-image: linear-gradient(to bottom, #000 80%, transparent); }
  .work-item { flex-basis: 84vw; }
  .process { display: flex; overflow-x: auto; padding-bottom: 12px; scroll-snap-type: x mandatory; background: transparent; border: 0; gap: 10px; }
  .process > div { flex: 0 0 72vw; border: 1px solid var(--line); scroll-snap-align: start; }

  .page-hero { min-height: 440px; padding: calc(var(--header) + 36px) 0 40px; background-position: 60% center; }
  .page-hero::before { background: linear-gradient(90deg, rgba(2,7,19,.97), rgba(2,7,19,.72) 78%, rgba(2,7,19,.2)), linear-gradient(0deg,var(--navy-950),transparent 44%); }
  .page-hero h1 { max-width: 10ch; font-size: clamp(2.75rem, 12vw, 3.7rem); }
  .page-hero .lead { max-width: 92%; }
  .hero-journey, .hero-about { background-position: 43% center; }
  .price { align-items: flex-start; flex-direction: column; gap: 2px; }
  .price strong { font-size: 2rem; }

  .journey-image, .career-track { display: none; }
  .journey-mobile { display: block; }
  .form-grid { grid-template-columns: 1fr; }
  .field.full { grid-column: auto; }
  .cta-panel { min-height: 0; grid-template-columns: 1fr; gap: 22px; padding: 32px 25px; }
  .cta-panel h2 { font-size: 2.2rem; }
  .cta-panel .btn { width: fit-content; }
  .footer-grid { grid-template-columns: 1fr; gap: 28px; }
  .footer-bottom { align-items: flex-start; flex-direction: column; }
}

@media (max-width: 390px) {
  .home-hero-copy { max-width: 100%; }
  .home-hero h1 { font-size: 2.72rem; }
  .home-hero .lead { max-width: 23ch; }
  .hero-roster { right: 6px; width: 168px; opacity: .9; }
  .app-showcase-copy { width: 88%; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
  .reveal { opacity: 1; transform: none; }
}

/* ==========================================================================
   Mobile and tablet corrections — 30 July
   Appended as overrides rather than edited in place, so the original rules
   stay readable and each fix below is traceable to what it changed.
   ========================================================================== */

@media (max-width: 900px) {
  /* The waitlist CTA was `display: none` here, so the one action that matters
     most vanished on exactly the devices most visitors use. It stays, sized
     down, pushed right so it sits beside the collapsed nav button. */
  .nav-cta {
    display: inline-flex !important;
    align-items: center;      /* vertically centres the label in the gold box */
    justify-content: center;
    margin-left: auto;
    margin-right: 10px;
    order: 2;                 /* before the toggle, which is order 3 */
    min-height: 38px;
    padding: 0 13px;
    font-size: .62rem;
    letter-spacing: .08em;
    line-height: 1;           /* stops the descender pushing text off-centre */
    white-space: nowrap;
  }

  .nav-toggle { order: 3; margin-left: 0; }

  /* The hero headline dominated the image behind it. Smaller, and wide enough
     to break as three lines — "Football language / for players / going
     abroad" — rather than one word per line. */
  .home-hero h1 {
    /* Narrow enough to break as three lines — "Football language / for players
       / going abroad" — which is how Foley wants it read. 15ch let the first
       two words share a line with "for". */
    max-width: 13ch;
    font-size: clamp(1.95rem, 8vw, 2.55rem);
    line-height: 1.04;
  }

  .page-hero h1 {
    font-size: clamp(1.85rem, 7.6vw, 2.45rem);
    line-height: 1.06;
  }

  /* The lead sat over the player card. Kept clear of it instead. */
  .home-hero .lead {
    max-width: 20rem;
    font-size: .82rem;
  }

  /* The website-development button was hidden on mobile, so half the studio's
     offer was invisible. Shown — and at the same weight as the waitlist
     button: a shrunken sibling read as a caption rather than an action. */
  .home-hero .actions { flex-wrap: wrap; gap: 9px; }
  .home-hero .actions .btn-secondary {
    display: inline-flex !important;
    min-height: 54px;
    padding-inline: 21px;
    font-size: .85rem;
  }

  /* The footer was one long column: brand, then every link, in a single
     stack. Two columns for the link groups keeps it scannable without
     shrinking the tap targets. */
  .footer-grid {
    grid-template-columns: 1fr 1fr;
    gap: 26px 20px;
    padding-bottom: 26px;
  }
  .footer-brand { grid-column: 1 / -1; }
  .footer-col { min-width: 0; }

  /* The career timeline and its checkpoints were hidden below 900px, so the
     journey read as disconnected cards with no thread between them. */
  .journey-mobile { display: block; }
  .journey-image { display: none; }
}

/* The footer logo carried trailing transparent space, leaving a gap after
   "DigiStudio" that read as a layout error. Cropped to the mark itself. */
.footer-brand img,
.site-footer .brand img {
  max-width: 168px;
  height: auto;
  object-fit: contain;
  object-position: left center;
}

/* An email icon beside the address, drawn in CSS so it costs no request and
   inherits the link colour. */
.footer-col a[href^="mailto:"],
.footer-brand a[href^="mailto:"] {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.footer-col a[href^="mailto:"]::before,
.footer-brand a[href^="mailto:"]::before {
  content: "";
  width: 15px;
  height: 11px;
  flex: 0 0 auto;
  border: 1.4px solid currentColor;
  border-radius: 2px;
  /* The diagonal pair reads as the flap of an envelope. */
  background:
    linear-gradient(to bottom right, transparent 44%, currentColor 44%, currentColor 52%, transparent 52%) no-repeat left top / 50% 100%,
    linear-gradient(to bottom left, transparent 44%, currentColor 44%, currentColor 52%, transparent 52%) no-repeat right top / 50% 100%;
  opacity: .85;
}

/* The contact and waitlist pages lost their left-hand card — nobody reads a
   list of bullet points when they came to send a message. With one child left,
   the two-column grid would leave the form in half the page beside dead space,
   so it becomes a single centred column. */
.contact-layout--single {
  grid-template-columns: minmax(0, 620px);
  justify-content: center;
}

/* ==========================================================================
   Pitch sections, headline breaks and PDF copy — 30 July, second pass
   ========================================================================== */

/* Headlines that were meant to break at a specific point. A span rather than
   a <br> so the break survives the line wrapping again on a narrow screen. */
h1 .line, h2 .line { display: block; }
/* The page-hero cap of 760px left the longest of these lines three pixels
   short, so it wrapped and put one word on a line of its own. Widened just
   enough to hold the line, and still well clear of the photograph. */
.page-hero h1.split-lines { max-width: 840px; }

/* The blue panels sat on top of the pitch photograph and hid it. Inside a
   pitch section the content now sits directly on the grass; everywhere else
   the panels are unchanged, because they are what separates the content from
   a flat background. */
.section-pitch .app-showcase,
.section-pitch .studio-panel {
  background: none;
  border: 0;
  border-radius: 0;
}
/* The phones were clipped at the panel's bottom edge. That read as a bleed
   while the panel was there to do the cutting; on open grass it just looked
   like a sliced photograph, so they now run to their full height and the
   section itself is the only thing that can clip them.
   Desktop only: below 1050px the copy stacks over the phones, and letting
   them out of the box puts a phone through the middle of the paragraph. */
@media (min-width: 1051px) {
  .section-pitch .app-showcase,
  .section-pitch .app-showcase-visual { overflow: visible; }
}

/* The padding existed to hold the copy off the edge of the panel. With no
   panel, it only pushes the copy out of line with everything else in the
   wrap, so the outer side goes. */
.section-pitch .app-showcase-copy { padding-left: 0; }
.section-pitch .studio-panel-copy { padding-right: 0; }
/* The photograph was square-cornered because the panel around it was doing
   the rounding. On its own it needs its own. */
.section-pitch .studio-panel img { border-radius: 20px; }

/* Same reasoning for the career stops on the About page: the dot and the gold
   thread already group them, so the boxes were only covering the pitch. */
.section-pitch .career-track .career-stop {
  padding-inline: 0;
  background: none;
  border: 0;
  border-radius: 0;
}
.section-pitch .career-track .career-stop::before { left: 2px; }

/* Below 1050px the phones were positioned over the copy: a paragraph, and on
   the home page the primary button, ran underneath a screenshot. The panel
   used to hide the worst of it behind its own gradient. With the panel gone
   they get a band of their own under the copy. */
@media (max-width: 1050px) {
  .section-pitch .app-showcase,
  .section-pitch .app-showcase-visual { overflow: visible; }
  /* The two-column grid only collapsed at 760px, so from 761 to 1050 the
     phones stayed in column two and ran straight through the copy. Dropping
     to a block here is what actually puts them underneath. */
  .section-pitch .app-showcase { display: block; min-height: 0; }
  .section-pitch .app-showcase-copy { width: 100%; padding-inline: 0; }
  /* Absolutely-positioned phones in a fixed-height band always overflowed it —
     the phones are ~410px tall and the band was 300px, so they reached back up
     into the copy. As a grid stack the band is exactly as tall as the phones,
     which makes touching the text impossible rather than merely unlikely. */
  .section-pitch .app-showcase-visual {
    position: relative;
    right: auto;
    bottom: auto;
    display: grid;
    place-items: center;
    width: 100%;
    height: auto;
    margin-top: 30px;
  }
  .section-pitch .app-screen-stack img {
    position: relative;
    right: auto;
    bottom: auto;
    grid-area: 1 / 1;
    width: min(46vw, 196px);
    height: auto;
  }
  .section-pitch .app-screen-stack img:nth-child(1) { transform: translateX(-56%) rotate(-10deg) scale(.86); }
  .section-pitch .app-screen-stack img:nth-child(2) { transform: translateX(56%) rotate(10deg) scale(.86); }
  .section-pitch .app-screen-stack img:nth-child(3) { transform: rotate(1deg); }
}

/* A short h2 in the two-column heading left a wide gap before the price. In
   the compact (single-column) form the price sits under the heading, which is
   where a buyer looks for it anyway.
   `justify-self: end` came from the two-column rule and is not inert here —
   Chrome now honours box alignment in block layout too, which pushed the line
   290px to the right of the heading it belongs to. */
.section-heading.compact > p {
  justify-self: start;
  margin-top: 14px;
}
/* --muted is a light grey for the dark sections. On the ice background it was
   barely legible, and this line carries the price. */
.section-ice .section-heading > p { color: #47566b; }

/* ==========================================================================
   Third pass — hero stack, video control, screen tour
   ========================================================================== */

/* --- Home hero ----------------------------------------------------------- */

/* The copy sat low enough that the waitlist button fell near the fold. Less
   room above it lifts the whole block, button included. */
.home-hero-inner { padding-top: 34px; }

/* The lead broke to three lines. Wide enough for two, and still clear of the
   card, which starts further right than this ends. */
.home-hero .lead { max-width: 660px; }

/* The card behind the active one was offset far enough to read as two cards
   side by side. Pulled in tight so it reads as a stack with one card on top —
   and deliberately less of it showing than the app screens fan out. */
.hero-player.is-next {
  opacity: .5;
  transform: translate(24px, 9px) rotate(2.5deg) scale(.95);
}
.hero-player.is-third { display: none; }

/* Three cards in the stack means up to five are on screen during a change —
   the two leaving and the three arriving. At .55s that read as a pile of
   ghosts. The fade is now quick and the movement keeps the slower easing. */
.hero-player { transition: opacity .26s ease, transform .55s ease; }

/* Moved the roster in from the right edge so the copy and the cards are not
   fighting for the same corner. */
@media (min-width: 901px) {
  .hero-player { right: 11%; }
  .hero-controls { right: 13%; }
}

/* --- The video play control ---------------------------------------------- */

/* The triangle was dead centre, which put it over Foley's face. Moved down
   into the lower third, where it covers the pitch instead. */
.video-cover > span {
  /* Percentage margins resolve against the container's *width*, which threw
     the button clean out of a landscape frame. Positioned against the height
     instead: 68% down puts it on the pitch below Foley's face. */
  position: absolute;
  z-index: 2;
  top: 68%;
  left: 50%;
  display: grid;
  width: 62px;
  height: 62px;
  place-items: center;
  padding-left: 4px;          /* optical centring — a triangle is left-heavy */
  color: var(--ink);
  background: var(--gold);
  border-radius: 50%;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .45);
  font-size: 1.25rem;
  line-height: 1;
  transform: translate(-50%, -50%);
  transition: transform .2s ease;
}
.video-cover:hover > span { transform: translate(-50%, -50%) scale(1.07); }
.video-cover > img { position: absolute; inset: 0; }

/* --- Inside TFLSK: copy and phones ---------------------------------------- */

/* Side by side, a gutter is reserved between the columns rather than trusting
   the phones to be positioned clear of the text. At 1051px the copy column is
   at its narrowest and the gap was down to 39px. */
@media (min-width: 1051px) {
  .section-pitch .app-showcase { align-items: center; }
  .section-pitch .app-showcase-copy { padding-right: 56px; }

  /* The phone stack hung off the bottom of its column. Against two lines of
     copy that read as a deliberate bleed; against a seven-item list it read
     as three phones sliding off the page. Centred on the copy instead. */
  .app-showcase--tall .app-screen-stack img { top: 50%; bottom: auto; }
  .app-showcase--tall .app-screen-stack img:nth-child(1) { transform: translateY(-50%) rotate(-10deg) scale(.88); }
  .app-showcase--tall .app-screen-stack img:nth-child(2) { transform: translateY(-50%) rotate(10deg) scale(.88); }
  .app-showcase--tall .app-screen-stack img:nth-child(3) { transform: translateY(-50%) rotate(1deg); }
}

/* --- The screen tour ------------------------------------------------------ */

.app-screen-track figcaption em {
  justify-self: start;
  margin-top: 2px;
  padding: 3px 9px;
  color: #6b5a12;
  background: rgba(245, 197, 24, .22);
  border-radius: 999px;
  font-size: .66rem;
  font-style: normal;
  font-weight: 800;
  letter-spacing: .07em;
  text-transform: uppercase;
}
/* Placeholders are flat mock-ups, not photographs — the heavy drop shadow read
   as a claim that they were real captures. */
.app-screen-track figure.is-placeholder > img {
  background: #0a1628;
  box-shadow: 0 10px 26px rgba(5, 22, 47, .14);
}

/* --- Phone and tablet hero ------------------------------------------------
   The hero used to end partway down the first screen, with the card crammed
   into the right margin on top of the web-development button. It now owns the
   whole first screen: copy at the top, then the roster centred underneath as
   a three-card stack, fanned the same way as the app screens.
   -------------------------------------------------------------------------- */

@media (max-width: 900px) {
  .home-hero { min-height: 100svh; }
  /* Every property below is one the 760px block also sets. Naming them all is
     what makes this override actually take — leaving `display` out was enough
     to keep the old absolutely-positioned roster in the right margin. */
  .home-hero-inner {
    display: grid;
    /* min-height, not height: a fixed 100svh cap left no room for the roster
       once the copy (long headline + stacked buttons) grew past the fold on
       narrow phones, forcing the card back over the buttons. Letting the
       section grow keeps the two from ever colliding. */
    min-height: 100svh;
    height: auto;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
    gap: 0;
    padding: 22px 0 26px;
  }
  .home-hero-copy { max-width: 100%; }

  /* Two lines rather than three. The card is below the copy now, so the line
     can use the full width without running into anything. */
  .home-hero .lead {
    max-width: 100%;
    margin-top: 14px;
    font-size: .88rem;
  }

  /* The web-development button goes under the primary action instead of
     beside it — side by side, it was being covered by the card. */
  .home-hero .actions { flex-direction: column; align-items: flex-start; gap: 10px; }
  .home-hero .actions .btn { width: 100%; max-width: 320px; }

  /* Centred, and as large as the space under the copy allows. */
  .hero-roster {
    position: relative;
    right: auto;
    bottom: auto;
    display: grid;
    grid-template-rows: minmax(0, 1fr) auto;
    width: 100%;
    height: auto;
    min-height: 0;
    place-items: center;
    margin-top: 14px;
    opacity: 1;
    /* JS drives the horizontal swipe (site.js) and decides for itself when
       a drag is horizontal vs. the page just being scrolled — this only
       needs to stop the browser claiming the gesture before JS sees it. */
    touch-action: pan-y;
  }
  .hero-player {
    position: relative;
    right: auto;
    bottom: auto;
    grid-area: 1 / 1;
    width: min(66vw, 252px);
    /* Sized off the viewport, not the grid row's percentage height — against
       an auto-height row that resolves to nothing reliable and was how the
       card ended up oversized and overlapping the buttons above it. */
    height: min(40svh, 392px);
    padding: 7px;
    border-radius: 18px 4px 18px 4px;
  }
  .hero-player img { height: calc(100% - 54px); border-radius: 13px 2px 9px 2px; }
  /* The card is roughly half as big again as the old corner version, so the
     label scales with it rather than staying at 7px. */
  .hero-player footer { padding: 9px 5px 3px; }
  .hero-player footer img { width: 29px; height: 29px; }
  .hero-player small { font-size: .55rem; }
  .hero-player strong { font-size: .76rem; }

  /* Fanned left and right behind the active card, like the app screens. */
  .hero-player.is-active { transform: rotate(0) scale(1); }
  .hero-player.is-next {
    z-index: 2;
    opacity: .62;
    transform: translate(34px, 12px) rotate(7deg) scale(.93);
  }
  .hero-player.is-third {
    z-index: 1;
    display: block;
    opacity: .38;
    transform: translate(-34px, 12px) rotate(-7deg) scale(.93);
  }

  /* The dots were hidden below 760px, which left the carousel with no visible
     control and no signal that there was more than one edition. */
  .hero-controls {
    position: relative;
    right: auto;
    bottom: auto;
    display: flex;
    justify-content: center;
    margin-top: 26px;
  }
  .hero-control { width: 30px; height: 4px; }
}

/* Landscape phones are shorter than the stack needs — let the hero grow
   rather than crushing the card into the copy. */
@media (max-width: 900px) and (max-height: 620px) {
  .home-hero, .home-hero-inner { height: auto; min-height: 0; }
  .hero-player { height: 340px; }
}

/* ==========================================================================
   Fourth pass — 30 July
   ========================================================================== */

/* The pitch sections had a black gradient top and bottom that swallowed the
   photograph. The pitch is the point, so it stays visible. */
.section-pitch::after { display: none; }

/* --- Home hero: centred, larger, buttons stacked in the middle ----------- */

.home-hero-copy { text-align: center; }
.home-hero h1 {
  max-width: 18ch;
  margin-inline: auto;
  font-size: clamp(3.9rem, 7vw, 6.6rem);
  line-height: .98;
}
.home-hero .lead { max-width: 46ch; margin-inline: auto; }
.home-hero .actions { justify-content: center; }
.home-hero .eyebrow { justify-content: center; }

/* --- Nav ------------------------------------------------------------------ */

/* The collapsed menu repeated the waitlist button that already sits in the
   header bar beside it. */
.site-nav-mobile-cta { display: none !important; }

/* "Start a project" reads as the quiet option in white outline. Navy gives it
   the weight of a real second action on a light background. */
.section-ice .btn-secondary,
.page-hero .btn-secondary {
  color: var(--navy-950);
  background: transparent;
  border-color: var(--navy-950);
  border-width: 2px;
}
.section-ice .btn-secondary:hover,
.page-hero .btn-secondary:hover { color: var(--white); background: var(--navy-950); }

/* --- Form pages: get the form onto the first screen ---------------------- */

/* A contact form below the fold is a contact form nobody fills in. */
.hero-contact, .hero-waitlist { min-height: 0; padding-bottom: 26px; }
.hero-contact + .section, .hero-waitlist + .section { padding-top: 26px; }

/* --- Footer email icon --------------------------------------------------- */

/* Instagram and TikTok are gold; the envelope was inheriting the link colour
   and looked like a different class of thing. */
.footer-col a[href^="mailto:"]::before,
.footer-brand a[href^="mailto:"]::before { color: var(--gold); opacity: 1; }

/* --- Horizontal tracks: show the next card ------------------------------- */

/* A row of cards that ends flush at the viewport edge looks like the end of
   the row. Each card is narrowed so the next one is always part-visible,
   which is the only affordance telling you it scrolls. */
.scenario-track > *   { flex: 0 0 clamp(230px, 27%, 320px); }
/* Three cards fitted exactly at desktop, so nothing was cut and the row read
   as complete. Sized so the third is always part-visible. */
.testimonial-track > * { flex: 0 0 clamp(260px, 36%, 400px); }
.work-track > *        { flex: 0 0 clamp(270px, 42%, 470px); }

/* --- Edition cards: price badge, no dead column -------------------------- */

/* 42%/1fr left a wide empty gutter beside three short lines of text. */
.edition-card { grid-template-columns: 38% 1fr; gap: 14px; align-items: center; }
.edition-card span { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.edition-price {
  align-self: flex-start;
  margin: 8px 0 6px;
  padding: 5px 12px;
  color: var(--ink);
  background: var(--gold);
  border-radius: 999px;
  font-size: .95rem;
  font-weight: 900;
  letter-spacing: -.01em;
}

/* --- About: one journey, at every width ---------------------------------- */

/* Previously there were two: a desktop timeline and a separate mobile block
   with its own image and card stack. At tablet widths both were visible at
   once — gold thread above the photo, blue cards below it. There is now one
   treatment: photo, then the thread with its dots, then the text. */
.journey-image { display: block; }
.career-track {
  grid-template-columns: repeat(6, minmax(0, 1fr));
  padding-top: 34px;
}
/* No card, at any width. The dot and the thread do the grouping. */
.career-stop {
  min-height: 0;
  padding: 0 14px 0 0;
  background: none;
  border: 0;
  border-radius: 0;
}
.career-stop::before { left: 0; }
.career-stop span { margin-bottom: 20px; }

@media (max-width: 1050px) {
  /* Below this the six stops cannot share a row legibly, so the thread
     becomes a scroller. The dots stay — they are the timeline. */
  .career-track {
    grid-template-columns: repeat(6, 66vw);
    max-width: 100%;
    overflow-x: auto;
    overscroll-behavior-inline: contain;
    gap: 18px;
    padding-bottom: 12px;
    scroll-snap-type: x mandatory;
  }
  .career-stop { scroll-snap-align: start; }
  .career-track::before { right: 0; left: 0; }
}
@media (min-width: 761px) {
  /* The hint only applies while the track actually scrolls. */
  .journey-image + .career-track + .scroll-hint { display: none; }
}
@media (max-width: 1050px) and (min-width: 761px) {
  .journey-image + .career-track + .scroll-hint { display: block; }
}
@media (max-width: 760px) {
  .career-track { grid-template-columns: repeat(6, 80vw); }
}

/* --- Mobile: centre everything, and show more of the hero photo ---------- */

@media (max-width: 900px) {
  /* Superseded in pass 5 — see the measured brightness note there. The photo
     is black on its left half, so pulling left hid it completely. */

  .home-hero-copy,
  .page-hero .wrap { text-align: center; }
  .home-hero .eyebrow,
  .page-hero .eyebrow { justify-content: center; }
  .home-hero h1,
  .page-hero h1,
  .home-hero .lead,
  .page-hero .lead { margin-inline: auto; }
  .home-hero .actions,
  .page-hero .actions { justify-content: center; align-items: center; }
  .home-hero .actions .btn,
  .page-hero .actions .btn { margin-inline: auto; }

  /* The split headlines lose their forced break when centred and narrow —
     a two-word line under a centred block reads as a mistake. */
  .page-hero h1.split-lines { max-width: 100%; }
  .page-hero h1.split-lines .line { display: inline; }
}

/* --- The studio panel now carries the logo, not a photograph ------------- */

.studio-panel-logo {
  align-self: center;
  width: min(78%, 300px);
  min-height: 0;
  height: auto;
  margin-inline: auto;
  padding: 22px;
  background: var(--white);
  border-radius: 20px;
  object-fit: contain;
}

/* Keeps a two-word phrase together when the headline wraps. */
.nowrap { white-space: nowrap; }

/* Evens the ragged last line on the centred hero headline. */
.home-hero h1 { text-wrap: balance; }

/* The cover is the product, and it was giving up half the card to a column of
   whitespace. Bigger cover, tighter text block. */
.edition-card { grid-template-columns: 47% 1fr; gap: 16px; padding: 15px; }
.edition-card h3 { margin: 4px 0 0; font-size: clamp(1.05rem, 1.6vw, 1.35rem); }
.edition-card > img { border-radius: 9px; }

@media (max-width: 900px) {
  /* Bigger than it was, but the hero has to end at the fold with the card
     whole — the desktop clamp pushed the roster off the bottom. */
  .home-hero h1 {
    max-width: 16ch;
    font-size: clamp(2.5rem, 10.5vw, 3.4rem);
    line-height: 1;
  }
  .home-hero .lead { font-size: .9rem; }
}

/* ==========================================================================
   Pass 5 — 30 July 2026
   Foley's review: the hero photograph was invisible under its own scrim,
   centring was inconsistent between the hero and everything below it, and
   three components carried dead space.
   ========================================================================== */

/* --- Hero: let the photograph be seen ------------------------------------ */

/* The old scrim ran to 97% opacity at the left edge, which is not a tint —
   it is a wall. The headline still needs contrast, so this keeps an even,
   much lighter wash plus a bottom fade to carry the CTA row, rather than a
   heavy left-to-right gradient that hid the half of the image the subject
   is standing in. */
.home-hero::before {
  background:
    linear-gradient(180deg, rgba(2, 7, 19, .34) 0%, rgba(2, 7, 19, .30) 45%, rgba(2, 7, 19, .62) 100%);
}

/* Pushed RIGHT, not left. Pass 4 moved this to 30% on the theory that the
   subject sat right of centre — the opposite was true. Measured column
   brightness across stadium-hero-v2.webp: the left half is 8-11/255, which is
   effectively black, and the floodlit stands and pitch only start around 60%.
   On a phone the hero is ~430x1400 against a 1672x941 image, so `cover` crops
   to a ~17% vertical strip; at 30% that strip was pure black, which is why the
   photograph looked missing rather than dark.

   Horizontal position is a no-op on a wide desktop viewport (the image fits
   the width exactly and only the vertical is cropped), so one value is safe at
   every size. */
.home-hero { background-position: 76% center; }

/* With a lighter scrim the text is doing the work on its own, so it gets a
   shadow rather than a heavier background. */
.home-hero h1,
.home-hero .lead { text-shadow: 0 2px 18px rgba(2, 7, 19, .58); }

/* --- Centre headline blocks and their buttons, site-wide ------------------ */

/* The home hero was centred in pass 4 and the rest of the site was not, so
   every other page read as misaligned against it. Scoped to headline blocks
   and action rows — centring body copy, lists and card internals as well
   would hurt readability rather than help it. */
.page-hero .wrap,
.section-heading,
.cta-panel,
.section-heading.compact { text-align: center; }

.page-hero .eyebrow,
.section-heading .eyebrow { justify-content: center; }

.page-hero h1,
.page-hero .lead,
.section-heading h2,
.section-heading p,
.cta-panel h2 { margin-inline: auto; }

.page-hero .actions,
.section-heading .actions,
.cta-panel { justify-content: center; }

.page-hero .actions { align-items: center; }

/* The CTA band is a two-column grid (headline | button). Centred, it reads
   better stacked. */
.cta-panel {
  grid-template-columns: 1fr;
  justify-items: center;
  gap: 22px;
}

/* --- The video play control: centred on the frame ------------------------ */

/* Pass 4 pushed this to 68% to clear Foley's face. The cover image is now the
   studio shot, so dead centre is right again. */
.video-cover > span { top: 50%; }

/* --- The studio logo panel ----------------------------------------------- */

/* The logo was filling its panel edge to edge — and the pass-4 rule that was
   meant to stop that never applied: `.studio-panel img` is specificity 0-1-1
   and `.studio-panel-logo` is 0-1-0, so the generic photo rule (width 100%,
   height 100%, min-height 380px, object-fit cover) won every time. The mark
   was being cover-cropped to a photograph's dimensions. Qualified by element
   so it actually lands. */
.studio-panel img.studio-panel-logo {
  width: min(68%, 258px);
  height: auto;
  min-height: 0;
  padding: 18px;
  object-fit: contain;
  align-self: center;
  /* Ranged to the inner edge of its half rather than centred in it: the mark
     and "The company behind TFLSK." belong together, and centring each in its
     own column left a corridor of dead space between them. */
  margin-inline: auto 0;
}

@media (min-width: 901px) {
  /* Close the gap from the copy side too — the panel's own padding was holding
     the text off the logo by another 60px. */
  .studio-panel .studio-panel-copy { padding-left: clamp(20px, 2.6vw, 34px); }
}

/* --- Edition cards: the dead space on the right -------------------------- */

/* The cover sat in a 47% column against a text column that only needed about
   half of what was left, so every card carried a band of empty white down its
   right edge. Tightening the image column and letting the text start hard
   against it closes the gap. */
.edition-card {
  grid-template-columns: 40% 1fr;
  gap: 12px;
  padding: 13px;
  align-items: center;
}
.edition-card > * { min-width: 0; }
.edition-card h3 { margin: 3px 0 0; }
.edition-card span { gap: 3px; }

/* --- The closing CTA band ------------------------------------------------ */

/* On desktop the panel sat flush against the pitch photograph above it, so
   the heading looked like part of the image rather than a separate band. */
@media (min-width: 901px) {
  .cta-band { padding-top: clamp(64px, 7vw, 104px); }
}

/* --- Inside TFLSK: screens directly under the title ---------------------- */

/* The screens were a second grid column, so on a tall section they sat level
   with the middle of the bullet list — below the fold on a laptop. They now
   follow the headline and precede the list, which is the order Foley reads it
   in. One column, so the base grid's second track is dropped. */
.app-showcase--stacked,
.section-pitch .app-showcase--stacked {
  display: block;
  min-height: 0;
}
.app-showcase--stacked .app-showcase-copy {
  width: 100%;
  max-width: 100%;
  padding-inline: 0;
  text-align: center;
}
.app-showcase--stacked .eyebrow { justify-content: center; }

/* The three phones become a real row rather than absolutely-positioned
   overlaps — a fanned stack needs a container height to overlap inside, and
   this one is sized by its content. */
.app-screen-row {
  position: static;
  display: flex;
  overflow: visible;
  justify-content: center;
  align-items: flex-end;
  gap: clamp(10px, 2.4vw, 30px);
  margin: clamp(26px, 4vw, 44px) auto clamp(24px, 3.5vw, 40px);
  perspective: none;
}
.app-screen-row img,
.section-pitch .app-screen-row img,
.app-showcase--tall .app-screen-row img {
  position: static;
  top: auto;
  right: auto;
  bottom: auto;
  width: min(30%, 232px);
  height: auto;
  border-radius: 18px;
  filter: drop-shadow(0 26px 40px rgba(0, 0, 0, .42));
  transform: none;
}
/* A slight fan keeps it from looking like a stock three-up, without the
   absolute positioning the old stack needed. Qualified by the wrapper because
   `.section-pitch .app-screen-stack img:nth-child(n)` is 0-3-1 and would
   otherwise keep applying the old 10-degree overlap fan. */
.app-showcase--stacked .app-screen-row img:nth-child(1) { transform: rotate(-4deg) translateY(8px); }
.app-showcase--stacked .app-screen-row img:nth-child(2) { transform: none; }
.app-showcase--stacked .app-screen-row img:nth-child(3) { transform: rotate(4deg) translateY(8px); }

/* The bullets read better as a centred two-column block under a centred
   headline than as one long ragged list. */
.app-showcase--stacked .tick-list {
  display: grid;
  max-width: 900px;
  margin-inline: auto;
  gap: 10px 34px;
  text-align: left;
}
@media (min-width: 760px) {
  .app-showcase--stacked .tick-list { grid-template-columns: 1fr 1fr; }
}

/* --- Mobile hero: the photograph, actually visible ------------------------ */

/* A 1672x941 landscape photo cannot fill a ~430x1450 portrait hero without
   `cover` reducing it to a 17%-wide sliver — and with an exact height fit that
   sliver includes the image's black bottom fifth.

   Measured, so this is not guesswork: the brightest strip sits at 96% across
   (the floodlit stand), where the band 20-40% down reads 118/255 while the
   bottom 20% reads 12 and 4. Overshooting the height to 132% crops that dead
   bottom off and puts the lit stand behind the headline, and 94% across keeps
   the strip on the bright side of the frame.

   Desktop is untouched: there the image fits the width exactly, only the
   vertical is cropped, and it already reads well. */
@media (max-width: 900px) {
  .home-hero {
    background-size: auto 132%;
    background-position: 94% 18%;
  }

  /* With a legible photograph behind it the headline needs the contrast back,
     but as a soft vertical wash rather than the wall this started as. */
  .home-hero::before {
    background:
      linear-gradient(180deg, rgba(2, 7, 19, .46) 0%, rgba(2, 7, 19, .34) 38%, rgba(2, 7, 19, .70) 100%);
  }
}

/* ==========================================================================
   Pass 6 — 30 July 2026
   The journey rebuilt, plus card width, button contrast and navigation aids.
   ========================================================================== */

/* --- Edition cards: narrower, so the text is not swimming ---------------- */

/* Pass 5 tightened the image column but left the card at full grid width, so
   the copy still had more room than it needed. Capping the card is what
   actually removes the empty right-hand band. */
/* Narrow the *column*, not the card. `max-width` + `margin-inline: auto` on a
   grid item switches it from stretch to fit-content alignment, and the card's
   `width: 100%` cover image then has no definite width to resolve against —
   the whole card collapsed to 133px. Sizing the track keeps the item stretched
   and does the same job. */
.edition-grid {
  grid-template-columns: repeat(3, minmax(0, 336px));
  justify-content: center;
}
.edition-card { grid-template-columns: 38% 1fr; }

/* --- "View selected work": legible on its band --------------------------- */

/* "View selected work" sits in the services hero, which is a dark photograph.
   Pass 4 had given every secondary button navy text on a transparent navy
   outline — correct on the light `.section-ice` bands, invisible on a dark
   hero. Split by background rather than styled once for both. */
.page-hero .btn-secondary {
  color: var(--navy-950);
  background: var(--white);
  border-color: var(--white);
}
.page-hero .btn-secondary:hover {
  color: var(--navy-950);
  background: #eef2f7;
  border-color: #eef2f7;
}

/* --- Back to top --------------------------------------------------------- */

.to-top {
  position: fixed;
  z-index: 60;
  right: clamp(14px, 2.5vw, 26px);
  bottom: clamp(14px, 2.5vw, 26px);
  display: grid;
  width: 46px;
  height: 46px;
  place-items: center;
  padding: 0;
  color: var(--navy-950);
  background: var(--gold);
  border: 0;
  border-radius: 50%;
  box-shadow: 0 10px 26px rgba(2, 7, 19, .34);
  cursor: pointer;
  /* Hidden but still in the layout, so showing it cannot shift the page. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
}
.to-top.is-visible { opacity: 1; visibility: visible; transform: none; }
.to-top:hover { background: #ffd75a; }
.to-top svg { width: 22px; height: 22px; }
.to-top:focus-visible { outline: 3px solid var(--white); outline-offset: 3px; }

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

/* --- Back link ----------------------------------------------------------- */

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 4px;
  color: var(--muted);
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: .02em;
  text-decoration: none;
}
.back-link::before { content: "←"; font-size: .95rem; }
.back-link:hover { color: var(--gold); }
.back-link:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

/* ==========================================================================
   Pass 7 — 30 July 2026
   ========================================================================== */

/* --- My journey: one photograph, timeline aligned to its five panels ------ */

/* Foley wanted the panorama whole again, not sliced. So the image stays in one
   piece and the timeline sits beneath it as a five-column grid across exactly
   the same width — each column is one fifth, so a centred dot lands on the
   centre of its panel by arithmetic rather than by eye.

   The image and the track share a scroll container. On a phone that means one
   swipe moves both together and the dots can never drift out of register with
   the picture, which is what splitting the file was working around. */
.journey { margin-top: clamp(24px, 3.5vw, 38px); }

.journey-scroll {
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  /* Promotes the scroller to its own compositor layer — without it,
     dragging the large panorama image repaints on the main thread and
     reads as laggy. */
  will-change: scroll-position;
  contain: layout paint;
}
.journey-scroll::-webkit-scrollbar { display: none; }

.journey-inner { width: 100%; }

.journey-pano {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, .09);
}

.journey-track {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  margin: 0;
  padding: 0;
  list-style: none;
}

.journey-stop {
  position: relative;
  padding: 0 clamp(6px, 1vw, 14px);
  text-align: center;
}

/* The connecting rule is drawn per column so it cannot fall out of step with
   the columns when the container scrolls. */
.journey-stop::before {
  position: absolute;
  top: 16px;
  right: 0;
  left: 0;
  height: 2px;
  content: "";
  background: rgba(245, 197, 24, .5);
}
.journey-stop:first-child::before { left: 50%; }
.journey-stop:last-child::before  { right: 50%; }

.journey-stop__dot {
  position: relative;
  z-index: 1;
  display: block;
  width: 13px;
  height: 13px;
  margin: 10px auto 12px;
  background: var(--gold);
  border-radius: 50%;
  box-shadow: 0 0 0 4px #0b3c21;
}

.journey-stop__num {
  display: block;
  color: var(--gold);
  font-size: .67rem;
  font-weight: 900;
  letter-spacing: .12em;
}
.journey-stop h3 { margin: 5px 0 0; font-size: clamp(.98rem, 1.35vw, 1.2rem); }
.journey-stop p {
  margin: 7px auto 0;
  max-width: 26ch;
  color: #c7d0dc;
  font-size: .8rem;
  line-height: 1.5;
}

@media (max-width: 900px) {
  /* Below this the panorama is unreadable at viewport width, so the strip gets
     a floor and scrolls — image and timeline together, still in register. */
  .journey-inner { width: 940px; }
  .journey-stop p { font-size: .76rem; }
}

@media (min-width: 901px) {
  .journey + .scroll-hint { display: none; }
}

/* --- Inside TFLSK: a fanned stack, as on the home page ------------------- */

/* Back to overlapping at an angle, but sized and offset so all three read —
   the earlier version put every phone in one grid cell with no offset, which
   is why only the top one was visible. */
.app-screen-fan {
  position: relative;
  display: block;
  width: 100%;
  height: clamp(300px, 44vw, 470px);
  /* The two outer screens are rotated within an overflow:visible box, so
     their bounding box runs past the declared height — the old bottom
     margin (22-36px) wasn't enough clearance and the tick-list text below
     read as jammed against them. */
  margin: clamp(26px, 4vw, 44px) 0 clamp(40px, 5.5vw, 60px);
  overflow: visible;
}
.section-pitch .app-showcase--stacked .app-screen-fan { display: block; height: clamp(300px, 44vw, 470px); }

.app-screen-fan img,
.section-pitch .app-showcase--stacked .app-screen-fan img,
.app-showcase--tall .app-screen-fan img {
  position: absolute;
  top: 0;
  left: 50%;
  grid-area: auto;
  width: clamp(148px, 21vw, 226px);
  height: auto;
  border-radius: 18px;
  filter: drop-shadow(0 26px 42px rgba(0, 0, 0, .5));
}
/* Outer two sit behind and lean away; the centre one is upright and on top. */
.app-screen-fan img:nth-child(1) { z-index: 1; transform: translateX(-104%) rotate(-9deg) scale(.9); }
.app-screen-fan img:nth-child(2) { z-index: 1; transform: translateX(4%)    rotate(9deg)  scale(.9); }
.app-screen-fan img:nth-child(3) { z-index: 2; transform: translateX(-50%)  rotate(1deg); }

/* --- Edition cards: narrower, and never clipped -------------------------- */

/* Fixed 336px tracks overflowed the wrap once the gap was counted, so the
   right-hand card was cut. `auto-fit` + `minmax` lets the browser size them
   against the space that actually exists. */
.edition-grid {
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  justify-content: center;
  max-width: 1010px;
  margin-inline: auto;
}
/* Six languages in two rows of three, with the bundle on its own row beneath —
   seven cards never divide evenly, so the odd one out is the one that should
   stand apart anyway. */
@media (min-width: 901px) {
  .edition-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .edition-card--bundle { grid-column: 2; }
}
.edition-card { grid-template-columns: 38% 1fr; }

/* The bundle has no cover of its own, so it gets a mark rather than a
   stretched-out placeholder image. */
.edition-card--bundle .edition-bundle-mark {
  display: grid;
  aspect-ratio: 2 / 3;
  place-content: center;
  gap: 2px;
  padding: 8px;
  text-align: center;
  background: linear-gradient(160deg, var(--navy-950), #16324f);
  border-radius: 7px;
}
.edition-card--bundle .edition-bundle-mark strong {
  color: var(--gold);
  font-size: 1.45rem;
  line-height: 1;
}
.edition-card--bundle .edition-bundle-mark small {
  color: #b9c6d6;
  font-size: .58rem;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
}

/* --- Back arrow ---------------------------------------------------------- */

/* Moved out of the hero: it belongs to the page, not to the headline block,
   and inside a centred hero it read as part of the copy. */
.page-back { padding: clamp(14px, 2vw, 22px) 0 0; }
.page-back .wrap { padding: 0; }
.back-link {
  display: inline-grid;
  width: 42px;
  height: 42px;
  margin-left: max(18px, calc((100vw - 1180px) / 2));
  place-items: center;
  color: var(--navy-950);
  background: var(--gold);
  border-radius: 50%;
  text-decoration: none;
  transition: transform .16s ease, background .16s ease;
}
.back-link::before { content: none; }
.back-link svg { width: 21px; height: 21px; }
.back-link:hover { background: #ffd75a; transform: translateX(-2px); }
.back-link:focus-visible { outline: 3px solid var(--gold); outline-offset: 3px; }

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

/* --- Brand lockup -------------------------------------------------------- */

/* Bigger on desktop, and the mark now sits close to the wordmark: the 50px
   gap between them was baked into the artwork, where letter gaps are 7-9px, so
   no amount of CSS would have closed it. Retightened to 18px in a new file
   (`-tight`) and the outer padding trimmed from 60px to 8px, which is what
   makes the same box render a visibly larger logo. */
@media (min-width: 901px) {
  .brand { width: 232px; height: 58px; }
}

/* --- Headline alignment, desktop ---------------------------------------- */

/* Pass 5 centred `.section-heading` and `.page-hero`, and this rule pulled the
   two-column panels in with them. The story and studio panels sit BESIDE an
   image, so centring their prose left a ragged column floating in the middle of
   its half — they read correctly ranged left against the image edge. The
   showcase and PDF blocks are full-width and stay centred. */
@media (min-width: 901px) {
  .app-showcase-copy,
  .pdf-feature-copy { text-align: center; }

  .app-showcase-copy .eyebrow,
  .pdf-feature-copy .eyebrow { justify-content: center; }

  .app-showcase-copy h2, .app-showcase-copy p,
  .pdf-feature-copy h2, .pdf-feature-copy p { margin-inline: auto; }

  .app-showcase-copy .actions,
  .pdf-feature-copy .actions { justify-content: center; }

  /* Bullet lists stay left-aligned inside a centred block — centred list items
     with a tick marker are genuinely hard to scan. */
  .app-showcase-copy .tick-list,
  .story-copy .tick-list { text-align: left; }
}

/* --- Video ---------------------------------------------------------------- */

/* The cover is restored on pause and on end, so a paused video shows the
   poster again rather than a frozen frame. */
.story-video-shell { position: relative; }
.video-cover[hidden] { display: none; }

/* --- Headings: centred on the page, not inside their own column ---------- */

/* Two separate reasons the titles read as "more left":
   - `.section-heading` is a two-column grid (headline | standfirst), so the
     headline was centred within column one, which sits left of the page centre.
   - `.section-heading.compact` has `max-width: 760px` and no auto margin, so
     the whole block was pinned to the left edge of a 1180px wrap and its
     centred text landed ~230px left of true centre.
   Collapsing both to one centred column fixes them together. */
.section-heading {
  display: block;
  max-width: 900px;
  margin-inline: auto;
}
.section-heading > p {
  justify-self: auto;
  max-width: 620px;
  margin: 14px auto 0;
}
.section-heading.compact { max-width: 820px; margin-inline: auto; }

/* Pre-launch: the PDF editions are still in production, so purchase
   controls render as inert "Coming soon" pills. Same geometry as .btn so
   the layouts do not shift when the real buttons come back. */
.is-coming-soon {
  cursor: default;
  pointer-events: none;
  color: var(--muted);
  background: rgba(174, 185, 200, .14);
  border-color: rgba(174, 185, 200, .3);
  box-shadow: none;
}
.btn.is-coming-soon:hover, .is-coming-soon:hover { transform: none; }
.section-ice .is-coming-soon { color: #5a6a80; background: rgba(7, 20, 39, .06); border-color: var(--line-dark); }
.edition-card--bundle .is-coming-soon {
  display: inline-block;
  padding: 6px 14px;
  border-radius: 4px;
  font-weight: 900;
  letter-spacing: .07em;
}
/* The pre-launch price line carries words, not a short "£9.99", so it needs
   its own scale or the label wraps mid-phrase against the description. */
.price--soon strong { font-size: 1.5rem; white-space: nowrap; }

/* ==========================================================================
   Mobile pass — owner review, 3 Aug 2026
   Buttons were different widths and left-aligned, the hero cover fan grew
   into the second button, the studio logo sat right of centre, and images
   swallowed vertical swipes so the page could not be scrolled from them.
   ========================================================================== */
@media (max-width: 900px) {
  /* One column, full width, centred — applies to every button row. */
  .actions {
    justify-content: center;
    align-items: stretch;
    flex-direction: column;
    max-width: 340px;
    margin-inline: auto;
  }
  .actions .btn,
  .actions .is-coming-soon {
    width: 100%;
    min-height: 54px;
    font-size: .85rem;
  }
  .cta-panel .btn { width: 100%; }

  /* The fan was tall enough to overlap the buttons underneath it. The covers
     are absolutely positioned from the bottom of this box, so any min-height
     beyond their own height renders as dead space above them — at 360px that
     was ~150px of it. 232px still left ~30px of it: the tallest cover here
     renders at ~200px with an 8% bottom offset, so 208px is the real fit. */
  .cover-fan { min-height: 208px; }
  .cover-fan img { max-width: 190px; }
  .cover-fan-three img { width: 34%; }

  /* The panel is a single-column grid; the logo was landing at the end of
     its track. justify-self is the grid axis that actually centres it, and
     the selector has to match the higher-specificity photo override. */
  .studio-panel img.studio-panel-logo,
  .studio-panel-logo { justify-self: center; align-self: center; margin-inline: auto; }
  .studio-panel-copy .actions { margin-inline: auto; }

  /* A finger starting on an image must still scroll the page. Images are
     not draggable content here, so vertical panning belongs to the page. */
  img, picture, video, .cover-fan, .cover-fan img,
  .app-showcase, .app-showcase img, .phone-frame, .phone-frame img {
    touch-action: pan-y pinch-zoom;
    -webkit-user-drag: none;
    user-select: none;
  }

  /* Carousels: let the next card peek so it reads as scrollable, and keep
     horizontal swipes horizontal without trapping vertical ones. */
  .edition-grid, .screens-track, .card-track, [data-carousel],
  .app-screen-track, .scenario-track, .language-track, .testimonial-track,
  .work-track, .feature-cards, .abroad-rail, .journey-scroll {
    touch-action: pan-x pan-y;
    scroll-padding-inline: 16px;
  }

  /* touch-action is resolved as the INTERSECTION of the touched element and
     every ancestor up to the viewport — so the blanket `img { pan-y
     pinch-zoom }` above was winning over the pan-x pan-y set on the
     carousel container itself, every time a finger landed on the image
     (which, for a card that's mostly a photo, is nearly always). That's
     why the "card" carousels (mostly text, padding, a small icon) swiped
     fine while every image-heavy one — languages, app screens, the
     journey photo, the playing-abroad rail — read as stuck or janky.
     Re-widened here, scoped to just the carousels, so the page-scroll
     fix above still holds for every other image on the site. */
  .edition-grid img, .screens-track img, .card-track img, [data-carousel] img,
  .app-screen-track img, .scenario-track img, .language-track img,
  .testimonial-track img, .work-track img, .feature-cards img,
  .abroad-rail img, .journey-scroll img {
    touch-action: pan-x pan-y;
  }
}

/* --- Playing abroad rail (About) -----------------------------------------
   A scroll-snap row on white. The card width is set so the next one is
   always part-visible — that peek is what tells a thumb there is more,
   without needing arrows. */
.section-abroad { background: var(--white); color: var(--ink); }
.section-abroad .section-heading p { color: #55617a; }

.abroad-rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(280px, 33%);
  gap: 18px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: 10px;
  scrollbar-width: thin;
  overscroll-behavior-x: contain;
  touch-action: pan-x pan-y;
  will-change: scroll-position;
  contain: layout paint;
}
.abroad-card { scroll-snap-align: start; margin: 0; }
.abroad-card img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 14px;
  border: 1px solid var(--line-dark);
}
.abroad-hint { margin-top: 14px; color: #7a869c; font-size: .75rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }

@media (max-width: 900px) {
  /* 78% keeps a clear slice of the next photo on a phone. */
  .abroad-rail { grid-auto-columns: 78%; gap: 14px; }
  .abroad-hint { text-align: center; }
}
