/*
 * Hani's World — the approved responsive stylesheet, copied from the design package's
 * app/globals.css (RiseOhana-Hanis-World-Responsive-v1) with TWO deliberate changes from
 * the source, both recorded here because everything else is byte-identical and a future
 * side-by-side diff against the package should show exactly these and nothing more.
 *
 * 1. MECHANICAL. The four /site2/ asset paths became /site-v3/, because /site-v2/ is
 *    already taken by the design this one is a candidate to replace.
 *
 * 2. THE PROTOTYPE FRAME IS GONE. The source presented the site as a fixed-size card
 *    floating on a gray backdrop — .prototype-shell carried a 24px gutter and a gray
 *    gradient, and .phone-frame was capped at 390x844 (base) and 1240x920 (desktop) with
 *    a border, a radius and a drop shadow. That is a REVIEW PRESENTATION, not a website:
 *    on a real browser it renders as a gray border around the whole page, on all four
 *    sides once the window is taller than the cap. Both rules now fill the viewport
 *    (width:100%, height:100dvh, no border, no radius, no backdrop).
 *
 *    ONLY the framing was removed. The internal stage-scroll model it wrapped is
 *    untouched: .phone-frame is still the 3-row grid (bars + .stage-scroll), .stage-scroll
 *    still scrolls internally above 430px, and hanis-world.js still branches its beat math
 *    on (max-width: 430px) between window scroll and scroller.scrollTop. The desktop
 *    layout's sticky-world math -- `calc(100vh - 158px)` at the time, base `calc(100vh - 146px)`
 *    -- was already written for a full-viewport frame and only becomes correct with this change.
 *    The desktop figure has since moved to `calc(100vh - 76px)`: the CTA was merged into the top
 *    bar and the frame lost its bottom row, so it now subtracts one bar instead of two.
 *
 * DO NOT REORDER OR CONSOLIDATE. The package's handoff is explicit that the cascade is
 * order-dependent: the mobile foundation comes first, then later production refinements,
 * then desktop overrides, and moving a rule can change positioning, scale or scroll-stage
 * behaviour even when the declarations look equivalent. Consolidation is allowed later,
 * but only after mobile and desktop comparison screenshots exist to verify parity against.
 *
 * Responsive contract, from the handoff:
 *   <= 430px   approved full-width mobile experience; sticky top bar, fixed bottom CTA
 *   431-899px  the base presentation with internal stage scrolling. NEVER SEPARATELY
 *              ART-DIRECTED as a tablet experience — in the source this band was hidden
 *              behind the 390px frame, so removing the frame is what first exposes it.
 *              Content is still sized for a phone and now stretches. Preserve as-is until
 *              the band is actually designed; do not tune it rule by rule.
 *   >= 900px   approved cinematic desktop; persistent black bars, internal stage scroll
 */

@import 'tailwindcss';
:root{--blue:#5c8dff;--deep:#243f99;--gold:#f2a23a;--pink:#d63a6c;--cloud:#e6e8ed}
*{box-sizing:border-box}html,body{margin:0;min-height:100%;background:#d9dde6;color:#111}body{font-family:Arial,Helvetica,sans-serif}button{font:inherit}
.prototype-shell{min-height:100dvh;display:block;padding:0}
.phone-frame{width:100%;height:100dvh;background:#fff;border:0;border-radius:0;overflow:hidden;display:grid;grid-template-rows:68px minmax(0,1fr) 78px}
.top-bar,.bottom-bar{position:relative;z-index:20;background:#111;color:#fff;display:flex;align-items:center}.top-bar{justify-content:space-between;padding:7px 13px}.top-bar>img{width:99px;height:52px;object-fit:contain}.menu-toggle{width:42px;height:42px;padding:10px;border:1px solid #555;border-radius:8px;background:#191919;display:grid;align-content:center;gap:5px}.menu-toggle i{display:block;width:20px;height:2px;background:#fff}.site-menu{position:absolute;right:10px;top:59px;z-index:60;width:132px;padding:5px;background:#111;border:2px solid var(--gold);box-shadow:5px 5px 0 #0006}.site-menu a{display:block;padding:10px;color:#fff;text-decoration:none;text-transform:uppercase;font-size:9px;font-weight:900;letter-spacing:.08em;border-bottom:1px solid #444}.site-menu a:last-child{border:0}.bottom-bar{padding:12px;gap:8px}.bottom-bar button{flex:1;min-height:44px;border:1px solid #777;border-radius:9px;color:#fff;background:#222;font-size:10px;font-weight:800}
.stage-scroll{min-height:0;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:none;-ms-overflow-style:none}
.app-intro{height:426px;position:relative;overflow:hidden;display:grid;grid-template-columns:1.12fr .92fr .75fr;gap:8px;align-items:center;padding:22px 13px 68px;background:linear-gradient(#fff 0 82%,#f6f7fa)}
.eyebrow{margin:0 0 6px;font-size:16px;font-weight:900;letter-spacing:.12em;color:var(--pink)}.copy-block{position:relative;z-index:3;align-self:center}.copy-block h1{margin:0 0 9px;color:var(--deep);font-size:22px;line-height:.93;letter-spacing:-.045em}.copy-block h1 span{display:block;white-space:nowrap}.copy-block p:not(.eyebrow){margin:0 0 9px;font-size:20px;line-height:1.3}.copy-block strong{font-size:10px;line-height:1.2}
.phone-screens{display:flex;align-items:center;justify-content:center;min-width:0}.screen-card{width:77px;height:164px;border:3px solid #222;border-radius:13px;background:#fff;padding:12px 6px;box-shadow:0 8px 0 #25345a22}.screen-card.rear{width:68px;height:144px;margin-left:-45px;transform:translate(19px,15px) rotate(5deg);background:#f0f3fa}.screen-card span{display:block;font-size:6px;font-weight:900;color:var(--deep);margin-bottom:8px}.screen-card i{display:block;height:23px;margin:6px 0;background:var(--cloud);border-radius:4px;border-left:4px solid var(--blue)}
.hani-invite{position:relative;z-index:5;text-align:center;align-self:center}.hani-invite img{display:block;width:76px;height:92px;margin:auto;object-fit:contain;filter:drop-shadow(0 5px 3px #5e421c44)}.hani-invite p{margin:3px -4px 0;padding:6px 3px;background:#fff;border:2px solid #111;border-radius:9px;font-size:16px;font-weight:800;line-height:1.2}.pixel-river{position:absolute;right:41px;bottom:-18px;width:66px;height:115px;opacity:.65;background:repeating-linear-gradient(45deg,var(--gold) 0 11px,var(--blue) 11px 22px,var(--pink) 22px 33px);clip-path:polygon(28% 0,100% 0,65% 100%,0 100%)}
.world-preview{height:48px;background-image:linear-gradient(#5c8dff22,#243f9977),url('/site-v3/house/house-approved-locked.png');background-size:100% auto;background-position:center -52px;border-top:5px solid #243f99;image-rendering:pixelated}
.world-runway{height:6900px;background:#8fc8ff}.sticky-world{position:sticky;top:0;height:100%;max-height:calc(100vh - 146px);min-height:620px;padding:12px;overflow:hidden;background:#111}
.house-board{position:relative;margin:8px auto 5px;width:330px;height:495px;overflow:hidden;background:#111}.house-master{display:block;width:100%;height:100%;object-fit:cover;image-rendering:pixelated}.yard-dog{position:absolute;z-index:5;top:34px;width:19px;height:16px;object-fit:contain;image-rendering:pixelated;transform:translateX(-50%);transition:left .18s steps(3,end);filter:drop-shadow(1px 1px 0 #17321288)}.house-overlays{position:absolute;inset:0}
.quest{position:absolute;padding:6px 7px;background:#fff;border:2px solid #111;box-shadow:3px 3px 0 var(--gold);font-size:7px;line-height:1.2;animation:bloop .16s ease-out both}.quest em{color:var(--pink);font-style:normal;font-weight:900}.tidy{left:48px;top:259px}.read{left:91px;top:228px}.guitar{left:38px;top:128px}.dishes{left:190px;top:281px}.dog{left:134px;top:365px}.bike-quest{right:8px;bottom:73px}
.character-sprite,.prop-sprite{position:absolute;z-index:3;display:block;object-fit:contain;image-rendering:pixelated;animation:bloop .16s steps(2,end) both}.character-sprite.eli-guitar{left:80px;top:83px;width:90px;height:110px}.character-sprite.eli-living{left:64px;top:205px;width:90px;height:110px}.character-sprite.lena{left:175px;bottom:55px;width:87px;height:117px}.character-sprite.eli-bike{right:80px;bottom:46px;width:90px;height:110px}.prop-sprite.bike-lawn{left:119px;bottom:45px;width:66px;height:48px}.prop-sprite.bike-garage{right:50px;bottom:74px;width:62px;height:46px}.prop-sprite.lena-car{left:207px;bottom:1px;width:52px;height:75px}.point-pop,.snap{position:absolute;z-index:4;padding:7px 8px;background:#fff;border:3px solid #111;box-shadow:4px 4px 0 var(--pink);font-size:10px;font-weight:900;animation:bloop .16s ease-out both}.point-pop{display:flex;align-items:center;gap:4px}.point-pop img{width:18px;height:18px;object-fit:cover;border-radius:50%;image-rendering:pixelated}.guitar-points{left:45px;top:102px;color:var(--pink)}.snap.parent{right:12px;bottom:143px;transform:rotate(-7deg)}.snap.kid{right:49px;bottom:129px;transform:rotate(7deg)}.bike-points{right:42px;bottom:120px;color:var(--pink)}
.character-sprite.lena{scale:-1 1}
.balance-card{position:absolute;left:56px;top:230px;width:220px;height:130px;padding:16px;border:4px solid #111;background:#fff;box-shadow:9px 9px 0 var(--gold);display:flex;flex-direction:column;justify-content:center;align-items:center;animation:bloop .16s ease-out both}.balance-card span{position:absolute;left:10px;top:10px;font-size:9px;font-weight:900}.balance-card small{font-size:9px;font-weight:900;letter-spacing:.08em;color:#555}.balance-card strong{display:flex;align-items:center;gap:8px;font-size:50px;line-height:1;color:var(--deep)}.balance-card strong img{width:42px;height:42px;object-fit:cover;border-radius:50%;image-rendering:pixelated}
.reward-shop{position:relative;height:438px;margin:13px 4px 7px;padding:42px 13px 14px;border:4px solid #111;background:#2a2e36;box-shadow:8px 8px 0 #1114;animation:bloop .16s ease-out both;overflow:hidden}.shop-title{position:absolute;top:0;left:0;right:0;height:36px;display:grid;place-items:center;background:#111;color:var(--gold);font-size:10px;font-weight:900;letter-spacing:.08em}.reward-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px}.reward-tile{min-height:143px;position:relative;padding:10px 7px;border:3px solid #111;background:#e6e8ed;display:flex;flex-direction:column;align-items:center;text-align:center}.reward-tile.selected{background:#fff0b9;outline:5px solid var(--gold);z-index:2;transform:translateY(-2px);animation:highlight .18s ease-out both}.reward-icon{height:61px;display:grid;place-items:center;font-size:30px}.reward-tile b{font-size:8px;line-height:1.1}.reward-tile span{margin-top:4px;font-size:10px;font-weight:900;color:var(--pink)}.reward-tile em{margin-top:5px;padding:3px 5px;background:#111;color:#fff;font-size:6px;font-style:normal;font-weight:900}.shop-eli{position:absolute;right:16px;bottom:12px;width:72px;padding:7px;border:3px solid #fff;background:var(--gold);text-align:center;font-size:8px;font-weight:900}.real-shop{background:#f1f4fa;border-radius:22px;border-color:#212735;padding-top:68px}.real-shop .shop-title{border-radius:17px 17px 0 0;color:#fff;background:var(--deep)}.real-shop .reward-tile{border:1px solid #cdd3df;border-radius:13px;background:#fff}.real-shop .reward-tile.selected{outline:4px solid var(--blue);background:#fff9e7}.real-app-chrome{position:absolute;top:38px;left:13px;right:13px;height:25px;display:flex;align-items:center;justify-content:space-between;font-size:10px;color:var(--deep)}.real-app-chrome i{width:14px;height:14px;border-radius:50%;background:var(--cloud)}.wipe-layer{position:absolute;z-index:8;inset:0;background:repeating-linear-gradient(90deg,#ffffffee 0 20px,#5c8dffee 20px 40px);clip-path:polygon(0 0,58% 0,38% 100%,0 100%);display:grid;place-items:center;animation:wipe .2s ease-out both}.wipe-layer span{background:#111;color:#fff;padding:7px;font-size:8px;font-weight:900}
.reward-icon{width:100%;height:72px;overflow:hidden;border:2px solid #111;background:#fff}.reward-icon img{display:block;width:100%;height:100%;object-fit:cover}.reward-shop:not(.real-shop) .reward-icon img{image-rendering:pixelated}.reward-tile b{margin-top:5px}.real-shop .reward-icon{border:0;border-radius:8px}
.hani-guide{position:absolute;z-index:12;right:9px;top:66px;width:136px;pointer-events:none;animation:bloop .16s steps(2,end) both}.hani-guide img{display:block;width:108px;height:122px;margin-left:auto;object-fit:contain;filter:drop-shadow(4px 4px 0 #1118)}.hani-guide p{position:relative;margin:-5px 0 0;padding:13px 10px 10px;background:#fff7d6;border:0;box-shadow:0 0 0 4px #111,6px 6px 0 var(--gold);clip-path:polygon(8px 0,calc(100% - 8px) 0,calc(100% - 8px) 4px,100% 4px,100% calc(100% - 8px),calc(100% - 4px) calc(100% - 8px),calc(100% - 4px) 100%,8px 100%,8px calc(100% - 4px),0 calc(100% - 4px),0 8px,4px 8px,4px 4px,8px 4px);font-family:var(--font-geist-mono),monospace;font-size:18px;font-weight:900;line-height:1.25;text-transform:uppercase}.hani-guide p:before{content:'HANI';position:absolute;left:8px;top:-8px;padding:2px 5px;background:#111;color:var(--gold);font-size:12px;letter-spacing:.08em}.hani-guide.over-shop{top:61px;width:128px}.hani-guide.over-shop img{width:94px;height:112px}.hani-guide.over-shop p{font-size:16px}
.payoff{padding:25px 13px 0;min-height:560px;background:#fff;border-top:9px solid var(--pink)}.payoff h2{margin:0 0 15px;font-size:25px;color:var(--deep);letter-spacing:-.04em}.benefit-cards{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}.benefit-card{position:relative;min-height:136px;padding:7px 5px;border:2px solid #111;box-shadow:3px 3px 0 var(--gold);display:flex;flex-direction:column;overflow:hidden;background:linear-gradient(145deg,#fff 0 72%,#f6d9e4 72%)}.benefit-card:before{content:'';position:absolute;inset:3px;border:1px solid #1113;pointer-events:none}.benefit-card span{position:relative;color:var(--pink);font-size:6px;font-weight:900}.benefit-card b{position:relative;margin:auto 0 4px;font-size:7px;line-height:1.05}.benefit-card small{position:relative;font-size:4.5px;color:#777}.card-scene{position:relative;height:45px;margin:7px 0 3px;border:2px solid #111;background:#8fc8ff;overflow:hidden}.card-scene i{position:absolute;display:block;background:var(--gold);box-shadow:2px 2px 0 #111}.card-scene i:nth-child(1){width:15px;height:15px;left:8px;bottom:5px}.card-scene i:nth-child(2){width:9px;height:25px;right:8px;bottom:5px;background:var(--pink)}.card-scene i:nth-child(3){width:7px;height:7px;left:31px;top:7px;background:#fff}.card-2 .card-scene{background:var(--gold)}.card-3 .card-scene{background:#fff0b9}.card-4 .card-scene{background:var(--deep)}.close-panel{margin:24px -13px 0;padding:25px 17px calc(76px + env(safe-area-inset-bottom));color:#fff;background:var(--deep);display:grid;grid-template-columns:1.15fr .85fr;gap:12px;align-items:start}.close-panel h3{margin:0;font-size:26px}.close-panel p{margin:2px 0;font-size:30px;font-weight:900;line-height:1.08}.close-panel em{grid-column:1/-1;font-size:7px;color:#b9c8ff;font-style:normal}.cta-lockup>small{font-size:10px}.footer-stores{display:flex;gap:5px;margin-top:13px}.footer-stores button{min-width:0;flex:1;padding:7px 3px;border:1px solid #899ee8;border-radius:5px;color:#fff;background:#111;font-size:6px;font-weight:900;opacity:1}
.character-sprite.eli-living{left:44px}.prop-sprite.bike-lawn{left:137px}
.balance-card{left:auto;right:6px;width:200px;padding:14px}.balance-card small{font-size:8px;letter-spacing:.06em}.balance-card strong{gap:7px;font-size:40px}.balance-card strong img{width:34px;height:34px}
.hani-guide.focus-bike{left:8px;right:auto;top:260px;bottom:auto;width:128px}.hani-guide.focus-bike img,.hani-guide.focus-points img{margin-left:0}.hani-guide.focus-bike p{font-size:16px}.hani-guide.focus-points{left:8px;right:auto;top:58px;width:128px}.hani-guide.focus-points p{font-size:16px}
@keyframes bloop{from{opacity:0;transform:scale(.82)}to{opacity:1}}@keyframes highlight{from{outline-width:0;transform:scale(.9)}to{outline-width:5px;transform:translateY(-2px)}}@keyframes wipe{from{clip-path:polygon(0 0,0 0,0 100%,0 100%)}to{clip-path:polygon(0 0,58% 0,38% 100%,0 100%)}}
@media(max-height:700px){.prototype-shell{padding:0}.phone-frame{border-radius:0;border-width:0}.sticky-world{min-height:554px}.house-board{transform:scale(.84);transform-origin:top center;margin-bottom:-77px}.reward-shop{transform:scale(.85);transform-origin:top center;margin-bottom:-61px}.hani-guide{transform:scale(.84);transform-origin:top right}}
@media(max-width:430px){html,body{height:auto;min-height:100%;overflow-x:clip;overflow-y:visible}.prototype-shell{display:block;min-height:100dvh;padding:0}.phone-frame{display:block;width:100%;height:auto;min-height:100dvh;border:0;border-radius:0;overflow:visible;box-shadow:none}.top-bar{position:sticky;top:0;height:68px;z-index:40}.stage-scroll{overflow:visible;padding-bottom:calc(78px + env(safe-area-inset-bottom))}.sticky-world{height:100dvh;max-height:none;min-height:0;padding:4px 6px}.bottom-bar{position:fixed;left:0;right:0;bottom:0;z-index:50;min-height:78px;padding-bottom:max(12px,env(safe-area-inset-bottom))}}
@media(max-width:430px) and (min-height:701px){.house-board{transform:scale(1.06);transform-origin:top center;margin-bottom:35px}}
@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important;transition:none!important;animation:none!important}}

/* Production review refinements */
.app-reward-page{position:relative;height:506px;margin:5px auto 0;width:315px;padding:25px 14px 62px;border:4px solid #111;border-radius:24px;background:#f7f8fc;color:#111;box-shadow:8px 8px 0 #0005;overflow:hidden;animation:bloop .16s ease-out both}.app-page-status{height:19px;display:flex;justify-content:space-between;font-size:7px;font-weight:900}.app-page-heading{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}.app-page-heading button{width:27px;height:27px;border:0;border-radius:50%;background:#e9edf6;color:var(--deep);font-size:21px}.app-page-heading div{display:flex;flex-direction:column;text-align:center}.app-page-heading small{font-size:6px;letter-spacing:.1em;color:#667}.app-page-heading b{font-size:16px;color:var(--deep)}.app-page-heading>span{padding:6px 7px;border-radius:12px;background:var(--gold);font-size:8px;font-weight:900}.app-page-tabs{display:flex;gap:21px;margin-bottom:9px;border-bottom:1px solid #d7dce8;font-size:7px}.app-page-tabs b{padding:6px 2px;color:var(--deep);border-bottom:3px solid var(--blue)}.app-page-tabs span{padding:6px 2px;color:#7b8392}.app-page-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}.app-page-grid img{display:block;width:100%;aspect-ratio:1;object-fit:cover;border-radius:12px;border:1px solid #dae0ef}.app-page-nav{position:absolute;left:0;right:0;bottom:0;height:54px;padding:7px 20px;display:flex;justify-content:space-between;background:#fff;border-top:1px solid #dce1ec}.app-page-nav span{display:flex;flex-direction:column;align-items:center;gap:2px;color:#8a91a0;font-size:13px}.app-page-nav small{font-size:5px;font-weight:900}.app-page-nav .active{color:var(--deep)}
.payoff{min-height:0;padding-top:18px}.close-panel{margin-top:16px;padding:16px 14px calc(82px + env(safe-area-inset-bottom));grid-template-columns:1.12fr .88fr;gap:10px;align-items:center}.close-panel h3{font-size:23px}.close-panel p{margin:0;font-size:24px}.cta-lockup>small{font-size:9px}.footer-stores{margin-top:9px}.brand-signoff{text-align:center}.footer-logo{display:block;width:88px;height:43px;margin:6px auto 0;object-fit:contain}.footer-hani{display:block;width:58px;height:58px;margin:-3px auto -7px;object-fit:contain;filter:drop-shadow(2px 2px 0 #1116)}
.app-intro{height:344px;padding:14px 13px 18px}.pixel-river{display:none}
@media(max-width:430px){.sticky-world{top:68px;height:calc(100dvh - 68px)}.house-board{margin-top:0}}

/* Approved final-art integration */
.app-intro{background-color:#fff8e8;background-image:linear-gradient(90deg,#fff9edeb 0 46%,#fff9ed70 72%,transparent),url('/site-v3/final-art/app-intro-background.png');background-size:cover;background-position:center bottom}
.reward-art-stage{position:relative;height:506px;margin:5px auto 0;width:340px;overflow:hidden;border:4px solid #111;border-radius:22px;background:#071b3d;box-shadow:8px 8px 0 #0005;animation:bloop .16s ease-out both}
.reward-art{position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:cover;transition:opacity .18s ease,transform .22s ease}
.reward-art-game{opacity:1;object-position:center}.reward-art-real{opacity:0;transform:translateX(12%);object-position:center}
.reward-art-stage.show-real .reward-art-game{opacity:0;transform:translateX(-12%)}.reward-art-stage.show-real .reward-art-real{opacity:1;transform:translateX(0)}
.headphone-focus{position:absolute;z-index:4;left:49.5%;top:28%;width:21%;height:29%;border:5px solid #ffd447;border-radius:9px;box-shadow:0 0 0 3px #071b3d,0 0 20px #ffd447;animation:shopPulse .75s steps(2,end) infinite}
.reward-art-stage .wipe-layer{background:repeating-linear-gradient(90deg,#fffdf0f2 0 18px,#58a7d9e8 18px 36px);animation:wipe .2s ease-out both}
@keyframes shopPulse{50%{filter:brightness(1.35);transform:scale(1.04)}}
.payoff{padding:20px 10px 0;background:#fff8e9;border-top:0}.payoff>.eyebrow,.payoff>h2{text-align:center}.payoff h2{font-size:23px;margin-bottom:12px}
.benefit-cards{grid-template-columns:repeat(4,minmax(0,1fr));gap:5px;align-items:start}.benefit-card{min-height:0;padding:0;border:0;border-radius:9px;background:transparent;box-shadow:2px 3px 0 #0a284a33;overflow:hidden}.benefit-card:before{display:none}.benefit-card img{display:block;width:100%;height:auto;aspect-ratio:2/3;object-fit:cover}
.close-panel{position:relative;isolation:isolate;overflow:hidden;color:#071f43;background:#fff4d7 url('/site-v3/final-art/final-cta-background.png') center/cover no-repeat;padding:20px 16px calc(82px + env(safe-area-inset-bottom))}.close-panel:before{content:'';position:absolute;z-index:-1;inset:0;background:linear-gradient(90deg,#fff9e8d9,#fff9e88c 55%,#fff9e8c7)}.close-panel h3{color:#092b59}.close-panel p{color:#092b59}.cta-lockup>small{color:#613f21}.footer-stores button{border-color:#18345a;background:#081a36}.footer-logo{filter:drop-shadow(0 2px 1px #fff)}
@media(max-height:700px){.reward-art-stage{transform:scale(.85);transform-origin:top center;margin-bottom:-72px}}
@media(max-width:430px){.app-intro{background-position:58% bottom}.reward-art-stage{width:min(340px,calc(100vw - 20px));height:min(506px,calc((100vw - 20px)*1.488))}.close-panel{background-position:center bottom}}

/* Production review layout corrections */
.founder-promo{margin:0 auto;padding:4px 9px;border-left:1px solid #ffffff44;color:#ddd;font-size:14px;line-height:1.2;letter-spacing:.03em;text-align:left}.founder-promo b{color:#f2b14b;font-size:15px}
.app-intro{height:250px;align-items:start;padding:0 13px 10px;background-position:center bottom}.app-intro .copy-block{align-self:start;padding-top:0}.app-intro .copy-block>.eyebrow{margin-top:0;padding-top:0}.app-intro .phone-screens,.app-intro .hani-invite{align-self:center}
.reward-art-stage{width:350px;height:233px;margin-top:24px;background:#06182f}.reward-art{object-fit:contain}.headphone-focus{left:50.2%;top:39%;width:20.3%;height:34%;border-width:3px;border-radius:5px}
.payoff{background:#fff4d7}.payoff h2 strong{font-weight:1000}.benefit-cards{padding-bottom:14px}.close-panel{margin-top:0}.cta-logo{display:block;width:118px;height:57px;margin:0 0 2px;object-fit:contain}.close-panel h3{text-transform:none;font-size:25px;letter-spacing:-.03em}.footer-hani-wrap{position:relative;display:flex;align-items:flex-end;justify-content:center;margin-top:6px}.footer-hani-wrap span{position:relative;margin:0 0 30px -5px;padding:7px 8px;background:#fff7d6;color:#071f43;box-shadow:0 0 0 3px #071f43,4px 4px 0 #f2a23a;font-family:var(--font-geist-mono),monospace;font-size:8px;font-weight:900;text-transform:uppercase;white-space:nowrap}.footer-hani-wrap span:before{content:'';position:absolute;left:-8px;bottom:7px;width:9px;height:9px;background:#fff7d6;border-left:3px solid #071f43;border-bottom:3px solid #071f43;transform:rotate(45deg)}.footer-hani{width:67px;height:67px;margin:0;flex:0 0 auto}
@media(max-height:700px){.reward-art-stage{transform:scale(.94);margin-bottom:-14px}}
@media(max-width:430px){.app-intro{height:238px;padding-top:0;background-position:58% bottom}.reward-art-stage{width:min(350px,calc(100vw - 16px));height:auto;aspect-ratio:3/2;margin-top:16px}.founder-promo{font-size:13px}.close-panel{background-position:center top}}

/* Clear, vertically stacked reward story */
.action-copy{position:absolute;z-index:4;padding:5px 7px;background:#071f43;color:#fff7d6;border:2px solid #fff7d6;box-shadow:3px 3px 0 #071f43;font-family:var(--font-geist-mono),monospace;font-size:7px;font-weight:900;letter-spacing:.03em;white-space:nowrap;animation:bloop .16s ease-out both}.guitar-action{left:44px;top:192px}.bike-action{right:8px;bottom:181px}.guitar-points{left:176px;top:76px}.bike-quest{left:120px;right:auto;bottom:99px}
.reward-stack{width:100%;height:100%;padding-top:3px;display:flex;flex-direction:column;align-items:center;overflow:hidden}.reward-stack .reward-art-stage{position:relative;flex:0 0 auto;width:322px;height:auto;aspect-ratio:3/2;margin:0;background:#06182f;border:3px solid #111;border-radius:14px;box-shadow:5px 5px 0 #0004;overflow:hidden}.reward-stack .reward-art{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;transform:none;opacity:1}.reward-stack .headphone-focus{left:50.2%;top:39%;width:20.3%;height:34%}.reward-hani-break{flex:0 0 91px;width:322px;display:flex;align-items:center;justify-content:center;gap:8px;position:relative;z-index:5}.reward-hani-break img{width:70px;height:82px;object-fit:contain;filter:drop-shadow(3px 3px 0 #1116)}.reward-hani-break p{position:relative;width:224px;margin:0;padding:10px 9px;background:#fff7d6;color:#071f43;box-shadow:0 0 0 3px #111,4px 4px 0 #f2a23a;font-family:var(--font-geist-mono),monospace;font-size:15px;font-weight:900;line-height:1.2;text-transform:uppercase}.reward-hani-break p:before{content:'';position:absolute;left:-7px;top:25px;width:9px;height:9px;background:#fff7d6;border-left:3px solid #111;border-bottom:3px solid #111;transform:rotate(45deg)}.reward-real-stage{animation:bloop .2s ease-out both}
@media(max-height:700px){.reward-stack{padding-top:0}.reward-stack .reward-art-stage{width:292px}.reward-hani-break{width:292px;flex-basis:78px}.reward-hani-break img{width:58px;height:68px}.reward-hani-break p{width:216px;font-size:14px}}
@media(max-width:430px){.reward-stack .reward-art-stage{width:min(322px,calc(100vw - 24px));height:auto}.reward-hani-break{width:min(322px,calc(100vw - 24px))}}

/* Final App Intro screenshots and section handoff */
.app-intro{height:258px;padding-top:8px}.screen-card{padding:0;overflow:hidden;background:#fff}.screen-card img{display:block;width:100%;height:100%;object-fit:cover}.screen-card.rear{padding:0}.reward-stack{justify-content:center}
@media(max-width:430px){.app-intro{height:246px;padding-top:8px}}

/* Approved change order: typography, prompts, and final staging */
body{font-family:var(--font-parent-body),Montserrat,Arial,sans-serif}.copy-block h1,.payoff h2,.close-panel h3{font-family:Georgia,'Times New Roman',serif}.copy-block p,.copy-block strong,.founder-promo,.cta-lockup small,.brand-signoff p{font-family:var(--font-parent-body),Montserrat,Arial,sans-serif}.hani-invite p,.hani-guide p,.reward-hani-break p,.footer-hani-wrap span{font-family:var(--font-kid-body),Nunito,Arial,sans-serif}.hani-guide p:before,.action-copy,.quest,.point-pop,.snap,.balance-card,.scroll-nudge{font-family:var(--font-geist-mono),monospace}.payoff>.eyebrow{font-family:var(--font-parent-body),Montserrat,Arial,sans-serif}.payoff h2{font-weight:700;letter-spacing:-.025em}
.founder-promo{padding:2px 8px;font-size:12.8px;line-height:1.13}.founder-promo strong{color:#fff;font-size:12.4px;letter-spacing:.08em}.founder-promo b{font-size:14px}
.guitar-action{left:69px;top:202px}.bike-action{right:48px;bottom:8px}
.reward-stack{justify-content:flex-start;padding-top:8px}.reward-stack .reward-art-stage{width:350px}.reward-hani-break{width:350px}.reward-hani-break p{font-family:var(--font-kid-body),Nunito,Arial,sans-serif;font-weight:800;text-transform:none;font-size:16px}.reward-hani-break p strong{font-family:var(--font-kid-title),Fredoka,Arial,sans-serif}.hani-welcome{right:9px;top:52px}.hani-welcome p{font-family:var(--font-kid-body),Nunito,Arial,sans-serif;text-transform:none;font-size:18px}
.scroll-nudge{position:absolute;z-index:30;right:12px;bottom:15px;display:flex;flex-direction:column;align-items:center;gap:3px;color:#fff;filter:drop-shadow(2px 2px 0 #111);pointer-events:none}.scroll-nudge span{padding:3px 5px;border-radius:3px;background:#071f43d9;font-size:5px;font-weight:900;letter-spacing:.08em;white-space:nowrap}.scroll-nudge i{display:grid;place-items:center;width:22px;height:22px;border:2px solid #fff;border-radius:50%;background:#071f43;color:#f2a23a;font-size:18px;line-height:1;font-style:normal;font-weight:900;animation:scrollPulse 1.05s ease-in-out infinite}@keyframes scrollPulse{0%,100%{transform:translateY(0);opacity:.78}50%{transform:translateY(6px);opacity:1}}
@media(max-height:700px){.reward-stack{padding-top:5px}.reward-stack .reward-art-stage{width:310px}.reward-hani-break{width:310px}.guitar-action{top:200px}}
@media(max-width:430px){.reward-stack{padding-top:8px}.reward-stack .reward-art-stage{width:min(350px,calc(100vw - 16px))}.reward-hani-break{width:min(350px,calc(100vw - 16px))}.scroll-nudge{right:9px;bottom:90px}}

/* Unified Hani voice */
.hani-invite p,.hani-guide p,.reward-hani-break p,.footer-hani-wrap span{font-family:var(--font-kid-title),Fredoka,Arial,sans-serif;font-weight:600;font-style:normal;text-transform:none;letter-spacing:0}.hani-guide p:before{content:'Hani';font-family:var(--font-kid-title),Fredoka,Arial,sans-serif;font-weight:600;text-transform:none;letter-spacing:0}.hani-welcome p,.hani-guide.focus-bike p,.hani-guide.focus-points p,.reward-hani-break p{font-family:var(--font-kid-title),Fredoka,Arial,sans-serif;text-transform:none}.footer-hani-wrap span{font-size:8px}.hani-invite p{font-size:16px}.hani-guide p{font-size:18px;line-height:1.28}.reward-hani-break p{font-size:16px;line-height:1.25}

/* Eli action and quest-complete alignment */
.guitar-action{left:76px;top:194px}.bike-action{right:62px;bottom:29px}.guitar-points{left:35px;top:30px;z-index:14;display:flex;flex-direction:column;align-items:stretch;gap:3px;padding:5px 7px}.guitar-points small{display:block;padding-bottom:3px;border-bottom:1px solid #1115;color:#071f43;font-size:5px;line-height:1;letter-spacing:.08em;text-align:center}.guitar-points b{display:flex;align-items:center;justify-content:center;gap:4px;font-size:10px}.guitar-points b img{width:18px;height:18px}
@media(max-height:700px){.guitar-action{top:194px}.guitar-points{top:28px}}

/* Shared quest-complete notification */
.completion-points{display:flex;flex-direction:column;align-items:stretch;gap:3px;padding:5px 7px}.completion-points small{display:block;padding-bottom:3px;border-bottom:1px solid #1115;color:#071f43;font-size:5px;line-height:1;letter-spacing:.08em;text-align:center}.completion-points b{display:flex;align-items:center;justify-content:center;gap:4px;font-size:10px}.completion-points b img{width:18px;height:18px}

/* Approved compact in-world quest markers */
.quest{display:inline-flex;align-items:stretch;width:max-content;max-width:168px;padding:3px;border:0;background:#071f43;color:#071f43;box-shadow:4px 4px 0 #d75d62;font-family:var(--font-kid-title),Fredoka,Arial,sans-serif;font-size:9px;line-height:1;clip-path:polygon(6px 0,calc(100% - 6px) 0,calc(100% - 6px) 3px,100% 3px,100% calc(100% - 6px),calc(100% - 3px) calc(100% - 6px),calc(100% - 3px) 100%,6px 100%,6px calc(100% - 3px),0 calc(100% - 3px),0 6px,3px 6px,3px 3px,6px 3px)}.quest:after{content:'';position:absolute;right:13px;bottom:-5px;width:8px;height:8px;background:#071f43;transform:rotate(45deg);z-index:-1}.quest b{display:flex;align-items:center;padding:7px 8px;background:#fff6dc;font-weight:700;text-transform:uppercase;white-space:nowrap}.quest em{display:flex;align-items:center;gap:3px;padding:5px 6px;border-left:3px solid #071f43;background:#f5ad2d;color:#071f43;font-size:10px;font-style:normal;font-weight:700;white-space:nowrap}.quest em img{width:15px;height:15px;border-radius:50%;object-fit:cover;image-rendering:pixelated}.tidy{left:44px;top:255px}.read{left:82px;top:218px}.guitar{left:24px;top:116px}.dishes{left:196px;top:276px}.dog{left:128px;top:357px}.bike-quest{left:111px;right:auto;bottom:96px}
.scroll-nudge{top:184px;bottom:auto}
@media(max-width:430px){.scroll-nudge{top:174px;bottom:auto}}

/* Reward-center swipe overhaul and final typography polish */
.founder-promo{font-size:15.2px;line-height:1.2}.founder-promo strong{font-size:14.8px}.founder-promo b{font-size:16.4px}
.copy-block h1,.payoff h2,.close-panel h3{font-family:Georgia,'Times New Roman',serif;font-weight:700}
.cta-lockup>small{color:var(--pink);font-weight:900}
.brand-signoff{align-self:end}
.scroll-nudge{top:248px;bottom:auto}
.reward-stack{position:relative;justify-content:center;padding-top:0}.reward-hani-float{position:absolute;z-index:8;left:8px;top:25px;width:205px;display:flex;align-items:flex-start;gap:5px}.reward-hani-float img{width:68px;height:79px;object-fit:contain;filter:drop-shadow(3px 3px 0 #1116)}.reward-hani-float p{position:relative;margin:9px 0 0;padding:9px 8px;background:#fff7d6;color:#071f43;box-shadow:0 0 0 3px #111,4px 4px 0 #f2a23a;font-family:var(--font-kid-title),Fredoka,Arial,sans-serif;font-size:16px;font-weight:600;line-height:1.25}.reward-hani-float p:before{content:'';position:absolute;left:-7px;top:18px;width:9px;height:9px;background:#fff7d6;border-left:3px solid #111;border-bottom:3px solid #111;transform:rotate(45deg)}
.reward-swipe-stage{position:relative;width:350px;aspect-ratio:3/2;margin-top:74px;overflow:hidden;border:3px solid #111;border-radius:14px;background:#06182f;box-shadow:5px 5px 0 #0004}.reward-swipe-image{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;transition:transform .38s steps(8,end),opacity .18s linear}.reward-swipe-game{transform:translateX(0);opacity:1}.reward-swipe-real{transform:translateX(105%);opacity:0}.reward-swipe-stage.show-real .reward-swipe-game{transform:translateX(-105%);opacity:0}.reward-swipe-stage.show-real .reward-swipe-real{transform:translateX(0);opacity:1}.reward-swipe-stage .headphone-focus{left:50.2%;top:39%;width:20.3%;height:34%;border-width:3px;border-radius:5px}
@media(max-height:700px){.reward-hani-float{top:12px}.reward-swipe-stage{width:310px;margin-top:65px}}
@media(max-width:430px){.founder-promo{font-size:14.4px}.founder-promo strong{font-size:14px}.founder-promo b{font-size:15.6px}.scroll-nudge{top:224px;bottom:auto}.reward-hani-float{left:7px;top:20px;width:198px}.reward-hani-float img{width:62px;height:72px}.reward-hani-float p{font-size:15.2px}.reward-swipe-stage{width:min(350px,calc(100vw - 16px));margin-top:76px}}

/* Reward Hani continues directly from her final house position */
.reward-stack{display:block}.reward-guide{top:58px;left:8px;right:auto;width:128px}.reward-guide img{width:108px;height:122px;margin-left:0}.reward-guide p{margin:-5px 0 0;font-size:16px}.reward-swipe-stage{position:absolute;left:50%;top:236px;transform:translateX(-50%);margin:0}
@media(max-height:700px){.reward-swipe-stage{top:207px;width:310px}}
@media(max-width:430px){.reward-guide{top:58px;left:8px}.reward-swipe-stage{top:232px;width:min(350px,calc(100vw - 16px));margin:0}}

/* Approved 8-bit point celebration */
.balance-card{left:17px;right:auto;top:319px;z-index:15;width:178px;height:96px;padding:12px 10px 9px;border:5px solid #071f43;background:linear-gradient(180deg,#123f78,#071f43);color:#fff7d6;box-shadow:0 0 0 3px #f5ad2d,7px 7px 0 #d75d62;isolation:isolate;overflow:visible}
.balance-card:before{content:'';position:absolute;z-index:-1;inset:4px;background:repeating-conic-gradient(from 0deg at 50% 68%,#f5ad2d 0 5deg,transparent 5deg 15deg);opacity:.25}
.balance-card span{left:9px;top:8px;padding:3px 6px;background:#fff7d6;color:#071f43;box-shadow:2px 2px 0 #d75d62;font-size:7px;letter-spacing:.1em}
.balance-card small{position:relative;margin-top:8px;color:#f5ad2d;font-size:6px;letter-spacing:.1em;text-shadow:1px 1px 0 #000}
.balance-card strong{position:relative;gap:5px;color:#fff7d6;font-size:35px;text-shadow:3px 3px 0 #d75d62}
.balance-card strong img{width:34px;height:34px;border:2px solid #fff7d6;box-shadow:2px 2px 0 #d75d62}
.balance-spark{position:absolute;z-index:2;display:block;width:5px;height:5px;background:#fff7d6;box-shadow:0 -5px 0 #fff7d6,0 5px 0 #fff7d6,-5px 0 0 #fff7d6,5px 0 0 #fff7d6}
.balance-spark.spark-one{right:13px;top:13px}.balance-spark.spark-two{left:-11px;top:45px;transform:scale(.65)}.balance-spark.spark-three{right:-9px;bottom:13px;transform:scale(.8)}

/* Actual-app label rides with the IRL reward reveal */
.real-screens-label{position:absolute;z-index:13;left:50%;top:220px;transform:translateX(-50%);margin:0;padding:5px 9px;border:2px solid #071f43;border-radius:999px;background:#fff7d6;color:#071f43;box-shadow:3px 3px 0 #d75d62;font-family:var(--font-parent-body),Montserrat,Arial,sans-serif;font-size:12px;font-weight:900;letter-spacing:.06em;white-space:nowrap}

/* Final collectible bonus cards: true Pixel Burst artwork lives inside each card */
.benefit-card{display:block;min-width:0;padding:4px;border:2px solid #071f43;border-radius:10px;background:linear-gradient(#fff7d6d9,#fff7d6d9),url('/site-v3/bonus/pixel-burst.jpg') center/cover;box-shadow:3px 4px 0 #d75d62;overflow:hidden}
.benefit-card:before{display:none}.bonus-kicker{display:block;margin:0 0 4px;color:#071f43!important;font-family:var(--font-parent-body),Montserrat,Arial,sans-serif;font-size:4.8px!important;font-weight:800!important;letter-spacing:.03em;text-align:center;text-transform:none}
.bonus-portrait{position:relative;width:100%;aspect-ratio:1;border:2px solid #071f43;border-radius:7px;overflow:hidden;background:#dcecff}.bonus-portrait>img:not(.coin){display:block;width:100%;height:100%;aspect-ratio:auto;object-fit:cover}.bonus-card-1 .bonus-portrait>img{object-position:51% 48%}.bonus-card-2 .bonus-portrait>img{object-position:50% 35%}.bonus-card-3 .bonus-portrait>img{object-position:64% 50%}
.bonus-copy{position:relative;margin-top:4px;min-height:35px;padding:5px 3px 7px;border-radius:6px;background:#fffaf0e8;text-align:center}.bonus-copy h3{margin:0;color:#071f43;font-family:Georgia,'Times New Roman',serif;font-size:8px;font-weight:700;line-height:1.04;letter-spacing:-.02em;text-transform:none}.bonus-copy i{position:absolute;left:50%;bottom:3px;width:17px;height:2px;border-radius:2px;background:#f28a22;transform:translateX(-50%)}
.coin-rain{background:radial-gradient(circle at 50% 44%,#4b86cb 0,#164b86 48%,#071f43 100%)}.coin-rain:before{content:'';position:absolute;inset:0;background:url('/site-v3/bonus/pixel-burst.jpg') center/cover;mix-blend-mode:screen;opacity:.25}.coin-rain .coin{position:absolute;display:block;object-fit:contain;filter:drop-shadow(2px 2px 0 #071f43)}.coin-one{left:7%;top:5%;width:30%;transform:rotate(-18deg)}.coin-two{right:5%;top:8%;width:38%;transform:rotate(12deg)}.coin-three{left:31%;top:39%;width:38%;transform:rotate(8deg)}.coin-four{left:2%;bottom:-3%;width:38%;transform:rotate(-8deg)}.coin-five{right:3%;bottom:3%;width:31%;transform:rotate(19deg)}
.cta-lockup{text-align:center}.cta-logo{margin:0 auto 2px}
@media(max-height:700px){.real-screens-label{top:191px}}
@media(max-width:430px){.real-screens-label{top:216px}.balance-card{top:319px}}

/* Final sequence spacing, light celebration, and production footer */
.world-runway{height:7200px}
.bike-quest{left:96px;right:auto;bottom:12px}
.balance-card{border:7px solid transparent;background:linear-gradient(#fff,#fff) padding-box,repeating-linear-gradient(135deg,#f5ad2d 0 8px,#f5ad2d 8px 12px,#2e64a4 12px 20px,#2e64a4 20px 24px) border-box;color:#071f43;box-shadow:0 0 0 3px #071f43,7px 7px 0 #f5ad2d}
.balance-card:before{inset:5px;background:repeating-conic-gradient(from 0deg at 50% 68%,#f5ad2d 0 4deg,transparent 4deg 14deg);opacity:.12}
.balance-card span{background:#071f43;color:#fff7d6;box-shadow:2px 2px 0 #f5ad2d}.balance-card small{color:#2e64a4;text-shadow:none}.balance-card strong{color:#071f43;text-shadow:3px 3px 0 #f5ad2d}.balance-card strong img{border-color:#071f43;box-shadow:2px 2px 0 #f5ad2d}.balance-spark{background:#f5ad2d;box-shadow:0 -5px 0 #f5ad2d,0 5px 0 #f5ad2d,-5px 0 0 #2e64a4,5px 0 0 #2e64a4}
.bottom-bar a,.footer-stores a{display:grid;place-items:center;color:#fff;background:#111;font-weight:900;text-decoration:none}.bottom-bar a{flex:1;min-height:44px;border:1px solid #777;border-radius:9px;font-size:10px}.footer-stores a{min-width:0;flex:1;padding:7px 3px;border:1px solid #18345a;border-radius:5px;background:#081a36;font-size:6px}
.close-panel{padding-bottom:20px}.site-footer{margin:0 -13px;padding:12px 14px calc(82px + env(safe-area-inset-bottom));display:flex;align-items:center;justify-content:space-between;gap:10px;background:#071f43;color:#fff7d6;font-family:var(--font-parent-body),Montserrat,Arial,sans-serif;font-size:7px}.site-footer span{font-weight:800;white-space:nowrap}.site-footer nav{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:5px 9px}.site-footer a{color:#fff7d6;font-weight:700;text-decoration:none}.site-footer a:hover,.site-footer a:focus-visible{color:#f5ad2d;text-decoration:underline}

/* Approved Item Shop-family milestone panel */
.balance-card{left:17px;right:auto;top:319px;width:190px;height:106px;padding:16px 13px 12px;border:6px solid #8e4d10;background:#061b3b;color:#071f43;box-shadow:0 0 0 4px #e99a18,7px 7px 0 #020d1e;overflow:visible;isolation:isolate}
.balance-card:before{content:'';position:absolute;z-index:-1;inset:6px;border:3px solid #e7a447;background:linear-gradient(#fff2ca,#f2ce85);box-shadow:inset 0 0 0 2px #7f4210;opacity:1}
.balance-card span{position:relative;left:auto;top:auto;margin:0 0 7px;padding:0;background:transparent;color:#143d73;box-shadow:none;font-family:var(--font-pixel),'Courier New',monospace;font-size:5.8px;font-weight:400;letter-spacing:0;white-space:nowrap}
.balance-card strong{position:relative;display:flex;align-items:center;justify-content:center;max-width:100%;gap:5px;color:#f0a51f;font-family:var(--font-pixel),'Courier New',monospace;font-size:20px;font-weight:400;line-height:1;text-shadow:2px 0 #071f43,-2px 0 #071f43,0 2px #071f43,0 -2px #071f43,3px 3px #8f4f10;white-space:nowrap}
.balance-card strong img{width:28px;height:28px;flex:0 0 28px;border:0;border-radius:0;box-shadow:none;object-fit:contain;filter:drop-shadow(2px 2px 0 #8f4f1066)}
.balance-card small{position:relative;margin-top:9px;color:#d75d62;font-family:var(--font-pixel),'Courier New',monospace;font-size:6px;font-weight:400;letter-spacing:0;text-shadow:1px 1px 0 #fff7d6}
.balance-card .balance-number{position:relative;left:auto;top:auto;display:inline-flex;align-items:baseline;margin:0;padding:0;background:transparent;color:inherit;box-shadow:none;font:inherit;letter-spacing:0}.balance-number b{font:inherit}.balance-number i{margin:0 -4px 0 -1px;font:inherit;font-style:normal;transform:translateY(1px)}

/* Approved matched top-and-bottom navigation framing */
.top-bar:after{content:'';position:absolute;z-index:1;left:13px;right:13px;bottom:7px;height:1px;background:#ffffff61;pointer-events:none}
.bottom-bar{position:relative;padding:20px 12px 10px;gap:9px;background:linear-gradient(#171717,#080808)}
.bottom-bar:before{content:'TRY THE APP';position:absolute;z-index:3;left:50%;top:0;padding:5px 13px;background:#f2a23a;color:#071f43;box-shadow:3px 3px 0 #d75d62;font-family:var(--font-pixel),'Courier New',monospace;font-size:7px;line-height:1;white-space:nowrap;transform:translate(-50%,-42%)}
.bottom-bar:after{content:'';position:absolute;z-index:1;left:13px;right:13px;top:7px;height:1px;background:#ffffff61;pointer-events:none}
.bottom-bar a{position:relative;z-index:2;min-height:48px;border-color:#ffffff38;border-radius:10px;background:#222;font-size:10px}
.site-footer{padding:12px 14px 14px}
@media(max-width:430px){.bottom-bar{padding:20px 12px max(10px,env(safe-area-inset-bottom))}.site-footer{padding-bottom:14px}}

/* Pricing-led Our Difference layout and simplified conversion path */
.payoff>.eyebrow,.payoff>h2{text-align:left}.payoff h2 span{display:block}.difference-grid{display:grid;grid-template-columns:minmax(0,1.72fr) minmax(112px,.82fr);gap:10px;align-items:stretch}.difference-grid .benefit-cards{grid-template-columns:repeat(2,minmax(0,1fr));gap:7px;padding-bottom:0}.difference-grid .benefit-card{height:100%}.difference-grid .bonus-kicker{font-size:5.2px!important}.difference-grid .bonus-copy{min-height:39px;padding-top:6px}.difference-grid .bonus-copy h3{font-size:9.2px}.difference-side{display:flex;min-width:0;flex-direction:column;gap:9px}.difference-founders-note{padding:10px 9px 9px;border:1px solid rgba(7,31,67,.2);border-radius:10px;background:rgba(255,255,255,.88);box-shadow:0 4px 12px rgba(7,31,67,.08);color:#071f43}.difference-founders-note p{margin:0 0 7px;font-family:var(--font-parent-body),Montserrat,Arial,sans-serif;font-size:13.6px;font-weight:600;line-height:1.38}.difference-founders-note .founders-signoff{color:#d75d78;font-family:var(--font-kid-title),Fredoka,Arial,sans-serif;font-size:14.4px;font-weight:800}.difference-founders-note .rewards-tip{margin:9px 0 0;padding-top:8px;border-top:1px dashed #f2a23a;font-size:12.2px;line-height:1.35}.difference-founders-note .rewards-tip b{color:#d65e24}.pricing-module{padding:10px 8px 11px;border:3px solid #071f43;border-radius:10px;background:#fffaf0;box-shadow:4px 4px 0 #f2a23a;color:#071f43}.pricing-module>small{display:block;color:#d75d62;font-family:var(--font-parent-body),Montserrat,Arial,sans-serif;font-size:5px;font-weight:900;letter-spacing:.08em}.pricing-module>strong{display:flex;align-items:baseline;gap:3px;margin:8px 0 9px}.pricing-module>strong s{color:#ef6483;font-family:var(--font-kid-title),Fredoka,Arial,sans-serif;font-size:10px;font-weight:800;text-decoration-thickness:2px}.pricing-module>strong b{font-family:Georgia,'Times New Roman',serif;font-size:29px;line-height:.85}.pricing-module>strong em{font-family:var(--font-parent-body),Montserrat,Arial,sans-serif;font-size:7px;font-style:normal;font-weight:800}.pricing-module ul{display:grid;gap:6px;margin:0;padding:0;list-style:none}.pricing-module li{position:relative;padding-left:10px;font-size:6.5px;font-weight:800;line-height:1.2}.pricing-module li:before{content:'✓';position:absolute;left:0;color:#f2a23a;font-weight:1000}
.cta-lockup{display:flex;flex-direction:column;align-items:center;text-align:center}.cta-lockup>small{margin:2px 0 10px;color:#d63a6c;font-size:9px;font-weight:900;line-height:1.2}.cta-button{display:inline-grid;place-items:center;min-width:132px;min-height:36px;padding:8px 13px;border:3px solid #071f43;border-radius:8px;background:#f2a23a;color:#071f43;box-shadow:4px 4px 0 #d75d62;font-family:var(--font-parent-body),Montserrat,Arial,sans-serif;font-size:10px;font-weight:1000;text-decoration:none}.cta-button:hover,.cta-button:focus-visible{background:#ffc35e;transform:translateY(-1px)}
.bottom-bar:before{content:'GET THE APP'}.bottom-bar{justify-content:center}.bottom-bar a{flex:0 1 280px;width:min(280px,100%);font-family:var(--font-parent-body),Montserrat,Arial,sans-serif;font-weight:900;letter-spacing:.04em}
@media(max-width:350px){.difference-grid{grid-template-columns:minmax(0,1.58fr) minmax(102px,.82fr);gap:7px}.difference-grid .benefit-cards{gap:5px}.difference-grid .bonus-copy h3{font-size:8px}.difference-founders-note{padding-inline:7px}.difference-founders-note p{font-size:12px}.difference-founders-note .rewards-tip{font-size:11px}.pricing-module{padding-inline:6px}.pricing-module>strong b{font-size:25px}}
.balance-spark{background:#f5ad2d;box-shadow:0 -5px 0 #f5ad2d,0 5px 0 #f5ad2d,-5px 0 0 #f5ad2d,5px 0 0 #f5ad2d}.balance-spark.spark-one{right:9px;top:-10px}.balance-spark.spark-two{left:-9px;top:53px}.balance-spark.spark-three{right:-8px;bottom:15px}

/* Desktop cinematic adaptation. The mobile branch remains unchanged. */
@media(min-width:900px){
  html,body{height:100%;overflow:hidden;background:#d9dde6}
  .prototype-shell{min-height:100dvh;padding:0}
  .phone-frame{width:100%;height:100dvh;border:0;border-radius:0;grid-template-rows:76px minmax(0,1fr)}
  .top-bar{padding:8px 28px;background:linear-gradient(180deg,#181818,#080808)}
  .top-bar:after{left:28px;right:28px;bottom:8px}
  .top-bar>img{width:132px;height:60px}
  .founder-promo{margin-left:auto;margin-right:28px;padding:4px 20px 4px 24px;font-size:20px;line-height:1.2}
  .founder-promo strong{font-size:18px}.founder-promo b{font-size:22px}
  .menu-toggle{width:48px;height:48px;padding:12px}.menu-toggle i{width:22px}
  .site-menu{top:67px;right:26px;width:174px}.site-menu a{padding:13px;font-size:11px}
  .stage-scroll{width:100%;overflow-x:hidden}
  .bottom-bar{min-height:82px;padding:22px 28px 12px;background:linear-gradient(#171717,#070707)}
  .bottom-bar:after{left:28px;right:28px}
  .bottom-bar:before{padding:6px 18px;font-size:8px}
  .bottom-bar a{flex:0 0 320px;min-height:50px;font-size:12px}

  /* TRACK FLOORS ARE MEASURED FROM THE CONTENT, not from the design canvas. They were
   * 320/320/220 = 860px, but at a 900px window this row only has 706px after padding and gaps,
   * so the desktop layout could not physically fit until 1080px and .app-intro's overflow:hidden
   * silently clipped it across that whole 180px range. What the columns actually need:
   *   230  .copy-block h1's spans are white-space:nowrap -- "YOUR HOUSE." at 40px
   *   215  .screen-card 158px + .screen-card.rear 139px at margin-left:-82px (its transform
   *        does not affect layout, so the layout width is the overlap, not the visual extent)
   *   170  .hani-invite's img; the <p> under it wraps freely
   * 615 total, which leaves the fr ratios in charge at every width from 900 up -- these floors
   * are a safety net again rather than the thing setting the layout. If the headline is ever
   * allowed to wrap, col 1's floor can go too and this becomes fully fluid. */
  .app-intro{height:570px;grid-template-columns:minmax(230px,1.05fr) minmax(215px,.9fr) minmax(170px,.66fr);gap:34px;padding:42px clamp(48px,7vw,92px) 52px;background-position:center 68%;background-size:cover}
  .app-intro .copy-block{align-self:center;padding:0}
  .eyebrow{margin-bottom:12px;font-size:22px}
  .copy-block h1{margin-bottom:20px;font-size:56px;line-height:.9}
  .copy-block p:not(.eyebrow){max-width:390px;margin-bottom:18px;font-size:34px;line-height:1.42}
  .copy-block strong{font-size:17px;line-height:1.35}
  .phone-screens{align-self:center;justify-content:center}
  .screen-card{width:158px;height:336px;border-width:5px;border-radius:25px;box-shadow:0 18px 0 #25345a22}
  .screen-card.rear{width:139px;height:300px;margin-left:-82px;transform:translate(42px,25px) rotate(5deg)}
  .hani-invite{align-self:center;max-width:230px}
  .hani-invite img{width:166px;height:194px}
  .hani-invite p{margin:8px 0 0;padding:13px 12px;border-width:3px;border-radius:14px;font-size:28px;line-height:1.28;box-shadow:5px 5px 0 #f2a23a}

  .world-runway{height:7600px}
  .sticky-world{top:0;height:100%;max-height:calc(100vh - 76px);min-height:610px;padding:10px 18px;background:radial-gradient(circle at 50% 44%,#181818 0,#0c0c0c 58%,#050505 100%)}
  .house-board{width:400px;height:600px;margin:0 auto;overflow:visible}
  .house-master{width:400px;height:600px}
  .house-overlays{width:330px;height:495px;transform:scale(1.212121);transform-origin:top left}
  .yard-dog{top:41px;width:24px;height:20px}
  .hani-guide{right:clamp(22px,calc(50% - 540px),120px);top:96px;width:230px}
  .hani-guide img{width:160px;height:182px}
  .hani-guide p{margin-top:-4px;padding:18px 15px 15px;font-size:28px;line-height:1.3;box-shadow:0 0 0 5px #111,8px 8px 0 var(--gold)}
  .hani-guide p:before{left:12px;top:-11px;padding:3px 7px;font-size:18px}
  .hani-welcome{right:clamp(22px,calc(50% - 540px),120px);top:86px;width:230px}
  .hani-welcome p{font-size:28px}
  .hani-guide.focus-bike{left:clamp(22px,calc(50% - 540px),120px);right:auto;top:250px;width:230px}
  .hani-guide.focus-bike img,.hani-guide.focus-points img{width:160px;height:182px}
  .hani-guide.focus-bike p,.hani-guide.focus-points p{font-size:28px}
  .hani-guide.focus-points{left:clamp(22px,calc(50% - 540px),120px);right:auto;top:88px;width:230px}
  .scroll-nudge{right:34px;top:50%;transform:translateY(-50%)}
  .scroll-nudge span{padding:5px 8px;font-size:7px}.scroll-nudge i{width:30px;height:30px;font-size:22px}
  .balance-card{left:calc(100% + 42px);right:auto;top:255px;width:248px;height:138px;padding:21px 17px 16px}
  .balance-card span{font-size:8px}.balance-card strong{font-size:27px}.balance-card strong img{width:36px;height:36px;flex-basis:36px}.balance-card small{font-size:8px}

  .reward-stack{position:relative;display:grid;grid-template-columns:230px minmax(0,1fr);align-items:center;justify-content:center;gap:44px;width:100%;height:100%;padding:32px 54px;overflow:hidden}
  .reward-guide,.hani-guide.focus-points.reward-guide{position:relative;left:auto;right:auto;top:auto;width:230px;align-self:center}
  .reward-guide img,.hani-guide.focus-points.reward-guide img{width:174px;height:198px;margin:0 auto}
  .reward-guide p,.hani-guide.focus-points.reward-guide p{margin:0;padding:18px 15px 15px;font-size:28px;line-height:1.3}
  .reward-swipe-stage{position:relative;left:auto;top:auto;transform:none;align-self:center;width:min(100%,calc((tan(atan2(100vh,1px)) - 160) * 1.5px));height:auto;margin:0 auto;aspect-ratio:3/2;border-width:4px;border-radius:18px;box-shadow:9px 9px 0 #0006}
  .real-screens-label{left:calc(50% + 112px);top:38px;padding:8px 14px;border-width:3px;font-size:20px;box-shadow:4px 4px 0 #d75d62}

  .payoff{padding:52px clamp(48px,6vw,76px) 0;overflow:hidden}
  .payoff>.eyebrow,.payoff>h2{text-align:left}
  .payoff h2{max-width:1100px;margin:0 auto 28px;font-size:48px;line-height:.94}
  .payoff>.eyebrow{max-width:1100px;margin:0 auto 10px;font-size:22px}
  .difference-grid{max-width:1100px;margin:0 auto;grid-template-columns:minmax(0,1fr) 310px;gap:28px}
  .difference-grid .benefit-cards{grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}
  .difference-grid .benefit-card{padding:8px;border-width:3px;border-radius:14px;box-shadow:5px 6px 0 #d75d62}
  .difference-grid .bonus-kicker{margin-bottom:7px;font-size:9px!important}
  .bonus-portrait{border-width:3px;border-radius:10px}
  .difference-grid .bonus-copy{min-height:66px;margin-top:7px;padding:11px 7px 14px}
  .difference-grid .bonus-copy h3{font-size:15px;line-height:1.08}
  .bonus-copy i{bottom:6px;width:28px;height:3px}
  .difference-side{gap:18px}
  .difference-founders-note{padding:22px 20px 18px;border-radius:16px}
  .difference-founders-note p{margin-bottom:12px;font-size:26px;line-height:1.45}
  .difference-founders-note .founders-signoff{font-size:28px}
  .difference-founders-note .rewards-tip{margin-top:15px;padding-top:14px;font-size:24px}
  .pricing-module{padding:20px 18px 22px;border-width:4px;border-radius:15px;box-shadow:7px 7px 0 #f2a23a}
  .pricing-module>small{font-size:9px}.pricing-module>strong{margin:14px 0 17px;gap:6px}.pricing-module>strong s{font-size:18px}.pricing-module>strong b{font-size:50px}.pricing-module>strong em{font-size:13px}.pricing-module ul{gap:10px}.pricing-module li{padding-left:18px;font-size:12px}
  .close-panel{margin:52px calc(clamp(48px,6vw,76px) * -1) 0;padding:48px clamp(58px,8vw,104px);grid-template-columns:1fr 1fr;gap:44px;min-height:285px}
  .cta-logo{width:190px;height:92px}.cta-lockup>small{margin:4px 0 17px;font-size:15px}.cta-button{min-width:220px;min-height:52px;padding:12px 20px;border-width:4px;border-radius:11px;font-size:15px;box-shadow:6px 6px 0 #d75d62}
  .brand-signoff p{font-size:40px;line-height:1.2}.footer-hani{width:108px;height:108px}.footer-hani-wrap span{margin-bottom:46px;padding:11px 13px;font-size:13px}
  .site-footer{margin:0 calc(clamp(48px,6vw,76px) * -1);padding:18px clamp(48px,6vw,76px);font-size:11px}
  .site-footer nav{gap:10px 18px}
}

@media(min-width:900px) and (max-height:760px){
  .phone-frame{grid-template-rows:66px minmax(0,1fr)}
  .top-bar>img{height:50px}.top-bar{padding-block:6px}.bottom-bar{min-height:70px;padding-top:19px}.bottom-bar a{min-height:42px}
  .app-intro{height:470px;padding-block:28px 34px}.copy-block h1{font-size:48px}.screen-card{width:132px;height:280px}.screen-card.rear{width:116px;height:250px}.hani-invite img{width:132px;height:154px}
  .sticky-world{max-height:calc(100vh - 66px);min-height:520px}
  .house-board{width:350px;height:525px}.house-master{width:350px;height:525px}.house-overlays{transform:scale(1.060606)}
  .hani-guide,.hani-welcome,.hani-guide.focus-bike,.hani-guide.focus-points{transform:scale(.86)}
  .reward-stack{grid-template-columns:200px minmax(0,1fr);gap:28px;padding-block:18px}.reward-swipe-stage{width:min(100%,calc((tan(atan2(100vh,1px)) - 132) * 1.5px))}
}

/* Desktop refinement: one steady Hani position and a compact 2x2 Difference grid. */
@media(min-width:900px){
  .house-board{transform:translateX(-135px)}
  .sticky-world > .hani-guide{
    left:calc(50% + 80px);
    right:auto;
    top:58px;
    width:300px;
    transform:none;
    transform-origin:top center;
  }
  .sticky-world > .hani-guide img{
    width:214px;
    height:238px;
    margin:0 auto;
  }
  .sticky-world > .hani-guide p{
    margin:0;
    padding:21px 18px 18px;
    font-size:32px;
    line-height:1.3;
    box-shadow:0 0 0 5px #111,9px 9px 0 var(--gold);
  }
  .sticky-world > .hani-guide p:before{left:14px;top:-12px;padding:4px 8px;font-size:20px}
  .balance-card{left:calc(100% + 66px);top:432px}

  .difference-grid{grid-template-columns:minmax(0,1fr) 310px;align-items:start}
  .difference-grid .benefit-cards{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
  .difference-grid .benefit-card{
    display:grid;
    grid-template-columns:44% minmax(0,1fr);
    grid-template-rows:22px minmax(0,1fr);
    height:190px;
    padding:8px;
  }
  .difference-grid .bonus-kicker{grid-column:1/-1;grid-row:1;margin:0;font-size:9px!important}
  .difference-grid .bonus-portrait{grid-column:1;grid-row:2;width:100%;height:100%;aspect-ratio:auto}
  .difference-grid .bonus-copy{grid-column:2;grid-row:2;display:grid;place-items:center;min-height:0;height:100%;margin:0 0 0 8px;padding:14px 10px 18px}
  .difference-grid .bonus-copy h3{font-size:18px;line-height:1.08}
  .difference-grid .bonus-copy i{bottom:9px;width:34px}
}

@media(min-width:900px) and (max-height:760px){
  .house-board{transform:translateX(-112px)}
  .sticky-world > .hani-guide{left:calc(50% + 72px);top:42px;transform:scale(.84)}
  .balance-card{top:372px}
}

/* Larger desktop story UI and a compact shared pricing/signoff row. */
.difference-grid>.benefit-cards{grid-row:1/3}
.difference-grid>.difference-side{grid-column:2;grid-row:1}
.conversion-row{display:contents}
.conversion-row>.pricing-module{grid-column:2;grid-row:2}
.conversion-row>.close-panel{grid-column:1/-1;grid-row:3}

@media(min-width:900px){
  .sticky-world > .hani-guide{width:340px}
  .sticky-world > .hani-guide img{width:230px;height:256px}
  .sticky-world > .hani-guide p{padding:24px 22px 21px;font-size:36px;line-height:1.3}
  .sticky-world > .hani-guide p:before{font-size:22px}

  .house-overlays .quest{scale:1.28;transform-origin:center}
  .house-overlays .action-copy,
  .house-overlays .point-pop,
  .house-overlays .snap{scale:1.32;transform-origin:center}
  .character-sprite.eli-guitar,
  .character-sprite.eli-living,
  .character-sprite.eli-bike{scale:1.22;transform-origin:center bottom}
  .character-sprite.lena{scale:-1.22 1.22;transform-origin:center bottom}
  .balance-card{scale:1.12;transform-origin:left top}

  .reward-stack{grid-template-columns:270px minmax(0,1fr)}
  .reward-guide,.hani-guide.focus-points.reward-guide{width:270px}
  .reward-guide img,.hani-guide.focus-points.reward-guide img{width:194px;height:218px}
  .reward-guide p,.hani-guide.focus-points.reward-guide p{padding:21px 18px 18px;font-size:32px}
  .real-screens-label{scale:1.18}

  .difference-grid>.benefit-cards{grid-row:1}
  .difference-grid>.difference-side{grid-column:2;grid-row:1}
  .conversion-row{
    display:grid;
    grid-column:1/-1;
    grid-row:2;
    grid-template-columns:310px minmax(0,1fr);
    gap:28px;
    align-items:stretch;
    margin-top:10px;
  }
  .conversion-row>.pricing-module{grid-column:1;grid-row:1}
  .conversion-row>.close-panel{
    grid-column:2;
    grid-row:1;
    min-height:190px;
    margin:0;
    padding:22px 34px;
    grid-template-columns:.9fr 1.1fr;
    gap:28px;
    align-items:center;
    border-radius:16px;
  }
  .conversion-row .cta-logo{width:165px;height:78px}
  .conversion-row .cta-lockup>small{margin:2px 0 12px;font-size:13px}
  .conversion-row .cta-button{min-width:190px;min-height:46px;font-size:14px}
  .conversion-row .brand-signoff{align-self:center}
  .conversion-row .brand-signoff p{font-size:32px;line-height:1.18}
  .conversion-row .footer-hani{width:82px;height:82px}
  .conversion-row .footer-hani-wrap{margin-top:2px}
  .conversion-row .footer-hani-wrap span{margin-bottom:34px;padding:8px 10px;font-size:11px}
  .site-footer{margin-top:24px}
}

@media(min-width:900px) and (max-height:760px){
  .house-overlays .quest{scale:1.18}
  .house-overlays .action-copy,
  .house-overlays .point-pop,
  .house-overlays .snap{scale:1.2}
  .character-sprite.eli-guitar,
  .character-sprite.eli-living,
  .character-sprite.eli-bike{scale:1.14}
  .character-sprite.lena{scale:-1.14 1.14}
}

/* House scene sized to the stage HEIGHT, not the width.
 *
 * The scene is locked 2:3 -- house-approved-locked.png is 800x1200 and .house-overlays is a
 * 330x495 coordinate space holding every quest, sprite and the balance card as absolute px.
 * So it can only grow until it hits the height of the stage, and the width follows at 2/3.
 *
 * ONE TRANSFORM ON .house-board, NOT THREE COUPLED SIZES. The obvious alternative -- resizing
 * .house-board and .house-master and re-deriving .house-overlays' scale as boardWidth/330, the
 * way the max-height:760px step above does -- has to keep three numbers in agreement, and
 * .yard-dog is a child of .house-board rather than .house-overlays so it needs a fourth by hand.
 * Get any of them out of step and every quest bubble lands in the wrong room, silently. Scaling
 * the whole subtree by one factor cannot drift.
 *
 * CONTINUOUS, NOT STEPPED. This started as four min-height breakpoints and they were visibly
 * short between steps -- at a 1039px viewport the house sat on the 920px step's 1.23 when it had
 * room for 1.43, stopping ~17% above the floor. tan(atan2(<length>,1px)) is the standard way to
 * get a unitless number out of a length, which is the one thing plain calc() cannot do, so the
 * fit is exact at every height instead of at four of them.
 *
 * --k-fit-height: 600 is the board's flow height; 96px is the frame's single bar row (76px) plus
 * .sticky-world's block padding (20px). This is the factor that makes the house exactly fill.
 *
 * --k-fit-viewport is only a keep-it-on-screen backstop: the board is CENTRED, so its right edge
 * is 50% + 200k and it just has to stay inside the stage. It does not bind at any realistic
 * desktop size -- height always does -- which is the point. It used to be a much tighter
 * vw/400 - 1.625 because the board was shifted 135px left and the balance card stood off its
 * right edge; both of those are gone.
 *
 * WHY THE SHIFT AND THE STAND-OFF WENT. Together they were a clipping bug. The card reached
 * 429 board-px past the board's right edge -- left:calc(100% + 66px) (:329) on a 330px overlay,
 * 248px wide, times scale:1.12 (:374), times the overlay's own 1.212121 (:243) -- so
 * .sticky-world's overflow:hidden cut it off whenever k > vw/1258 + 0.186. That is false at
 * 1920x1080 and TRUE at 1512x982, 1728x1117, 1920x1200 and 2560x1440, which is why it only
 * showed up on some screens. Centring the board and overlaying the card inside it removes the
 * geometry that caused it rather than bounding k around it.
 *
 * The clamp floor of 1 keeps the established 400x600 as the minimum; the ceiling of 2.4 stops a
 * very tall display from scaling the pixel art past what it was drawn for.
 *
 * transform-origin:top center IS LOAD-BEARING. .house-board is a plain block at the TOP of
 * .sticky-world (margin:0 auto, no vertical margin), so scaling about the default centre would
 * grow it upward past the stage top, where .sticky-world's overflow:hidden clips it.
 *
 * NO translateX. The board is centred at every width, matching the mobile layout. The -135px
 * shift set above is overridden here; it existed to open a gap on the right for the balance card,
 * which now sits on the house instead.
 *
 * If a browser lacks the trig functions the whole declaration is invalid and the house falls back
 * to the unscaled translateX(-135px) above -- the behaviour before this block existed.
 */
@media(min-width:900px){
  .house-board{
    --k-fit-height:calc((tan(atan2(100vh,1px)) - 96) / 600);
    --k-fit-viewport:calc(tan(atan2(100vw,1px)) / 400 - 0.09);
    transform:scale(clamp(1,min(var(--k-fit-height),var(--k-fit-viewport)),2.4));
    transform-origin:top center;
  }

  /* Balance card OVERLAID ON the house, centred, instead of standing off its right edge.
   * It is a child of .house-overlays, so these are coordinates in the 330x495 space: the card
   * is 248x138 with scale:1.12 (:374) = 277.8x154.6 visually, which centres at left 26 / top 170.
   * Overrides :329's left:calc(100% + 66px)/top:432px and :350's top:372px.
   * z-index clears the sprites, which sit at 3. */
  .balance-card{left:26px;right:auto;top:170px;z-index:15}
}

/* CTA moved from the bottom bar to the middle of the top bar, DESKTOP ONLY.
 *
 * MOBILE IS UNTOUCHED ON PURPOSE. The stylesheet header records "<= 430px approved full-width
 * mobile experience; sticky top bar, fixed bottom CTA" as part of the handoff, so below 900px the
 * fixed bottom bar stays exactly as approved and .top-cta is not rendered at all.
 *
 * WHY A SECOND ANCHOR RATHER THAN MOVING THE ONE IN THE MARKUP. The CTA lives inside
 * .bottom-bar, and mobile still needs it there. CSS cannot move an element between parents, so
 * the top bar carries its own anchor and exactly one of the two is ever displayed.
 *
 * Absolutely centred rather than placed in the flex row, because .top-bar is
 * justify-content:space-between over a logo, the founder promo and the menu button -- centring by
 * flex would put the CTA at the midpoint of whatever space those happen to leave, which moves as
 * the promo text reflows. left:50% is the middle of the BAR, which is what was asked for.
 *
 * FIVE CONSTANTS MOVED TOGETHER WITH THIS. Dropping the bottom row changes the frame grid, and
 * three separate rules encoded the old two-bar total: .phone-frame's rows, .sticky-world's
 * max-height (158 -> 76, and 136 -> 66 on the short-desktop variant) and the house fit's 178 -> 96
 * (one bar row plus .sticky-world's 20px block padding). They must stay in agreement or the house
 * silently overflows the stage or stops short of it.
 *
 * The gold "GET THE APP" pixel tab was .bottom-bar:before and went with the bar; it is not
 * reproduced here.
 */
.top-cta{display:none}

@media(min-width:900px){
  .bottom-bar{display:none}
  .top-cta{position:absolute;z-index:3;left:50%;top:50%;transform:translate(-50%,-50%);display:grid;place-items:center;width:300px;min-height:46px;padding:0 18px;border:1px solid #ffffff38;border-radius:10px;background:#222;color:#fff;font-family:var(--font-parent-body),Montserrat,Arial,sans-serif;font-size:12px;font-weight:900;letter-spacing:.04em;text-decoration:none}
}

/* Short desktop keeps a 66px bar, so the house fit's constant is 66 + 20 rather than 76 + 20. */
@media(min-width:900px) and (max-height:760px){
  .top-cta{min-height:40px;font-size:11px}
  .house-board{--k-fit-height:calc((tan(atan2(100vh,1px)) - 86) / 600)}
}

/* The gold "GET THE APP" tab, back on the top bar's separator under the CTA.
 *
 * This is .bottom-bar:before rebuilt on .top-bar:before -- same gold, same offset red shadow,
 * same Courier fallback -- because the bar that used to carry it is display:none above 900px.
 * .top-bar:after is the separator hairline (left:28px right:28px bottom:8px), so bottom:8px with
 * translateY(50%) centres the tab exactly ON that line rather than above or below it.
 *
 * NOTE ON THE FONT: var(--font-pixel) is NOT DEFINED anywhere in this stylesheet, so this and the
 * mobile tab both render in the 'Courier New' fallback. The document does load Press Start 2P and
 * nothing consumes it -- the design package presumably defined --font-pixel through next/font and
 * it did not survive the port. Left as-is deliberately: defining it now would silently restyle the
 * approved mobile tab too, and Press Start 2P is far wider at the same size against a
 * white-space:nowrap box.
 *
 * The CTA shifts up 8px to clear it -- the tab occupies roughly 58-78px down a 76px bar, and a
 * 46px button centred at 50% would have run into its top edge by about 3px.
 */
@media(min-width:900px){
  .top-bar:before{content:'GET THE APP';position:absolute;z-index:3;left:50%;bottom:8px;transform:translate(-50%,50%);padding:6px 18px;background:#f2a23a;color:#071f43;box-shadow:3px 3px 0 #d75d62;font-family:var(--font-pixel),'Courier New',monospace;font-size:8px;line-height:1;white-space:nowrap;pointer-events:none}
  .top-cta{top:calc(50% - 8px)}
}

/* Short desktop keeps a 66px bar, so the tab and the clearance both come down a notch. */
@media(min-width:900px) and (max-height:760px){
  .top-bar:before{padding:4px 13px;font-size:7px}
  .top-cta{top:calc(50% - 7px)}
}

/* Same height fit below desktop. The two fixed scales this replaces -- scale(.84) at
 * max-height:700px and scale(1.06) at max-width:430px/min-height:701px -- were the phone
 * equivalent of the four breakpoints the desktop rule started as, and left the same slack.
 *
 * WIDTH USUALLY BINDS HERE, AND THAT IS NOT A BUG. The art is 2:3 (0.667) and a phone viewport is
 * nearer 0.46-0.56 -- MORE portrait than the art -- so on everything but the shortest handsets
 * the board runs out of width before it runs out of height, and some vertical slack is
 * unavoidable without cropping the scene. --k-fit-width is doing real work at these sizes,
 * unlike on desktop where it is only a backstop.
 *
 * .house-overlays has no scale of its own below 900px (base inset:0, not the desktop 330x495 +
 * scale(1.212121)), so the board's own factor is the only one in play and the balance card,
 * already inside the board on mobile, comes along with it.
 *
 * <=430px  usable height = 100dvh - 68 (sticky .top-bar) - 78 (FIXED .bottom-bar, which overlays
 *          the stage rather than taking flow space) - 8 (.sticky-world padding) = 100dvh - 154.
 *          dvh, not vh, to match .sticky-world's own height, which is already dvh-based.
 * 431-899  both bars are still grid rows and .sticky-world keeps its 12px padding, so the
 *          subtrahend is 68 + 78 + 24 = 170 and the width allowance is 100vw - 24.
 */
@media(max-width:430px){
  .house-board{
    /* The bottom bar is NOT a flat 78px on every phone, which the old constant assumed.
     * It is position:fixed with min-height:78px and
     * padding:20px 12px max(10px,env(safe-area-inset-bottom)) over a 44px link, so its real
     * height is max(78, 64 + max(10, inset)). On Android the inset is 0, that resolves to
     * max(78,74) = 78 and nothing changes. On a notched iPhone the inset is about 34, which
     * gives max(78,98) = 98 -- 20px taller than assumed, so the house was being scaled and
     * centred against 20px of room that is actually underneath the bar.
     *
     * --bar-px restates the bar's own formula rather than hardcoding a result, so it tracks
     * whatever the device reports. 76 is the rest: 68 sticky .top-bar + 8 .sticky-world padding.
     * env() STAYS OUT OF THE TRIG, deliberately. The first version of this nested
     * env(safe-area-inset-bottom) inside atan2(), and Safari is far stricter than Chrome about
     * env() inside math functions -- if it rejects that, --bar-px is invalid, which poisons
     * --stage-px, --k-fit-height and --k in turn, so transform:scale(var(--k)) is DISCARDED and
     * margin-top collapses to 0. The board then sits unscaled at the top of the stage with all
     * the slack below it, which is exactly how it looked on iPhone while Android was fine.
     * Here env() is only ever inside a plain calc(), which is universally supported.
     *
     * The centring margin is pure length arithmetic now and touches no math function at all, so
     * it survives even if the one remaining tan(atan2()) ever fails. Only --k-fit-height converts
     * a length to a number, because scale() needs a unitless value and calc() cannot divide a
     * length by a length. */
    --bar-len:max(78px,calc(64px + max(10px,env(safe-area-inset-bottom,0px))));
    --stage-len:calc(100dvh - 76px - var(--bar-len));
    --k-fit-height:calc(tan(atan2(var(--stage-len),1px)) / 495);
    --k-fit-width:calc((tan(atan2(100vw,1px)) - 12) / 330);
    --k:clamp(1,min(var(--k-fit-height),var(--k-fit-width)),2.4);
    transform:scale(var(--k));
    transform-origin:top center;
    /* CENTRE THE VISUAL BOX, NOT THE FLOW BOX. transform does not affect layout, so the board
     * still occupies its unscaled 495px at the top of .sticky-world while painting 495*k tall --
     * which is why it hugged the top with the slack underneath. This is the leftover height
     * halved. max(0px,...) matters: when the height bound wins the two are equal and this is 0,
     * and on a viewport short enough for the clamp floor to hold k at 1 it would otherwise go
     * negative and pull the board off the top. */
    margin-top:max(0px,calc((var(--stage-len) - var(--k) * 495px) / 2));
    margin-bottom:0;
  }
}

@media(min-width:431px) and (max-width:899px){
  .house-board{
    --k-fit-height:calc((tan(atan2(100vh,1px)) - 170) / 495);
    --k-fit-width:calc((tan(atan2(100vw,1px)) - 24) / 330);
    --k:clamp(1,min(var(--k-fit-height),var(--k-fit-width)),2.4);
    transform:scale(var(--k));
    transform-origin:top center;
    /* CENTRE THE VISUAL BOX, NOT THE FLOW BOX. transform does not affect layout, so the board
     * still occupies its unscaled 495px at the top of .sticky-world while painting 495*k tall --
     * which is why it hugged the top with the slack underneath. This is the leftover height
     * halved. max(0px,...) matters: when the height bound wins the two are equal and this is 0,
     * and on a viewport short enough for the clamp floor to hold k at 1 it would otherwise go
     * negative and pull the board off the top. */
    margin-top:max(0px,calc((tan(atan2(100vh,1px)) - 170 - 495 * var(--k)) * .5px));
    margin-bottom:0;
  }
}

/* Scrollbars hidden on the stage, scrolling untouched.
 *
 * scrollbar-width:none is the standard property; ::-webkit-scrollbar{display:none} is what Safari
 * and Chrome still need. Both are required -- neither covers every engine on its own.
 *
 * scrollbar-gutter:stable went with them. It reserved a permanent ~15px column for a scrollbar
 * that no longer paints, which is why .sticky-world measured narrower than the viewport, so
 * removing it hands that width back to the stage.
 *
 * The scroll affordance is not lost: .scroll-nudge is the design's own cue and is still there.
 * hanis-world.js reads scroller.scrollTop above 430px and window.scrollY below it -- neither is
 * affected by whether the bar is painted.
 */
.stage-scroll::-webkit-scrollbar{display:none}

/* Mobile app-intro: slide the phone mockups right and drop them behind Hani.
 *
 * position:relative IS REQUIRED, not decoration -- .phone-screens sets no position of its own, so
 * z-index on it would be ignored. Its siblings are already stacked (.copy-block z-index:3,
 * .hani-invite z-index:5), so 1 puts the mockups under both while keeping them over the
 * background art.
 *
 * translateX is a TRANSFORM, so it moves the mockups WITHOUT changing the grid. The intro is
 * grid-template-columns:1.12fr .92fr .75fr and .copy-block's track is unchanged by this, so the
 * paragraph does not actually get wider -- it gets clear space beside it to grow into. See below.
 */
@media(max-width:430px){
  .phone-screens{position:relative;z-index:1;transform:translateX(10%)}

  /* Hand the 10% the mockups vacated to the copy, in the TRACK rather than as an overflow.
   * Two transfers of .092fr each -- 10% of .phone-screens' original .92fr share, twice -- so
   * .92 -> .736 and 1.12 -> 1.304. The total stays 2.79fr, so .hani-invite's column is untouched.
   *
   * .736fr is NARROWER THAN THE MOCKUPS' INTRINSIC WIDTH: .screen-card is 77px and .screen-card
   * .rear is 68px at margin-left:-45px, so they need ~100px against a ~93px track. min-width:0 on
   * .phone-screens lets the track shrink and the cards spill, which is fine only because they are
   * now z-index:1 and translated right -- they spill UNDER .hani-invite by design. Take more than
   * this and they start spilling past it. */
  .app-intro{grid-template-columns:1.304fr .736fr .75fr}
}

/* Below 900px the <p> scale is 1.5x the design's original, not the 2x desktop keeps.
 *
 * The doubling earlier in this file is applied IN PLACE, so these are 0.75x of that -- 2 x 0.75
 * = the 1.5x asked for. Every rule below reproduces its original selector and media condition
 * with (max-width:899px) added, which is what keeps desktop on 2x while preserving each rule's
 * own height/width conditioning: flattening them into one mobile block would let a
 * max-height:700px or max-width:350px value leak to viewports it was never meant for.
 *
 * Generated from the doubled rules, so if the desktop factor changes these have to be
 * regenerated -- they are 0.75 OF THE DOUBLED VALUE, not an independent set of sizes.
 */
@media (max-width:899px){
  .eyebrow{font-size:12px}
  .copy-block p:not(.eyebrow){font-size:15px}
  .hani-invite p{font-size:12px}
  .hani-guide p{font-size:13.5px}
  .hani-guide p:before{font-size:9px}
  .hani-guide.over-shop p{font-size:12px}
  .close-panel p{font-size:22.5px}
  .hani-guide.focus-bike p{font-size:12px}
  .hani-guide.focus-points p{font-size:12px}
  .close-panel p{font-size:18px}
  .founder-promo{font-size:10.5px}
  .founder-promo b{font-size:11.25px}
  .reward-hani-break p{font-size:11.25px}
  .founder-promo{font-size:9.6px}
  .founder-promo strong{font-size:9.3px}
  .founder-promo b{font-size:10.5px}
  .reward-hani-break p{font-size:12px}
  .hani-welcome p{font-size:13.5px}
  .hani-invite p{font-size:12px}
  .hani-guide p{font-size:13.5px}
  .reward-hani-break p{font-size:12px}
  .founder-promo{font-size:11.4px}
  .founder-promo strong{font-size:11.1px}
  .founder-promo b{font-size:12.3px}
  .reward-hani-float p{font-size:12px}
  .reward-guide p{font-size:12px}
  .real-screens-label{font-size:9px}
  .difference-founders-note p{font-size:10.2px}
  .difference-founders-note .founders-signoff{font-size:10.8px}
  .difference-founders-note .rewards-tip{font-size:9.15px}
}
@media (max-width:430px) and (max-width:899px){
  .founder-promo{font-size:9.75px}
  .founder-promo{font-size:10.8px}
  .founder-promo strong{font-size:10.5px}
  .founder-promo b{font-size:11.7px}
  .reward-hani-float p{font-size:11.4px}
}
@media (max-height:700px) and (max-width:899px){
  .reward-hani-break p{font-size:10.5px}
}
@media (max-width:350px) and (max-width:899px){
  .difference-founders-note p{font-size:9px}
  .difference-founders-note .rewards-tip{font-size:8.25px}
}

/* The HANI tag was being sliced in half by its own bubble.
 *
 * .hani-guide p carries clip-path:polygon(...) -- the stepped pixel corners -- and the tag is
 * ::before ON THAT SAME ELEMENT at top:-11/-12px, deliberately straddling the top edge. clip-path
 * clips an element's WHOLE rendering, pseudo-elements included, and the polygon runs 0 -> 100% of
 * the box, so everything above y:0 was cut. That has always been true; at the old 10-11px the tag
 * was small enough not to read as broken, and at 22px about a third of it disappears.
 *
 * FIX: move the clipped LAYER off the element. The bubble's background and shadows move to an
 * ::after that carries the clip-path, and the <p> itself stops clipping -- so ::before is free.
 * The shape is unchanged because the same polygon still clips the same painted area.
 *
 * The box-shadows move WITH the clip rather than staying on the <p>, and that is deliberate: they
 * sit outside the border box, so today the polygon erases them entirely and the bubble renders as
 * flat cream. Leaving them on the now-unclipped <p> would suddenly reveal a black ring and a gold
 * drop shadow that have never been visible -- a change nobody asked for. Keeping them on the
 * clipped layer preserves exactly the current look. If that ring IS wanted (it is the same idiom
 * as .quest, .point-pop and .balance-card, so it was probably the intent) it is a one-line move.
 *
 * z-index:-1 keeps the layer behind the text. .hani-guide already establishes a stacking context
 * at z-index:12, so it cannot escape behind the stage.
 */
.hani-guide p{background:transparent;box-shadow:none;clip-path:none}
.hani-guide p:after{content:'';position:absolute;z-index:-1;inset:0;background:#fff7d6;box-shadow:0 0 0 4px #111,6px 6px 0 var(--gold);clip-path:polygon(8px 0,calc(100% - 8px) 0,calc(100% - 8px) 4px,100% 4px,100% calc(100% - 8px),calc(100% - 4px) calc(100% - 8px),calc(100% - 4px) 100%,8px 100%,8px calc(100% - 4px),0 calc(100% - 4px),0 8px,4px 8px,4px 4px,8px 4px)}

@media(min-width:900px){
  .hani-guide p:after{box-shadow:0 0 0 5px #111,8px 8px 0 var(--gold)}
}

/* KEEP SCROLLING moved down 15%, so it stops landing on Hani.
 *
 * .scroll-nudge is z-index:30 and .hani-guide / .hani-welcome are z-index:12, so wherever they
 * overlap the nudge wins -- and both are pinned to the right edge (right:9px here, right:34px on
 * desktop), so on the beats where the bubble is on the right they were stacking on each other.
 * The bubble is the content; the nudge is the affordance, so the nudge is what moves.
 *
 * 15% OF .sticky-world, not 15% of the existing offset. .scroll-nudge is absolutely positioned
 * against .sticky-world (position:sticky counts as positioned), so a percentage top resolves
 * against the stage height and the nudge keeps its position as the stage grows -- which matters
 * now that the stage is viewport-height-driven. Adding 15% of the old px value instead would have
 * moved it ~34px on a phone, which is not enough to clear a bubble that runs to roughly y=258.
 *
 * calc() mixing px and % is deliberate: the px part is the design's original offset, kept intact
 * so this reads as a 15% nudge rather than a new position.
 */
/* ...then back up to 5% on phones, and 10% on NON-iOS phones only.
 *
 * The 15% below was sized to clear the Hani bubble, which runs to roughly y=258 on a phone. iOS
 * wants it at 5%; Android reads better 5% lower again, hence the split.
 *
 * HOW THE SPLIT IS MADE, because CSS cannot ask what OS it is on. -webkit-touch-callout is an
 * iOS-only property and every browser on iOS is WebKit underneath, so
 * "@supports not (-webkit-touch-callout:none)" is effectively "not iOS". It is a proxy, not a
 * real platform check: it would also catch any future engine that drops the property, and it
 * says nothing about WHY the two platforms differ here.
 *
 * If the underlying difference turns out to be the notch rather than the OS, keying off
 * env(safe-area-inset-bottom) directly would be the honest version of this rule -- that value is
 * ~34 on a notched iPhone and 0 on Android, and unlike a UA proxy it describes the actual cause.
 *
 * Worth watching on a 667px handset: 5% puts the nudge at 254px, just above the bubble's ~258px,
 * so iOS SE-sized devices are the tight case here. The 431-899 band and desktop keep 15%. */
@media(max-width:430px){
  .scroll-nudge{top:calc(224px + 5%)}

  @supports not (-webkit-touch-callout:none){
    .scroll-nudge{top:calc(224px + 10%)}
  }
}

@media(min-width:431px) and (max-width:899px){
  .scroll-nudge{top:calc(248px + 15%)}
}

@media(min-width:900px){
  .scroll-nudge{top:65%}
}

/* KEEP SCROLLING label at 2x. Base 5px -> 10px, desktop 7px -> 14px.
 *
 * Only the <span> label. .scroll-nudge i -- the chevron in its circle -- is 18px/22px in a fixed
 * 22px/30px well, so doubling it would overflow the circle rather than enlarge the control; if the
 * whole nudge should grow, that is a matched change to the well and the glyph together.
 *
 * Padding is left alone: at 10px and 14px the 3px/5px and 5px/8px pills still read as badges, and
 * white-space:nowrap holds the label on one line (~78px on a phone, ~110px on desktop, against
 * right:9px / right:34px). This element is aria-hidden, so the size is purely visual. */
.scroll-nudge span{font-size:10px}

@media(min-width:900px){
  .scroll-nudge span{font-size:14px}
}

/* Reward stage full width on phones.
 *
 * It resolved to min(350px,calc(100vw - 16px)) and the 350px CAP was what bound on every current
 * handset -- 350 inside a 381px stage at 393w, 350 inside 418 at 430w -- so the viewport term
 * never got a say. width:100% is the full width of .reward-stack, which is .sticky-world less its
 * 6px inline padding, i.e. as wide as the stage goes without escaping the padding.
 *
 * This also has to out-rank the (max-height:700px) rule that pins width:310px: that one carries no
 * width condition, so on a short phone it would otherwise still apply. Being last in the file at
 * equal specificity is what settles it.
 *
 * aspect-ratio:3/2 is untouched, so the height follows the new width -- 233px -> 254px at 393w,
 * against a stage top of 232px in roughly 698px of room, so it still clears. .headphone-focus is
 * positioned in percentages of this box and needs no adjustment.
 */
@media(max-width:430px){
  .reward-swipe-stage{width:100%}
}

/* Reward stage fills the width between 431 and 899 too -- but bounded by height, unlike phones.
 *
 * This band was left on the design's fixed 350px (310px under max-height:700px), so narrowing a
 * desktop window dropped below 900 and the stage stopped filling. Repeating the phones' plain
 * width:100% does NOT work here: the band goes up to 899px wide, and a 3:2 box that wide is
 * ~583px tall against a stage that has already spent 236px positioning it, so it would overflow
 * and .reward-stack's overflow:hidden would cut the bottom off.
 *
 * So: full width WHEN THERE IS ROOM, and height-derived when there is not. The room below the
 * stage's top edge is (100vh - 170) - 236 - 8 = 100vh - 414 -- 146px of bars, 24px of
 * .sticky-world padding, the 236px top offset and an 8px margin -- and at 3:2 that allows
 * 1.5x as much width.
 *
 * 414 is deliberately the tall-viewport figure. Under max-height:700px the design moves the stage
 * up to top:207px, which frees another 29px; using the larger subtrahend there just makes the
 * stage slightly smaller than it could be, which is the safe direction to be wrong in.
 *
 * Also has to out-rank that same max-height:700px rule's width:310px, which carries no width
 * condition -- being last at equal specificity is what settles it.
 */
@media(min-width:431px) and (max-width:899px){
  .reward-swipe-stage{width:min(100%,calc((100vh - 414px) * 1.5))}
}

/* Re-assert the fixed mobile CTA. This is a PRE-EXISTING BUG, not a regression from this branch --
 * it is in the design package's globals.css and shipped in the first Hani's World commit.
 *
 * The mobile block sets .bottom-bar{position:fixed;left:0;right:0;bottom:0;z-index:50}, and then a
 * later UNCONDITIONAL rule in the "Production review refinements" section re-declares
 * .bottom-bar{position:relative;...} for its padding and gradient. Same specificity, later in the
 * file, no media condition -- so it wins everywhere and the phone CTA silently falls back into
 * normal flow at the end of the document. That is why it only appears at the very bottom of the
 * page instead of staying pinned.
 *
 * With position:relative the left/right/bottom:0 from the mobile block are not errors, they are
 * simply inert -- relative offsets of zero -- which is why nothing looked obviously wrong in the
 * stylesheet.
 *
 * Only position needs restoring: min-height and z-index from the mobile block were never
 * overridden, and the safe-area padding is re-applied by a still-later base rule
 * (padding:20px 12px max(10px,env(safe-area-inset-bottom))), so the home-indicator inset survives.
 *
 * Scoped to <=430px deliberately. Between 431 and 899 the bar is a grid row of .phone-frame and
 * belongs in flow; at >=900 it is display:none because the CTA moved into the top bar.
 */
@media(max-width:430px){
  .bottom-bar{position:fixed}
}

/* Payoff on narrow viewports: two columns, not three.
 *
 * .difference-grid is two tracks -- minmax(0,1.72fr) for .benefit-cards and minmax(112px,.82fr)
 * for .difference-side -- but .benefit-cards is itself repeat(2,minmax(0,1fr)), so the page reads
 * as THREE columns: two of cards plus the aside. Below 600px that leaves the cards around 140px
 * each with a 112px aside wedged beside them, and nothing has room.
 *
 * Collapsing to one track stacks them: the cards keep their own two columns at full width, and
 * .difference-side drops underneath. The explicit placement has to be undone too -- .benefit-cards
 * carries grid-row:1/3 and .difference-side grid-column:2/grid-row:1, which would otherwise pin
 * them back into a two-column arrangement that no longer exists and leave an empty second row.
 *
 * ONLY grid-template-columns is overridden, not gap: the (max-width:350px) rule tightens the gap
 * to 7px alongside its own column values, and that half should survive.
 *
 * 600px rather than 430px on purpose. The three-column squeeze is a WIDTH problem, so a real phone
 * and a narrowed desktop window should behave the same -- scoping this to phones only would
 * reproduce the split behaviour that made the stacked reward layout not worth keeping.
 */
@media(max-width:599px){
  .difference-grid{grid-template-columns:minmax(0,1fr)}
  .difference-grid>.benefit-cards{grid-column:1;grid-row:auto}
  .difference-grid>.difference-side{grid-column:1;grid-row:auto}
  /* .conversion-row is display:contents, so .pricing-module and .close-panel are grid items of
   * .difference-grid too, not of the row. .pricing-module is pinned to grid-column:2/grid-row:2 --
   * left alone it recreates the very column collapsing the track was meant to remove, because an
   * item placed in column 2 makes an implicit column 2 exist. Both are released to auto so the
   * four items flow in source order: cards, founders note, pricing, CTA panel. */
  .conversion-row>.pricing-module{grid-column:1;grid-row:auto}
  .conversion-row>.close-panel{grid-column:1;grid-row:auto}
}

/* .bonus-kicker doubled: 5.2px -> 10.4px below 900, 9px -> 18px at desktop.
 *
 * Every existing declaration is !important, so an override has to be !important AND match their
 * (0,2,0) specificity -- a bare .bonus-kicker rule is (0,1,0) and loses to
 * ".difference-grid .bonus-kicker" no matter how late it appears. The base .bonus-kicker{4.8px}
 * is doubled too for consistency, though in practice the markup only ever puts a kicker inside
 * .difference-grid, so the more specific rules are what actually render.
 *
 * This is a straight 2x at every width, unlike the <p> scale which is 2x on desktop and 1.5x
 * below 900 -- .bonus-kicker is a <span> and was never part of that pass. Say if it should follow
 * the paragraph convention instead.
 */
.bonus-kicker{font-size:9.6px!important}
.difference-grid .bonus-kicker{font-size:10.4px!important}

@media(min-width:900px){
  .difference-grid .bonus-kicker{font-size:18px!important}
}

/* Pricing module goes two-up below 600px: price on the left, the tick list beside it.
 *
 * Only worth doing here because the module just became full width -- above 600 it still sits in
 * .difference-grid's ~112px second column, where there is no room to put anything beside anything.
 * Same breakpoint as the payoff stack for that reason; they are one change, not two.
 *
 * The module carries no display of its own below 900 (it is a plain block), so making it a grid is
 * additive rather than an override. auto / minmax(0,1fr): the left track sizes to the price, which
 * is a 29px serif numeral and therefore the widest fixed thing in the box, and the list takes
 * whatever is left.
 *
 * <strong>'s margin is reset from 8px 0 9px to 4px 0 0 -- the 9px bottom was separating it from a
 * list that was underneath it and is now beside it, so it would only push the price off centre.
 */
@media(max-width:599px){
  .pricing-module{display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:16px;align-items:center}
  .pricing-module>small{grid-column:1;grid-row:1;align-self:end}
  .pricing-module>strong{grid-column:1;grid-row:2;margin:4px 0 0}
  .pricing-module ul{grid-column:2;grid-row:1/3;align-content:center}
}

/* Pricing module text doubled, except the price lockup.
 *
 *   .pricing-module>small   5px -> 10px   (9px -> 18px desktop)   "ONE SIMPLE PLAN"
 *   .pricing-module li      6.5px -> 13px (12px -> 24px desktop)  the tick list
 *
 * EVERYTHING INSIDE <strong> IS LEFT ALONE -- s ($15), b ($12) and em (/month). It is one lockup
 * laid out with display:flex;align-items:baseline, so the three sizes are set against each other;
 * scaling any of them independently would break that baseline relationship. That includes /month,
 * which is not money itself but is part of the same line.
 *
 * li's padding-left doubles with it (10 -> 20, 18 -> 36). It is not decoration: li:before is the
 * absolutely-positioned check at left:0 and the padding is the gutter it sits in, so leaving it at
 * 10px would put a 13px glyph under the text.
 *
 * Straight 2x at both breakpoints, matching how .bonus-kicker was handled rather than the <p>
 * scale's 2x/1.5x split. Desktop still fits: the module's inner width there is ~266px against
 * ~175px for the small and ~203px for the longest li.
 */
.pricing-module>small{font-size:10px}
.pricing-module li{padding-left:20px;font-size:13px}

@media(min-width:900px){
  .pricing-module>small{font-size:18px}
  .pricing-module li{padding-left:36px;font-size:24px}
}

/* Founders note back to 50% at desktop -- which is the design's ORIGINAL size.
 *
 *   p                 26px -> 13px
 *   .founders-signoff 28px -> 14px
 *   .rewards-tip      24px -> 12px
 *
 * 50% of the doubled value is exactly what the design package shipped: 13 / 14 / 12px. So this
 * does not shrink the note below its drawn size, it opts it out of the <p> doubling entirely and
 * leaves it as authored. Worth saying plainly, because it means there is no smaller sensible step
 * after this one -- anything further is genuinely under-sizing the copy.
 *
 * It is the only desktop element at 1x. Defensible: it is a long paragraph of body copy in
 * .difference-side's 310px column, whereas the doubling was aimed at short labels and headings
 * that had room to grow.
 *
 * Scoped to min-width:900px only. Below that the (max-width:899px) 1.5x block already governs
 * these three and is unaffected.
 */
@media(min-width:900px){
  .difference-founders-note p{font-size:13px}
  .difference-founders-note .founders-signoff{font-size:14px}
  .difference-founders-note .rewards-tip{font-size:12px}
}

/* Founder promo to 75% at desktop.
 *
 *   .founder-promo        20px -> 15px
 *   .founder-promo strong 18px -> 13.5px
 *   .founder-promo b      22px -> 16.5px
 *
 * Same arithmetic as the founders note: these were 10 / 9 / 11px before the <p> pass doubled
 * them, so 75% of the doubled value is 1.5x the original -- the promo now carries the same factor
 * as everything below 900px rather than the desktop 2x.
 *
 * It needed it more than most. The promo is three lines (LIMITED TIME: / Free Trial During /
 * Founder's Season) at line-height 1.2, so 20px made it about 72px tall inside a 76px .top-bar --
 * it was effectively setting the bar's height. At 15px that drops to ~54px, which leaves the bar
 * room for the logo, the centred CTA and the GET THE APP tab that now share it.
 *
 * Scoped to min-width:900px. Below that the (max-width:899px) 1.5x block already governs the
 * promo's five conditional sizes and is unaffected.
 */
@media(min-width:900px){
  .founder-promo{font-size:15px}
  .founder-promo strong{font-size:13.5px}
  .founder-promo b{font-size:16.5px}
}

/* Brand signoff to 50% -- which is the design's ORIGINAL size.
 *
 *   .brand-signoff p                  40px -> 20px
 *   .conversion-row .brand-signoff p  32px -> 16px
 *
 * Both source rules are min-width:900px only -- there is no sub-900 declaration for this
 * paragraph -- so this is a desktop change by construction rather than by choice of scope.
 *
 * The second selector is the one that renders: the signoff sits inside .close-panel inside
 * .conversion-row, and (0,2,1) beats (0,1,1) regardless of order, so the override has to repeat
 * the longer selector rather than just re-declaring .brand-signoff p. The shorter rule is scaled
 * too so the pair stays consistent if the markup ever moves the signoff out of the row.
 *
 * These were 20px and 16px before the <p> pass doubled them, so 50% puts them back exactly as
 * authored -- like the founders note, this opts the signoff out of the doubling rather than
 * shrinking it below its drawn size, and there is no smaller sensible step after this one. The
 * copy is three <br>-separated lines (Made for Kids. / Works for Parents. / Powered by Research.),
 * which is why 32px was reading as a wall.
 */
@media(min-width:900px){
  .brand-signoff p{font-size:20px}
  .conversion-row .brand-signoff p{font-size:16px}
}

/* Pricing module to 75% between 600 and 899.
 *
 * In this band the module is back inside .difference-grid's minmax(112px,.82fr) aside column --
 * roughly 162px of inner width at 600 and 258px at 899 -- rather than the full width it gets under
 * 600px, where the two-up layout and the doubled sizes were chosen for it. So the sizes that suit
 * the phone stack are too big here, and the desktop block does not reach down this far.
 *
 * EVERYTHING SCALES, THE PRICE LOCKUP INCLUDED. That is safe here in a way it was not when the
 * module was doubled: s / b / em are laid out on align-items:baseline against each other, so a
 * UNIFORM factor preserves the relationship, whereas scaling one member of the lockup breaks it.
 *
 * li's padding-left comes down with the text (20 -> 15) for the same reason it went up: it is the
 * gutter the absolutely-positioned check sits in.
 *
 * Lower bound is 600px, matching the payoff stack, so the full-width two-up layout below it keeps
 * the sizes it was designed around. If this was meant for all of 431-899 instead, the one number
 * to change is the min-width.
 */
@media(min-width:600px) and (max-width:899px){
  .pricing-module>small{font-size:7.5px}
  .pricing-module>strong s{font-size:7.5px}
  .pricing-module>strong b{font-size:21.75px}
  .pricing-module>strong em{font-size:5.25px}
  .pricing-module li{padding-left:15px;font-size:9.75px}
}

/* Brand signoff to 80% in the same 600-899 band as the pricing module.
 *
 * There is NO .brand-signoff rule in this band -- both of its declarations are min-width:900px
 * only -- so the paragraph is being sized by .close-panel p, which .brand-signoff sits inside and
 * which resolves to 18px here (the last of the generated 1.5x block's two .close-panel p rules).
 * 80% of that is 14.4px.
 *
 * (0,1,1) matches .close-panel p exactly, so this wins on source order rather than specificity --
 * which is what we want: it lifts the signoff off the shared .close-panel value without touching
 * the panel's own CTA copy, which stays at 18px.
 *
 * .conversion-row .brand-signoff p is not in play here; that selector only exists at
 * min-width:900px, so there is nothing more specific to out-rank.
 */
@media(min-width:600px) and (max-width:899px){
  .brand-signoff p{font-size:14.4px}
}

/* Intro paragraph down from 34px to 28px in the largest band.
 *
 * The selector has to be repeated verbatim: .copy-block p:not(.eyebrow) is (0,2,1) because :not()
 * contributes its argument's specificity, so a plainer .copy-block p would lose to it however late
 * it appeared.
 *
 * NOTE THE SIBLING. <strong>Turn down the nagging...</strong> is a direct child of .copy-block, NOT
 * inside the <p>, so the <p> doubling pass never touched it and it is still at its authored 17px.
 * The design had both at 17px; they are now 28 and 17. Left alone because only the paragraph was
 * asked for, but that gap is deliberate-looking and probably is not.
 */
@media(min-width:900px){
  .copy-block p:not(.eyebrow){font-size:28px}
}

/* Intro headline down from 56px to 40px in the largest band.
 *
 * The short-desktop step comes with it: (min-width:900px) and (max-height:760px) sets 48px, which
 * is deliberately SMALLER than the 56px above it because a short window has less room. Change only
 * the 56 and that ordering inverts -- a short desktop would render the headline larger than a tall
 * one. 48 * 40/56 = 34px keeps the same 86% relationship rather than flattening the two to one
 * size, which would lose the distinction entirely.
 *
 * Unlike the paragraph, this is not unwinding the <p> doubling: <h1> is not a <p> and was never
 * part of that pass, so 56px is the design's own figure and 40px is a genuine reduction below it.
 */
@media(min-width:900px){
  .copy-block h1{font-size:40px}
}

@media(min-width:900px) and (max-height:760px){
  .copy-block h1{font-size:34px}
}

/* Why the desktop stage is width-driven, and why .headphone-focus depended on it.
 *
 * .headphone-focus is sized in PERCENTAGES OF THE STAGE (width:20.3%, height:34%) and pointed at
 * the headphones in art that is drawn 3:2. Those two only agree while the stage is itself exactly
 * 3:2 -- .reward-swipe-image is object-fit:contain, so the moment the box drifts off ratio the
 * picture letterboxes inside it while the highlight keeps tracking the BOX. The visible symptom is
 * a highlight that grows taller and slides as the window narrows, and only looks right at the one
 * width where the ratio happens to come out true.
 *
 * Every other band was already safe because width is stated and aspect-ratio derives the height,
 * which cannot drift. Desktop was the exception: align-self:stretch made HEIGHT the driver, so
 * aspect-ratio derived the width and max-width:100% then clamped it -- and a clamped derived
 * dimension is exactly how an aspect-ratio breaks.
 *
 * So the width is stated here too, capped by the room available rather than by max-width:
 * .sticky-world is 100vh - 76 (one bar row) less 20px of its own padding, and .reward-stack
 * spends another 64px (32px block padding, or 36 on the short-desktop variant, hence 132 there).
 * At 3:2 that height allows 1.5x as much width. min() picks whichever of the track width and the
 * height allowance is smaller, and the ratio holds either way because height is always derived.
 */

/* The scroll-nudge chevron, drawn instead of typed.
 *
 * <i>&#8964;</i> is U+2304 DOWNWARDS CHEVRON and the circle centres it with place-items:center --
 * which centres its LINE BOX, not its ink. A chevron's ink sits low in the em box, so the mark
 * lands below the middle of the circle no matter how the box is aligned.
 *
 * There is a second problem underneath that one: .scroll-nudge inherits
 * font-family:var(--font-geist-mono),monospace, and --font-geist-mono is DEFINED NOWHERE in this
 * stylesheet (same as --font-pixel). So the glyph renders in whatever the platform's monospace
 * fallback is, and if that face has no U+2304 the browser substitutes a third font with different
 * metrics again. The mark's position was never really under our control.
 *
 * So: font-size:0 hides the glyph without touching the markup, and ::before draws the chevron
 * from two borders on a rotated square -- geometry rather than typography, identical on every
 * platform.
 *
 * THE SHIFT IS DERIVED, THEN EASED OFF BY EYE. Rotating a square 45deg keeps its centre fixed,
 * so the chevron's point lands half a diagonal BELOW centre while its two arms end level WITH
 * centre -- the whole mark hangs below the middle. Half that distance is the geometric correction:
 * 2.83px for the 8px square, 3.54px for the 10px one.
 *
 * The values below are less than that, on purpose: a "V" reads as heavier at its point than at its
 * open arms, so centring its bounding box exactly leaves it looking high. TUNE THESE IN PIXELS,
 * NOT PERCENTAGES -- the correction is under 4px to begin with, so a 20% adjustment is half a
 * pixel and invisible. 0 would sit the mark's bounding box dead centre, which reads low;
 * -2.83 / -3.54 is the geometric centre, which reads high; these are between.
 */
.scroll-nudge i{font-size:0}
.scroll-nudge i:before{content:'';display:block;width:8px;height:8px;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:translateY(-0.35px) rotate(45deg)}

@media(min-width:900px){
  .scroll-nudge i:before{width:10px;height:10px;transform:translateY(-1.15px) rotate(45deg)}
}

/* Brand signoff to 60% below 600, and "See you soon!" 50% bigger everywhere.
 *
 * BRAND SIGNOFF. It has no rule of its own under 900px -- both its declarations are
 * min-width:900px -- so below that it inherits .close-panel p, which the generated 1.5x block
 * leaves at 18px. 60% of that is 10.8px. (0,1,1) matches .close-panel p exactly, so this wins on
 * source order and lifts the signoff off the shared value without touching the panel's own CTA
 * copy. Capped at 599px because 600-899 was already set to 14.4px and reads correctly.
 *
 * FOOTER SPAN. Two rules set it at desktop and the SHORTER one is not the one that renders:
 * .conversion-row .footer-hani-wrap span is (0,2,1) and beats .footer-hani-wrap span's (0,1,1)
 * regardless of order, so the live value is 11px, not 13px. Both are scaled by 1.5 so the pair
 * stays consistent if the markup ever moves the signoff out of .conversion-row -- overriding only
 * the short one would have changed nothing visible.
 *
 * The span is white-space:nowrap; "See you soon!" at 16.5px is roughly 110px, which its
 * flex-end-aligned wrap has room for.
 */
@media(max-width:599px){
  .brand-signoff p{font-size:10.8px}
}

.footer-hani-wrap span{font-size:12px}

@media(min-width:900px){
  .footer-hani-wrap span{font-size:19.5px}
  .conversion-row .footer-hani-wrap span{font-size:16.5px}
}

/* THE FIVE FONT VARIABLES, WHICH HAVE NEVER BEEN DEFINED.
 *
 * The document has always downloaded Fredoka, Geist Mono, Montserrat, Nunito and Press Start 2P
 * from Google Fonts, and never used one of them. 33 declarations reference these variables and
 * nothing ever gave them a value.
 *
 * WHY THE FALLBACK LISTS DID NOT SAVE IT, which is the non-obvious part: in
 *   font-family:var(--font-kid-title),Fredoka,Arial,sans-serif
 * the commas are font-family list separators, NOT a var() fallback -- that would have to be
 * INSIDE the parens, var(--font-kid-title, Fredoka). An unresolvable var() makes the whole
 * declaration invalid at computed-value time, so the browser does not skip to Fredoka; it discards
 * the entire line. The element then inherits font-family from its parent, and since body's own
 * rule has the same defect, that chain ends at the browser default. Every one of these 33 sites
 * has been rendering in the platform default face -- Helvetica-ish on iOS, Roboto on Android --
 * which is a large part of why the two render differently.
 *
 * next/font generated this block at build time in the source package; it did not survive the port,
 * same category of leftover as the @import 'tailwindcss' line that 404s on every page load.
 *
 * Names are exactly as Google Fonts serves them, matching the family= parameters on the <link>.
 * The existing per-declaration fallbacks stay in force after these resolve.
 */
:root{
  --font-parent-body:'Montserrat';
  --font-kid-title:'Fredoka';
  --font-kid-body:'Nunito';
  --font-geist-mono:'Geist Mono';
  --font-pixel:'Press Start 2P';
}


/* ── TEMPORARY: hamburger nav hidden until Blog and Research ship ──────────────────────────
 *
 * DELETE THIS WHOLE BLOCK TO BRING THE MENU BACK. That is the entire restore step: the markup
 * in _HanisWorldPartial.cshtml is untouched, the .menu-toggle / .site-menu rules above are
 * untouched, and the JS toggle still binds. Nothing else was changed to hide it.
 *
 * Why hide rather than leave it: all three links are href="#", so the panel opens onto three
 * dead ends. A menu that advertises sections we cannot show yet costs more trust than the menu
 * earns us while the site is a single page.
 *
 * display:none, not visibility:hidden -- the button should give its 42px back to the top bar
 * rather than hold an empty gap, and display:none also takes it out of the tab order and the
 * accessibility tree, so it is hidden from keyboard and screen-reader users too rather than
 * only visually.
 *
 * .site-menu is hidden alongside it. It is already style="display:none" inline and only the
 * button opens it, so this is belt-and-braces -- but the inline style is what the JS toggles,
 * and this rule means no future path can open a panel of dead links while the block is here.
 */
.menu-toggle,
.site-menu{display:none !important}


/* ── TEMPORARY: pricing module hidden ──────────────────────────────────────────────────────
 *
 * DELETE THIS WHOLE BLOCK TO BRING PRICING BACK. That is the entire restore step: the markup
 * in _HanisWorldPartial.cshtml is untouched, and every .pricing-module rule above it stays
 * exactly as it was.
 *
 * display:none rather than visibility:hidden, so the module gives its space back instead of
 * leaving a hole where the card was, and so screen readers do not announce a price that is
 * not on screen.
 *
 * Safe against the grid it sits in. .conversion-row is display:contents, so .pricing-module
 * and .close-panel are placed directly in .difference-grid by explicit grid-column/grid-row.
 * Removing one therefore does NOT reflow the other -- close-panel keeps the cell it names.
 * .difference-grid declares only grid-template-COLUMNS, so its rows are implicit and
 * auto-sized, and the row the pricing card occupied collapses to zero height rather than
 * leaving a gap.
 *
 * NOTE the wrapper still carries aria-label="RiseOhana pricing and sign-up", which is now
 * half true. Left alone deliberately: this is a CSS-only hide and the markup should come back
 * untouched. Fix the label if pricing stays hidden for long.
 */
.pricing-module{display:none !important}
