
*{box-sizing:border-box}body{margin:0;font-family:'Avenir Next','Trebuchet MS',system-ui,sans-serif}button,a{font:inherit}button{cursor:pointer}.app-header{display:flex;align-items:center}.brand{display:flex;align-items:center;font-weight:650;text-decoration:none}.skip{position:absolute;left:16px;top:-100px}.skip:focus{top:12px;z-index:20;padding:12px;background:var(--paper);color:var(--ink)}main{outline:none}button:focus-visible,a:focus-visible,summary:focus-visible{outline:3px solid var(--accent);outline-offset:4px}/* Wise Sparks: brand presence without changing a learner's saved appearance. */
.wise-mark{width:42px;height:42px;object-fit:contain;flex:none}.brand{gap:10px!important;letter-spacing:-.045em}.brand>span{white-space:nowrap}.brand:hover .wise-mark{transform:rotate(-6deg)}.wise-mark{transition:transform .22s ease}[hidden]{display:none!important}
:root[data-space=welcome][data-space=welcome][data-space=welcome]{--bg:#f7faff;--board:#f7faff;--paper:#fff;--ink:#182b48;--muted:#566982;--accent:#254ccb;--on-accent:#fff;--accent-hover:#1d3eab;--soft:#eaf1ff;--soft-strong:#dbe7ff;--line:#dbe4f0;--control-line:#738aad;--on-soft:#254589;--card-edge:#d9e4f5;--surface-tint:#f3f7fd;background:var(--bg);color:var(--ink);color-scheme:light}
:root[data-space=welcome][data-space=welcome][data-space=welcome][data-welcome-night=true]{--bg:#101e34;--board:#101e34;--paper:#192b45;--ink:#edf4ff;--muted:#b0c3dd;--accent:#adcaff;--on-accent:#152c56;--accent-hover:#c4d9ff;--soft:#213959;--soft-strong:#294469;--line:#36506e;--control-line:#8ba6c9;--on-soft:#c2d8ff;--card-edge:#2b4568;--surface-tint:#17283f;color-scheme:dark}
:root[data-space=welcome] body{background:var(--bg);color:var(--ink)}:root[data-space=welcome] body::before{display:none}:root[data-space=welcome] .app-header{max-width:1320px;margin:20px auto 0;border:0;border-bottom:1px solid var(--line);box-shadow:none;border-radius:0;background:transparent;padding:14px 24px;gap:18px}:root[data-space=welcome] #main{max-width:1296px;padding:0 28px;margin:0 auto}:root[data-space=welcome] .motion-control{font-size:12px;padding:9px 12px;min-height:44px;border:0;background:transparent;color:var(--muted)}:root[data-space=welcome] .play-dock{display:none}:root[data-space=welcome] #planner-alert{display:none}:root[data-space=welcome] .app-header .brand{color:var(--ink);font-size:26px}
.ws-welcome{--ws-gold:#f6c85f;--ws-blue:#254ccb;--ws-mint:#78d5bd;color:var(--ink);font-size:17px;line-height:1.65}.ws-welcome *{box-sizing:border-box}.ws-welcome section{scroll-margin-top:28px}.ws-welcome h1,.ws-welcome h2,.ws-welcome h3{color:var(--ink);font-weight:650;letter-spacing:-.045em;text-wrap:balance}.ws-welcome h1{font-size:clamp(54px,6vw,80px);line-height:1.035;margin:24px 0}.ws-welcome h1 em{font-style:normal;color:var(--accent)}.ws-welcome h2{font-size:clamp(32px,3.5vw,46px);line-height:1.13;margin:14px 0 22px}.ws-welcome h3{font-size:23px;line-height:1.25;margin:20px 0 12px;letter-spacing:-.035em}.ws-welcome p{margin:0 0 20px;max-width:65ch}.ws-welcome button,.ws-welcome a{font:inherit}.ws-welcome button{min-height:44px;cursor:pointer}
.ws-welcome button:focus-visible,.ws-welcome a:focus-visible{outline:3px solid var(--accent);outline-offset:4px}.ws-kicker{font-size:13px;font-weight:650;letter-spacing:.045em;color:var(--accent)}.ws-gold-spark{color:#b77b12;font-size:23px;vertical-align:middle;margin-right:8px}.ws-hero{display:grid;grid-template-columns:1fr 1fr;gap:48px;align-items:center;padding:24px 0 56px;min-height:620px}.ws-hero-copy{padding:12px 0}.ws-lead{font-size:19px;line-height:1.7;color:var(--muted);max-width:44ch!important}.ws-hero .intro-actions,.ws-welcome .enroll-actions,.ws-welcome .ws-entry-actions{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:28px 0 12px}.ws-welcome .primary,.ws-welcome .outline-action,.ws-welcome .ws-entry-actions a,.ws-welcome .enroll-actions button{display:inline-flex;align-items:center;justify-content:center;gap:16px;min-height:54px;padding:14px 22px;border-radius:16px;font-size:15px;font-weight:650;text-decoration:none;line-height:1.4;border:1px solid var(--control-line);background:var(--paper);color:var(--ink);box-shadow:none}.ws-welcome .primary,.ws-welcome .ws-entry-actions .primary{background:var(--accent);color:var(--on-accent);border-color:var(--accent);box-shadow:0 4px 0 color-mix(in srgb,var(--accent) 28%,transparent)}.ws-welcome .primary:hover{background:var(--accent-hover);transform:translateY(-2px)}.ws-welcome .outline-action:hover{background:var(--soft)}.ws-welcome .journey-icon{width:20px;height:20px}.ws-welcome .intro-account-note{font-size:13px;color:var(--muted);max-width:46ch;line-height:1.6}.ws-hero-foot{font-size:13px;color:var(--muted);display:flex;align-items:center;gap:12px;margin-top:24px}.ws-hero-foot>span[aria-hidden]{display:grid;place-items:center;width:30px;height:30px;border-radius:50%;background:var(--soft);color:var(--accent);font-size:20px}.ws-hero-play{min-width:0;position:relative}.ws-illustration{position:relative;min-height:265px;display:grid;place-items:center;padding-bottom:5px}.ws-illustration img{display:block;width:290px;max-width:80%;height:auto;aspect-ratio:1240/1268;object-fit:contain;filter:drop-shadow(0 18px 20px #17386618)}.ws-orbit-label{position:absolute;left:0;top:55px;font-size:13px;font-weight:650;color:var(--ink);background:var(--paper);border:1px solid var(--line);border-radius:12px 12px 2px 12px;padding:9px 15px;transform:rotate(-6deg)}.ws-art-caption{position:absolute;right:0;bottom:40px;font-size:12px;color:var(--muted);transform:rotate(5deg)}.ws-demo{position:relative;background:var(--paper);border:1px solid var(--line);border-radius:24px;padding:24px;box-shadow:0 14px 38px -20px #182b4850;min-height:290px}.ws-demo-top{display:flex;gap:12px;align-items:center;justify-content:space-between}.ws-demo-note{color:var(--muted);font-size:12px}.ws-demo-tabs{display:flex;gap:4px;margin:16px 0 12px;padding:4px;background:var(--bg);border:1px solid var(--line);border-radius:12px}.ws-demo-tabs button{flex:1;min-height:44px;border:0;border-radius:8px;font-size:13px;font-weight:650;padding:6px;background:transparent;color:var(--muted);box-shadow:none}.ws-demo-tabs button[aria-pressed=true]{color:var(--accent);background:var(--paper);box-shadow:0 2px 5px #182b4810}.ws-question{font-size:17px;line-height:1.5;font-weight:650;margin:14px 0!important;min-height:51px}.ws-answers{display:flex;gap:8px}.ws-answers button{flex:1;border:1px solid var(--control-line);border-radius:12px;background:var(--paper);color:var(--ink);font-size:15px;font-weight:700;padding:10px;box-shadow:0 3px 0 var(--line);min-width:0}.ws-answers button:hover{background:var(--soft);transform:translateY(-2px)}.ws-answers button[aria-pressed=true]{background:var(--soft-strong);border-color:var(--accent)}.ws-demo[data-result=correct] [data-spark-answer][aria-pressed=true]{background:#e2f4eb;color:#20573f;border-color:#458568;animation:ws-pop .35s ease-out}.ws-demo-bottom{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px 14px;margin-top:18px;min-height:44px}.ws-hint{font-size:12px!important;background:none!important;border:0!important;padding:6px 0!important;color:var(--accent)!important;box-shadow:none!important;white-space:nowrap;text-decoration:underline;text-underline-offset:4px}.ws-answer-feedback{font-size:13px;line-height:1.6;color:var(--muted);margin:12px 0 0!important;min-height:0}.ws-answer-feedback:empty{display:none}.ws-demo[data-result=correct] .ws-answer-feedback{color:var(--ink)}
.ws-how{padding:72px 0 80px;border-top:1px solid var(--line)}.ws-section-head{display:grid;grid-template-columns:1.35fr 1fr;column-gap:80px;align-items:end}.ws-section-head>.ws-kicker{grid-column:1/-1}.ws-section-head>p:last-child{color:var(--muted);max-width:40ch}.ws-steps{list-style:none;padding:0;margin:32px 0 0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:32px}.ws-steps li{position:relative;border-top:1px solid var(--line);padding-top:20px}.ws-step-number{font-size:12px;font-weight:650;color:var(--muted)}.ws-step-art{height:112px;display:flex;align-items:center;gap:8px;position:relative;margin:12px 0}.ws-step-art i{font-style:normal}.ws-art-map{flex-wrap:wrap;align-content:center;padding:14px 8px 14px 66px}.ws-art-map i{position:absolute;left:10px;top:17px;color:var(--accent);font-size:55px}.ws-art-map>span{padding:5px 12px;background:var(--soft);border:1px solid var(--line);border-radius:12px;font-size:12px;transform:rotate(-5deg)}.ws-art-map>span:nth-child(3){transform:rotate(6deg);background:var(--paper)}.ws-art-clue>span{padding:20px;border:1px solid var(--line);border-radius:16px;background:var(--paper);transform:rotate(-4deg);color:var(--accent);font-size:16px;font-weight:700;box-shadow:0 5px 0 var(--soft)}.ws-art-clue i{color:var(--accent);font-size:42px}.ws-art-spark i{background:#f6c85f;color:#78520a;display:grid;place-items:center;font-size:48px;width:82px;height:82px;border-radius:28px;transform:rotate(-10deg);box-shadow:0 6px 0 #d5a749}.ws-art-spark span{font-size:14px;font-weight:700;padding:10px;background:var(--paper);border:1px solid var(--line);border-radius:12px;margin-left:-10px;z-index:1}.ws-steps p{color:var(--muted);font-size:16px;max-width:34ch}
.ws-world{display:grid;grid-template-columns:1fr 1fr;gap:64px;align-items:center;background:var(--soft);border:1px solid var(--line);border-radius:32px;padding:56px}.ws-world-preview{padding:24px 0}.ws-world-window{background:var(--paper);border:1px solid var(--line);border-radius:24px;overflow:hidden;transform:rotate(-3deg);box-shadow:0 12px 0 color-mix(in srgb,var(--accent) 12%,transparent)}.ws-window-top{display:flex;justify-content:space-between;padding:16px 22px;font-size:13px;font-weight:650;border-bottom:1px solid var(--line)}.ws-window-top>span:last-child{color:#b77b12}.ws-garden-art{display:flex;justify-content:center;align-items:flex-end;gap:18px;height:160px;padding:25px;background:radial-gradient(ellipse at 50% 120%,#b9e2cd 0,transparent 65%)}.ws-garden-art span{font-size:54px;filter:drop-shadow(0 7px 3px #182b4818)}.ws-garden-art span:nth-child(2){font-size:76px}.ws-window-bottom{padding:18px 24px;font-size:14px;display:grid}.ws-window-bottom i{font-size:12px;font-style:normal;color:var(--muted)}.ws-swatches{display:flex;align-items:center;justify-content:center;gap:7px;margin-top:36px}.ws-swatches i{width:19px;height:19px;border:2px solid var(--paper);border-radius:50%;background:#254ccb;box-shadow:0 0 0 1px var(--line)}.ws-swatches i:nth-child(2){background:#c94e8a}.ws-swatches i:nth-child(3){background:#795fc0}.ws-swatches i:nth-child(4){background:#479686}.ws-swatches span{font-size:12px;color:var(--muted);margin-left:8px}.ws-world-copy>p{color:var(--muted)}.ws-world-copy>.ws-kicker{color:var(--accent)}.ws-world-copy ul{padding:0;list-style:none;margin:20px 0}.ws-world-copy li{font-size:14px;margin:9px 0;display:flex;gap:12px}.ws-world-copy li:before{content:'✓';color:var(--accent);font-weight:650}.ws-fine{font-size:12px!important;line-height:1.65}.ws-families{display:grid;grid-template-columns:1fr 1fr;gap:64px;padding:88px 0 64px;border-bottom:1px solid var(--line)}.ws-families>div:last-child{padding-top:32px;color:var(--muted)}.ws-signoff{font-size:14px;font-weight:650;color:var(--accent)}.ws-faq{display:grid;grid-template-columns:.8fr 1.2fr;gap:64px;padding:64px 0}.ws-faq h2{font-size:30px}.ws-faq details{border-bottom:1px solid var(--line);padding:16px 0}.ws-faq summary{cursor:pointer;font-weight:650;font-size:16px;padding:6px 24px 6px 0;min-height:44px}.ws-faq details p{font-size:14px;color:var(--muted);padding:12px 24px 0 0}.ws-welcome .intro-family-access,.ws-welcome .enroll-storage{margin:24px auto 0;max-width:780px;font-size:13px;color:var(--muted);border:1px solid var(--line);padding:16px 22px;border-radius:16px}.ws-welcome .intro-family-access p,.ws-welcome .enroll-storage p{font-size:13px;max-width:none}.ws-welcome .enroll-storage h2{font-size:23px}.ws-welcome .intro-family-access summary{min-height:44px;display:list-item;padding:10px 0}
/* App baseline: bounded surfaces, readable controls and consistent rhythm. */
:root:not([data-space=welcome]) .app-header{max-width:1440px;margin-left:auto;margin-right:auto}.page,.world-journey,.student-page{min-width:0}.app-header .spaces-nav{min-width:0}.learner-bar{gap:12px}.page h1,.student-heading h1{letter-spacing:-.04em}button,input,select,textarea{accent-color:var(--accent)}
@keyframes ws-pop{50%{transform:translateY(-3px)}100%{transform:translateY(0)}}
@media(min-width:900px){:root[data-space=welcome]:not([data-motion=off]) .ws-hero-copy{animation:ws-arrive .5s ease-out}:root[data-space=welcome]:not([data-motion=off]) .ws-hero-play{animation:ws-arrive .65s ease-out}}@keyframes ws-arrive{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
@media(max-width:1050px){.ws-hero{gap:32px}.ws-welcome h1{font-size:64px}.ws-illustration img{width:290px}.ws-orbit-label{left:0;top:38px;font-size:11px}.ws-art-caption{font-size:11px}.ws-world{padding:32px;gap:32px}.ws-art-spark span{font-size:12px}.ws-steps{gap:22px}.ws-section-head{column-gap:40px}}
@media(max-width:760px){:root[data-space=welcome] .app-header{margin-top:0;padding:14px 20px;flex-wrap:wrap;gap:8px}:root[data-space=welcome] .app-header .brand{font-size:23px}:root[data-space=welcome] .motion-control{margin-left:auto}:root[data-space=welcome] #main{padding:0 22px}.ws-hero{grid-template-columns:1fr;padding:24px 0 48px;gap:4px;min-height:0}.ws-hero-copy{padding:8px 0}.ws-welcome h1{font-size:clamp(48px,9vw,66px);margin:20px 0}.ws-lead{font-size:17px;max-width:55ch!important}.ws-hero-foot{margin-top:18px}.ws-illustration{min-height:230px;margin-top:18px}.ws-illustration img{width:240px}.ws-orbit-label{left:4%;top:50px}.ws-art-caption{right:1%;bottom:32px}.ws-demo{padding:20px}.ws-demo-top{gap:8px}.ws-how{padding:48px 0}.ws-section-head{display:block}.ws-section-head>p:last-child{max-width:50ch}.ws-steps{grid-template-columns:1fr;gap:16px;margin-top:24px}.ws-steps li{display:grid;grid-template-columns:126px 1fr;column-gap:18px;padding-top:18px}.ws-step-number{grid-column:1/-1}.ws-step-art{grid-row:2/4;height:auto;min-height:100px;margin:8px 0}.ws-steps h3{margin:8px 0 10px;font-size:21px}.ws-steps p{font-size:14px;max-width:none}.ws-art-map{padding:30px 0 0;gap:4px}.ws-art-map i{top:-10px;left:42px;font-size:36px}.ws-art-map>span{font-size:10px;padding:2px 7px}.ws-art-clue{flex-direction:column;justify-content:center;gap:4px}.ws-art-clue>span{font-size:11px;padding:14px 7px}.ws-art-clue i{font-size:26px}.ws-art-spark{flex-direction:column;justify-content:center}.ws-art-spark i{width:62px;height:62px;font-size:37px;border-radius:21px}.ws-art-spark span{font-size:10px;padding:5px;margin:0;margin-top:-16px}.ws-world{grid-template-columns:1fr;padding:28px 22px;gap:20px;border-radius:24px}.ws-world-preview{order:2;padding:0 12px}.ws-world-copy p{font-size:15px}.ws-families,.ws-faq{grid-template-columns:1fr;gap:12px;padding:48px 0}.ws-families>div:last-child{padding-top:0;font-size:15px}.ws-faq details{padding:10px 0}.ws-welcome h2{font-size:32px}.ws-fine{font-size:12px}.ws-demo-note{font-size:10px}.ws-kicker{font-size:12px}.ws-question{min-height:52px}.ws-answers button{font-size:13px}.ws-welcome .primary,.ws-welcome .outline-action,.ws-welcome .ws-entry-actions a{padding:14px 17px}.ws-hero .intro-actions{gap:10px}.ws-families h2{font-size:32px}}
@media(prefers-reduced-motion:reduce){.ws-welcome *,.wise-mark{animation:none!important;transition:none!important;scroll-behavior:auto!important}.ws-welcome button:hover,.ws-welcome .primary:hover{transform:none!important}}:root[data-motion=off] .ws-welcome *{animation:none!important;transition:none!important}

.ws-demo[data-result=correct]::after{content:'';position:absolute;right:26px;top:-16px;width:20px;height:20px;border-radius:50%;background:radial-gradient(circle,#fff 0%,#e2f4eb 38%,#45856800 72%);pointer-events:none;animation:ws-celebrate .8s ease-out both}@keyframes ws-celebrate{0%{opacity:0;transform:translateY(12px) scale(.6)}35%{opacity:1;transform:translateY(-3px) scale(1.15)}100%{opacity:0;transform:translateY(-20px) scale(.8)}}@media(prefers-reduced-motion:reduce){.ws-demo[data-result=correct]::after{display:none}}:root[data-motion=off] .ws-demo[data-result=correct]::after{display:none}
/* Keep the main destinations at the top; phones use one browsable row. */
@media(max-width:760px){
 :root:not([data-space=welcome]) .app-header{padding:10px 14px 0;gap:6px 14px;border-radius:0 0 22px 22px}
 :root:not([data-space=welcome]) .app-header .spaces-nav{display:flex!important;flex-wrap:nowrap;width:100%;min-width:0;justify-content:flex-start!important;gap:5px;overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:thin;padding:7px 0 10px;margin:0;scroll-padding-inline:5px}
 :root:not([data-space=welcome]) .app-header .spaces-nav .nav-button{flex:0 0 auto;min-width:0;min-height:44px;padding:10px 15px;border-radius:12px;font-size:13px}
 :root:not([data-space=welcome]) .app-header .brand{font-size:23px}
 :root:not([data-space=welcome]) .app-header .wise-mark{width:35px;height:35px}
}

/* Keep the original family copy visibly separate from student accounts. */
.family-review-identity{display:grid;gap:4px;min-width:0}.family-review-identity .style-eyebrow{font-size:11px;letter-spacing:.04em}.family-review-identity>strong{font-size:17px}.family-review-bar .family-signin{display:inline-flex;gap:8px;align-items:center;min-height:44px;padding:10px 14px;border:1px solid var(--line);border-radius:14px;text-decoration:none;color:var(--accent);background:var(--paper);font-size:14px}.family-signin svg{width:18px;height:18px}.family-review-page{max-width:1020px;margin:auto}.family-review-page>.subtitle{max-width:55ch}.family-archive-heading{margin-top:42px}.family-archive-heading h2{margin-bottom:12px}.family-archive-heading p{max-width:65ch;color:var(--muted);line-height:1.7}.family-archive-cards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:22px;margin:22px 0}.family-archive-cards article{padding:28px;border:1px solid var(--line);border-radius:26px;background:var(--paper);min-width:0}.family-archive-face{font-size:44px;display:block}.family-archive-cards p{font-size:13px;color:var(--muted);margin:16px 0 5px}.family-archive-cards h3{font-size:27px;margin:0 0 20px}.family-archive-cards button{display:flex;align-items:center;gap:12px;font-size:14px;min-height:48px;text-align:left}.family-archive-cards .journey-icon{width:18px;height:18px}@media(max-width:560px){.family-archive-cards{grid-template-columns:1fr;gap:16px}.family-archive-cards article{padding:22px}.family-review-bar .family-review-identity{flex-basis:100%}.family-review-bar .family-signin{font-size:13px}.family-review-page h1{font-size:32px}}

/* Public challenge controls use the same calm light/dark palette as the welcome. */
.ws-challenge{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:6px 12px;padding:2px 0 12px;border-bottom:1px solid var(--line)}
.ws-challenge>span{font-size:12px;color:var(--muted)}
.ws-levels{display:flex;gap:4px}
.ws-levels button{min-height:44px;padding:8px 13px;border:1px solid transparent;border-radius:999px;background:transparent;color:var(--muted);font-size:12px;font-weight:650;box-shadow:none}
.ws-levels button:hover{background:var(--bg);color:var(--ink);transform:none}
.ws-levels button[aria-pressed=true]{background:var(--soft);border-color:var(--line);color:var(--accent)}
.ws-answers-long{flex-direction:column}
.ws-answers-long button{text-align:left;font-size:14px;line-height:1.45;padding:11px 14px}
.ws-question:focus-visible{outline:2px solid var(--accent);outline-offset:5px;border-radius:4px}
.ws-next{display:inline-flex;align-items:center;justify-content:center;gap:9px;min-height:44px;padding:9px 13px;border-radius:11px;border:1px solid var(--line);background:var(--bg);color:var(--accent);font-size:12px!important;font-weight:650;box-shadow:none}
.ws-next:hover{background:var(--soft);border-color:var(--control-line);transform:none}
@media(max-width:420px){.ws-challenge{align-items:flex-start;gap:3px}.ws-levels{width:100%}.ws-levels button{flex:1}.ws-answers-long button{font-size:13px}.ws-world{grid-template-columns:minmax(0,1fr)}.ws-world-preview,.ws-world-copy{min-width:0}.ws-garden-art{padding:14px;gap:8px;height:132px}.ws-garden-art span{font-size:40px}.ws-garden-art span:nth-child(2){font-size:56px}.ws-swatches{flex-wrap:wrap}}
.daily-joke blockquote span,.daily-joke blockquote strong{white-space:pre-line}

/* A closing horizon: quiet oversized type, with real navigation on a clear surface. */
.ws-closing{position:relative;isolation:isolate;container-type:inline-size;margin-top:12px;background:radial-gradient(ellipse 35% 42% at 35% 54%,color-mix(in srgb,var(--accent) 10%,transparent),transparent 100%),radial-gradient(ellipse 30% 36% at 69% 61%,color-mix(in srgb,var(--ws-gold) 12%,transparent),transparent 100%)}
.ws-closing .ws-final{position:relative;text-align:center;padding:64px 24px 20px}
.ws-footer-constellation{position:relative;display:grid;place-items:center;width:112px;height:70px;margin:0 auto 18px;color:#ad7310;font-size:48px;line-height:1}
.ws-footer-constellation span{display:block;text-shadow:0 3px 20px #f6c85f48}
.ws-footer-constellation span:nth-child(2){position:absolute;left:7px;top:34px;font-size:18px;color:var(--accent)}
.ws-footer-constellation span:nth-child(3){position:absolute;right:10px;top:8px;font-size:13px;color:var(--accent)}
.ws-closing-kicker{display:block;font-size:12px;font-weight:650;letter-spacing:.06em;color:var(--muted)}
.ws-closing .ws-final h2{font-size:clamp(42px,5.3vw,68px);line-height:1.04;margin:20px 0}
.ws-closing .ws-final h2 em{font-style:normal;color:var(--accent)}
.ws-closing .ws-final p{margin:0 auto 24px;max-width:46ch;color:var(--muted)}
.ws-closing .ws-final .intro-actions,.ws-closing .ws-final .enroll-actions,.ws-closing .ws-final .ws-entry-actions{display:flex;justify-content:center;flex-wrap:wrap;gap:12px;margin:28px 0 0}
.ws-closing .ws-final .enroll-actions .primary{background:var(--accent);color:var(--on-accent);border-color:var(--accent)}
.ws-closing .ws-final .intro-account-note{font-size:12px;margin:22px auto 0;max-width:54ch}
.ws-footer{position:relative;color:var(--muted)}
/* The footer names the RELEASE, not the brand. It used to carry "Wise Sparks"
   a third time, in the logo's own letters, a few hundred pixels from the logo
   in the header and the logo in the footer: three brand names on one screen
   and nothing saying which Wise Sparks this is. It now shows the chapter this
   page belongs to, named in scripts/releases.py and set here at build time.
   The name is a title, not the logo, so it is set in the page's own heavy face,
   the headline's voice. The two layers are the ones the wordmark had: a
   gradient painted through the letters and fading toward the footer, and the
   light that follows the pointer (mountWiseFooterLight). Each span hugs its
   text, so the gradient runs across the letters rather than across the row. */
.ws-footer-wordmark{position:relative;display:grid;justify-items:center;text-align:center;
 padding:40px 8px 22px;user-select:none;cursor:default;container-type:inline-size}
.ws-release-kicker{margin:0 0 4px;font-size:clamp(12px,1.05cqi,15px);font-weight:700;
 letter-spacing:.34em;text-transform:uppercase;color:var(--muted)}
.ws-release-word{display:grid;justify-items:center;width:100%;--chars:6;
 --size:var(--word-size,min(280px,calc(92cqi / (var(--chars) * .62))));margin-bottom:calc(var(--size) * -.12)}
/* The same rounded voice .entry-joke-words already speaks in (accounts.css),
   not the generic bold system sans this carried before: on a screen this
   size, plain Helvetica/Segoe weight reads as placeholder text, not a name.
   No new font file or network request; every one of these is either a
   system face already on the device or falls through to sans-serif. */
.ws-release-word span{grid-area:1/1;display:block;width:max-content;max-width:none;pointer-events:none;
 font-family:ui-rounded,'SF Pro Rounded','Hiragino Maru Gothic ProN','Varela Round','Trebuchet MS',system-ui,sans-serif;
 font-weight:800;font-size:var(--size);line-height:.9;
 letter-spacing:.01em;text-transform:uppercase;white-space:nowrap;padding:.04em .06em .1em;
 color:transparent;-webkit-text-fill-color:transparent;-webkit-background-clip:text;background-clip:text}
.ws-footer-wordmark .ws-wordmark-base{background-image:linear-gradient(115deg,color-mix(in srgb,var(--accent) 38%,var(--bg)) 12%,color-mix(in srgb,var(--ink) 20%,var(--bg)) 56%,color-mix(in srgb,#b77b12 40%,var(--bg)) 95%);
 -webkit-mask-image:linear-gradient(#000 12%,#0009 60%,#0002 100%);
         mask-image:linear-gradient(#000 12%,#0009 60%,#0002 100%)}
.ws-footer-wordmark .ws-wordmark-light{background-image:radial-gradient(circle clamp(110px,16cqi,210px) at var(--ws-light-x,50%) var(--ws-light-y,50%),#a36c05 0%,#325cde 35%,transparent 100%);opacity:0;transition:opacity .2s ease-out}
.ws-footer-wordmark[data-lit=true] .ws-wordmark-light{opacity:1}
.ws-release-line{margin:8px 0 0;font-size:clamp(14px,1.25cqi,18px);color:var(--muted)}
.ws-visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
/* Three equal tracks. The identity column was 1.8fr -- 557px at 1440 -- for a
   logo and a 189px tagline, which left a 400px hole between it and EXPLORE:
   one fat column and two thin ones, rather than a grid. Equal thirds halve the
   hole and, more to the point, give the three a regular rhythm. Each column
   still has trailing air, but it is the same air three times, which reads as a
   grid instead of a gap. */
.ws-footer-bottom{display:grid;
 grid-template-columns:minmax(0,1.5fr) repeat(3,minmax(0,1fr));
 gap:40px clamp(28px,4vw,72px);padding:48px 0 36px;border-top:1px solid var(--line);
 align-items:start}
.ws-footer-identity{min-width:0}
.ws-footer-brand{display:inline-flex;align-items:center;gap:9px;color:var(--ink);text-decoration:none;width:fit-content;border-radius:8px}
.ws-footer-brand .wise-mark{width:36px;height:36px}
.ws-footer .ws-footer-identity p{font-size:14px;line-height:1.6;margin:14px 0 0;max-width:30ch}
.ws-footer-made{display:block;font-size:12px;line-height:1.6;margin-top:6px}
.ws-footer-links{display:flex;flex-direction:column;align-items:flex-start;gap:0;min-width:0}
.ws-footer-act{display:flex;flex-direction:column;align-items:flex-start;gap:0;min-width:0}
.ws-footer-act h3{font-size:12px;line-height:1.5;font-weight:650;letter-spacing:.07em;
 text-transform:uppercase;color:var(--muted);margin:0 0 12px}
.ws-footer-act a{display:inline-flex;align-items:center;gap:10px;min-height:44px;
 color:var(--ink);font-size:14px;font-weight:500;text-decoration:none;border-radius:10px}
.ws-footer-act a:hover{color:var(--accent)}
/* only the first one is a button; the second sits under it as a plain link */
.ws-footer-act .ws-footer-cta{padding:11px 16px;font-weight:600;border-radius:12px;
 background:var(--paper);border:1px solid var(--line);margin-bottom:4px}
.ws-footer-act .ws-footer-cta:hover{background:var(--soft);border-color:var(--accent)}
.ws-footer-links h3{font-size:12px;line-height:1.5;font-weight:650;letter-spacing:.07em;text-transform:uppercase;color:var(--muted);margin:0 0 12px;padding:0 10px}
.ws-footer-links :is(button,a){display:inline-flex;align-items:center;justify-content:space-between;gap:16px;border:0;background:transparent;color:var(--ink);font:inherit;font-size:14px;font-weight:500;line-height:1.5;text-align:left;text-decoration:none;min-height:44px;max-width:100%;padding:10px;border-radius:10px;box-shadow:none;transition:color .18s ease-out,background-color .18s ease-out}
.ws-footer-links button span{color:var(--muted);font-size:16px}
.ws-footer-links .ws-back-top{margin-top:6px;border:1px solid var(--line);padding-inline:12px}
.ws-closing-context{border-top:1px solid var(--line);padding:20px 0 12px;color:var(--muted)}
.ws-preview-note{display:block;font-size:12px;line-height:1.7}
.ws-colophon{display:grid;gap:10px;justify-items:center;text-align:center}
.ws-colophon p{margin:0}
.ws-colophon-line{font-size:15px;line-height:1.65;color:var(--ink);max-width:58ch}
.ws-colophon-rights{font-size:11.5px;line-height:1.7;color:var(--muted);max-width:72ch}
.ws-colophon-rights b{font-weight:650;color:var(--ink)}
.ws-colophon-meta{display:grid;justify-items:center;gap:3px;
 font-size:11.5px;line-height:1.7;color:var(--muted)}
.ws-colophon-meta>span:last-child{opacity:.78}
.ws-colophon-meta a{color:var(--ink);font-weight:600;text-decoration:none}
.ws-colophon-meta a:hover{color:var(--accent);text-decoration:underline;text-underline-offset:3px}
.ws-colophon-build{display:block;margin-top:4px;opacity:.78}

.ws-closing-context .intro-family-access,.ws-closing-context .enroll-storage{margin:12px auto 0}
:root[data-welcome-night=true] .ws-footer-constellation{color:var(--ws-gold)}
:root[data-welcome-night=true] .ws-wordmark-base{background-image:linear-gradient(115deg,#709ae2 12%,#8cadd3 54%,#eac775 95%);opacity:.42}
:root[data-welcome-night=true] .ws-wordmark-light{background-image:radial-gradient(circle clamp(110px,16cqi,210px) at var(--ws-light-x,50%) var(--ws-light-y,50%),#fff1cc 0%,#f6cc74 22%,#b9d6ff 48%,transparent 100%)}
/* One short response to a pointer entering the closing scene; no looping or flashing. */
@media(hover:hover) and (pointer:fine){
 .ws-footer-links :is(button,a):hover{color:var(--accent);background:var(--soft);transform:none}

 :root:not([data-motion=off]):not([data-input=keyboard]):not(:has([data-spark-motion][aria-pressed=false])) .ws-closing:hover .ws-footer-constellation span{animation:ws-footer-curiosity 3.6s ease-in-out both}
 .ws-closing:hover .ws-footer-constellation span:nth-child(2){animation-delay:.14s}
 .ws-closing:hover .ws-footer-constellation span:nth-child(3){animation-delay:.28s}
}
@keyframes ws-footer-curiosity{0%,100%{transform:translateY(0) rotate(0)}35%{transform:translateY(-7px) rotate(12deg)}68%{transform:translateY(2px) rotate(-5deg)}}
@media(max-width:760px){
 .ws-closing{margin-top:0}
 .ws-closing .ws-final{padding:44px 10px 14px}
 .ws-closing .ws-final h2{font-size:clamp(40px,7.5vw,54px)}
 .ws-closing .ws-final>p:not(.intro-account-note){font-size:15px;max-width:34ch}
 .ws-closing-kicker{font-size:11px;letter-spacing:.025em}
 .ws-footer-wordmark{padding:30px 0 16px}
 .ws-footer-bottom{grid-template-columns:repeat(2,minmax(0,1fr));gap:28px 16px;padding:28px 0}
 .ws-footer-act{grid-column:1/-1}
 .ws-footer-identity{grid-column:1/-1}
 .ws-footer-links h3{padding:0;margin-bottom:10px}
 .ws-footer-links :is(button,a){padding:10px 0;font-size:13px}
 .ws-footer-links .ws-back-top{padding-inline:10px}

 .ws-closing-context{padding-top:20px}
}
@media(max-width:360px){.ws-closing .ws-final{padding-inline:0}.ws-footer-bottom{column-gap:12px}.ws-footer-links :is(button,a){font-size:12px;gap:8px}}
@media(forced-colors:active){.ws-footer-wordmark .ws-wordmark-base{background:none;color:CanvasText;-webkit-text-fill-color:CanvasText;opacity:.3;mask-image:none;-webkit-mask-image:none}.ws-wordmark-light{display:none}}
@media(prefers-reduced-motion:reduce){.ws-wordmark-light{display:none}}
:root[data-motion=off] .ws-wordmark-light,:root[data-input=keyboard] .ws-wordmark-light{display:none}

/* Selected direction B. Preserve text names for accessibility and custom branding. */
[data-brand-name="Wise Sparks"]{position:relative;min-width:116px;min-height:64px}
[data-brand-name="Wise Sparks"]::before{content:"";display:block;width:116px;height:66px;background:url("/assets/d2c14e3d12515f144b1387f8c1348e207197a7e14eb60e2c3ea5bd481012e9a6.svg") center/contain no-repeat;flex:none}
[data-brand-name="Wise Sparks"]>.wise-mark{display:none!important}
[data-brand-name="Wise Sparks"]>span{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
[data-brand-name="Wise Sparks"]::after{content:"";position:absolute;inset:0;
 background:url("/assets/81847952de9e906330eb12d338cc6053f181c9b42e8e5abd201958e0c55e0f07.svg") center/contain no-repeat;
 opacity:0;pointer-events:none}
:root[data-mode="dark"] [data-brand-name="Wise Sparks"]::after,:root[data-welcome-night="true"] [data-brand-name="Wise Sparks"]::after{opacity:1}
@media(max-width:520px){[data-brand-name="Wise Sparks"]{min-width:102px;min-height:58px}[data-brand-name="Wise Sparks"]::before{width:102px;height:58px}}
/* Moving between Wise Sparks pages crossfades instead of blanking, where the
   browser supports it. Both pages must opt in, so every public page does. */
@view-transition{navigation:auto}
@media(prefers-reduced-motion:reduce){@view-transition{navigation:none}}

/* ---- One day/night switch, everywhere.

        There were two. The welcome page had an 86x44 chip with a 12px radius,
        no fill, 12px text reading "Day view", sitting beside the Sign in
        button and losing to it. The account pages had a filled 999px pill at
        14px semibold that collapsed to a 44px circle only under 600px. Same
        job, same two glyphs, two different controls -- and a visitor crosses
        between them in one click.

        This is the one control. A 44px circle, a line icon that follows
        currentColor, and nothing else: no label to translate, no width to
        wrap, no second shape to keep in step. 44px is the target size, not a
        decoration, because the people reaching for it include children on
        phones.

        Loaded by both bundles -- scripts/build_playground.py for the welcome
        page and scripts/hosted_assets.py for the account pages. Add it to
        both or it silently governs only one of them.

        The icon is inline SVG in the markup rather than a background, so it
        inherits the button's colour on hover and focus and there is nothing
        for a content policy to fetch. Both builders emit the same shape:
        app/welcome.js and app/accounts.js. ---- */
.ws-mode{
 display:inline-flex;align-items:center;justify-content:center;flex:none;
 width:44px;min-width:44px;height:44px;min-height:44px;padding:0;
 border:1px solid var(--line);border-radius:999px;
 background:color-mix(in srgb,var(--paper) 72%,transparent);
 color:var(--ink);font:inherit;line-height:1;cursor:pointer;box-shadow:none;
 transition:border-color .18s ease,color .18s ease,background-color .18s ease}
.ws-mode>svg{width:20px;height:20px;display:block;pointer-events:none}
.ws-mode:hover{border-color:var(--accent);color:var(--accent);
 background:color-mix(in srgb,var(--accent) 12%,var(--paper))}
.ws-mode:focus-visible{outline:3px solid var(--accent);outline-offset:3px}
@media(prefers-reduced-motion:reduce){.ws-mode{transition:none}}

/* ---- The menu bar: one component on every page.

        Home, Plans, Sign in and the Trust & care pages each used to draw
        their own: the same six destinations in three fonts, two sizes and
        two colours, and even on the home page the four section links and the
        two page links were styled differently. This is the one bar. Every
        item is the same link at the same size; the current page is bold.
        Signed in, the same bar carries the member's own destinations
        (.site-nav-member) with Sign out where Sign in sits.

        It carries its own colours, the home page's day and night, so it
        reads the same whatever the page around it is doing: night follows
        data-welcome-night (home, Plans) or data-mode (Sign in, Trust & care).
        The day/night switch inside it is mode-switch.css, fed these colours.

        Loaded by all four builders; site-nav.js builds it where a script runs:
        scripts/build_playground.py, scripts/plans_page.py,
        scripts/hosted_assets.py and scripts/policy_center.py. ---- */
.site-nav{--ink:#182b48;--muted:#566982;--accent:#254ccb;--soft:#eaf1ff;--paper:#fff;--line:#dbe4f0;--control-line:#738aad;
 position:relative;display:flex;align-items:center;justify-content:flex-end;gap:4px;margin-left:auto;
 padding:5px 6px 5px 14px;border-radius:999px;color:var(--ink);
 font:400 14px/1.2 'Avenir Next','Trebuchet MS',system-ui,sans-serif;letter-spacing:normal;
 background:color-mix(in srgb,#f7faff 66%,transparent);
 backdrop-filter:blur(18px) saturate(1.35);-webkit-backdrop-filter:blur(18px) saturate(1.35);
 box-shadow:0 1px 0 #ffffffcc inset,0 18px 40px -30px #1d356440}
:root[data-welcome-night=true] .site-nav,:root[data-mode=dark] .site-nav{
 --ink:#edf4ff;--muted:#b0c3dd;--accent:#adcaff;--soft:#213959;--paper:#192b45;--line:#36506e;--control-line:#8ba6c9;
 background:color-mix(in srgb,#0b1428 42%,transparent);box-shadow:0 1px 0 #ffffff1f inset,0 18px 40px -28px #00000099}
.site-nav .ws-nav-links{display:contents}
.site-nav .ws-nav-more{display:none}
.site-nav .ws-nav-toggle{list-style:none}
.site-nav .ws-nav-toggle::-webkit-details-marker{display:none}
.site-nav .ws-nav-link{display:inline-flex;align-items:center;min-height:44px;padding:0 14px;border-radius:12px;
 color:var(--ink);font:inherit;text-decoration:none;white-space:nowrap;transition:background .2s ease}
.site-nav .ws-nav-link:hover{background:var(--soft)}
.site-nav .ws-nav-link[aria-current=page]{font-weight:700}
/* Sign out is a <button>, and the account pages paint every night button;
   :root keeps it the same pill as Sign in. */
:root .site-nav .ws-nav-signin{display:inline-flex;align-items:center;min-height:44px;padding:0 20px;border-radius:999px;
 color:var(--ink);font:inherit;text-decoration:none;white-space:nowrap;cursor:pointer;
 border:1px solid color-mix(in srgb,var(--control-line) 60%,transparent);
 background:color-mix(in srgb,var(--paper) 55%,transparent);
 backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);transition:background .2s ease,border-color .2s ease}
:root .site-nav .ws-nav-signin:hover{background:color-mix(in srgb,var(--paper) 85%,transparent);border-color:var(--control-line)}
:root .site-nav .ws-nav-signin[aria-current=page]{font-weight:700;border-color:var(--accent)}
.site-nav :is(.ws-nav-link,.ws-nav-signin,.ws-nav-toggle):focus-visible{outline:3px solid var(--accent);outline-offset:3px}

/* The Menu disclosure takes the row's place on phones and small tablets, on a
   signed-in bar from a wider screen (it carries more), and always on a bar
   with more destinations than any row holds. The menu hangs from the bar's
   right edge, so it never runs off a small screen. */
.site-nav .ws-nav-toggle{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:0 14px;border-radius:999px;
 font:inherit;font-weight:650;color:var(--ink);background:color-mix(in srgb,var(--paper) 72%,transparent);
 border:1px solid color-mix(in srgb,var(--line) 80%,transparent);box-shadow:none;cursor:pointer;user-select:none}
.site-nav .ws-nav-toggle svg{width:16px;height:16px}
.site-nav .ws-nav-more[open]>.ws-nav-toggle{border-color:var(--accent);color:var(--accent)}
.site-nav .ws-nav-menu{display:flex;position:absolute;top:calc(100% + 10px);right:0;z-index:30;min-width:220px;
 flex-direction:column;gap:2px;padding:8px;border-radius:18px;background:var(--paper);border:1px solid var(--line);
 box-shadow:0 24px 48px -24px color-mix(in srgb,var(--ink) 45%,transparent)}
.site-nav .ws-nav-menu>.ws-nav-link{width:100%;font-size:15px;font-weight:600}
.site-nav .ws-nav-menu>.ws-nav-link[aria-current=page]{color:var(--accent)}
.site-nav .ws-nav-menu>.ws-nav-link:hover{background:var(--soft);color:var(--accent)}
.site-nav.site-nav-folded .ws-nav-links{display:none}
.site-nav.site-nav-folded .ws-nav-more{display:block}
@media(min-width:701px){.site-nav.site-nav-folded .ws-nav-menu{display:grid;grid-template-columns:repeat(2,minmax(200px,1fr))}}
/* Where the row stops fitting, measured on 2026-09-22 with the brand beside
   it: the website's six links need 978px of window (Sign in's 52px margins),
   a family's six signed-in destinations 1157px. Each fold has room to spare
   for wider fallback fonts. */
@media(max-width:1240px){
 .site-nav.site-nav-member .ws-nav-links{display:none}
 .site-nav.site-nav-member .ws-nav-more{display:block}}
@media(max-width:1040px){
 .site-nav .ws-nav-links{display:none}
 .site-nav .ws-nav-more{display:block}}
@media(max-width:760px){
 .site-nav{padding:0;border-radius:0;background:none;box-shadow:none;backdrop-filter:none;-webkit-backdrop-filter:none;gap:8px}}
@media(max-width:560px){
 .site-nav{gap:6px;white-space:nowrap}
 .site-nav .ws-nav-toggle{width:44px;padding:0;justify-content:center;border-radius:50%}
 .site-nav .ws-nav-toggle span{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
 :root .site-nav .ws-nav-signin{padding:0 16px}}
@media(prefers-reduced-motion:no-preference){.site-nav .ws-nav-more[open] .ws-nav-menu{animation:site-menu-in .16s ease-out both}}
@keyframes site-menu-in{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
@media print{.site-nav{display:none}}
.site-nav[hidden]{display:none}

/* A layered version of the original artwork. Every animated layer owns its pivot. */
.ws-living-art{width:350px;max-width:88%;position:relative;container-type:inline-size;aspect-ratio:1240/1268;--spark-look-x:0px;--spark-look-y:0px;--spark-lean:0deg;filter:drop-shadow(0 15px 20px #17386616)}
.ws-scene-svg{display:block;width:100%;height:auto;overflow:visible}
.ws-gaze{transform:translate(var(--spark-look-x),var(--spark-look-y))}
.ws-star-curiosity{transform-origin:630px 815px;transform:rotate(var(--spark-lean))}
.ws-star-float{transform-origin:632px 835px;animation:ws-star-wonder 6.8s cubic-bezier(.45,0,.55,1) infinite}
.ws-leaf-breeze{transform-origin:342px 528px;animation:ws-leaf-wind 4.8s cubic-bezier(.45,0,.55,1) infinite}
.ws-page-left{transform-origin:550px 924px;animation:ws-page-left-flutter 5.8s cubic-bezier(.45,0,.55,1) infinite}
.ws-page-right{transform-origin:664px 975px;animation:ws-page-right-flutter 6.4s cubic-bezier(.45,0,.55,1) infinite}
.ws-book-breathe{transform-origin:620px 1140px;animation:ws-book-breathe 6.8s cubic-bezier(.45,0,.55,1) infinite}
.ws-pencil-write{transform-origin:1150px 368px;animation:ws-pencil-write 5.4s cubic-bezier(.45,0,.55,1) infinite}
.ws-writing-trail{stroke-dasharray:130;stroke-dashoffset:130;animation:ws-pencil-line 5.4s linear infinite}
.ws-scene-glints{animation:ws-scene-glow 6.8s ease-in-out infinite}
.ws-math-orbit{--cube-edge:56px;--cube-edge:16cqw;--cube-half:calc(var(--cube-edge)/2);position:absolute;left:75.5%;top:17%;width:var(--cube-edge);height:var(--cube-edge);perspective:600px;transform:translate(-50%,-50%);pointer-events:none}
.ws-math-cube{width:100%;height:100%;position:relative;transform-style:preserve-3d;transform:rotateX(-22deg) rotateY(-32deg) rotateZ(12deg);animation:ws-cube-earth 18s linear infinite}
.ws-cube-face{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;border-radius:12%;border:1px solid #b3ddff;backface-visibility:hidden;background:linear-gradient(140deg,#99d4ff,#4b94d4 66%,#347bbd);color:#fff6e9;font:750 calc(var(--cube-edge)*.72)/1 'Avenir Next',system-ui,sans-serif;text-shadow:0 2px 1px #2e5e98;box-shadow:inset 2px 2px 3px #e8f5ff80,inset -2px -3px 4px #2361a250}
.ws-cube-front{transform:translateZ(var(--cube-half))}.ws-cube-back{transform:rotateY(180deg) translateZ(var(--cube-half))}.ws-cube-right{transform:rotateY(90deg) translateZ(var(--cube-half));background:linear-gradient(150deg,#83b9ec,#3e75b4)}.ws-cube-left{transform:rotateY(-90deg) translateZ(var(--cube-half))}.ws-cube-top{transform:rotateX(90deg) translateZ(var(--cube-half));background:linear-gradient(145deg,#badffb,#83bdea)}.ws-cube-bottom{transform:rotateX(-90deg) translateZ(var(--cube-half))}
.ws-scene-controls{position:relative;display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:4px 14px;margin:-4px 0 16px;color:var(--muted);font-size:11px;line-height:1.4;text-align:center}
.ws-scene-controls button{font-size:11px;min-height:44px;padding:8px 12px;border:1px solid var(--line);background:var(--paper);color:var(--ink);border-radius:22px;box-shadow:none;white-space:nowrap}.ws-scene-controls button:hover{background:var(--soft)}.ws-scene-controls button:disabled{cursor:default;color:var(--muted)}
.ws-illustration>.ws-orbit-label{z-index:1;pointer-events:none;top:40px;left:0}
.ws-living-art[data-running=false] *{animation-play-state:paused!important}
:root[data-motion=off] .ws-living-art *{animation:none!important}
@keyframes ws-star-wonder{0%,100%{transform:translate(0,0) rotate(-.6deg)}30%{transform:translate(7px,-14px) rotate(1deg)}65%{transform:translate(-5px,-8px) rotate(-1deg)}}
@keyframes ws-leaf-wind{0%,100%{transform:rotate(-7deg)}35%{transform:rotate(9deg)}55%{transform:rotate(-2deg)}78%{transform:rotate(6deg)}}
@keyframes ws-page-left-flutter{0%,100%{transform:rotate(0deg)}22%{transform:rotate(-3deg)}38%{transform:rotate(-1deg)}65%{transform:rotate(-2.5deg)}82%{transform:rotate(0deg)}}
@keyframes ws-page-right-flutter{0%,100%{transform:rotate(0deg)}35%{transform:rotate(3.2deg)}53%{transform:rotate(.5deg)}72%{transform:rotate(2deg)}}
@keyframes ws-book-breathe{0%,100%{transform:scaleY(1)}48%{transform:scaleY(1.006)}}
@keyframes ws-pencil-write{0%,100%{transform:translate(0,0) rotate(0deg)}14%{transform:translate(-13px,-7px) rotate(-3deg)}26%{transform:translate(9px,-17px) rotate(3deg)}38%{transform:translate(19px,-5px) rotate(-2deg)}48%{transform:translate(30px,-14px) rotate(3deg)}65%,85%{transform:translate(5px,-5px) rotate(0deg)}}
@keyframes ws-pencil-line{0%,8%{stroke-dashoffset:130;opacity:0}12%{opacity:.85}48%,58%{stroke-dashoffset:0;opacity:.85}76%,100%{stroke-dashoffset:0;opacity:0}}
@keyframes ws-scene-glow{0%,100%{opacity:.6}48%{opacity:1}}
@keyframes ws-cube-earth{from{transform:rotateX(-22deg) rotateY(-32deg) rotateZ(12deg)}to{transform:rotateX(-22deg) rotateY(328deg) rotateZ(12deg)}}
@media(max-width:760px){.ws-living-art{width:310px;max-width:88%}.ws-illustration>.ws-orbit-label{top:28px;font-size:10px;padding:7px 10px;left:0}.ws-scene-controls{font-size:10px;gap:2px 8px;margin-top:0}.ws-scene-controls button{font-size:10px}}
@media(hover:none){.ws-scene-invite{display:none}}
@media(prefers-reduced-motion:reduce){.ws-living-art *{animation:none!important}.ws-scene-invite{display:none}}

/* One cream sheet lifts from the binding, turns over and settles behind the cover. */
.ws-turning-page{transform-origin:620px 925px;transform:perspective(1400px) rotateY(0deg);opacity:0;animation:ws-book-page-turn 8s cubic-bezier(.45,0,.55,1) infinite;pointer-events:none}
@keyframes ws-book-page-turn{0%,12%{opacity:0;transform:perspective(1400px) rotateY(0deg) rotateZ(0deg)}18%{opacity:1;transform:perspective(1400px) rotateY(-5deg) rotateZ(-2deg)}39%{opacity:1;transform:perspective(1400px) rotateY(-86deg) rotateZ(-9deg)}62%{opacity:1;transform:perspective(1400px) rotateY(-166deg) rotateZ(-3deg)}72%{opacity:0;transform:perspective(1400px) rotateY(-178deg) rotateZ(0deg)}100%{opacity:0;transform:perspective(1400px) rotateY(-178deg) rotateZ(0deg)}}

/* A window into the product. Color belongs to the art; reading surfaces stay clear. */
.ws-discovery{padding:clamp(22px,3.4vw,44px);background:var(--soft);border:1px solid var(--line);border-radius:32px;min-width:0}
.wd-heading{display:grid;grid-template-columns:1.15fr 1fr;align-items:end;gap:36px}
.ws-welcome .wd-heading h2{font-size:clamp(30px,3.2vw,43px);margin:12px 0 0}
.wd-heading h2 em{font-style:normal;color:var(--accent)}
.ws-welcome .wd-heading>p{font-size:16px;color:var(--muted);line-height:1.7;margin:0 0 3px;max-width:42ch}
.wd-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:30px 0 22px}
.wd-tabs{display:flex;flex-wrap:wrap;gap:6px}
.wd-tabs button,.wd-motion{background:transparent;border:1px solid transparent;border-radius:12px;color:var(--muted);padding:9px 12px;font-size:12px!important;font-weight:650;box-shadow:none;white-space:nowrap}
.wd-tabs button>span{font-size:10px;opacity:.65;margin-right:6px}
.wd-tabs button[aria-pressed=true]{background:var(--paper);color:var(--accent);border-color:var(--line);box-shadow:0 3px 7px #15335708}
.wd-motion{font-weight:500;padding:8px;flex-shrink:0}
.wd-motion span{margin-right:5px}
.wd-motion:disabled{cursor:default;opacity:.75}
.wd-tabs button:hover,.wd-motion:not(:disabled):hover{background:var(--paper)}
.wd-rail{position:relative;display:flex;gap:18px;overflow-x:auto;overscroll-behavior-x:contain;scroll-snap-type:x mandatory;scrollbar-width:none;padding:5px 0 16px;scroll-padding:0;min-width:0;border-radius:22px}
.wd-rail::-webkit-scrollbar{display:none}
.wd-rail:after{content:"";flex:0 0 44px}
.wd-rail:focus-visible{outline:3px solid var(--accent);outline-offset:5px}
.wd-card{flex:0 0 calc(100% - 62px);min-width:0;display:grid;grid-template-columns:1fr 1fr;scroll-snap-align:start;scroll-snap-stop:always;background:var(--paper);border:1px solid var(--line);border-radius:23px;box-shadow:0 9px 0 color-mix(in srgb,var(--accent) 8%,transparent);overflow:hidden}
.wd-card-copy{padding:42px 32px 28px;display:flex;flex-direction:column;align-items:flex-start;justify-content:center;position:relative}
.ws-welcome .wd-card-copy .ws-kicker{font-size:11px;letter-spacing:.025em;line-height:1.5;margin:12px 0 0}
.ws-welcome .wd-card-copy h3{font-size:clamp(25px,2.6vw,33px);margin:12px 0 16px;line-height:1.13}
.ws-welcome .wd-card-copy>p:not(.ws-kicker){font-size:15px;color:var(--muted);line-height:1.75;margin:0 0 18px;max-width:39ch}
.ws-welcome .wd-card-copy .wd-note{font-size:12px!important;color:var(--ink)!important;padding-top:6px}
.wd-card-index{position:absolute;top:22px;right:26px;font-size:10px;letter-spacing:.15em;color:var(--muted)}
.wd-try{display:flex;align-items:center;gap:22px;background:var(--soft);border:1px solid var(--line);border-radius:13px;color:var(--accent);font-size:13px!important;font-weight:650;padding:10px 14px;box-shadow:0 3px 0 var(--line);transition:transform .18s cubic-bezier(.23,1,.32,1),background .18s}
.wd-try span{font-size:19px}
.wd-try:hover{background:var(--soft-strong);transform:translateY(-2px)}
.wd-try:active{transform:translateY(1px) scale(.98);box-shadow:none}
.wd-play-invite{font-size:12px;font-weight:650;color:var(--accent);padding:10px 0}
.wd-play-invite>span{margin-right:8px}
.wd-scene{--scene-ink:#203c52;position:relative;display:flex;flex-direction:column;min-width:0;justify-content:center;background:#e6f4ef;color:var(--scene-ink);padding:24px 22px 18px;isolation:isolate}
.wd-preview-label{font-size:9px;font-weight:650;letter-spacing:.15em;display:flex;align-items:center;justify-content:space-between;gap:12px;z-index:1}
.wd-preview-label i{font-size:21px;font-style:normal;color:#b47b12}
.wd-art{position:relative;display:flex;flex-direction:column;justify-content:center;min-width:0;flex:1;min-height:255px}
.ws-welcome .wd-caption{position:relative;z-index:1;text-align:center;font-size:12px;line-height:1.55;min-height:56px;display:flex;align-items:center;justify-content:center;margin:14px 0 0;max-width:none}
.wd-footer{display:flex;align-items:center;justify-content:space-between;gap:22px;margin-top:10px}
.ws-welcome .wd-position{font-size:11px;letter-spacing:.1em;white-space:nowrap;margin:0}
.wd-position span{letter-spacing:0;font-weight:650;margin-left:12px}
.ws-welcome .wd-preview-note{font-size:11px;color:var(--muted);margin:0;text-align:center}
.wd-arrows{display:flex;gap:8px}
.wd-arrows button{width:44px;height:44px;border:1px solid var(--line);background:var(--paper);color:var(--ink);border-radius:50%;font-size:22px;box-shadow:none}
.wd-arrows button:disabled{opacity:.35;cursor:default}
.wd-arrows button:not(:disabled):hover{background:var(--accent);color:var(--on-accent)}
/* Mission islands, a path that lights up only on request. */
.wd-map{height:245px;position:relative}
.wd-map svg{position:absolute;width:100%;height:100%;inset:0;overflow:visible}
.wd-map path{fill:none;stroke:#74b6a0;stroke-width:3;stroke-dasharray:5 9;stroke-linecap:round}
.wd-island{position:absolute;display:flex;align-items:center;flex-direction:column;width:85px;gap:6px;transition:transform .25s cubic-bezier(.23,1,.32,1)}
.wd-island i{font-style:normal;background:#fff;border-radius:24px;box-shadow:0 7px 0 #afd2c0,0 14px 18px #21413c13;width:76px;height:66px;display:grid;place-items:center;font-size:37px}
.wd-island b{font-size:10px;background:#ffffffb3;border-radius:8px;padding:4px 10px}
.wd-island-one{left:0;top:115px}
.wd-island-two{left:calc(50% - 43px);top:54px}
.wd-island-three{right:-2px;top:2px}
.wd-missions[data-step="0"] [data-stop="0"],.wd-missions[data-step="1"] [data-stop="1"],.wd-missions[data-step="2"] [data-stop="2"]{transform:translateY(-8px)}
.wd-missions[data-step="0"] [data-stop="0"] i,.wd-missions[data-step="1"] [data-stop="1"] i,.wd-missions[data-step="2"] [data-stop="2"] i{background:#fff3b9;box-shadow:0 7px 0 #dfc579,0 14px 18px #21413c13}
.wd-mini-spark{position:absolute;right:14%;bottom:10px;font-size:31px;color:#bd8213}
.wd-cloud{position:absolute;background:#ffffff8f;border-radius:50%;width:70px;height:16px}
.wd-cloud:before{content:"";position:absolute;bottom:0;left:17px;border-radius:50%;background:inherit;width:31px;height:30px}
.wd-cloud-one{top:6px;left:4px}.wd-cloud-two{bottom:30px;right:0;transform:scale(.7)}
/* Number bridge: a real, small interaction, with no reward transaction. */
.wd-games .wd-scene{background:#f9eed8}
.wd-game-target{text-align:center;margin:0 0 18px}
.wd-game-target>span{font-size:12px;display:block}
.wd-game-target>strong{display:block;font-size:65px;line-height:1.15;letter-spacing:-.07em;color:#705119}
.wd-number-tiles{display:flex;gap:10px;justify-content:center;position:relative;z-index:2}
.wd-number-tiles button{color:#674d1e;background:#fffdf5;border:1px solid #dbca9e;width:52px;height:59px;border-radius:15px;font-size:26px;box-shadow:0 6px 0 #d7c492;transition:transform .2s,background .2s}
.wd-number-tiles button:nth-child(even){transform:translateY(9px)}
.wd-number-tiles button[aria-pressed=true]{background:#4e7391;color:#fff;border-color:#36566e;transform:translateY(-7px);box-shadow:0 6px 0 #36566e}
.wd-bridge{display:flex;justify-content:center;gap:5px;margin-top:33px;transform:rotate(-4deg)}
.wd-bridge i{display:block;height:12px;width:38px;border-radius:4px;background:#d6bd89;transition:background .2s,transform .2s}
.wd-games[data-solved=true] .wd-bridge i{background:#68a984;transform:translateY(-4px)}
/* Prepared clue: the same strip shown in differently sized pieces. */
.wd-clues .wd-scene{background:#edeafa}
.wd-clue-sheet{position:relative;background:#fffefa;border:1px solid #d1cce3;padding:25px 18px 30px;margin:15px 4px;border-radius:14px;box-shadow:5px 9px 0 #d5d0e7;transform:rotate(-5deg)}
.wd-sheet-label{display:block;font-size:8px;letter-spacing:.13em;color:#69758b}
.wd-clue-sheet strong{display:block;color:#423d66;font-size:50px;line-height:1.3;letter-spacing:.03em;margin:13px 0}
.wd-fraction-strips>div{display:flex;gap:3px;margin-top:7px}
.wd-fraction-strips i{height:18px;border:1px solid #bcafd7;border-radius:3px;flex:1;background:#eeebf6}
.wd-fraction-strips i:first-child{background:#9682c0}
.wd-fraction-strips>div:nth-child(2) i:first-child{background:#e2b34b}
.wd-clues[data-clue=true] .wd-fraction-strips>div:first-child i:first-child{background:linear-gradient(90deg,#9682c0 49%,#fffefa 49%,#fffefa 51%,#9682c0 51%)}
.wd-pencil{position:absolute;right:-8px;bottom:34px;font-size:48px;transform:rotate(-15deg)}
.wd-thought{position:absolute;right:-1px;top:5px;width:40px;height:40px;display:grid;place-items:center;background:#fffefa;border:1px solid #d1cce3;border-radius:50% 50% 50% 3px;font-size:24px;color:#7462a5}
/* A small reward display, without invented prices or awarded points. */
.wd-rewards .wd-scene{background:#fbe9e9}
.wd-ticket{position:absolute;top:15px;left:12px;display:flex;align-items:center;justify-content:center;gap:9px;width:185px;height:63px;background:#ffdc7a;border:1px solid #cea447;border-radius:10px;transform:rotate(-13deg);box-shadow:0 5px 0 #d8b45e}
.wd-ticket>span{font-size:9px;letter-spacing:.14em;color:#705216}
.wd-ticket>strong{font-size:32px;color:#947024}
.wd-ticket:before,.wd-ticket:after{content:"";position:absolute;top:24px;width:11px;height:15px;border-radius:50%;background:#fbe9e9}
.wd-ticket:before{left:-6px}.wd-ticket:after{right:-6px}
.wd-prizes{display:flex;justify-content:center;align-items:center;gap:10px;margin-top:84px}
.wd-prize{width:76px;height:100px;display:grid;place-items:center;font-size:47px;border:4px solid #fff;border-radius:15px;box-shadow:0 8px 0 #dac1c7;transform:rotate(8deg);transition:transform .25s cubic-bezier(.23,1,.32,1)}
.wd-prize-stars{background:#2b4167;color:#ffdf9f;position:relative;transform:rotate(-9deg)}
.wd-prize-stars i{font-size:18px;position:absolute;bottom:10px;right:9px}
.wd-prize-flower{background:#dfebed;transform:rotate(-2deg)}
.wd-prize-egg{background:#eee2fa}
.wd-rewards[data-prize="0"] .wd-prize-stars,.wd-rewards[data-prize="1"] .wd-prize-flower,.wd-rewards[data-prize="2"] .wd-prize-egg{transform:translateY(-13px) rotate(0)}
.wd-reward-label{text-align:center;font-size:11px;margin-top:22px;color:#71505c}
/* Companion garden. Idle motion is paused outside the viewport. */
.wd-companions .wd-scene{background:#e4f1e9}
.wd-pet-garden{position:relative;height:190px;display:flex;align-items:flex-end;justify-content:center;gap:10px;padding:18px 0;background:radial-gradient(ellipse at 50% 85%,#b0d9c3,transparent 64%)}
.wd-pet{font-size:97px;line-height:1.2;filter:drop-shadow(0 9px 4px #476f4820);transform-origin:50% 90%}
.wd-leaf{font-size:43px;transform-origin:50% 100%}
.wd-pet-heart{position:absolute;right:28px;top:6px;font-size:37px;color:#c56381;opacity:0;transition:opacity .2s,transform .2s;transform:translateY(9px)}
.wd-companions[data-wave=true] .wd-pet-heart{opacity:1;transform:translateY(0)}
.wd-care{display:flex;gap:12px;justify-content:center;margin-top:10px}
.wd-care>button{padding:0;cursor:pointer;color:#204936;box-shadow:0 3px 0 #bed7c9;background:#ffffffb5;border:1px solid #bcd7c9;border-radius:13px;display:grid;place-items:center;width:44px;height:44px;font-size:23px}
/* Color changes are confined to the little window. */
.wd-style .wd-scene{background:#e4effa}
.wd-style-window{--preview-bg:#bedaf2;--preview-ink:#254463;position:relative;margin:16px 8px 18px;background:var(--preview-bg);color:var(--preview-ink);border:4px solid white;border-radius:17px;box-shadow:5px 9px 0 #bacfe5;transform:rotate(-4deg);transition:background .22s}
.wd-style-window[data-wd-shade=pink]{--preview-bg:#ffd8e9;--preview-ink:#763e5f}
.wd-style-window[data-wd-shade=white]{--preview-bg:#f9fbff;--preview-ink:#33485b}
.wd-style-window[data-wd-shade=black]{--preview-bg:#223248;--preview-ink:#f2ddaf}
.wd-style-top{display:flex;justify-content:space-between;font-size:10px;padding:12px 15px;border-bottom:1px solid #6a91b533}
.wd-style-sky{display:flex;align-items:center;justify-content:center;gap:24px;height:70px}
.wd-style-sky span{font-size:38px;color:white;text-shadow:0 3px 0 #507f981c}
.wd-style-sky b{font-size:38px;color:#c1902f}
.wd-style-paper{margin:0 14px 14px;padding:15px 12px;background:#ffffffef;border-radius:9px;font-size:10px;color:#38536a}
.wd-style-paper i{display:block;width:80%;height:4px;background:#dbe6ee;border-radius:3px;margin-top:9px}.wd-style-paper i:last-child{width:60%}
.wd-color-choices{display:flex;gap:7px;justify-content:center}
.wd-color-choices button{position:relative;width:44px;height:44px;border:0;background:transparent;border-radius:50%;padding:7px}
.wd-color-choices button:before{content:"";display:block;width:30px;height:30px;background:#75b0dc;border:3px solid #fff;border-radius:50%;box-shadow:0 0 0 1px #7a92a9}
.wd-color-choices [data-wd-color=pink]:before{background:#e99ab9}
.wd-color-choices [data-wd-color=white]:before{background:#fff}
.wd-color-choices [data-wd-color=black]:before{background:#273347}
.wd-color-choices button[aria-pressed=true]{box-shadow:0 0 0 2px #3b6080}
/* Slow, small ambient motion; no automatic slide changes, flashing or timed tasks. */
.wd-card .wd-cloud{animation:wd-drift 6s ease-in-out infinite alternate}
.wd-card .wd-mini-spark,.wd-card .wd-thought{animation:wd-float 4s ease-in-out infinite}
.wd-card .wd-ticket{animation:wd-ticket-float 5s ease-in-out infinite}
.wd-card .wd-pet{animation:wd-breathe 4s ease-in-out infinite}
.wd-card .wd-leaf{animation:wd-breeze 3.8s ease-in-out infinite alternate}
.wd-card .wd-leaf-two{animation-delay:-1.6s}
.wd-card .wd-style-sky b{animation:wd-float 4.5s ease-in-out infinite}
.wd-card .wd-pencil{animation:wd-pencil 4s ease-in-out infinite}
.wd-card *,[data-wise-discovery][data-animated=false] .wd-card *{animation-play-state:paused}
[data-wise-discovery][data-animated=true] .wd-card[data-active=true] *{animation-play-state:running}
[data-wise-discovery][data-animated=true] .wd-companions[data-wave=true] .wd-pet{animation:wd-wave .6s ease-in-out 3}
@keyframes wd-drift{to{translate:12px 0}}
@keyframes wd-float{50%{translate:0 -8px;rotate:5deg}}
@keyframes wd-ticket-float{50%{transform:translateY(-7px) rotate(-9deg)}}
@keyframes wd-breathe{50%{transform:translateY(-5px) rotate(2deg)}}
@keyframes wd-breeze{from{rotate:-7deg}to{rotate:9deg}}
@keyframes wd-pencil{0%,70%,100%{translate:0 0}78%,90%{translate:-5px 4px}84%,96%{translate:3px -3px}}
@keyframes wd-wave{25%{transform:rotate(-9deg) translateY(-5px)}75%{transform:rotate(9deg) translateY(-5px)}}
/* Night is not a dimmed day. brightness(.88) on a pastel gives a muddy pastel,
   and these six panels were the only light surfaces left on the night page --
   a light-theme component sitting inside a dark card. Each keeps its own hue
   identity and gets a deep version of it instead. */
:root[data-welcome-night=true] .wd-scene{--scene-ink:#dceafb;background:#122b33}
:root[data-welcome-night=true] .wd-games .wd-scene{background:#2b2418}
:root[data-welcome-night=true] .wd-clues .wd-scene{background:#1e1b38}
:root[data-welcome-night=true] .wd-rewards .wd-scene{background:#2f1a1f}
:root[data-welcome-night=true] .wd-companions .wd-scene{background:#152d23}
:root[data-welcome-night=true] .wd-style .wd-scene{background:#13253c}
/* the drawn objects on those panels were tuned against pastel ground */
:root[data-welcome-night=true] .wd-scene .wd-preview-label{color:#9fb6d4}
:root[data-welcome-night=true] .wd-caption{color:#b7c9e2}
@media(max-width:1100px){.wd-toolbar{align-items:flex-start}.wd-tabs{gap:3px}.wd-tabs button{padding:8px}.wd-tabs button>span{display:none}.wd-card{grid-template-columns:1fr 1.05fr;flex-basis:calc(100% - 38px)}.wd-rail:after{flex-basis:20px}.wd-card-copy{padding:26px 22px}.wd-scene{padding:22px 18px 16px}.wd-motion{font-size:11px!important}.wd-prize{width:65px}}
@media(max-width:760px){.ws-discovery{padding:24px 18px;border-radius:24px}.wd-heading{grid-template-columns:1fr;gap:16px}.ws-welcome .wd-heading>p{font-size:14px;max-width:48ch}.wd-toolbar{margin:22px 0 14px;flex-wrap:wrap;gap:4px}.wd-tabs{width:100%;display:grid;grid-template-columns:repeat(3,minmax(0,1fr))}.wd-tabs button{font-size:12px!important;min-height:44px;padding:8px 6px}.wd-motion{margin-left:auto;min-height:44px}.wd-card{flex-basis:100%;grid-template-columns:1fr}.wd-rail:after{display:none}.wd-card-copy{padding:24px}.wd-scene{padding:18px 24px 10px}.wd-art{min-height:230px;flex:none;max-width:330px;width:100%;align-self:center}.wd-caption{min-height:42px!important;margin-top:4px!important}.wd-preview-label{max-width:330px;width:100%;align-self:center}.ws-welcome .wd-card-copy h3{font-size:29px}.wd-card-copy .ws-kicker{margin-top:8px!important}.wd-card-copy .wd-note{margin-top:0!important}.wd-card-index{display:none}.wd-footer{flex-wrap:wrap;gap:14px}.wd-preview-note{order:3;width:100%;text-align:left!important}.wd-position{margin-right:auto!important}.wd-map{height:225px}.wd-play-invite{display:none}.wd-game-target{margin-bottom:14px}.wd-pet-garden{height:175px}.wd-clue-sheet{margin:10px 20px 15px;padding-top:18px;padding-bottom:21px}.wd-style-window{margin:8px 22px 16px}.wd-prize{width:76px}.wd-prizes{margin-top:76px}}
@media(max-width:390px){.ws-discovery{padding:22px 12px}.wd-scene{padding:16px 12px 8px}.wd-card-copy{padding:22px 18px}.ws-welcome .wd-heading h2{font-size:28px}.wd-prize{width:62px}.wd-prizes{gap:8px}.wd-number-tiles{gap:8px}.wd-number-tiles button{width:44px;height:51px;font-size:23px}.wd-island{width:67px}.wd-island i{width:60px;height:57px;font-size:31px}.wd-island-two{left:calc(50% - 33px)}.wd-island b{padding:4px 6px}.wd-island-three{right:0}.wd-pet{font-size:81px}.wd-leaf{font-size:32px}.wd-style-window{margin-left:10px;margin-right:10px}.wd-style-paper{font-size:9px;padding:12px 8px}}
@media(prefers-reduced-motion:reduce){.ws-discovery *{animation:none!important;transition:none!important;scroll-behavior:auto!important}}
:root[data-motion=off] .ws-discovery *{animation:none!important;transition:none!important}
@media print{.wd-rail{display:block;overflow:visible}.wd-card{display:grid;break-inside:avoid;margin:20px 0}.wd-tabs,.wd-motion,.wd-footer,.wd-try{display:none}.ws-discovery *{animation:none!important}}

/* ---- Sparki, the one character: his drawn face and his living spark. Every
        page that shows him loads this, so he is the same everywhere. A rig is
        any element carrying data-sparki; "live" lets him move, "still" does
        not, and reduced motion or the page's motion switch always win. The
        face sits exactly over the frames (the render's 385x560 geometry, body
        in rows 116..560) and shows only on the forward pose, whose painted
        eyes were removed for it. ---- */
/* ---- Sparki's face. The visor is a screen and the eyes are drawn on it, so
        they follow the pointer up and down as well as sideways, blink as eyes
        rather than as a cut to another picture, and change shape. Shown only
        on the forward frame, whose painted eyes were removed to make room. ---- */
.sparki-face{position:absolute;left:0;top:20.7143%;width:100%;height:79.2857%;
 overflow:visible;pointer-events:none;opacity:0;
 transform:translateZ(1px);backface-visibility:hidden}
[data-sparki][data-show="c"] .sparki-face,
[data-sparki]:not([data-show]) .sparki-face{opacity:1}
.sparki-face .sf-glow{fill:#ffb02e;opacity:.8;filter:url(#sparki-blur)}
.sparki-face .sf-ring{fill:url(#sparki-ring)}
.sparki-face .sf-iris{fill:url(#sparki-iris)}
.sparki-face .sf-rim{fill:url(#sparki-rim)}
.sparki-face .sf-hi{fill:#fffdf6}
.sparki-face .sf-hi2{fill:#fffdf6;opacity:.75}
.sparki-face .sf-cheek{fill:#170903}
/* Aim. The whole eye shifts a little on the screen and the pupil further inside
   it; together that is up to 12px, enough to read as looking, not drifting. */
.sparki-face .sf-look{transform:translate(calc(var(--lx,0) * 6px),calc(var(--ly,0) * 5px));
 transition:transform .09s ease-out}
.sparki-face .sf-pupil{transform:translate(calc(var(--lx,0) * 6.5px),calc(var(--ly,0) * 6.5px));
 transition:transform .09s ease-out}
.sparki-face .sf-lid{transform-box:fill-box;transform-origin:50% 50%;transition:transform .07s ease-in}
[data-sparki][data-blink="true"] .sf-lid{transform:scaleY(.07)}
/* The cheek rests below the eye and rises for a warm, smiling look: what a miss
   gets from him, instead of a frown. */
.sparki-face .sf-cheek{transition:transform .3s cubic-bezier(.3,1.3,.5,1)}
[data-sparki][data-face="soft"] .sf-eye[data-eye="0"] .sf-cheek{transform:translateY(-17px)}
[data-sparki][data-face="soft"] .sf-eye[data-eye="1"] .sf-cheek{transform:translateY(-18px)}

/* ---- The living spark. A light, not a picture: the core breathes, two flares
        turn against each other, three motes ride tilted orbits, and only a
        right answer sets off the burst. ---- */
.sparki-spark{display:block;width:100%;height:100%;overflow:visible;
 transition:scale .3s ease,opacity .4s ease}
.sparki-spark .sk-bloom{fill:url(#sparki-bloom)}
.sparki-spark .sk-flare path{fill:url(#sparki-flare)}
.sparki-spark .sk-star{fill:url(#sparki-core)}
.sparki-spark .sk-hot{fill:#fffef8}
.sparki-spark .sk-orbit circle{fill:#fff4d0}
.sparki-spark .sk-b{fill:#ffe39a;opacity:0}
/* The pivot is the spark's centre, which is the ORIGIN of its viewBox. A view-box
   reference box starts at that origin, so "50% 50%" would be (44,44), and a
   turning flare swung off to one side and drew a stray cross. */
.sparki-spark .sk-bloom,.sparki-spark .sk-flare,.sparki-spark .sk-body,.sparki-spark .sk-orbit,.sparki-spark .sk-b{
 transform-box:view-box;transform-origin:0 0}
.sparki-spark .sk-b[data-b="1"]{--a:45deg}.sparki-spark .sk-b[data-b="2"]{--a:90deg}
.sparki-spark .sk-b[data-b="3"]{--a:135deg}.sparki-spark .sk-b[data-b="4"]{--a:180deg}
.sparki-spark .sk-b[data-b="5"]{--a:225deg}.sparki-spark .sk-b[data-b="6"]{--a:270deg}
.sparki-spark .sk-b[data-b="7"]{--a:315deg}
[data-sparki="live"] .sparki-spark .sk-bloom{animation:ws-sk-glow 3.8s ease-in-out infinite alternate}
[data-sparki="live"] .sparki-spark .sk-flare{animation:ws-sk-turn 26s linear infinite,ws-sk-breathe 3.4s ease-in-out infinite alternate}
[data-sparki="live"] .sparki-spark .sk-flare-2{animation:ws-sk-turn-back 38s linear infinite,ws-sk-twinkle 2.2s ease-in-out infinite alternate}
[data-sparki="live"] .sparki-spark .sk-body{animation:ws-sk-pulse 2.6s ease-in-out infinite alternate}
[data-sparki="live"] .sparki-spark .sk-o1{animation:ws-sk-turn 5.8s linear infinite}
[data-sparki="live"] .sparki-spark .sk-o2{animation:ws-sk-turn-back 8.6s linear infinite}
[data-sparki="live"] .sparki-spark .sk-o3{animation:ws-sk-turn 12.5s linear infinite}
@keyframes ws-sk-turn{to{rotate:360deg}}
@keyframes ws-sk-turn-back{to{rotate:-360deg}}
@keyframes ws-sk-breathe{from{scale:.86}to{scale:1.08}}
@keyframes ws-sk-twinkle{from{scale:.7;opacity:.5}to{scale:1.15;opacity:1}}
@keyframes ws-sk-pulse{from{scale:.94}to{scale:1.06}}
@keyframes ws-sk-glow{from{opacity:.62;scale:.92}to{opacity:1;scale:1.06}}
/* a right answer: the core pops a quarter turn (a four-point star lands on
   itself, so nothing snaps) and eight sparks fly out */
[data-sparki="live"][data-show="joy"] .sk-body{animation:ws-sk-pop .8s cubic-bezier(.3,1.6,.4,1)}
[data-sparki="live"][data-show="joy"] .sk-bloom{animation:ws-sk-flash .9s ease-out}
[data-sparki="live"][data-show="joy"] .sk-b{animation:ws-sk-burst .9s cubic-bezier(.2,.7,.3,1) both}
@keyframes ws-sk-pop{0%{scale:1;rotate:0deg}35%{scale:1.45;rotate:45deg}100%{scale:1;rotate:90deg}}
@keyframes ws-sk-flash{0%{opacity:1;scale:1}30%{opacity:1;scale:1.55}100%{opacity:.8;scale:1}}
@keyframes ws-sk-burst{
 0%{opacity:1;transform:rotate(var(--a,0deg)) translateX(6px) scale(1)}
 100%{opacity:0;transform:rotate(var(--a,0deg)) translateX(56px) scale(.25)}}
/* a clue: one bright beat, the "idea" */
[data-sparki="live"][data-show="curious"] .sk-bloom{animation:ws-sk-flash .7s ease-out}
/* carried: brighter and a little bigger; a miss: calmer */
[data-sparki][data-face="soft"] .sparki-spark{opacity:.82}

@media(prefers-reduced-motion:reduce){
 .sparki-spark *,.sparki-face *{animation:none!important;transition:none!important}}
:root[data-motion=off] .sparki-spark *,:root[data-motion=off] .sparki-face *{
 animation:none!important;transition:none!important}


/* wide eyes: noticing something */
.sparki-face .sf-lid{scale:1;transition:transform .07s ease-in,scale .25s ease}
[data-sparki][data-face="wide"] .sf-lid{scale:1.12;transition:transform .07s ease-in,scale .18s cubic-bezier(.3,1.6,.5,1)}

/* ---- His layers, for every page that draws him with sparkiCharacter(): eight
        rendered poses stacked with one opaque (swapping OPACITY keeps every
        frame decoded, so a turn never flickers), the drawn face over the
        forward pose, and the spark in a box of its own so it can trail the
        head. Each picture is referenced once, here, so several of him on one
        page share one copy. The forward pose is the empty-visor render. ---- */
/* Sparki waits with the visitor while the next page loads (welcome.js). */
.wise-leaving{position:fixed;inset:0;z-index:1000;display:grid;place-items:center;pointer-events:none;
 background:rgba(12,8,24,.26);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
 animation:wise-leaving-in .3s ease both}
.wise-leaving-sparki{width:clamp(72px,8vw,104px);filter:drop-shadow(0 0 28px rgba(255,209,92,.55))}
.wise-leaving .sparki-float{transform-origin:50% 88%;animation:wise-leaving-hover 1.6s ease-in-out infinite}
.wise-leaving-label{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}
@keyframes wise-leaving-in{from{opacity:0}}
@keyframes wise-leaving-hover{0%,100%{transform:translateY(0) rotate(-3deg)}50%{transform:translateY(-10px) rotate(3deg)}}
@media(prefers-reduced-motion:reduce){.wise-leaving,.wise-leaving .sparki-float{animation:none}}
/* The shared defs are an inline SVG at the end of the page: out of flow, or
   its empty line box adds a strip of page background under the last section. */
.sparki-defs{position:absolute;width:0;height:0;overflow:hidden}
.sparki-character{position:relative;display:block;width:100%;aspect-ratio:385/560;
 --f-m2:url(/assets/19cbdb10e1208a2faccae5bce3d1f5be4d45e2680665354a0470bc63b74d200e.webp);--f-m1:url(/assets/38a256a612b35a3de42edcf5828d5d258299e0ae443cd90846c1df2e792d6c34.webp);--f-c:url(/assets/4dbaa613a81c2235f91309c1ef0f628405ccb4dcc0836e2f59677057e9217c9d.webp);
 --f-r1:url(/assets/38b5a8b0990874a482d3bad58ae998af39d4710b87f406150777198f528c0c22.webp);--f-r2:url(/assets/a1d84f99119858c8af4ca454e85545ac9c58ad8972f7b598bbf50f955168534a.webp);
 --f-blink:url(/assets/fc82bd7fc2980b38876ffcc965391e13a8b323792f99515255fc4d4ac86437d3.webp);--f-joy:url(/assets/82fe1d11d54472ce002e6781cc23415578e83451ca8d7af3ae9152471e24ddcc.webp);
 --f-curious:url(/assets/4da11859136e61d37b7e623d01fa0b046f4cff40b9b122e687375342470eaf91.webp)}
.sparki-float{position:absolute;inset:0;display:block}
.sparki-frame{position:absolute;left:0;top:20.7143%;width:100%;height:79.2857%;
 display:block;opacity:0;background-repeat:no-repeat;background-size:contain;
 background-position:50% 100%;filter:drop-shadow(0 6px 5px #bd892226)}
.sparki-frame[data-f=m2]{background-image:var(--f-m2)}
.sparki-frame[data-f=m1]{background-image:var(--f-m1)}
.sparki-frame[data-f=c]{background-image:var(--f-c)}
.sparki-frame[data-f=r1]{background-image:var(--f-r1)}
.sparki-frame[data-f=r2]{background-image:var(--f-r2)}
.sparki-frame[data-f=blink]{background-image:var(--f-blink)}
.sparki-frame[data-f=joy]{background-image:var(--f-joy)}
.sparki-frame[data-f=curious]{background-image:var(--f-curious)}
.sparki-character:not([data-show]) .sparki-frame[data-f=c],
.sparki-character[data-show=c] .sparki-frame[data-f=c],
.sparki-character[data-show=m2] .sparki-frame[data-f=m2],
.sparki-character[data-show=m1] .sparki-frame[data-f=m1],
.sparki-character[data-show=r1] .sparki-frame[data-f=r1],
.sparki-character[data-show=r2] .sparki-frame[data-f=r2],
.sparki-character[data-show=joy] .sparki-frame[data-f=joy],
.sparki-character[data-show=curious] .sparki-frame[data-f=curious]{opacity:1}
.sparki-halo{position:absolute;left:27.7922%;top:1.9643%;width:41.8182%;height:18.75%;
 display:block;overflow:visible;filter:drop-shadow(0 0 11px #ffd98a96);
 transform:translateX(calc(var(--sx,0) * -7px)) rotate(calc(var(--sx,0) * -7deg));
 transition:transform .55s cubic-bezier(.22,.61,.36,1)}

/* Where Sparki stands in for a glyph: the tutor's launcher and its panel head
   wore a star in a yellow square. The character is the same one used
   everywhere else, sized to the box that square left behind. */
.sparki-symbol:has(.sparki-character){background:transparent;box-shadow:none;overflow:visible;padding:0}
.sparki-symbol .sparki-character{width:auto;height:100%}

/* Canopy: a cinematic world around the existing hero. Pure CSS + inline SVG --
   no images, no fonts, no network, so the welcome CSP is untouched.
   Nothing here restructures .ws-hero's grid; the world is painted behind it. */

.ws-hero{position:relative;isolation:isolate;
  padding:0!important;min-height:0!important;
 height:min(100vh,78vw);align-content:center}
/* No max-height: a 960px cap left 215px of empty page below the hero on a
   1175px-tall screen. 100vh is the ceiling; the vw term only matters on short
   wide windows, where it stops the band growing taller than the art can fill. */
.ws-canopy-sky{position:absolute;top:0;bottom:0;left:50%;width:100vw;margin-left:-50vw;
 z-index:-1;overflow:hidden;pointer-events:none;
 background:
  radial-gradient(120% 82% at 74% 6%,#2b3f77 0%,#1b2b55 34%,#0f1c3a 62%,#0b1428 100%),
  linear-gradient(178deg,#0c1731 0%,#122145 38%,#16294f 70%,#101d3c 100%)}
/* The seam colour follows the page theme, so the sky always dissolves into
   whatever sits below the hero instead of cutting against it. */
.ws-canopy-sky{--ws-seam:#f7faff}
:root[data-welcome-night=true] .ws-canopy-sky{--ws-seam:#101e34}
.ws-canopy-sky>*{position:absolute;pointer-events:none}

/* Depth 1 -- aurora. Two slow blurred fields; the light of the place. */

/* Depth 2 -- god rays, leaning from the upper right. */

/* Depth 3 -- far ridges. */

/* Depth 4 -- the great tree, anchored under the play column. */


/* Lanterns sit over the art and light as motes arrive. */
.ws-tree-lamp{position:absolute;width:52px;height:52px;border-radius:50%;opacity:0;
 transform:translate(-50%,-50%);pointer-events:none;
 background:radial-gradient(circle,#fffdf2 0%,#ffe9a8 22%,#f6c85f 46%,#f6c85f00 72%);
 mix-blend-mode:screen}
.ws-lamp-1{left:23%;top:31%}.ws-lamp-2{left:75%;top:27%}
.ws-lamp-3{left:48%;top:13%}.ws-lamp-4{left:41%;top:73%}

/* Depth 5 -- three subject worlds. */


/* Five worlds on an arc that descends away from the viewer. Near worlds are
   large, sharp and drift; far worlds are small, hazed and still. */
/* Depth haze: the far worlds sit back in the atmosphere. */
/* Near worlds keep their bite. */

/* Depth 6 -- ground mist under everything. */

:root:not([data-welcome-night=true]) .ws-canopy-sky{
 background:
  linear-gradient(178deg,#1b2750 0%,#34356b 26%,#5d4576 48%,#95597a 68%,#c8806f 84%,#e6ab7d 100%)}
:root:not([data-welcome-night=true]) :root:not([data-welcome-night=true]) :root:not([data-welcome-night=true]) :root:not([data-welcome-night=true]) :root:not([data-welcome-night=true]) 
/* Night. The page already flips --ink/--paper; the world follows it. */
:root[data-welcome-night=true] .ws-canopy-sky{
 background:linear-gradient(176deg,#070f20 0%,#0d1b33 40%,#101e34 74%,#101e34 100%)}
:root[data-welcome-night=true] :root[data-welcome-night=true] :root[data-welcome-night=true] :root[data-welcome-night=true] :root[data-welcome-night=true] :root[data-welcome-night=true] :root[data-welcome-night=true] :root[data-welcome-night=true] 

/* Stars: night only. A static field, cheap, no JS. */

/* The quiz stops being a card on a page and becomes a lit object in the world. */
.ws-illustration{position:relative}
.ws-illustration::before{content:'';position:absolute;z-index:0;left:50%;top:46%;
 width:118%;aspect-ratio:1;transform:translate(-50%,-50%);pointer-events:none;
 background:radial-gradient(circle,#ffeec44a 0%,#cfe0ff2e 26%,#9fc4ff1a 46%,#9fc4ff00 68%);
 filter:blur(3px);mix-blend-mode:screen}
.ws-illustration>.ws-living-art{z-index:1}

.ws-discover .ws-demo{backdrop-filter:blur(14px) saturate(1.15);-webkit-backdrop-filter:blur(14px) saturate(1.15);
 background:color-mix(in srgb,var(--paper) 78%,transparent);
 border-color:color-mix(in srgb,var(--line) 70%,#ffffff);
 box-shadow:0 30px 70px -34px #16305e73,0 2px 0 #ffffff8c inset,0 0 0 1px #ffffff1f inset}
:root[data-welcome-night=true] .ws-discover .ws-demo{
 background:color-mix(in srgb,var(--paper) 72%,transparent);
 box-shadow:0 34px 80px -34px #0006,0 1px 0 #ffffff1a inset,0 0 0 1px #ffffff14 inset}

/* ---- Build 02: the world reacts to the real quiz ---- */

/* The pool. Lives on .ws-hero-play, whose ::before/::after are both unused. */

.ws-discover::before{content:'';position:absolute;inset:-6% -8%;z-index:-1;pointer-events:none;
 border-radius:50%;opacity:0;transform:scale(.82);
 background:radial-gradient(closest-side,#f6c85f3d 0%,#f6c85f1a 46%,#f6c85f00 78%);
 transition:opacity .85s cubic-bezier(.22,.61,.36,1),transform .95s cubic-bezier(.22,.61,.36,1)}
/* A miss opens the world instead of closing it. Nothing red, nothing removed. */
.ws-canopy-on .ws-discover:has(.ws-demo[data-result=try])::before{opacity:1;transform:scale(1.14)}
.ws-canopy-on .ws-discover:has(.ws-demo[data-result=hint])::before{opacity:.92;transform:scale(1)}
.ws-canopy-on .ws-discover:has(.ws-demo[data-result=correct])::before{opacity:.8;transform:scale(1.04)}

/* The hint beam: light leans in and points at the question. */

.ws-discover::after{content:'';position:absolute;z-index:-1;pointer-events:none;
 left:6%;right:6%;top:-4%;height:74%;opacity:0;transform:translateY(-12px);
 background:conic-gradient(from 168deg at 50% -18%,#fff0 0deg,#fff3c98f 14deg,#fff0 30deg);
 filter:blur(9px);transition:opacity .6s ease,transform .8s cubic-bezier(.22,.61,.36,1)}
.ws-canopy-on .ws-discover:has(.ws-demo[data-result=hint])::after{opacity:.95;transform:translateY(0)}
.ws-canopy-on .ws-discover:has(.ws-demo[data-result=try])::after{opacity:.4;transform:translateY(0)}
:root[data-welcome-night=true] .ws-discover::after{
 background:conic-gradient(from 168deg at 50% -18%,#fff0 0deg,#ffeab54a 14deg,#fff0 30deg)}

/* The question itself catches the light. */
.ws-canopy-on .ws-demo[data-result=hint] .ws-question,
.ws-canopy-on .ws-demo[data-result=try] .ws-question{
 background:radial-gradient(120% 180% at 50% 50%,#f6c85f24 0%,#f6c85f00 72%);
 border-radius:14px;box-shadow:0 0 0 10px #f6c85f0f}

/* The mote: a learning light. A sibling of the demo, so welcome.js:91 cannot destroy it. */
.ws-mote-field{position:absolute;inset:0;z-index:4;pointer-events:none;overflow:visible}
.ws-mote{position:absolute;width:15px;height:15px;border-radius:50%;
 background:radial-gradient(circle,#fff 0%,#eafff6 34%,#78d5bdcc 62%,#78d5bd00 76%);
 box-shadow:0 0 16px 5px #78d5bd5c;
 transform:translate(-50%,-50%);will-change:transform,opacity;
 animation:ws-mote-fly var(--fly,1150ms) cubic-bezier(.34,.02,.24,1) forwards}
@keyframes ws-mote-fly{
 0%{offset-distance:0%;transform:translate(-50%,-50%) scale(.35);opacity:0}
 14%{transform:translate(-50%,-50%) scale(1.25);opacity:1}
 78%{opacity:1}
 100%{transform:translate(calc(-50% + var(--dx)),calc(-50% + var(--dy))) scale(.5);opacity:0}}

/* The canopy answers. Each arriving mote lights one more lamp, and it stays lit. */
.ws-canopy-tree[data-lit="1"] .ws-lamp-1,.ws-canopy-tree[data-lit="2"] .ws-lamp-1,
.ws-canopy-tree[data-lit="3"] .ws-lamp-1,.ws-canopy-tree[data-lit="4"] .ws-lamp-1,
.ws-canopy-tree[data-lit="2"] .ws-lamp-2,.ws-canopy-tree[data-lit="3"] .ws-lamp-2,
.ws-canopy-tree[data-lit="4"] .ws-lamp-2,.ws-canopy-tree[data-lit="3"] .ws-lamp-3,
.ws-canopy-tree[data-lit="4"] .ws-lamp-3,.ws-canopy-tree[data-lit="4"] .ws-lamp-4{opacity:1}
.ws-tree-lamp{transition:opacity .7s ease}
.ws-canopy-tree[data-pulse=true] 
/* The subject world you are actually practising lifts. Driven by the demo's own data-topic. */
.ws-canopy-act[data-topic=math] .ws-canopy-act[data-topic=math] 
/* ---- Motion. Gated on the pause control's own state, never on data-running,
        because data-running is also false when Sparki scrolls out of view. ---- */
.ws-canopy-on /* Three drift paths so no two worlds move in lockstep. Each combines lift, a
   little lateral swing and a slow tilt -- a thing hanging in air, not a bob. */

/* Both pause controls, the OS preference, and the page's own motion flag. */
@media(prefers-reduced-motion:reduce){
 .ws-canopy-sky *,.ws-mote{animation:none!important;transition:none!important}
 .ws-mote{display:none}}
:root[data-motion=off] .ws-canopy-sky *,:root[data-motion=off] .ws-mote{animation:none!important;transition:none!important}
:root[data-motion=off] .ws-mote{display:none}

/* ---- Responsive. The world is not a desktop luxury. ---- */
@media(max-width:1050px){
  }
@media(max-width:760px){
 .ws-canopy-sky{top:0;bottom:0}
 .ws-hero{padding-top:64px!important;padding-bottom:64px!important}
   
      .ws-discover::before{inset:-4% -6%}}


/* ---- The hero is a cinematic band. It borrows the page's OWN night tokens
        (brand.css:4) so the preserved headline, lead, CTAs, pilot notice and the
        live demo all restyle themselves -- no new colours invented. ---- */
.ws-hero{
 --bg:#101e34;--board:#101e34;--paper:#192b45;--ink:#edf4ff;--muted:#b0c3dd;
 --accent:#adcaff;--on-accent:#152c56;--accent-hover:#c4d9ff;--soft:#213959;
 --soft-strong:#294469;--line:#36506e;--control-line:#8ba6c9;--on-soft:#c2d8ff;
 --card-edge:#2b4568;--surface-tint:#17283f;
 color:var(--ink)}
.ws-hero .ws-kicker{color:#ffd98a}
.ws-hero h1{color:var(--ink)}
.ws-hero h1 em{color:#ffd15c}
.ws-hero .ws-lead,.ws-hero .intro-account-note,.ws-hero .ws-hero-foot{color:#bed0ec}
.ws-hero .ws-hero-foot span[aria-hidden]{color:#ffd15c}
.ws-hero .ws-orbit-label{background:#16294ad9;color:#dfeaff;border-color:#ffffff1f}

/* ---- Day view ink. The hero's colours were written for a midnight plate:
        near-white headline, pale blue body. On the daylight plate that is
        white-on-white -- measured at rgb(237,244,255) over a bright sky. The
        plate changed, so the ink has to. ---- */
:root:not([data-welcome-night=true]) .ws-hero h1{color:#122440}
:root:not([data-welcome-night=true]) .ws-hero h1 em{color:#a8670a}
:root:not([data-welcome-night=true]) .ws-hero .ws-kicker{color:#95580a}
:root:not([data-welcome-night=true]) .ws-hero .ws-lead,
:root:not([data-welcome-night=true]) .ws-hero .intro-account-note,
:root:not([data-welcome-night=true]) .ws-hero .ws-hero-foot{color:#33496b}
:root:not([data-welcome-night=true]) .ws-hero .ws-hero-foot span[aria-hidden]{color:#a8670a}
/* Named places sit over bright cloud in day view, so the halo inverts too. */
:root:not([data-welcome-night=true]) .ws-place{color:#12294c;
 text-shadow:0 1px 8px #ffffffe6,0 0 20px #ffffffcc}

/* The distant city, furthest layer, behind the ridges. */

/* The worlds arc rather than sit in a row. */
/* Measured: the copy's text ends at x696, Sparki starts at x923, the tree at
   x936 and the quiz at y469. That leaves exactly one clean pocket of sky --
   x700-920 by y120-460 -- so the three playable worlds go there, offset in both
   axes. `top` is in px from the sky, not %, because the sky's height changes
   with the hero and % kept sliding them into the text. */
/* Account-only worlds: far, small and hazed, high on the right where no text runs. */

@media(max-width:760px){
     }


/* ---- Depth layers: cloud bands sit BETWEEN island depths, which is what makes
        the sky read as volume rather than a flat backdrop. ---- */
:root:not([data-welcome-night=true]) :root:not([data-welcome-night=true]) 
/* Fireflies and light motes fill the regions that were previously dead. */


/* ---- Chrome out of the picture. .ws-scene-controls must stay a child of
        .ws-illustration -- mountWiseHeroMotion() resolves the pause button with
        host.parentElement.querySelector('[data-spark-motion]') -- so it is
        repositioned inside that parent, not moved. ---- */
/* "Move your pointer" is meaningless on touch -- hero-scene.js:54 returns early
   for pointerType==='touch'. Hide the invite, keep the pause control. */
@media(hover:none){ }

/* The chip belongs ABOVE Sparki with a tail pointing down at him. Beside him
   still overlapped: .ws-illustration is exactly his silhouette, so any inset
   percentage lands on his body. Anchoring to bottom:100% puts it clear of him
   entirely, whatever size he is drawn at. */
.ws-hero .ws-orbit-label{left:50%;right:auto;top:auto;bottom:calc(100% + 12px);
 font-size:12.5px;padding:8px 14px;border-radius:14px;z-index:6;
 text-align:center;text-wrap:balance}
.ws-hero .ws-orbit-label::after{content:'';position:absolute;left:50%;top:100%;
 width:12px;height:12px;margin:-7px 0 0 -6px;transform:rotate(45deg);
 background:inherit;border-right:1px solid #ffffff1f;border-bottom:1px solid #ffffff1f}

/* Sparki is sized so the quiz clears the fold at 1440x900. */
.ws-hero .ws-living-art{width:250px;max-width:none;aspect-ratio:385/560}
@media(max-width:1050px){.ws-hero .ws-living-art{width:210px}}
@media(max-width:760px){.ws-hero .ws-living-art{width:196px}}


.ws-canopy-sky,.ws-canopy-sky *{user-select:none;-webkit-user-select:none}



/* ---- DISCOVER: the live quiz as its own full-width band, the way the reference
        boards draw it. The world continues behind it; the quiz is the subject. ---- */
.ws-discover{position:relative;isolation:isolate;display:grid;
 grid-template-columns:minmax(0,.74fr) minmax(0,1.05fr) minmax(0,.62fr);
 gap:40px;align-items:center;
 padding:40px 0 64px;
 --paper:#192b45;--ink:#edf4ff;--muted:#b0c3dd;--accent:#adcaff;--on-accent:#152c56;
 --soft:#213959;--soft-strong:#294469;--line:#36506e;--control-line:#8ba6c9;
 --on-soft:#c2d8ff;--card-edge:#2b4568;--surface-tint:#17283f;color:var(--ink)}
.ws-discover::marker{content:none}
/* full-bleed backdrop that continues the sky */
.ws-discover>:not(.ws-band-sky){position:relative;z-index:2}
.ws-discover-sky{position:absolute;top:0;bottom:0;left:50%;width:100vw;margin-left:-50vw;
 z-index:0;overflow:hidden;pointer-events:none;user-select:none;
 background:#0b1428}
.ws-discover-sky img{position:absolute;inset:0;width:100%;height:100%;
 object-fit:cover;object-position:50% 62%;display:block}
/* The art is beautiful and the copy still has to be readable on it. The veil
   sits between them: heavy where the text and the card are, clearing toward
   the right so the island and the glow survive. */
.ws-discover-veil{position:absolute;inset:0;display:block;
 background:radial-gradient(64% 86% at 16% 46%,#0b1428e0 0%,#0b1428a8 42%,#0b14284d 68%,#0b142800 88%),
            linear-gradient(#0b1428b3 0%,#0b142826 18%,#0b142800 52%,#0b142840 84%,#0b142899 100%)}
@media(max-width:900px){
 .ws-discover-sky img{object-position:62% 58%}
 .ws-discover-veil{background:linear-gradient(#0b1428cc 0%,#0b14288c 34%,#0b1428a6 68%,#0b1428e6 100%)}}
.ws-discover-copy .ws-kicker{color:#ffd98a}
.ws-discover-copy h2{font-size:clamp(30px,3.4vw,46px);line-height:1.08;margin:10px 0 16px;
 letter-spacing:-.03em;color:var(--ink)}
.ws-discover-copy h2 em{font-style:normal;color:#ffd15c}
.ws-discover-copy p{color:#bed0ec;max-width:34ch}
.ws-discover .ws-demo{margin:0}
:root:not([data-welcome-night=true]) .ws-discover-sky{
 background:linear-gradient(178deg,#f2f6ff 0%,#eaf1ff 60%,#f7faff 100%)}
/* Night art under a day page reads as a mistake. Until the daylight plate is
   cut, the light theme keeps its wash and drops the image. */
:root:not([data-welcome-night=true]) .ws-discover-sky img,
:root:not([data-welcome-night=true]) .ws-discover-veil{display:none}
:root:not([data-welcome-night=true]) .ws-discover{
 --paper:#fff;--ink:#182b48;--muted:#566982;--accent:#254ccb;--on-accent:#fff;
 --soft:#eaf1ff;--soft-strong:#dbe7ff;--line:#dbe4f0;--control-line:#738aad;
 --on-soft:#254589;--card-edge:#d9e4f5;--surface-tint:#f3f7fd}
:root:not([data-welcome-night=true]) .ws-discover-copy h2{color:#182b48}
:root:not([data-welcome-night=true]) .ws-discover-copy p{color:#566982}
:root:not([data-welcome-night=true]) .ws-discover-copy .ws-kicker{color:#b77b12}
@media(max-width:1180px){
 /* the reward is the third thing to read; below the quiz rather than squeezed */
 .ws-discover{grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr)}
 .ws-discover>.ws-discover-reward{grid-column:1/-1;display:grid;
  grid-template-columns:auto 1fr;align-items:center;justify-items:start;
  gap:6px 22px;text-align:left;padding:20px 24px}
 .ws-discover>.ws-discover-reward .ws-reward-star{grid-row:1/3}
 .ws-discover>.ws-discover-reward .ws-reward-say{grid-column:2;align-self:end}
 .ws-discover>.ws-discover-reward .ws-reward-note{grid-column:2;align-self:start;max-width:52ch}}
@media(max-width:900px){
 .ws-discover{grid-template-columns:1fr;gap:24px;padding:32px 0 48px}
 .ws-discover-copy p{max-width:none}
 .ws-discover>.ws-discover-reward{gap:14px 18px;padding:18px 20px}}

/* ---- The subject marks. Inline SVG, aria-hidden, currentColor -- they sit
        inside a button whose own text is the label, so they say nothing and
        inherit the pressed state's colour for free. ---- */
.ws-demo-tabs button{display:inline-flex;align-items:center;justify-content:center;gap:7px}
.ws-topic-icon{width:16px;height:16px;flex:none;opacity:.72}
.ws-demo-tabs button[aria-pressed=true] .ws-topic-icon{opacity:1}
@media(max-width:420px){.ws-topic-icon{display:none}}

/* ---- The reward beat. Every state comes from :has() on the demo's own
        data-result, so the quiz stays the single source of truth about whether
        an answer was right -- this panel only reacts. ---- */
.ws-discover-reward{display:grid;justify-items:center;text-align:center;gap:14px;
 padding:26px 20px;border-radius:24px;
 background:color-mix(in srgb,var(--paper) 74%,transparent);
 border:1px solid var(--card-edge);
 box-shadow:0 1px 0 #ffffff12 inset,0 26px 60px -40px #00000099;
 backdrop-filter:blur(14px) saturate(1.15);-webkit-backdrop-filter:blur(14px) saturate(1.15)}
.ws-reward-star{position:relative;display:grid;place-items:center;
 width:104px;height:104px;color:#3d5175;border-radius:50%;
 border:2px solid #ffffff1a;
 transition:color .5s ease,transform .6s cubic-bezier(.3,1.5,.45,1),
            border-color .5s ease,box-shadow .5s ease}
.ws-discover:has(.ws-demo[data-result=correct]) .ws-reward-star{
 border-color:#ffd15c66;box-shadow:0 0 0 6px #ffd15c14,0 0 46px -6px #ffd98a80}
.ws-reward-star > svg{width:64px;height:64px;position:relative;z-index:1}
.ws-reward-burst{position:absolute;inset:-14%;border-radius:50%;opacity:0;
 background:radial-gradient(circle,#ffd98acc 0%,#ffd98a4d 38%,#ffd98a00 70%);
 transition:opacity .5s ease,transform .6s ease;transform:scale(.6)}
.ws-reward-say{margin:0!important;font-size:15px;font-weight:650;color:var(--ink);min-height:22px}
.ws-reward-say span{display:none}
.ws-reward-say span[data-say=idle]{display:inline}
.ws-reward-note{margin:0!important;font-size:12.5px;line-height:1.55;color:var(--muted);max-width:26ch}

.ws-discover:has(.ws-demo[data-result=correct]) .ws-reward-star{color:#ffd15c;transform:scale(1.06)}
.ws-discover:has(.ws-demo[data-result=correct]) .ws-reward-burst{opacity:1;transform:scale(1)}
.ws-discover:has(.ws-demo[data-result]) .ws-reward-say span[data-say=idle]{display:none}
.ws-discover:has(.ws-demo[data-result=correct]) .ws-reward-say span[data-say=correct]{display:inline}
.ws-discover:has(.ws-demo[data-result=try]) .ws-reward-say span[data-say=try]{display:inline}
.ws-discover:has(.ws-demo[data-result=hint]) .ws-reward-say span[data-say=hint]{display:inline}
.ws-canopy-on .ws-discover:has(.ws-demo[data-result=correct]) .ws-reward-star > svg{
 animation:ws-reward-pop .7s cubic-bezier(.3,1.6,.4,1)}
@keyframes ws-reward-pop{0%{scale:1;rotate:0deg}38%{scale:1.18;rotate:8deg}70%{scale:.97;rotate:-3deg}100%{scale:1;rotate:0deg}}
@media(prefers-reduced-motion:reduce),(prefers-reduced-motion){
 .ws-reward-star,.ws-reward-burst{transition:none}
 .ws-reward-star > svg{animation:none!important}}
:root[data-motion=off] .ws-reward-star,:root[data-motion=off] .ws-reward-burst{transition:none}
:root[data-motion=off] .ws-reward-star > svg{animation:none!important}


/* Worlds spread across real sky now that the quiz has its own band: two far and
   high over the copy, three near down the open channel between copy and tree. */


/* ---- Menu: glass floating ON the world, not a bar above it. The sky now runs
        up behind it, so the seam and the rule under it are gone. ---- */
/* The full-width panel was a dark band straight across the moon and the top of
   the tree. The glass now hugs the nav itself, so the sky -- moon included --
   reads through the top of the frame instead of being painted over. */
:root[data-space=welcome] .app-header{
 position:fixed;top:0;left:0;right:0;z-index:20;border-bottom:0!important;
 max-width:none;margin:0;padding:14px clamp(20px,4vw,52px);
 background:linear-gradient(#0b142866 0%,#0b142824 52%,#0b142800 100%);
 box-shadow:none}
:root[data-space=welcome]:not([data-welcome-night=true]) .app-header{
 background:linear-gradient(#f7faffc4 0%,#f7faff4d 55%,#f7faff00 100%);
 box-shadow:none}
:root[data-space=welcome] .ws-welcome section{scroll-margin-top:112px}
@media(max-width:760px){
 :root[data-space=welcome] .ws-welcome section{scroll-margin-top:164px}}
/* Below 760px brand.css gives the nav its own full-width row (order:3,
   width:100%). A pill around a full-width wrapping row is not a pill -- it was
   a stacked block sitting on the headline. The glass belongs to the floating
   layout only. */
@media(max-width:760px){
 :root[data-space=welcome] .app-header{
  background:linear-gradient(#0b1428f0 0%,#0b1428d9 62%,#0b142800 100%)}
 :root[data-space=welcome]:not([data-welcome-night=true]) .app-header{
  background:linear-gradient(#f7faffF2 0%,#f7faffdb 62%,#f7faff00 100%)}}



/* The hero's pointer invite and pause button were both removed at the owner's
   request. hero-scene.js:36 still queries for the button and is null-safe. */


/* ---- ONE COMPOSED SCENE. The tree is rooted in land inside the artwork, the
        islands sit at their own depths inside it, and there is a single horizon
        and a single light source -- none of which survives compositing cutouts,
        which is why the old stack read as objects floating on a gradient. ---- */
/* Isolated: this band composites the plate, the clip and the scrim as one
   picture, and must not reach outside itself to do it. */
.ws-canopy-sky{background:#0b1428;isolation:isolate}
:root:not([data-welcome-night=true]) .ws-canopy-sky{background:#cfe2f7}
.ws-scene-art{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
 object-position:62% 46%;display:block;z-index:0}
/* Keeps the headline column readable over whatever the art does on the left. */
/* A scrim sized to the TEXT, not to half the frame. The old linear wash ran
   90% opaque across the left 46%, which on a wide screen painted out the
   artwork entirely and left a hard vertical seam mid-page. */
.ws-scene-glow{position:absolute;inset:0;z-index:1;pointer-events:none;
 background:radial-gradient(44% 78% at 13% 50%,#08101fd6 0%,#08101f9c 40%,#08101f36 64%,#08101f00 80%)}
/* Day view: the copy is dark ink, so the scrim lifts instead of darkening. */
:root:not([data-welcome-night=true]) .ws-scene-glow{
 background:radial-gradient(46% 80% at 13% 50%,#f7faffe6 0%,#f7faffb8 40%,#f7faff4d 66%,#f7faff00 82%)}
@media(max-width:900px){
 :root:not([data-welcome-night=true]) .ws-scene-glow{
  background:linear-gradient(#f7faffeb 0%,#f7faffdb 44%,#f7faffb0 70%,#f7faff61 100%)}}
/* No ken-burns on the plate. A drifting camera is what made the loop visible;
   the frame is now dead still and only the water inside it moves. */

/* The lanterns that answer a correct answer sit over the tree in the artwork. */
.ws-canopy-tree{position:absolute;right:2%;top:4%;width:min(520px,38vw);aspect-ratio:1/1.1;z-index:2}
.ws-lamp-1{left:52%;top:18%}.ws-lamp-2{left:74%;top:9%}
.ws-lamp-3{left:64%;top:31%}.ws-lamp-4{left:83%;top:24%}

@media(max-width:760px){
 .ws-scene-art{object-position:76% 46%}
 .ws-scene-glow{background:linear-gradient(178deg,#08101fd9 0%,#08101f8f 42%,#08101f40 72%,#08101f00 100%)}
 .ws-canopy-tree{width:64vw;right:-2%;top:3%}}


/* Firefly field. One authoritative rule: the earlier ones were shredded by a
   regex cleanup and collapsed the layer to a 900px strip, which is what put a
   hard vertical seam down the middle of the hero on wide screens. */
.ws-canopy-sky .ws-motefield{
 position:absolute;left:0;right:0;top:0;height:56%;z-index:3;pointer-events:none;
 /* Two 900px tiles slide through a band that is 390px wide on a phone. The sky
    clips them visually, so nothing spilled and no scrollbar appeared -- but the
    layer itself was still laid out and composited 1800px wide, with a blend
    mode and a 54s animation on it, on the smallest devices. Clipping here
    matches the composited layer to the band. */
 overflow:hidden;
 display:flex;flex-wrap:nowrap;align-items:flex-start;
 mix-blend-mode:screen;opacity:.12;will-change:transform;
 -webkit-mask-image:linear-gradient(90deg,#000 0%,#000 46%,#0000 74%);
         mask-image:linear-gradient(90deg,#000 0%,#000 46%,#0000 74%)}
.ws-canopy-sky .ws-motefield img{flex:0 0 900px;width:900px;height:auto;display:block}
.ws-canopy-on .ws-canopy-sky .ws-motefield{animation:ws-motes 54s linear infinite}
@keyframes ws-motes{from{transform:translate3d(0,0,0)}to{transform:translate3d(-900px,0,0)}}


/* ---- Grounding. Sparki had the same fault the tree had: a cutout with nothing
        beneath it, so he hung in the air. He now sits lower, on the grassy ledge
        in the artwork, with a contact shadow and a little bounced light -- the
        two cues that say an object is resting on a surface. ---- */
.ws-hero-play{align-self:end;padding-bottom:clamp(40px,9vh,104px)}
.ws-illustration{position:relative}
.ws-illustration::after{content:'';position:absolute;z-index:0;left:50%;bottom:4%;
 width:58%;height:34px;transform:translateX(-50%);pointer-events:none;
 background:radial-gradient(closest-side,#040a14b8 0%,#040a1459 48%,#040a1400 78%);
 filter:blur(7px)}
/* bounced warm light from the grass, so his underside is not lit like a sticker */
.ws-illustration::before{
 background:radial-gradient(circle,#ffeec44a 0%,#cfe0ff2e 26%,#9fc4ff1a 46%,#9fc4ff00 68%),
            radial-gradient(70% 34% at 50% 92%,#9fd98a3d 0%,#9fd98a00 72%)}

/* ---- The scene stopped dead against the band below. It now dissolves into the
        page colour instead of cutting. ---- */
:root:not([data-welcome-night=true]) 

/* ---- Sparki. A rendered companion lit to match the scene, replacing the flat
        star rig that read as a sticker on the artwork. The pointer tracking is
        unchanged -- mountWiseHeroMotion() still writes --spark-look-x/y and
        --spark-lean on the host; the multipliers below widen its travel, which
        was only +/-9px, +/-7px and +/-1.8deg and read as barely moving. ---- */
/* the old rig's leftovers must not show through */
.ws-living-art .ws-math-orbit,.ws-living-art .ws-scene-svg{display:none}


/* ---- Sparki's frames. Eight stacked images on one baseline; exactly one is
        visible. Swapping opacity (not display) keeps every frame decoded, so a
        turn never flickers while the browser rasterises. ---- */
.ws-sparki{position:relative;width:100%;height:100%}
/* The body occupies rows 116..560 of the original 385x560 render and the star
   rows 11..116 -- so both are placed by those exact fractions, and the host box
   is given the art's own ratio. Any other ratio makes object-fit:contain
   letterbox, and the two layers drift apart. */
.ws-sparki img{position:absolute;left:0;top:20.7143%;
 width:100%;max-width:none;height:79.2857%;
 aspect-ratio:auto;object-fit:contain;display:block;opacity:0;
 /* A swap is a CUT. Cross-fading over 220ms put two Sparkis on screen at once,
    which is the ghosting that read as flashing -- and a real eye saccade is
    instant anyway. */
 transition:none;
 filter:drop-shadow(0 0 26px #ffd98a45) drop-shadow(0 18px 22px #040a1466)}
/* The star trails the head. Same --sx the rig writes every frame, but read
   through a transition, so it arrives late and settles after he does. The
   double-smoothing that was a bug on the body is the whole point here. */
.ws-sparki-halo{position:absolute;left:27.7922%;top:1.9643%;
 width:41.8182%;height:18.75%;display:block;overflow:visible;
 filter:drop-shadow(0 0 14px #ffd98a8c);
 transform:translateX(calc(var(--sx) * -10px)) rotate(calc(var(--sx) * -8deg));
 transition:transform .55s cubic-bezier(.22,.61,.36,1)}
.ws-sparki[data-show="m2"] img[data-f="m2"],.ws-sparki[data-show="m1"] img[data-f="m1"],
.ws-sparki[data-show="c"] img[data-f="c"],.ws-sparki[data-show="r1"] img[data-f="r1"],
.ws-sparki[data-show="r2"] img[data-f="r2"],.ws-sparki[data-show="blink"] img[data-f="blink"],
.ws-sparki[data-show="joy"] img[data-f="joy"],.ws-sparki[data-show="curious"] img[data-f="curious"]{opacity:1}
/* the celebration frame gets a beat of extra light */
.ws-sparki[data-show="joy"] img[data-f="joy"]{
 filter:drop-shadow(0 0 40px #ffd98aa8) drop-shadow(0 18px 22px #040a1466)}


@media(prefers-reduced-motion:reduce){
 .ws-sparki,.ws-sparki img{animation:none!important;transition:none!important}}
:root[data-motion=off] .ws-sparki,:root[data-motion=off] .ws-sparki img{
 animation:none!important;transition:none!important}


/* ---- Sparki's motion is continuous, not frame-stepped. Three transforms on
        three different clocks compose into a path that never repeats exactly:
        a long drift, a slower bank, and the eased pointer lean. Frame swaps are
        reserved for event beats, where a cut is meant to read as a cut. ---- */
/* Sparki occupies depth, not a plane. The host carries the perspective, the
   character rotates about Y and X inside it, and the frames supply the keyposes
   so his silhouette changes as he turns. Planar translate + 2D rotate is what
   made the motion read as sliding rather than turning. */
.ws-illustration{perspective:900px;perspective-origin:50% 45%}
.ws-sparki{
 --sx:0;--sy:0;--ry:0deg;--rx:0deg;--sz:0px;--bank:0deg;
 transform-style:preserve-3d;
 /* --bank is the lean into the direction he is carried; zero at rest */
 transform:translate3d(calc(var(--sx) * 22px),calc(var(--sy) * 13px),var(--sz))
           rotateZ(var(--bank)) rotateY(var(--ry)) rotateX(var(--rx));
 /* NO transition here. paint() writes these vars every animation frame; easing
    them again in CSS eased the motion twice and is what made him feel like he
    was swimming rather than turning. The spring in canopy.js is the only
    smoothing, and it is the one that can overshoot. */
 will-change:transform}
.ws-sparki img{backface-visibility:hidden;transform:translateZ(0)}
.ws-sparki img{transform-style:preserve-3d}
/* Both on the rig, not one on the rig and one on the image: they touch
   different properties so they compose, and the star -- a child now -- inherits
   the whole idle instead of drifting away from the head. */
.ws-canopy-on .ws-sparki{animation:ws-sparki-drift 13s ease-in-out infinite alternate,
                                   ws-sparki-bank 9s ease-in-out infinite alternate}
@keyframes ws-sparki-drift{
 0%  {translate:0 0 0}
 28% {translate:-14px -22px 18px}
 55% {translate:9px -34px -26px}
 78% {translate:16px -14px 12px}
 100%{translate:-6px -5px 0}}
@keyframes ws-sparki-bank{
 0%  {rotate:y -7deg;scale:1}
 35% {rotate:y 4deg;scale:1.015}
 70% {rotate:y 9deg;scale:.998}
 100%{rotate:y -3deg;scale:1.004}}
/* the celebration is the one place a jolt is wanted */
.ws-canopy-on .ws-sparki[data-show="joy"] img{animation:ws-sparki-cheer .62s cubic-bezier(.3,1.6,.4,1)}
.ws-canopy-on .ws-sparki[data-show="joy"] .ws-sparki-halo{animation:ws-halo-pop .7s cubic-bezier(.3,1.6,.4,1)}
@keyframes ws-halo-pop{0%{translate:0 0}40%{translate:0 -9px}100%{translate:0 0}}
@keyframes ws-sparki-cheer{
 0%{scale:1;rotate:0deg}
 32%{scale:1.09;rotate:-3deg}
 62%{scale:.98;rotate:2deg}
 100%{scale:1;rotate:0deg}}

@media(prefers-reduced-motion:reduce){.ws-sparki,.ws-sparki img{animation:none!important;transition:none!important}}
:root[data-motion=off] .ws-sparki,:root[data-motion=off] .ws-sparki img{animation:none!important;transition:none!important}


/* ---- The hero is a BAND the width of the screen, proportioned to the artwork
        (1344x576) so the scene is neither letterboxed nor heavily cropped, and
        the section below rises into view instead of leaving a dead strip. ---- */
.ws-hero{position:relative;display:grid;grid-template-columns:minmax(0,33%) 1fr;align-items:center}
.ws-hero-copy{padding:0 0 0 2px;position:relative;z-index:3}
/* The words grow with the band. They were sized for a laptop and then capped,
   so on a 2000px screen an 1100px-tall scene carried a 46px headline, a 15.5px
   paragraph and an 11.5px note: the smallest things in the first view were the
   ones it exists to say. The column stays a third of the band, because Sparki
   stands in the pocket beside it at 36.5%, so the type grows in size and the
   block grows in height, which the band has to spare at every width. */
.ws-hero .ws-kicker{font-size:clamp(14px,1.05vw,18px);margin:0 0 .75em}
.ws-hero h1{font-size:clamp(32px,3.4vw,68px)!important;line-height:1.04;margin:0 0 clamp(12px,.3em,22px)}
.ws-hero .ws-lead{font-size:clamp(15px,1.12vw,21px);line-height:1.55;max-width:32ch!important;margin:0 0 1.15em}
.ws-hero .ws-entry-actions{margin:0 0 12px}
.ws-hero .ws-entry-actions a{font-size:clamp(15px,1vw,19px);padding:.8em 1.25em}
.ws-hero .intro-account-note{font-size:clamp(13px,.88vw,16px);max-width:36ch}
.ws-hero .ws-hero-foot{font-size:clamp(13.5px,.8vw,15.5px);max-width:25em;margin-top:14px}
.ws-hero .ws-keep{white-space:nowrap}
/* The img, not just the <picture>, has to fill the band. object-fit on a
   <picture> does nothing -- it is not a replaced element -- so the image was
   laying out at its own aspect and leaving the bottom of the band bare. At
   night that gap is dark navy on dark navy and invisible; in day view it is a
   seam. The <video> already had these rules, so the still and the clip did not
   even agree with each other on fade-in. */
.ws-scene-art img{position:absolute;inset:0;width:100%;height:100%;
 object-fit:cover;display:block;object-position:57% 50%}
/* Exactly one plate is displayed. The theme picks it; nothing else does. */
.ws-scene-day{display:none}
:root:not([data-welcome-night=true]) .ws-scene-art{display:none}
:root:not([data-welcome-night=true]) .ws-scene-day{display:block}
/* Day has its own portrait render now, so it art-directs exactly as night
   does -- same breakpoint, same framing values. */
/* Each shape is a scene composed FOR that shape, so cover has almost nothing to
   crop. One 21:9 image stretched across every screen was losing the islands on
   short-wide displays and the children on narrow ones. */
@media(max-aspect-ratio:23/20){.ws-scene-art img{object-position:50% 46%}}

/* Named places, positioned over the landmarks in the render. */
.ws-places{position:absolute;inset:0;z-index:2;pointer-events:none}
.ws-place{position:absolute;transform:translate(-50%,0);
 font-size:12.5px;font-weight:650;letter-spacing:.11em;text-transform:uppercase;
 color:#eaf2ff;text-shadow:0 2px 10px #04101fcc,0 0 22px #04101f99;white-space:nowrap}
.ws-place-science{left:74.5%;top:35%}
.ws-place-reading{left:85.5%;top:49%}
.ws-place-math{left:92.5%;top:60%}
@media(max-width:1100px){.ws-place-math{display:none}}
@media(max-width:860px){.ws-places{display:none}}

@media(max-width:900px){
 /* Stacked, the copy sits ON the plate rather than beside it, so the scrim has
    to be a full-width wash -- the desktop radial is anchored at 13% and leaves
    the paragraph bare. Day view inverts it: the ink is dark, so the wash lifts. */
 .ws-scene-glow{background:linear-gradient(#08101fdb 0%,#08101fc7 44%,#08101f94 70%,#08101f52 100%)}
 /* Sparki gets his own strip at the foot of the band. At bottom:6% of an
    auto-height hero he landed on the actions -- and he is draggable, so he was
    swallowing taps meant for the button underneath him. */
 .ws-hero .ws-hero-play{bottom:10px}
 .ws-hero{grid-template-columns:1fr;height:auto;min-height:0;
  padding:32px 0 124px!important;align-content:start}
 .ws-hero-copy{padding-top:8px}
 .ws-scene-art img{object-position:50% 44%}}


/* The band is exactly the artwork's 1344x576, full-bleed, starting under the
   floating header -- so nothing is letterboxed, nothing is cropped away, and
   there is no strip of empty page between the scene and the section below. */
:root[data-space=welcome] main{padding-top:0}
.ws-hero-copy{padding-top:96px!important}
/* Sparki stands in the pocket the scene was composed to leave beside the child. */
.ws-hero .ws-hero-play{position:absolute;left:36.5%;bottom:13%;width:auto;z-index:4;
 padding:0;align-self:auto}
.ws-hero .ws-illustration{min-height:0;padding:0}
.ws-hero .ws-living-art{width:clamp(96px,10.4vw,168px)}
@media(max-width:900px){
 :root[data-space=welcome] main{padding-top:0}
 .ws-hero-copy{padding-top:112px!important}
 .ws-hero .ws-hero-play{left:auto;right:6%;bottom:6%}
 .ws-hero .ws-living-art{width:96px}
 /* Below this width the bubble's containing block is the 96px illustration.
    Anchored by `left` alone it shrink-to-fits into what is left of that box:
    "Try a spark with me." came out 60px wide over five lines.

    It goes above his head rather than beside it. In this band the hero is
    still one row, so his left is where the closing line ends up -- at 620px
    that line runs to x=342 and a bubble hung off his shoulder sat on the
    last two words of it. The sky over him is empty at every width here. */
 .ws-hero .ws-orbit-label{top:-62px;bottom:auto;left:auto;right:-8px;
  width:116px;max-width:none;
  transform:translate(0,7px) scale(.94);transform-origin:70% 118%}
 .ws-hero .ws-orbit-label[data-said="true"]{transform:translate(0,0) scale(1)}}

/* The words sit in the sky, not on the children. Centred in the band, the
   larger block put its paragraph over the girl's head and a button across her
   face on a 2000px screen. From the laptop up it starts under the header
   instead, and on a very wide window it moves toward the window's edge (never
   nearer than 12vw) so the words keep clear of the two figures the scene is
   composed around. Below 1654px the formula gives nothing and the copy stays
   on the page's own edge. */
@media(min-width:901px){
 .ws-hero{align-content:start}
 .ws-hero-copy{padding-top:clamp(110px,17vh,220px)!important;
  left:min(0px,12vw - (100vw - 1240px) / 2)}}


/* ---- Sparki is a pet: he can be picked up and set down anywhere in the band,
        by pointer or by keyboard. While he is held the idle drift stops, so he
        goes exactly where he is put rather than swimming out of your hand. ---- */
.ws-hero .ws-hero-play{cursor:grab;touch-action:none}
.ws-sparki{cursor:grab}
.ws-sparki[data-held="true"],.ws-hero .ws-hero-play:active{cursor:grabbing}
.ws-canopy-on .ws-sparki[data-held="true"]{animation:none}
.ws-canopy-on .ws-sparki[data-held="true"] img{animation:none}
.ws-canopy-on .ws-sparki[data-held="true"] .ws-sparki-halo{animation:ws-halo-bob 1.1s ease-in-out infinite alternate}
@keyframes ws-halo-bob{from{translate:0 0}to{translate:0 -6px}}
.ws-sparki[data-held="true"]{transition:none;scale:1.06}
.ws-sparki:focus-visible{outline:2px solid #ffd15c;outline-offset:6px;border-radius:18px}
/* once he has been moved, his placement comes from the drag, not the default spot */
.ws-hero[data-sparki-placed="true"] .ws-hero-play{bottom:auto}


/* ---- THE LIVING PLATE. The clip was shot with a locked camera -- verified:
        sky and mountains vary by a mean of 1/255 across thirteen seconds while
        the falls swing by 42 -- and its tail was cross-faded back into its head
        at build time, so <video loop> has nothing to jump over. The still
        underneath is this clip's own first frame, so the fade-in cannot shift.
        Same cover geometry as the plate, or the two would not register. ---- */
.ws-scene-video{position:absolute;inset:0;width:100%;height:100%;z-index:0;
 object-fit:cover;object-position:57% 50%;
 pointer-events:none;opacity:0;transition:opacity 1.1s ease}
.ws-scene-video[data-ready="true"]{opacity:1}
@media(prefers-reduced-motion:reduce){.ws-scene-video{display:none}}
:root[data-motion=off] .ws-scene-video{display:none}
/* the clip is the wide composition; narrow screens show the tall plate instead */
@media(hover:none),(max-width:999px){.ws-scene-video{display:none}}


/* Sparki's bubble appears when he speaks and gets out of the way when he does
   not. It stays aria-hidden: the quiz already announces results through
   .ws-answer-feedback, and a companion repeating them would double-speak. */
/* An explicit width, not max-width. The bubble is absolutely positioned inside
   .ws-illustration, which is only clamp(96px,10.4vw,168px) wide, so shrink-to-fit
   sizes it to that box and no max-width can widen it: at a 1000px window "Pick me
   up if you like." came out 64px across five one-word lines. */
.ws-hero .ws-orbit-label{opacity:0;transform:translate(-50%,7px) scale(.94);
 transition:opacity .34s ease,transform .42s cubic-bezier(.34,1.56,.64,1);
 transform-origin:50% 118%;width:148px;max-width:none;white-space:normal;line-height:1.32}
.ws-hero .ws-orbit-label[data-said="true"]{opacity:1;transform:translate(-50%,0) scale(1)}
@media(prefers-reduced-motion:reduce){.ws-hero .ws-orbit-label{transition:none}}


/* ============================================================================
   BANDS 3-8. One dark palette shared by every new band, mirroring the one
   .ws-discover already declares, plus a light-theme inversion. Declared once on
   the group rather than per section so the bands cannot drift apart.
   ========================================================================== */
.ws-learn,.ws-play,.ws-grow,.ws-origin,.ws-world-band,.ws-join{
 position:relative;isolation:isolate;
 --paper:#192b45;--ink:#edf4ff;--muted:#b0c3dd;--accent:#adcaff;--on-accent:#152c56;
 --soft:#213959;--line:#36506e;--card-edge:#2b4568;
 color:var(--ink)}
:root:not([data-welcome-night=true]) .ws-learn,
:root:not([data-welcome-night=true]) .ws-play,
:root:not([data-welcome-night=true]) .ws-grow,
:root:not([data-welcome-night=true]) .ws-origin,
:root:not([data-welcome-night=true]) .ws-world-band,
:root:not([data-welcome-night=true]) .ws-join{
 --paper:#fff;--ink:#182b48;--muted:#566982;--accent:#254ccb;--on-accent:#fff;
 --soft:#eaf1ff;--line:#dbe4f0;--card-edge:#d9e4f5}
.ws-learn h2,.ws-play h2,.ws-grow h2,.ws-origin h2,.ws-world-band h2,.ws-join h2{
 font-size:clamp(28px,3.2vw,44px);line-height:1.08;letter-spacing:-.03em;
 margin:10px 0 16px;color:var(--ink)}
.ws-learn h2 em,.ws-play h2 em,.ws-grow h2 em,.ws-origin h2 em,
.ws-world-band h2 em,.ws-join h2 em{font-style:normal;color:#ffd15c}
:root:not([data-welcome-night=true]) .ws-learn h2 em,
:root:not([data-welcome-night=true]) .ws-play h2 em,
:root:not([data-welcome-night=true]) .ws-grow h2 em,
:root:not([data-welcome-night=true]) .ws-origin h2 em,
:root:not([data-welcome-night=true]) .ws-world-band h2 em,
:root:not([data-welcome-night=true]) .ws-join h2 em{color:#a8670a}
.ws-learn p,.ws-play p,.ws-grow p,.ws-origin p,.ws-world-band p,.ws-join p{color:var(--muted)}
.ws-learn .ws-kicker,.ws-play .ws-kicker,.ws-grow .ws-kicker,
.ws-origin .ws-kicker,.ws-world-band .ws-kicker,.ws-join .ws-kicker{color:#ffd98a}
:root:not([data-welcome-night=true]) .ws-learn .ws-kicker,
:root:not([data-welcome-night=true]) .ws-play .ws-kicker,
:root:not([data-welcome-night=true]) .ws-grow .ws-kicker,
:root:not([data-welcome-night=true]) .ws-origin .ws-kicker,
:root:not([data-welcome-night=true]) .ws-world-band .ws-kicker,
:root:not([data-welcome-night=true]) .ws-join .ws-kicker{color:#95580a}

/* ---- Truth chips. Every forward-looking claim on this page wears one, so a
        visitor can tell at a glance what exists today from what is intended.
        They are real text, not decoration -- a screen reader reads them with
        the heading they qualify. ---- */
.ws-tier{display:inline-block;vertical-align:middle;margin-left:8px;
 font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
 padding:3px 8px;border-radius:999px;white-space:nowrap;
 border:1px solid currentColor}
.ws-tier[data-tier=now]{color:#7fd8b4}
.ws-tier[data-tier=limited]{color:#ffd98a}
.ws-tier[data-tier=soon]{color:#a8bcd8}
.ws-tier[data-tier=vision]{color:#c4b2ff}
.ws-tier[data-tier=example]{color:#a8bcd8}
:root:not([data-welcome-night=true]) .ws-tier[data-tier=now]{color:#1d6b4c}
:root:not([data-welcome-night=true]) .ws-tier[data-tier=limited]{color:#8a5a06}
:root:not([data-welcome-night=true]) .ws-tier[data-tier=soon]{color:#516781}
:root:not([data-welcome-night=true]) .ws-tier[data-tier=vision]{color:#54399e}
:root:not([data-welcome-night=true]) .ws-tier[data-tier=example]{color:#516781}

/* ---- Band 3: LEARN. The rail describes the journey; it does not claim an
        unlock feature. Each node keeps the step copy that was already here. --- */
.ws-learn{display:grid;grid-template-columns:minmax(0,.78fr) minmax(0,1.22fr);
 gap:clamp(28px,3.4vw,56px);align-items:center;padding:64px 0}
.ws-learn-copy p{max-width:34ch}
.ws-learn-copy>:first-child{margin-top:0}
.ws-learn-copy>:last-child{margin-bottom:0}
/* Horizontal, the way the markup draws it: three nodes in a row on one line,
   label and detail beneath each. It was vertical, which read as a list of
   steps rather than a journey with a place you are up to. */
.ws-rail{list-style:none;margin:0;display:grid;position:relative;
 grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(14px,2vw,26px);
 padding:30px clamp(20px,2.4vw,30px) 26px;border-radius:24px;
 background:color-mix(in srgb,var(--paper) 74%,transparent);
 border:1px solid var(--card-edge);
 backdrop-filter:blur(14px) saturate(1.1);-webkit-backdrop-filter:blur(14px) saturate(1.1);
 box-shadow:0 1px 0 #ffffff12 inset,0 28px 56px -40px #000000a6}
:root:not([data-welcome-night=true]) .ws-rail{
 box-shadow:0 1px 0 #ffffffcc inset,0 28px 56px -44px #1d356440}
/* the connector runs between the dot centres, behind them */
.ws-rail::before{content:'';position:absolute;left:calc(16.666% + 10px);right:calc(16.666% + 10px);
 top:calc(30px + 20px);height:2px;transform-origin:0 50%;
 background:linear-gradient(90deg,#7fd8b4,#adcaff 52%,var(--line))}
.ws-rail li{position:relative;text-align:center;padding:0 2px;min-width:0}
.ws-rail-dot{position:relative;display:grid;place-items:center;margin:0 auto 14px;
 width:40px;height:40px;border-radius:50%;background:var(--paper);
 border:2px solid var(--line);color:var(--muted);z-index:1}
.ws-rail-dot svg{width:20px;height:20px}
.ws-rail li[data-state=now] .ws-rail-dot{border-color:#7fd8b4;color:#7fd8b4}
.ws-rail li[data-state=next] .ws-rail-dot{border-color:#adcaff;color:#adcaff}
.ws-rail li[data-state=later] .ws-rail-dot{opacity:.78}
.ws-rail h3{margin:0 0 7px;font-size:16px;color:var(--ink)}
.ws-rail p{margin:0;font-size:13.5px;line-height:1.6;color:var(--muted)}
@media(max-width:620px){
 .ws-rail{grid-template-columns:1fr;gap:18px;padding:24px 20px}
 .ws-rail::before{left:39px;right:auto;top:48px;bottom:48px;width:2px;height:auto;
  background:linear-gradient(#7fd8b4,#adcaff 52%,var(--line))}
 .ws-rail li{text-align:left;padding-left:58px}
 .ws-rail-dot{position:absolute;left:0;top:-2px;margin:0}}
@media(max-width:900px){.ws-learn{grid-template-columns:1fr;gap:28px;padding:44px 0}}

/* ---- Band 4: PLAY & EARN. The one band a child is meant to see themselves
        in, so it is the one band that gets to be loud: a colour per tile, a
        neon bloom behind each mark, and a lift on hover. ---- */
.ws-play{display:grid;
 grid-template-columns:minmax(0,.55fr) minmax(0,1.65fr) minmax(0,.57fr);
 gap:clamp(22px,2.4vw,34px);align-items:center;
 padding:clamp(56px,7vw,86px) 0;min-height:min(74vh,560px)}
.ws-play>.ws-play-art-gap{display:block}
.ws-play>:not(.ws-band-sky){position:relative;z-index:2}
.ws-play-copy p{max-width:32ch}
.ws-tiles{list-style:none;margin:0;padding:0;display:grid;gap:12px;
 align-items:stretch;grid-template-columns:repeat(5,minmax(0,1fr))}
/* Flip cards: the name on the front, what it means on the back. Five columns of
   running text was unreadable at any width the markup's layout allows -- this
   keeps the front to a mark and a word and gives the sentence room on the back. */
.ws-tiles li{position:relative;perspective:1000px;background:none;border:0;padding:0;
 overflow:visible;box-shadow:none}
.ws-tile-flip{position:relative;display:block;width:100%;aspect-ratio:1/1.38;
 transform-style:preserve-3d;cursor:pointer;border-radius:20px;
 transition:transform .62s cubic-bezier(.34,1.12,.46,1)}
.ws-tiles li:hover .ws-tile-flip,.ws-tile-flip:focus-visible{transform:rotateY(180deg)}
.ws-tile-flip:focus-visible{outline:2px solid #ffd15c;outline-offset:4px}
.ws-tile-face{position:absolute;inset:0;border-radius:20px;overflow:hidden;
 min-width:0;
 -webkit-backface-visibility:hidden;backface-visibility:hidden;
 display:grid;align-content:center;justify-items:center;gap:0;
 padding:16px 11px;text-align:center;
 background:color-mix(in srgb,var(--paper) 76%,transparent);
 border:1px solid var(--card-edge);
 backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
 box-shadow:0 24px 50px -38px #000000a6}
:root:not([data-welcome-night=true]) .ws-tile-face{
 box-shadow:0 24px 50px -40px #1d356440}
/* the tile's own colour, blooming from the top */
.ws-tile-face::before{content:'';position:absolute;left:50%;top:-46%;translate:-50% 0;
 width:132%;aspect-ratio:1;border-radius:50%;pointer-events:none;
 background:radial-gradient(circle,var(--tint) 0%,transparent 66%);opacity:.42;
 transition:opacity .5s ease}
.ws-tiles li:hover .ws-tile-face::before{opacity:.72}
.ws-tile-back{transform:rotateY(180deg);
 background:color-mix(in srgb,var(--paper) 88%,transparent);
 border-color:color-mix(in srgb,var(--tint) 46%,transparent)}
.ws-tile-front>*,.ws-tile-back>*{position:relative}
.ws-tile-mark{display:grid;place-items:center;width:46px;height:46px;border-radius:15px;
 color:var(--tint);
 background:color-mix(in srgb,var(--tint) 19%,transparent);
 border:1px solid color-mix(in srgb,var(--tint) 36%,transparent);
 box-shadow:0 0 28px -6px var(--tint),0 1px 0 #ffffff1f inset;
 transition:box-shadow .45s ease,transform .45s cubic-bezier(.3,1.4,.45,1)}
.ws-tiles li:hover .ws-tile-mark{box-shadow:0 0 40px -4px var(--tint),0 1px 0 #ffffff2e inset}
.ws-tile-mark svg{width:24px;height:24px;fill:currentColor}
.ws-tiles h3{margin:12px 0 0;font-size:14.5px;color:var(--ink);line-height:1.25;
 letter-spacing:-.01em;overflow-wrap:anywhere;hyphens:none}
.ws-tiles .ws-tier{margin:8px 0 0;font-size:10px;padding:2px 7px}
.ws-tile-back p{margin:0;font-size:12.5px;line-height:1.5;color:var(--ink);
 max-width:100%;overflow-wrap:anywhere}
.ws-tiles li[data-tier=soon] .ws-tile-front{opacity:.9}
.ws-tiles li[data-tile=missions]{--tint:#ff8a3d}
.ws-tiles li[data-tile=games]{--tint:#a78bfa}
.ws-tiles li[data-tile=rewards]{--tint:#ffd15c}
.ws-tiles li[data-tile=companions]{--tint:#ff9a5c}
.ws-tiles li[data-tile=themes]{--tint:#4fd0ff}
/* No flip where motion is unwanted: the back simply sits under the front and
   both are reachable, rather than a card that spins on a hover you did not ask
   for. Screen readers read both faces either way -- they are in the DOM. */
@media(prefers-reduced-motion:reduce){
 .ws-tile-flip{transition:none}
 .ws-tiles li:hover .ws-tile-flip,.ws-tile-flip:focus-visible{transform:none}
 .ws-tile-back{position:relative;transform:none;inset:auto;margin-top:8px;
  -webkit-backface-visibility:visible;backface-visibility:visible}
 .ws-tile-flip{aspect-ratio:auto}}
:root[data-motion=off] .ws-tile-flip{transition:none}
:root[data-motion=off] .ws-tiles li:hover .ws-tile-flip{transform:none}

@media(max-width:1300px){
 /* no room for all three zones: the art column goes and the veil comes up, so
    the child reads as the band's mood instead of being half-covered by a card */
 .ws-play{grid-template-columns:minmax(0,.66fr) minmax(0,1.34fr)}
 .ws-play>.ws-play-art-gap{display:none}
 .ws-play .ws-band-veil{
  background:linear-gradient(92deg,#0b1428ed 0%,#0b1428cf 42%,#0b1428b3 72%,#0b1428a1 100%)}
 :root:not([data-welcome-night=true]) .ws-play .ws-band-veil{
  background:linear-gradient(92deg,#f4f8fff7 0%,#f4f8ffdb 42%,#f4f8ffc4 72%,#f4f8ffb0 100%)}
 .ws-tiles{grid-template-columns:repeat(5,minmax(0,1fr));gap:9px}
 .ws-tiles{gap:9px}
 .ws-tile-face{padding:14px 10px}
 .ws-tile-mark{width:42px;height:42px;border-radius:13px}
 .ws-tile-mark svg{width:23px;height:23px}
 .ws-tiles h3{margin-top:11px;font-size:13.5px}
 .ws-tile-back p{font-size:11.5px;line-height:1.5}}
@media(max-width:900px){
 .ws-play{grid-template-columns:1fr;gap:24px;padding:48px 0;min-height:0}
 .ws-play>.ws-play-art-gap{display:none}
 .ws-tiles{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
 /* stacked, the child is behind the cards whatever we do, so she becomes
    atmosphere and the veil comes up to keep the copy readable */
 .ws-play .ws-band-veil{background:linear-gradient(#0b1428e0 0%,#0b1428b8 32%,#0b1428cc 70%,#0b1428eb 100%)}
 :root:not([data-welcome-night=true]) .ws-play .ws-band-veil{
  background:linear-gradient(#f4f8ffed 0%,#f4f8ffc7 32%,#f4f8ffd6 70%,#f4f8fff2 100%)}}
/* the child sits in the right third, so this band's veil clears early */
.ws-play .ws-band-veil{
 background:radial-gradient(52% 88% at 12% 50%,#0b1428e6 0%,#0b1428ad 40%,#0b14283d 66%,#0b142800 84%),
            linear-gradient(#0b142899 0%,#0b142800 20%,#0b142800 80%,#0b142899 100%)}
:root:not([data-welcome-night=true]) .ws-play .ws-band-veil{
 background:radial-gradient(52% 88% at 12% 50%,#f4f8fff2 0%,#f4f8ffc4 40%,#f4f8ff54 66%,#f4f8ff00 84%),
            linear-gradient(#f4f8ffa8 0%,#f4f8ff00 20%,#f4f8ff00 80%,#f4f8ffa8 100%)}

/* ---- Band 5: GROW TOGETHER. The panel is an illustration and says so. ---- */
.ws-grow{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
 gap:48px;align-items:center;padding:78px 0;min-height:min(72vh,520px)}
.ws-grow-copy p{max-width:48ch;font-size:15px;line-height:1.7}
.ws-grow-aim{font-weight:650;color:var(--ink)!important}
/* The panel used to be three bars reading Math 58%, Reading 72%, Science 44%.
   Two things were wrong with that, and neither was decoration. A percentage is
   a label, and the band's own closing line says the aim is "not labels". And a
   bar shows a LEVEL, while the headline promises "you see progress" -- which is
   a change over time. So the panel now shows what the copy actually claims:
   where a child was, where they are now, and the distance between the two,
   with no number anywhere. School evidence sits below a visible divider on its
   own scale, because that separation is a promise the copy makes out loud. */
.ws-compass{margin:0;background:color-mix(in srgb,var(--paper) 80%,transparent);
 border:1px solid var(--card-edge);border-radius:22px;padding:24px;
 position:relative;isolation:isolate;overflow:hidden;
 backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px)}
.ws-compass figcaption{display:flex;align-items:center;justify-content:space-between;
 gap:12px;font-size:13.5px;font-weight:700;color:var(--ink);margin-bottom:8px}
.ws-compass .ws-compass-lede{margin:0 0 20px!important;font-size:12.5px;
 line-height:1.55;color:var(--muted)!important;max-width:44ch}

.ws-compass-rows{list-style:none;margin:0;padding:0;display:grid;gap:18px}
.ws-compass-rows li{display:grid;grid-template-columns:minmax(0,1fr) auto;
 grid-template-areas:'name say' 'track track';gap:11px 14px;align-items:baseline}
.ws-compass-name{grid-area:name;font-size:13.5px;font-weight:700;color:var(--ink)}
.ws-compass-say{grid-area:say;font-size:12px;color:var(--muted);text-align:right}
.ws-compass-track{grid-area:track;position:relative;height:10px;
 border-radius:999px;background:var(--soft)}
.ws-compass-track i{position:absolute;top:0;bottom:0;left:var(--from);
 width:calc(var(--to) - var(--from));border-radius:999px;
 background:linear-gradient(90deg,#4f7fe8,#9ad8ff);
 box-shadow:0 0 16px -4px #9ad8ffcc}
.ws-compass-track .ws-compass-then,.ws-compass-track .ws-compass-now{
 position:absolute;top:50%;border-radius:50%}
/* The "then" marker sits where the lit segment begins, so it needs to separate
   from the fill as well as from the empty track: a ring of the track's own
   colour around it does that in both directions. */
.ws-compass-track .ws-compass-then{left:var(--from);width:12px;height:12px;z-index:2;
 margin:-6px 0 0 -6px;background:var(--paper);box-sizing:border-box;
 border:2.5px solid color-mix(in srgb,var(--ink) 55%,transparent);
 box-shadow:0 0 0 2px var(--soft)}
.ws-compass-track .ws-compass-now{left:var(--to);width:14px;height:14px;z-index:3;
 margin:-7px 0 0 -7px;background:#ffd15c;
 box-shadow:0 0 0 3px #ffd15c33,0 0 18px -2px #ffd15c}

/* The bar draws from "then" to "now" as the panel arrives, so the change is
   something you watch happen. Default state is the finished one -- the
   collapsed state is gated on the reveal flag, so nothing is ever hidden by
   CSS that JS might fail to undo. */
.ws-compass-track i{transition:width .95s cubic-bezier(.22,.61,.36,1) calc(var(--d,0) * 1s)}
.ws-compass-track .ws-compass-now{transition:left .95s cubic-bezier(.22,.61,.36,1) calc(var(--d,0) * 1s)}
:root[data-ws-reveal=on] .ws-compass:not([data-reveal=in]) .ws-compass-track i{width:0}
:root[data-ws-reveal=on] .ws-compass:not([data-reveal=in]) .ws-compass-track .ws-compass-now{left:var(--from)}
@media(prefers-reduced-motion:reduce){
 .ws-compass-track i,.ws-compass-track .ws-compass-now{transition:none}}
:root[data-motion=off] .ws-compass-track i,
:root[data-motion=off] .ws-compass-track .ws-compass-now{transition:none}

.ws-compass .ws-compass-key{display:flex;align-items:center;gap:7px;flex-wrap:wrap;
 margin:14px 0 0!important;font-size:11.5px;color:var(--muted)!important}
.ws-compass-key .ws-compass-then,.ws-compass-key .ws-compass-now{
 width:11px;height:11px;border-radius:50%;flex:none}
.ws-compass-key .ws-compass-then{background:var(--paper);box-sizing:border-box;
 border:2.5px solid color-mix(in srgb,var(--ink) 55%,transparent)}
.ws-compass-key .ws-compass-now{background:#ffd15c;margin-left:10px}

/* "Kept separate" is not a caption, it is the privacy promise drawn. */
.ws-compass-split{display:flex;align-items:center;gap:12px;margin:20px 0 14px;
 font-size:10px;font-weight:700;letter-spacing:.11em;text-transform:uppercase;
 color:var(--muted)}
.ws-compass-split::before,.ws-compass-split::after{content:'';height:1px;flex:1;
 background:linear-gradient(90deg,transparent,var(--line) 40%,var(--line) 60%,transparent)}
.ws-compass-school{border-radius:14px;padding:13px 15px;
 background:color-mix(in srgb,var(--soft) 55%,transparent);
 border:1px dashed color-mix(in srgb,var(--line) 85%,transparent)}
.ws-compass .ws-compass-eyebrow{margin:0 0 6px!important;font-size:10px;font-weight:700;
 letter-spacing:.1em;text-transform:uppercase;color:var(--muted)!important}
.ws-compass .ws-compass-quote{margin:0!important;font-size:14px;line-height:1.45;
 font-weight:650;color:var(--ink)!important}
.ws-compass .ws-compass-foot{margin:7px 0 0!important;font-size:11.5px;line-height:1.5;
 color:var(--muted)!important}
.ws-compass .ws-compass-step{display:flex;align-items:flex-start;gap:10px;
 margin:18px 0 0!important;font-size:13.5px;line-height:1.5;color:var(--ink)!important}
.ws-compass .ws-compass-step .ws-gold-spark{flex:none;margin-top:1px}
.ws-compass .ws-progress-note{margin:16px 0 0!important;font-size:11.5px;line-height:1.55;
 color:var(--muted)!important}

/* The same pointer light the peek band uses, in the same coordinates. */
.ws-compass::after{content:'';position:absolute;inset:0;z-index:3;pointer-events:none;
 opacity:0;border-radius:inherit;transition:opacity .45s ease;
 background:radial-gradient(340px circle at var(--wd-mx,50%) var(--wd-my,40%),
            #ffd15c1f 0%,#ffd15c0d 38%,transparent 68%)}
.ws-compass[data-glow=on]::after{opacity:1}
@media(hover:none){.ws-compass::after{display:none}}
:root[data-motion=off] .ws-compass::after{display:none}

:root:not([data-welcome-night=true]) .ws-compass-track i{
 background:linear-gradient(90deg,#254ccb,#4f86e8);box-shadow:0 0 14px -5px #254ccb99}
:root:not([data-welcome-night=true]) .ws-compass-track .ws-compass-now{
 background:#a8670a;box-shadow:0 0 0 3px #a8670a24,0 0 16px -4px #a8670a80}
:root:not([data-welcome-night=true]) .ws-compass-key .ws-compass-now{background:#a8670a}
:root:not([data-welcome-night=true]) .ws-compass::after{
 background:radial-gradient(340px circle at var(--wd-mx,50%) var(--wd-my,40%),
            #a8670a14 0%,#a8670a08 38%,transparent 68%)}

@media(max-width:560px){
 .ws-compass{padding:18px}
 .ws-compass-rows li{grid-template-columns:1fr;grid-template-areas:'name' 'say' 'track';gap:5px}
 .ws-compass-say{text-align:left}}
@media(max-width:900px){.ws-grow{grid-template-columns:1fr;gap:26px;padding:44px 0}}

/* ---- Band 6: A REAL BEGINNING ---- */
.ws-origin{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
 gap:48px;align-items:center;padding:78px 0;min-height:min(72vh,520px)}
.ws-origin-copy p{max-width:46ch;font-size:15px;line-height:1.7}
.ws-origin-quote{font-size:21px!important;line-height:1.4;font-weight:650;
 color:var(--ink)!important;margin:0 0 16px!important;max-width:22ch!important}
/* These four are a CYCLE, and the band's own copy says so -- "keep what was
   saved, so the next step is informed rather than guessed" feeds straight back
   into Understand. Four numbered boxes in a grid could not say that: they read
   as four unrelated features. The loop is drawn where the four cards meet, and
   each step carries a mark, the way every other card set on this page does. */
.ws-origin-loop{position:relative;isolation:isolate}
/* Spokes into the hub. Without them the loop mark floats between the cards and
   reads as decoration; with them the four are visibly wired to one junction.
   They run in the gutter and only graze the card edges, where the cards' own
   blur softens them. */
.ws-origin-loop::before{content:'';position:absolute;left:50%;top:50%;
 translate:-50% -50%;width:62px;height:62px;z-index:0;pointer-events:none;
 background:linear-gradient(90deg,#ffd15c00,#ffd15c5c 26%,#ffd15c5c 74%,#ffd15c00) 50% 50%/100% 1.5px no-repeat,
            linear-gradient(180deg,#ffd15c00,#ffd15c5c 26%,#ffd15c5c 74%,#ffd15c00) 50% 50%/1.5px 100% no-repeat}
:root:not([data-welcome-night=true]) .ws-origin-loop::before{
 background:linear-gradient(90deg,#a8670a00,#a8670a5c 26%,#a8670a5c 74%,#a8670a00) 50% 50%/100% 1.5px no-repeat,
            linear-gradient(180deg,#a8670a00,#a8670a5c 26%,#a8670a5c 74%,#a8670a00) 50% 50%/1.5px 100% no-repeat}
@media(max-width:620px){.ws-origin-loop::before{display:none}}
.ws-origin-steps{list-style:none;margin:0;padding:0;counter-reset:origin;
 display:grid;gap:26px;grid-template-columns:repeat(2,minmax(0,1fr))}
.ws-origin-steps li{counter-increment:origin;position:relative;
 display:grid;grid-template-columns:38px minmax(0,1fr);gap:4px 13px;
 background:color-mix(in srgb,var(--paper) 66%,transparent);
 border:1px solid var(--card-edge);border-radius:18px;padding:17px 16px;
 backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
.ws-step-mark{grid-row:1/3;width:38px;height:38px;border-radius:50%;
 display:grid;place-items:center;color:#ffd15c;
 background:color-mix(in srgb,#ffd15c 13%,transparent);
 border:1px solid color-mix(in srgb,#ffd15c 34%,transparent)}
.ws-step-mark svg{width:20px;height:20px}
:root:not([data-welcome-night=true]) .ws-step-mark{color:#a8670a;
 background:color-mix(in srgb,#a8670a 9%,transparent);
 border-color:color-mix(in srgb,#a8670a 26%,transparent)}
.ws-origin-steps li::before{content:counter(origin,decimal-leading-zero);
 grid-column:2;align-self:end;
 font-size:11px;font-weight:800;letter-spacing:.1em;color:#ffd15c}
:root:not([data-welcome-night=true]) .ws-origin-steps li::before{color:#a8670a}
.ws-origin-steps h3{grid-column:2;margin:0;font-size:16px;color:var(--ink);line-height:1.2}
.ws-origin-steps p{grid-column:2;margin:5px 0 0;font-size:13px;line-height:1.55}

/* The loop mark sits in the gutter crossing, so the four cards read as a ring
   rather than a list. Decorative: the order is already in 01-04 and in the
   reading order, so a screen reader loses nothing by never meeting it. */
.ws-origin-cycle{position:absolute;left:50%;top:50%;translate:-50% -50%;z-index:1;
 width:34px;height:34px;display:grid;place-items:center;border-radius:50%;
 color:#ffd15c;background:color-mix(in srgb,var(--paper) 88%,transparent);
 border:1px solid color-mix(in srgb,#ffd15c 38%,transparent);
 box-shadow:0 0 0 5px color-mix(in srgb,var(--bg) 62%,transparent),
            0 0 22px -4px #ffd15c66;
 backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}
.ws-origin-cycle svg{width:17px;height:17px;
 animation:ws-origin-turn 9s linear infinite}
:root:not([data-welcome-night=true]) .ws-origin-cycle{color:#a8670a;
 border-color:color-mix(in srgb,#a8670a 30%,transparent);
 box-shadow:0 0 0 5px color-mix(in srgb,#f4f8ff 70%,transparent),
            0 0 18px -6px #a8670a80}
@keyframes ws-origin-turn{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){.ws-origin-cycle svg{animation:none}}
:root[data-motion=off] .ws-origin-cycle svg{animation:none}
@media(max-width:620px){
 .ws-origin-steps{grid-template-columns:1fr;gap:12px}
 .ws-origin-cycle{display:none}}
@media(max-width:900px){.ws-origin{grid-template-columns:1fr;gap:26px;padding:44px 0}}

/* ---- Band 7: A BRIGHTER WORLD ---- */
.ws-world-band{display:grid;grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);
 gap:44px;align-items:center;padding:82px 0;min-height:min(74vh,540px)}
.ws-world-copy p{max-width:34ch}
/* Four places, two columns. `auto-fit` with a 210px floor resolved to THREE
   tracks in this column, which left Community alone on a second row beside an
   empty half -- the one thing a "brighter world" band should not look like.
   Two columns also does the grouping for free: the two places that exist today
   sit on the top row, the two that do not on the bottom. */
.ws-places-grid{list-style:none;margin:0;padding:0;display:grid;gap:16px;
 grid-template-columns:repeat(2,minmax(0,1fr))}
.ws-places-grid li{display:grid;align-content:start;gap:11px;
 background:color-mix(in srgb,var(--paper) 68%,transparent);
 border:1px solid var(--card-edge);border-radius:18px;padding:18px 17px;
 backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
.ws-places-grid li[data-tier=vision]{border-style:dashed;opacity:.9}
/* The mark carries the tier's colour, so the chip is confirming what the card
   already said rather than being the only place the truth lives. Rounded
   squares here; the origin steps are discs, and these are different things. */
.ws-place-mark{width:40px;height:40px;border-radius:13px;display:grid;place-items:center;
 background:color-mix(in srgb,currentColor 14%,transparent);
 border:1px solid color-mix(in srgb,currentColor 34%,transparent)}
.ws-place-mark svg{width:21px;height:21px}
.ws-places-grid li[data-tier=now] .ws-place-mark{color:#7fd8b4}
.ws-places-grid li[data-tier=limited] .ws-place-mark{color:#ffd98a}
.ws-places-grid li[data-tier=vision] .ws-place-mark{color:#c4b2ff}
:root:not([data-welcome-night=true]) .ws-places-grid li[data-tier=now] .ws-place-mark{color:#1d6b4c}
:root:not([data-welcome-night=true]) .ws-places-grid li[data-tier=limited] .ws-place-mark{color:#8a5a06}
:root:not([data-welcome-night=true]) .ws-places-grid li[data-tier=vision] .ws-place-mark{color:#54399e}
.ws-places-grid h3{margin:0;font-size:16px;color:var(--ink);line-height:1.3}
.ws-places-grid p{margin:0;font-size:13px;line-height:1.55}
@media(max-width:560px){.ws-places-grid{grid-template-columns:1fr}}
@media(max-width:900px){.ws-world-band{grid-template-columns:1fr;gap:26px;padding:44px 0}}

/* ---- Band 8: JOIN THE JOURNEY ---- */
.ws-join{padding:clamp(24px,3vw,40px) 0 clamp(56px,7vw,86px);display:grid;
 align-content:start}
/* the kicker carries its own top margin from brand.css, which stacked on top
   of the band's padding -- 23px nobody asked for at a band boundary */
.ws-join .ws-join-head>.ws-kicker{margin-top:0}
.ws-welcome .ws-closing{margin-top:0}
.ws-join-head{max-width:46ch;margin-bottom:28px}
/* Three roles, three tracks, stated. `auto-fit` was resolving a phantom fourth
   track here -- harmless at this width, but it is the same shape of rule that
   orphaned a card in the band above. */
.ws-join-cards{list-style:none;margin:0;padding:0;display:grid;gap:16px;
 grid-template-columns:repeat(3,minmax(0,1fr))}
.ws-join-cards>li{background:color-mix(in srgb,var(--paper) 76%,transparent);
 border:1px solid var(--card-edge);border-radius:22px;padding:24px 22px;
 display:grid;align-content:start;gap:14px;
 backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
.ws-join-cards>li[data-tier=vision]{border-style:dashed}
/* One of these three is a door you can walk through today; the other two are a
   shape and a hope. They were identical surfaces. The parent card carries the
   live tier's own colour on its edge and a lift under it, so the real one
   looks real before you have read a word. */
.ws-join-cards>li[data-tier=now]{
 border-color:color-mix(in srgb,#7fd8b4 46%,var(--card-edge));
 box-shadow:0 1px 0 #ffffff14 inset,0 26px 54px -38px #000000b3,
            0 0 34px -18px #7fd8b4}
:root:not([data-welcome-night=true]) .ws-join-cards>li[data-tier=now]{
 border-color:color-mix(in srgb,#1d6b4c 34%,var(--card-edge));
 box-shadow:0 1px 0 #ffffffcc inset,0 26px 54px -42px #1d356440,
            0 0 30px -18px #1d6b4c66}
.ws-join-cards h3{margin:0;font-size:18px;color:var(--ink)}
.ws-join-points{list-style:none;margin:0;padding:0;display:grid;gap:9px}
.ws-join-points li{position:relative;padding-left:24px;font-size:14px;line-height:1.5;color:var(--muted)}
/* A tick means "you get this". On the educator and tutor cards -- NOT OPEN and
   VISION -- three green ticks were quietly promising three things that do not
   exist. Only the card that can deliver gets ticks; the other two get an open
   ring in their own tier colour, which reads as "intended", not "included". */
.ws-join-points li::before{content:'';position:absolute;left:0;top:5px;
 width:13px;height:7px;border-left:2px solid #7fd8b4;border-bottom:2px solid #7fd8b4;
 transform:rotate(-45deg)}
:root:not([data-welcome-night=true]) .ws-join-points li::before{border-color:#1d6b4c}
.ws-join-cards>li[data-tier=soon],.ws-join-cards>li[data-tier=vision]{--ring:#a8bcd8}
.ws-join-cards>li[data-tier=vision]{--ring:#c4b2ff}
:root:not([data-welcome-night=true]) .ws-join-cards>li[data-tier=soon]{--ring:#516781}
:root:not([data-welcome-night=true]) .ws-join-cards>li[data-tier=vision]{--ring:#54399e}
.ws-join-cards>li[data-tier=soon] .ws-join-points li::before,
.ws-join-cards>li[data-tier=vision] .ws-join-points li::before{
 width:9px;height:9px;left:2px;top:6px;border-radius:50%;transform:none;
 border:1.6px solid var(--ring)}
.ws-join-note{margin:0!important;font-size:12.5px;line-height:1.55}
.ws-join-cards button{justify-self:start;min-height:44px;padding:11px 18px;border-radius:14px;
 border:1px solid var(--control-line,var(--card-edge));background:var(--accent);
 color:var(--on-accent);font-size:14px;font-weight:650;cursor:pointer}
.ws-join-cards button:hover{transform:translateY(-2px)}
@media(prefers-reduced-motion:reduce){.ws-join-cards button:hover{transform:none}}
@media(max-width:900px){.ws-join-cards{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:620px){.ws-join-cards{grid-template-columns:1fr}}


/* ---- Arrival. The hidden state is gated on :root[data-ws-reveal=on], which
        only the script sets -- so if the script never runs, or the browser has
        no IntersectionObserver, every band is simply visible. Content is never
        hidden by CSS that JS might fail to undo. ---- */
:root[data-ws-reveal=on] [data-reveal]{
 opacity:0;transform:translate3d(0,22px,0);
 transition:opacity .72s cubic-bezier(.22,.61,.36,1),
            transform .72s cubic-bezier(.22,.61,.36,1);
 transition-delay:calc(var(--i,0) * 65ms);
 will-change:opacity,transform}
:root[data-ws-reveal=on] [data-reveal=in]{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){
 :root[data-ws-reveal=on] [data-reveal]{opacity:1!important;transform:none!important;transition:none}}
:root[data-motion=off] [data-reveal]{opacity:1!important;transform:none!important;transition:none}

/* The rail draws itself as the band arrives, then the nodes light in turn. */
.ws-rail::before{transform-origin:50% 0;transform:scaleY(0);
 transition:transform 1.05s cubic-bezier(.22,.61,.36,1) .12s}
:root[data-ws-reveal=on] .ws-learn[data-rail=in] .ws-rail::before,
:root:not([data-ws-reveal=on]) .ws-rail::before{transform:scaleY(1)}
.ws-rail-dot{transition:border-color .5s ease .35s,color .5s ease .35s,
                        box-shadow .5s ease .35s,transform .5s cubic-bezier(.3,1.5,.45,1) .35s}
.ws-learn[data-rail=in] .ws-rail li[data-state=now] .ws-rail-dot{
 box-shadow:0 0 0 5px #7fd8b41f,0 0 26px -6px #7fd8b4}
.ws-learn[data-rail=in] .ws-rail li[data-state=next] .ws-rail-dot{
 box-shadow:0 0 0 5px #adcaff1a}
@media(prefers-reduced-motion:reduce){
 .ws-rail::before{transform:scaleY(1)!important;transition:none}
 .ws-rail-dot{transition:none}}
:root[data-motion=off] .ws-rail::before{transform:scaleY(1)!important;transition:none}

/* ---- Depth. Cards were flat rectangles on a flat colour; they now sit on the
        band with an inner highlight and lift toward the pointer. ---- */
.ws-tiles li,.ws-origin-steps li,.ws-places-grid li,.ws-join-cards>li,.ws-compass{
 box-shadow:0 1px 0 #ffffff12 inset,0 24px 50px -38px #00000099;
 transition:transform .4s cubic-bezier(.22,.61,.36,1),
            border-color .4s ease,box-shadow .4s ease}
:root:not([data-welcome-night=true]) .ws-tiles li,
:root:not([data-welcome-night=true]) .ws-origin-steps li,
:root:not([data-welcome-night=true]) .ws-places-grid li,
:root:not([data-welcome-night=true]) .ws-join-cards>li,
:root:not([data-welcome-night=true]) .ws-compass{
 box-shadow:0 1px 0 #ffffffcc inset,0 24px 50px -40px #1d356433}
.ws-origin-steps li:hover,.ws-places-grid li:hover,.ws-join-cards>li:hover{
 transform:translateY(-4px);border-color:#ffd15c4d;
 box-shadow:0 1px 0 #ffffff1f inset,0 30px 60px -36px #000000b3}
@media(prefers-reduced-motion:reduce){
 .ws-origin-steps li:hover,.ws-places-grid li:hover,.ws-join-cards>li:hover{transform:none}}
:root[data-motion=off] .ws-origin-steps li:hover,
:root[data-motion=off] .ws-places-grid li:hover,
:root[data-motion=off] .ws-join-cards>li:hover{transform:none}

/* ---- Each content band carries its own sky, the way the hero and DISCOVER
        already do. Mounted as an <img>, not a CSS url(): a base64 payload in
        the stylesheet is first-paint weight and these are all below the fold. */
.ws-band-sky{position:absolute;top:0;bottom:0;left:50%;width:100vw;margin-left:-50vw;
 z-index:0;overflow:hidden;pointer-events:none;user-select:none;background:#0b1428}
.ws-band-sky img{position:absolute;inset:0;width:100%;height:100%;
 object-fit:cover;object-position:50% 50%;display:block}
/* Exactly one plate shows. The theme picks it; nothing else does. Scoped to
   the container because `.ws-band-sky img` above is 0,1,1 -- a bare class
   selector loses to it and both plates stack. */
.ws-band-sky .ws-sky-day{display:none}
:root:not([data-welcome-night=true]) .ws-band-sky .ws-sky-night{display:none}
:root:not([data-welcome-night=true]) .ws-band-sky .ws-sky-day{display:block}
.ws-band-veil{position:absolute;inset:0;display:block;
 background:radial-gradient(58% 86% at 16% 50%,#0b1428e0 0%,#0b1428a1 40%,#0b14283d 66%,#0b142800 86%),
            linear-gradient(#0b142899 0%,#0b142800 20%,#0b142800 80%,#0b142899 100%)}
.ws-learn>:not(.ws-band-sky),.ws-grow>:not(.ws-band-sky),
.ws-origin>:not(.ws-band-sky),.ws-world-band>:not(.ws-band-sky),
.ws-closing-world>:not(.ws-band-sky){position:relative;z-index:2}

/* ---- The ask and the sign-off are one moment, so they share one sky. It used
        to sit on .ws-join alone, which left a hard cut where the plate stopped
        and the closing section -- the last thing anyone sees, and the biggest
        type on the page -- became the only flat surface on a page that had
        just walked them through a world. The veil runs darker down the block
        and lands exactly on the page colour, so the footer wordmark still has
        clean ground under it. ---- */
.ws-closing-world{position:relative;isolation:isolate}
/* Two stacked gradients multiply, so the first pass buried the plate it was
   there to reveal. The radial only darkens behind the centred type; the linear
   does the landing. */
.ws-closing-world .ws-band-veil{
 background:radial-gradient(92% 62% at 50% 30%,#0b1428ad 0%,#0b142866 46%,#0b142824 72%,#0b142800 92%),
            linear-gradient(#0b142899 0%,#0b142800 16%,#0b14285c 60%,#0b1428 100%)}
:root:not([data-welcome-night=true]) .ws-closing-world .ws-band-veil{
 background:radial-gradient(92% 62% at 50% 30%,#f4f8ffc4 0%,#f4f8ff8c 46%,#f4f8ff3d 72%,#f4f8ff00 92%),
            linear-gradient(#f4f8ffb0 0%,#f4f8ff00 16%,#f4f8ff85 60%,#f4f8ff 100%)}
@media(max-width:900px){
 .ws-closing-world .ws-band-veil{
  background:linear-gradient(#0b1428d9 0%,#0b1428a6 22%,#0b1428cc 64%,#0b1428 100%)}
 :root:not([data-welcome-night=true]) .ws-closing-world .ws-band-veil{
  background:linear-gradient(#f4f8ffe6 0%,#f4f8ffc0 22%,#f4f8ffdd 64%,#f4f8ff 100%)}}
/* Day view has its own plates now, so the veil inverts rather than vanishing:
   the ink is dark, so it lifts the art instead of darkening it. */
:root:not([data-welcome-night=true]) .ws-band-sky{background:#eef4ff}
:root:not([data-welcome-night=true]) .ws-band-veil{
 background:radial-gradient(58% 86% at 16% 50%,#f4f8ffed 0%,#f4f8ffb8 40%,#f4f8ff54 66%,#f4f8ff00 86%),
            linear-gradient(#f4f8ffa8 0%,#f4f8ff00 20%,#f4f8ff00 80%,#f4f8ffa8 100%)}
@media(max-width:900px){
 :root:not([data-welcome-night=true]) .ws-band-veil{
  background:linear-gradient(#f4f8ffe6 0%,#f4f8ffb0 30%,#f4f8ffc7 70%,#f4f8ffed 100%)}}
@media(max-width:900px){
 .ws-band-veil{background:linear-gradient(#0b1428d9 0%,#0b14289e 30%,#0b1428b8 70%,#0b1428e6 100%)}}



/* ---- PLAY & EARN needs air. It is a card, and it was sitting flush against
        the band above and the band below, so the LEARN copy read as part of it.
        The band around it is the breathing room. ---- */
.ws-welcome .ws-discovery{margin:0 auto;max-width:1180px}
:root[data-space=welcome] .ws-welcome > .ws-discovery{
 margin-block:clamp(28px,5vw,64px)}
.ws-learn{padding-bottom:clamp(56px,7vw,96px)}
.ws-welcome .ws-discovery{
 box-shadow:0 1px 0 #ffffff14 inset,0 40px 80px -52px #000000b3}
:root:not([data-welcome-night=true]) .ws-welcome .ws-discovery{
 box-shadow:0 1px 0 #ffffffcc inset,0 40px 80px -56px #1d356433}
@media(max-width:760px){
 :root[data-space=welcome] .ws-welcome > .ws-discovery{margin-block:26px}}


/* ============================================================================
   A FEW THINGS TO KNOW. The one band with no treatment: an empty left column,
   the browser's default disclosure triangles, and a flat surface between two
   bands carrying art -- so it read as a hole rather than a pause. It is a pause
   now, deliberately: no plate, but a shaped surface, a left column that says
   something, and disclosures that behave.
   ========================================================================== */
.ws-faq{position:relative;isolation:isolate;display:grid;
 grid-template-columns:minmax(0,.78fr) minmax(0,1.22fr);gap:clamp(28px,4vw,64px);
 /* The copy is half the height of the question list, so `start` left 183px of
    void under it and put the two columns 91px out of line. The band is one
    screen tall -- there is nothing for a sticky column to follow -- so the
    copy centres on the list instead. */
 align-items:center;
 padding:clamp(56px,7vw,92px) 0;
 --paper:#192b45;--ink:#edf4ff;--muted:#b0c3dd;--line:#36506e;--card-edge:#2b4568;
 color:var(--ink)}
:root:not([data-welcome-night=true]) .ws-faq{
 --paper:#fff;--ink:#182b48;--muted:#566982;--line:#dbe4f0;--card-edge:#d9e4f5}
/* a shaped surface instead of a flat fill, full-bleed like its neighbours */
.ws-faq::before{content:'';position:absolute;top:0;bottom:0;left:50%;width:100vw;
 margin-left:-50vw;z-index:-1;pointer-events:none;
 background:radial-gradient(120% 90% at 50% 0%,#16294c 0%,#101d3a 46%,#0b1428 100%);
 box-shadow:0 1px 0 #ffffff0f inset,0 -1px 0 #ffffff0a inset}
:root:not([data-welcome-night=true]) .ws-faq::before{
 background:radial-gradient(120% 90% at 50% 0%,#ffffff 0%,#f3f7ff 48%,#eaf1ff 100%);
 box-shadow:0 1px 0 #ffffff inset,0 -1px 0 #1d35640d inset}

.ws-faq-copy{min-width:0;position:sticky;top:112px;align-self:start}
.ws-faq .ws-kicker{color:#ffd98a}
:root:not([data-welcome-night=true]) .ws-faq .ws-kicker{color:#95580a}
.ws-faq h2{font-size:clamp(28px,3.2vw,44px);line-height:1.08;letter-spacing:-.03em;
 margin:10px 0 16px;color:var(--ink)}
.ws-faq h2 em{font-style:normal;color:#ffd15c}
:root:not([data-welcome-night=true]) .ws-faq h2 em{color:#a8670a}
.ws-faq-copy p{color:var(--muted);max-width:36ch;font-size:15px;line-height:1.7}
.ws-faq-link{display:inline-flex;align-items:center;gap:8px;margin-top:6px;
 font-size:14px;font-weight:650;color:#ffd98a;text-decoration:none;
 border-bottom:1px solid currentColor;padding-bottom:2px}
:root:not([data-welcome-night=true]) .ws-faq-link{color:#95580a}
.ws-faq-link:hover{gap:12px}

.ws-faq-list{display:grid;gap:10px;min-width:0}
.ws-faq-group{margin:18px 0 2px;font-size:11px;font-weight:700;letter-spacing:.14em;
 text-transform:uppercase;color:var(--muted);display:flex;align-items:center;gap:14px}
.ws-faq-group:first-child{margin-top:0}
/* the rule runs to the edge of the column, not under the words */
.ws-faq-group::after{content:'';flex:1;height:1px;background:var(--card-edge)}

.ws-faq details{background:color-mix(in srgb,var(--paper) 70%,transparent);
 border:1px solid var(--card-edge);border-radius:16px;overflow:hidden;
 transition:border-color .3s ease,background .3s ease}
.ws-faq details[open]{border-color:#ffd15c47;
 background:color-mix(in srgb,var(--paper) 86%,transparent)}
.ws-faq summary{display:flex;align-items:center;justify-content:space-between;gap:16px;
 padding:17px 20px;cursor:pointer;list-style:none;
 font-size:16px;font-weight:650;color:var(--ink);min-height:44px}
/* the browser's own triangle is what made this look unstyled */
.ws-faq summary::-webkit-details-marker{display:none}
.ws-faq summary::marker{content:''}
.ws-faq summary:hover{color:#ffd15c}
:root:not([data-welcome-night=true]) .ws-faq summary:hover{color:#a8670a}
.ws-faq summary:focus-visible{outline:2px solid #ffd15c;outline-offset:-3px;border-radius:16px}
.ws-faq-chev{width:16px;height:16px;flex:none;opacity:.7;
 transition:transform .32s cubic-bezier(.22,.61,.36,1),opacity .3s ease}
.ws-faq details[open] .ws-faq-chev{transform:rotate(180deg);opacity:1;color:#ffd15c}
:root:not([data-welcome-night=true]) .ws-faq details[open] .ws-faq-chev{color:#a8670a}
.ws-faq details p{margin:0!important;padding:0 20px 19px;
 font-size:14.5px;line-height:1.7;color:var(--muted);max-width:66ch}
.ws-faq details a{color:#ffd98a;font-weight:600;text-underline-offset:3px;
 text-decoration-thickness:1px;text-decoration-color:#ffd98a70}
:root:not([data-welcome-night=true]) .ws-faq details a{color:#95580a;
 text-decoration-color:#95580a70}
.ws-faq details a:hover{text-decoration-color:currentColor}
@media(prefers-reduced-motion:reduce){.ws-faq-chev{transition:none}}
:root[data-motion=off] .ws-faq-chev{transition:none}
@media(max-width:900px){
 .ws-faq{grid-template-columns:1fr;gap:24px;align-items:start}
 .ws-faq-copy{position:static}
 .ws-faq-copy p{max-width:none}}


/* ============================================================================
   A PEEK INSIDE. Three things this band was missing.
   ========================================================================== */

/* 1. The next card was HARD CLIPPED at the card's edge -- a sliver of the one
      behind it, cut straight through. A carousel should say "there is more
      this way", not look broken. The rail fades into the edge instead. */
.ws-discovery{position:relative}
.ws-discovery .wd-rail{-webkit-mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 96px),transparent 100%);
 mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 96px),transparent 100%)}
@media(max-width:760px){
 .ws-discovery .wd-rail{-webkit-mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 40px),transparent 100%);
  mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 40px),transparent 100%)}}

/* 2. Six plain text labels with a faint number in front is a list, not a
      control. This is a segmented control: one track, a lit pill on the
      active one, and the index carried as a real numeral. */
.ws-discovery .wd-tabs{background:color-mix(in srgb,var(--paper) 58%,transparent);
 border:1px solid var(--line);border-radius:14px;padding:4px;gap:2px}
.ws-discovery .wd-tabs button{border-radius:10px;border-color:transparent;
 transition:background .28s ease,color .28s ease}
.ws-discovery .wd-tabs button[aria-pressed=true]{
 background:color-mix(in srgb,#ffd15c 15%,transparent);color:#ffd98a;
 border-color:#ffd15c3d;box-shadow:none}
:root:not([data-welcome-night=true]) .ws-discovery .wd-tabs button[aria-pressed=true]{
 background:color-mix(in srgb,#a8670a 12%,transparent);color:#8a5a06;border-color:#a8670a33}
.ws-discovery .wd-tabs button[aria-pressed=true]>span{opacity:1}
@media(prefers-reduced-motion:reduce){.ws-discovery .wd-tabs button{transition:none}}

/* 3. The card sits ON the band's art now, so it has to be glass like every
      other card on the page rather than a solid slab. */
.ws-discovery>*{position:relative;z-index:2}
.ws-discovery{background:color-mix(in srgb,var(--paper) 62%,transparent);
 backdrop-filter:blur(16px) saturate(1.15);-webkit-backdrop-filter:blur(16px) saturate(1.15);
 box-shadow:0 40px 90px -56px #000000b8}
:root:not([data-welcome-night=true]) .ws-discovery{
 box-shadow:0 40px 90px -60px #1d356433}
.ws-discovery .wd-card{background:color-mix(in srgb,var(--paper) 88%,transparent)}


/* ---- C: the progress rail. 01 / 06 stays as the announced position; this is
        the same thing you can see and drag. Its fill is --wd-p, which the
        carousel's own scroll handler writes, so it is true however you got
        there: tab, arrow key, trackpad or a drag on the track itself. ---- */
.ws-discovery .wd-progress{position:relative;display:block;flex:1 1 auto;
 max-width:340px;height:4px;margin:0 20px;border-radius:99px;
 background:color-mix(in srgb,var(--line) 70%,transparent);
 cursor:grab;touch-action:none}
.ws-discovery .wd-progress:active{cursor:grabbing}
/* a comfortable hit area without a fat bar */
.ws-discovery .wd-progress::after{content:'';position:absolute;inset:-14px 0}
.ws-discovery .wd-progress>i{position:absolute;inset:0 auto 0 0;display:block;
 width:calc(12% + var(--wd-p,0) * 88%);border-radius:99px;
 background:linear-gradient(90deg,#4fd0ff,#ffd15c);
 box-shadow:0 0 14px -2px #ffd15c;
 transition:width .28s cubic-bezier(.22,.61,.36,1)}
:root:not([data-welcome-night=true]) .ws-discovery .wd-progress>i{
 background:linear-gradient(90deg,#2f6fd0,#a8670a);box-shadow:0 0 12px -3px #a8670a}
@media(prefers-reduced-motion:reduce){.ws-discovery .wd-progress>i{transition:none}}
:root[data-motion=off] .ws-discovery .wd-progress>i{transition:none}
@media(max-width:760px){.ws-discovery .wd-progress{margin:0 12px;max-width:none}}

/* ---- D: depth. The carousel already marks the centred card with
        data-active, so this is only CSS: the others sit back, dim and lose a
        little colour, then lift as they arrive. ---- */
.ws-discovery .wd-card{transform-origin:50% 50%;
 transition:transform .55s cubic-bezier(.22,.61,.36,1),
            opacity .55s ease,filter .55s ease,border-color .55s ease}
.ws-discovery .wd-card[data-active="false"]{
 transform:scale(.93);opacity:.5;filter:saturate(.62)}
.ws-discovery .wd-card[data-active="true"]{
 transform:none;opacity:1;filter:none;
 border-color:color-mix(in srgb,#ffd15c 26%,var(--card-edge))}
@media(prefers-reduced-motion:reduce){
 .ws-discovery .wd-card{transition:none}
 .ws-discovery .wd-card[data-active="false"]{transform:none;opacity:.78;filter:none}}
:root[data-motion=off] .ws-discovery .wd-card{transition:none}
:root[data-motion=off] .ws-discovery .wd-card[data-active="false"]{transform:none;opacity:.78;filter:none}

/* ---- B: the spotlight. A warm light where the pointer is, on a card big
        enough that its far corners were going dead. Fades out rather than
        snapping when the pointer leaves, and never runs on touch or when
        motion is off. ---- */
.ws-discovery::after{content:'';position:absolute;inset:0;z-index:1;
 pointer-events:none;border-radius:inherit;opacity:0;
 background:radial-gradient(420px circle at var(--wd-mx,50%) var(--wd-my,40%),
            #ffd15c26 0%,#ffd15c0f 38%,transparent 68%);
 transition:opacity .45s ease}
.ws-discovery[data-glow=on]::after{opacity:1}
:root:not([data-welcome-night=true]) .ws-discovery::after{
 background:radial-gradient(420px circle at var(--wd-mx,50%) var(--wd-my,40%),
            #a8670a1a 0%,#a8670a0a 38%,transparent 68%)}
@media(hover:none){.ws-discovery::after{display:none}}
@media(prefers-reduced-motion:reduce){.ws-discovery::after{transition:none}}
:root[data-motion=off] .ws-discovery::after{display:none}


/* ---- The handwritten asides. A second voice, in a second hand: the comp's
        script annotations, drawn as outlines rather than set in a webfont,
        because this page ships none and its CSP has no font-src. One <defs>
        sheet of letters lives at the end of <body>; each aside is <use>
        references into it, so a repeated letter costs a tag, not a shape. ---- */
.ws-letter-sheet{position:absolute;width:0;height:0;overflow:hidden}
.ws-aside{position:absolute;z-index:3;pointer-events:none;user-select:none;
 width:clamp(180px,22vw,320px);
 transform:rotate(var(--tilt,-4deg));transform-origin:50% 50%;
 filter:drop-shadow(0 0 16px #ffd98a3d) drop-shadow(0 3px 6px #0b142899)}
.ws-aside svg{display:block;width:100%;height:auto;fill:#ffd98a}
.ws-hero>.ws-aside,.ws-discover>.ws-aside,
.ws-play>.ws-aside,.ws-origin>.ws-aside{position:absolute;z-index:3}
/* Day is a light page, so the ink darkens and the glow becomes a shadow. */
:root:not([data-welcome-night=true]) .ws-aside svg{fill:#a8670a}
:root:not([data-welcome-night=true]) .ws-aside{
 filter:drop-shadow(0 2px 5px #ffffffcc) drop-shadow(0 1px 2px #1d356433)}

.ws-hero .ws-aside{right:3.5%;top:auto;bottom:9%;--tilt:-5deg}
.ws-play .ws-aside{right:2.5%;top:14%;--tilt:-4deg}
/* The steps grew when they became a cycle, so this one sits under them in the
   clear strip rather than across them -- and smaller, because it is a closing
   note rather than a second headline. */
.ws-origin .ws-aside{right:3%;bottom:22px;--tilt:-3deg;width:clamp(160px,18vw,246px)}

/* "Great! You found it!" is a REACTION, not a caption. It is a sibling of the
   demo so the demo's own data-result drives it, and it says nothing until the
   visitor has actually found it. */
.ws-discover .ws-aside[data-aside=spark]{right:4%;top:8%;--tilt:-6deg;
 width:clamp(150px,17vw,235px);
 opacity:0;transform:rotate(-6deg) scale(.82);
 transition:opacity .42s ease,transform .52s cubic-bezier(.3,1.5,.45,1)}
[data-spark-demo][data-result=correct] ~ .ws-aside[data-aside=spark]{
 opacity:1;transform:rotate(-6deg) scale(1)}
@media(prefers-reduced-motion:reduce){
 .ws-discover .ws-aside[data-aside=spark]{transition:none;transform:rotate(-6deg)}
 [data-spark-demo][data-result=correct] ~ .ws-aside[data-aside=spark]{transform:rotate(-6deg)}}
:root[data-motion=off] .ws-discover .ws-aside[data-aside=spark]{transition:none}
/* Wide screens: Sparki now stands at the top of the panel this note used to sit
   over, so it lifts just above him and reads as his exclamation. */
@media(min-width:1181px){.ws-discover .ws-aside[data-aside=spark]{top:-6%}}

/* Below the wide breakpoints the bands stack and the art is a backdrop behind
   copy -- there is no clear space left for an aside, and one laid over the
   words is worse than none. */
@media(max-width:900px){.ws-aside{display:none}}
@media(forced-colors:active){.ws-aside{display:none}}


/* ==== PHONE ================================================================
   Measured on a 390px viewport against the same faults a real iPhone showed.
   Three of them, all structural rather than cosmetic. ==================== */
@media(max-width:560px){

 /* 2. Sparki. I hid him here once and it was the wrong call twice over: the
       page lost its companion on the one screen size a child is most likely
       to hold, and his speech bubble is a SEPARATE element that I left behind
       -- .ws-orbit-label, absolutely positioned inside an illustration I had
       just collapsed, so "Try a spark with me." landed squeezed to 52px wide
       on top of the Sign in button.

       The band was always built to hold him: .ws-hero carries a bottom strip
       and .ws-hero-play sits in it. I had taken the strip away too. It is
       back, sized so he clears the closing line rather than standing on it,
       and the bubble is anchored to HIS left instead of floating up into the
       buttons -- which is also the way its tail already points. */
 .ws-hero-foot{position:relative;z-index:3}
 /* The band fills the first screen. At 375x812 it stopped at 720px and let
    92px of the section below show under the art, which reads as the hero
    being cut off rather than ending. svh, not vh: vh is the height with the
    browser chrome retracted, so on a phone it overflows by the address bar.
    The padding stays as the floor -- the larger of the two wins, so a short
    screen still gets Sparki his strip. The plate is inset:0 on the band, so
    it grows with it.

    Both declarations are !important because the band sets padding:0 and
    min-height:0 that way itself -- on a wide screen it is sized by
    height:min(100vh,78vw) instead, which on a 375px phone would come to
    292px. There is no quieter way to say this here. */
 :root[data-space=welcome] .ws-hero{padding-bottom:196px!important;
  min-height:100vh!important;min-height:100svh!important}
 :root[data-space=welcome] .ws-hero .ws-hero-play{right:5%;bottom:14px}
 :root[data-space=welcome] .ws-hero .ws-living-art{width:104px}
 :root[data-space=welcome] .ws-hero .ws-illustration{min-height:0}
 /* an explicit width, because the bubble's containing block is the 104px
    illustration: anchored by `right` alone it shrink-to-fits into what little
    is left of that box and breaks one short sentence over four lines */
 :root[data-space=welcome] .ws-hero .ws-orbit-label{
  top:auto;bottom:78px;left:auto;right:92px;width:116px;max-width:none;
  transform:translate(0,7px) scale(.94);transform-origin:100% 100%}
 :root[data-space=welcome] .ws-hero .ws-orbit-label[data-said="true"]{
  transform:translate(0,0) scale(1)}
}

/* ---- Which button is the button.

        The hero runs on dark-mode tokens even by day, so over a bright sky the
        primary was the pale accent #ADCAFF and the secondary the dark paper
        #192B45: the heavier of the two was the one that mattered less. The
        closing section uses the same markup under day tokens and always had
        it right, which is why this is scoped to the hero and no further.

        Primary is solid and saturated in both modes, blue by day and the
        brand gold at night. Secondary is glass: present, legible, and plainly
        the second choice. ---- */
:root:not([data-welcome-night=true]) .ws-hero .ws-entry-actions .primary{
 background:#254CCB;color:#fff;border-color:#254CCB;
 box-shadow:0 14px 28px -14px rgb(37 76 203 / .75)}
:root:not([data-welcome-night=true]) .ws-hero .ws-entry-actions .primary:hover{background:#1d3fb0}
:root:not([data-welcome-night=true]) .ws-hero .ws-entry-actions a:not(.primary){
 background:rgb(255 255 255 / .72);color:#182b48;border:1px solid rgb(37 76 203 / .22);
 box-shadow:none;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
:root:not([data-welcome-night=true]) .ws-hero .ws-entry-actions a:not(.primary):hover{
 background:rgb(255 255 255 / .9);border-color:rgb(37 76 203 / .45)}
:root[data-welcome-night=true] .ws-hero .ws-entry-actions .primary{
 background:#ffd15c;color:#1b1633;border-color:#ffd15c;
 box-shadow:0 14px 30px -14px rgb(255 209 92 / .6)}
:root[data-welcome-night=true] .ws-hero .ws-entry-actions .primary:hover{background:#ffdb7d}
:root[data-welcome-night=true] .ws-hero .ws-entry-actions a:not(.primary){
 background:rgb(11 20 40 / .42);color:#edf4ff;border:1px solid rgb(255 255 255 / .22);
 box-shadow:none;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
:root[data-welcome-night=true] .ws-hero .ws-entry-actions a:not(.primary):hover{
 background:rgb(11 20 40 / .6);border-color:rgb(255 255 255 / .4)}
/* the sign-in path for families already in the pilot, inside the note */
.ws-hero .intro-account-note a{color:inherit;font-weight:650;text-underline-offset:3px}


.ws-canopy-on .ws-sparki[data-nod="true"] > img,
.ws-canopy-on .ws-sparki[data-nod="true"] > .sparki-face{animation:ws-sparki-nod .9s ease-in-out}
@keyframes ws-sparki-nod{0%,100%{translate:0 0}24%{translate:0 5px}50%{translate:0 0}72%{translate:0 3px}}
.sparki-sparki[data-held="true"] .sparki-spark{scale:1.12}

/* ---- One Sparki, flying. He lives in a layer above the page, under the header,
        and flies between his spots. The layer is the camera: its perspective is
        what makes coming toward the screen make him bigger. His own turn and
        tilt use a closer perspective of their own, so he looks the same in a
        corner as in the middle. ---- */
.ws-sparki-flight{position:fixed;inset:0;z-index:4;pointer-events:none;overflow:hidden;
 perspective:1000px;perspective-origin:50% 50%}
.ws-sparki-actor{position:absolute;left:0;top:0;width:150px;height:218px;
 transform-origin:0 0;will-change:transform;perspective:900px;perspective-origin:50% 45%}
.ws-sparki-flight .ws-sparki{pointer-events:none}
/* he can be picked up only at home, and never mid-knock */
.ws-sparki-flight[data-at="hero"]:not([data-knock]) .ws-sparki{pointer-events:auto}
/* his spot by the question: sized for him, and empty, because he flies in */
.ws-reward-star[data-perch="on"]{display:block;width:112px;height:163px;
 border-color:transparent;border-radius:0;box-shadow:none}
.ws-discover:has(.ws-demo[data-result=correct]) .ws-reward-star[data-perch="on"]{
 border-color:transparent;box-shadow:none}
.ws-reward-star[data-perch="on"] .ws-reward-burst{inset:8% -30% -4%}
/* the hero's speech bubble talks only while he is home */
.ws-hero .ws-orbit-label{transition:opacity .35s ease}
:root[data-sparki-at]:not([data-sparki-at="hero"]) .ws-hero .ws-orbit-label{opacity:0}
/* the light he leaves behind when he flies fast */
.ws-sparki-trail{position:absolute;width:12px;height:12px;margin:-6px 0 0 -6px;border-radius:50%;
 background:radial-gradient(circle,#fffbe8 0%,#ffd98acc 35%,#ffd15c00 70%);
 animation:ws-sparki-trail .75s ease-out forwards}
@keyframes ws-sparki-trail{from{opacity:.95;scale:1}to{opacity:0;scale:.2}}
/* a knock on the glass: a ring where his finger meets the screen */
.ws-knock{position:absolute;width:26px;height:26px;margin:-13px 0 0 -13px;border-radius:50%;
 border:2px solid #fff6d8;box-shadow:0 0 18px #ffd98a99,inset 0 0 12px #ffd98a66;
 animation:ws-knock .7s cubic-bezier(.2,.7,.3,1) forwards}
@keyframes ws-knock{from{opacity:1;scale:.4}to{opacity:0;scale:4.2}}
@media(prefers-reduced-motion:reduce){.ws-sparki-trail,.ws-knock{display:none}}
:root[data-motion=off] .ws-sparki-trail,:root[data-motion=off] .ws-knock{display:none}

/* his words: the quiz's own lines, until he has somewhere to point */
.ws-discover-reward .ws-reward-say span[data-say="next"]{display:none}
.ws-discover-reward[data-guide] .ws-reward-say span{display:none!important}
.ws-discover-reward[data-guide] .ws-reward-say span[data-say="next"]{display:inline!important}

/* guide: the subject he suggests glows until it is chosen */
.ws-demo [data-sparki-next="true"]{position:relative;z-index:1;
 box-shadow:0 0 0 2px #ffd15c,0 0 22px 3px #ffd15c8c}
.ws-canopy-on .ws-demo [data-sparki-next="true"]{animation:ws-sparki-next 1.5s ease-in-out infinite}
@keyframes ws-sparki-next{50%{box-shadow:0 0 0 3px #ffd15c,0 0 34px 8px #ffd15cb3}}
/* guide: the clue catches the light he is looking at */
.ws-answer-feedback{border-radius:10px}
.ws-canopy-on .ws-answer-feedback[data-sparki-look="true"]{animation:ws-sparki-look 1.9s ease-out}
@keyframes ws-sparki-look{
 0%{box-shadow:0 0 0 0 #ffd15c00;background-color:#ffd15c00}
 20%{box-shadow:0 0 0 6px #ffd15c40;background-color:#ffd15c26}
 100%{box-shadow:0 0 0 12px #ffd15c00;background-color:#ffd15c00}}

/* reveal: the way onward, once two subjects are lit */
.ws-reward-bridge{display:inline-flex;align-items:center;gap:8px;justify-self:center;
 padding:10px 18px;border-radius:999px;background:var(--accent);color:var(--on-accent);
 font-weight:700;font-size:14px;line-height:1.2;text-decoration:none;
 box-shadow:0 12px 26px -14px var(--accent)}
.ws-reward-bridge[hidden]{display:none}
.ws-reward-bridge:hover{filter:brightness(1.08)}
.ws-reward-bridge:focus-visible{outline:2px solid #ffd15c;outline-offset:3px}
.ws-canopy-on .ws-reward-bridge:not([hidden]){animation:ws-bridge-in .6s cubic-bezier(.3,1.4,.5,1)}
@keyframes ws-bridge-in{from{opacity:0;translate:0 8px;scale:.94}to{opacity:1;translate:0 0;scale:1}}
@media(max-width:1180px){
 .ws-discover>.ws-discover-reward .ws-reward-bridge{grid-column:2;justify-self:start}}
/* reveal, continued: arriving by his path, the tile that says what a right
   answer earns turns over by itself for a moment */
.ws-tiles li[data-sparki-reveal="true"] .ws-tile-flip{transform:rotateY(180deg)}
.ws-tiles li[data-sparki-reveal="true"]{filter:drop-shadow(0 0 18px #ffd15c73)}

@media(prefers-reduced-motion:reduce){
 .ws-tiles li[data-sparki-reveal="true"] .ws-tile-flip{transform:none}}
:root[data-motion=off] .ws-tiles li[data-sparki-reveal="true"] .ws-tile-flip{transform:none}
/* the closing constellation is where Sparki comes to rest, his spark its star */
:root[data-sparki-at] .ws-final .ws-footer-constellation{visibility:hidden}

/* The last spot is the centre of the page's ending, and his spark is its north
   star: bigger, brighter, and breathing slowly while he rests there. */
.ws-sparki-flight[data-at="star"] .sparki-spark{scale:1.6;
 filter:drop-shadow(0 0 16px #ffe7a0) drop-shadow(0 0 40px #ffd15ca6)}
.ws-sparki-flight.ws-canopy-on[data-at="star"] .sparki-spark .sk-bloom{
 animation:ws-north-star 3.4s ease-in-out infinite alternate}
@keyframes ws-north-star{from{opacity:.78;scale:1}to{opacity:1;scale:1.4}}

