/* Batch kids card player — mobile-first (390px), file:// safe */
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
:root {
  --bg: #FFF6E9; --card: #FFFFFF; --ink: #3A3042; --sub: #8a7a64;
  --coral: #FF6B6B; --teal: #2EC4B6; --sun: #FFBF3F; --purple: #9B5DE5;
  --blue: #4CC9F0; --green: #57CC99; --soft: #F2E4CE;
  /* Little Lamb sunrise brand accents (replace coral in brand/decorative roles) */
  --gold: #F0A62B; --gold-deep: #D28E1A; --sky: #58B7E8; --sky-deep: #3D95C4;
  --good: #57CC99; --good-deep: #3da877; --bad: #FF6B6B; --bad-deep: #d94f4f;
  --radius: 20px;
}
html, body { margin: 0; padding: 0; background: var(--bg); color: var(--ink);
  font-family: ui-rounded, -apple-system, "Segoe UI", system-ui, sans-serif; }
#app { max-width: 480px; margin: 0 auto; min-height: 100dvh; display: flex; flex-direction: column;
  padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom); }

button { font: inherit; color: inherit; cursor: pointer; border: 0; background: none; }
button:disabled { opacity: .45; cursor: default; }
img, svg { max-width: 100%; display: block; }

/* ---------- chunky button ---------- */
.btn { display: block; width: 100%; padding: 16px 20px; border-radius: 18px;
  font-size: 19px; font-weight: 800; text-align: center; color: #fff;
  background: var(--teal); box-shadow: 0 5px 0 #1e9c8f; transition: transform .06s, box-shadow .06s; }
.btn:active:not(:disabled) { transform: translateY(4px); box-shadow: 0 1px 0 #1e9c8f; }
.btn.alt { background: var(--purple); box-shadow: 0 5px 0 #7a41c4; }
.btn.good { background: var(--good); box-shadow: 0 5px 0 var(--good-deep); }
.btn.bad { background: var(--bad); box-shadow: 0 5px 0 var(--bad-deep); }

/* ---------- home ---------- */
.home { padding: 20px 18px 40px; }
/* topbar wraps (2026-07-22, John): chips must NEVER hide behind a scroll a kid
   won't find — when they don't fit beside the brand they wrap to a second row. */
.topbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 12px; margin-bottom: 14px; }
.brand { font-size: 22px; font-weight: 900; letter-spacing: -.5px; flex-shrink: 0; }
.brand em { color: var(--gold); font-style: normal; }
/* topbar right cluster (avatar + ring + ⚙️ + 🏆 + streak + XP) wraps onto extra
   rows on narrow phones — everything stays visible, nothing hides behind a scroll. */
.stats { display: flex; flex-wrap: wrap; gap: 10px; min-width: 0; flex: 1;
  justify-content: flex-end; align-items: center; }
.stats > * { flex-shrink: 0; }
.pill { background: #fff; border-radius: 999px; padding: 7px 13px; font-weight: 800; font-size: 14px;
  box-shadow: 0 2px 0 var(--soft); flex-shrink: 0; white-space: nowrap; }
.coursehead { background: linear-gradient(135deg, #FFE7C2, #CDEBFB); border-radius: 24px;
  padding: 20px; margin-bottom: 26px; }
.coursehead .kicker { font-size: 13px; font-weight: 800; color: var(--gold-deep); text-transform: uppercase; letter-spacing: 1px; }
.coursehead h1 { margin: 4px 0 6px; font-size: 28px; }
.coursehead p { margin: 0; color: var(--sub); font-weight: 600; }
.coverart { border-radius: 18px; margin-top: 14px; }

/* unit list (multi-course home) */
.units { display: flex; flex-direction: column; gap: 16px; }
.unitcard { display: block; width: 100%; background: var(--card); border-radius: 24px;
  padding: 0; text-align: left; box-shadow: 0 5px 0 var(--soft); overflow: hidden;
  transition: transform .06s, box-shadow .06s; }
.unitcard:active:not(:disabled) { transform: translateY(3px); box-shadow: 0 2px 0 var(--soft); }
.unitcard.locked { opacity: .55; }
.unit-cover { width: 100%; height: 110px; object-fit: cover; }
.unit-row { display: flex; align-items: center; gap: 12px; padding: 14px 16px; }
.unit-meta { flex: 1; min-width: 0; }
.unit-kicker { font-size: 16px; font-weight: 900; color: var(--ink); }
.unit-tagline { margin: 3px 0 6px; font-size: 14px; color: var(--sub); font-weight: 600; line-height: 1.3; }
.unit-progress { font-size: 13px; font-weight: 800; color: var(--teal); }
.unitcard.locked .unit-progress { color: #b3a488; }
.unit-badge { width: 44px; height: 44px; min-width: 44px; border-radius: 50%; display: grid;
  place-items: center; font-size: 22px; font-weight: 900; }
.unit-badge.done { background: var(--sun); color: #fff; box-shadow: 0 4px 0 #d99c12; }
.unit-badge.locked { background: var(--soft); }

/* back to units */
.backbtn { display: inline-block; margin-bottom: 8px; padding: 7px 14px; border-radius: 999px;
  background: #fff; font-size: 14px; font-weight: 800; color: var(--ink);
  box-shadow: 0 3px 0 var(--soft); }
.backbtn:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--soft); }

/* lesson path */
.path { display: flex; flex-direction: column; gap: 14px; }
.node { display: flex; align-items: center; gap: 14px; background: var(--card);
  border-radius: var(--radius); padding: 14px 16px; box-shadow: 0 4px 0 var(--soft);
  text-align: left; width: 100%; }
.node:nth-child(odd) { margin-left: 14px; }
.node:nth-child(even) { margin-right: 14px; }
.node .bubble { width: 54px; height: 54px; min-width: 54px; border-radius: 50%; display: grid; place-items: center;
  font-size: 24px; font-weight: 900; color: #fff; background: var(--teal); box-shadow: 0 4px 0 #1e9c8f; }
.node.locked { opacity: .55; }
.node.locked .bubble { background: #cdbfa8; box-shadow: 0 4px 0 #b3a488; }
.node.done .bubble { background: var(--sun); box-shadow: 0 4px 0 #d99c12; }
.trackhead { margin: 22px 4px 2px; }
.trackhead:first-child { margin-top: 4px; }
.trackhead-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.trackhead-title { font-size: 20px; font-weight: 900; letter-spacing: -.3px; }
.trackhead-count { font-size: 13px; font-weight: 800; color: var(--sub); flex: none; }
.trackhead.done .trackhead-count { color: var(--good-deep); }
.trackbar { height: 6px; background: var(--soft); border-radius: 999px; overflow: hidden; margin-top: 6px; }
.trackbar > i { display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--teal), var(--sun)); }
.trackhead.done .trackbar > i { background: linear-gradient(90deg, var(--good), var(--good-deep)); }
@media (prefers-reduced-motion: no-preference) {
  .trackbar > i { transition: width .7s cubic-bezier(.22,1,.36,1); }
}
.node.review { background: linear-gradient(135deg, #F3E8FF, #E8F4FF); margin-bottom: 14px; }
.node.review .bubble { background: var(--purple); box-shadow: 0 4px 0 #7a41c4; font-size: 22px; }
.node .meta { flex: 1; min-width: 0; }
.node .meta h3 { margin: 0 0 2px; font-size: 17px; }
.node .meta span { font-size: 13px; color: var(--sub); font-weight: 700; }
.node .node-thumb { width: 48px; height: 48px; min-width: 48px; border-radius: 12px; object-fit: cover;
  box-shadow: 0 2px 0 var(--soft); margin-left: 2px; }
.node.locked .node-thumb { filter: grayscale(.55); opacity: .7; }

/* ---------- player ---------- */
/* Fill #app's content box (which already subtracts the safe-area insets) instead of
   forcing a 2nd full 100dvh — that double-count pushed the footer/Continue button below
   the home-indicator on notched iPhones (reported on iPhone 16 Pro 2026-06-19). */
.player { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.phead { display: flex; align-items: center; gap: 12px; padding: 14px 16px 6px; }
.quit { font-size: 26px; font-weight: 900; color: #c9b793; padding: 4px 8px; }
.backpg { font-size: 30px; font-weight: 900; color: #c9b793; padding: 2px 10px; line-height: 1;
  min-width: 44px; min-height: 36px; }
.backpg:active { color: var(--ink, #5b4a2f); }
.progress { flex: 1; height: 16px; background: var(--soft); border-radius: 999px; overflow: hidden; }
.progress i { display: block; height: 100%; background: var(--green); border-radius: 999px;
  transition: width .35s cubic-bezier(.22,1.2,.36,1); }
.stage { flex: 1; padding: 14px 18px 12px; display: flex; flex-direction: column; gap: 14px; overflow-y: auto; }
.prompt { font-size: 21px; font-weight: 800; margin: 0; line-height: 1.3; }
.concept-text { font-size: 22px; font-weight: 700; line-height: 1.35; margin: 0; }
.visual { background: var(--card); border-radius: var(--radius); box-shadow: 0 4px 0 var(--soft); overflow: hidden; }
.visual img { width: 100%; }
.visual svg { width: 100%; height: auto; display: block; }
/* Calm-mode hook (player.js inlineSceneArt): scene SVGs are injected inline so the
   in-app Calm toggle can reach their CSS animations, which an <img>-embedded SVG
   never exposes. */
svg.ll-calm, svg.ll-calm * { animation: none !important; transition: none !important; }

/* choice */
.opts { display: flex; flex-direction: column; gap: 12px; }
.opt { background: var(--card); border: 3px solid var(--soft); border-radius: 18px; padding: 15px 16px;
  font-size: 18px; font-weight: 700; text-align: left; box-shadow: 0 4px 0 var(--soft); }
.opt.sel { border-color: var(--blue); background: #ECFAFF; box-shadow: 0 4px 0 var(--blue); }
.opt.correct { border-color: var(--good); background: #EAFBF2; box-shadow: 0 4px 0 var(--good); }
.opt.wrong { border-color: var(--bad); background: #FFF0F0; box-shadow: 0 4px 0 var(--bad); }

/* sort */
.sort-item { background: var(--card); border-radius: 22px; padding: 26px 18px; text-align: center;
  box-shadow: 0 5px 0 var(--soft); font-size: 22px; font-weight: 800; }
.sort-item .icon { font-size: 56px; display: block; margin-bottom: 8px; }
.sort-count { text-align: center; color: var(--sub); font-weight: 800; font-size: 14px; }
.buckets { display: flex; gap: 12px; }
.bucket { flex: 1; padding: 18px 10px; border-radius: 18px; font-size: 17px; font-weight: 800; color: #fff; }
.bucket.b0 { background: var(--teal); box-shadow: 0 5px 0 #1e9c8f; }
.bucket.b1 { background: var(--purple); box-shadow: 0 5px 0 #7a41c4; }
.bucket:active { transform: translateY(4px); box-shadow: none; }
.sort-item.flash-good { outline: 4px solid var(--good); }
.sort-item.flash-bad { outline: 4px solid var(--bad); animation: shake .35s; }
@keyframes shake { 25% { transform: translateX(-7px);} 75% { transform: translateX(7px);} }

/* fill blank */
.sentence { font-size: 23px; font-weight: 800; line-height: 1.5; }
.gap { display: inline-block; min-width: 110px; border-bottom: 4px dashed #cdbfa8; text-align: center;
  color: var(--purple); padding: 0 6px; }
.bank { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
.chip { background: var(--card); border-radius: 14px; padding: 12px 18px; font-size: 18px; font-weight: 800;
  box-shadow: 0 4px 0 var(--soft); border: 3px solid var(--soft); }
.chip.used { opacity: .35; }

/* tap diagram */
.tapwrap { position: relative; }
.hotspot { position: absolute; background: transparent; border-radius: 12px; }
.hotspot.reveal-good { outline: 4px solid var(--good); background: rgba(87,204,153,.18); }
.hotspot.reveal-bad { outline: 4px solid var(--bad); background: rgba(255,107,107,.18); }

/* order steps */
.slots { display: flex; flex-direction: column; gap: 10px; min-height: 60px; }
.slot { background: #FFFDF8; border: 3px dashed #e3d5bb; border-radius: 16px; padding: 13px 14px;
  font-size: 17px; font-weight: 800; display: flex; gap: 10px; align-items: center; }
.slot .num { width: 28px; height: 28px; min-width: 28px; border-radius: 50%; background: var(--sun); color: #fff;
  display: grid; place-items: center; font-size: 15px; }
.pool { display: flex; flex-direction: column; gap: 10px; }

/* speed round */
.speedtrack { height: 14px; background: var(--soft); border-radius: 999px; overflow: hidden; }
.speedfill { display: block; height: 100%; width: 100%; background: var(--sun); border-radius: 999px;
  transition-property: width; transition-timing-function: linear; }
.speed-card { background: var(--card); border-radius: 22px; padding: 30px 18px; text-align: center;
  box-shadow: 0 5px 0 var(--soft); font-size: 22px; font-weight: 800; line-height: 1.35; }
.speed-card.flash-good { outline: 4px solid var(--good); }
.speed-card.flash-bad { outline: 4px solid var(--bad); animation: shake .35s; }
.tfrow { display: flex; gap: 12px; }
.tf { flex: 1; padding: 20px 10px; border-radius: 18px; font-size: 20px; font-weight: 900; color: #fff; }
.tf-true { background: var(--teal); box-shadow: 0 5px 0 #1e9c8f; }
.tf-false { background: var(--coral); box-shadow: 0 5px 0 var(--bad-deep); }
.tf:active { transform: translateY(4px); box-shadow: none; }
.tf.tf-reveal { outline: 4px solid var(--sun); }

/* feedback sheet + footer */
.pfoot { padding: 12px 18px calc(16px + env(safe-area-inset-bottom)); background: var(--bg); }
.sheet { border-radius: 22px 22px 0 0; padding: 16px 18px 8px; margin: 0 -18px 10px; }
.sheet.good { background: #EAFBF2; color: var(--good-deep); }
.sheet.bad { background: #FFF0F0; color: var(--bad-deep); }
.sheet h4 { margin: 0 0 4px; font-size: 20px; }
.sheet p { margin: 0 0 8px; font-weight: 700; color: inherit; }

/* win screen */
.winwrap { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 30px 26px; gap: 12px; }
.winwrap .burst { font-size: 84px; animation: pop .5s cubic-bezier(.22,1.6,.36,1); }
@keyframes pop { from { transform: scale(.2); } }
.winwrap h2 { margin: 0; font-size: 30px; }
.winwrap .recap { color: var(--sub); font-weight: 700; font-size: 18px; line-height: 1.4; }
.xpchip { background: var(--sun); color: #fff; font-weight: 900; font-size: 22px;
  padding: 12px 26px; border-radius: 999px; box-shadow: 0 5px 0 #d99c12; }

@media (min-width: 500px) {
  #app { border-left: 1px solid #f0e3cc; border-right: 1px solid #f0e3cc; }
}

/* ============================================================
   JUICE / ENGAGEMENT LAYER — 2026-06-18
   Animations + mascot + combo toast + badges + daily ring.
   All motion is gated behind prefers-reduced-motion.
   ============================================================ */

/* topbar: sound toggle + daily-goal ring */
.stats { align-items: center; }
.sound-toggle { background: #fff; border-radius: 999px; padding: 7px 11px; font-size: 16px;
  line-height: 1; box-shadow: 0 2px 0 var(--soft); flex-shrink: 0; }
.sound-toggle:active { transform: translateY(2px); box-shadow: none; }
.daily-ring { position: relative; width: 40px; height: 40px; flex-shrink: 0; }
.daily-ring svg { width: 40px; height: 40px; display: block; transform: rotate(-90deg); }
.daily-ring .dr-num { position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 13px; font-weight: 900; color: var(--ink); }
.daily-ring.hit .dr-num { color: var(--good-deep); }
.dr-arc { transition: stroke-dashoffset .6s cubic-bezier(.22,1,.36,1); }

/* badges shelf on home */
.shelf-head { font-size: 14px; font-weight: 900; color: var(--sub); margin: 2px 4px 6px;
  text-transform: uppercase; letter-spacing: .5px; }
.badges-shelf { display: flex; gap: 10px; overflow-x: auto; padding: 2px 2px 10px;
  margin-bottom: 12px; -webkit-overflow-scrolling: touch; }
.badge-chip { min-width: 66px; height: 70px; border-radius: 18px; background: #fff;
  box-shadow: 0 3px 0 var(--soft); display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 3px; }
.badge-chip .bi { font-size: 28px; line-height: 1; }
.badge-chip .bl { font-size: 9px; font-weight: 800; color: var(--sub); text-align: center;
  padding: 0 4px; line-height: 1.1; }
.badge-chip.locked { background: #FBF4E6; box-shadow: 0 3px 0 #ece0c8; }
.badge-chip.locked .bi { filter: grayscale(1); opacity: .35; }
.badge-chip.locked .bl { opacity: .5; }

/* sticker book shelf on home — a collection that reveals as lifetime XP climbs.
   Mirrors the badges shelf but with a teal tint so the two read as distinct. */
.stickers-shelf { display: flex; gap: 10px; overflow-x: auto; padding: 2px 2px 10px;
  margin-bottom: 12px; -webkit-overflow-scrolling: touch; }
.sticker-chip { min-width: 66px; height: 70px; border-radius: 18px; background: #F1FBF8;
  box-shadow: 0 3px 0 #c8ece5; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 3px; cursor: pointer; }
.sticker-chip .si { font-size: 28px; line-height: 1; }
.sticker-chip .sl { font-size: 9px; font-weight: 800; color: var(--sub); text-align: center;
  padding: 0 4px; line-height: 1.1; }
.sticker-chip.locked { background: #FBF4E6; box-shadow: 0 3px 0 #ece0c8; }
.sticker-chip.locked .si { opacity: .5; }
.sticker-chip.locked .sl { opacity: .55; letter-spacing: 1px; }
.sticker-chip:active { transform: scale(.94); }

/* mascot "Bo" */
.bo { width: 100%; height: auto; display: block; }
.win-mascot { width: 138px; margin: 0 auto; }
.sheet-help { font-size: 13.5px; background: rgba(255,255,255,.65); border-radius: 12px;
  padding: 6px 10px; margin-top: 6px !important; }
.sheet-mascot { width: 56px; min-width: 56px; }
.sheet.with-mascot { display: flex; align-items: center; gap: 12px; }
.sheet.with-mascot .sheet-body { flex: 1; min-width: 0; }
.sheet.with-mascot h4, .sheet.with-mascot p { margin: 0; }

/* combo + badge toast (transient, centred) */
.fx-toast { position: fixed; left: 50%; top: 16%; z-index: 9999; white-space: nowrap;
  transform: translate(-50%, -10px) scale(.85); opacity: 0; pointer-events: none;
  background: #fff; color: var(--ink); font-weight: 900; font-size: 21px;
  padding: 12px 22px; border-radius: 999px; box-shadow: 0 6px 0 rgba(58,48,66,.12);
  transition: opacity .22s ease, transform .3s cubic-bezier(.22,1.7,.36,1); }
.fx-toast.show { opacity: 1; transform: translate(-50%, 0) scale(1); }
.fx-toast.combo { background: #FFF0DE; color: #c9622e; }
.fx-toast.badge { background: #F1E8FF; color: var(--purple); font-size: 18px;
  display: flex; align-items: center; gap: 10px; }
.fx-toast.badge .bi { font-size: 30px; }
.fx-toast .small { display: block; font-size: 12px; font-weight: 800; opacity: .8; }

/* win-screen badge unlock row */
.badge-unlock { display: flex; align-items: center; gap: 12px; background: #F6EEFF;
  border-radius: 18px; padding: 12px 16px; box-shadow: 0 4px 0 #e3d2ff; width: 100%;
  max-width: 320px; }
.badge-unlock .bi { font-size: 34px; }
.badge-unlock .bt { font-size: 11px; font-weight: 900; color: var(--purple); text-transform: uppercase; letter-spacing: .5px; }
.badge-unlock .bn { font-size: 16px; font-weight: 900; color: var(--ink); }
/* sticker reveal row — a teal variant of the badge-unlock row */
.sticker-unlock { background: #E8FBF6; box-shadow: 0 4px 0 #c4ebe2; }
.sticker-unlock .bt { color: #1f9e90; }

/* ---- animations (gated on motion preference) ---- */
@media (prefers-reduced-motion: no-preference) {
  .stage { animation: cardIn .34s cubic-bezier(.22,1,.36,1); }
  @keyframes cardIn { from { opacity: 0; transform: translateY(16px); } }

  .sheet { animation: sheetUp .3s cubic-bezier(.22,1.3,.36,1); }
  @keyframes sheetUp { from { opacity: 0; transform: translateY(22px); } }

  .opt.correct { animation: optPop .5s cubic-bezier(.22,1.6,.36,1); }
  @keyframes optPop { 0% { transform: scale(1); } 38% { transform: scale(1.045); } 100% { transform: scale(1); } }

  .reveal-good { animation: goodPing .5s ease; }
  @keyframes goodPing { 0% { transform: scale(1); } 40% { transform: scale(1.12); } 100% { transform: scale(1); } }

  .xpchip { animation: pop .5s cubic-bezier(.22,1.6,.36,1); }

  .fx-pop { animation: fxPop .52s cubic-bezier(.22,1.7,.36,1); }
  @keyframes fxPop { 0% { transform: scale(1); } 34% { transform: scale(1.2); } 100% { transform: scale(1); } }

  .badge-unlock { animation: pop .45s cubic-bezier(.22,1.6,.36,1); }

  .win-mascot { animation: boBob 2.6s ease-in-out infinite; }
  @keyframes boBob { 0%,100% { transform: translateY(0) rotate(-2deg); } 50% { transform: translateY(-7px) rotate(2deg); } }

  .bo-cheer .bo-arm-l { animation: boArmL 1s ease-in-out infinite; transform-box: fill-box; transform-origin: 70% 30%; }
  .bo-cheer .bo-arm-r { animation: boArmR 1s ease-in-out infinite; transform-box: fill-box; transform-origin: 30% 30%; }
  @keyframes boArmL { 0%,100% { transform: rotate(0deg); } 50% { transform: rotate(-18deg); } }
  @keyframes boArmR { 0%,100% { transform: rotate(0deg); } 50% { transform: rotate(18deg); } }

  .badge-chip.justunlocked { animation: fxPop .6s cubic-bezier(.22,1.7,.36,1); }
}

@media (prefers-reduced-motion: reduce) {
  .fx-toast { transition: opacity .2s ease; }
}

/* ---- progression / levels ---- */
.levelbar { background: #fff; border-radius: 16px; box-shadow: 0 3px 0 var(--soft);
  padding: 10px 14px; margin-bottom: 14px; }
.lb-row { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 7px; }
.lb-title { font-size: 14px; font-weight: 900; color: var(--ink); }
.lb-next { font-size: 12px; font-weight: 800; color: var(--sub); }
.lb-track { height: 12px; background: var(--soft); border-radius: 999px; overflow: hidden; }
.lb-track i { display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--sun), var(--gold)); width: 0; }
@media (prefers-reduced-motion: no-preference) {
  .lb-track i { transition: width .7s cubic-bezier(.22,1,.36,1); }
}
/* level-up banner on the win screen */
.levelup { display: flex; align-items: center; gap: 12px; width: 100%; max-width: 320px;
  background: linear-gradient(135deg, #FFE9B8, #FFD0A8); border-radius: 18px;
  padding: 12px 16px; box-shadow: 0 4px 0 #e9c483; }
.levelup .lu-ic { font-size: 38px; }
.levelup .lu-k { font-size: 11px; font-weight: 900; color: #b9701a; text-transform: uppercase; letter-spacing: .5px; }
.levelup .lu-n { font-size: 18px; font-weight: 900; color: var(--ink); }
@media (prefers-reduced-motion: no-preference) {
  .levelup { animation: pop .5s cubic-bezier(.22,1.6,.36,1); }
}

/* finishing a whole track — bigger, rainbow celebration banner */
.trackdone { display: flex; align-items: center; gap: 14px; width: 100%; max-width: 340px;
  background: linear-gradient(135deg, #FFE9B8, #FFD0E0, #E8D6FF); border-radius: 20px;
  padding: 14px 16px; box-shadow: 0 5px 0 #e6c79a; }
.trackdone .td-ic { font-size: 46px; line-height: 1; }
.trackdone .td-k { font-size: 11px; font-weight: 900; color: var(--purple); text-transform: uppercase; letter-spacing: .6px; }
.trackdone .td-n { font-size: 21px; font-weight: 900; color: var(--ink); }
.trackdone .td-sub { font-size: 13px; font-weight: 800; color: var(--sub); }
@media (prefers-reduced-motion: no-preference) {
  .trackdone { animation: pop .55s cubic-bezier(.22,1.6,.36,1); }
}

/* ---- match_pairs card ---- */
.matchwrap { display: flex; gap: 12px; }
.mp-col { flex: 1; display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.mp-tile { background: var(--card); border: 3px solid var(--soft); border-radius: 16px;
  padding: 14px 8px; font-size: 17px; font-weight: 800; text-align: center;
  box-shadow: 0 4px 0 var(--soft); }
.mp-tile .mp-ic { display: block; font-size: 30px; margin-bottom: 3px; }
.mp-tile:active:not(:disabled) { transform: translateY(3px); box-shadow: 0 1px 0 var(--soft); }
.mp-left.sel { border-color: var(--blue); background: #ECFAFF; box-shadow: 0 4px 0 var(--blue); }
.mp-tile.matched { border-color: var(--good); background: #EAFBF2; box-shadow: 0 4px 0 var(--good); opacity: 1; }
.mp-tile.matched:disabled { opacity: .9; }
.mp-shake { animation: shake .35s; }

/* ---- read-aloud button + settings sheet ---- */
.readaloud { display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; border-radius: 50%; background: #fff; font-size: 22px;
  box-shadow: 0 3px 0 var(--soft); }
.readaloud:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--soft); }
.settings-overlay { position: fixed; inset: 0; z-index: 9999; background: rgba(58,48,66,.45);
  display: flex; align-items: center; justify-content: center; padding: 24px; }
.settings-card { background: var(--bg); border-radius: 24px; padding: 20px; width: 100%;
  max-width: 340px; box-shadow: 0 10px 0 rgba(0,0,0,.12); }
.settings-card h3 { margin: 2px 0 14px; font-size: 22px; }
.setrow { display: flex; align-items: center; justify-content: space-between; width: 100%;
  background: #fff; border-radius: 16px; padding: 14px 16px; margin-bottom: 10px;
  font-size: 17px; font-weight: 800; box-shadow: 0 3px 0 var(--soft); }
.toggle { width: 52px; height: 30px; border-radius: 999px; background: #d9ccb4; position: relative; flex: none; }
.toggle i { position: absolute; top: 3px; left: 3px; width: 24px; height: 24px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.2); }
.toggle.on { background: var(--good); }
.toggle.on i { left: 25px; }
.settings-card .btn { margin-top: 6px; }
@media (prefers-reduced-motion: no-preference) {
  .toggle, .toggle i { transition: background .18s, left .18s; }
  .settings-card { animation: pop .35s cubic-bezier(.22,1.5,.36,1); }
}

/* ---- badge detail sheet (tap a badge chip on a home shelf) ---- */
.badge-chip[data-badge] { cursor: pointer; }
.badge-card { text-align: center; max-width: 320px; }
.badge-card .badge-hero { font-size: 76px; line-height: 1; margin: 4px 0 2px; }
.badge-card .badge-hero.locked { filter: grayscale(1); opacity: .4; }
.badge-card .badge-name { margin: 6px 0 10px; font-size: 22px; }
.badge-status { display: inline-block; font-weight: 900; font-size: 14px; border-radius: 999px;
  padding: 5px 14px; margin-bottom: 12px; }
.badge-status.earned { background: rgba(87,204,153,.20); color: #2F8F5B; }
.badge-status.locked { background: #F1E7D4; color: #8a7c60; }
.badge-card .badge-how { color: var(--sub); font-size: 15px; font-weight: 700; line-height: 1.4;
  margin: 0 4px 16px; }
@media (prefers-reduced-motion: no-preference) {
  .badge-chip[data-badge]:active { transform: scale(.94); }
}

/* ---- home greeter (Bo) + perfect-lesson star ---- */
.greeter { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.greeter-bo { width: 60px; min-width: 60px; }
.greeter-bubble { position: relative; flex: 1; background: #fff; border-radius: 16px;
  padding: 12px 14px; font-size: 15px; font-weight: 800; color: var(--ink); box-shadow: 0 3px 0 var(--soft); }
.greeter-bubble::before { content: ""; position: absolute; left: -7px; top: 22px;
  border: 8px solid transparent; border-right-color: #fff; border-left: 0; }
.node.perfect .bubble { box-shadow: 0 4px 0 #d99c12; }
@media (prefers-reduced-motion: no-preference) {
  .greeter-bo { animation: boBob 3s ease-in-out infinite; }
}

/* ---- home streak chain ("don't break the chain") ---- */
.chaincard { background: #fff; border-radius: 16px; box-shadow: 0 3px 0 var(--soft);
  padding: 12px 14px; margin-bottom: 16px; }
.chaincard.risk { background: linear-gradient(135deg, #FFF1D9, #FFE2D0); box-shadow: 0 3px 0 #f0cda0; }
.chain-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.chain-flame { font-size: 26px; line-height: 1; flex: none; }
.chain-title { font-size: 15px; font-weight: 900; color: var(--ink); }
.chain-sub { font-size: 12.5px; font-weight: 800; color: var(--sub); }
.chaincard.risk .chain-sub { color: #c0682f; }
.chain-links { display: flex; justify-content: space-between; gap: 4px; }
.chain-link { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 0; }
.cl-dot { width: 30px; height: 30px; border-radius: 50%; display: flex; align-items: center;
  justify-content: center; font-size: 15px; background: var(--soft); color: transparent; }
.chain-link.lit .cl-dot { background: linear-gradient(135deg, var(--sun), var(--gold)); }
.chain-link.lit.froze .cl-dot { background: linear-gradient(135deg, #CFEFFF, var(--sky)); }
.chain-link.today .cl-dot { box-shadow: 0 0 0 3px rgba(255,191,63,.45); }
.chain-link.target .cl-dot { background: #fff; border: 2px dashed var(--gold-deep);
  color: var(--gold-deep); font-weight: 900; }
.cl-day { font-size: 10px; font-weight: 800; color: var(--sub); }
@media (prefers-reduced-motion: no-preference) {
  .chaincard.risk .chain-link.target .cl-dot { animation: chainPulse 1.4s ease-in-out infinite; }
}
@keyframes chainPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.12); } }

/* ---- first-run onboarding (Bo intro) ---- */
.onboard-overlay { position: fixed; inset: 0; z-index: 10000; background: rgba(58,48,66,.55);
  display: flex; align-items: center; justify-content: center; padding: 24px; }
.onboard-card { position: relative; background: var(--bg); border-radius: 26px;
  padding: 26px 22px 22px; width: 100%; max-width: 340px; text-align: center;
  box-shadow: 0 12px 0 rgba(0,0,0,.14); }
.onb-skip { position: absolute; top: 12px; right: 12px; font-size: 14px; font-weight: 800;
  color: var(--sub); padding: 6px 9px; border-radius: 12px; }
.onb-bo { width: 122px; margin: 2px auto 4px; }
.onb-bo .emoji { font-size: 84px; line-height: 1; }
.onb-title { margin: 4px 0 6px; font-size: 24px; font-weight: 900; color: var(--ink); }
.onb-body { margin: 0 6px 16px; font-size: 16px; font-weight: 700; line-height: 1.45; color: var(--ink); }
.onb-dots { display: flex; justify-content: center; gap: 7px; margin-bottom: 18px; }
.onb-dots i { width: 9px; height: 9px; border-radius: 50%; background: var(--soft); display: block; }
.onb-dots i.on { background: var(--gold); transform: scale(1.18); }
@media (prefers-reduced-motion: no-preference) {
  .onboard-card { animation: onbPop .4s cubic-bezier(.22,1.5,.36,1); }
  @keyframes onbPop { from { opacity: 0; transform: translateY(14px) scale(.96); } }
  .onb-bo { animation: boBob 3s ease-in-out infinite; }
  .onb-dots i { transition: background .2s, transform .2s; }
}

/* ============ accounts gate (js/auth-ui.js) — optional, gate OFF by default ============ */
.authwrap { flex: 1 1 auto; min-height: 0; display: flex; align-items: center; justify-content: center;
  padding: 22px 16px; }
.authcard { width: 100%; max-width: 420px; background: var(--card); border-radius: 26px;
  padding: 22px 20px 24px; box-shadow: 0 6px 0 var(--soft); }
.authlogo { display: flex; justify-content: center; margin-bottom: 6px; }
.authlogo svg { width: 104px; height: 104px; }
.auth-emoji { font-size: 78px; line-height: 1; }
.authtitle { margin: 4px 0 4px; text-align: center; font-size: 27px; font-weight: 900; }
.authsub { margin: 0 0 16px; text-align: center; color: var(--sub); font-weight: 700; line-height: 1.4; }
.authtabs { display: flex; gap: 8px; background: var(--soft); border-radius: 999px; padding: 5px; margin-bottom: 16px; }
.authtab { flex: 1; padding: 10px; border-radius: 999px; font-weight: 800; color: var(--sub); }
.authtab.on { background: #fff; color: var(--ink); box-shadow: 0 2px 0 rgba(0,0,0,.06); }
.authform { display: flex; flex-direction: column; }
.authlabel { font-size: 13px; font-weight: 800; color: var(--sub); margin: 10px 2px 5px; }
.authlabel small { font-weight: 700; opacity: .8; }
.authinput { width: 100%; padding: 14px 15px; border-radius: 14px; font-size: 16px; font-weight: 700;
  color: var(--ink); background: #FFFDF8; border: 2px solid var(--soft); }
.authinput:focus { outline: none; border-color: var(--teal); }
.authcheck { display: flex; gap: 9px; align-items: flex-start; margin: 12px 2px 2px;
  font-size: 13px; font-weight: 700; color: var(--ink); line-height: 1.35; }
.authcheck input { width: 20px; height: 20px; margin-top: 1px; accent-color: var(--teal); }
.autherr { color: var(--bad-deep); font-weight: 800; font-size: 14px; min-height: 18px; margin: 8px 2px 0; }
.authbtn { display: block; width: 100%; margin-top: 14px; padding: 15px 18px; border-radius: 16px;
  font-size: 18px; font-weight: 800; text-align: center; color: #fff;
  background: var(--teal); box-shadow: 0 5px 0 #1e9c8f; transition: transform .06s, box-shadow .06s; }
.authbtn:active:not(:disabled) { transform: translateY(4px); box-shadow: 0 1px 0 #1e9c8f; }
.authbtn.google { background: #fff; color: var(--ink); border: 2px solid var(--soft); box-shadow: 0 5px 0 var(--soft); }
.authbtn.google:active:not(:disabled) { transform: translateY(4px); box-shadow: 0 1px 0 var(--soft); }
.authdivider { display: flex; align-items: center; gap: 10px; margin: 16px 2px 4px; color: var(--sub); font-weight: 800; font-size: 13px; }
.authdivider::before, .authdivider::after { content: ""; flex: 1; height: 2px; background: var(--soft); }
.authnote { margin: 14px 4px 0; text-align: center; font-size: 12.5px; font-weight: 700; color: var(--sub); line-height: 1.4; }
.authrowtop { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; gap: 10px; }
.authmini { font-size: 12.5px; font-weight: 800; color: var(--sub); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.authlink { font-size: 13px; font-weight: 800; color: var(--sky-deep); padding: 4px 6px; }

/* kid list + add player */
.kidlist { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.kidrow { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  background: #FFFDF8; border: 2px solid var(--soft); border-radius: 18px; padding: 12px 14px;
  transition: transform .06s, box-shadow .06s; box-shadow: 0 4px 0 var(--soft); }
.kidrow:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--soft); }
.kidav { font-size: 34px; line-height: 1; }
.kidname { flex: 1; font-weight: 900; font-size: 17px; display: flex; flex-direction: column; }
.kidname small { font-weight: 700; font-size: 12.5px; color: var(--sub); }
.kidxp { font-weight: 800; font-size: 13px; color: var(--teal); }
.addkid { border-top: 2px dashed var(--soft); margin-top: 4px; padding-top: 10px; }
.avatarpick { display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px; }
.avataropt { font-size: 25px; padding: 6px 0; border-radius: 12px; background: #FFFDF8; border: 2px solid transparent; }
.avataropt.sel { border-color: var(--teal); background: #E8FAF7; }
.unamecheck { min-height: 18px; font-size: 13px; font-weight: 800; margin: 6px 2px 0; color: var(--sub); }
.unamecheck.ok { color: var(--good-deep); }
.unamecheck.bad { color: var(--bad-deep); }

/* who's playing */
.pickgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.pickbtn { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 18px 10px;
  background: #FFFDF8; border: 2px solid var(--soft); border-radius: 20px; box-shadow: 0 5px 0 var(--soft);
  transition: transform .06s, box-shadow .06s; }
.pickbtn:active { transform: translateY(4px); box-shadow: 0 1px 0 var(--soft); }
.pickav { font-size: 46px; line-height: 1; }
.pickname { font-weight: 900; font-size: 16px; }
.pickxp { font-weight: 800; font-size: 12.5px; color: var(--teal); }
.pickbtn.add { justify-content: center; color: var(--sub); border-style: dashed; }
.pickbtn.add .pickav { color: var(--teal); }

/* leaderboard (Phase 2) */
.lbwrap { padding: 18px 16px 40px; }
.lbhead { margin-bottom: 14px; }
.lbtitle { margin: 8px 0 2px; font-size: 26px; font-weight: 900; }
.lbsub { margin: 0; color: var(--sub); font-weight: 700; font-size: 14px; }
.lblist { display: flex; flex-direction: column; gap: 8px; }
.lbmsg { color: var(--sub); font-weight: 700; text-align: center; padding: 24px 8px; }
.lbrow { display: flex; align-items: center; gap: 12px; background: var(--card); border-radius: 16px;
  padding: 12px 14px; box-shadow: 0 3px 0 var(--soft); }
.lbrow.me { background: #E8FAF7; box-shadow: 0 3px 0 #b8ece4; }
.lbrank { width: 34px; font-weight: 900; font-size: 17px; text-align: center; }
.lbav { font-size: 28px; line-height: 1; }
.lbname { flex: 1; font-weight: 800; font-size: 16px; }
.lbname small { color: var(--teal); font-weight: 800; font-size: 12px; }
.lbxp { font-weight: 900; font-size: 15px; color: var(--teal); }
.lbxp::after { content: " XP"; font-size: 11px; font-weight: 800; color: var(--sub); }

/* ---- summer tournament (Phase 3) — optional layer, only shows when accounts are ON ---- */
.tbanner { border-radius: 18px; padding: 13px 15px; margin-bottom: 14px; box-shadow: 0 4px 0 var(--soft); }
.tbanner.t-pre { background: linear-gradient(135deg, #FFF1D9, #FFE2D0); box-shadow: 0 4px 0 #f0cda0; }
.tbanner.t-active { background: linear-gradient(135deg, #FFEDD6, #FFE0E0); box-shadow: 0 4px 0 #f3c9b0; }
.tbanner.t-ended { background: linear-gradient(135deg, #EDE3FF, #E0F4FF); box-shadow: 0 4px 0 #cdb9ee; }
.tbmsg { font-size: 15px; font-weight: 800; color: var(--ink); line-height: 1.3; }
.tbmsg b { font-weight: 900; }
.tbar { height: 9px; border-radius: 999px; background: rgba(255,255,255,.65); margin: 9px 0 2px; overflow: hidden; }
.tbar i { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--sun), var(--gold)); }
.tbinfo { display: inline-block; margin-top: 8px; font-size: 13px; font-weight: 900; color: var(--purple);
  background: rgba(255,255,255,.7); border-radius: 999px; padding: 5px 12px; box-shadow: 0 2px 0 var(--soft); }
.tbinfo:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--soft); }

/* top-3 podium (shown on the final/ended board) */
.podium { display: grid; grid-template-columns: 1fr 1fr 1fr; align-items: end; gap: 8px; margin-bottom: 16px; }
.pod { background: var(--card); border-radius: 16px 16px 0 0; padding: 12px 6px 8px; text-align: center; box-shadow: 0 3px 0 var(--soft); }
.pod-1 { padding-top: 22px; background: linear-gradient(180deg, #FFF6DD, #fff); box-shadow: 0 3px 0 #f0d999; }
.pod-2 { padding-top: 14px; }
.pod-3 { padding-top: 8px; }
.pod-empty { background: #FBF4E6; box-shadow: none; min-height: 84px; }
.podmedal { font-size: 26px; line-height: 1; }
.podav { font-size: 34px; line-height: 1; margin: 2px 0; }
.podname { font-weight: 900; font-size: 14px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.podxp { font-weight: 800; font-size: 12px; color: var(--teal); }
.podbase { margin-top: 6px; font-weight: 900; font-size: 16px; color: var(--sub); }

/* rules / prize sheet (mirrors the settings + onboarding overlays) */
.tsheet-overlay { position: fixed; inset: 0; z-index: 9999; background: rgba(58,48,66,.45);
  display: flex; align-items: center; justify-content: center; padding: 24px; }
.tsheet-card { position: relative; background: var(--bg); border-radius: 24px; padding: 22px 20px 18px;
  width: 100%; max-width: 340px; box-shadow: 0 10px 0 rgba(0,0,0,.12); }
.trules h2 { margin: 2px 0 10px; font-size: 22px; }
.trintro { margin: 0 0 12px; font-size: 15px; font-weight: 700; color: var(--ink); line-height: 1.4; }
.trlist { list-style: none; padding: 0; margin: 0 0 16px; display: flex; flex-direction: column; gap: 9px; }
.trlist li { background: #fff; border-radius: 14px; padding: 10px 13px; font-size: 14.5px; font-weight: 700;
  color: var(--ink); line-height: 1.35; box-shadow: 0 3px 0 var(--soft); }
.trlist li b { font-weight: 900; }
.trclose { width: 100%; padding: 13px; border-radius: 16px; background: var(--sky); color: #fff;
  font-size: 17px; font-weight: 900; box-shadow: 0 4px 0 var(--sky-deep); }
.trclose:active { transform: translateY(3px); box-shadow: 0 1px 0 var(--sky-deep); }
@media (prefers-reduced-motion: no-preference) {
  .tsheet-card { animation: pop .35s cubic-bezier(.22,1.5,.36,1); }
}

/* ============================================================
   ✨ PREMIUM POLISH PASS — 2026-06-24 (launch eve)
   Depth, tactile finish, and entrance motion. All additive +
   file://-safe (gradients/shadows only, no url()/defs) and gated
   on prefers-reduced-motion. Sits at the END of the cascade so it
   refines the base styles above without changing any markup.
   Nothing here touches scoring/auth/gate — pure visual lift.
   ============================================================ */

/* --- ambient background glow: soft brand-colour light warms the flat
   cream so the app reads as dimensional. Painted into the body background
   itself (a fixed pseudo-layer hides behind the body canvas), attachment
   fixed so it stays put while the page scrolls. --- */
body {
  background:
    radial-gradient(760px 500px at 6% -8%, rgba(255,191,63,.32), transparent 60%),
    radial-gradient(700px 540px at 106% 3%, rgba(88,183,232,.24), transparent 60%),
    radial-gradient(860px 640px at 50% 114%, rgba(155,93,229,.18), transparent 64%),
    var(--bg);
  background-attachment: fixed;
}

/* --- floating surfaces: keep the chunky hard offset shadow, add a soft
   ambient shadow beneath so cards lift off the page (premium depth). --- */
.unitcard { box-shadow: 0 5px 0 var(--soft), 0 18px 30px -12px rgba(58,48,66,.32); }
.unitcard:active:not(:disabled) { box-shadow: 0 2px 0 var(--soft), 0 9px 16px -9px rgba(58,48,66,.30); }
.coursehead { box-shadow: 0 18px 34px -16px rgba(240,166,43,.42); }
.levelbar, .chaincard, .greeter-bubble,
.badge-chip, .sticker-chip { box-shadow: 0 3px 0 var(--soft), 0 11px 20px -10px rgba(58,48,66,.22); }
.node { box-shadow: 0 4px 0 var(--soft), 0 14px 22px -12px rgba(58,48,66,.24); }
.visual { box-shadow: 0 4px 0 var(--soft), 0 16px 26px -14px rgba(58,48,66,.20); }
.pill, .sound-toggle { box-shadow: 0 2px 0 var(--soft), 0 6px 12px -6px rgba(58,48,66,.22); }

/* --- glossy candy buttons: a top inner highlight turns the flat colour
   into a rounded, 3-D sheen; the hard colour shadow underneath stays. --- */
.btn { box-shadow: inset 0 2px 0 rgba(255,255,255,.32), 0 5px 0 #1e9c8f; }
.btn.alt { box-shadow: inset 0 2px 0 rgba(255,255,255,.32), 0 5px 0 #7a41c4; }
.btn.good { box-shadow: inset 0 2px 0 rgba(255,255,255,.32), 0 5px 0 var(--good-deep); }
.btn.bad { box-shadow: inset 0 2px 0 rgba(255,255,255,.32), 0 5px 0 var(--bad-deep); }
.btn:active:not(:disabled) { box-shadow: inset 0 2px 0 rgba(255,255,255,.22), 0 1px 0 #1e9c8f; }
.tf-true { box-shadow: inset 0 2px 0 rgba(255,255,255,.32), 0 5px 0 #1e9c8f; }
.tf-false { box-shadow: inset 0 2px 0 rgba(255,255,255,.32), 0 5px 0 var(--bad-deep); }
.bucket.b0 { box-shadow: inset 0 2px 0 rgba(255,255,255,.30), 0 5px 0 #1e9c8f; }
.bucket.b1 { box-shadow: inset 0 2px 0 rgba(255,255,255,.30), 0 5px 0 #7a41c4; }

/* --- tactile press: tappable tiles that lacked it now give under the finger --- */
@media (prefers-reduced-motion: no-preference) {
  .opt, .chip, .node, .backbtn { transition: transform .08s ease, box-shadow .08s ease; }
  .opt:active:not(.correct):not(.wrong):not(.sel) { transform: translateY(3px); box-shadow: 0 1px 0 var(--soft); }
  .chip:not(.used):active { transform: translateY(2px) scale(.97); box-shadow: 0 1px 0 var(--soft); }
  .node:not(.locked):active { transform: translateY(3px); }
  .node:not(.locked):active .bubble { transform: translateY(1px); }
}

/* --- entrance cascade: home blocks + cards rise in with a quick, gentle
   stagger. Resting state is fully visible (opacity 1, no transform), and
   the whole thing is gated — so content never hides if motion is reduced
   or the animation is skipped. Fast (<.7s total) so re-renders stay snappy. --- */
@media (prefers-reduced-motion: no-preference) {
  @keyframes riseIn { from { opacity: 0; transform: translateY(15px); } }
  .home > *:not(.topbar):not(.units):not(.path) { animation: riseIn .5s cubic-bezier(.22,1,.36,1) both; }
  .home > *:nth-child(2) { animation-delay: .03s; }
  .home > *:nth-child(3) { animation-delay: .07s; }
  .home > *:nth-child(4) { animation-delay: .11s; }
  .home > *:nth-child(n+5) { animation-delay: .15s; }

  .units .unitcard, .path .node { animation: riseIn .48s cubic-bezier(.22,1,.36,1) both; }
  .units .unitcard:nth-child(2), .path .node:nth-child(2) { animation-delay: .05s; }
  .units .unitcard:nth-child(3), .path .node:nth-child(3) { animation-delay: .10s; }
  .units .unitcard:nth-child(4), .path .node:nth-child(4) { animation-delay: .15s; }
  .units .unitcard:nth-child(5), .path .node:nth-child(5) { animation-delay: .20s; }
  .units .unitcard:nth-child(n+6), .path .node:nth-child(n+6) { animation-delay: .24s; }
}

/* ============================================================
   ✨ PREMIUM POLISH — hero + celebration (2026-06-24)
   The payoff moments: the win screen and the lesson hero. Pure
   CSS, file://-safe, gated. No markup / scoring changes.
   ============================================================ */

/* --- WIN SCREEN: a warm sun-halo + a one-shot ring burst behind Bo turns
   "lesson complete" into a real moment (the confetti + bobbing mascot were
   already there). Content sits above the glow via z-index. --- */
.winwrap { position: relative; overflow: hidden; }
.winwrap > * { position: relative; z-index: 1; }
.winwrap::before {
  content: ""; position: absolute; left: 50%; top: 33%; z-index: 0;
  width: 540px; height: 540px; transform: translate(-50%, -50%); pointer-events: none;
  background: radial-gradient(circle, rgba(255,191,63,.42), rgba(255,191,63,.12) 42%, transparent 68%);
}
@media (prefers-reduced-motion: no-preference) {
  .winwrap::after {
    content: ""; position: absolute; left: 50%; top: 33%; z-index: 0;
    width: 180px; height: 180px; border-radius: 50%; pointer-events: none;
    transform: translate(-50%, -50%); border: 6px solid rgba(255,191,63,.6);
    animation: winRing 1.15s cubic-bezier(.22,1,.36,1) forwards;
  }
  @keyframes winRing {
    0% { transform: translate(-50%,-50%) scale(.35); opacity: .9; }
    100% { transform: translate(-50%,-50%) scale(2.6); opacity: 0; }
  }
}
/* golden glow under the XP chip */
.xpchip { box-shadow: inset 0 2px 0 rgba(255,255,255,.35), 0 5px 0 #d99c12, 0 12px 24px -6px rgba(255,191,63,.55); }

/* --- LESSON HERO: a soft top sheen + light inner edge gives the coursehead
   gradient banner a glossy, dimensional finish. --- */
.coursehead { position: relative; overflow: hidden;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.55), 0 18px 34px -16px rgba(240,166,43,.42); }
.coursehead::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(120% 80% at 0% 0%, rgba(255,255,255,.40), transparent 55%);
}
.coursehead > * { position: relative; }

/* --- PROGRESS BAR (in-lesson): brand-gradient fill + soft inner highlight so
   forward motion feels rewarding. --- */
.progress i {
  background: linear-gradient(90deg, var(--good), var(--teal));
  box-shadow: inset 0 2px 0 rgba(255,255,255,.35);
}
/* level + track + tournament fill bars get the same glossy inner light */
.lb-track i, .trackbar > i, .tbar i { box-shadow: inset 0 1px 0 rgba(255,255,255,.45); }

/* --- FEEDBACK SHEET: a clearer correct/again identity — accent edge + pop --- */
.sheet.good { box-shadow: inset 4px 0 0 var(--good); }
.sheet.bad { box-shadow: inset 4px 0 0 var(--bad); }

/* --- DAILY-GOAL RING + topbar level pill: a touch of lift --- */
.daily-ring { filter: drop-shadow(0 4px 8px rgba(58,48,66,.16)); }

/* ============================================================
   ✨ PREMIUM POLISH — living details (2026-06-24)
   Small touches that make the app feel alive + cohesive. Pure
   CSS, file://-safe, gated. No markup / scoring changes.
   ============================================================ */

/* --- progress glimmer: a slow, subtle highlight glints across the home
   level bar so progress feels alive (signature touch; level bar only, to
   stay focused). Gated; the fill clips it. --- */
@media (prefers-reduced-motion: no-preference) {
  .lb-track i { position: relative; overflow: hidden; }
  .lb-track i::after {
    content: ""; position: absolute; top: 0; left: -45%; width: 45%; height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.6), transparent);
    animation: barSheen 3.8s ease-in-out infinite; animation-delay: 1s;
  }
  @keyframes barSheen { 0% { left: -45%; } 50%, 100% { left: 130%; } }
}

/* --- brand wordmark: a hair more presence so the logo reads premium --- */
.brand { text-shadow: 0 1px 0 rgba(255,255,255,.6); }
.brand em { text-shadow: 0 2px 8px rgba(240,166,43,.32); }

/* --- gated launch UI (accounts ON): give the auth + tournament buttons the
   same glossy candy finish as the rest of the app so the signed-in flow
   feels of-a-piece. Additive; only visible when the gate is flipped. --- */
.authbtn { box-shadow: inset 0 2px 0 rgba(255,255,255,.30), 0 5px 0 #1e9c8f; }
.authbtn.google { box-shadow: inset 0 2px 0 rgba(255,255,255,.7), 0 5px 0 var(--soft); }
.authbtn:active:not(:disabled) { box-shadow: inset 0 2px 0 rgba(255,255,255,.22), 0 1px 0 #1e9c8f; }
.trclose { box-shadow: inset 0 2px 0 rgba(255,255,255,.30), 0 4px 0 var(--sky-deep); }
.kidrow, .pickbtn { box-shadow: 0 4px 0 var(--soft), 0 10px 18px -12px rgba(58,48,66,.20); }
.lbrow.me { box-shadow: 0 3px 0 #b8ece4, 0 10px 18px -10px rgba(46,196,182,.35); }

/* --- podium top step gets a soft golden glow (final leaderboard moment) --- */
.pod-1 { box-shadow: 0 3px 0 #f0d999, 0 14px 26px -10px rgba(255,191,63,.55); }

/* ============================================================
   ✨ PREMIUM POLISH — refinements (2026-06-24)
   Tidies the rough edges. Pure CSS, file://-safe, gated where
   it animates. No markup / scoring changes.
   ============================================================ */

/* --- scroll affordance: the badge + sticker shelves overflow horizontally
   and were hard-cutting mid-item. A soft right-edge fade signals "scroll for
   more" and reads as a premium finish. (Topbar .stats is intentionally NOT
   faded — its right-most XP pill must stay crisp.) --- */
.badges-shelf, .stickers-shelf {
  -webkit-mask-image: linear-gradient(90deg, #000 90%, transparent 100%);
          mask-image: linear-gradient(90deg, #000 90%, transparent 100%);
}

/* --- celebration banners: a warm glow makes level-up + track-complete feel
   like the big moments they are. --- */
.levelup { box-shadow: 0 4px 0 #e9c483, 0 14px 28px -8px rgba(255,191,63,.50); }
.trackdone { box-shadow: 0 5px 0 #e6c79a, 0 16px 32px -8px rgba(155,93,229,.42); }
.badge-unlock { box-shadow: 0 4px 0 #e3d2ff, 0 13px 24px -10px rgba(155,93,229,.35); }
.sticker-unlock { box-shadow: 0 4px 0 #c4ebe2, 0 13px 24px -10px rgba(46,196,182,.35); }

/* --- greeter Bo: a touch larger for friendly presence on the home --- */
.greeter-bo { width: 66px; min-width: 66px; }

/* --- desktop niceties: a gentle hover-lift on the collectible chips (no-op
   on touch; keeps the playful tactility on the wider/installed view) --- */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .badge-chip, .sticker-chip, .unitcard, .node { transition: transform .12s ease, box-shadow .12s ease; }
  .badge-chip:hover, .sticker-chip:hover { transform: translateY(-2px); }
}

/* ============================================================
   📱→📲 TABLET / iPad RESPONSIVE PASS — 2026-06-25
   The app is mobile-first (≤480px column). On an iPad that column
   was small and stranded in whitespace. Keep the single-column flow
   (ideal reading width + the lesson-player layout) but WIDEN the
   column and SCALE UP type, art, and tap targets so it fills the
   screen and is comfortable at arm's length. Additive, at the end
   of the cascade; nothing here changes markup, scoring, or motion
   gating. Diagrams/cards/buttons are width:100%, so they grow with
   the wider column automatically — this just tunes proportions.
   ============================================================ */

/* iPad portrait (768) and up — also big phones in landscape */
@media (min-width: 700px) {
  #app { max-width: 600px; }

  /* home */
  .home { padding: 30px 26px 56px; }
  .brand { font-size: 27px; }
  .pill { font-size: 15px; padding: 8px 15px; }
  .coursehead { padding: 26px; }
  .coursehead h1 { font-size: 34px; }
  .coursehead p { font-size: 17px; }
  .unit-cover { height: 150px; }
  .unit-kicker { font-size: 19px; }
  .unit-tagline { font-size: 16px; }
  .unit-progress { font-size: 14px; }
  .greeter-bo { width: 78px; min-width: 78px; }
  .greeter-bubble { font-size: 17px; }
  .shelf-head { font-size: 15px; }

  /* lesson path */
  .trackhead-title { font-size: 23px; }
  .node { padding: 16px 18px; }
  .node .meta h3 { font-size: 19px; }
  .node .meta span { font-size: 14px; }
  .node .bubble { width: 62px; height: 62px; min-width: 62px; font-size: 28px; }

  /* player — bigger prompts, art, options, buttons */
  .phead { padding: 16px 22px 8px; }
  .stage { padding: 18px 26px 14px; gap: 18px; }
  .prompt { font-size: 24px; }
  .concept-text { font-size: 25px; line-height: 1.4; }
  .opt { font-size: 20px; padding: 18px 20px; }
  .sentence { font-size: 26px; }
  .chip { font-size: 20px; padding: 14px 22px; }
  .bucket { font-size: 19px; padding: 22px 12px; }
  .sort-item { font-size: 24px; padding: 30px 20px; }
  .speed-card { font-size: 24px; padding: 34px 20px; }
  .tf { font-size: 22px; padding: 24px 12px; }
  .btn, .authbtn { font-size: 21px; padding: 18px 22px; }
  .pfoot { padding: 14px 26px calc(18px + env(safe-area-inset-bottom)); }
  .sheet h4 { font-size: 22px; }

  /* win screen */
  .winwrap h2 { font-size: 34px; }
  .winwrap .recap { font-size: 19px; }
  .win-mascot { width: 168px; }
  .xpchip { font-size: 25px; padding: 14px 30px; }

  /* accounts / leaderboard / tournament */
  .authcard { max-width: 460px; padding: 26px 24px 28px; }
  .authtitle { font-size: 29px; }
  .lbtitle { font-size: 29px; }
  .lbname { font-size: 17px; }
  .lbav { font-size: 30px; }
}

/* larger iPads / landscape (≥1000px): a touch more room + bigger art */
@media (min-width: 1000px) {
  #app { max-width: 640px; }
  .unit-cover { height: 170px; }
  .coursehead h1 { font-size: 36px; }
}

/* ============================================================
   🖥️ iPad LANDSCAPE 2-COLUMN GRID — 2026-08-02
   On a wide landscape iPad the single mobile-first column left the
   screen mostly empty. The home course grid and the lesson list
   now flow into a centered 2-column grid so the width gets used.
   The in-lesson card player (.stage) stays single-column and
   centered on purpose — one prompt/one decision at a time is the
   point for kids — it's just capped at a comfortable reading width
   instead of stretching edge to edge. Landscape-gated so a portrait
   iPad (still narrower than it is tall even on 12.9") keeps the
   single-column flow from the pass above. Additive only — no
   markup/JS changes, no scoring or motion changes. */
@media (min-width: 1000px) and (orientation: landscape) {
  #app { max-width: 900px; }

  /* home: course/unit cards flow into 2 columns. Each course renders as its
     own [trackhead, unitcard] pair in source order (one header per course) —
     a CSS grid would force the short header's row to match its tall card's
     row height next to it, leaving an ugly gap. Multi-column flow instead:
     reads top-to-bottom down the left column then continues down the right,
     and keeps each header glued to its own card. */
  .units { display: block; column-count: 2; column-gap: 20px; }
  .units .trackhead { break-after: avoid; -webkit-column-break-after: avoid; margin: 22px 4px 8px; }
  .units .unitcard { break-inside: avoid; -webkit-column-break-inside: avoid; margin: 0 0 20px; }

  /* lesson path: nodes flow 2-up. The single-column "zigzag" offset
     (odd/even side margins) only reads right in one column, so it's
     neutralized here in favor of a clean grid. */
  .path { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
  .path .node:nth-child(odd), .path .node:nth-child(even) { margin-left: 0; margin-right: 0; }

  /* card player: stays single-column & centered, just capped in width */
  .player { align-self: center; width: 100%; max-width: 640px; }
}


/* tap_find styles — appended to bible build stylesheet */
.tf-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:14px 0}
.tf-tile{font-size:44px;padding:16px 0;border:0;border-radius:18px;background:var(--card,#fff);
  box-shadow:0 4px 12px rgba(0,0,0,.08);cursor:pointer;transition:transform .12s}
.tf-tile:active{transform:scale(.94)}
.tf-tile.tf-good{background:#E2F6F1;box-shadow:inset 0 0 0 3px #2EC4B6}
.tf-tile.tf-bad{animation:tfshake .4s}
.tf-count{text-align:center;font-weight:700;color:var(--muted,#8a7a64)}
@keyframes tfshake{0%,100%{transform:translateX(0)}25%{transform:translateX(-6px)}75%{transform:translateX(6px)}}

/* ---------- Storybook Shelf + Big Story teasers (Sprint LL1) ---------- */
.shelfcard { display: flex; align-items: center; gap: 14px; width: 100%;
  background: linear-gradient(135deg, #FFF3DC, #EAF6FF); border-radius: var(--radius);
  padding: 14px; margin: 0 0 14px; text-align: left;
  box-shadow: 0 4px 0 var(--soft), 0 12px 22px -12px rgba(58,48,66,.25); }
.shelfcard:active { transform: translateY(2px); }
.shelfcard .bubble { width: 54px; height: 54px; min-width: 54px; border-radius: 50%;
  display: grid; place-items: center; font-size: 24px; background: var(--gold);
  box-shadow: 0 4px 0 var(--gold-deep); }
.shelfcard .meta { flex: 1; min-width: 0; }
.shelfcard .meta h3 { margin: 0 0 2px; font-size: 17px; }
.shelfcard .meta span { font-size: 13px; color: var(--sub); font-weight: 700; }
.sb-new { background: var(--gold); color: #fff; font-size: 12px; font-weight: 900;
  padding: 4px 10px; border-radius: 999px; box-shadow: 0 2px 0 var(--gold-deep);
  white-space: nowrap; }
.storybook .sb-course { margin: 18px 0 6px; }
.sb-course-head { display: flex; justify-content: space-between; align-items: baseline;
  margin: 0 4px 8px; }
.sb-course-title { font-size: 16px; font-weight: 900; }
.sb-course-count { font-size: 13px; font-weight: 800; color: var(--sub); }
.sb-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.sb-tile { position: relative; border-radius: 14px; overflow: hidden; background: var(--card);
  box-shadow: 0 3px 0 var(--soft); padding: 0; aspect-ratio: 4 / 3; }
.sb-tile img { width: 100%; height: 100%; object-fit: cover; }
.sb-tile:active { transform: scale(.96); }
.sb-tile.locked { background: #F6EEDF; }
.sb-tile.locked img { filter: grayscale(1) brightness(0); opacity: .12; }
.sb-q { position: absolute; inset: 0; display: grid; place-items: center; font-size: 26px;
  font-weight: 900; color: #b3a488; }
.sb-empty { color: var(--sub); font-weight: 700; text-align: center; padding: 30px 10px; }
.sb-page { max-width: 420px; }
.sb-art { width: 100%; border-radius: 14px; background: #fff; }
.sb-caption { font-size: 17px; font-weight: 700; margin: 12px 2px 6px; line-height: 1.45; }
.sb-from { font-size: 13px; color: var(--sub); font-weight: 800; margin-bottom: 12px; }
.sb-nav { display: flex; gap: 10px; }
.sb-nav .sb-prev, .sb-nav .sb-next { width: 64px; flex: 0 0 auto; }
.sb-nav .sb-close { flex: 1; }
.tease { display: flex; align-items: center; gap: 12px;
  background: linear-gradient(135deg, #FFF3DC, #EAF6FF); border-radius: 16px;
  padding: 12px; margin: 14px auto 0; max-width: 340px; text-align: left;
  box-shadow: 0 3px 0 var(--soft); }
.tease-thumb { width: 74px; height: 56px; object-fit: cover; border-radius: 10px;
  flex: 0 0 auto; }
.tease-meta { min-width: 0; }
.tease-k { font-size: 12px; font-weight: 800; color: var(--sub); }
.tease-line { font-size: 15px; font-weight: 900; }
.sb-winline { font-weight: 800; }

/* ── new-version update pill (ported from Batch, 2026-07-22) ──────── */
.update-pill { display: block; width: calc(100% - 8px); margin: 10px auto 2px; padding: 12px 16px;
  border: none; border-radius: 14px; background: var(--purple); color: #fff;
  font-family: inherit; font-size: 14.5px; font-weight: 800; cursor: pointer;
  box-shadow: 0 4px 0 #7a41c4; -webkit-tap-highlight-color: transparent; }
.update-pill:active { transform: translateY(3px); box-shadow: 0 1px 0 #7a41c4; }
