/* bl-home.css - the redesigned homepage (includes/home/v2.php; plan docs/plans/HOMEPAGE_REDESIGN.md).
   Brand tokens only (brainlag.css :root and its dark block). Full-bleed bands alternate so no two neighbours share a
   background or a layout. Keycap buttons with square-ish corners (no pills), no card in card, no hairlines.
   Motion: transform and opacity only; nothing moves under prefers-reduced-motion or html[data-motion="off"]. */
.hm main{display:block}
.hm-band{padding:clamp(56px,8vw,104px) 0}
.hm-canvas{background:var(--surface)}
.hm-paper{background:var(--paper)}
.hm-blue{background:var(--blue-tint)}
.hm-gold{background:var(--gold-tint)}
.hm-navy{background:var(--navy);color:#fff;position:relative;overflow:hidden}
.hm-teal{background:var(--study);color:#04161c}
.hm-h2{font-size:clamp(30px,4vw,48px);line-height:1.08;letter-spacing:-.02em;margin:0 0 20px}
.hm-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px 24px;flex-wrap:wrap;margin:0 0 24px}
.hm-head .hm-h2{margin:0}
.hm-link{font-weight:700;color:var(--study-ink);text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:5px}
/* a 44 px tap height without moving anything: the padding grows the hit area, the negative margin gives the space back */
.hm-link{display:inline-block;padding-block:12px;margin-block:-12px}
.hm-link:hover{text-decoration-thickness:3px}
.hm a:focus-visible,.hm button:focus-visible,.hm summary:focus-visible{outline:3px solid var(--gold);outline-offset:3px;border-radius:6px}
.hm-teal a:focus-visible{outline-color:#04161c}
/* the focus ring on a lipped button wraps the lip too (owner, 9 Oct: "the shadow is part of the button too"; the shared
   pattern is brainlag.css, f09a8c72): --lip the lip's height (1 px while pressed), --ring-r the face radius plus 5 px */
.hm :where(.hm-b-go,.hm-b-alt,.hm-b-light,.hm-key):focus-visible{position:relative}
.hm :is(.hm-b-go,.hm-b-alt,.hm-b-light,.hm-key,.hm-up):focus-visible{outline:none}
.hm :is(.hm-b-go,.hm-b-alt,.hm-b-light,.hm-key,.hm-up):focus-visible::after{content:"";position:absolute;inset:-5px -5px calc(-5px - var(--lip,4px)) -5px;
  border:3px solid var(--ring,var(--study-ink));border-radius:var(--ring-r,19px);pointer-events:none;z-index:1}
.hm-b,.hm-key,.hm-up{--lip:4px;--ring-r:19px}
.hm-up{position:relative;--ring-r:21px}
.hm-b:active,.hm-key:active,.hm-up:active{--lip:1px}
.hm-teal{--ring:#04161c}
@media (forced-colors:active){.hm :is(.hm-b-go,.hm-b-alt,.hm-b-light,.hm-key,.hm-up):focus-visible::after{border-color:Highlight}}

/* keycaps: a face on a darker lip that drops when pressed */
.hm-b{display:inline-flex;align-items:center;justify-content:center;min-height:54px;padding:0 26px;border-radius:10px;font:700 17px/1.2 var(--f-body);
  text-decoration:none;text-align:center;transition:transform .09s cubic-bezier(.34,1.56,.64,1),box-shadow .09s cubic-bezier(.22,1,.36,1)}
.hm-b:active{transform:scale(.98)}
.hm-b-go{background:var(--study-btn);color:var(--on-study-btn);box-shadow:none}
.hm-b-go:hover{background:var(--study-btn-hover)}
.hm-b-go:active{box-shadow:none}
/* the secondary button (owner, 10 Oct: "Find my level button not visible enough"): a 2 px teal outline on the page,
   teal text, a teal tint on hover and focus; the same height and radius as the primary. Outline 3:1 or more against
   the page, text 4.5:1 or more, in both themes. */
.hm-b-alt{--alt-edge:#0b8792;--alt-ink:#06606a;--alt-tint:#dcf3f2;background:transparent;color:var(--alt-ink);border:2px solid var(--alt-edge)}
:root[data-theme="dark"] .hm-b-alt{--alt-edge:#3fbfc8;--alt-ink:#7ad7de;--alt-tint:#0f3438}
.hm-b-alt:hover,.hm-b-alt:focus-visible{background:var(--alt-tint)}
.hm-b-alt:active{background:var(--alt-tint);transform:scale(.98)}
.hm-b-light{background:#fff;color:#15365a;box-shadow:none}
.hm-b-light:hover{background:#eff8ff}
.hm-b-light:active{box-shadow:none}

/* ---- hero */
.hm-hero{padding:clamp(32px,6vw,80px) 0 clamp(48px,7vw,96px)}
.hm-hero-in{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);gap:40px;align-items:center}
.hm-hero h1{font-size:clamp(40px,6vw,76px);line-height:1.02;letter-spacing:-.03em;margin:0;text-wrap:balance}
.hm-lede{font-size:clamp(17px,1.6vw,20px);line-height:1.5;color:var(--ink-2);margin:24px 0 0;max-width:36ch}
.hm-ctas{display:flex;flex-wrap:wrap;gap:14px;margin:32px 0 0}
/* Up next (signed in, after a lesson): a card in the keycap family, held invisible from the first paint so filling it
   never moves the page; bl-home.js shows it (.is-on) with the next lesson, its course and unit, and the unit's progress */
.hm-up{--c:var(--blue);--ci:var(--blue-ink);--ct:var(--blue-tint);display:flex;align-items:center;gap:14px;max-width:440px;min-height:78px;margin:22px 0 0;
  padding:12px 20px 12px 12px;border-radius:16px;background:var(--surface);color:var(--ink);text-decoration:none;box-shadow:none;
  visibility:hidden;opacity:0;transition:opacity .24s cubic-bezier(.22,1,.36,1),transform .09s cubic-bezier(.34,1.56,.64,1),box-shadow .09s cubic-bezier(.22,1,.36,1)}
.hm-up.is-on{visibility:visible;opacity:1}
/* a lesson left part way through takes the Up next card's place (components/resume-card.php) */
.bl-resuming #hmNext{display:none}
.hm-resume{margin:28px 0 0}.bl-resuming .hm-ctas{margin-top:18px}
.hm-resume .hm-up-ic svg{display:block}
.hm-up:hover{transform:translateY(-2px);box-shadow:none}
.hm-up:active{transform:scale(.98);box-shadow:none}
.hm-up[data-s="science"]{--c:var(--study);--ci:var(--study-ink);--ct:var(--study-tint)}
.hm-up[data-s="cs"]{--c:var(--play);--ci:var(--play-ink);--ct:var(--play-tint)}
.hm-up[data-s="music"]{--c:var(--music);--ci:var(--music-ink);--ct:var(--music-tint)}
.hm-up-ic{flex:none;display:flex;align-items:center;justify-content:center;width:52px;height:52px;border-radius:12px;background:var(--ct);color:var(--ci)}
.hm-up-tx{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1 1 auto}
.hm-up-tx b{display:block;min-height:21px;font:600 17px/1.25 var(--f-display);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hm-up-tx small{display:block;min-height:19px;font-size:14px;line-height:1.35;color:var(--ink-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hm-up-pg{display:flex;align-items:center;gap:10px;min-height:18px;margin-top:2px}
.hm-up-pg em{flex:none;font:600 13px/1.3 var(--f-body);font-style:normal;color:var(--ink-2)}
.hm-up-bar{display:block;flex:1 1 auto;height:6px;border-radius:3px;background:var(--sunk);overflow:hidden}
.hm-up-bar i{display:block;height:100%;border-radius:3px;background:var(--c);transform-origin:0 50%;transform:scaleX(var(--p,0));transition:transform .48s cubic-bezier(.22,1,.36,1) .12s}
:root[data-theme="dark"] .hm-up{background:#1b2f4b;box-shadow:none}
:root[data-theme="dark"] .hm-up-bar{background:var(--sunk)}
.hm-art{position:relative;aspect-ratio:560/500;width:100%}
.hm-noodle{position:absolute;inset-inline-start:21%;width:58%;height:auto;bottom:4%}
.hm-ft{position:absolute;width:19%;will-change:transform;z-index:1}
.hm-ft1{inset-inline-start:0;top:8%;width:16%}
.hm-ft2{inset-inline-start:2%;top:60%;width:16%}
.hm-ft3{inset-inline-end:0;top:6%;width:16%}
.hm-ft4{inset-inline-end:1%;top:58%;width:16%}
.hm-ft-face{display:flex;align-items:center;justify-content:center;text-align:center;border-radius:18px;padding:8px;color:var(--ink);transform-origin:50% 100%;
  box-shadow:0 14px 28px rgba(21,54,90,.12)}
.hm-ft-formula{aspect-ratio:1;background:var(--surface);color:var(--blue-ink);transform:rotate(-6deg)}
:root[data-theme="dark"] .hm-ft-formula{background:var(--sunk)}
.hm-ft-card{aspect-ratio:1;background:var(--gold-tint);color:var(--gold-ink);transform:rotate(5deg)}
.hm-ft-code{aspect-ratio:1;background:#15365a;color:#7ad7de;font:700 clamp(16px,2.4vw,30px)/1 var(--f-mono);transform:rotate(5deg)}
.hm-ft-note{aspect-ratio:1;background:var(--pink-tint);color:var(--pink-ink);transform:rotate(-5deg)}
.hm-ft-face svg{width:72%;height:auto;overflow:visible}
:root[data-theme="dark"] .hm-ft-face{box-shadow:0 14px 28px rgba(0,0,0,.3)}
.hm-ft-code span{display:inline-block}
.hm-ft-pen{opacity:0}

/* ---- the hero's life (owner, 8 Oct: "more dynamic"; Kurzgesagt and Devon House rules: purposeful, small, never
   frantic). Each tile floats on its own uneven loop (translate), and each has one beat of its own subject on a shared
   12 s cycle, a quarter apart, so only one thing moves at a time (played once since 10 Oct: "nothing looping except the
   phone demo", then still): the triangle's hypotenuse plots itself across its
   axes, the flask swirls, the brackets snap round the slash, the note hops and lands with a squash (a thing, so it
   may squash). Noodle breathes 1.5 px (he never scales) and blinks (bl-home.js). Paused while the hero is off screen.
   Transform and opacity only; nothing under reduced motion (the rules at the end). */
.hm-ft1{--fp:3.3s;--fd:-1.1s}.hm-ft2{--fp:2.9s;--fd:-2.3s}.hm-ft3{--fp:3.7s;--fd:-.4s}.hm-ft4{--fp:3.1s;--fd:-1.7s}
.hm-js .hm-ft-face{animation:none}   /* the float loop is gone (10 Oct: nothing loops but the phone demo); the scroll parallax moves them */
@keyframes hm-fl{from{translate:0 0}to{translate:0 -5px}}
.hm-js .hm-ft-hyp{transform-box:fill-box;transform-origin:0 50%;animation:hm-plot 12s 1.4s 1 both}
.hm-js .hm-ft-pen{animation:hm-pen 12s 1.4s 1 both}
@keyframes hm-plot{0%{opacity:1;scale:1 1;animation-timing-function:cubic-bezier(.55,0,1,.45)}2%{opacity:0;scale:1 1}2.1%{opacity:1;scale:0 1;animation-timing-function:cubic-bezier(.45,0,.55,1)}10%,100%{opacity:1;scale:1 1}}
@keyframes hm-pen{0%,2%{opacity:0;translate:-41.04px 0}2.1%{opacity:1;translate:-41.04px 0;animation-timing-function:cubic-bezier(.45,0,.55,1)}10%{opacity:1;translate:0 0;animation-timing-function:cubic-bezier(.55,0,1,.45)}12.5%,100%{opacity:0;translate:0 0}}
.hm-js .hm-ft-card svg{transform-origin:50% 88%;animation:hm-swirl 12s 1.4s 1 both}
@keyframes hm-swirl{0%,25%{rotate:0deg;animation-timing-function:cubic-bezier(.45,0,.55,1)}27%{rotate:-9deg;animation-timing-function:cubic-bezier(.45,0,.55,1)}29.5%{rotate:7deg;animation-timing-function:cubic-bezier(.45,0,.55,1)}31.5%{rotate:-3deg;animation-timing-function:cubic-bezier(.45,0,.55,1)}33%{rotate:1deg;animation-timing-function:cubic-bezier(.22,1,.36,1)}34.5%,100%{rotate:0deg}}
.hm-js .hm-c1{animation:hm-cl 12s 1.4s 1 both}.hm-js .hm-c3{animation:hm-cr 12s 1.4s 1 both}.hm-js .hm-c2{animation:hm-cs 12s 1.4s 1 both}
@keyframes hm-cl{0%,50%{translate:0 0;animation-timing-function:cubic-bezier(.22,1,.36,1)}52%{translate:4px 0;animation-timing-function:cubic-bezier(.34,1.56,.64,1)}56%,100%{translate:0 0}}
@keyframes hm-cr{0%,50%{translate:0 0;animation-timing-function:cubic-bezier(.22,1,.36,1)}52%{translate:-4px 0;animation-timing-function:cubic-bezier(.34,1.56,.64,1)}56%,100%{translate:0 0}}
@keyframes hm-cs{0%,50.5%{rotate:0deg;animation-timing-function:cubic-bezier(.22,1,.36,1)}52.5%{rotate:14deg;animation-timing-function:cubic-bezier(.34,1.56,.64,1)}56.5%,100%{rotate:0deg}}
.hm-js .hm-ft-note svg{transform-origin:50% 100%;animation:hm-hop 12s 1.4s 1 both}
@keyframes hm-hop{0%,75%{translate:0 0;scale:1 1;animation-timing-function:cubic-bezier(.22,1,.36,1)}77.5%{translate:0 -8px;scale:.95 1.06;animation-timing-function:cubic-bezier(.55,0,1,.45)}79.5%{translate:0 0;scale:1.1 .88;animation-timing-function:cubic-bezier(.34,1.56,.64,1)}82%{scale:.98 1.02;translate:0 0}84%,100%{translate:0 0;scale:1 1}}
.hm-js .hm-noodle{animation:none}   /* no breathing loop (10 Oct); he blinks in the phone demo */
@keyframes hm-breath{from{translate:0 0}to{translate:0 -1.5px}}
.hm-art.is-off *{animation-play-state:paused!important}

/* ---- the hero's world (hero_look 'world'; owner, 8 Oct): a day sky in light mode, dusk in dark; far hills whose ridge
   carries a stave (the video world's stave hills; no sun: wherever it sat it crowded a tile), a nearer hill of graph paper, and the near hill in the page paper,
   which runs on into the next band. Low contrast and low on the text side, so nothing sits behind the headline or the
   buttons; flat fills (no glow, no gradient), lines 3 px at every size. Tokens only. */
.hm[data-hero="world"] .hm-hero{--w-sky:var(--blue-tint);--w-far:#ccdef5;--w-st:#e4eefa;--w-mid:#d5f4f5;--w-gr:#ebfafb;--w-sh:#e4eefa;
  position:relative;isolation:isolate;overflow:hidden;background:var(--w-sky)}
:root[data-theme="dark"] .hm[data-hero="world"] .hm-hero{--w-sky:#103457;--w-far:#33295a;--w-st:#4a3785;--w-mid:#0e2137;--w-gr:#13304f;--w-sh:#081120}
.hm-bg{position:absolute;inset-inline-start:0;bottom:0;z-index:-1;display:block;width:100%;height:clamp(240px,28vw,420px);pointer-events:none}
.hm-bg .w-far{fill:var(--w-far)}
.hm-bg .w-st{fill:none;stroke:var(--w-st);stroke-width:3;stroke-linecap:round}
.hm-bg .w-mid{fill:var(--w-mid)}
.hm-bg .w-gr{fill:none;stroke:var(--w-gr);stroke-width:3}
.hm-bg .w-near{fill:var(--paper)}
.hm-ground{position:absolute;z-index:0;inset-inline-start:-150%;top:91.6%;width:400%;height:auto;overflow:visible;pointer-events:none}
.hm-ground path{fill:var(--paper)}
.hm-ground .hm-ground-sh{fill:var(--w-sh)}
.hm[data-hero="world"] .hm-hero-tx{position:relative;z-index:1}
.hm[data-hero="world"] .hm-hero{padding-bottom:clamp(40px,5vw,72px)}
.hm[data-hero="world"] .hm-hero + .hm-band{padding-top:clamp(28px,4vw,56px)}
.hm[data-hero="world"] .hm-noodle{z-index:1}
.hm[data-hero="world"] .hm-hero .hm-b-alt{background:var(--surface)}
.hm[data-hero="world"] .hm-hero .hm-b-alt:hover{background:var(--paper)}
:root[data-theme="dark"] .hm[data-hero="world"] .hm-hero .hm-b-alt{background:#1b2f4b}
:root[data-theme="dark"] .hm[data-hero="world"] .hm-hero .hm-b-alt:hover{background:var(--blue-tint)}

/* ---- ways in: the bento. Each tile: a soft light from the top left (one hue, lighter to a touch deeper), a quiet
   motif in its own ink on the calm side (the text side stays plain), and the character standing on a soft shadow. */
.hm-cu{margin:0 0 48px}
.hm-bento{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:20px;margin-top:32px}
.hm-tl{--tb:var(--blue-tint);--ci:var(--blue-ink);--hl:#fff;--hla:55%;position:relative;isolation:isolate;display:flex;flex-direction:column;gap:16px;border-radius:26px;padding:28px;color:var(--ink);text-decoration:none;min-height:220px;overflow:hidden;
  --lg:linear-gradient(135deg,color-mix(in srgb,var(--tb),var(--ci) 4%) 0%,color-mix(in srgb,var(--tb),var(--ci) 10%) 55%,color-mix(in srgb,var(--tb),var(--ci) 22%) 100%);background:var(--lg);
  box-shadow:0 1px 2px rgba(21,54,90,.05),0 4px 14px rgba(21,54,90,.05);
  transition:transform .2s cubic-bezier(.22,1,.36,1),box-shadow .2s cubic-bezier(.22,1,.36,1)}
/* owner, 9 Oct ("too light in the lighter corners, hard to see", then "I liked the gradient though"): the whole sweep
   shifts down instead of shrinking. The light end is a light tint (4% of the tile's ink), at least 0.044 OKLab L off
   the page, and the dark end goes deeper (22%), so the corner-to-corner sweep is at least the original's (0.057 to
   0.072; measured by handoff-2026-10-06/homepage/card-corners/edge.cjs). Same angle and direction; a very soft resting
   shadow, no border. Dark mode keeps its light-to-tint gradient: its corners
   already stand 0.075 or more off the page. */
:root[data-theme="dark"] .hm-tl{--hla:6%;background:linear-gradient(135deg,color-mix(in srgb,var(--tb),var(--hl) var(--hla)) 0%,var(--tb) 55%,color-mix(in srgb,var(--tb),var(--ci) 9%) 100%);box-shadow:none}
.hm-tl:hover{transform:translateY(-4px);box-shadow:var(--shadow)}
.hm-tl-tx{position:relative;z-index:1}
.hm-tl h3{font-size:clamp(24px,2.4vw,30px);margin:0 0 6px}
.hm-tl p{margin:0;color:var(--ink-2);font-size:16px;line-height:1.45;max-width:32ch}
/* one quiet motif, only on the large Courses tile: a patch of graph paper in the free corner under the list, fading out
   toward the bottom right, never behind the text or the character (contrast 4% or less) */
.hm-mo{position:absolute;z-index:0;inset-inline-start:0;bottom:0;width:36%;height:42%;background:var(--ci);opacity:.06;pointer-events:none;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 240' fill='none' stroke='%23000' stroke-width='3'%3E%3Cpath d='M0 40H240M0 80H240M0 120H240M0 160H240M0 200H240M40 0V240M80 0V240M120 0V240M160 0V240M200 0V240'/%3E%3C/svg%3E") left bottom/240px no-repeat,radial-gradient(farthest-corner at 0 100%,#000 20%,transparent 85%);-webkit-mask-composite:source-in;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 240' fill='none' stroke='%23000' stroke-width='3'%3E%3Cpath d='M0 40H240M0 80H240M0 120H240M0 160H240M0 200H240M40 0V240M80 0V240M120 0V240M160 0V240M200 0V240'/%3E%3C/svg%3E") left bottom/240px no-repeat,radial-gradient(farthest-corner at 0 100%,#000 20%,transparent 85%);mask-composite:intersect}
:root[data-theme="dark"] .hm-mo{opacity:.07}
/* the character on the ground: a soft, outline-free shadow in a darker tint of the tile */
.hm-gr{position:relative;z-index:1;display:block;align-self:flex-end;margin-top:auto;flex:none}
.hm-gr::before{content:"";position:absolute;inset-inline-start:20%;inset-inline-end:20%;bottom:-1%;height:8%;border-radius:50%;z-index:-1;
  background:radial-gradient(closest-side,color-mix(in srgb,var(--tb),#000 22%),transparent)}
:root[data-theme="dark"] .hm-gr::before{background:radial-gradient(closest-side,rgba(0,0,0,.45),transparent)}
.hm-gr .hm-char{display:block;width:100%;height:auto}
.hm-tl-learn{grid-column:span 2;grid-row:span 2;--tb:var(--study-tint);--ci:var(--study-ink)}
.hm-tl-learn .hm-gr{width:min(320px,62%);margin-top:-40px}
.hm-tl-list{display:flex;flex-direction:column;gap:10px;margin:22px 0 0}
.hm-tl-list > span{display:flex;align-items:center;gap:10px;font:600 17px/1.2 var(--f-display);color:var(--ink)}
.hm-tl-list svg{flex:none;color:var(--study-ink)}
.hm-tl-list [data-s="maths"] svg{color:var(--blue-ink)}
.hm-tl-list [data-s="cs"] svg{color:var(--play-ink)}
.hm-tl-code{grid-column:span 2;background:#15365a;color:#fff}
.hm-tl-code h3{color:#fff}
.hm-tl-code p{color:#c7d8ea}
.hm-tl-code pre{margin:auto 0 0;font:500 15px/1.6 var(--f-mono);color:#efece7;white-space:pre;overflow:hidden}
.hm-tl-code pre .k{color:#7ad7de}.hm-tl-code pre .s{color:#ffc23d}
/* Code (owner, 10 Oct: "needs a bit more to it"): text and the four tracks on the left, a small editor on the right.
   The title link covers the card; the track links sit above it. The editor is real text, decorative (aria-hidden). */
.hm-tl-code{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:22px;align-items:stretch}
.hm-tl-a{color:inherit;text-decoration:none}
.hm-tl-a::after{content:"";position:absolute;inset:0;z-index:1;border-radius:inherit}
.hm-tl-a:focus-visible{outline:none}
.hm-tl-code:has(.hm-tl-a:focus-visible){outline:3px solid var(--gold);outline-offset:3px}
.hm-code-list{position:relative;z-index:2;display:flex;flex-direction:column;gap:6px;margin:18px 0 0}
.hm-code-list a{display:inline-flex;align-items:center;gap:10px;min-height:32px;width:max-content;font:600 16.5px/1.2 var(--f-display);color:#fff;text-decoration:none}
.hm-code-list a:hover{text-decoration:underline;text-underline-offset:4px}
.hm-code-list a:focus-visible{outline:3px solid var(--gold);outline-offset:2px;border-radius:6px}
.hm-code-list svg{flex:none;color:#7ad7de}
.hm-ed{position:relative;z-index:0;display:flex;flex-direction:column;align-self:center;border-radius:14px;overflow:hidden;background:#0b1626;
  box-shadow:0 14px 30px rgba(0,0,0,.28);font:500 13px/1.55 var(--f-mono);color:#efece7}
:root[data-theme="dark"] .hm-ed{background:#12233a}
.hm-ed-tabs{display:flex;align-items:flex-end;gap:2px;padding:6px 6px 0;background:rgba(255,255,255,.06)}
.hm-ed-tabs i{font-style:normal;font-size:11px;padding:5px 7px 6px;min-width:0;overflow:hidden;text-overflow:ellipsis;border-radius:8px 8px 0 0;color:#8eaed4;white-space:nowrap}
.hm-ed-tabs i.on{background:#0b1626;color:#fff}
:root[data-theme="dark"] .hm-ed-tabs i.on{background:#12233a}
.hm-ed-code{display:grid;grid-template-columns:auto 1fr;gap:0 12px;padding:12px 14px 12px}
.hm-ed-code b{font-weight:500;color:#58779b;text-align:end}
.hm-ed-code span{white-space:pre}
.hm-ed-code em{font-style:normal}.hm-ed-code .k{color:#7ad7de}.hm-ed-code .s{color:#ffc23d}
.hm-ed-key{display:inline-flex;align-items:center;gap:5px;margin:0 2px 5px auto;padding:3px 9px;border-radius:7px;background:#0a7f8a;color:#fff;font:700 11.5px/1.4 var(--f-body);box-shadow:none;flex:none}
.hm-ed-out{display:flex;flex-direction:column;padding:9px 14px 10px;background:rgba(0,0,0,.22);color:#c7d8ea;font-size:12px;line-height:1.32}   /* one line per print, as Python writes it */
/* the output appears once, line by line, when the tile is first seen; still under reduced motion */
.hm-js .hm-tl-code.hm-rv .hm-ed-out span{opacity:0}
.hm-js .hm-tl-code.is-in .hm-ed-out span{opacity:1;transition:opacity .25s ease calc(.4s + var(--i) * .12s)}
.hm-js .hm-tl-code.is-in.is-now .hm-ed-out span{transition:none}   /* arrived in a fling: the output is simply there */
@media (prefers-reduced-motion:reduce){.hm-js .hm-tl-code .hm-ed-out span{opacity:1;transition:none}}
html[data-motion="off"] .hm-tl-code .hm-ed-out span{opacity:1!important;transition:none!important}
:root[data-theme="dark"] .hm-tl-code{background:var(--surface)}   /* code-bg sat 0.025 L off the dark page: the edge vanished */
.hm-tl-rev{--tb:var(--play-tint);--ci:var(--play-ink)}
.hm-tl-tools{--tb:var(--blue-tint);--ci:var(--blue-ink)}
.hm-tl-rev .hm-gr,.hm-tl-tools .hm-gr{width:150px}
.hm-tl-music,.hm-tl-shop{grid-column:span 2;flex-direction:row;align-items:flex-end}
.hm-tl-music{--tb:var(--music-tint);--ci:var(--music-ink)}
/* Music follows the --music tokens (owner, 10 Oct: pink, over the 9 Oct brass): light sweeps the tint toward ink and the rose partner
   (the house tile floor and sweep, edge.cjs); dark keeps the richer sweep, a lit rose behind the white title into the deep tint */
.hm-tl.hm-tl-music{--lg:linear-gradient(135deg,color-mix(in srgb,var(--music-tint),var(--music-ink) 6%) 0%,color-mix(in srgb,var(--music-tint),var(--music-ink) 12%) 55%,color-mix(in srgb,var(--music-tint),var(--music-2) 30%) 100%)}
:root[data-theme="dark"] .hm-tl.hm-tl-music{background:linear-gradient(135deg,color-mix(in srgb,var(--music-2-tint),var(--music-2) 24%) 0%,var(--music-2-tint) 50%,var(--music-tint) 100%)}
:root[data-theme="dark"] .hm-tl-music h3{color:#fff}
:root[data-theme="dark"] .hm-tl-music p{color:#f4f9ff}
:root[data-theme="dark"] .hm-tl-music .hm-stave{color:var(--music)}
.hm-tl-shop{--tb:var(--gold-tint);--ci:var(--gold-ink)}
.hm-tl-music .hm-tl-tx,.hm-tl-shop .hm-tl-tx{align-self:flex-start;flex:1 1 auto}
.hm-tl-shop .hm-gr{width:150px;margin:0}
.hm-stave{position:relative;z-index:1;flex:none;width:min(250px,50%);align-self:center;color:var(--music-ink)}
.hm-stave svg{display:block;width:100%;height:auto}

/* ---- the nav and the hero (owner, 8 Oct; options in handoff-2026-10-06/homepage/nav-hero/). Separated by tone,
   never a rule. glow: the hero on the page paper with one soft light behind the art. nav: a darker nav in dark mode
   (light keeps the white nav) and the hero on the paper in light mode. */
.hm[data-hero="glow"] .hm-hero,.hm[data-hero="nav"] .hm-hero{background:var(--paper)}
:root[data-theme="dark"] .hm[data-hero="nav"] .hm-hero{background:var(--surface)}
.hm[data-hero="glow"] .hm-hero{position:relative;overflow:hidden}
.hm[data-hero="glow"] .hm-art::before{content:"";position:absolute;inset:-12% -10% -6%;z-index:-1;border-radius:50%;
  background:radial-gradient(closest-side,rgba(13,154,167,.16),rgba(13,154,167,.06) 55%,transparent)}
:root[data-theme="dark"] .hm[data-hero="glow"] .hm-art::before{background:radial-gradient(closest-side,rgba(63,191,200,.16),rgba(63,191,200,.05) 55%,transparent)}
.hm[data-hero="glow"] .hm-art{isolation:isolate}
:root[data-theme="dark"] .hm[data-hero="nav"] header.blh{background:#081120;box-shadow:0 4px 18px rgba(0,0,0,.45)}

/* ---- the phone (hero_look 'phone'). Owner, 10 Oct: "this is the hero!", "like a cool Apple website", then "That's an
   incorrect vis though ... what if someone interacts with the phone?". A phone-proportioned card (9:19.5) with a navy
   device edge, no notch and no maker's look, whose screen is the real Learn player: its markup and its own rules
   (assets/css/bl-home-player.css, extracted from learn.css and scoped to .hm-ph-app) at the player's phone size,
   390 px wide, scaled to the screen (--k, set as the page is read and on resize). It is a working demo (bl-home.js).
   bl-home.js gives it the 3D tilt, eased level while the pointer is on it so taps land. */
.hm[data-hero="phone"] .hm-hero{background:var(--paper)}
.hm[data-hero="phone"] .hm-art{perspective:1500px;perspective-origin:50% 40%}
.hm-phone{will-change:transform;--edge:#15365a;
  position:absolute;z-index:1;top:0;bottom:0;left:50%;height:100%;aspect-ratio:9/19.5;translate:-50% 0;padding:7px;border-radius:44px;background:var(--edge);
  transform-origin:50% 55%;transform:rotateX(9deg) rotateY(-17deg) rotateZ(2.5deg);
  box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.08)}
:root[data-theme="dark"] .hm-phone{--edge:#1b2f4b}
.hm-ph-shd{position:absolute;z-index:0;left:50%;bottom:-11%;width:44%;height:9%;translate:-50% 0;border-radius:50%;pointer-events:none;
  background:radial-gradient(closest-side,rgba(21,54,90,.30),rgba(21,54,90,.10) 60%,transparent);transform:translateX(22px) scaleX(1.12);opacity:.9}
:root[data-theme="dark"] .hm-ph-shd{background:radial-gradient(closest-side,rgba(0,0,0,.62),rgba(0,0,0,.2) 60%,transparent)}
.hm-ph-scr{position:relative;height:100%;border-radius:37px;overflow:hidden;background:var(--paper);isolation:isolate;--k:.6}
/* (bl-home-player.css is inlined after this file, so an override here takes .hm-ph-app.ln-play to outrank it) */
/* the player's screen: 390 px wide, as tall as the screen at that width, scaled from its top left corner */
.hm-ph-app{position:absolute;inset-inline-start:0;top:0;width:390px;height:var(--ah,844px);transform-origin:0 0;transform:scale(var(--k));display:flex;flex-direction:column;
  background:var(--paper);color:var(--ink);font:400 17px/1.5 var(--f-body);text-align:start;overflow:hidden}
.hm-ph-app.ln-play .lp-top{position:relative}
.hm-ph-app.ln-play .lp-stage{flex:1 1 auto;padding:10px 16px 0;overflow:hidden}
.hm-ph-app.ln-play .lp-foot{position:absolute}
/* the phone's rounded screen (about 64 px of radius at the player's scale): the sheet and its buttons keep clear of the
   bezel and its curve (owner, 10 Oct: "a margin for the buttons at the bottom"), about 20 px from the bezel on screen */
.hm-ph-app.ln-play .lp-sheet{padding-inline-start:40px;padding-inline-end:40px}
.hm-ph-app.ln-play .lp-actions{padding:14px 40px 44px}
.hm-ph-app.ln-play .lp-coach .hm-noodle{position:static;display:block;width:100%;height:100%}   /* the coach is the page's rigged Noodle, in the player's coach box */
.hm-ph-app.ln-play .hm-ph-lf{font-weight:700;color:var(--study-ink)}
.hm-ph-app.ln-play .lq-title{font-family:var(--f-display);font-weight:600;letter-spacing:-.01em;line-height:1.15;color:var(--ink);text-wrap:balance}   /* the player's h1 (the page has one h1, so a p here) */
.hm-ph-app.ln-play .lq-tile:focus-visible,.hm-ph-app.ln-play .lp-btn:focus-visible{outline:3px solid var(--study);outline-offset:2px}
.hm-ph-app.ln-play .hm-ph-end{flex:1;display:flex;flex-direction:column;justify-content:center;padding:24px 8px 140px}
.hm-ph-app.ln-play .hm-ph-end .lp-h{font:600 30px/1.15 var(--f-display);margin:0 0 10px;color:var(--ink)}
.hm-ph-app.ln-play .hm-ph-end .lp-sub{margin:0;color:var(--ink-2)}
/* the end screen (owner, 12 Oct: "Improve this screen"; bl-home-phone.js end()): Noodle cheering over the heading, the
   topics tried as a ring, the one line, the next lesson; under them the flat button and a text link back to the topics.
   The blocks sit 16 px apart, centred in the room above the action bar, so no part of the screen is left empty. */
.hm-ph-app.ln-play .hm-pe{gap:16px;padding:8px 8px 160px}
.hm-pe-top{display:flex;flex-direction:column;align-items:center;gap:4px}
.hm-pe-coach{position:relative;display:block;width:140px;height:145px}
.hm-pe-coach > img{display:block;width:100%;height:100%}
.hm-ph-app.ln-play .hm-pe .lp-h{margin:0;text-align:center}
.hm-pe-prog{display:flex;align-items:center;gap:14px;padding:12px 16px;border-radius:var(--r2);background:var(--sunk)}
.hm-pe-ring{position:relative;flex:none;width:64px;height:64px}
.hm-pe-ring svg{display:block}
.hm-pe-ring circle{fill:none;stroke-width:7}
.hm-pe-ring .tr{stroke:rgba(var(--ink-rgb),.14)}
.hm-pe-ring .fl{stroke:var(--study);stroke-linecap:round}
.hm-pe-ring b{position:absolute;inset:0;display:grid;place-items:center;font:700 21px/1 var(--f-display);color:var(--ink)}
.hm-pe-pt{flex:1;min-width:0;margin:0;display:flex;flex-direction:column;gap:2px}
.hm-pe-pt b{font:700 17px/1.3 var(--f-body);color:var(--ink)}
.hm-pe-pt span{font-size:15px;line-height:1.3;color:var(--ink-2)}
.hm-pe-st{flex:none;display:inline-flex;align-items:center;gap:4px;font:700 17px/1 var(--f-body);color:var(--ink)}
.hm-pe-st span{font-weight:400;font-size:15px;color:var(--ink-2)}
.hm-pe-line{margin:0;font-size:17px;line-height:1.45;color:var(--ink-2);text-align:center;text-wrap:balance}
.hm-pe-next{padding:14px 16px;border:2px solid var(--rule);border-radius:var(--r2);background:var(--surface)}
.hm-pe-next p{margin:0}
.hm-pe-next .k{font:700 14px/1.2 var(--f-body);color:var(--study-ink)}
.hm-pe-next .t{margin-top:4px;font:600 21px/1.2 var(--f-display);color:var(--ink);text-wrap:balance}
.hm-pe-next .m{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-top:6px;font-size:15px;line-height:1.3;color:var(--ink-2)}
.hm-pe-next .u{min-width:0;overflow-wrap:anywhere}
.hm-pe-next .min{flex:none;display:inline-flex;align-items:center;gap:5px}
/* the button stays flat (no lip): pressed is the darker fill and scale(.98), from the player's own rule */
.hm-ph-app.ln-play .lp-actions .lp-btn{box-shadow:none}
.hm-ph-app.ln-play .lp-actions:has(.hm-pe-back){row-gap:4px;padding-bottom:24px}
.hm-pe-back{flex:1 0 100%;display:flex;align-items:center;justify-content:center;min-height:44px;font:700 16px/1.2 var(--f-body);color:var(--study-ink);text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:2px}
.hm-pe-back:hover{color:var(--ink)}
.hm-pe-back:focus-visible{outline:3px solid var(--study);outline-offset:2px;border-radius:8px}
/* no selection on art, tiles and the demo (owner, 11 Oct: "Beware of user-select, consider cursor:pointer too?": a
   double-click on the code tile painted the selection behind its glyphs; tapping answers selected text). Reading text
   (the lede, the facts, the bands' paragraphs) stays selectable. */
.hm-art,.hm-ft,.hm-ph-app,.hm-tl,.hm-crs-it,.hm-tabs,.hm-inside-ic,.hm-stave,.hm-gr,.hm-ed,.hm-crs-cov,.hm-ph-shd{-webkit-user-select:none;user-select:none}
.hm a,.hm button,.hm-ph-app,.hm-ft{-webkit-tap-highlight-color:transparent}
/* the demo phone: a pointer on what works (the answers, Check, Continue, the actions, the close cross), the default
   arrow everywhere else, as in the player */
.hm-ph-app{cursor:default}
.hm-ph-app.ln-play .lq-tile:not(:disabled),.hm-ph-app.ln-play .lp-btn:not(:disabled),.hm-ph-app.ln-play .lp-x{cursor:pointer}
.hm-ph-app.ln-play .lq-tile:disabled,.hm-ph-app.ln-play .lp-btn:disabled{cursor:default}
.hm-ph-app.ln-play .lp-x{background:none;border:0;padding:0}
.hm-ph-app.ln-play .lp-x:focus-visible{outline:3px solid var(--study);outline-offset:2px}
/* the idle demo's tap: a soft ring where a finger would land (transform and opacity only) */
.hm-ph-tap{position:absolute;z-index:40;width:44px;height:44px;margin:-22px 0 0 -22px;border-radius:50%;background:var(--study);opacity:0;pointer-events:none}
.hm-ph-tap.is-on{animation:ph-tap .6s cubic-bezier(.22,1,.36,1) both}
@keyframes ph-tap{0%{opacity:.4;transform:scale(.3)}100%{opacity:0;transform:scale(1.5)}}
@media (prefers-reduced-motion:reduce){.hm-phone{transform:rotateX(5deg) rotateY(-9deg) rotateZ(1.5deg)}.hm-ph-shd{transform:translateX(12px) scaleX(1.06)}}
html[data-motion="off"] .hm-phone{transform:rotateX(5deg) rotateY(-9deg) rotateZ(1.5deg)!important}
/* desktop: 15% taller than the art box (coordinator, 9 Oct: "small relative to the art column"); out of flow, so no shift */
@media (min-width:761px){.hm-phone{top:-7.5%;bottom:-7.5%;height:115%}}
@media (max-width:760px){
  .hm[data-hero="phone"] .hm-art{aspect-ratio:358/400;max-width:420px}
  .hm-phone{padding:6px;border-radius:36px}.hm-ph-scr{border-radius:30px}
  .hm-ph-shd{bottom:-6%;height:7%}
  /* owner, 8 Oct ("spacing on mobile"): the section rhythm above the phone; the phone at most 62% of the width and 55% of
     the screen's height; the tiles (56 px) beside it, 12 px clear of its edge, 16 px or more from the screen's edge */
  .hm[data-hero="phone"] .hm-hero-in{gap:44px}
  .hm-hero h1{font-size:min(40px,8.6vw)}
  .hm-hero h1 span{display:block}
  .hm[data-hero="phone"] .hm-art{--ph-h:min(48vh,520px,calc(56vw * 19.5 / 9));--ph-x:max(0px,calc(50% - var(--ph-h) * 9 / 39 - 68px));aspect-ratio:auto;height:var(--ph-h);max-width:none}
  .hm[data-hero="phone"] .hm-ft{width:56px}
  .hm[data-hero="phone"] .hm-ft-face{border-radius:14px;padding:6px}
  .hm[data-hero="phone"] .hm-ft-code{font-size:15px}
  .hm[data-hero="phone"] .hm-ft1{inset-inline-start:var(--ph-x);top:12%}
  .hm[data-hero="phone"] .hm-ft3{inset-inline-start:auto;inset-inline-end:var(--ph-x);top:26%}
  .hm[data-hero="phone"] .hm-ft2{inset-inline-start:var(--ph-x);top:62%}
  .hm[data-hero="phone"] .hm-ft4{inset-inline-start:auto;inset-inline-end:var(--ph-x);top:74%}
}

/* ---- the Shop tile's looks (owner, 8 Oct; options in handoff-2026-10-06/homepage/shop-tile/). 'paper' and 'note' are
   light tiles in both themes, a sheet of paper on the navy desk, so their text keeps the ink colours; the background is
   one soft drawing behind Petri on the free side (rounded shapes, no lines, low contrast), never behind the text. */
.hm-tl-shop[data-look="paper"],.hm-tl-shop[data-look="covers"],.hm-tl-shop[data-look="basket"]{--tb:#efece7;--ci:#655c4e}
:root .hm-tl-shop[data-look="paper"],:root .hm-tl-shop[data-look="covers"],:root .hm-tl-shop[data-look="basket"],:root .hm-tl-shop[data-look="note"]{background:var(--lg)}
.hm-tl-shop[data-look="note"]{--tb:#f9edc5;--ci:#7b5600}
.hm-tl-shop[data-look="basket"] h3,.hm-tl-shop[data-look="paper"] h3,.hm-tl-shop[data-look="note"] h3,.hm-tl-shop[data-look="covers"] h3{color:#15365a}
.hm-tl-shop[data-look="basket"] p,.hm-tl-shop[data-look="paper"] p,.hm-tl-shop[data-look="note"] p,.hm-tl-shop[data-look="covers"] p{color:#334963}
:root[data-theme="dark"] .hm-tl-shop[data-look] .hm-gr::before{background:radial-gradient(closest-side,color-mix(in srgb,var(--tb),#000 22%),transparent)}
:root[data-theme="dark"] .hm-tl-shop[data-look="gold"] .hm-gr::before{background:radial-gradient(closest-side,rgba(0,0,0,.45),transparent)}
.hm-shop-bg{position:absolute;z-index:0;inset-inline-end:158px;bottom:22px;width:min(30%,170px);aspect-ratio:320/220;pointer-events:none;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 220'%3E%3Cg transform='rotate(-9 120 120)'%3E%3Crect x='52' y='34' width='132' height='170' rx='14' fill='%23e1dcd1'/%3E%3C/g%3E%3Cg transform='rotate(6 200 110)'%3E%3Crect x='130' y='18' width='138' height='176' rx='14' fill='%23ffffff'/%3E%3Crect x='150' y='62' width='98' height='7' rx='3.5' fill='%23e1dcd1'/%3E%3Crect x='150' y='86' width='98' height='7' rx='3.5' fill='%23e1dcd1'/%3E%3Crect x='150' y='110' width='72' height='7' rx='3.5' fill='%23e1dcd1'/%3E%3C/g%3E%3Cg transform='rotate(-18 176 22)'%3E%3Crect x='140' y='10' width='76' height='24' rx='5' fill='%23aee9ec' fill-opacity='.85'/%3E%3C/g%3E%3C/svg%3E") right bottom/contain no-repeat}
.hm-tl-shop[data-look="note"] .hm-shop-bg{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 220'%3E%3Cg transform='rotate(-6 190 120)'%3E%3Crect x='110' y='22' width='168' height='184' rx='16' fill='%23ffffff'/%3E%3Crect x='110' y='22' width='168' height='34' rx='16' fill='%23f4db8f'/%3E%3Crect x='110' y='40' width='168' height='16' fill='%23f4db8f'/%3E%3Crect x='126' y='70' width='38' height='32' rx='8' fill='%23fcf7e3'/%3E%3Crect x='176' y='70' width='38' height='32' rx='8' fill='%23fcf7e3'/%3E%3Crect x='226' y='70' width='38' height='32' rx='8' fill='%23fcf7e3'/%3E%3Crect x='126' y='114' width='38' height='32' rx='8' fill='%23fcf7e3'/%3E%3Crect x='176' y='114' width='38' height='32' rx='8' fill='%23fcf7e3'/%3E%3Crect x='226' y='114' width='38' height='32' rx='8' fill='%23fcf7e3'/%3E%3Crect x='126' y='158' width='38' height='32' rx='8' fill='%23fcf7e3'/%3E%3Crect x='176' y='158' width='38' height='32' rx='8' fill='%23fcf7e3'/%3E%3Crect x='226' y='158' width='38' height='32' rx='8' fill='%23fcf7e3'/%3E%3Cpath d='M134 87l7 7 13-14' fill='none' stroke='%23b38500' stroke-width='6' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M184 131l7 7 13-14' fill='none' stroke='%23b38500' stroke-width='6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/g%3E%3Cg transform='rotate(14 262 30)'%3E%3Crect x='222' y='18' width='80' height='24' rx='5' fill='%23ffced4' fill-opacity='.9'/%3E%3C/g%3E%3C/svg%3E")}
.hm-tl-shop[data-look] .hm-tl-tx p{max-width:22ch}
/* the basket: the tile's hero when there is no character; it carries its own soft ground shadow */
.hm-basket{position:relative;z-index:1;flex:none;align-self:flex-end;width:190px;margin:0 -6px -8px 0}
.hm-basket img{display:block;width:100%;height:auto}
.hm-tl-shop[data-look="basket"] .hm-shop-bg{inset-inline-end:200px;width:min(28%,160px)}
@media (max-width:640px){.hm-basket{width:120px}.hm-tl-shop[data-look="basket"] .hm-shop-bg{display:none}}
.hm-shop-from{margin-top:10px!important;font-weight:700;color:#15365a!important}
.hm-shop-fan{position:relative;z-index:1;flex:none;align-self:center;width:170px;height:150px;margin-inline-end:-36px}
.hm-shop-fan img{position:absolute;bottom:0;width:86px;height:auto;border-radius:6px;box-shadow:0 10px 22px rgba(21,54,90,.16)}
.hm-shop-fan img:nth-child(1){inset-inline-start:0;transform:rotate(-12deg)}
.hm-shop-fan img:nth-child(2){inset-inline-start:42px;bottom:14px;transform:rotate(-2deg)}
.hm-shop-fan img:nth-child(3){inset-inline-start:84px;transform:rotate(9deg)}
.hm-tl-shop[data-look="covers"] .hm-gr{position:relative;z-index:2}
@media (max-width:1000px){.hm-shop-bg{inset-inline-end:150px;width:min(30%,180px)}}
@media (max-width:640px){.hm-shop-fan{display:none}.hm-shop-bg{inset-inline-end:10px;bottom:10px;width:46%}}

/* ---- try one now */
.hm-split{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:56px;align-items:center}
.hm-try-tx p{font-size:18px;color:var(--ink-2);margin:0 0 16px;max-width:34ch}
.hm-try-tx .hm-note{font-size:15px;color:var(--ink-3)}
.hm-blue .hm-link{color:var(--blue-ink)}
.hm-q{background:var(--surface);border-radius:26px;padding:clamp(22px,3vw,36px);box-shadow:var(--shadow)}
.hm-q-p{font:600 clamp(22px,2.4vw,28px)/1.25 var(--f-display);margin:0 0 22px}
.hm-q-ch{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.hm-key{min-height:64px;border:0;border-radius:14px;background:var(--paper);color:var(--ink);font:600 22px/1.2 var(--f-body);cursor:pointer;
  box-shadow:none;transition:transform .09s cubic-bezier(.34,1.56,.64,1),box-shadow .09s cubic-bezier(.22,1,.36,1),background .15s cubic-bezier(.22,1,.36,1)}
:root[data-theme="dark"] .hm-key{background:var(--sunk)}
.hm-key:hover:not([disabled]){background:var(--blue-tint)}
.hm-key:active:not([disabled]){transform:scale(.98);box-shadow:none}
.hm-key[disabled]{cursor:default}
.hm-key.is-right{background:#dff5ea;color:#0b5e39;box-shadow:none}
.hm-key.is-wrong{background:var(--pink-tint);color:var(--pink-ink);box-shadow:none}
:root[data-theme="dark"] .hm-key.is-right{background:#0f3a2a;color:#3fd59a}
.hm-key.is-shake{animation:hm-shake .32s cubic-bezier(.45,0,.55,1)}
@keyframes hm-shake{20%{transform:translateX(-6px)}40%{transform:translateX(5px)}60%{transform:translateX(-3px)}80%{transform:translateX(2px)}}
.hm-q-fb{min-height:3.2em;margin:18px 0 0;font-size:17px;line-height:1.45;color:var(--ink-2)}
.hm-q-fb b{color:var(--ink)}

/* ---- find your level: a soft panel under Courses by level (it was its own navy band until 8 Oct) */
.hm-lvl{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:20px 32px;margin:28px 0 0;padding:26px 28px;border-radius:22px;background:var(--paper);scroll-margin-top:96px}
.hm-lvl h3{font-size:clamp(21px,2vw,24px);margin:0 0 6px}
.hm-lvl p{margin:0;color:var(--ink-2);font-size:16.5px;line-height:1.5;max-width:52ch}
.hm-level-go{display:flex;flex-wrap:wrap;gap:12px}
/* ---- courses by level */
.hm-tabs{display:flex;flex-wrap:wrap;gap:10px;margin:0 0 20px}
/* level tabs (lesson-player review, 10 Oct: too dark in dark mode). Resting: a surface a step lighter than the
   section with a 1.5 px edge, label 4.5:1 or more. Selected: a teal tint with a teal bar along the bottom (inside the
   tab, so no pill and no rule), label in teal ink. */
.hm-tabs{--tab:#eef5fd;--tab-h:#e2edf9;--tab-edge:#7a8fa8;--tab-ink:var(--ink);--tab-on:#dcf3f2;--tab-on-ink:#06606a;--tab-bar:#0d9aa7}
:root[data-theme="dark"] .hm-tabs{--tab:#2a4368;--tab-h:#33507a;--tab-edge:#7f97b3;--tab-ink:#ffffff;--tab-on:#0e5f68;--tab-on-ink:#ffffff;--tab-bar:#3fbfc8}
.hm-tabs button{min-height:46px;padding:0 20px;border:0;border-radius:12px;background:var(--tab);box-shadow:inset 0 0 0 1.5px var(--tab-edge);color:var(--tab-ink);font:700 16px var(--f-body);cursor:pointer}
.hm-tabs button:hover{background:var(--tab-h)}
.hm-tabs button[aria-selected="true"]{background:var(--tab-on);color:var(--tab-on-ink);box-shadow:inset 0 0 0 2px var(--tab-bar)}   /* a fill and a full outline, no bottom bar (owner, 12 Oct) */
.hm-crs{list-style:none;margin:0;padding:4px 0 14px;display:grid;grid-auto-flow:column;grid-auto-columns:minmax(260px,1fr);gap:16px;overflow-x:auto;scroll-snap-type:x mandatory;overscroll-behavior-x:contain;
  scrollbar-width:none;-webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent);mask-image:linear-gradient(90deg,#000 calc(100% - 28px),transparent)}
.hm-crs::-webkit-scrollbar{display:none}
/* owner, 11 Oct ("Adds a scrollbar"): sideways scroll only where the cards do not fit (under 1024 px), its bar hidden and
   a fade at the right edge as the hint; at 1024 px and up every card fits, so the row is a plain grid, no scroll
   container, nothing clipped, the cards one height; the hover lean and lift are transforms with room in the padding */
@media (min-width:1024px){.hm-crs{overflow:visible;grid-auto-columns:minmax(0,1fr);scroll-snap-type:none;-webkit-mask-image:none;mask-image:none;padding:8px 0 16px}}
.hm-crs li{scroll-snap-align:start;display:flex}
.hm-crs-it{--c:var(--blue);--ci:var(--blue-ink);--ct:var(--blue-tint);flex:1;display:flex;flex-direction:column;gap:14px;padding:0 0 18px;border-radius:18px;overflow:hidden;background:var(--ct);color:var(--ink);text-decoration:none;min-height:104px}
/* the course art on each card (owner, 10 Oct: "Images needed here"): edge to edge in an 8:5 media box, the card's top corners
   clipping it; one framing scale for all (brand/tools/home-course-crops.cjs) */
.hm-crs-cov{display:block;aspect-ratio:8/5;overflow:hidden}
.hm-crs-cov .crs-th{object-fit:cover}
.hm-crs-row{display:flex;gap:12px;align-items:flex-start;padding:0 18px}
/* a two-course panel (Music) shares the row 50/50, so no empty third slot (coordinator, 10 Oct), and keeps the other rows'
   media height (a three-across card's 8:5 box), so it reads as the same grid: the subject at the same size, centred,
   the wide ground (bgw, the same pattern at the same scale) filling the sides */
.hm-crs{--crs-gap:16px;container-type:inline-size}
@media (min-width:1024px){.hm-crs{--crs-gap:24px}}
.hm-crs-cov .crs-th.hm-cv-bgw{display:none!important}
@media (min-width:900px){
  .hm-crs:has(> li:nth-child(2):last-child){grid-auto-columns:minmax(0,1fr)}
  .hm-crs:has(> li:nth-child(2):last-child) .hm-crs-cov{aspect-ratio:auto;height:calc((100cqw - 2 * var(--crs-gap)) / 3 * .625)}
  .hm-crs:has(> li:nth-child(2):last-child) .hm-crs-cov .crs-th.hm-cv-bg{display:none!important}
  :root:not([data-theme="dark"]) .hm-crs:has(> li:nth-child(2):last-child) .hm-crs-cov .crs-th.hm-cv-bgw.th-light,
  :root[data-theme="dark"] .hm-crs:has(> li:nth-child(2):last-child) .hm-crs-cov .crs-th.hm-cv-bgw.th-dark{display:block!important}
  .hm-crs:has(> li:nth-child(2):last-child) .hm-crs-cov .crs-th.hm-cv-fg{width:auto;inset-inline-end:0;inset-inline-start:0;margin:0 auto}
}
.hm-crs-it:hover{box-shadow:var(--shadow)}
.hm-crs-it[data-s="science"]{--c:var(--study);--ci:var(--study-ink);--ct:var(--study-tint)}
.hm-crs-it[data-s="cs"]{--c:var(--play);--ci:var(--play-ink);--ct:var(--play-tint)}
.hm-crs-it[data-s="music"]{--c:var(--music);--ci:var(--music-ink);--ct:var(--music-tint)}
.hm-crs-it[data-s="python"]{--ci:#7f5b00;--ct:#fcecc0}
.hm-crs-it[data-s="web"]{--ci:#a8420f;--ct:#fdd9c4}
.hm-crs-it[data-s="sql"]{--ci:#1b65a6;--ct:#cfe3f4}
.hm-crs-it[data-s="c"]{--ci:#b8204b;--ct:#f9d3db}
:root[data-theme="dark"] .hm-crs-it[data-s="python"]{--ci:#ffcf5c;--ct:#2a2614}
:root[data-theme="dark"] .hm-crs-it[data-s="web"]{--ci:#ff9a66;--ct:#2c1d18}
:root[data-theme="dark"] .hm-crs-it[data-s="sql"]{--ci:#74b9f2;--ct:#13304f}
:root[data-theme="dark"] .hm-crs-it[data-s="c"]{--ci:#ff819f;--ct:#2e1726}
.hm-crs-ic{flex:none;color:var(--ci);display:flex}
.hm-crs-tx{display:flex;flex-direction:column;gap:4px}
.hm-crs-tx b{font:600 19px/1.2 var(--f-display)}
.hm-crs-tx small{font-size:14px;color:var(--ink-2);line-height:1.4}
/* a course to come: the same card, art, tint and motion as a live one, with a small label on its art (11 Oct) */
.hm-crs-it{position:relative}
.hm-crs-soon{align-self:flex-start;margin-top:6px;padding:4px 10px;border-radius:8px;background:var(--surface);color:var(--ci);font:700 13px/1.2 var(--f-body);box-shadow:none}
:root[data-theme="dark"] .hm-crs-soon{background:color-mix(in srgb,var(--ct),#000 25%);color:#fff}

/* ---- study tools */
.hm-tools{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:20px}
.hm-tool{--c:var(--blue);--ci:var(--blue-ink);--ct:var(--blue-tint);display:flex;flex-direction:column;align-items:center;gap:14px;padding:24px 16px 22px;border-radius:18px;background:var(--ct);color:var(--ink);text-decoration:none;height:100%}
.hm-tool[data-tone="teal"]{--c:var(--study);--ci:var(--study-ink);--ct:var(--study-tint)}
.hm-tool[data-tone="violet"]{--c:var(--play);--ci:var(--play-ink);--ct:var(--play-tint)}
.hm-tool[data-tone="pink"]{--c:var(--pink);--ci:var(--pink-ink);--ct:var(--pink-tint)}
.hm-tool b{font:600 18px/1.2 var(--f-display);text-align:center}
.hm-tool:hover{box-shadow:var(--shadow)}
.hm-pv{width:150px;height:120px;display:block;overflow:visible}
.hm-pv .hm-pv-gd{fill:var(--ci);opacity:.16}
.hm-pv .hm-pv-face{fill:var(--surface)}
.hm-pv .hm-pv-tone{fill:var(--c)}
.hm-pv .hm-pv-ln{fill-opacity:1;stroke:var(--ci);stroke-width:5;stroke-linecap:round;stroke-linejoin:round}
.hm-pv path.hm-pv-ln:not(.hm-pv-face):not(.hm-pv-tone){fill:none}
.hm-pv .hm-pv-tl{fill:none;stroke:var(--c);stroke-width:5;stroke-linecap:round;stroke-linejoin:round}
.hm-pv .hm-pv-ax{fill:none;stroke:var(--ci);stroke-width:5;stroke-linecap:round;opacity:.35}
.hm-pv .hm-pv-curve{fill:none;stroke:var(--c);stroke-width:5;stroke-linecap:round;stroke-dasharray:100;stroke-dashoffset:0}
/* The Focus Timer thumb counts DOWN, as the tool does (owner, 10 Oct: "counting down? time going up?"): the ring is the
   time left, from the hand clockwise round to 12; it empties clockwise from 12 o'clock, and the hand rides its leading
   edge. A negative offset on a 100-unit path does that (the tool's #arc uses the same rule); the gap is one unit longer
   than the path, so at empty no sliver of the pattern wraps round to 12. At rest: a third used,
   about 2/3 inset-inline-start: offset -33.333, the hand turned 120deg clockwise from 12 (also the reduced-motion frame). */
.hm-pv .hm-pv-ring{fill:none;stroke:var(--c);stroke-width:8;stroke-dasharray:100 101;stroke-dashoffset:-33.333;transform-box:view-box;transform-origin:60px 52px;transform:rotate(-90deg)}
.hm-pv .hm-pv-arm{transform-box:view-box;transform-origin:60px 72px;transform:rotate(-10deg)}
.hm-pv .hm-pv-card{transform-box:view-box;transform-origin:60px 55px}
.hm-pv .hm-pv-cb{opacity:0}
.hm-pv .hm-pv-dot{fill:var(--c)}   /* the flashcard: the front reads "?", the back a tick and an answer line */
:root[data-theme="dark"] .hm-pv .hm-pv-face{fill:var(--paper)}
/* moving only once seen, and only with motion on */
.hm-js .hm-pv-curve{stroke-dashoffset:100}
.hm-pv .hm-pv-hand{transform-box:view-box;transform-origin:60px 52px;rotate:120deg}
.hm-pv .hm-pv-cap{transform-box:view-box}
/* One play at a time (owner, 10 Oct: the Focus Timer thumb "snaps"): a thumb's moment runs once on arrival and again on
   hover or keyboard focus, always to its end, and every moment ENDS on the still drawing. bl-home.js adds .hm-play and
   takes it off when the last part has finished, so leaving the card mid-way never cuts it short or jumps it back, and
   nothing restarts on the way out (before: hover-out removed the hover animation, the thumb jumped to rest and the
   arrival animation replayed). Easing is the house in-out (cubic-bezier(.45,0,.55,1)); no overshoot snaps.
   Metronome: the pendulum swings to each side and back to rest (2.6 s). Timer (3.2 s): the block runs out (the ring empties
   clockwise and the hand sweeps to 12 at one steady rate), the cap presses, ring and hand fade, a fresh full ring fades
   in and counts down to rest. Time only ever runs down; the jump from empty to full happens while both are invisible. Flashcard: it turns over, shows its back, and turns
   back (1.9 s). Graph: the curve plots itself while a point rides its pen tip (1.3 s). Static under reduced motion. */
.hm-js .is-in .hm-pv-curve{stroke-dashoffset:0}
.hm-js .hm-play .hm-pv-arm{animation:hm-swing 2.4s var(--hm-d,0s) both}
.hm-js .hm-play .hm-pv-ring{animation:hm-cd 3.2s var(--hm-d,0s) both}
.hm-js .hm-play .hm-pv-hand{animation:hm-cdh 3.2s var(--hm-d,0s) both}
.hm-js .hm-play .hm-pv-cap{animation:hm-press 3.2s var(--hm-d,0s) both}
.hm-js .hm-play .hm-pv-card{animation:hm-flip 1.9s var(--hm-d,0s) both}
.hm-js .hm-play .hm-pv-cf{animation:hm-cfout 1.9s steps(1,end) var(--hm-d,0s) both}
.hm-js .hm-play .hm-pv-cb{animation:hm-cbin 1.9s steps(1,end) var(--hm-d,0s) both}
.hm-js .hm-play .hm-pv-curve{animation:hm-plotc 1.1s linear var(--hm-d,0s) both}
.hm-js .hm-play .hm-pv-pt{animation:hm-glide 1.3s linear var(--hm-d,0s) both}
.hm-js .hm-play.hm-first{--hm-d:.3s}
/* the metronome (owner, 11 Oct: "moves too slowly?"): about 109 bpm, each swing extreme to extreme 0.55 s, sine
   in-out on every segment so it slows into each end like a real pendulum (where the click falls) and speeds through
   the middle: rest -> +16, three full swings, back to rest (2.4 s). Rotation only: nothing fades or flashes. */
@keyframes hm-swing{0%{transform:rotate(-10deg);animation-timing-function:cubic-bezier(.37,0,.63,1)}19.6%{transform:rotate(16deg);animation-timing-function:cubic-bezier(.37,0,.63,1)}42.5%{transform:rotate(-16deg);animation-timing-function:cubic-bezier(.37,0,.63,1)}65.4%{transform:rotate(16deg);animation-timing-function:cubic-bezier(.37,0,.63,1)}88.3%{transform:rotate(-16deg);animation-timing-function:cubic-bezier(.22,1,.36,1)}100%{transform:rotate(-10deg)}}
/* the countdown: 0-50% a steady sweep from a third used to empty (2/3 of a turn), 50-56% hold at 12, 56-64% fade
   out, 65% (invisible) back to full, 65-75% fade in full, 75-100% a steady sweep to rest (1/3 of a turn): both sweeps
   at nearly the same rate (1.33 and 1.33 turns per run), linear like the tool's own ring */
@keyframes hm-cd{0%{stroke-dashoffset:-33.333;opacity:1;animation-timing-function:linear}50%{stroke-dashoffset:-100.5}56%{stroke-dashoffset:-100.5;opacity:1;animation-timing-function:cubic-bezier(.45,0,.55,1)}64%{stroke-dashoffset:-100.5;opacity:0}65%{stroke-dashoffset:0;opacity:0;animation-timing-function:cubic-bezier(.45,0,.55,1)}75%{stroke-dashoffset:0;opacity:1;animation-timing-function:linear}100%{stroke-dashoffset:-33.333;opacity:1}}
@keyframes hm-cdh{0%{rotate:120deg;opacity:1;animation-timing-function:linear}50%{rotate:360deg}56%{rotate:360deg;opacity:1;animation-timing-function:cubic-bezier(.45,0,.55,1)}64%{rotate:360deg;opacity:0}65%{rotate:0deg;opacity:0;animation-timing-function:cubic-bezier(.45,0,.55,1)}75%{rotate:0deg;opacity:1;animation-timing-function:linear}100%{rotate:120deg;opacity:1}}
@keyframes hm-press{0%,50%{translate:0 0;animation-timing-function:cubic-bezier(.45,0,.55,1)}53%{translate:0 3px;animation-timing-function:cubic-bezier(.45,0,.55,1)}58%,100%{translate:0 0}}
@keyframes hm-flip{0%{transform:scaleX(1);animation-timing-function:cubic-bezier(.45,0,.55,1)}13%{transform:scaleX(0);animation-timing-function:cubic-bezier(.45,0,.55,1)}26%{transform:scaleX(1)}70%{transform:scaleX(1);animation-timing-function:cubic-bezier(.45,0,.55,1)}83%{transform:scaleX(0);animation-timing-function:cubic-bezier(.45,0,.55,1)}96%,100%{transform:scaleX(1)}}
/* the flashcard's faces swap while the card is edge-on (scaleX 0), so each frame shows a face with content. Own names:
   a later @keyframes hm-in (the entrances) used to replace the back's, which kept the back blank (owner, 11 Oct) */
@keyframes hm-cfout{0%{opacity:1}13%{opacity:0}83%,100%{opacity:1}}
@keyframes hm-cbin{0%{opacity:0}13%{opacity:1}83%,100%{opacity:0}}
@keyframes hm-plotc{from{stroke-dashoffset:100}to{stroke-dashoffset:0}}
/* the graphing calculator's point (owner, 9 Oct: "a hover animation for the graphing calculator thumb too") */
.hm-pv .hm-pv-pt{fill:var(--surface);stroke:var(--ci);stroke-width:3.5;opacity:0;translate:82px 28px}
:root[data-theme="dark"] .hm-pv .hm-pv-pt{fill:var(--paper)}   /* rides the curve by equal arc-length keys */
@keyframes hm-glide{0.0%{translate:46.0px 28.0px}7.08%{translate:47.6px 35.8px}14.17%{translate:49.3px 43.4px}21.25%{translate:51.4px 51.0px}28.33%{translate:53.9px 58.5px}35.42%{translate:57.3px 65.6px}42.5%{translate:63.3px 70.0px}49.58%{translate:69.2px 65.1px}56.67%{translate:72.8px 58.2px}63.75%{translate:75.6px 50.8px}70.83%{translate:78.0px 43.3px}77.92%{translate:80.1px 35.7px}85.0%{translate:82.0px 28.0px}0%,85%{opacity:1}100%{translate:82px 28px;opacity:0}}
.hm-ad{margin-top:48px}
.hm-ad:empty{display:none}

/* ---- from the Shop */
.hm-shop{display:grid;grid-template-columns:minmax(0,4fr) minmax(0,8fr);gap:56px;align-items:center}
.hm-shop-tx p{font-size:18px;color:var(--ink-2);margin:0 0 18px;max-width:30ch}
.hm-picks{list-style:none;margin:0;padding:24px 0 0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:28px}
.hm-picks a{display:flex;flex-direction:column;gap:12px;color:var(--ink);text-decoration:none}
.hm-picks img{display:block;width:100%;height:auto;border-radius:8px;box-shadow:0 16px 32px rgba(21,54,90,.16);transition:transform .2s cubic-bezier(.22,1,.36,1)}
.hm-picks li:nth-child(1) img{transform:rotate(-3deg)}
.hm-picks li:nth-child(2){margin-top:-24px}
.hm-picks li:nth-child(3) img{transform:rotate(3deg)}
.hm-picks a:hover img{transform:translateY(-6px)}
.hm-picks b{font:600 17px/1.25 var(--f-display)}

/* ---- quick breaks (the game cards from games-ui.php) */
.gstrip .tiles{grid-template-columns:repeat(6,minmax(0,1fr))}

/* ---- questions */
.hm-faq{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,5fr);gap:64px;align-items:start}
.hm-qa{background:var(--paper);border-radius:18px;margin:0 0 12px}
.hm-paper .hm-qa{background:var(--surface)}
.hm-qa summary{position:relative;list-style:none;cursor:pointer;padding:20px 56px 20px 22px;font:600 19px/1.3 var(--f-display);color:var(--ink);min-height:44px}
.hm-qa summary::-webkit-details-marker{display:none}
.hm-qa summary::after{content:"";position:absolute;inset-inline-end:24px;top:50%;width:10px;height:10px;margin-top:-8px;border-inline-end:3px solid var(--ink-3);border-bottom:3px solid var(--ink-3);border-radius:0 0 3px 0;transform:rotate(45deg);transition:transform .2s cubic-bezier(.22,1,.36,1)}
.hm-qa[open] summary::after{transform:rotate(-135deg);margin-top:-2px}
.hm-qa p{margin:0;padding:2px 22px 24px;color:var(--ink-2);line-height:1.55}
.hm-qa p a{color:var(--study-ink);font-weight:700}
.hm-guides h3{font-size:22px;margin:8px 0 14px}
.hm-guides ul{list-style:none;margin:0 0 18px;padding:0}
.hm-guides li{margin:0 0 12px}
.hm-guides li a{color:var(--ink);font-weight:600;line-height:1.4}
.hm-guides li a:hover{color:var(--study-ink);text-decoration:underline;text-underline-offset:3px}
.hm-pt{margin:36px 0 0;color:var(--ink-2)}
.hm-pt a{color:var(--gold-ink);font-weight:700}

/* ---- the end (owner, 8 Oct): a full-bleed teal band straight onto a full-bleed navy footer, both on the page grid,
   separated by the colour change and their own padding (no rule). The footer is made full width on the homepage only
   (footer.php is shared). */
.hm-final{display:flex;align-items:center;justify-content:space-between;gap:32px}
.hm-final h2{font-size:clamp(32px,5vw,56px);line-height:1.05;margin:0 0 24px;color:var(--ink)}
.hm-final-art{width:200px;height:auto;flex:none}
.hm footer.blf{max-width:none;margin-top:0;border-radius:0;background:var(--navy);color:#b9cde3;
  padding:56px max(24px,calc((100% - var(--wrap)) / 2 + 24px)) 40px}
.hm .blf .blf-brand,.hm .blf h2,.hm .blf a[aria-current="true"]{color:#fff}
.hm .blf a{color:#d3e1ef}
.hm .blf a:hover{color:#fff;text-decoration:underline;text-underline-offset:3px}
.hm .blf .blf-copy{color:#9fb8d2}
.hm .blf a:focus-visible{outline-color:var(--gold)}
@media (max-width:640px){
  .hm footer.blf{padding:40px 16px 32px}
  .hm-final{flex-direction:column-reverse;align-items:flex-start;gap:12px}
  .hm-final-art{width:130px}
}
/* the house ad's button: the house keycap, not a pill */
.hm-ad .house{border-radius:18px}
.hm-ad .house .hb{border-radius:12px;box-shadow:none;padding:10px 18px}

/* ---- motion (owner, 10 Oct: "more parallax and cool motion for the website", then "Don't make the motion too
   distracting but enough to be engaging and fun to use"). One language for the page, in these tokens: one easing (a
   settle, no bounce), two durations, one distance scale; parallax at most 16 px, hover tilt at most 6 degrees,
   entrances under 400 ms; nothing loops but the phone demo, and whatever moves while you read stops once it settles.
   Transform and opacity only. Reduced motion turns all of it off (the rules at the end). Notes for other pages:
   docs/plans/HOMEPAGE_REDESIGN.md, "Motion rules". */
.hm{--m-ease:cubic-bezier(.22,1,.36,1);--m-t1:180ms;--m-t2:320ms;--m-step:60ms;--m-d1:8px;--m-d2:12px;--m-d3:16px;--m-tilt:6deg;--m-enter:200ms;--m-enter-step:40ms;--m-enter-d:12px}
@media (pointer:coarse){.hm{--m-enter-d:8px}}   /* fast scrollers (owner, 11 Oct): the same short entrances as every page (brainlag.css) */
/* entrances: everything is drawn complete at rest. bl-home.js adds .is-enter only to a block that was below the fold at
   load, as it comes into view: it rises the small distance and fades in, its row neighbours a step later (--i) */
.hm-js .is-enter{animation:hm-in var(--m-enter) var(--m-ease) both;animation-delay:calc(var(--i,0) * var(--m-enter-step))}
.hm-js .is-enter.hm-in-x{animation-name:hm-in-x}
@keyframes hm-in{from{opacity:0;translate:0 var(--m-enter-d)}}
@keyframes hm-in-x{from{opacity:0;translate:var(--m-enter-d) 0}}
.hm-tl{transition:transform var(--m-t2) var(--m-ease),box-shadow var(--m-t2) var(--m-ease)}
/* Courses by level: the art is two layers (the ground and the subject, brand/tools/home-course-crops.cjs). On scroll the
   ground drifts one way and the subject the other (--py, -1 to 1 across the screen); with a mouse the card leans toward
   the pointer (at most 6 degrees), a light sheen crosses it and the subject lifts a little. bl-home.js sets the numbers. */
.hm-crs-cov{position:relative}
.hm-crs-cov .crs-th{position:absolute;inset:0;width:100%;height:100%;will-change:transform}
.hm-cv-bg,.hm-cv-bgw{transform:translate3d(calc(var(--mx,0) * -4px),calc(var(--py,0) * 6px + var(--my,0) * -3px),0) scale(1.1)}
.hm-cv-fg{transform:translate3d(calc(var(--mx,0) * 6px),calc(var(--py,0) * -6px + var(--my,0) * 4px + var(--lift,0px)),0)}
.hm-crs-cov::after{content:"";position:absolute;inset:-30% -60%;pointer-events:none;opacity:0;
  background:linear-gradient(110deg,transparent 42%,rgba(255,255,255,.28) 50%,transparent 58%);transform:translateX(calc(var(--mx,0) * 18%));transition:opacity var(--m-t2) var(--m-ease)}
:root[data-theme="dark"] .hm-crs-cov::after{background:linear-gradient(110deg,transparent 42%,rgba(255,255,255,.10) 50%,transparent 58%)}
@media (hover:hover) and (pointer:fine) and (min-width:1024px){   /* the lean only where the row is not a scroller */
  .hm-crs-it{transform:perspective(900px) rotateX(calc(var(--my,0) * -4deg)) rotateY(calc(var(--mx,0) * var(--m-tilt)));transition:transform var(--m-t2) var(--m-ease),box-shadow var(--m-t2) var(--m-ease)}
  .hm-crs-it.is-tilt{transition:transform 90ms linear,box-shadow var(--m-t2) var(--m-ease)}
  .hm-crs-it:hover{--lift:-4px}
  .hm-crs-it:hover .hm-crs-cov::after{opacity:1}
  .hm-cv-fg{transition:transform var(--m-t2) var(--m-ease)}
  .hm-crs-it.is-tilt .hm-cv-fg,.hm-crs-it.is-tilt .hm-cv-bg,.hm-crs-it.is-tilt .hm-cv-bgw{transition:transform 90ms linear}
}
/* more room: the cards 24 px apart, a little more space under the tabs */
@media (min-width:1024px){.hm-crs{gap:24px}}
.hm-tabs{margin-bottom:28px}

/* ---- reduced motion: the end state at once */
@media (prefers-reduced-motion:reduce){
  .hm *,.hm *::before,.hm *::after{animation:none!important;transition:none!important}
  .hm-js .hm-pv-curve{stroke-dashoffset:0}
  .hm-tool:hover .hm-pv-cf{opacity:0}.hm-tool:hover .hm-pv-cb{opacity:1}
  .hm-tl:hover,.hm-picks a:hover img{transform:none}
  .hm-crs-it,.hm-cv-bg,.hm-cv-bgw,.hm-cv-fg{transform:none!important}.hm-crs-cov::after{display:none}
}
html[data-motion="off"] .hm *,html[data-motion="off"] .hm *::before,html[data-motion="off"] .hm *::after{animation:none!important;transition:none!important}
html[data-motion="off"] .hm-crs-it,html[data-motion="off"] .hm-cv-bg,html[data-motion="off"] .hm-cv-bgw,html[data-motion="off"] .hm-cv-fg{transform:none!important}html[data-motion="off"] .hm-crs-cov::after{display:none}
html[data-motion="off"].hm-js .hm-pv-curve{stroke-dashoffset:0}

/* ---- responsive */
@media (max-width:1100px){
  .gstrip .tiles{grid-template-columns:repeat(3,minmax(0,1fr))}
  .hm-tools{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:1000px){
  .hm-mo{display:none}
  .hm-bento{grid-template-columns:repeat(2,minmax(0,1fr))}
  .hm-tl-learn{grid-row:auto;flex-direction:row;align-items:flex-end}
  .hm-tl-learn .hm-tl-tx{align-self:flex-start;flex:1 1 auto}
  .hm-tl-learn .hm-gr{width:200px;margin:0}
  .hm-split,.hm-shop,.hm-faq{grid-template-columns:1fr;gap:32px}
}
@media (max-width:760px){
  .hm-hero-in{grid-template-columns:minmax(0,1fr);gap:20px}   /* minmax(0,…): a long Up next name must never widen the column (owner, 11 Oct) */
  .hm-art{aspect-ratio:390/300;max-width:520px;margin:0 auto}
  .hm-noodle{inset-inline-start:23%;width:54%;bottom:0}
  .hm-ground{top:95.3%}
  .gstrip .tiles{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:640px){
  .hm-bento{grid-template-columns:1fr;gap:14px}
  .hm-tl,.hm-tl-learn,.hm-tl-code,.hm-tl-music,.hm-tl-shop{grid-column:auto;min-height:0;padding:22px 20px}
  .hm-tl-rev,.hm-tl-tools{flex-direction:row;align-items:flex-end}
  .hm-tl-rev .hm-tl-tx,.hm-tl-tools .hm-tl-tx{align-self:flex-start;flex:1 1 auto}
  .hm-tl .hm-gr,.hm-tl-learn .hm-gr,.hm-tl-rev .hm-gr,.hm-tl-tools .hm-gr,.hm-tl-shop .hm-gr{width:108px;margin:0}
  .hm-stave{width:150px}
  .hm-tl-list{flex-direction:column;gap:8px;margin-top:12px}   /* shown on phones too; three items stay a column, never 2 + 1 */
  .hm-tl-code pre{font-size:13.5px}
  .hm-tl-code{grid-template-columns:1fr;gap:16px}
  .hm-code-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:2px 12px;margin-top:12px}   /* 2 x 2, never 3 + 1 */
  .hm-code-list a{min-height:44px;width:auto;gap:8px}
  .hm-tl-code .hm-tl-tx{container-type:inline-size}
  .hm-ctas{gap:12px}
  .hm-ctas .hm-b{flex:1 1 0;min-width:0;padding:0 14px}
  .hm-q-ch{gap:10px}
  .hm-key{font-size:19px;min-height:58px}
  .hm-crs{grid-auto-columns:minmax(240px,82%)}
  .hm-tools{gap:12px}
  .hm-pv{width:120px;height:96px}
  .hm-picks{gap:14px}
  .hm-picks b{font-size:14px}
  .hm-level-go .hm-b{flex:1 1 100%}
  @container (min-width:430px){.hm-code-list{grid-template-columns:repeat(4,max-content);gap:2px 18px}}
  .hm-lvl{padding:22px 20px}
  .hm-up{max-width:none}
}
@media (max-width:360px){
  .hm-tl .hm-gr,.hm-tl-learn .hm-gr,.hm-tl-rev .hm-gr,.hm-tl-tools .hm-gr,.hm-tl-shop .hm-gr{width:88px}
  .hm-stave{width:120px}
  .hm-tools{grid-template-columns:1fr 1fr}
  .hm-tool{padding:20px 8px 18px;min-width:0}.hm-pv{width:100%;max-width:120px;height:auto;aspect-ratio:5/4}
  .hm-key{font-size:17px}
}

/* ---- space and separation (owner, 9 Oct: "Make better use of space on the homepage, and make the 'Pick a way in'
   section obviously distinct from the hero banner above it"). The hero is as tall as its content; its text column
   carries three plain facts under the buttons; at 1500 px and up the copy column takes more of the row; "Pick a way in" is its own
   band, a surface with a softly rounded top, so the first screen shows the hero and the start of the next band. */
.hm-hero{padding:clamp(40px,6vw,104px) 0 clamp(72px,8vw,136px)}   /* owner, 10 Oct: "needs a bit more vertical space" (was 28-56 / 40-64) */
.hm-inside{list-style:none;margin:30px 0 0;padding:0;display:flex;flex-wrap:wrap;gap:10px 26px;max-width:640px}
.hm-inside li{display:flex;font-size:15.5px;line-height:1.35;color:var(--ink-2)}
.hm-inside a{display:flex;align-items:center;gap:9px;min-height:44px;margin:0 -6px;padding:4px 8px 4px 6px;border-radius:12px;color:inherit;text-decoration:none;transition:background-color .2s ease,color .2s ease}
.hm-inside a:hover{background:var(--surface);color:var(--ink)}
.hm-inside a:focus-visible{outline:3px solid var(--study);outline-offset:1px}
.hm-inside-go{flex:none;color:var(--ink-3);transition:transform .2s cubic-bezier(.22,1,.36,1),color .2s ease}
.hm-inside a:hover .hm-inside-go,.hm-inside a:focus-visible .hm-inside-go{transform:translateX(3px);color:var(--study-ink)}
:root[data-theme="dark"] .hm-inside a:hover{background:var(--surface)}
.hm-inside-ic{flex:none;display:inline-flex;width:34px;height:34px;align-items:center;justify-content:center;border-radius:10px;background:var(--study-tint);color:var(--study-ink)}
.hm-inside li:nth-child(2) .hm-inside-ic{background:var(--blue-tint);color:var(--blue-ink)}
.hm-inside li:nth-child(3) .hm-inside-ic{background:var(--gold-tint);color:var(--gold-ink)}
@media (min-width:1500px){
  .hm-hero-in{grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);gap:56px}
  .hm[data-hero="phone"] .hm-art{max-width:640px;justify-self:end}
}
/* the band: one surface step from the page, rounded only at the top, with a soft shadow along its top edge (no rule):
   white in light (the page is paper), --surface in dark (the code slab drops to --code-bg on it). Chosen so every way-in tile's lightest corner still
   clears the band by the 0.044 OKLab floor (handoff-2026-10-06/homepage/card-corners/edge.cjs); --sunk in light failed it. */
.hm-ways{position:relative;background:var(--surface);border-radius:0;padding-top:clamp(56px,6.5vw,104px);   /* square and full-bleed (owner, 10 Oct); the colour change and a soft top shadow mark the join */
 
  box-shadow:0 -10px 28px -14px rgba(var(--ink-rgb),.18)}
:root[data-theme="dark"] .hm-ways{background:var(--surface);box-shadow:0 -10px 28px -14px rgba(0,0,0,.6)}
:root[data-theme="dark"] .hm-ways .hm-tl-code{background:var(--code-bg)}
:root[data-theme="dark"] .hm-ways .hm-tl-learn{--hla:9%}   /* a touch more light end, so its near-flat dark sweep stays above the original */
:root[data-theme="dark"] .hm-ways .hm-tl-rev{--tb:color-mix(in srgb,var(--play-tint),var(--play) 16%);--hla:10%}   /* the dark violet tint sat 0.016 L off --surface */   /* the code slab sat on --surface, the band's own colour */
.hm-ways .hm-h2{margin-top:0}
@media (max-width:760px){
  .hm-inside{margin-top:20px;gap:8px 14px}
  .hm-inside li{flex:1 1 100%;font-size:15px}
  .hm-inside li + li{display:none}   /* on a phone, the courses fact only, so the next band still peeks into the first screen */
  .hm[data-hero="phone"] .hm-art{--ph-h:min(50vh,480px,calc(60vw * 19.5 / 9))}   /* the hero's phone, larger and legible (owner, 10 Oct) */
  .hm[data-hero="phone"] .hm-hero-in{gap:40px}
  .hm-hero{padding-bottom:56px}
  .hm-inside li{font-size:14.5px}.hm-inside-ic{width:30px;height:30px}
}

/* no lone item on a wrapped row (owner, 10 Oct: "Avoid multiple lines for just one item on one"); home-check runs
   orphans at 320 to 768 px. The level tabs: one row where they fit, else two equal columns (an even count) or one
   column (an odd count). The Find your level buttons: one row where all three fit, else one per line. */
.hm-tabs-c{container-type:inline-size}
@container (max-width:539px){
  .hm-tabs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}
  .hm-tabs[data-n="1"],.hm-tabs[data-n="3"],.hm-tabs[data-n="5"]{grid-template-columns:1fr}
}
@media (max-width:900px){.hm-level-go .hm-b{flex:1 1 100%}}

/* the body font's fallback, sized to match Onest (metrics from bl-onest.woff2: ascent 970, descent 305 per 1000; widths
   106.2% of Arial), so its late swap no longer re-wraps the hero text on a phone and moves the art (CLS 0.17). A preload
   would do it too but cost about 70 ms of LCP, since it competes with the display font. */
@font-face{font-family:"BL Body FB";src:local("Arial"),local("ArialMT");size-adjust:106.2%;ascent-override:91.3%;descent-override:28.7%;line-gap-override:0%}
/* Android has no Arial: the same match on Roboto (widths 106.7% of Roboto Regular; ascent 90.9%, descent 28.6%) */
@font-face{font-family:"BL Body FBR";src:local("Roboto"),local("Roboto-Regular"),local("Roboto Regular");size-adjust:106.7%;ascent-override:90.9%;descent-override:28.6%;line-gap-override:0%}
.hm{--f-body:"BL Body","BL Body FB","BL Body FBR",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif}

/* (last in the file, so it outranks the phone rules above) on a phone (600 px and under; owner, 11 Oct: "On mobile it doesn't work: too tiny, and we're already on mobile"): no
   phone frame and no floating tiles; the same working question sits in the page as a full-width card at the player's
   own size, under the hero text: no top bar, no idle demo (bl-home-phone.js), the feedback area's height reserved so
   choosing, Check, the sheet and Continue never move the page */
@media (max-width:600px){
  .hm[data-hero="phone"] .hm-art{height:auto;aspect-ratio:auto;max-width:none;perspective:none;margin:4px 0 0}
  .hm[data-hero="phone"] .hm-ft,.hm-ph-shd{display:none}
  /* will-change:auto: no composited layer for a card that never moves here. Android's WebView (the store app, Pixel 7,
     12 Oct) painted a stale copy of that layer beside the answers ("luct", "st: Si" at the left edge); the hero also clips
     sideways so nothing of it can be painted past the page's edges */
  .hm-phone{position:static;translate:none;height:auto;aspect-ratio:auto;width:auto;padding:0;border-radius:var(--r3);background:none;box-shadow:none;transform:none!important;will-change:auto}
  .hm[data-hero="phone"] .hm-hero{overflow-x:clip}
  .hm-ph-scr{height:auto;border-radius:var(--r3);background:var(--surface);box-shadow:var(--shadow)}
  .hm-ph-app,.hm-ph-app.ln-play{position:static;width:auto;height:auto;transform:none;background:var(--surface);overflow:visible}
  .hm-ph-app.ln-play .lp-top{display:none}
  .hm-ph-app.ln-play .lp-stage{padding:18px 16px 4px}
  .hm-ph-app.ln-play .lq-title{margin-top:0}
  /* the answer slot (owner, 11 Oct: no dead space): Check sits straight under the options; after Check the same block
     becomes the feedback, tinted like the player's, with Continue (or Try again) inside it. It is as tall as what it
     holds; bl-home-phone.js eases its height (180 ms) and keeps the card's top where it was. The growth follows the
     Check tap, so it is not counted as a layout shift (hadRecentInput). */
  .hm-ph-app.ln-play .lp-foot{position:static;display:flex;flex-direction:column;justify-content:flex-start;margin:0 4px 4px;padding:0 12px 12px;background:transparent;box-shadow:none!important;border:0;border-radius:var(--r2);transition:background-color .18s,height .18s ease-out}
  .hm-ph-app.ln-play .lp-foot.is-sizing{overflow:hidden}
  .hm-ph-app.ln-play .lp-foot:has(.lp-sheet.is-right){background:var(--ln-right-bg)}
  .hm-ph-app.ln-play .lp-foot:has(.lp-sheet.is-wrong){background:var(--ln-wrong-bg)}
  .hm-ph-app.ln-play .lp-foot:has(.lp-sheet.is-neutral){background:var(--ln-self-bg)}
  .hm-ph-app.ln-play .lp-sheet{padding:0 2px}
  .hm-ph-app.ln-play .lp-sheet:is(.is-right,.is-wrong,.is-neutral){padding-top:12px}
  .hm-ph-app.ln-play .lp-sheet .l:has(+ .why){display:none}   /* a right answer's mark count: the title and the working say it on a card this small (a wrong answer's .l is its explanation: kept) */
  .hm-ph-app.ln-play .lp-actions{padding:8px 0 0}
  .hm-ph-app.ln-play .hm-ph-end{padding:8px 0 16px}
  .hm-ph-app.ln-play .hm-pe{gap:14px;padding:0 0 4px}
  .hm-pe-coach{width:112px;height:116px}
  .hm-ph-app.ln-play .lp-actions:has(.hm-pe-back){padding-bottom:0}
}

/* every hero and continue button on a phone (owner, 11 Oct: "Continue learning", "Find my level" and the Music theory
   continue card "break the mobile layout"): one under the other, full width; a long label wraps inside its button
   (balanced, padding kept); the Up next card is never wider than the page, its lesson on one line and the course and
   unit on a smaller second line, each cut with an ellipsis, the whole name in its aria-label (bl-home.js) */
@media (max-width:480px){
  .hm-hero-tx,.hm-ctas,.hm-up,.hm-up-tx{min-width:0}
  .hm-ctas{flex-direction:column;align-items:stretch;gap:12px}
  .hm-ctas .hm-b,.hm-final .hm-b,#hmFinal{width:100%}
  .hm-b{white-space:normal;text-wrap:balance;line-height:1.25;padding:12px 20px;overflow-wrap:anywhere}
  .hm-up{max-width:100%;box-sizing:border-box;gap:12px;padding-inline-start:12px;padding-inline-end:14px}
  .hm-up-ic{width:44px;height:44px}
}

/* Plans near the bottom (owner, 11 Oct): three plans with their prices, one action, the gift for parents */
.hm-pl-lede{margin:-6px 0 22px;max-width:60ch;color:var(--ink-2);font-size:17px;line-height:1.5}
.hm-pl-cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;margin:0;padding:0;list-style:none}
.hm-pl-c{display:flex;flex-direction:column;gap:8px;padding:22px 22px 24px;border-radius:var(--r3,20px);background:var(--surface);box-shadow:var(--shadow)}
.hm-pl-c h3{margin:0;font:700 21px/1.2 var(--f-display);color:var(--ink)}
.hm-pl-plus{box-shadow:var(--shadow),inset 0 0 0 2px var(--study)}
.hm-pl-pr{margin:0;color:var(--ink-2);font-size:15px}
.hm-pl-pr b{font:700 26px/1.1 var(--f-display);color:var(--ink)}
.hm-pl-pr small{display:block;margin-top:3px;font-size:14px;color:var(--ink-3)}
.hm-pl-l{margin:4px 0 0;color:var(--ink-2);font-size:15.5px;line-height:1.5}
.hm-pl-go{display:flex;flex-wrap:wrap;align-items:center;gap:14px 24px;margin:24px 0 0}
@media (max-width:760px){.hm-pl-cards{grid-template-columns:minmax(0,1fr)}}
@media (max-width:480px){.hm-pl-go .hm-b{width:100%}}


/* ---- The app home (html.bl-app; home/v2.php #blAppHome, 12 Oct 2026): it takes the page's place in the installed app */
html.bl-app body.hm main:has(> #blAppHome) > :not(#blAppHome){display:none!important}
.bl-ah{padding:18px 0 28px}
.bl-ah .wrap{display:grid;gap:14px;max-width:640px}
.bl-ah-h{margin:4px 0 2px;font:700 26px/1.2 var(--f-display);color:var(--ink)}
.bl-ah .hm-resume{margin:0}
.bl-ah-go{display:flex;align-items:center;justify-content:center;min-height:52px;padding:0 20px;border-radius:999px;background:var(--study-btn);color:var(--on-study-btn);font:700 17px/1.1 var(--f-body);text-decoration:none;box-shadow:none}
.bl-ah-go.is-alt{background:var(--btn-2);color:var(--ink);border:2px solid var(--btn-2-edge);box-shadow:none}
.bl-ah-go:active{transform:scale(.98);box-shadow:none}
.bl-ah-stats{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.bl-ah-stat{display:grid;gap:2px;padding:14px 16px;min-height:76px;background:var(--surface);border:1px solid var(--rule);border-radius:18px;color:var(--ink);text-decoration:none}
.bl-ah-stat b{font:700 28px/1 var(--f-display);font-variant-numeric:tabular-nums}
.bl-ah-stat span{color:var(--ink-2);font-size:14.5px}
.bl-ah-sec{display:grid;gap:8px}
.bl-ah-sec[hidden]{display:none}
.bl-ah-sec h2{margin:10px 0 0;font:700 17px/1.3 var(--f-body);color:var(--ink)}
.bl-ah-list,.bl-ah-tools{list-style:none;margin:0;padding:0;display:grid;gap:8px}
.bl-ah-list a{display:flex;align-items:center;min-height:52px;padding:0 16px;background:var(--surface);border:1px solid var(--rule);border-radius:14px;color:var(--ink);font-weight:650;text-decoration:none}
.bl-ah-tools{grid-template-columns:1fr 1fr}
.bl-ah-tools a{display:flex;align-items:center;gap:10px;min-height:56px;padding:8px 12px;background:var(--surface);border:1px solid var(--rule);border-radius:14px;color:var(--ink);font-weight:650;font-size:15px;line-height:1.25;text-decoration:none}
.bl-ah-ic{flex:none;display:grid;place-items:center;width:36px;height:36px;border-radius:10px;background:var(--study-tint);color:var(--study-ink)}
.bl-ah-hi{display:grid;justify-items:center;text-align:center;gap:10px;padding:18px 0 6px}
.bl-ah-hi img{border-radius:18px}
.bl-ah-in{display:grid;gap:10px}
.bl-ah-link{display:flex;align-items:center;justify-content:center;min-height:48px;color:var(--study-ink);font-weight:700;text-decoration:underline;text-underline-offset:3px}

/* the demo's label (owner, 12 Oct): "Try a question" names the block; the prompt says what to do */
.hm-ph-app.ln-play .lq-title.hm-ph-label{font:700 15px/1.3 var(--f-body);letter-spacing:0;color:var(--study-ink);margin:0 0 6px}
