/* ps-landing-kit.css
   Verbatim extraction of the <style> block from views/landing.ejs (lines 85-892 on 2026-09-05).
   Shared by the marketing feature pages so they match the landing look and motion exactly.
   Do not restyle here without checking every page that links it. */
        body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
        .hero-glow {
            background:
                radial-gradient(ellipse 70% 55% at 75% 0%, rgba(16, 185, 129, 0.13) 0%, transparent 65%),
                radial-gradient(ellipse 55% 45% at 0% 100%, rgba(20, 184, 166, 0.08) 0%, transparent 60%),
                radial-gradient(ellipse 40% 35% at 20% 20%, rgba(52, 211, 153, 0.05) 0%, transparent 60%);
        }
        @keyframes scroll-x {
            0%   { transform: translateX(0); }
            100% { transform: translateX(-50%); }
        }
        .logo-track {
            display: flex;
            gap: 5rem;
            width: max-content;
            animation: scroll-x 50s linear infinite;
            align-items: center;
        }
        /* Pro fade: dual technique. The mask gives a smooth alpha falloff on
           the logos themselves; the gradient pseudo-elements draw a true
           color-matched veil over the edges so the section background bleeds
           through cleanly (looks better than a plain black mask, especially
           against the bg-slate-50 we have here). */
        .logo-fade {
            position: relative;
            -webkit-mask-image: linear-gradient(to right,
                transparent 0%,
                rgba(0,0,0,0.5) 6%,
                #000 18%,
                #000 82%,
                rgba(0,0,0,0.5) 94%,
                transparent 100%);
                    mask-image: linear-gradient(to right,
                transparent 0%,
                rgba(0,0,0,0.5) 6%,
                #000 18%,
                #000 82%,
                rgba(0,0,0,0.5) 94%,
                transparent 100%);
        }
        .logo-fade::before,
        .logo-fade::after {
            content: '';
            position: absolute;
            top: 0;
            bottom: 0;
            width: 14%;
            pointer-events: none;
            z-index: 2;
        }
        .logo-fade::before {
            left: 0;
            background: linear-gradient(to right,
                rgb(248, 250, 252) 0%,            /* slate-50, matches section bg */
                rgba(248, 250, 252, 0.85) 35%,
                rgba(248, 250, 252, 0) 100%);
        }
        .logo-fade::after {
            right: 0;
            background: linear-gradient(to left,
                rgb(248, 250, 252) 0%,
                rgba(248, 250, 252, 0.85) 35%,
                rgba(248, 250, 252, 0) 100%);
        }
        .logo-track:hover { animation-play-state: paused; }
        .logo-item img {
            max-height: 72px;
            width: auto;
            opacity: 0.6;
            filter: grayscale(100%);
            transition: opacity 0.2s, filter 0.2s;
        }
        .logo-item img:hover { opacity: 1; filter: grayscale(0%); }
        .float-soft { animation: float-soft 6s ease-in-out infinite; }
        @keyframes float-soft {
            0%, 100% { transform: translateY(0); }
            50%      { transform: translateY(-12px); }
        }
        details > summary { list-style: none; cursor: pointer; }
        details > summary::-webkit-details-marker { display: none; }
        details[open] .chev { transform: rotate(180deg); }
        .chev { transition: transform 0.2s; }
        /* Comparison table responsive: horizontal scroll on tiny screens */
        .compare-wrap { overflow-x: auto; }
        .compare-table { min-width: 720px; }

        /* ─── Custom motion system ───────────────────────────────────────────
           Signature easing: expo-out for entrances (confident deceleration),
           gentle overshoot for hovers. Transform/opacity only → 60fps.
           Progressive enhancement: reveal targets are VISIBLE by default; the
           `js-anim` class is added to <html> by inline JS only when JS runs
           AND the user has not requested reduced motion. So no-JS and
           reduced-motion users always see fully-rendered content. */
        :root {
            --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
            --ease-overshoot: cubic-bezier(0.34, 1.56, 0.64, 1);
        }
        /* Only when JS+motion are active do we hide-then-reveal */
        .js-anim [data-reveal] {
            opacity: 0;
            transform: translateY(20px);
            transition: opacity 0.7s var(--ease-out-expo),
                        transform 0.7s var(--ease-out-expo);
            transition-delay: var(--reveal-delay, 0ms);
            will-change: opacity, transform;
        }
        .js-anim [data-reveal].is-in {
            opacity: 1;
            transform: none;
        }
        /* Hero cascade uses the same mechanism with a tighter feel */
        .js-anim [data-hero] {
            opacity: 0;
            transform: translateY(18px);
            transition: opacity 0.7s var(--ease-out-expo),
                        transform 0.7s var(--ease-out-expo);
            transition-delay: var(--hero-delay, 0ms);
        }
        .js-anim [data-hero].is-in { opacity: 1; transform: none; }

        /* ─── How-it-works mini illustrations (match real product, BIG + punchy) ── */
        .hiw-visual { width: 120px; height: 120px; }
        /* Step 1: QR (course-qr look — dark modules, rounded corner brackets, scan sweep + glow) */
        .hiw-qr {
            position: relative; width: 120px; height: 120px;
            background: #fff; border-radius: 20px; padding: 16px;
            box-shadow: 0 10px 24px -8px rgba(15,23,42,0.25); overflow: hidden;
        }
        .hiw-qr-grid { display: grid; grid-template-columns: repeat(7,1fr); gap: 3px; width: 100%; height: 100%; }
        .hiw-qr-cell { background: transparent; border-radius: 2px; }
        .hiw-qr-cell.on { background: #0f172a; }
        .hiw-qr-corner { position: absolute; width: 22px; height: 22px; border: 3px solid #10b981; }
        .hiw-qr-corner.tl { top: 7px; left: 7px; border-right: none; border-bottom: none; border-radius: 7px 0 0 0; }
        .hiw-qr-corner.tr { top: 7px; right: 7px; border-left: none; border-bottom: none; border-radius: 0 7px 0 0; }
        .hiw-qr-corner.bl { bottom: 7px; left: 7px; border-right: none; border-top: none; border-radius: 0 0 0 7px; }
        .hiw-qr-corner.br { bottom: 7px; right: 7px; border-left: none; border-top: none; border-radius: 0 0 7px 0; }
        .hiw-qr-scan { position: absolute; left: 10px; right: 10px; height: 4px; top: 14px; border-radius: 4px;
            background: linear-gradient(90deg, transparent, #10b981, transparent);
            box-shadow: 0 0 14px 3px rgba(16,185,129,0.7); opacity: 0; }
        /* Step 1: edit-hole form (matches dashboard.ejs .form-label + .sq-input — typing + par select) */
        .hiw-edit { width: 150px; display: flex; flex-direction: column; gap: 10px; }
        .hiw-field { display: flex; flex-direction: column; gap: 4px; }
        .hiw-flabel { font-size: 10px; font-weight: 600; color: #6b7280; }
        .hiw-finput { height: 30px; border: 1.5px solid #d1d5db; border-radius: 8px; background: #fff;
            display: flex; align-items: center; padding: 0 9px; font-size: 12px; font-weight: 600; color: #111827; }
        .hiw-type { white-space: nowrap; overflow: hidden; }
        .hiw-caret { width: 1.5px; height: 14px; background: #10b981; margin-left: 1px; }
        .hiw-par-row { display: flex; gap: 6px; }
        .hiw-par { width: 30px; height: 30px; border-radius: 8px; border: 1.5px solid #d1d5db; background: #fff;
            color: #374151; font-weight: 700; font-size: 13px; display: flex; align-items: center; justify-content: center; }
        .hiw-par.on { background: #10b981; border-color: #10b981; color: #fff; box-shadow: 0 0 0 3px rgba(16,185,129,0.25); }
        /* Step 3: analytics (rising bars + stat label/delta) */
        .hiw-dash { width: 130px; }
        .hiw-bars { display: flex; align-items: flex-end; gap: 9px; height: 72px; }
        .hiw-bars span { width: 22px; border-radius: 5px 5px 0 0; background: linear-gradient(180deg,#34d399,#10b981); height: var(--h);
            box-shadow: 0 4px 10px -4px rgba(16,185,129,0.5); }
        .hiw-dash-meta { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
        .hiw-dash-label { font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: #94a3b8; }
        .hiw-dash-delta { font-size: 13px; font-weight: 800; color: #16a34a; }

        /* DOPAMINE: bold, looping, satisfying motion. Each illustration has a
           hero loop so the section feels alive, not static. */
        @media (prefers-reduced-motion: no-preference) {
            /* QR — scan sweep with a whole-tile pulse + glow flash on completion */
            .js-anim .step-card.is-in .hiw-qr { animation: hiw-qr-pulse 2.2s ease-in-out infinite; }
            @keyframes hiw-qr-pulse {
                0%,100% { transform: scale(1); box-shadow: 0 10px 24px -8px rgba(15,23,42,0.25); }
                48%     { transform: scale(1.06); box-shadow: 0 12px 30px -8px rgba(16,185,129,0.55); }
            }
            .js-anim .step-card.is-in .hiw-qr-scan { animation: hiw-scan 2.2s cubic-bezier(0.45,0,0.2,1) infinite; }
            @keyframes hiw-scan { 0%{top:14px;opacity:0;} 10%{opacity:1;} 45%{top:100px;opacity:1;} 55%,100%{top:100px;opacity:0;} }

            /* Edit form — typewriter "The Windmill" + par-3 select pop, looping */
            .js-anim .step-card.is-in .hiw-type {
                display: inline-block; max-width: 0; overflow: hidden; vertical-align: bottom; white-space: nowrap;
                animation: hiw-typing 4s steps(11) infinite;
            }
            @keyframes hiw-typing {
                0%   { max-width: 0; }
                45%  { max-width: 92px; }
                85%  { max-width: 92px; }
                100% { max-width: 0; }
            }
            .js-anim .step-card.is-in .hiw-caret { animation: hiw-blink 0.9s steps(1) infinite; }
            @keyframes hiw-blink { 0%,50%{opacity:1;} 51%,100%{opacity:0;} }
            .js-anim .step-card.is-in .hiw-par.on { animation: hiw-par-pop 4s var(--ease-overshoot) infinite; }
            @keyframes hiw-par-pop {
                0%,50%,100% { transform: scale(1); box-shadow: 0 0 0 3px rgba(16,185,129,0.25); }
                60%         { transform: scale(1.3); box-shadow: 0 0 0 10px rgba(16,185,129,0); }
            }

            /* Analytics bars — spring up with overshoot, then keep a subtle live wiggle */
            .js-anim .step-card.is-in .hiw-bars span { animation: hiw-grow 0.7s var(--ease-overshoot) both, hiw-breathe 2.4s ease-in-out infinite; transform-origin: bottom; }
            .js-anim .step-card.is-in .hiw-bars span:nth-child(1){animation-delay:.05s, 0.7s;}
            .js-anim .step-card.is-in .hiw-bars span:nth-child(2){animation-delay:.15s, 0.85s;}
            .js-anim .step-card.is-in .hiw-bars span:nth-child(3){animation-delay:.25s, 1.0s;}
            .js-anim .step-card.is-in .hiw-bars span:nth-child(4){animation-delay:.35s, 1.15s;}
            @keyframes hiw-grow { from{transform:scaleY(0);} to{transform:scaleY(1);} }
            @keyframes hiw-breathe { 0%,100%{transform:scaleY(1);} 50%{transform:scaleY(1.12);} }
        }

        /* Clean card holding the real scorecard UI (What is PuttScores).
           No phone frame — just the scorecard floating in a soft white card. */
        .ps-card {
            position: relative;
            width: 340px;
            max-width: 100%;
            background: #ffffff;
            border-radius: 28px;
            padding: 18px 16px;
            border: 1px solid #e2e8f0;
            box-shadow: 0 30px 60px -20px rgba(15,23,42,0.22);
        }
        .ps-card-screen {
            overflow: hidden;
            position: relative;
            min-height: 360px;
        }

        /* ─── Multi-scene cross-fade: scorecard → booking → food → check-in ───
           One scene visible at a time; JS toggles .ps-scene-active every ~5s.
           Non-active scenes are stacked absolutely so the card height is stable
           and they fade/slide in. Scene 0 (scorecard) stays in normal flow so it
           sets the card height; scenes 1+ are positioned over it. */
        /* Pure opacity cross-fade on the container = the smoothest, flicker-free
           way to swap scenes. ALL the motion (slide/pop/spring) lives INSIDE each
           scene, not on the container — so there are no fighting transforms and no
           reset-snap when a scene deactivates. Both scenes are stacked, so they
           cross-fade through each other with no gap/jump. */
        .ps-scene {
            transition: opacity 0.6s ease;
            will-change: opacity;
        }
        .ps-scene:not(.ps-scene-active) {
            opacity: 0;
            pointer-events: none;
        }
        .ps-scene.ps-scene-active {
            opacity: 1;
            /* incoming scene fades in over the SAME window the outgoing fades out
               (no delay) — a true continuous cross-fade. The outgoing scene holds
               its confirmation fully visible, so there is never a blank gap. */
            transition: opacity 0.6s ease;
        }
        /* Scene 0 must also be absolutely stacked so it cross-fades like the rest
           (it previously sat in flow, which caused a layout jump on swap). */
        .ps-card-screen > .ps-scene[data-scene="0"] { position: relative; }
        .ps-card-screen > .ps-scene[data-scene="0"]:not(.ps-scene-active) { position: absolute; inset: 0; }
        /* Scenes 1+ overlay scene 0 (which holds the height). */
        .ps-scene-overlay {
            position: absolute;
            inset: 0;
            display: flex;
            flex-direction: column;
            justify-content: center;
            padding: 8px 4px;
            background: #ffffff;   /* opaque so scene 0 (scorecard) never bleeds through */
        }
        .ps-scene-body {
            display: flex;
            flex-direction: column;
            gap: 16px;        /* breathing room between head / fields / button */
            justify-content: center;
            height: 100%;
            padding: 4px 2px;
        }

        /* Shared scene primitives — match the emerald/slate landing look. */
        .ps-mini-head { font-size: 15px; font-weight: 800; color: #0f172a; text-align: center; margin-bottom: 2px; }
        .ps-row { display: flex; gap: 10px; }
        .ps-pill-field {
            flex: 1; display: flex; flex-direction: column; gap: 2px;
            background: #f1f5f9; border: 1px solid #e2e8f0; border-radius: 14px; padding: 10px 12px;
        }
        .ps-pill-label { font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #94a3b8; }
        .ps-pill-value { font-size: 15px; font-weight: 800; color: #0f172a; }
        .ps-slots { display: flex; gap: 8px; justify-content: center; }
        .ps-slot { flex: 1; text-align: center; padding: 9px 0; border-radius: 10px; font-weight: 700; font-size: 14px; background: #f1f5f9; color: #475569; border: 1px solid #e2e8f0; }
        .ps-slot-sel { background: #10b981; color: #fff; border-color: #10b981; }

        .ps-cta-btn {
            margin-top: 4px; width: 100%; padding: 13px; border: none; border-radius: 14px;
            background: #10b981; color: #fff; font-weight: 800; font-size: 15px; cursor: default;
        }
        .ps-confirm-check {
            width: 46px; height: 46px; border-radius: 999px; background: #10b981; color: #fff;
            display: flex; align-items: center; justify-content: center; font-size: 24px; font-weight: 900;
            box-shadow: 0 8px 20px -6px rgba(16,185,129,0.6);
        }
        .ps-confirm-title { font-size: 17px; font-weight: 900; color: #0f172a; }
        .ps-confirm-sub { font-size: 13px; color: #64748b; }

        /* Food scene */
        .ps-food-item { display: flex; align-items: center; gap: 12px; background: #f1f5f9; border: 1px solid #e2e8f0; border-radius: 16px; padding: 14px; }
        .ps-food-emoji { font-size: 30px; }
        .ps-food-info { flex: 1; display: flex; flex-direction: column; min-width: 0; }
        .ps-food-name { font-size: 15px; font-weight: 800; color: #0f172a; }
        .ps-food-meta { font-size: 12px; color: #94a3b8; }
        .ps-food-price { font-size: 16px; font-weight: 900; color: #059669; }

        /* Check-in scene */
        .ps-checkin-card { display: flex; align-items: center; gap: 12px; background: #f1f5f9; border: 1px solid #e2e8f0; border-radius: 16px; padding: 14px; }
        .ps-checkin-avatar { width: 44px; height: 44px; border-radius: 999px; background: #10b981; color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 800; }
        .ps-checkin-info { display: flex; flex-direction: column; }
        .ps-checkin-name { font-size: 15px; font-weight: 800; color: #0f172a; }
        .ps-checkin-meta { font-size: 12px; color: #94a3b8; }

        /* The confirmation is a CENTERED standalone overlay — when it shows, the
           scene body is gone, so only the check-mark group is on screen. */
        .ps-confirm {
            position: absolute; inset: 0;
            display: flex; flex-direction: column; align-items: center; justify-content: center;
            gap: 6px; text-align: center;
            opacity: 0;   /* BASE state: hidden. Only the per-scene animation reveals
                             it — so the confirmation can NEVER show on top of the
                             body (that superimposition was the glitch). */
        }

        /* Per-scene micro-play (6s window): button taps → scene body fades out →
           the standalone confirmation pops in alone → holds → fades before next. */
        @media (prefers-reduced-motion: no-preference) {
            /* button press — quick squish + glossy brighten on release */
            .ps-scene-active .ps-tap-btn { animation: ps-btn-tap 6s cubic-bezier(0.34,1.56,0.64,1); }
            @keyframes ps-btn-tap {
                0%, 30% { transform: scale(1); filter: brightness(1); box-shadow: 0 0 0 0 rgba(16,185,129,0); }
                35%     { transform: scale(0.92); filter: brightness(0.85); }
                40%     { transform: scale(1.04); filter: brightness(1.12); box-shadow: 0 0 0 6px rgba(16,185,129,0.18); }
                46%, 100% { transform: scale(1); filter: brightness(1); box-shadow: 0 0 0 0 rgba(16,185,129,0); }
            }
            /* scene body fades + lifts + softly blurs away after the tap (smooth) */
            .ps-scene-active [data-scene-body] { animation: ps-body-out 6s cubic-bezier(0.22,1,0.36,1); }
            @keyframes ps-body-out {
                0%, 44%  { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
                54%, 100% { opacity: 0; transform: translateY(-14px) scale(0.96); filter: blur(4px); }
            }
            /* standalone confirmation: springy overshoot pop, settle, then HOLD
               visible all the way to 100%. It does NOT fade itself out — the
               scene-level cross-fade carries it off as the next scene fades in,
               so there is never a blank gap between scenes. */
            .ps-scene-active [data-scene-confirm] { animation: ps-confirm-pop 6s cubic-bezier(0.34,1.56,0.64,1) forwards; }
            @keyframes ps-confirm-pop {
                0%, 47%  { opacity: 0; transform: scale(0.8) translateY(10px); }
                55%      { opacity: 1; transform: scale(1.12) translateY(0); }  /* overshoot pop */
                60%      { transform: scale(0.97); }                            /* settle bounce */
                64%, 100% { opacity: 1; transform: scale(1); }                  /* hold to the end */
            }
            /* the check icon itself gets a punchy bounce + expanding glow ring */
            .ps-scene-active .ps-confirm-check { animation: ps-check-pop 6s cubic-bezier(0.34,1.56,0.64,1); }
            @keyframes ps-check-pop {
                0%, 48% { transform: scale(0.5) rotate(-18deg); box-shadow: 0 0 0 0 rgba(16,185,129,0.55); }
                56%     { transform: scale(1.25) rotate(0deg); box-shadow: 0 0 0 10px rgba(16,185,129,0.25); }
                62%     { transform: scale(1); box-shadow: 0 0 0 18px rgba(16,185,129,0); }
                100%    { transform: scale(1); box-shadow: 0 8px 22px -6px rgba(16,185,129,0.6); }
            }
        }
        /* While a scene fades OUT, freeze it on its final state (confirmation
           shown, body hidden) and stop its inner animations — so it doesn't
           snap back to the body during the cross-fade. Kills the flicker. */
        .ps-scene-leaving [data-scene-body] { animation: none !important; opacity: 0 !important; }
        .ps-scene-leaving [data-scene-confirm] { animation: none !important; opacity: 1 !important; transform: none !important; }
        .ps-scene-leaving .ps-confirm-check { animation: none !important; }
        .ps-scene-leaving .ps-tap-btn { animation: none !important; }
        /* Scorecard scene 0 has no confirm/body split — just freeze its loops. */
        .ps-scene-leaving .ps-tap, .ps-scene-leaving .ps-check,
        .ps-scene-leaving .ps-banner-inner, .ps-scene-leaving.ps-card { animation: none !important; }

        /* Reduced motion / static: just show the confirmation, body hidden. */
        @media (prefers-reduced-motion: reduce) {
            .ps-scene-active [data-scene-body] { opacity: 0; }
            .ps-scene-active [data-scene-confirm] { opacity: 1; }
        }

        /* ─── Scorecard "plays itself": tap → hole-in-one → tap → so-close ──
           Static-safe: circles show selected end-state for reduced motion. */
        .ps-circle { transition: none; }
        /* Banner — exact .dopamine-streak-banner look, scoped inside the card */
        .ps-banner { position: absolute; top: 0; left: 0; right: 0; z-index: 5; pointer-events: none; }
        .ps-banner-inner {
            position: absolute; top: 0; left: 0; right: 0;
            color: #fff; text-align: center; padding: 16px 14px;
            box-shadow: 0 6px 24px rgba(0,0,0,0.35);
            transform: translateY(-110%); opacity: 0;
        }
        .ps-banner-ace   { background: linear-gradient(135deg, #f59e0b, color-mix(in srgb, #f59e0b 70%, #000)); }
        .ps-banner-close { background: linear-gradient(135deg, #3b82f6, color-mix(in srgb, #3b82f6 70%, #000)); }
        .ps-banner-heading { font-size: 19px; font-weight: 900; letter-spacing: 0.5px; margin-bottom: 2px; }
        .ps-banner-text { font-size: 13px; font-weight: 600; opacity: 0.92; }

        @media (prefers-reduced-motion: no-preference) {
            /* tap animation: a circle lights up to its brand color with a glow pop */
            .js-anim [data-reveal].is-in .ps-card .ps-pcard[data-player="0"] .ps-tap { animation: ps-tap 8s ease-in-out infinite; }
            .js-anim [data-reveal].is-in .ps-card .ps-pcard[data-player="1"] .ps-tap { animation: ps-tap 8s ease-in-out 3.5s infinite; }
            @keyframes ps-tap {
                0%, 4% { background:#e5e7eb; border-color:#d1d5db; color:#1f2937; transform: scale(1); box-shadow: none; }
                8%     { background: var(--brand); border-color: rgba(255,255,255,0.7); color:#fff; transform: scale(1.22); box-shadow: 0 0 0 8px color-mix(in srgb, var(--brand) 30%, transparent); }
                14%    { transform: scale(1); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 45%, transparent); }
                /* stay selected through the rest of the loop */
                100%   { background: var(--brand); border-color: rgba(255,255,255,0.7); color:#fff; box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 45%, transparent); }
            }
            /* checkmarks pop in when each player scores */
            .js-anim [data-reveal].is-in .ps-card .ps-pcard[data-player="0"] .ps-check { animation: ps-check 8s ease-in-out infinite; }
            .js-anim [data-reveal].is-in .ps-card .ps-pcard[data-player="1"] .ps-check { animation: ps-check 8s ease-in-out 3.5s infinite; }
            @keyframes ps-check { 0%,5%{opacity:0;transform:scale(0.4);} 10%{opacity:1;transform:scale(1.3);} 14%,100%{opacity:1;transform:scale(1);} }

            /* banner slide-in (cubic-bezier matches real dopamine banner), staggered */
            .js-anim [data-reveal].is-in .ps-card .ps-banner-ace   { animation: ps-banner 8s ease-in-out infinite; }
            .js-anim [data-reveal].is-in .ps-card .ps-banner-close { animation: ps-banner 8s ease-in-out 3.5s infinite; }
            @keyframes ps-banner {
                0%, 9%   { transform: translateY(-110%); opacity: 0; }
                13%      { transform: translateY(0); opacity: 1; }   /* slide down (spring) */
                30%      { transform: translateY(0); opacity: 1; }   /* hold */
                36%      { transform: translateY(-110%); opacity: 0; } /* slide up */
                100%     { transform: translateY(-110%); opacity: 0; }
            }
            /* spring easing on the slide-down portion */
            .js-anim [data-reveal].is-in .ps-card .ps-banner-inner { animation-timing-function: cubic-bezier(0.34,1.56,0.64,1); }

            /* confetti-ish card shake on the ace moment */
            .js-anim [data-reveal].is-in .ps-card { animation: ps-card-jolt 8s ease-in-out infinite; }
            @keyframes ps-card-jolt { 0%,10%,16%,100%{transform:translateX(0);} 12%{transform:translateX(-3px);} 14%{transform:translateX(3px);} }
        }

        /* ─── HERO: 3D-tilted phone playing a round (above the fold, plays on load) ──
           A dramatic perspective tilt with a slow float. The scorecard inside cycles
           Hole #1 → #2 → #3 with scores tapping in and celebration banners firing,
           so it reads like watching a real round. Flattens on small screens so the
           UI text stays legible; fully static for prefers-reduced-motion. */
        .hero-phone-stage {
            perspective: 1100px;           /* closer perspective = stronger 3D foreshortening */
            perspective-origin: 60% 42%;
            width: 100%;
            max-width: 500px;
            transform-style: preserve-3d;
        }
        .hero-phone {
            transform-style: preserve-3d;
            /* showroom angle — strong enough to read 3D, not so strong the right
               edge foreshortens and buries the score circles / action buttons */
            transform: rotateX(5deg) rotateY(-18deg) rotateZ(1.5deg);
            transform-origin: center;
            filter: drop-shadow(40px 50px 60px rgba(15,23,42,0.32));
        }
        /* real device THICKNESS: an extruded dark rail pushed behind the screen
           plane so the phone has a visible 3D side, not a flat sticker. */
        .hero-phone-frame::after {
            content: "";
            position: absolute; inset: 0;
            border-radius: 52px;
            background: linear-gradient(135deg,#2b2f37,#0a0c11);
            transform: translateZ(-18px);
            box-shadow: 0 0 0 2px #06080c;
            z-index: -2;
        }
        /* Photoreal device chassis: machined titanium rail with edge highlights. */
        .hero-phone-frame {
            position: relative;
            width: 320px;
            max-width: 100%;
            border-radius: 52px;
            padding: 12px;
            transform-style: preserve-3d;
            background:
                linear-gradient(135deg, #41464f 0%, #20242c 18%, #14171d 50%, #0c0e13 82%, #2a2e36 100%);
            box-shadow:
                inset 0 0 0 1.5px rgba(255,255,255,0.10),
                inset 0 3px 4px rgba(255,255,255,0.16),
                inset 0 -3px 6px rgba(0,0,0,0.7),
                0 2px 2px rgba(255,255,255,0.05);
        }
        /* thin glossy black bezel ring just inside the metal rail */
        .hero-phone-frame::before {
            content: "";
            position: absolute; inset: 6px;
            border-radius: 46px;
            background: #04060a;
            z-index: 0;
        }
        /* the live screen */
        .hero-phone-screen {
            position: relative;
            z-index: 1;
            border-radius: 41px;
            overflow: hidden;
            background: #ffffff;
        }
        /* slow specular glare sweeping across the glass */
        .hero-phone-screen::after {
            content: "";
            position: absolute; inset: 0;
            z-index: 6;
            pointer-events: none;
            background: linear-gradient(115deg,
                transparent 30%,
                rgba(255,255,255,0.18) 44%,
                rgba(255,255,255,0.05) 50%,
                transparent 60%);
            transform: translateX(-30%);
        }
        /* Dynamic Island — slim floating pill */
        .hero-phone-notch {
            position: absolute;
            top: 16px; left: 50%; transform: translateX(-50%);
            width: 86px; height: 26px;
            background: #04060a;
            border-radius: 16px;
            z-index: 5;
            display: flex; align-items: center; justify-content: flex-end; gap: 7px;
            padding-right: 12px;
        }
        .hero-phone-cam {
            position: absolute; top: 24px; right: calc(50% - 32px);
            width: 9px; height: 9px; border-radius: 50%;
            background: radial-gradient(circle at 35% 30%, #344056, #04070d 72%);
            box-shadow: 0 0 0 1px rgba(40,60,90,0.5);
            z-index: 6;
        }
        /* machined side buttons with highlight */
        .hero-phone-btn {
            position: absolute;
            background: linear-gradient(180deg,#4a515e 0%,#23272f 50%,#14171d 100%);
            border-radius: 2px 0 0 2px; z-index: 0;
            box-shadow: -1px 0 1px rgba(0,0,0,0.4);
        }
        .hero-phone-btn.pwr   { right: -3px; top: 150px; width: 3px; height: 62px; border-radius: 0 2px 2px 0; }
        .hero-phone-btn.vol-u { left: -3px; top: 118px; width: 3px; height: 38px; }
        .hero-phone-btn.vol-d { left: -3px; top: 164px; width: 3px; height: 38px; }

        /* scorecard fills the screen top-to-bottom (real hole page layout) */
        .hero-ps-card { width: 100%; border: 0 !important; border-radius: 0 !important;
            box-shadow: none !important; background: #ffffff; padding: 0 !important; }
        /* TRUE iPhone screen aspect ratio (~19.5:9) so it reads as a real device */
        .hero-ps-card .ps-card-screen {
            aspect-ratio: 9 / 19.5;
            display: flex; flex-direction: column;
        }
        /* hole image banner at the top (real scorecard #header-image), full-bleed.
           FIXED height so the celebration banner can pin exactly to its bottom edge. */
        .hero-hole-image {
            width: 100%; height: 150px; overflow: hidden; flex-shrink: 0;
            background: #e2e8f0;
        }
        .hero-hole-image img { width: 100%; height: 100%; object-fit: cover; display: block; }
        /* celebration toast DROPS IN from the very top of the phone, like a real
           iOS notification — floats over the status bar / Dynamic Island area. */
        .hero-ps-card .ps-banner { top: 0 !important; left: 10px !important; right: 10px !important; z-index: 7 !important; }
        .hero-ps-card .ps-banner-inner {
            top: 12px !important; left: 0; right: 0;
            border-radius: 22px;
            box-shadow: 0 14px 34px rgba(0,0,0,0.30);
            padding: 14px 16px !important;
        }
        /* everything below the image gets real left/right breathing room */
        .hero-hole-header-row,
        .hero-hole-desc { padding-left: 16px; padding-right: 16px; }
        .hero-hole-header-row { padding-top: 14px; }
        /* score cards sit INSET from the screen edges (real app spacing) */
        .hero-ps-card .ps-pcard { margin-left: 16px !important; margin-right: 16px !important; width: auto !important; }
        /* action bar inset so Skip clears the tilted bezel curve on the right.
           Right margin is larger than left because the rotateY foreshortens the
           right side — the bezel visually overlaps anything too close to the edge. */
        .hero-ps-card .hero-hole-actions { margin-left: 16px; margin-right: 28px; gap: 7px !important; }
        /* tighten the side buttons so all three fit with room to spare */
        .hero-ps-card .hero-hole-actions > button:first-child,
        .hero-ps-card .hero-hole-actions > button:last-child { padding: 0 10px !important; flex: 0 0 auto; }
        .hero-ps-card .hero-hole-actions > button:first-child svg,
        .hero-ps-card .hero-hole-actions > button:last-child svg { width: 16px; height: 16px; }
        /* push the action bar to the bottom so the screen fills naturally */
        .hero-hole-actions { margin-top: auto !important; padding-bottom: 40px; }
        /* circles must FIT the card — shrink + even gaps, no overflow clip */
        .hero-ps-card .ps-pcard { padding: 10px 12px !important; }
        .hero-ps-card .ps-pcard > div:last-child {
            display: flex !important; justify-content: space-between !important;
            gap: 6px; overflow: visible !important; padding: 4px 0 !important;
        }
        .hero-ps-card .ps-circle {
            width: 50px !important; height: 50px !important; min-width: 50px !important;
            margin: 0 !important; font-size: 1.35rem !important; flex: 0 0 auto;
        }

        @media (prefers-reduced-motion: no-preference) {
            /* gentle float + a touch of live tilt sway on the 3D phone */
            .hero-phone { animation: hero-phone-float 7s ease-in-out infinite; }
            @keyframes hero-phone-float {
                0%, 100% { transform: rotateX(5deg) rotateY(-18deg) rotateZ(1.5deg) translateY(0); }
                50%      { transform: rotateX(6deg) rotateY(-16deg) rotateZ(1.5deg) translateY(-14px); }
            }

            /* specular glare sweeps across the glass every few seconds */
            .hero-phone-screen::after { animation: hero-glare 7s ease-in-out infinite; }
            @keyframes hero-glare {
                0%, 55%  { transform: translateX(-60%); opacity: 0; }
                65%      { opacity: 1; }
                85%, 100%{ transform: translateX(130%); opacity: 0; }
            }

            /* TAP WITH WEIGHT: circle springs in with overshoot + settle, glow ring */
            .hero-ps-card .ps-pcard[data-player="0"] .ps-tap { animation: hero-tap 9s ease-in-out infinite !important; }
            .hero-ps-card .ps-pcard[data-player="1"] .ps-tap { animation: hero-tap 9s ease-in-out 1.2s infinite !important; }
            @keyframes hero-tap {
                0%, 4%  { background:#e5e7eb; border-color:#d1d5db; color:#1f2937; transform: scale(1); box-shadow:none; }
                7%      { transform: scale(0.86); }                                   /* press down */
                10%     { background: var(--brand); border-color: rgba(255,255,255,0.8); color:#fff;
                          transform: scale(1.28); box-shadow: 0 0 0 10px color-mix(in srgb, var(--brand) 32%, transparent); } /* spring up + glow */
                13%     { transform: scale(0.97); }                                   /* overshoot settle */
                16%     { transform: scale(1.05); box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand) 45%, transparent); }
                19%     { transform: scale(1); }
                100%    { background: var(--brand); border-color: rgba(255,255,255,0.8); color:#fff;
                          transform: scale(1); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 42%, transparent); }
            }
            .hero-ps-card .ps-tap { animation-timing-function: cubic-bezier(0.34,1.56,0.64,1); }

            /* Next button gets pressed near the end of each cycle (advance the hole) */
            .hero-next-btn { animation: hero-next-press 9s ease-in-out infinite; }
            @keyframes hero-next-press {
                0%, 86%   { transform: scale(1); filter: brightness(1); }
                90%       { transform: scale(0.94); filter: brightness(0.9); }   /* press */
                94%       { transform: scale(1.02); filter: brightness(1.05); }  /* spring back */
                100%      { transform: scale(1); filter: brightness(1); }
            }
            .hero-next-btn { animation-timing-function: cubic-bezier(0.34,1.56,0.64,1); }

            .hero-hole-desc { transition: opacity 0.3s ease; }
            .hero-hole-image img { transition: opacity 0.3s ease; }
            .hero-ps-card.hero-swapping .hero-hole-desc { opacity: 0; }
            .hero-ps-card.hero-swapping .hero-hole-img { opacity: 0.4; }

            /* The hero scorecard plays on LOAD (not gated behind scroll reveal).
               One full round cycle = 9s, looping. Two players tap, staggered. */
            .hero-ps-card .ps-pcard[data-player="0"] .ps-tap   { animation: ps-tap 9s ease-in-out infinite; }
            .hero-ps-card .ps-pcard[data-player="1"] .ps-tap   { animation: ps-tap 9s ease-in-out 1.2s infinite; }
            .hero-ps-card .ps-pcard[data-player="0"] .ps-check { animation: ps-check 9s ease-in-out infinite; }
            .hero-ps-card .ps-pcard[data-player="1"] .ps-check { animation: ps-check 9s ease-in-out 1.2s infinite; }
            .hero-ps-card .ps-banner-ace   { animation: ps-banner 9s ease-in-out infinite; }
            .hero-ps-card .ps-banner-close { animation: ps-banner 9s ease-in-out 1.2s infinite; }
            .hero-ps-card .ps-banner-inner { animation-timing-function: cubic-bezier(0.34,1.56,0.64,1); }

            /* hole header advances #1 → #2 → #3 across the loop, with par + scores
               swapping at the same beats the circles reset. Driven by JS class toggles
               on .hero-ps-card (hero-hole-1/2/3) so the text content can change. */
            .hero-hole-title, .hero-hole-par { transition: opacity 0.35s ease; }
            .hero-ps-card.hero-swapping .hero-hole-title,
            .hero-ps-card.hero-swapping .hero-hole-par { opacity: 0; }
        }

        /* Tablet: ease the tilt so the screen reads cleanly */
        @media (max-width: 1024px) {
            .hero-phone { transform: rotateY(-14deg) rotateX(5deg); }
            @media (prefers-reduced-motion: no-preference) {
                @keyframes hero-phone-float {
                    0%, 100% { transform: rotateY(-14deg) rotateX(5deg) translateY(0); }
                    50%      { transform: rotateY(-11deg) rotateX(4deg) translateY(-10px); }
                }
            }
        }
        /* Mobile: flatten to straight-on so the UI is fully legible, no overflow */
        @media (max-width: 640px) {
            .hero-phone-stage { perspective: none; max-width: 320px; }
            .hero-phone { transform: none !important; animation: none !important; filter: drop-shadow(0 24px 44px rgba(15,23,42,0.22)); }
        }

        /* ─── Final CTA celebratory illustration ─────────────────────────── */
        .cta-celebrate { position: relative; width: 72px; height: 72px; margin: 0 auto 18px; }
        .cta-trophy { width: 72px; height: 72px; border-radius: 999px; background: rgba(255,255,255,0.18);
            display: flex; align-items: center; justify-content: center; backdrop-filter: blur(2px); }
        .cta-trophy svg { width: 38px; height: 38px; color: #fde68a; }
        .cta-confetti { position: absolute; top: 50%; left: 50%; width: 8px; height: 8px; border-radius: 2px; opacity: 0; }
        .cta-confetti.c1 { background: #fde68a; } .cta-confetti.c2 { background: #fff; }
        .cta-confetti.c3 { background: #6ee7b7; } .cta-confetti.c4 { background: #fbbf24; }
        .cta-confetti.c5 { background: #fff; }   .cta-confetti.c6 { background: #a7f3d0; }
        /* floating background orbs */
        .cta-orb { position: absolute; border-radius: 999px; background: rgba(255,255,255,0.10); pointer-events: none; }
        .cta-orb-1 { width: 140px; height: 140px; top: -40px; left: -30px; }
        .cta-orb-2 { width: 90px;  height: 90px;  bottom: -30px; right: 40px; }
        .cta-orb-3 { width: 60px;  height: 60px;  top: 30px; right: -20px; }

        @media (prefers-reduced-motion: no-preference) {
            .js-anim .cta-band.is-in .cta-trophy { animation: cta-bob 2.2s var(--ease-overshoot) infinite; }
            @keyframes cta-bob { 0%,100%{transform:translateY(0) rotate(0) scale(1);} 50%{transform:translateY(-8px) rotate(-5deg) scale(1.06);} }
            .js-anim .cta-band.is-in .cta-confetti { animation: cta-burst 2.2s ease-out infinite; }
            .js-anim .cta-band.is-in .cta-confetti.c1 { animation-delay: 0s;    --dx:-46px; --dy:-40px; }
            .js-anim .cta-band.is-in .cta-confetti.c2 { animation-delay: .05s;  --dx: 46px; --dy:-38px; }
            .js-anim .cta-band.is-in .cta-confetti.c3 { animation-delay: .1s;   --dx:-58px; --dy: 6px;  }
            .js-anim .cta-band.is-in .cta-confetti.c4 { animation-delay: .03s;  --dx: 58px; --dy: 4px;  }
            .js-anim .cta-band.is-in .cta-confetti.c5 { animation-delay: .12s;  --dx:-30px; --dy:-54px; }
            .js-anim .cta-band.is-in .cta-confetti.c6 { animation-delay: .08s;  --dx: 32px; --dy:-52px; }
            @keyframes cta-burst {
                0%   { opacity: 0; transform: translate(-50%,-50%) scale(0.4); }
                15%  { opacity: 1; }
                55%  { opacity: 1; transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(1) rotate(140deg); }
                75%,100% { opacity: 0; transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy) + 14px)) scale(0.6) rotate(220deg); }
            }
            .js-anim .cta-band.is-in .cta-orb { animation: cta-float 7s ease-in-out infinite; }
            .js-anim .cta-band.is-in .cta-orb-2 { animation-delay: -2.5s; }
            .js-anim .cta-band.is-in .cta-orb-3 { animation-delay: -4s; }
            @keyframes cta-float { 0%,100%{transform:translate(0,0);} 50%{transform:translate(10px,-12px);} }
        }

        /* Nav gains a shadow + tighter feel once scrolled past the hero top. */
        .site-header { transition: box-shadow 0.3s ease, background-color 0.3s ease; }
        .site-header.scrolled {
            box-shadow: 0 1px 0 rgba(15,23,42,0.06), 0 8px 24px -12px rgba(15,23,42,0.18);
            background-color: rgba(255,255,255,0.95);
        }

        /* CTA tactile feel: press-scale on all pill buttons. Subtle, fast. */
        @media (prefers-reduced-motion: no-preference) {
            a.inline-flex.rounded-full:active { transform: scale(0.97); }
            a.inline-flex.rounded-full { transition-property: background-color, box-shadow, border-color, transform; }
        }

        /* FAQ smooth open: animate the answer height via grid-rows trick
           (height:auto isn't transitionable; 0fr→1fr is). */
        details .faq-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.3s var(--ease-out-expo); }
        details[open] .faq-body { grid-template-rows: 1fr; }
        details .faq-body > div { overflow: hidden; }

        /* Magnetic feature cards: icon springs on card hover. Pointer-fine
           only — no hover state to chase on touch. Composes with the existing
           Tailwind hover:-translate-y / hover:shadow on the card. */
        @media (hover: hover) and (pointer: fine) {
            .feature-icon { transition: transform 0.35s var(--ease-overshoot); }
            .feature-card:hover .feature-icon { transform: scale(1.12) rotate(-3deg); }
        }

        /* ─── Feature card mini-illustrations (match real product) ───────── */
        .fv-wrap { height: 56px; display: flex; align-items: center; }
        /* QR */
        .fv-qr { position: relative; width: 56px; height: 56px; background: #fff; border-radius: 12px; padding: 8px;
            box-shadow: 0 4px 12px -4px rgba(15,23,42,0.2); overflow: hidden; }
        .fv-qr-grid { display: grid; grid-template-columns: repeat(7,1fr); gap: 1.5px; width: 100%; height: 100%; }
        .fv-qr-cell { border-radius: 1px; } .fv-qr-cell.on { background: #0f172a; }
        .fv-qr-corner { position: absolute; width: 11px; height: 11px; border: 2px solid #10b981; }
        .fv-qr-corner.tl{top:3px;left:3px;border-right:none;border-bottom:none;border-radius:4px 0 0 0;}
        .fv-qr-corner.tr{top:3px;right:3px;border-left:none;border-bottom:none;border-radius:0 4px 0 0;}
        .fv-qr-corner.bl{bottom:3px;left:3px;border-right:none;border-top:none;border-radius:0 0 0 4px;}
        .fv-qr-corner.br{bottom:3px;right:3px;border-left:none;border-top:none;border-radius:0 0 4px 0;}
        .fv-qr-scan { position: absolute; left:5px; right:5px; height:2.5px; top:6px; border-radius:3px;
            background: linear-gradient(90deg,transparent,#10b981,transparent); box-shadow:0 0 10px 2px rgba(16,185,129,0.7); opacity:0; }
        /* Check-in */
        .fv-checkin { display: flex; align-items: center; gap: 8px; }
        .fv-check { width: 48px; height: 48px; border-radius: 999px; background: linear-gradient(135deg,#34d399,#10b981);
            display: flex; align-items: center; justify-content: center; box-shadow: 0 8px 18px -6px rgba(16,185,129,0.6); }
        .fv-check svg { width: 26px; height: 26px; color: #fff; }
        .fv-paid { font-size: 13px; font-weight: 800; color: #16a34a; }
        /* Analytics bars */
        .fv-bars { display: flex; align-items: flex-end; gap: 6px; height: 52px; }
        .fv-bars span { width: 12px; border-radius: 3px 3px 0 0; background: linear-gradient(180deg,#34d399,#10b981); height: var(--h);
            box-shadow: 0 4px 10px -4px rgba(16,185,129,0.5); }
        /* Stars */
        .fv-stars { display: flex; gap: 3px; font-size: 24px; color: #d1d5db; }
        .fv-stars span { line-height: 1; }
        /* Food row */
        .fv-food { display: flex; align-items: center; gap: 7px; background: #fff; border: 1px solid #e2e8f0;
            border-radius: 10px; padding: 8px 10px; box-shadow: 0 4px 12px -6px rgba(15,23,42,0.18); }
        .fv-food-dot { width: 10px; height: 10px; border-radius: 999px; background: #f97316; flex-shrink: 0; }
        .fv-food-name { font-size: 12px; font-weight: 600; color: #111827; white-space: nowrap; }
        .fv-food-price { font-size: 12px; font-weight: 800; color: #16a34a; }
        /* Booking slots */
        .fv-slots { display: flex; gap: 6px; }
        .fv-slot { font-size: 11px; font-weight: 700; color: #475569; background: #f1f5f9; border: 1px solid #e2e8f0;
            border-radius: 8px; padding: 6px 8px; }
        .fv-slot.on { background: #10b981; border-color: #10b981; color: #fff; box-shadow: 0 0 0 3px rgba(16,185,129,0.25); }

        @media (prefers-reduced-motion: no-preference) {
            /* QR scan + pulse */
            .js-anim .feature-card.is-in .fv-qr { animation: fv-qr-pulse 2.2s ease-in-out infinite; }
            @keyframes fv-qr-pulse { 0%,100%{transform:scale(1);} 48%{transform:scale(1.07);} }
            .js-anim .feature-card.is-in .fv-qr-scan { animation: fv-scan 2.2s cubic-bezier(0.45,0,0.2,1) infinite; }
            @keyframes fv-scan { 0%{top:6px;opacity:0;} 10%{opacity:1;} 45%{top:46px;opacity:1;} 55%,100%{top:46px;opacity:0;} }
            /* Check-in pop + ring burst */
            .js-anim .feature-card.is-in .fv-check { animation: fv-check-pop 2s var(--ease-overshoot) infinite; }
            @keyframes fv-check-pop { 0%,55%,100%{transform:scale(1);box-shadow:0 8px 18px -6px rgba(16,185,129,0.6);} 70%{transform:scale(1.18);box-shadow:0 0 0 10px rgba(16,185,129,0);} }
            /* Bars breathe */
            .js-anim .feature-card.is-in .fv-bars span { animation: fv-grow 0.7s var(--ease-overshoot) both, fv-breathe 2.4s ease-in-out infinite; transform-origin: bottom; }
            .js-anim .feature-card.is-in .fv-bars span:nth-child(1){animation-delay:.05s,.7s;}
            .js-anim .feature-card.is-in .fv-bars span:nth-child(2){animation-delay:.15s,.85s;}
            .js-anim .feature-card.is-in .fv-bars span:nth-child(3){animation-delay:.25s,1s;}
            .js-anim .feature-card.is-in .fv-bars span:nth-child(4){animation-delay:.35s,1.15s;}
            @keyframes fv-grow { from{transform:scaleY(0);} to{transform:scaleY(1);} }
            @keyframes fv-breathe { 0%,100%{transform:scaleY(1);} 50%{transform:scaleY(1.12);} }
            /* Stars fill left→right, looping */
            .js-anim .feature-card.is-in .fv-stars span { animation: fv-star 2.5s ease-in-out infinite; }
            .js-anim .feature-card.is-in .fv-stars span:nth-child(1){animation-delay:0s;}
            .js-anim .feature-card.is-in .fv-stars span:nth-child(2){animation-delay:.12s;}
            .js-anim .feature-card.is-in .fv-stars span:nth-child(3){animation-delay:.24s;}
            .js-anim .feature-card.is-in .fv-stars span:nth-child(4){animation-delay:.36s;}
            .js-anim .feature-card.is-in .fv-stars span:nth-child(5){animation-delay:.48s;}
            @keyframes fv-star { 0%,40%{color:#d1d5db;transform:scale(1);} 50%{color:#f59e0b;transform:scale(1.3);} 80%,100%{color:#f59e0b;transform:scale(1);} }
            /* Food row slides + dot pulse */
            .js-anim .feature-card.is-in .fv-food { animation: fv-food-in 2.6s ease-in-out infinite; }
            @keyframes fv-food-in { 0%,100%{transform:translateX(0);} 50%{transform:translateX(4px);} }
            .js-anim .feature-card.is-in .fv-food-dot { animation: fv-dot 2.6s ease-in-out infinite; }
            @keyframes fv-dot { 0%,100%{transform:scale(1);box-shadow:0 0 0 0 rgba(249,115,22,0.5);} 50%{transform:scale(1.3);box-shadow:0 0 0 5px rgba(249,115,22,0);} }
            /* Booking — selected slot hops between options */
            .js-anim .feature-card.is-in .fv-slot.on { animation: fv-slot-pop 2.4s var(--ease-overshoot) infinite; }
            @keyframes fv-slot-pop { 0%,60%,100%{transform:scale(1);box-shadow:0 0 0 3px rgba(16,185,129,0.25);} 72%{transform:scale(1.12);box-shadow:0 0 0 9px rgba(16,185,129,0);} }
        }

        /* Belt-and-suspenders: if the user prefers reduced motion, force
           everything visible and kill transitions even if a class slips on. */
        @media (prefers-reduced-motion: reduce) {
            .js-anim [data-reveal],
            .js-anim [data-hero] {
                opacity: 1 !important;
                transform: none !important;
                transition: none !important;
            }
        }
