/* ===================================================================
   Motion and finish.

   Three things: cards get a pointer-tracked glow and a lift, icons
   draw themselves in when their section arrives and respond to hover,
   and reveals stagger instead of all firing at once.

   Timings follow the interaction tiers: 200–300ms for hover, 300–400ms
   for a scroll reveal, with a small travel so a reveal reads as a fade
   rather than a slide. Every effect animates transform, opacity or a
   shadow only — never width, height or top, which force layout.

   The whole file is switched off under prefers-reduced-motion.
   =================================================================== */

/* ---------------------- pointer-tracked glow ---------------------- */
/* --mx/--my are written by polish.js on pointermove. The gradient is
   painted on a pseudo-element so it never affects the card's own
   background, text contrast or hit area. */
.card,
.tier,
.step-card,
.feature,
.form-card,
.empty-state,
.entrance-card,
.ecosystem-feature,
.sponsor-panel {
  position: relative;
  isolation: isolate;
}

.card::before,
.tier::before,
.step-card::before,
.form-card::before,
.entrance-card::before,
.ecosystem-feature::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
  background: radial-gradient(
    380px circle at var(--mx, 50%) var(--my, 0%),
    rgba(0, 98, 255, 0.13),
    transparent 62%
  );
}
.dark .card::before,
.dark .tier::before,
.dark .step-card::before,
.dark .form-card::before,
.entrance-card::before,
.ecosystem-feature::before {
  background: radial-gradient(
    380px circle at var(--mx, 50%) var(--my, 0%),
    rgba(25, 200, 255, 0.20),
    transparent 62%
  );
}

@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .card:hover::before,
  .tier:hover::before,
  .step-card:hover::before,
  .form-card:focus-within::before,
  .entrance-card:hover::before,
  .ecosystem-feature:hover::before {
    opacity: 1;
  }

  /* Lift and edge-light. The card floats up and the light comes with
     it over the same 360ms, on one soft ease-out — at 250ms with the
     colour untransitioned the whole thing read as a snap. */
  .card,
  .tier,
  .step-card,
  .form-card,
  .entrance-card,
  .ecosystem-feature,
  .empty-state,
  .sponsor-panel {
    transition: var(--surface-transition);
    /* The lift is a transform, so declare the resting state rather than
       leaving it `none`: a transform that starts from `none` has nothing
       to interpolate the first time and jumps to the hovered value. */
    transform: translateY(0);
  }
  .card:hover,
  .tier:hover,
  .step-card:hover,
  .entrance-card:hover,
  .ecosystem-feature:hover,
  .sponsor-panel:hover,
  .card:focus-visible,
  .tier:focus-within,
  .step-card:focus-within,
  .entrance-card:focus-visible {
    transform: translateY(-6px);
    border-color: rgba(0, 98, 255, 0.45);
    box-shadow: 0 18px 38px -18px rgba(4, 22, 44, 0.5);
  }
  .dark .card:hover,
  .dark .tier:hover,
  .dark .step-card:hover,
  .dark .card:focus-visible,
  .dark .tier:focus-within,
  .entrance-card:hover,
  .entrance-card:focus-visible {
    border-color: rgba(25, 200, 255, 0.5);
    box-shadow: 0 20px 44px -20px rgba(0, 0, 0, 0.8),
                0 0 30px -12px rgba(25, 200, 255, 0.38);
  }
  /* Settle back a touch faster than it lifts, so releasing the pointer
     feels like the card dropping rather than drifting. */
  .card, .tier, .step-card, .entrance-card, .ecosystem-feature, .sponsor-panel {
    transition-duration: calc(var(--surface-dur) * 0.72);
  }
  .card:hover, .tier:hover, .step-card:hover,
  .entrance-card:hover, .ecosystem-feature:hover, .sponsor-panel:hover {
    transition-duration: var(--surface-dur);
  }
}

/* Keyboard users get the same affordance as pointer users. */
.card:focus-visible,
.tier:focus-within,
.entrance-card:focus-visible {
  border-color: var(--cyan);
}

/* --------------------------- icon motion -------------------------- */
/* Icons draw themselves when their section reveals. pathLength="1" on
   every shape (see icons.mjs) makes one dash value work for all of
   them, so a short tick and a long outline finish together. */
@media (prefers-reduced-motion: no-preference) {
  .reveal .icon > *,
  .reveal .icon {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
  }
  .reveal.is-visible .icon > * {
    animation: icon-draw 0.75s cubic-bezier(0.65, 0, 0.35, 1) forwards;
  }
  /* A short cascade between the shapes inside one icon. */
  .reveal.is-visible .icon > *:nth-child(2) { animation-delay: 0.09s; }
  .reveal.is-visible .icon > *:nth-child(3) { animation-delay: 0.18s; }
  .reveal.is-visible .icon > *:nth-child(4) { animation-delay: 0.27s; }

  @keyframes icon-draw {
    from { stroke-dashoffset: 1; }
    to   { stroke-dashoffset: 0; }
  }

  /* Hover: a small, quick nudge. Scale only — no layout properties. */
  .feature .icon,
  .card .icon,
  .tier .icon,
  .hero-mark .icon,
  .step-card .step-n {
    transition: transform 0.25s cubic-bezier(0.215, 0.61, 0.355, 1),
                color 0.25s ease;
  }
  .feature:hover .icon,
  .card:hover .icon,
  .tier:hover .icon { transform: scale(1.12) rotate(-3deg); }
  .step-card:hover .step-n { transform: translateX(3px); }

  /* The check marks in a list tick in one after another. */
  .reveal.is-visible .check-list li {
    animation: tick-in 0.4s cubic-bezier(0.215, 0.61, 0.355, 1) backwards;
  }
  .reveal.is-visible .check-list li:nth-child(1) { animation-delay: 0.05s; }
  .reveal.is-visible .check-list li:nth-child(2) { animation-delay: 0.11s; }
  .reveal.is-visible .check-list li:nth-child(3) { animation-delay: 0.17s; }
  .reveal.is-visible .check-list li:nth-child(4) { animation-delay: 0.23s; }
  .reveal.is-visible .check-list li:nth-child(5) { animation-delay: 0.29s; }
  .reveal.is-visible .check-list li:nth-child(6) { animation-delay: 0.35s; }
  .reveal.is-visible .check-list li:nth-child(7) { animation-delay: 0.41s; }

  @keyframes tick-in {
    from { opacity: 0; transform: translateX(-8px); }
    to   { opacity: 1; transform: none; }
  }
}

/* ------------------------ staggered reveals ----------------------- */
/* Children of a revealed grid arrive in sequence rather than together.
   --i is set by polish.js. */
@media (prefers-reduced-motion: no-preference) {
  /* Scoped to html.js — the class the inline snippet in <head> sets
     before first paint.

     Only JavaScript ever adds `is-visible`, so without this scope the
     opacity:0 below is permanent when scripts do not run: the three
     tier cards on Corporate, Apartment and College Cricket, and the
     sponsor tiers, simply never appear. It is the same rule the
     Championships diagrams already follow — animate FROM hidden, never
     sit in a hidden base state waiting on a class that may never come.

     With no JS the hiding rule does not match, the cards render as
     ordinary content, and the reveal rules below are harmless no-ops. */
  .js .cards > *,
  .js .tiers > *,
  .js .steps > *,
  .js .features > * {
    opacity: 0;
  }
  /* An animation, not a transition, and on `translate` rather than
     `transform`. Two reasons, both of which were bugs before:

       - a `transition` here is the element's ONLY transition list, so
         it silently deleted the hover's border-colour and shadow
         transitions (see --surface-transition in core.css);
       - the stagger delay applied to every property in that list, so a
         card's hover lift waited out its own reveal delay.

     `translate` is a separate property from `transform`, so this fills
     its end state forever without ever pinning the hover lift. */
  .js .is-visible.cards > *,
  .js .is-visible.tiers > *,
  .js .is-visible.steps > *,
  .js .is-visible.features > *,
  .js .reveal.is-visible .cards > *,
  .js .reveal.is-visible .tiers > *,
  .js .reveal.is-visible .steps > *,
  .js .reveal.is-visible .features > * {
    animation: card-rise 520ms var(--surface-ease) both;
    animation-delay: calc(var(--i, 0) * 70ms);
  }
}
@keyframes card-rise {
  from { opacity: 0; translate: 0 14px; }
  to   { opacity: 1; translate: none; }
}

/* ---------------------------- buttons ----------------------------- */
.button {
  overflow: hidden;
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  /* A light sweep across the face on hover. */
  .button::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-120%);
    background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.22), transparent);
    transition: transform 0.55s ease;
    pointer-events: none;
  }
  .button:hover::after { transform: translateX(120%); }
}

/* -------------------------- section rule -------------------------- */
/* A hairline that draws itself across the top of each section, so the
   transition between light and dark bands reads as deliberate. */
@media (prefers-reduced-motion: no-preference) {
  .section + .section::before {
    content: "";
    position: absolute;
    inset: 0 auto auto 0;
    height: 1px;
    width: 0;
    background: linear-gradient(90deg, var(--blue), var(--cyan), transparent);
    transition: width 1.1s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .section.is-visible + .section::before,
  .section:has(.is-visible)::before { width: 100%; }
}

/* ------------------------- reduced motion ------------------------- */
@media (prefers-reduced-motion: reduce) {
  .card::before, .tier::before, .step-card::before,
  .form-card::before, .entrance-card::before, .ecosystem-feature::before { display: none; }
  .reveal .icon > * { stroke-dasharray: none; stroke-dashoffset: 0; }
  .cards > *, .tiers > *, .steps > *, .features > * {
    opacity: 1; translate: none; transform: none;
    transition: none; animation: none;
  }
  .button::after { display: none; }
  .section + .section::before { display: none; }
}
