/* ===========================================================================
   Class League — home page (index.html): tunnel hero + scroll sections.

   Companion stylesheet to css/styles.css, which provides the design tokens
   (--ink/--muted/--accent/--surface/...), the shared .nav-link / .section-label,
   the landing-rise keyframe and the auth dialogs. Everything here is namespaced
   .cl-* so it sits alongside the shared styles without clashing. Paired with the
   page-UI script js/landing-ui.js (and the shared auth module js/landing.js).
   =========================================================================== */

html {
  scroll-behavior: smooth;
}
/* Stop sideways scroll on the home page. The accent blob behind each "How it
   works" screenshot (.cl-flow-media::before, inset -20% horizontally) and the
   O/X marks (large negative dx) intentionally bleed past their containers; on
   narrow screens that bleed is wider than the viewport and makes the whole page
   scroll right/left into a blank column. Clip the off-screen part at the root.
   `clip` (not `hidden`) leaves the sticky nav working — it makes no scroll
   container — and leaves vertical scrolling untouched. */
html,
body {
  overflow-x: clip;
}

/* ---- Top nav (single centred bar, sticky) ---- */
.cl-nav-wrap {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid rgba(17, 24, 39, 0.06);
}
.cl-nav {
  display: flex;
  align-items: center;
  gap: 20px;
  /* Full-bleed: brand hard-left, CTAs hard-right (a gutter, not a centred cap),
     so the header spans the width of the hero image beneath it. */
  padding: 14px 40px;
}
.cl-brand {
  font-family: 'Urbanist', sans-serif;
  font-weight: 800;
  font-size: 1.15rem;
  color: var(--ink);
  text-decoration: none;
  letter-spacing: -0.01em;
}
.cl-nav-links {
  display: flex;
  gap: 4px;
}
.cl-nav-links a,
.cl-nav-links button {
  color: var(--muted);
  background: none;
  border: 0;
  font: inherit;
  font-size: 0.9rem;
  cursor: pointer;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  text-decoration: none;
}
.cl-nav-links a:hover,
.cl-nav-links button:hover {
  color: var(--ink);
  background: rgba(17, 24, 39, 0.05);
}
.cl-nav-cta {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
}

/* ---- Hero: full-bleed tunnel photo + centred glass panel ---- */
.cl-hero {
  min-height: calc(100svh - 64px);
  position: relative;
  background-image: url('../assets/images/tunnel-view.webp');
  background-size: cover;
  background-position: center;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 56px 24px;
}
/* Dark overlay over the image, keeping the white hero text legible. It fades in
   on load (see the motion block); this resting state is fully visible, so
   reduced-motion users get the contrast immediately. */
.cl-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: rgba(6, 10, 16, 0.5);
  pointer-events: none;
}
.cl-hero-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: 100%;
  max-width: 570px;
  position: relative;
  z-index: 1;
  /* background: rgba(12, 18, 28, 0.55);
  backdrop-filter: blur(12px) saturate(120%);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius-lg);
  padding: 28px 32px;
  box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.65); */
}
.cl-hero-panel-lower {
  position: absolute;
  bottom: 2.5vh;
  z-index: 1;
  display: flex;
  flex-direction: column;
  text-align: center;
  align-items: center;
  justify-content: center;
}
.cl-hero-title {
  font-family: 'Urbanist', sans-serif;
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.05;
  color: #fff;
  font-size: clamp(5rem, 6vw, 6rem);
  text-align: center;
  text-wrap: balance;
}
.gold-text {
  color: var(--gold);
}
.cl-hero-sub {
  font-family: 'Urbanist', sans-serif;
  font-size: 1.5rem;
  font-weight: 300;
  line-height: 1.5;
  color: #fff;
}
.cl-hero-sub span {
  font-weight: 600;
}
.cl-hero-cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}
.cl-hero-scroll {
  margin-top: 16px;
  color: rgba(255, 255, 255, 0.85);
  font-size: 1rem;
  font-weight: 100;
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  transition: color 0.15s ease;
}
.cl-hero-scroll:hover {
  color: #fff;
}
.cl-hero-scroll span {
  display: inline-block;
  animation: cl-bob 1.8s ease-in-out infinite;
}
@keyframes cl-bob {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(3px);
  }
}

/* ---- Sections ---- */
.cl-section {
  padding: 88px 24px;
  position: relative;
  scroll-margin-top: 72px; /* clear the sticky nav when jumped to via #anchor */
}
.cl-wrap {
  max-width: 1080px;
  margin: 0 auto;
}
.cl-wrap--narrow {
  max-width: 760px;
}
.cl-h2 {
  font-family: 'Urbanist', sans-serif;
  font-weight: 800;
  font-size: clamp(1.8rem, 3vw, 2.6rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-align: center;
  margin: 0 0 16px;
  text-wrap: balance;
}

/* ---- Feature rows (alternating text / media) ---- */
.cl-feature {
  background: var(--surface);
}
.cl-feature--alt {
  background: var(--bg);
}
/* a feature laid inside its own soft rounded panel, on the plain page */
.cl-feature--panel {
  padding-top: 32px;
  padding-bottom: 32px;
}
.cl-feature--panel .cl-feature-inner {
  background: rgba(26, 188, 156, 0.1);
  border-radius: 28px;
  padding: 48px 56px;
  box-shadow:
    rgba(0, 0, 0, 0.4) 0px 2px 4px,
    rgba(0, 0, 0, 0.3) 0px 7px 13px -3px,
    rgba(0, 0, 0, 0.2) 0px -3px 0px inset;
}
.cl-feature-inner {
  display: grid;
  grid-template-columns: 1fr 1.35fr;
  gap: 48px;
  align-items: center;
  max-width: 1180px;
  margin: 0 auto;
}
/* Reversed rows (image left): flip the COLUMN widths too, so the image keeps the
   wide column instead of being squeezed into the narrow one. order alone moves
   the items, not the column sizes. */
.cl-feature--reverse .cl-feature-inner {
  grid-template-columns: 1.35fr 1fr;
}
.cl-feature--reverse .cl-feature-media {
  order: -1;
}
.cl-feature-text > .section-label {
  text-align: left;
  margin-bottom: 14px;
}
.cl-feature-text .cl-h2 {
  text-align: left;
  margin: 0 0 18px;
}
.cl-feature-text p {
  color: var(--muted);
  line-height: 1.65;
  font-size: 1.05rem;
  margin: 0 0 14px;
  max-width: 48ch;
}
.cl-feature-text .nav-link {
  margin-top: 12px;
  width: 100%;
  padding: 14px 12px;
}
.cl-feature-media {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* Founder portrait in the About dialog — circular. Overrides the rectangular
   .signin-images img styling (border/radius/shadow) from styles.css. */
.cl-about-media img {
  width: 100%;
  max-width: 240px;
  max-height: 240px;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 50%;
  border: 0;
  box-shadow: none;
}

/* ---- Demo video (feature 4) ---- */
/* Sits in the same stadium "class screen" frame as the screenshot sections
   (.cl-frame), so it reads as being up on the class screen. The video is inset
   into the screen like .cl-slide img (scale 0.86) but with NO border / radius
   of its own. Plays inline with a slim CUSTOM control bar (play / scrub / time);
   no native fullscreen, PiP or download chrome. Reuses the .lv-* control styles
   from styles.css (hidden there by default, gated on the old
   .landing-video-wrap.lv-active), re-shown for this player below. */
.cl-video {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 10px;
  background: url('../assets/images/screenBck.webp') center / 100% 100%
    no-repeat;
}
/* The player inset into the screen bezel, mirroring .cl-slide img's scale, but
   with no border or radius. Establishes the positioning context for overlay/bar. */
.cl-video-stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
  transform: scale(0.86);
  transform-origin: center;
}
.cl-video-el {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  background: #0b1f17;
  cursor: pointer;
  /* Kill WebKit/Safari's default <video> rounding + any focus ring, otherwise
     the corners clip round and the dark screen behind shows through. */
  border: 0;
  border-radius: 0;
  outline: none;
}
/* Control bar stays hidden until the demo is first played (mirrors Triptico's
   .video-card.is-started gating), then auto-hides while idle (below). */
.cl-video.is-started .lv-controls {
  display: flex;
}
.cl-video.is-paused .lv-overlay {
  display: flex;
}
/* While playing, the bar fades ~1.5s after the last pointer move (JS adds
   .lv-idle) so it stops covering the recorded UI. */
.cl-video.lv-idle .lv-controls {
  opacity: 0;
  pointer-events: none;
}
.cl-video.lv-idle {
  cursor: none;
}

/* ---- Per-section screenshot carousel (sat in "our screen") ---- */
.cl-carousel {
  width: 100%;
}
.cl-frame {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 10px;
  /* The same stadium-screen backdrop as the hero's screen-frame, so every
     screenshot reads as being up on the class screen. */
  background: url('../assets/images/screenBck.webp') center / 100% 100%
    no-repeat;
}
.cl-slide {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  transition: opacity 0.45s ease;
  pointer-events: none;
}
.cl-slide.is-current {
  opacity: 1;
  pointer-events: auto;
}
.cl-slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  /* Sit the screenshot in the screen with a thin light edge so the backdrop
     shows, like the hero's .landing-screenshot. */
  transform: scale(0.86);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 3px;
}
/* The in-slide <figcaption> is just the text source; the visible caption sits
   centred below the frame, between the image and the controls. */
.cl-slide .cl-cap {
  display: none;
}
.cl-caption {
  text-align: center;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.45;
  margin: 14px auto 0;
  max-width: 100%;
}
.cl-caption:empty {
  display: none;
}
.cl-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-top: 16px;
}
.cl-arrow {
  width: 34px;
  height: 34px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: #fff;
  box-shadow: var(--shadow);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  line-height: 1;
  transition:
    background 0.15s ease,
    color 0.15s ease,
    border-color 0.15s ease;
}
.cl-arrow:hover {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
.cl-arrow-icon {
  width: 13px;
  height: 13px;
  display: block;
  fill: currentColor;
}
.cl-dots {
  display: flex;
  gap: 8px;
  justify-content: center;
}
.cl-dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  border: 0;
  padding: 0;
  background: var(--border);
  cursor: pointer;
  transition:
    background 0.15s ease,
    transform 0.15s ease;
}
.cl-dot.is-active {
  background: var(--accent);
  transform: scale(1.25);
}

/* ---- Social proof ---- */
/* white, to keep the white/grey alternation running (the grey feature 4 sits
   directly above it). */
.cl-proof {
  background: var(--surface);
}
.cl-quotes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
.cl-quote {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 26px;
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
  margin: 0;
}
.cl-quote blockquote {
  margin: 0 0 18px;
  font-family: 'Urbanist', sans-serif;
  font-size: 1.05rem;
  line-height: 1.5;
  color: var(--ink);
}
.cl-quote figcaption {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  color: var(--ink);
}
.cl-quote .flag {
  width: 20px;
  height: auto;
  border-radius: 2px;
}

/* ---- FAQ ---- */
.cl-faq {
  background: var(--surface);
  padding-top: 40px;
}
.cl-faq details {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  margin-bottom: 12px;
  padding: 0 20px;
}
.cl-faq summary {
  cursor: pointer;
  font-family: 'Urbanist', sans-serif;
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--ink);
  padding: 18px 0;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
}
.cl-faq summary::-webkit-details-marker {
  display: none;
}
.cl-faq summary::after {
  content: '+';
  color: var(--accent);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1;
  flex-shrink: 0;
}
.cl-faq details[open] summary::after {
  content: '\2013';
}
.cl-faq details p {
  margin: 0 0 18px;
  color: var(--muted);
  line-height: 1.6;
}
.cl-faq details a {
  color: var(--accent);
  font-weight: 600;
}

/* ---- Final CTA band ---- */
/* The hero's tunnel image again, bookending the page (the start of a match, for
   "start your league"). Neutral dark scrim (no colour tint) so it matches the
   hero and just darkens the image enough to keep the white text/buttons legible. */
.cl-final {
  background-image:
    linear-gradient(rgba(8, 12, 20, 0.6), rgba(8, 12, 20, 0.72)),
    url('../assets/images/tunnel-view.webp');
  background-size: cover;
  background-position: center;
  display: flex;
}
.cl-final-inner {
  text-align: center;
}
.cl-final-h2 {
  font-family: 'Urbanist', sans-serif;
  font-weight: 800;
  font-size: clamp(2.2rem, 4.2vw, 3.4rem);
  line-height: 1.05;
  color: #fff;
  margin: 0 0 12px;
  letter-spacing: -0.02em;
  text-wrap: balance;
}
.cl-final p {
  color: rgba(255, 255, 255, 0.9);
  font-size: 1.1rem;
  margin: 0 0 28px;
}
/* Reassure chips in the final band: centre them and keep the chip size (inherits
   the white colour + text-shadow from .cl-final p above). */
.cl-final .cl-final-reassure {
  justify-content: center;
  font-size: 0.95rem;
  background: rgba(255, 255, 255, 0.9);
  color: var(--ink);
  border-radius: var(--radius-sm);
  border-top: 1px solid rgba(255, 255, 255, 0.3);
  border-bottom: 1px solid #000;
  padding: 12px 20px;
  width: fit-content;
}
.landing-reassure .reassure-item svg {
  opacity: 1;
}
.cl-final-cta {
  display: flex;
  gap: 14px;
  justify-content: center;
  flex-wrap: wrap;
}
.cl-btn {
  font-family: 'Urbanist', sans-serif;
  font-weight: 700;
  font-size: 1.05rem;
  padding: 14px 30px;
  border-radius: var(--radius-lg);
  cursor: pointer;
  text-decoration: none;
  border: 2px solid transparent;
  transition:
    transform 0.15s ease,
    filter 0.15s ease;
  display: inline-block;
}
.cl-btn--light {
  background: var(--accent);
  color: #fff;
}
.cl-btn--ghost {
  background: transparent;
  color: #fff;
  border-color: rgba(255, 255, 255, 0.6);
}
.cl-btn:hover {
  transform: translateY(-1px);
  filter: brightness(1.03);
}

/* ---- Footer ---- */
.cl-footer {
  background: var(--surface);
  border-top: 1px solid var(--border);
}
.cl-footer-inner {
  max-width: 1080px;
  margin: 0 auto;
  padding: 56px 32px 36px;
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr;
  gap: 40px;
}
.cl-footer-brand {
  max-width: 36ch;
}
.cl-footer-wordmark {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: 'Urbanist', sans-serif;
  font-weight: 800;
  font-size: 1.2rem;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
}
.cl-footer-wordmark img {
  width: 28px;
  height: 28px;
  padding: 2px;
  background: var(--accent);
  border-radius: 3px;
  box-shadow:
    rgba(0, 0, 0, 0.1) 0 1px 2px,
    rgba(0, 0, 0, 0.1) 0 -2px 0 inset,
    rgba(255, 255, 255, 0.18) 0 2px 0 inset;
}
.cl-footer-brand p {
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.55;
  margin: 12px 0 0;
}
.cl-footer-col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}
.cl-footer-col h2 {
  font-family: 'Urbanist', sans-serif;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink);
  margin: 0 0 4px;
}
.cl-footer-col a,
.cl-footer-col button {
  color: var(--muted);
  font: inherit;
  font-size: 0.95rem;
  text-decoration: none;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  transition: color 0.15s ease;
}
.cl-footer-col a:hover,
.cl-footer-col button:hover {
  color: var(--ink);
}
.cl-footer-base {
  border-top: 1px solid #fff;
  padding: 20px 32px;
  text-align: center;
  background: #3498db;
}
.cl-footer-base p {
  color: #fff;
  font-size: 0.85rem;
  margin: 0;
}
@media (max-width: 720px) {
  .cl-footer-inner {
    grid-template-columns: 1fr;
    gap: 28px;
    padding: 44px 24px 28px;
  }
}

/* ---- Responsive ---- */
/* When the header no longer fits on one line, centre the whole thing (brand,
   links and CTAs) and let it wrap as one group — tidier than a lopsided wrap
   with the brand/CTAs at the edges and the links stranded centred below. */
@media (max-width: 960px) {
  .cl-nav {
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px 18px;
    padding: 12px 18px;
  }
  .cl-nav-cta {
    margin-left: 0;
  }
}

@media (max-width: 880px) {
  /* On mobile the nav wraps to ~3 rows, so the header is far taller than the
     64px the desktop hero height assumes — `100svh - 64px` then overshoots the
     viewport and pushes the absolutely-pinned lower panel (Learn More) below
     the fold. Stack the hero as a normal centred column and let its height be
     content-driven so title, sub and Learn More are always on screen. */
  .cl-hero {
    min-height: auto;
    flex-direction: column;
    justify-content: center;
    gap: 24px;
    padding: 44px 24px 36px;
  }
  .cl-hero-panel {
    padding: 0;
  }
  .cl-hero-panel-lower {
    position: static;
    bottom: auto;
  }
  /* The clamp floor (5rem ≈ 80px) is far too big on a phone, so the title
     overflows and overlaps the sub. Scale it to the viewport width here. */
  .cl-hero-title {
    font-size: clamp(2.75rem, 13vw, 5rem);
  }
  .cl-hero-sub {
    font-size: 1.25rem;
  }
  .cl-section {
    padding: 56px 20px;
  }
  .cl-feature-inner,
  .cl-feature--reverse .cl-feature-inner {
    grid-template-columns: 1fr;
    gap: 28px;
  }
  .cl-feature--panel .cl-feature-inner {
    padding: 28px 20px;
  }
  .cl-feature-media {
    order: 2;
  }
  .cl-feature--reverse .cl-feature-media {
    order: 2;
  }
  .cl-quotes {
    grid-template-columns: 1fr;
  }
}

/* ---- Motion ---- */
@keyframes cl-hero-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes cl-hero-rise {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@media (prefers-reduced-motion: no-preference) {
  /* Staged hero entrance: clean image first (~0.5s), then the dark overlay
     fades in, then the headline, subtext and scroll cue rise in over ~1.5s. */
  .cl-hero::before {
    animation: cl-hero-fade 0.7s ease 0.5s both;
  }
  .cl-hero-title {
    animation: cl-hero-rise 0.7s cubic-bezier(0.16, 1, 0.3, 1) 0.9s both;
  }
  .cl-hero-sub {
    animation: cl-hero-rise 0.7s cubic-bezier(0.16, 1, 0.3, 1) 1.2s both;
  }
  .cl-hero-scroll {
    animation: cl-hero-rise 0.6s cubic-bezier(0.16, 1, 0.3, 1) 1.5s both;
  }
  /* Section content reveals as it scrolls into view. One-shot: a cheap CSS
     transition flipped by an IntersectionObserver (home-cl-design.js), the same
     mechanism as .cl-flow-step. This deliberately replaces a scroll-linked
     `animation-timeline: view()` reveal, which on iOS Safari scrubbed on the
     main thread every scroll frame across all these elements and made the
     (compositor-promoted, stationary) sticky header judder. */
  .cl-section .cl-h2,
  .cl-feature-text,
  .cl-feature-media,
  .cl-quote,
  .cl-faq details {
    opacity: 0;
    transform: translateY(14px);
    transition:
      opacity 0.6s ease,
      transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
  }
  .cl-section .cl-h2.is-in,
  .cl-feature-text.is-in,
  .cl-feature-media.is-in,
  .cl-quote.is-in,
  .cl-faq details.is-in {
    opacity: 1;
    transform: none;
  }
}
/* No-JS safety net: the observer never runs, so force the content visible
   rather than leaving the whole page below the hero blank. (Inside no-preference
   above, reduced-motion users already skip the hidden state entirely.) */
@media (scripting: none) {
  .cl-section .cl-h2,
  .cl-feature-text,
  .cl-feature-media,
  .cl-quote,
  .cl-faq details {
    opacity: 1;
    transform: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .cl-hero-scroll span {
    animation: none;
  }
}

/* ---- How it works: ClassDojo-style vertical flow + hand-drawn arrows ---- */
.cl-flow {
  background: var(--surface);
  /* subtle off-white chalk tone for the connecting arrows (tunable) */
  --chalk: #aeb8c6;
  padding-bottom: 40px;
}
/* last step carries no extra bottom padding, to tighten the gap below */
.cl-flow-step:last-child {
  padding-bottom: 54px;
}
.cl-flow-lead {
  text-align: center;
  color: var(--muted);
  max-width: 52ch;
  margin: 0 auto 24px;
  line-height: 1.6;
  font-size: 1.05rem;
}
.cl-flow-track {
  max-width: 1000px;
  margin: 0 auto;
  position: relative;
  z-index: 0; /* stacking context: lets the O/X marks sit behind every step */
}
/* connector arrows: drawn over the steps, in the gaps between them */
.cl-flow-links {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  z-index: 4;
}
/* O/X tactics marks: a back layer behind everything, so they can be large and
   never cover a screenshot or any text */
.cl-flow-marks {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  z-index: -1;
}
/* every connector SVG shares one stroke weight */
.cl-link,
.cl-link-mark {
  fill: none;
  stroke: var(--chalk);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
  transition: opacity 0.5s ease;
}
.cl-link-mark {
  transition: opacity 0.5s ease 0.15s;
}
.cl-link.is-in {
  opacity: 1;
}
/* the offset sketch copy: fainter than the main line */
.cl-link--sketch.is-in {
  opacity: 0.4;
}
.cl-link-mark.is-in {
  opacity: 0.6;
}
/* glyph marks (Amatic SC '°'/'×' instead of stroked shapes): filled chalk text,
   not a stroked outline, so override the shared .cl-link-mark stroke/fill rules */
.cl-link-mark--glyph {
  fill: var(--chalk);
  stroke: none;
  font-family: 'Amatic SC', cursive;
  font-weight: 400;
}
.cl-link-mark--glyph.is-in {
  opacity: 0.85;
}
/* closing "GOAL!" flourish on the final connector: chalk like the O/X marks, but
   in Amatic SC so it reads as a hand-scrawled word rather than a stroked shape */
.cl-flow-goal {
  fill: var(--chalk);
  font-family: 'Amatic SC', cursive;
  font-weight: 400;
  opacity: 0;
  transition: opacity 0.5s ease 0.15s;
}
.cl-flow-goal.is-in {
  opacity: 0.85;
}
.cl-flow-step {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  align-items: center;
  padding: 80px 0;
}
/* reversed rows put the screenshot on the right */
.cl-flow-step--reverse .cl-flow-media {
  order: 2;
}
/* soft organic blob sits BEHIND the screenshot, so the screenshot itself stays a
   clean rounded rectangle and no UI is cropped. */
.cl-flow-media {
  position: relative;
}
.cl-flow-media::before {
  content: '';
  position: absolute;
  inset: -24% -20%;
  background: var(--accent);
  -webkit-mask: url('../assets/images/blob.svg') center / 100% 100% no-repeat;
  mask: url('../assets/images/blob.svg') center / 100% 100% no-repeat;
  transform: rotate(-8deg);
  z-index: 0;
}
.cl-flow-step--reverse .cl-flow-media::before {
  transform: rotate(7deg);
}
.cl-flow-shot {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  /* border-radius: 18px; */
  border: 1px solid var(--border);
  background: #fff;
  box-shadow: 0 10px 30px rgba(17, 24, 39, 0.1);
}
/* number + title share row 1; description spans the row below */
.cl-flow-text {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  column-gap: 16px;
}
.cl-flow-num {
  grid-column: 1;
  grid-row: 1;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--bg);
  border: 2px dashed var(--chalk);
  color: var(--ink);
  font-family: 'Urbanist', sans-serif;
  font-weight: 800;
  font-size: 1.05rem;
  margin: 0;
}
.cl-flow-title {
  grid-column: 2;
  grid-row: 1;
  font-family: 'Urbanist', sans-serif;
  font-weight: 800;
  font-size: clamp(1.3rem, 2.2vw, 1.7rem);
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0;
}
.cl-flow-desc {
  grid-column: 1 / -1;
  color: var(--muted);
  line-height: 1.6;
  font-size: 1.05rem;
  margin: 14px 0 0;
  max-width: 42ch;
}
.cl-flow-desc span {
  font-size: 0.9rem;
  font-weight: 100;
}
/* arrowhead marker (shared by the connector layer): orient="auto" rotates it to
   the curve direction, so it is always a clean point. */
.cl-arrow-mk {
  stroke: var(--chalk, #aeb8c6);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
}

/* ---- gentle scroll reveal: steps fade up into view ---- */
.cl-flow-step {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity 0.6s ease,
    transform 0.6s ease;
}
.cl-flow-step.is-in {
  opacity: 1;
  transform: none;
}

.cl-flow-cta {
  text-align: center;
  margin-top: 40px;
}

@media (max-width: 860px) {
  /* Stack each step as number -> title -> screenshot -> quote, so the heading
     sits directly above the image it describes (image-first left it floating
     ambiguously between two steps). display:contents dissolves .cl-flow-text so
     its number/title/quote become flex children of the step alongside the media,
     which lets the media slot in between the title and the quote via order. */
  .cl-flow-step {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
    text-align: center;
    padding: 12px 0;
  }
  .cl-flow-text {
    display: contents;
  }
  .cl-flow-num {
    order: 1;
    margin: 20px auto 0; /* a little breathing room above each step number */
  }
  .cl-flow-title {
    order: 2;
    margin: 0;
  }
  /* both selectors so the desktop reverse rule (.cl-flow-step--reverse
     .cl-flow-media { order: 2 }, higher specificity) can't pull the image back
     above the title on alternating steps */
  .cl-flow-media,
  .cl-flow-step--reverse .cl-flow-media {
    order: 3;
    align-self: stretch; /* image fills the column width; other items stay centred */
    margin: 18px 0; /* breathing room so the blob clears the title and quote */
  }
  /* The blob bleeds 24% of the image height past the top/bottom on desktop, where
     it spills harmlessly into the side gutters. Stacked on mobile that vertical
     bleed reaches into the title above and quote below, so halve it here (and it
     scales with image height, so this stays clear on larger phones too). */
  .cl-flow-media::before {
    inset: -12% -20%;
  }
  .cl-flow-desc {
    order: 4;
    margin: 0;
    max-width: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cl-flow-step,
  .cl-flow-arrow {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
