/* ==========================================================================
   LearnTalkGo — design system + app styles
   Mobile-first. Desktop layout kicks in at 1024px.
   ========================================================================== */

:root{
  /* palette */
  --blue:#3b82f6; --blue-d:#2563eb;
  --green:#58cc02; --green-d:#46a302;
  --red:#ff4b4b;   --red-d:#e03e3e;
  --orange:#ff9600; --gold:#ffc800;
  --purple:#8b5cf6; --purple-d:#7c3aed;
  --pink:#ec4899;
  --cyan:#22d3ee;

  --ink:#1f2340;
  --ink-2:#5b6084;
  --ink-3:#9aa0c0;
  --line:#e6e8f5;
  --card:#ffffff;
  --bg:#f2f5ff;
  --bg-2:#e8ecfb;

  /* 8px grid */
  --s1:8px; --s2:16px; --s3:24px; --s4:32px; --s5:40px; --s6:48px;
  --r-sm:14px; --r:20px; --r-lg:28px; --r-xl:36px;

  --shadow:0 4px 0 rgba(31,35,64,.12), 0 8px 24px rgba(31,35,64,.10);
  --shadow-sm:0 2px 0 rgba(31,35,64,.10), 0 4px 12px rgba(31,35,64,.08);
  --shadow-lg:0 10px 30px rgba(31,35,64,.16);

  /* Toast needs its own pair. It must NOT reuse --ink as a background:
     --ink inverts in dark mode, which turned the toast white-on-white. */
  --toast-bg:#1f2340; --toast-fg:#ffffff;

  --spring:cubic-bezier(.34,1.56,.64,1);
  --dur:280ms;

  --font:'Baloo 2','Nunito',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
  --font-ui:'Nunito',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;

  --safe-b:env(safe-area-inset-bottom,0px);
  --tab-h:76px;
}

html[data-theme="dark"]{
  --ink:#eef0ff; --ink-2:#b3b8dd; --ink-3:#7b81ab;
  --line:#2c3157; --card:#1e2242; --bg:#12142b; --bg-2:#191d3a;
  --toast-bg:#3b4278; --toast-fg:#ffffff;   /* raised, still white-on-dark */
  --shadow:0 4px 0 rgba(0,0,0,.35), 0 8px 24px rgba(0,0,0,.45);
  --shadow-sm:0 2px 0 rgba(0,0,0,.3), 0 4px 12px rgba(0,0,0,.35);
  --shadow-lg:0 10px 30px rgba(0,0,0,.5);
}

*,*::before,*::after{box-sizing:border-box}
html,/* page-level x containment: outfit rack scrolls inside itself, not the page */
html{overflow-x:clip}
body{overflow-x:clip}
.app{overflow-x:clip; max-width:100%}
.center,.screen,.sec{max-width:100%; min-width:0}
.av-shelf{max-width:100%; min-width:0}
body{height:100%}
body{
  margin:0; font-family:var(--font-ui); color:var(--ink);
  background:var(--bg);
  -webkit-font-smoothing:antialiased; -webkit-tap-highlight-color:transparent;
  overscroll-behavior-y:none;
}
h1,h2,h3,h4{font-family:var(--font); margin:0; letter-spacing:-.01em}
button{font-family:inherit; color:inherit; border:0; background:none; cursor:pointer}
:focus-visible{outline:3px solid var(--blue); outline-offset:3px; border-radius:12px}

html[data-fontsize="large"]{font-size:19px}
html[data-fontsize="large"] body{font-size:1.05rem}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms !important; animation-iteration-count:1 !important; transition-duration:.001ms !important}
}
html[data-motion="off"] *,html[data-motion="off"] *::before,html[data-motion="off"] *::after{
  animation:none !important; transition:none !important;
}

/* ============================ App shell =================================== */
.app{
  position:relative; min-height:100dvh; max-width:520px; margin:0 auto;
  background:var(--bg);
}
.screen{display:none; padding-bottom:calc(var(--tab-h) + var(--safe-b) + 16px)}
.screen.is-active{display:block; animation:fadeUp var(--dur) var(--spring)}
@keyframes fadeUp{from{opacity:0; transform:translateY(10px)}to{opacity:1; transform:none}}

/* ---- top bar ---- */
.topbar{
  position:sticky; top:0; z-index:40; display:flex; align-items:center; justify-content:space-between;
  padding:14px var(--s2) 10px; background:var(--card);
  border-bottom:1px solid var(--line);
}
html[data-theme="dark"] .topbar{background:var(--card)}
.brand{font-family:var(--font); font-weight:800; font-size:26px; letter-spacing:-.5px}
.brand .b1{color:var(--blue)} .brand .b2{color:var(--orange)} .brand .b3{color:var(--green)}
.iconbtn{
  width:44px; height:44px; border-radius:14px; display:grid; place-items:center;
  font-size:20px; color:var(--ink-2); transition:transform 160ms var(--spring), background 160ms;
}
.iconbtn:active{transform:scale(.9); background:var(--bg-2)}

/* ---- revision number, top right ----
   Plain text for everyone. It only looks tappable once an admin has unlocked,
   because for a learner it is a fact about the build, not a control. */
.ver{
  margin-left:auto; margin-right:8px; padding:4px 8px; border-radius:999px;
  font-size:11px; font-weight:800; letter-spacing:.3px;
  color:var(--ink-3); background:transparent; cursor:default;
}
.ver.is-admin{
  color:var(--purple); background:rgba(139,92,246,.12); cursor:pointer;
}
.ver.is-admin:active{transform:scale(.94)}

/* ---- app-language picker (Settings) ---- */
.uilangs{display:flex; flex-wrap:wrap; gap:7px}
.uilang{
  display:flex; align-items:center; gap:6px; padding:8px 12px; border-radius:999px;
  background:var(--bg-2); font-weight:800; font-size:13px; color:var(--ink-2);
  transition:transform 160ms var(--spring);
}
.uilang.on{background:var(--purple); color:#fff; box-shadow:var(--shadow-sm)}
.uilang:active{transform:scale(.94)}
/* Said plainly rather than hidden: a machine translation nobody has read is a
   fact the reader is entitled to, especially in a children's app. */
.uilang-note{
  margin:10px 0 8px; padding:9px 11px; border-radius:var(--r);
  background:rgba(255,179,0,.13); border:2px solid rgba(255,179,0,.34);
  font-size:12px; font-weight:700; color:var(--ink-2); line-height:1.45;
}

/* ---- request tickets ---- */
.rq-item{
  padding:10px 12px; margin-bottom:8px; border-radius:var(--r);
  background:var(--bg-2); text-align:left;
}
.rq-item b{display:block; font-size:13.5px; line-height:1.35; margin:4px 0}
.rq-item small{display:block; color:var(--ink-3); font-weight:700; font-size:11px}
.rq-st{
  display:inline-block; padding:2px 8px; border-radius:999px;
  font-size:10px; font-weight:900; text-transform:uppercase; letter-spacing:.5px;
  background:rgba(139,92,246,.18); color:var(--purple);
}
.rq-completed{background:rgba(34,197,94,.18); color:#15803d}
.rq-rejected{background:rgba(148,163,184,.24); color:var(--ink-3)}

/* ---- hero card ---- */
.hero{
  margin:var(--s2); padding:var(--s2); border-radius:var(--r-lg);
  background:linear-gradient(150deg,#dff1ff,#f4e9ff 60%,#ffeef6);
  box-shadow:var(--shadow); position:relative; overflow:hidden;
}
html[data-theme="dark"] .hero{background:linear-gradient(150deg,#243056,#2c2450 60%,#3a2444)}
.hero-row{display:flex; gap:var(--s2); align-items:center}
.mascot-ring{
  width:76px; height:76px; flex:0 0 76px; border-radius:50%;
  background:radial-gradient(circle at 40% 30%,#fff,#e8f3ff);
  border:4px solid #fff; box-shadow:var(--shadow-sm);
  display:grid; place-items:center; font-size:40px; position:relative;
}
html[data-theme="dark"] .mascot-ring{background:radial-gradient(circle at 40% 30%,#3a4272,#252b52); border-color:#3a4272}
.mascot-ring .m{animation:bob 3.2s ease-in-out infinite}
@keyframes bob{0%,100%{transform:translateY(0) rotate(-2deg)}50%{transform:translateY(-6px) rotate(2deg)}}
.hero h2{font-size:22px; line-height:1.2}
.hero p{margin:2px 0 0; color:var(--ink-2); font-size:14px; font-weight:600}

.hero-stats{display:flex; gap:var(--s1); margin-top:var(--s2)}
.pill{
  flex:1; display:flex; align-items:center; gap:8px; background:var(--card);
  border-radius:999px; padding:8px 12px; box-shadow:var(--shadow-sm); min-width:0;
}
.pill .em{font-size:20px; flex:0 0 auto}
.pill .lbl{font-size:12px; font-weight:800; color:var(--ink-2); line-height:1.1}
.pill .val{font-size:15px; font-weight:800; line-height:1.15}
.xpbar{height:8px; border-radius:99px; background:var(--bg-2); overflow:hidden; margin-top:3px}
.xpbar > i{display:block; height:100%; border-radius:99px; background:linear-gradient(90deg,var(--blue),var(--cyan)); transition:width 700ms var(--spring)}
.addbtn{
  width:30px; height:30px; border-radius:50%; background:var(--green); color:#fff;
  font-size:20px; font-weight:800; display:grid; place-items:center; box-shadow:0 3px 0 var(--green-d);
}
.addbtn:active{transform:translateY(2px); box-shadow:0 1px 0 var(--green-d)}

/* ---- language switcher ---- */
.langbar{display:flex; gap:8px; padding:0 var(--s2); align-items:center}
.langpick{
  display:inline-flex; align-items:center; gap:8px; background:var(--card);
  padding:10px 14px; border-radius:999px; box-shadow:var(--shadow-sm);
  font-weight:800; font-size:15px;
}
.langpick .fl{font-size:20px}
.langpick .cv{color:var(--ink-3); font-size:12px}
.langmenu{
  position:absolute; z-index:60; margin-top:6px; background:var(--card); border-radius:var(--r);
  box-shadow:var(--shadow-lg); padding:6px; display:none; min-width:190px;
}
.langmenu.open{display:block; animation:pop 220ms var(--spring)}
@keyframes pop{from{opacity:0; transform:scale(.94) translateY(-6px)}to{opacity:1; transform:none}}
.langmenu button{display:flex; width:100%; gap:10px; align-items:center; padding:11px 12px; border-radius:14px; font-weight:800; font-size:15px}
.langmenu button:hover{background:var(--bg-2)}

/* ============================ World map =================================== */
.mapwrap{
  position:relative; margin:var(--s2); border-radius:var(--r-lg); overflow:hidden;
  box-shadow:var(--shadow); background:#57c4e5; aspect-ratio:3/4;
}
.mapwrap svg{position:absolute; inset:0; width:100%; height:100%; display:block}
.shimmer{animation:shimmer 6s ease-in-out infinite}
@keyframes shimmer{0%,100%{opacity:.35; transform:translateX(0)}50%{opacity:.7; transform:translateX(10px)}}
.cloud{animation:drift 40s linear infinite; opacity:.85}
.cloud.c2{animation-duration:56s; animation-delay:-14s}
.cloud.c3{animation-duration:70s; animation-delay:-30s}
@keyframes drift{from{transform:translateX(-30%)}to{transform:translateX(130%)}}
.sway{transform-origin:center bottom; animation:sway 5s ease-in-out infinite}
.sway.s2{animation-delay:-1.6s} .sway.s3{animation-delay:-3.1s}
@keyframes sway{0%,100%{transform:rotate(-2.5deg)}50%{transform:rotate(2.5deg)}}

.nodes{position:absolute; inset:0}
.node{
  position:absolute; transform:translate(-50%,-50%); display:flex; flex-direction:column;
  align-items:center; gap:4px; width:112px;
}
.node .dot{
  width:46px; height:46px; border-radius:50%; display:grid; place-items:center;
  font-weight:900; font-size:19px; color:#fff; border:4px solid #fff;
  background:linear-gradient(180deg,#4aa3f5,#2f7fe0); box-shadow:0 4px 0 rgba(0,0,0,.18);
  transition:transform 200ms var(--spring);
}
.node.done .dot{background:linear-gradient(180deg,#7ee04a,#4caf13)}
.node.locked .dot{background:linear-gradient(180deg,#b9c0d8,#98a0bd); color:#f3f5ff}
.node.current .dot{animation:pulse 1.8s ease-in-out infinite}
@keyframes pulse{0%,100%{transform:scale(1); box-shadow:0 4px 0 rgba(0,0,0,.18),0 0 0 0 rgba(255,255,255,.7)}50%{transform:scale(1.08); box-shadow:0 4px 0 rgba(0,0,0,.18),0 0 0 12px rgba(255,255,255,0)}}
.node:active .dot{transform:scale(.92)}
.node .plate{
  background:var(--card); border-radius:14px; padding:5px 10px; box-shadow:var(--shadow-sm);
  text-align:center; max-width:112px;
}
.node .plate b{display:block; font-size:12.5px; font-weight:800; line-height:1.2; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.stars{font-size:11px; letter-spacing:1px; color:var(--gold)}
.stars .off{color:var(--ink-3); opacity:.45}
.node.locked .plate{opacity:.72}
.node .lock{font-size:16px}

.chest{position:absolute; right:6%; bottom:9%; font-size:34px; animation:bob 4s ease-in-out infinite; filter:drop-shadow(0 4px 6px rgba(0,0,0,.25))}

/* ---- continue CTA ---- */
.cta{
  /* always reachable: rides just above the tab bar while the map scrolls */
  position:sticky; bottom:calc(var(--tab-h) + var(--safe-b) + 8px); z-index:30;
  display:flex; align-items:center; gap:12px; margin:0 var(--s2) var(--s2);
  background:var(--green); color:#fff; padding:16px; border-radius:var(--r);
  box-shadow:0 5px 0 var(--green-d); font-weight:900; font-size:17px; width:calc(100% - var(--s3));
  transition:transform 140ms var(--spring), box-shadow 140ms;
}
.cta:active{transform:translateY(4px); box-shadow:0 1px 0 var(--green-d)}
.cta .go{margin-left:auto; font-size:20px}
.cta .txt b{display:block; font-size:17px; line-height:1.2}
.cta .txt small{display:block; font-size:12.5px; font-weight:800; opacity:.85; margin-top:1px}

/* ============================ Tab bar ==================================== */
.tabbar{
  position:fixed; bottom:0; left:0; right:0; z-index:50; max-width:520px; margin:0 auto;
  display:grid; grid-template-columns:repeat(4,1fr); gap:2px;
  background:var(--card); border-top:1px solid var(--line);
  padding:8px 4px calc(8px + var(--safe-b));
}
/* six tabs on a 360px phone: the label has to give up a little */
.tab{display:flex; flex-direction:column; align-items:center; gap:3px; padding:6px 2px; border-radius:16px; color:var(--ink-3); font-size:11px; font-weight:800; letter-spacing:-.1px}
.tab .ti{font-size:23px; transition:transform 220ms var(--spring); filter:grayscale(.55) opacity(.75)}
.tab.is-active{color:var(--purple)}
.tab.is-active .ti{transform:translateY(-3px) scale(1.16); filter:none}

/* ============================ Lesson ===================================== */
#lesson{
  position:fixed; inset:0; z-index:100; background:var(--card); display:none;
  max-width:520px; margin:0 auto; flex-direction:column;
}
#lesson.open{display:flex; animation:slideUp 320ms var(--spring)}
@keyframes slideUp{from{transform:translateY(24px); opacity:0}to{transform:none; opacity:1}}

.lhead{display:flex; align-items:center; gap:12px; padding:14px var(--s2) 8px}
.lbar{flex:1; height:14px; border-radius:99px; background:var(--bg-2); overflow:hidden}
.lbar > i{display:block; height:100%; border-radius:99px; background:linear-gradient(90deg,var(--green),#8fe34a); transition:width 420ms var(--spring)}
.combo{font-weight:900; color:var(--orange); font-size:13px; white-space:nowrap}
.hearts{font-weight:900; color:var(--red); font-size:14px; white-space:nowrap}
.lbody{flex:1; overflow-y:auto; padding:var(--s2) var(--s2) 180px; text-align:center}
.lq{font-size:24px; font-weight:900; font-family:var(--font); margin-bottom:var(--s3)}

.bubblewrap{display:flex; align-items:flex-end; gap:10px; margin:0 auto var(--s3); max-width:420px}
.speaker{
  flex:0 0 86px; height:86px; border-radius:26px; display:grid; place-items:center; font-size:44px;
  background:linear-gradient(160deg,#e7ecff,#dbe4ff); box-shadow:var(--shadow-sm);
}
html[data-theme="dark"] .speaker{background:linear-gradient(160deg,#2b3260,#242a52)}
.speaker .m{animation:bob 3s ease-in-out infinite}
.bubble{
  position:relative; flex:1; background:var(--card); border:3px solid var(--line);
  border-radius:24px; padding:16px 14px; text-align:center; box-shadow:var(--shadow-sm);
}
/* The tail pointed at a mascot tile that no longer exists — the bubble is now
   the full width of the column. */
.bubble .tt{font-family:var(--font); font-size:26px; font-weight:800; line-height:1.15; color:var(--blue-d)}
html[data-theme="dark"] .bubble .tt{color:#8ab4ff}
.bubble .rr{font-size:13px; color:var(--ink-3); font-weight:700; margin-top:2px}
.bubble .ee{font-size:15px; color:var(--ink-2); font-weight:700; margin-top:6px}
.playbtn{
  position:absolute; right:-10px; bottom:-10px; width:46px; height:46px; border-radius:50%;
  background:var(--blue); color:#fff; font-size:20px; display:grid; place-items:center;
  box-shadow:0 4px 0 var(--blue-d);
}
.playbtn:active{transform:translateY(3px); box-shadow:0 1px 0 var(--blue-d)}
.playbtn.speaking{animation:ring 1s ease-in-out infinite}
@keyframes ring{0%,100%{box-shadow:0 4px 0 var(--blue-d),0 0 0 0 rgba(59,130,246,.5)}50%{box-shadow:0 4px 0 var(--blue-d),0 0 0 14px rgba(59,130,246,0)}}

/* mic */
.mic{
  width:132px; height:132px; border-radius:50%; margin:var(--s2) auto 8px; display:grid; place-items:center;
  font-size:52px; color:#fff; background:linear-gradient(160deg,#c04af0,#ff4bb0);
  box-shadow:0 8px 0 #9a2fc4, 0 14px 30px rgba(192,74,240,.4);
  transition:transform 160ms var(--spring);
}
.mic:active{transform:translateY(5px) scale(.97)}
.mic.listening{animation:mic 1.2s ease-in-out infinite}
@keyframes mic{0%,100%{box-shadow:0 8px 0 #9a2fc4,0 0 0 0 rgba(255,75,176,.55)}50%{box-shadow:0 8px 0 #9a2fc4,0 0 0 26px rgba(255,75,176,0)}}
.mic-label{font-weight:900; color:var(--purple); font-size:17px}
.heard{margin-top:10px; font-weight:800; color:var(--ink-2); min-height:22px; font-size:15px}

/* speaking-round step controls — quiet on purpose: an escape hatch for when
   recognition will not cooperate, not a headline action */
.speaknav{display:flex; gap:10px; justify-content:center; margin:12px auto 0; max-width:340px}
.navbtn{
  flex:1; padding:11px 14px; border-radius:var(--r); border:2px solid var(--line);
  background:var(--card); color:var(--ink-2); font-family:var(--font-ui);
  font-weight:800; font-size:14px; cursor:pointer;
  transition:transform var(--dur) var(--spring), border-color .18s, color .18s;
}
.navbtn:active{transform:scale(.96)}
.navbtn:hover:not(:disabled){border-color:var(--purple); color:var(--purple)}
.navbtn:disabled{opacity:.35; cursor:default}

/* choices */
.choices{display:grid; gap:12px; max-width:420px; margin:0 auto}
.choice{
  padding:16px; border-radius:var(--r); background:var(--card); border:2px solid var(--line);
  box-shadow:0 4px 0 var(--line); font-weight:800; font-size:17px; text-align:center;
  transition:transform 140ms var(--spring), border-color 140ms, background 140ms;
}
.choice:active{transform:translateY(3px); box-shadow:0 1px 0 var(--line)}
.choice.sel{border-color:var(--blue); background:rgba(59,130,246,.09); box-shadow:0 4px 0 var(--blue-d)}
.choice.good{border-color:var(--green); background:rgba(88,204,2,.14); box-shadow:0 4px 0 var(--green-d)}
.choice.bad{border-color:var(--red); background:rgba(255,75,75,.12); box-shadow:0 4px 0 var(--red-d)}
.choice .sub{display:block; font-size:12.5px; color:var(--ink-3); font-weight:700; margin-top:2px}

/* An option that's been ruled out: struck through, dimmed, no longer tappable. */
.choice.struck{
  border-color:var(--red); background:rgba(255,75,75,.07); box-shadow:none;
  opacity:.5; pointer-events:none; transform:none;
}
.choice.struck .ctext{text-decoration:line-through; text-decoration-thickness:2px}
.choice.struck .say{display:none}
.choice.struck::after{
  content:'✕'; position:absolute; right:16px; top:50%; transform:translateY(-50%);
  color:var(--red); font-weight:900; font-size:18px;
}
.choice:disabled{cursor:default}

/* between-strike nudge */
.strikebar{display:flex; align-items:center; gap:12px; margin-bottom:12px}
.strikebar .fm{font-size:30px}
.strikebar b{display:block; font-family:var(--font); font-size:17px; color:var(--orange)}
.strikebar small{color:var(--ink-2); font-weight:800; font-size:13.5px}
.shake{animation:shake 380ms ease}
@keyframes shake{
  0%,100%{transform:translateX(0)}
  20%{transform:translateX(-7px)} 40%{transform:translateX(6px)}
  60%{transform:translateX(-4px)} 80%{transform:translateX(3px)}
}
/* The speaker badge is a separate tap target: it plays the phrase and
   deliberately does NOT select the answer. */
.choice.has-say{position:relative; padding-right:58px}
.choice .ctext{display:block}
.choice .say{
  position:absolute; right:8px; top:50%; transform:translateY(-50%);
  width:42px; height:42px; border-radius:50%; display:grid; place-items:center;
  font-size:17px; opacity:.55; background:var(--bg-2); cursor:pointer;
}
.choice .say:hover,.choice .say:focus-visible{opacity:1}
.choice.speaking .say{opacity:1; animation:spk .9s ease-in-out infinite}
@keyframes spk{0%,100%{transform:translateY(-50%) scale(1)}50%{transform:translateY(-50%) scale(1.18)}}
.lq .hint{display:block; font-family:var(--font-ui); font-size:13.5px; font-weight:800; color:var(--ink-3); margin-top:4px}

/* word bank */
.answerline{
  min-height:66px; border-top:3px dashed var(--line); border-bottom:3px dashed var(--line);
  display:flex; flex-wrap:wrap; gap:8px; padding:12px 6px; justify-content:center; margin-bottom:var(--s3);
}
.bank{display:flex; flex-wrap:wrap; gap:10px; justify-content:center}
.word{
  padding:11px 15px; border-radius:16px; background:var(--card); border:2px solid var(--line);
  box-shadow:0 3px 0 var(--line); font-weight:800; font-size:16px;
  transition:transform 120ms var(--spring), opacity 120ms;
}
.word:active{transform:translateY(2px)}
.word.used{opacity:.25; pointer-events:none}

/* feedback footer */
.lfoot{
  position:absolute; left:0; right:0; bottom:0; padding:var(--s2) var(--s2) calc(var(--s2) + var(--safe-b));
  background:var(--card); border-top:1px solid var(--line);
}
.lfoot.good{background:#e8f9d5; border-top-color:#c9ee9c}
.lfoot.bad{background:#ffe9e9; border-top-color:#ffc4c4}
html[data-theme="dark"] .lfoot.good{background:#1f3a12} html[data-theme="dark"] .lfoot.bad{background:#42191c}
.fbrow{display:flex; align-items:center; gap:12px; margin-bottom:12px}
.fbrow .fm{font-size:34px; animation:cheer 700ms var(--spring)}
@keyframes cheer{0%{transform:scale(.4) rotate(-20deg)}60%{transform:scale(1.25) rotate(8deg)}100%{transform:none}}
.fbrow b{font-family:var(--font); font-size:19px; display:block}
.fbrow small{color:var(--ink-2); font-weight:700; font-size:13.5px}
.rewards{margin-left:auto; display:flex; gap:8px; font-weight:900; white-space:nowrap; font-size:14px}
.btn{
  display:block; width:100%; padding:16px; border-radius:var(--r); font-weight:900; font-size:17px;
  color:#fff; background:var(--green); box-shadow:0 5px 0 var(--green-d);
  transition:transform 130ms var(--spring), box-shadow 130ms;
}
.btn:active{transform:translateY(4px); box-shadow:0 1px 0 var(--green-d)}
.btn.blue{background:var(--blue); box-shadow:0 5px 0 var(--blue-d)}
.btn.blue:active{box-shadow:0 1px 0 var(--blue-d)}
.btn.purple{background:var(--purple); box-shadow:0 5px 0 var(--purple-d)}
.btn.purple:active{box-shadow:0 1px 0 var(--purple-d)}
.btn.ghost{background:transparent; color:var(--ink-2); box-shadow:none; border:2px solid var(--line)}
.btn[disabled]{opacity:.45; pointer-events:none}

/* ============================ Manga story ================================ */
.mg-head{text-align:center; margin-bottom:var(--s2)}
.mg-kicker{display:inline-block; background:var(--ink); color:#fff; font-weight:900; font-size:11px;
  letter-spacing:1.5px; text-transform:uppercase; padding:4px 12px; border-radius:99px}
html[data-theme="dark"] .mg-kicker{background:var(--purple)}
.mg-title{font-size:26px; margin-top:8px}
.mg-sub{color:var(--ink-2); font-weight:700; font-size:13.5px; margin:4px 0 0}

.mg-strip{display:flex; flex-direction:column; gap:14px}
.mg-panel{
  position:relative; margin:0; border:3px solid var(--ink); border-radius:6px;
  background:#fdfcf7; overflow:hidden; padding:14px 12px 10px; cursor:pointer;
  box-shadow:5px 5px 0 rgba(31,35,64,.85);
}
html[data-theme="dark"] .mg-panel{background:#232848; border-color:#8f97d6; box-shadow:5px 5px 0 rgba(0,0,0,.6)}
.mg-panel.pop{animation:mgpop 380ms var(--spring)}
@keyframes mgpop{from{opacity:0; transform:translateY(16px) rotate(-1deg)}to{opacity:1; transform:none}}
.mg-panel.bg-dawn{background:linear-gradient(180deg,#ffe8c9,#fff6ea)}
.mg-panel.bg-night{background:linear-gradient(180deg,#2b3163,#41497f); color:#fff}
.mg-panel.bg-park{background:linear-gradient(180deg,#dff5d8,#f4fbf0)}
.mg-panel.bg-shop{background:linear-gradient(180deg,#ffeede,#fff8f0)}
html[data-theme="dark"] .mg-panel.bg-dawn,html[data-theme="dark"] .mg-panel.bg-park,
html[data-theme="dark"] .mg-panel.bg-shop{background:#232848}
.mg-panel.bg-night .mg-note{color:#d8dcff}

.mg-tone{position:absolute; inset:0; width:100%; height:100%; color:var(--ink);
  opacity:.06; pointer-events:none}
.mg-burst{position:absolute; left:50%; top:45%; width:150%; transform:translate(-50%,-50%);
  color:var(--ink); pointer-events:none; opacity:.5}
html[data-theme="dark"] .mg-burst{color:#aeb6ff}

.mg-stage{position:relative; display:flex; align-items:flex-end; gap:10px}
.mg-stage.rev{flex-direction:row-reverse}
.mg-char{flex:0 0 88px}
.mg-fig{width:88px; height:110px; display:block}
.mg-fig.flip{transform:scaleX(-1)}
.mg-bubble{
  position:relative; flex:1; background:#fff; border:3px solid var(--ink);
  border-radius:20px; padding:12px 14px; text-align:center; min-width:0;
}
html[data-theme="dark"] .mg-bubble{background:#f4f5ff; border-color:#3b4278}
.mg-bubble::after{content:''; position:absolute; bottom:14px; left:-14px; width:0; height:0;
  border:9px solid transparent; border-right-color:var(--ink)}
.mg-bubble::before{content:''; position:absolute; bottom:16px; left:-9px; width:0; height:0;
  border:7px solid transparent; border-right-color:#fff; z-index:1}
html[data-theme="dark"] .mg-bubble::before{border-right-color:#f4f5ff}
.mg-bubble.right::after{left:auto; right:-14px; border-right-color:transparent; border-left-color:var(--ink)}
.mg-bubble.right::before{left:auto; right:-9px; border-right-color:transparent; border-left-color:#fff}
html[data-theme="dark"] .mg-bubble.right::before{border-left-color:#f4f5ff}
.mg-t{display:block; font-family:var(--font); font-size:23px; line-height:1.15; color:#1f2340}
.mg-r{display:block; font-size:12.5px; font-weight:800; color:#7b81ab; margin-top:1px}
.mg-en{display:block; font-size:13.5px; font-weight:800; color:#5b6084; margin-top:5px}
.mg-note{
  position:relative; margin-top:10px; font-size:12.5px; font-weight:800; color:var(--ink-2);
  background:rgba(255,255,255,.75); border-radius:6px; padding:6px 9px; line-height:1.4;
}
html[data-theme="dark"] .mg-note{background:rgba(0,0,0,.25); color:#c3c8ef}

/* ============================ Teach a word =============================== */
.teach{text-align:center}
.teach-card{
  position:relative; background:var(--card); border-radius:var(--r-lg); padding:26px 18px 22px;
  box-shadow:var(--shadow); margin-bottom:var(--s3); border:3px solid var(--line);
}
.teach-tag{
  position:absolute; top:-13px; left:50%; transform:translateX(-50%);
  background:var(--purple); color:#fff; font-weight:900; font-size:11px; letter-spacing:1.2px;
  text-transform:uppercase; padding:5px 14px; border-radius:99px; white-space:nowrap;
}
.teach-t{font-family:var(--font); font-size:40px; line-height:1.1; color:var(--blue-d); word-break:break-word}
html[data-theme="dark"] .teach-t{color:#8ab4ff}
.teach-r{font-size:15px; font-weight:800; color:var(--ink-3); margin-top:4px}
.teach-en{font-size:18px; font-weight:800; color:var(--ink-2); margin-top:8px}
.teach-play{position:static; margin:16px auto 0; display:grid}
.teach-hint{font-weight:800; color:var(--ink-2); font-size:15px; margin:0 0 10px}
.teach-mic{width:108px; height:108px; font-size:44px; margin:6px auto 4px}
.teach-input{
  width:100%; max-width:340px; padding:15px; border-radius:18px; border:2px solid var(--line);
  font:inherit; font-size:18px; font-weight:800; text-align:center;
  background:var(--card); color:var(--ink);
}
.teach-input:focus{outline:none; border-color:var(--blue)}

/* ============================ Generic sections =========================== */
.sec{padding:0 var(--s2)}
.sec h3{font-size:19px; margin:var(--s3) 0 var(--s2)}
.card{background:var(--card); border-radius:var(--r-lg); padding:var(--s2); box-shadow:var(--shadow-sm); margin-bottom:12px}
.row{display:flex; align-items:center; gap:12px}
.row .em{font-size:28px; flex:0 0 auto}
.row b{font-size:15.5px; display:block}
.row small{color:var(--ink-2); font-size:13px; font-weight:700}
.tag{margin-left:auto; font-weight:900; font-size:13px; color:var(--orange); white-space:nowrap}
.progress{height:10px; border-radius:99px; background:var(--bg-2); overflow:hidden; margin-top:8px}
.progress > i{display:block; height:100%; border-radius:99px; background:linear-gradient(90deg,var(--orange),var(--gold)); transition:width 600ms var(--spring)}

.grid4{display:grid; grid-template-columns:repeat(4,1fr); gap:10px}
.grid3{display:grid; grid-template-columns:repeat(3,1fr); gap:10px}
.grid2{display:grid; grid-template-columns:repeat(2,1fr); gap:10px}
.tile{
  aspect-ratio:1; border-radius:var(--r); background:var(--card); box-shadow:var(--shadow-sm);
  display:grid; place-items:center; font-size:34px; position:relative; border:3px solid transparent;
  transition:transform 160ms var(--spring);
}
.tile:active{transform:scale(.94)}
.tile.sel{border-color:var(--green)}
.tile.sel::after{content:'✓'; position:absolute; right:-6px; bottom:-6px; width:24px; height:24px; border-radius:50%; background:var(--green); color:#fff; font-size:14px; display:grid; place-items:center; font-weight:900}
.tile.locked{color:var(--ink-3); background:var(--bg-2)}
.tile .nm{position:absolute; bottom:5px; font-size:10.5px; font-weight:800; color:var(--ink-2)}
.tile .pr{position:absolute; top:5px; right:7px; font-size:11px; font-weight:900; color:var(--orange)}

.segs{display:flex; gap:6px; background:var(--bg-2); padding:5px; border-radius:999px; margin-bottom:var(--s2)}
.seg{flex:1; padding:9px; border-radius:999px; font-weight:800; font-size:14px; color:var(--ink-2); text-align:center}
.seg.on{background:var(--purple); color:#fff; box-shadow:var(--shadow-sm)}

/* profile header */
.phead{
  background:linear-gradient(160deg,var(--purple),#a855f7 60%,var(--pink));
  border-radius:0 0 var(--r-xl) var(--r-xl); padding:var(--s2) var(--s2) var(--s3);
  color:#fff; position:relative; overflow:hidden; text-align:center;
}
.phead .spark{position:absolute; font-size:16px; opacity:.5; animation:twinkle 3s ease-in-out infinite}
@keyframes twinkle{0%,100%{opacity:.2; transform:scale(.8)}50%{opacity:.85; transform:scale(1.15)}}
.pavatar{
  width:118px; height:118px; margin:var(--s2) auto 10px; border-radius:32px; border:5px solid #fff;
  background:radial-gradient(circle at 40% 30%,#fff,#e9f5ff); display:grid; place-items:center; font-size:62px;
  box-shadow:var(--shadow-lg); position:relative;
}
.pavatar .edit{position:absolute; right:-8px; bottom:-8px; width:34px; height:34px; border-radius:50%; background:#fff; color:var(--purple); display:grid; place-items:center; font-size:15px; box-shadow:var(--shadow-sm)}
.phead h2{font-size:26px}
/* Background is hard-coded white, so the text colour must be too — var(--ink)
   inverts in dark mode and made this read white-on-white. */
.lvlchip{display:inline-flex; gap:6px; align-items:center; background:#fff; color:#1f2340; padding:5px 14px; border-radius:999px; font-weight:900; font-size:14px; margin-top:6px}
.phead .xpbar{background:rgba(255,255,255,.3); height:10px; max-width:280px; margin:12px auto 4px}
.phead .xpbar > i{background:linear-gradient(90deg,var(--gold),#ffe066)}
.phead .xptxt{font-size:12px; font-weight:800; opacity:.9}
.statrow{
  display:grid; grid-template-columns:repeat(3,1fr); background:var(--card); border-radius:var(--r-lg);
  box-shadow:var(--shadow); margin:-20px var(--s2) var(--s2); padding:var(--s2) 0; position:relative; z-index:2;
}
.statrow div{text-align:center; border-right:1px solid var(--line)}
.statrow div:last-child{border-right:0}
.statrow .v{font-size:20px; font-weight:900; font-family:var(--font)}
.statrow .k{font-size:11.5px; color:var(--ink-2); font-weight:800}

/* toast / overlays */
.toast{
  position:fixed; left:50%; bottom:calc(var(--tab-h) + 20px); transform:translateX(-50%) translateY(20px);
  background:var(--toast-bg); color:var(--toast-fg); box-shadow:var(--shadow-lg);
  padding:12px 18px; border-radius:999px; font-weight:800; font-size:14px;
  opacity:0; pointer-events:none; transition:all 300ms var(--spring); z-index:200; max-width:90vw; text-align:center;
}
.toast.show{opacity:1; transform:translateX(-50%)}
/* keep achievement toasts clear of an open celebration sheet */
.sheet.open ~ .toast{bottom:auto; top:24px; transform:translateX(-50%) translateY(-20px)}
.sheet.open ~ .toast.show{transform:translateX(-50%)}

.sheet{position:fixed; inset:0; z-index:150; display:none; align-items:flex-end; justify-content:center; background:rgba(20,22,45,.55); backdrop-filter:blur(3px)}
.sheet.open{display:flex; animation:fadeUp 220ms ease}
.sheet-in{background:var(--card); width:100%; max-width:520px; border-radius:var(--r-xl) var(--r-xl) 0 0; padding:var(--s3) var(--s2) calc(var(--s3) + var(--safe-b)); animation:slideUp 320ms var(--spring); max-height:88dvh; overflow-y:auto}
.grab{width:44px; height:5px; border-radius:99px; background:var(--line); margin:-10px auto var(--s2)}
.sheet h3{text-align:center; font-size:22px; margin-bottom:6px}
.sheet .sub{text-align:center; color:var(--ink-2); font-weight:700; font-size:14px; margin-bottom:var(--s2)}
.bigmascot{font-size:80px; text-align:center; animation:cheer 800ms var(--spring)}

.switchrow{display:flex; align-items:center; gap:12px; padding:12px 0; border-bottom:1px solid var(--line)}
.switchrow:last-child{border-bottom:0}
.switchrow b{font-size:15px}
.sw{margin-left:auto; width:52px; height:30px; border-radius:99px; background:var(--line); position:relative; transition:background 200ms; flex:0 0 auto}
.sw::after{content:''; position:absolute; top:3px; left:3px; width:24px; height:24px; border-radius:50%; background:#fff; box-shadow:var(--shadow-sm); transition:transform 220ms var(--spring)}
.sw.on{background:var(--green)}
.sw.on::after{transform:translateX(22px)}

/* confetti */
#confetti{position:fixed; inset:0; pointer-events:none; z-index:300}
.cf{position:absolute; width:10px; height:14px; border-radius:2px; animation:fall 1.6s ease-in forwards}
@keyframes fall{to{transform:translateY(105vh) rotate(720deg); opacity:0}}
.coinfly{position:fixed; z-index:300; font-size:24px; pointer-events:none; animation:fly 850ms cubic-bezier(.4,0,.5,1) forwards}
@keyframes fly{to{transform:translate(var(--dx),var(--dy)) scale(.5); opacity:0}}

/* ============================ Desktop ==================================== */
.deskonly{display:none}
@media (min-width:1024px){
  .app{overflow:visible}

  body{background:
    radial-gradient(1200px 600px at 15% -10%, #dbeafe 0%, transparent 60%),
    radial-gradient(900px 500px at 90% 10%, #fae8ff 0%, transparent 60%),
    var(--bg);
    background-attachment:fixed;
  }
  html[data-theme="dark"] body{background:
    radial-gradient(1200px 600px at 15% -10%, #1e2a58 0%, transparent 60%),
    radial-gradient(900px 500px at 90% 10%, #34204f 0%, transparent 60%), var(--bg)}

  .deskonly{display:block}
  .app{
    max-width:1240px; display:grid; grid-template-columns:248px minmax(0,520px) 1fr;
    gap:var(--s3); padding:var(--s3) var(--s3) var(--s5); background:transparent; overflow:visible;
    align-items:start;
  }
  .screen{padding-bottom:0}
  .app > .topbar{display:none}

  /* left rail */
  .rail{
    position:sticky; top:var(--s3); background:var(--card); border-radius:var(--r-lg);
    padding:var(--s2); box-shadow:var(--shadow-sm);
  }
  .rail .brand{display:block; font-size:28px; padding:6px 8px var(--s2)}
  .rail .tab{flex-direction:row; gap:12px; justify-content:flex-start; padding:13px 14px; font-size:16px; border-radius:18px; margin-bottom:4px}
  .rail .tab .ti{font-size:24px}
  .rail .tab.is-active{background:rgba(139,92,246,.12)}
  .rail .tab:hover{background:var(--bg-2)}

  .center{min-width:0; background:var(--card); border-radius:var(--r-xl); box-shadow:var(--shadow); overflow:hidden; padding-bottom:var(--s2)}
  .center .hero,.center .mapwrap{margin-left:var(--s2); margin-right:var(--s2)}

  /* right panel */
  .aside{position:sticky; top:var(--s3); display:flex; flex-direction:column; gap:var(--s2)}
  .tabbar{display:none}
  #lesson{position:relative; inset:auto; max-width:none; margin:0; border-radius:var(--r-xl); box-shadow:var(--shadow-lg); min-height:640px; overflow:hidden}
  #lesson.open{display:flex}
  .lbody{padding-bottom:200px}
  .mapwrap{aspect-ratio:4/5}
  .cta{position:static}
  .hero h2{font-size:24px}
}
@media (max-width:1023px){ .rail,.aside{display:none} }

/* ==========================================================================
   WAYS TO LEARN — the five approaches (Learn screen + their overlays)
   Everything below is mobile-first; the overlay is the same #lesson panel the
   quests use, tagged with data-mode so each way can style its own space.
   ========================================================================== */

/* ---- the five cards on the Learn screen ---- */
.wayscard{
  width:100%; display:flex; align-items:center; gap:12px; text-align:left;
  padding:14px; margin-bottom:10px; border-radius:var(--r);
  background:var(--card); box-shadow:var(--shadow-sm);
  transition:transform 160ms var(--spring), box-shadow 160ms;
}
.wayscard:active{transform:scale(.975); box-shadow:var(--shadow)}
.way-em{font-size:32px; flex:0 0 46px; text-align:center}
.way-txt{min-width:0; flex:1}
.way-txt b{display:block; font-family:var(--font); font-size:17px; line-height:1.2}
.way-txt small{display:block; color:var(--ink-2); font-weight:700; font-size:12.5px; margin-top:3px}
.way-go{color:var(--ink-3); font-size:15px; flex:0 0 auto}

/* ---- pinning a way to the top of Learn ----
   The star is a real hit target (44px) sitting inside the card, so it is
   padded rather than sized: a 15px glyph you have to hit exactly is a star
   nobody taps on a phone. */
.way-fav{
  flex:0 0 auto; display:flex; align-items:center; justify-content:center;
  width:40px; height:40px; margin:-8px 0; border-radius:50%;
  font-size:19px; line-height:1; color:var(--ink-3); cursor:pointer;
  transition:transform 220ms var(--spring), color 160ms;
}
.way-fav:hover{color:var(--ink-2)}
.way-fav.on{color:#ffb300; transform:scale(1.12)}
.way-fav:active{transform:scale(.82)}
.way-fav.on:active{transform:scale(1)}

/* ---- a module that has only just shipped ---- */
.newcard{
  background:linear-gradient(135deg, rgba(124,92,255,.10), rgba(255,138,203,.10)), var(--card);
  box-shadow:0 0 0 2px rgba(124,92,255,.28), var(--shadow-sm);
}
.newpip{
  display:inline-block; vertical-align:2px; margin-left:6px; padding:2px 7px;
  border-radius:999px; background:var(--purple); color:#fff;
  font-size:9.5px; font-weight:900;
  letter-spacing:.6px;
}
.favhint{
  color:var(--ink-2); font-weight:700; font-size:12.5px;
  margin:-4px 0 10px 2px;
}

/* ============================ 1 · Flashcards ============================= */
.fc-wrap{display:flex; flex-direction:column; align-items:center; gap:10px}
.fc-meta{display:flex; align-items:center; justify-content:space-between; width:100%; max-width:340px}
.fc-box{letter-spacing:3px; color:var(--green-d); font-size:13px}
.fc-flip-dir{
  font-size:12px; font-weight:900; color:var(--ink-2); background:var(--bg-2);
  padding:6px 11px; border-radius:99px; min-height:32px;
}
.fc{width:100%; max-width:340px; aspect-ratio:5/6; perspective:1200px; cursor:pointer}
.fc-in{
  position:relative; width:100%; height:100%;
  transform-style:preserve-3d; transition:transform 460ms var(--spring);
}
.fc.is-flipped .fc-in{transform:rotateY(180deg)}
.fc-face{
  position:absolute; inset:0; backface-visibility:hidden; -webkit-backface-visibility:hidden;
  border-radius:var(--r-lg); background:var(--card); box-shadow:var(--shadow);
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  padding:20px; text-align:center; border:3px solid var(--line);
}
.fc-front{background:linear-gradient(160deg,#eaf3ff,#f6ecff)}
html[data-theme="dark"] .fc-front{background:linear-gradient(160deg,#22305a,#2c2450)}
.fc-back{transform:rotateY(180deg); background:linear-gradient(160deg,#eafbe6,#fff9e6)}
html[data-theme="dark"] .fc-back{background:linear-gradient(160deg,#1f3a29,#3a3320)}
.fc-hint{
  font-size:11px; font-weight:900; letter-spacing:1.4px; text-transform:uppercase;
  color:var(--ink-3); margin-bottom:10px;
}
.fc-t{font-family:var(--font); font-size:34px; line-height:1.15; color:var(--ink); word-break:break-word}
.fc-t.en{font-family:var(--font-ui); font-size:26px; font-weight:900}
.fc-r{font-size:14px; font-weight:800; color:var(--ink-2); margin-top:8px}
.fc-tap{position:absolute; bottom:14px; font-size:11.5px; font-weight:800; color:var(--ink-3)}
.fc-play{position:static; margin-top:16px}
/* The front's replay sits above "tap to flip" rather than in the middle of
   the face, so the word itself stays the thing you read. */
.fc-play.one{margin-top:14px; transform:scale(.86)}

/* ---- hear either language, from the back of the card ---- */
.fc-says{display:flex; gap:10px; margin-top:16px; flex-wrap:wrap; justify-content:center}
.fc-say{
  display:flex; align-items:center; gap:7px;
  padding:9px 14px; border-radius:999px;
  background:var(--card); box-shadow:var(--shadow-sm); border:2px solid var(--line);
  font-weight:900; font-size:13px; color:var(--ink);
  transition:transform 160ms var(--spring);
}
.fc-say:active{transform:scale(.93)}
.fc-say-f{font-size:15px; line-height:1}
.fc-say-l{max-width:88px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.fc-say-i{font-size:13px; opacity:.75}
.fc-swipe{font-size:11.5px; font-weight:800; color:var(--ink-3); margin:2px 0 0; text-align:center}
.fc-grade{display:grid; grid-template-columns:1fr 1fr 1fr; gap:8px}
.fc-grade .btn{padding:16px 6px; font-size:15px}
.fc.fly-left{transform:translateX(-120%) rotate(-14deg); opacity:0; transition:all 180ms ease-in}
.fc.fly-right{transform:translateX(120%) rotate(14deg); opacity:0; transition:all 180ms ease-in}

/* ============================== 2 · Writing ============================== */
.wr{display:flex; flex-direction:column; gap:14px}
.wr-tabs{display:flex; gap:8px; background:var(--bg-2); padding:5px; border-radius:99px}
.wr-tab{
  flex:1; padding:11px 8px; border-radius:99px; font-weight:900; font-size:14px;
  color:var(--ink-2); min-height:44px;
}
.wr-tab.on{background:var(--card); color:var(--ink); box-shadow:var(--shadow-sm)}
.wr-prompt{
  position:relative; text-align:center; background:var(--card); border-radius:var(--r);
  padding:18px 56px 18px 18px; box-shadow:var(--shadow-sm);
}
.wr-prompt small{display:block; color:var(--ink-3); font-weight:800; font-size:12px; margin-bottom:5px}
.wr-prompt b{font-family:var(--font); font-size:26px; line-height:1.2; word-break:break-word}
.wr-prompt.small b{font-size:22px}
.wr-play{position:absolute; right:12px; top:50%; transform:translateY(-50%)}

.pad-wrap{
  position:relative; width:100%; max-width:340px; margin:0 auto; aspect-ratio:1;
  border-radius:var(--r); background:var(--card); box-shadow:var(--shadow-sm);
  border:3px dashed var(--line); overflow:hidden; touch-action:none;
}
.pad,.pad-ghost{position:absolute; inset:0; width:100%; height:100%; display:block}
.pad{touch-action:none; cursor:crosshair}

/* ============================= 3 · Car Mode ============================== */
#lesson[data-mode="car"]{background:linear-gradient(180deg,#151a35,#0d1024)}
#lesson[data-mode="car"] #ltitle{color:#aeb6ff}
.car{display:flex; flex-direction:column; align-items:center; gap:16px; color:#fff; padding-top:4px}
.car-step{
  font-weight:900; font-size:14px; letter-spacing:.6px; color:#ffd76a;
  min-height:20px; text-align:center;
}
.car-card{
  width:100%; border-radius:var(--r-lg); padding:26px 18px; text-align:center;
  background:rgba(255,255,255,.07); border:1px solid rgba(255,255,255,.14);
}
.car-en{font-size:17px; font-weight:800; color:#c9cffb}
.car-t{
  font-family:var(--font); font-size:38px; line-height:1.15; margin-top:10px; color:#fff;
  word-break:break-word; transition:color 200ms, text-shadow 200ms;
}
.car-t.lit{color:#ffd76a; text-shadow:0 0 24px rgba(255,215,106,.5)}
.car-r{font-size:15px; font-weight:800; color:#9aa2dd; margin-top:8px}
.car-next{font-size:12.5px; font-weight:800; color:#7f88c4}
.car-controls{display:flex; align-items:center; justify-content:center; gap:22px}
.car-btn{
  width:64px; height:64px; border-radius:50%; font-size:26px; color:#fff;
  background:rgba(255,255,255,.10); display:grid; place-items:center;
}
.car-btn:active{transform:scale(.92)}
.car-play{
  width:92px; height:92px; border-radius:50%; font-size:38px; color:#12142b;
  background:linear-gradient(160deg,#ffd76a,#ff9600); display:grid; place-items:center;
  box-shadow:0 8px 28px rgba(255,150,0,.42);
}
.car-play:active{transform:scale(.94)}
.car-opts{width:100%; display:flex; flex-direction:column; gap:10px}
.car-opt{display:flex; align-items:center; justify-content:space-between; gap:10px}
.car-opt>span{font-size:13px; font-weight:900; color:#aeb6ff; flex:0 0 auto}
.car-seg{display:flex; gap:5px; background:rgba(255,255,255,.08); padding:4px; border-radius:99px}
.car-seg button{
  padding:9px 13px; border-radius:99px; font-size:12.5px; font-weight:900; color:#c9cffb;
  min-height:38px;
}
.car-seg button.on{background:#fff; color:#12142b}
.car-note{font-size:12px; font-weight:800; color:#7f88c4; text-align:center; margin:0}

/* =========================== 4 · Conversation ============================ */
.cv{display:flex; flex-direction:column; gap:12px}
.cv-log{display:flex; flex-direction:column; gap:8px}
.cv-log:empty{display:none}
.cv-line{display:flex; align-items:flex-end; gap:8px}
.cv-line.mine{flex-direction:row-reverse}
.cv-who{
  flex:0 0 38px; width:38px; height:38px; border-radius:50%; background:var(--bg-2);
  display:grid; place-items:center; font-size:21px;
}
.cv-bub{
  flex:1; min-width:0; text-align:left; background:var(--card); border-radius:18px;
  padding:11px 14px; box-shadow:var(--shadow-sm); position:relative;
}
.cv-line.mine .cv-bub{background:var(--blue); color:#fff}
.cv-line.mine .cv-bub small{color:rgba(255,255,255,.82)}
.cv-bub b{display:block; font-family:var(--font); font-size:19px; line-height:1.2}
.cv-bub i{display:block; font-size:12px; font-weight:800; color:var(--ink-3); font-style:normal}
.cv-bub small{display:block; font-size:12.5px; font-weight:800; color:var(--ink-2); margin-top:2px}
.cv-bub.speak{padding-right:42px}
.cv-spk{position:absolute; right:12px; top:50%; transform:translateY(-50%); font-size:17px}
.cv-scene{
  background:var(--bg-2); border-radius:var(--r-sm); padding:12px 14px;
  font-weight:800; font-size:13.5px; color:var(--ink-2); line-height:1.45;
  border-left:4px solid var(--purple);
}
.cv-ask{font-weight:900; font-size:14px; color:var(--ink-2); margin:2px 0 0; text-align:center}
.cv-replies{display:flex; flex-direction:column; gap:8px}
.cv-reply{
  width:100%; text-align:left; padding:13px 15px; border-radius:var(--r);
  background:var(--card); box-shadow:var(--shadow-sm); border:2px solid transparent;
  transition:transform 140ms var(--spring), border-color 140ms;
  min-height:56px;
}
.cv-reply:active{transform:scale(.98)}
.cv-reply b{display:block; font-family:var(--font); font-size:18px; line-height:1.2}
.cv-reply small{display:block; font-size:12px; font-weight:800; color:var(--ink-2); margin-top:2px}
.cv-reply.good{border-color:var(--green); background:rgba(88,204,2,.12)}
.cv-reply.bad{border-color:var(--red); opacity:.5; text-decoration:line-through}
.cv-mic-row{display:flex; align-items:center; justify-content:center; gap:12px; margin-top:2px}
.cv-mic{width:64px; height:64px; font-size:27px}
.cv-mic-hint{font-size:12.5px; font-weight:800; color:var(--ink-3)}

/* ========================== 5 · Manga Stories ============================= */
.lib{display:flex; flex-direction:column; gap:10px}
.lib-intro{font-size:13.5px; font-weight:700; color:var(--ink-2); line-height:1.5; margin:0 0 4px}
.lib-card{
  width:100%; display:flex; align-items:center; gap:12px; text-align:left;
  padding:14px; border-radius:var(--r); background:var(--card); box-shadow:var(--shadow-sm);
  border-left:6px solid var(--tc,var(--purple));
  transition:transform 160ms var(--spring);
}
.lib-card:active{transform:scale(.977)}
.lib-em{font-size:32px; flex:0 0 42px; text-align:center}
.lib-txt{flex:1; min-width:0}
.lib-txt b{display:block; font-family:var(--font); font-size:17px; line-height:1.2}
.lib-txt small{display:block; font-size:12.5px; font-weight:700; color:var(--ink-2); margin:3px 0 7px}
.lib-bar{display:block; height:6px; border-radius:99px; background:var(--bg-2); overflow:hidden}
.lib-bar i{display:block; height:100%; border-radius:99px; background:var(--tc,var(--purple)); transition:width 400ms}
.lib-go{flex:0 0 auto; color:var(--ink-3); font-size:16px; font-weight:900}

.rd{display:flex; flex-direction:column; gap:12px}
.rd-bar{display:flex; justify-content:center}
.rd-seg{display:flex; gap:4px; background:var(--bg-2); padding:4px; border-radius:99px; max-width:100%}
.rd-seg button{
  padding:9px 12px; border-radius:99px; font-size:12.5px; font-weight:900;
  color:var(--ink-2); white-space:nowrap; min-height:40px;
}
.rd-seg button.on{background:var(--card); color:var(--ink); box-shadow:var(--shadow-sm)}
.rd-panel{cursor:pointer}
.rd-name{
  display:block; font-size:10.5px; font-weight:900; letter-spacing:1.2px;
  text-transform:uppercase; color:#8d93bb; margin-bottom:4px;
}
.rd-t{display:block}
.rd-t .w{transition:background 140ms, color 140ms; border-radius:6px; padding:0 1px}
.rd-t .w.lit{background:#ffd76a; color:#3a2c00; box-shadow:0 0 0 3px #ffd76a}
.rd-t .vw{
  text-decoration:underline; text-decoration-style:dotted; text-decoration-thickness:2px;
  text-underline-offset:3px; text-decoration-color:var(--purple); cursor:pointer;
}
.rd-tools{display:flex; gap:8px}
.rd-tool{
  flex:1; padding:13px 8px; border-radius:var(--r-sm); background:var(--card);
  box-shadow:var(--shadow-sm); font-weight:900; font-size:13.5px; color:var(--ink-2);
  min-height:46px;
}
.rd-tool.on{background:var(--purple); color:#fff}
.rd-tip{font-size:12px; font-weight:800; color:var(--ink-3); text-align:center; margin:0}
.rd-tip .vw{
  text-decoration:underline; text-decoration-style:dotted; text-decoration-thickness:2px;
  text-decoration-color:var(--purple);
}
.gl-t{font-family:var(--font); font-size:36px; line-height:1.15; color:var(--blue-d)}
html[data-theme="dark"] .gl-t{color:#8ab4ff}
.gl-r{font-size:15px; font-weight:800; color:var(--ink-3); margin-top:4px}
.gl-en{font-size:19px; font-weight:900; color:var(--ink-2); margin-top:8px}

/* ---- extra manga backgrounds + the scenery/prop layers ---- */
.mg-scene{position:absolute; inset:0; width:100%; height:100%; pointer-events:none; opacity:.75}
.mg-prop{position:absolute; right:8px; top:8px; width:46px; height:34px; pointer-events:none; opacity:.9}
.mg-panel.bg-sea{background:linear-gradient(180deg,#cdeffb,#eef9ff)}
.mg-panel.bg-canoe{background:linear-gradient(180deg,#bde8f8,#eaf7ff)}
.mg-panel.bg-volcano{background:linear-gradient(180deg,#ffd9c2,#fff1e6)}
.mg-panel.bg-store{background:linear-gradient(180deg,#ffe3e3,#fff5f5)}
.mg-panel.bg-warehouse{background:linear-gradient(180deg,#e6ecff,#f6f8ff)}
.mg-panel.bg-farm{background:linear-gradient(180deg,#e3f7cf,#f7fdef)}
html[data-theme="dark"] .mg-panel.bg-sea,html[data-theme="dark"] .mg-panel.bg-canoe,
html[data-theme="dark"] .mg-panel.bg-volcano,html[data-theme="dark"] .mg-panel.bg-store,
html[data-theme="dark"] .mg-panel.bg-warehouse,html[data-theme="dark"] .mg-panel.bg-farm{background:#232848}

/* ---- desktop: give the wide surfaces room without breaking the phone ---- */
@media (min-width:1024px){
  .fc{max-width:380px}
  .pad-wrap{max-width:380px}
  .car-card{max-width:460px}
}

/* ==========================================================================
   Fixes from the first visual pass (screenshots/modeshot.py)
   ========================================================================== */

/* The overlay counter is a plain "3 / 12" in the learning modes, not hearts.
   Inheriting .hearts made every mode shout a red number at the learner. */
#lesson[data-mode] .hearts{color:var(--ink-2)}

/* "Again" is the one destructive-feeling grade and had no colour of its own,
   so it rendered in the default green next to "Good". */
.btn.red{background:var(--red); box-shadow:0 5px 0 var(--red-d)}
.btn.red:active{box-shadow:0 1px 0 var(--red-d)}

/* Flashcards: fill the space instead of stranding the card at the top, and
   keep the target word paired with its pronunciation on the back. */
.fc-wrap{justify-content:center; min-height:calc(100% - 8px); padding-bottom:8px}
.fc{aspect-ratio:4/5}
.fc-pair{
  margin-top:14px; padding-top:12px; border-top:2px solid rgba(31,35,64,.10);
  width:80%; max-width:240px;
}
.fc-pair b{font-family:var(--font); font-size:21px; line-height:1.15; display:block}
.fc-pair .fc-r{margin-top:2px; font-size:13px}

/* Car Mode is the only dark surface in the app. Its footer and close button
   were still wearing the light theme. */
#lesson[data-mode="car"] .lfoot{
  background:transparent; border-top:1px solid rgba(255,255,255,.14);
}
#lesson[data-mode="car"] .lfoot .btn.ghost{color:#dfe3ff; border-color:rgba(255,255,255,.28)}
#lesson[data-mode="car"] #lquit{color:#dfe3ff}
#lesson[data-mode="car"] .hearts{color:#8f97d6}
#lesson[data-mode="car"] .lbar{background:rgba(255,255,255,.14)}

/* The story prop sat under the speech bubble in the top-right corner. Park it
   in the caption strip, where nothing else ever goes. */
.mg-prop{right:12px; top:auto; bottom:12px}
.rd-panel .mg-note{padding-right:62px}

/* Sit the prop ON the caption strip, not washed out behind it. */
.mg-prop{z-index:2}

/* Japanese and Chinese break between any two characters by default, which split
   あお / い！ and ミラ / ナ！ across lines and destroyed the word the reader was
   meant to be learning. The tale lines are authored WITH spaces, so keep-all
   gives exactly the right break points; break-word is only the escape hatch for
   a single token longer than the bubble. */
.mg-t,.rd-t,.car-t,.fc-t{word-break:keep-all; overflow-wrap:break-word}
.rd-t .w{display:inline-block}

/* The props are small cast members now (the cow, the pig, the red ball), not
   corner doodles. */
.mg-prop{width:60px; height:44px; opacity:1}
.rd-panel .mg-note{padding-right:74px}

/* A white cow on a near-white caption strip vanished. */
.mg-prop{filter:drop-shadow(0 1px 2px rgba(31,35,64,.35))}

/* On desktop .app becomes a 3-column grid and #lesson is one of its children,
   so the overlay was auto-placed into row 2 / column 1 — a 248px-wide strip on
   top of the nav rail, one word per line. Pin it to the centre column's cell;
   it is opaque, so it covers the screen behind it exactly as on a phone. */
@media (min-width:1024px){
  /* Placing only #lesson made auto-placement shunt .center into column 3 and
     .aside onto a second row. Pin all four, and let the overlay share the
     centre cell — it is opaque and comes last in the DOM, so it paints over
     the screen behind it exactly as it does on a phone. */
  .rail  {grid-column:1; grid-row:1}
  .center{grid-column:2; grid-row:1}
  .aside {grid-column:3; grid-row:1}
  #lesson{grid-column:2; grid-row:1; align-self:start}
}

/* ---- flashcards are a deck you page through, not a test ---- */
.fc-nav{display:grid; grid-template-columns:1fr 1.4fr; gap:10px}
.fc-nav .btn{padding:16px 8px}
.fc-src{
  font-size:11.5px; font-weight:900; color:var(--ink-3); letter-spacing:.3px;
  text-transform:uppercase;
}

/* Where a Car Mode phrase came from — quests and stories are mixed together
   in one playlist, so it has to say which. */
.car-src{font-size:12px; font-weight:800; color:#8f97d6; margin-top:-8px}

/* ---- voice picker in Settings ---- */
.voicerow{padding:10px 0; border-bottom:1px solid var(--line)}
.voicerow:last-child{border-bottom:0}
.voicerow > b{display:block; font-size:14.5px; margin-bottom:7px}
.voicectl{display:flex; gap:8px; align-items:center}
.voicesel{
  flex:1; min-width:0; font-family:var(--font-ui); font-weight:800; font-size:14px;
  color:var(--ink); background:var(--bg-2); border:2px solid var(--line);
  border-radius:14px; padding:11px 12px; min-height:46px; appearance:none;
}
.voicesel:focus{outline:none; border-color:var(--blue)}
.voicetry{position:static; flex:0 0 46px; width:46px; height:46px; font-size:19px}

/* phrasebook sub-headings (Key words / Every line) */
.pb-sub{
  font-size:11px; font-weight:900; letter-spacing:1.2px; text-transform:uppercase;
  color:var(--ink-3); margin:12px 0 2px;
}

/* ---- autoplay toggle (Speaking Gym + the teach card) ---- */
.autochip{
  display:inline-flex; align-items:center; gap:7px; margin:12px auto 2px;
  padding:9px 15px; border-radius:99px; min-height:40px;
  background:var(--bg-2); color:var(--ink-3);
  font-weight:900; font-size:12.5px; letter-spacing:.2px;
  border:2px solid transparent; transition:all 160ms var(--spring);
}
.autochip.on{background:rgba(59,130,246,.13); color:var(--blue-d); border-color:rgba(59,130,246,.35)}
html[data-theme="dark"] .autochip.on{color:#8ab4ff}
.autochip:active{transform:scale(.95)}
.ac-ic{font-size:15px; line-height:1}

/* The word bubble is full width now that the mascot tile is gone, so the play
   button can no longer hang off its bottom-right corner — it centres on the
   bottom edge instead. */
.bubblewrap{margin-bottom:34px}
.bubble .playbtn{right:auto; left:50%; transform:translateX(-50%); bottom:-23px}
.bubble .playbtn:active{transform:translateX(-50%) translateY(3px)}

/* room for the play button now that it sits on the bubble edge */
.bubblewrap .bubble{padding-bottom:32px}

/* ---- session setup sheet (Speaking Gym) ---- */
.setup-lbl{
  display:flex; align-items:center; justify-content:space-between;
  font-size:11.5px; font-weight:900; letter-spacing:1.2px; text-transform:uppercase;
  color:var(--ink-3); margin:16px 0 8px;
}
.setup-all{
  font-size:11.5px; font-weight:900; color:var(--blue-d); letter-spacing:0;
  text-transform:none; padding:6px 10px; border-radius:99px; background:var(--bg-2);
  min-height:32px;
}
.setup-seg{display:grid; grid-template-columns:1fr 1fr 1fr; gap:6px;
  background:var(--bg-2); padding:5px; border-radius:20px}
.setup-seg button{
  padding:11px 6px; border-radius:16px; font-weight:900; font-size:14px;
  color:var(--ink-2); min-height:52px; display:grid; gap:1px; place-items:center;
}
.setup-seg button.on{background:var(--card); color:var(--ink); box-shadow:var(--shadow-sm)}
.setup-seg button i{font-style:normal; font-size:11px; font-weight:800; color:var(--ink-3)}
.setup-seg button.on i{color:var(--blue-d)}

.setup-groups{display:flex; flex-direction:column; gap:6px; max-height:44vh; overflow-y:auto}
.setup-grp{
  display:flex; align-items:center; gap:10px; width:100%; text-align:left;
  padding:11px 12px; border-radius:16px; background:var(--bg-2);
  border:2px solid transparent; min-height:56px;
}
.setup-grp.on{background:rgba(59,130,246,.10); border-color:rgba(59,130,246,.4)}
.setup-grp.empty{opacity:.45}
.sg-ic{font-size:22px; flex:0 0 26px; text-align:center}
.sg-tx{flex:1; min-width:0}
.sg-tx b{display:block; font-size:14.5px; line-height:1.2}
.sg-tx small{display:block; font-size:11.5px; font-weight:800; color:var(--ink-3); margin-top:1px}
.sg-ck{flex:0 0 22px; text-align:center; font-weight:900; color:var(--blue-d); font-size:16px}

/* ============================== 6 · Numbers ============================== */
.num{display:flex; flex-direction:column; gap:12px}
.num-intro{font-size:13.5px; font-weight:700; color:var(--ink-2); margin:0; text-align:center}
.num-grid{display:grid; grid-template-columns:repeat(3,1fr); gap:8px}
.num-cell{
  padding:11px 6px; border-radius:16px; background:var(--card); box-shadow:var(--shadow-sm);
  display:grid; gap:1px; place-items:center; min-height:74px; transition:transform 140ms var(--spring);
}
.num-cell:active{transform:scale(.95)}
.num-cell.lit{background:rgba(59,130,246,.15); box-shadow:0 0 0 2px var(--blue)}
.num-cell b{font-size:21px; font-family:var(--font-ui); font-weight:900; color:var(--blue-d)}
html[data-theme="dark"] .num-cell b{color:#8ab4ff}
.num-cell span{font-family:var(--font); font-size:14px; line-height:1.15; text-align:center; word-break:break-word}
.num-cell i{font-style:normal; font-size:10.5px; font-weight:800; color:var(--ink-3); text-align:center}
.num-big{
  font-family:var(--font-ui); font-weight:900; font-size:76px; line-height:1;
  text-align:center; color:var(--blue-d); margin:6px 0 10px;
}
html[data-theme="dark"] .num-big{color:#8ab4ff}
.num-word{text-align:center; font-size:15px; font-weight:800; color:var(--ink-3); min-height:20px}
.num-play{width:104px; height:104px; font-size:40px; margin:6px auto 4px;
  background:linear-gradient(160deg,#4aa3f5,#2f7fe0); box-shadow:0 8px 0 #1f63b8}
.num-opts{display:grid; grid-template-columns:repeat(3,1fr); gap:9px; margin-top:16px}
.num-opt{
  padding:18px 6px; border-radius:18px; background:var(--card); box-shadow:var(--shadow-sm);
  font-family:var(--font-ui); font-weight:900; font-size:24px; color:var(--ink);
  border:2px solid transparent; min-height:64px;
}
.num-opt:active{transform:scale(.96)}
.num-opt.good{border-color:var(--green); background:rgba(88,204,2,.15); color:var(--green-d)}
.num-opt.bad{border-color:var(--red); opacity:.45; text-decoration:line-through}

/* long romanizations (diecinueve -> dyeh-see-NWEH-veh) were clipped */
.num-cell i{font-size:9.5px; line-height:1.2; word-break:break-word; overflow-wrap:anywhere}
.num-cell{min-height:82px}

/* ============================ Story Studio =============================== */
.studiocard{border:2px dashed var(--purple); background:rgba(139,92,246,.06)}
.stu{display:flex; flex-direction:column}
.stu-intro{font-size:13.5px; font-weight:700; color:var(--ink-2); line-height:1.5; margin:0 0 14px}
.stu-empty{font-size:13.5px; font-weight:700; color:var(--ink-3); text-align:center; padding:14px 0}
.stu-row,.stu-panel{
  display:flex; align-items:center; gap:8px; padding:10px 12px; margin-bottom:8px;
  border-radius:16px; background:var(--card); box-shadow:var(--shadow-sm);
}
.stu-em{font-size:24px; flex:0 0 30px; text-align:center}
.stu-num{
  flex:0 0 26px; height:26px; border-radius:50%; background:var(--bg-2);
  display:grid; place-items:center; font-weight:900; font-size:12.5px; color:var(--ink-2);
}
.stu-tx{flex:1; min-width:0}
.stu-tx b{display:block; font-size:14.5px; line-height:1.25;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.stu-tx small{display:block; font-size:11.5px; font-weight:800; color:var(--ink-3); margin-top:1px}
.stu-act{
  flex:0 0 40px; width:40px; height:40px; border-radius:12px; background:var(--bg-2);
  display:grid; place-items:center; font-size:15px; color:var(--ink-2);
}
.stu-act.wide{flex:0 0 auto; width:auto; padding:0 14px; font-size:12.5px; font-weight:900}
/* the prompt the story was written from, kept beside the title */
.stu-prompt{color:var(--purple); font-style:italic;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
/* four actions (read / edit / share / delete) have to fit a 390px phone */
@media (max-width:430px){
  .stu-act{flex:0 0 34px; width:34px; height:34px; font-size:14px; border-radius:11px}
  .stu-row{gap:6px}
}
.stu-act:active{transform:scale(.92)}
.stu-act[disabled]{opacity:.3; pointer-events:none}
.stu-field{display:block; margin-bottom:10px}
.stu-field > span{
  display:block; font-size:11.5px; font-weight:900; letter-spacing:1.1px;
  text-transform:uppercase; color:var(--ink-3); margin-bottom:5px;
}
.stu-field .teach-input,.stu-field .voicesel{width:100%; text-align:left; font-size:15px}
.stu-field.row-field{display:flex; align-items:center; justify-content:space-between}
.stu-field.row-field > span{margin:0}
#stuprev{margin-bottom:16px}

/* Words you can tap to hear. They are <button>s now, so re-assert the block
   layout the divs used to have and give a little press feedback. */
.tappable{
  display:block; width:100%; text-align:center; font:inherit; color:inherit;
  border-radius:14px; padding:2px 4px; transition:background 140ms, transform 140ms;
}
.tappable:active{transform:scale(.97); background:rgba(59,130,246,.12)}
.bubble .tt.tappable{font-family:var(--font); font-size:26px; font-weight:800; line-height:1.15; color:var(--blue-d)}
html[data-theme="dark"] .bubble .tt.tappable{color:#8ab4ff}
.bubble .ee.tappable{font-size:15px; color:var(--ink-2); font-weight:700; margin-top:6px}
.bubble .rr.tappable{font-size:13px; color:var(--ink-3); font-weight:700; margin-top:2px}
.num-big.tappable{width:100%}

.stu-hint{font-size:12px; font-weight:800; color:var(--purple); text-align:center; margin:6px 0 10px}
.stu-hint.off{color:var(--ink-3)}

/* ---- topic packs (grocery, restaurant, transportation, aikido, Top 100) ---- */
.tp-list{display:flex; flex-direction:column; gap:8px; text-align:left}
.tp-row{
  display:flex; align-items:center; gap:10px; width:100%; text-align:left;
  padding:12px 14px; border-radius:16px; background:var(--card);
  box-shadow:var(--shadow-sm); min-height:60px;
  transition:transform 140ms var(--spring), box-shadow 140ms;
}
.tp-row:active{transform:scale(.98)}
.tp-row.lit{box-shadow:0 0 0 2px var(--blue)}
.tp-tx{flex:1; min-width:0}
.tp-tx b{display:block; font-family:var(--font); font-size:18px; line-height:1.2; word-break:break-word}
.tp-tx i{display:block; font-style:normal; font-size:12px; font-weight:800; color:var(--ink-3); margin-top:1px}
.tp-tx small{display:block; font-size:12.5px; font-weight:800; color:var(--ink-2); margin-top:2px}

/* ==========================================================================
   GAMES  (assets/js/games.js)
   The arcade is louder than the rest of the app on purpose — bigger type,
   harder colour, more motion. It still has to fit a 390px phone with no
   sideways scroll, so every board is a percentage grid, never fixed px.
   ========================================================================== */
.g-best{font-size:12px; font-weight:900; color:var(--orange)}

/* A game board is not a document: it must fit the phone in one piece, because
   a player cannot scroll to find the square they are about to jump to. The
   overlay body therefore stops scrolling and hands its height to the board. */
/* .lfoot is absolutely positioned over the bottom of the body, so a board that
   merely "fits the body" still ends up half under the scoreboard. Leave it
   room. */
#lesson[data-mode="song"] .lbody,
#lesson[data-mode="game"] .lbody{
  overflow:hidden; padding-bottom:96px; display:flex; flex-direction:column; min-height:0;
}
#lesson[data-mode="game"] .lbody > .rl,
#lesson[data-mode="game"] .lbody > .pp,
#lesson[data-mode="game"] .lbody > .as,
#lesson[data-mode="song"] .lbody > .sg,
#lesson[data-mode="game"] .lbody > .sy{flex:1; min-height:0}
/* the category picker in front of each game is an ordinary scrolling list */
#lesson[data-mode="game"] .lbody > .stu{overflow-y:auto; padding-bottom:120px}

/* ---- 🚦 Red Light, Green Light ---- */
.rl{display:flex; flex-direction:column; gap:10px}
.rl-hud{display:flex; flex-direction:column; gap:6px; align-items:center}
.rl-light{
  display:flex; align-items:center; gap:9px; padding:9px 18px; border-radius:99px;
  font-family:var(--font); font-size:16px; background:var(--bg-2); color:var(--ink-2);
  transition:background 160ms, color 160ms;
}
.rl-light .rl-dot{width:13px; height:13px; border-radius:50%; background:currentColor}
.rl-light.go{background:rgba(88,204,2,.16); color:var(--green-d)}
.rl-light.stop{background:rgba(255,75,75,.16); color:var(--red-d); animation:rlpulse .9s ease-in-out infinite}
@keyframes rlpulse{0%,100%{transform:scale(1)}50%{transform:scale(1.045)}}
.rl-task{font-size:13px; font-weight:800; color:var(--ink-2); text-align:center}
.rl-task b{color:var(--purple)}

.rl-board{
  display:grid; grid-template-columns:repeat(var(--cols),1fr);
  grid-auto-rows:minmax(0,1fr); gap:6px; flex:1; min-height:0;
}
.rl-cell{
  position:relative; min-height:46px; border-radius:16px; padding:5px 3px;
  background:var(--card); box-shadow:var(--shadow-sm); border:2px solid transparent;
  display:grid; place-items:center; overflow:hidden;
  transition:transform 160ms var(--spring), border-color 160ms, opacity 160ms;
}
.rl-face{display:block; text-align:center; padding:0 2px; min-width:0}
.rl-face b{
  display:block; font-family:var(--font); font-size:clamp(12px,3.4vw,15px); line-height:1.12;
  word-break:break-word; hyphens:auto;
  /* three lines is all a square can hold — better clipped than overflowing */
  display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden;
}
.rl-face small{display:block; font-size:10.5px; font-weight:800; color:var(--ink-3); margin-top:1px}
.rl-back{
  position:absolute; inset:0; display:none; place-items:center;
  font-family:var(--font); font-size:26px; color:#fff;
  background:linear-gradient(160deg,#ff6b6b,#e03e3e);
}
.rl-board.is-red .rl-face{visibility:hidden}
.rl-board.is-red .rl-back{display:grid}
.rl-cell.near{border-color:var(--green); box-shadow:0 0 0 3px rgba(88,204,2,.2)}
.rl-cell.here{border-color:var(--purple); background:rgba(139,92,246,.12)}
.rl-cell.trail{opacity:.5}
.rl-cell.hop{animation:rlhop 320ms var(--spring)}
@keyframes rlhop{0%{transform:scale(1)}45%{transform:scale(1.12)}100%{transform:scale(1)}}
.rl-cell.bust{animation:rlbust 420ms ease; border-color:var(--red)}
@keyframes rlbust{0%,100%{transform:none}25%{transform:translateX(-7px)}75%{transform:translateX(7px)}}
.rl-board.shake{animation:rlbust 460ms ease}

.rl-kerb{
  display:flex; align-items:center; gap:10px; padding:8px 14px; border-radius:16px;
  background:var(--bg-2); font-size:12.5px; font-weight:800; color:var(--ink-3);
}
.rl-you{font-size:26px; transition:opacity 200ms}
.rl-you svg{width:30px; height:30px}
.rl-hint{font-size:12px; font-weight:800; color:var(--ink-3); text-align:center; margin:0}

/* ---- shared score bar (Speed Round, Balloon Pop) ---- */
.sp-hud{display:flex; align-items:center; justify-content:space-between; gap:10px; width:100%}
.sp-time{
  font-family:var(--font); font-size:26px; min-width:56px; text-align:center;
  padding:4px 12px; border-radius:14px; background:var(--bg-2); color:var(--ink);
}
.sp-time.low{background:rgba(255,75,75,.16); color:var(--red-d); animation:rlpulse .8s ease-in-out infinite}
.sp-score{display:flex; flex-direction:column; align-items:center; line-height:1.1}
.sp-score b{font-family:var(--font); font-size:24px}
.sp-score small{font-size:10.5px; font-weight:800; color:var(--ink-3)}
.sp-streak{font-family:var(--font); font-size:19px; min-width:56px; text-align:center; color:var(--orange)}

/* ---- ⏱️ Speed Round ---- */
.sp-word{text-align:center; margin:6px 0 16px}
.sp-word b{display:block; font-family:var(--font); font-size:30px; line-height:1.15; word-break:break-word}
.sp-word small{display:block; font-size:14px; font-weight:800; color:var(--ink-3); margin-top:2px}
.sp-word.sp-word-cjk b{font-size:34px; line-height:1.2}
.sp-word.sp-word-cjk small{font-size:15px}

/* ---- 🎈 Balloon Pop ---- */
.pp{display:flex; flex-direction:column; min-height:0}
.pp-ask{text-align:center; margin-bottom:6px}
.pp-ask small{display:block; font-size:12px; font-weight:800; color:var(--ink-3)}
.pp-ask b{font-family:var(--font); font-size:25px; line-height:1.2}
/* the sky takes whatever height is left — never a vh guess, or the balloons
   fall out of the bottom of the screen on a short phone */
.pp-sky{position:relative; flex:1; min-height:0; overflow:hidden; border-radius:20px; background:var(--bg-2)}
.pp-b{
  position:absolute; top:0; width:22%; min-height:74px; border-radius:50% 50% 46% 46%;
  background:var(--hue); color:#fff; display:grid; place-items:center; padding:6px 4px;
  box-shadow:0 6px 16px rgba(0,0,0,.18); will-change:transform;
}
.pp-b::after{content:''; position:absolute; bottom:-9px; left:50%; width:2px; height:10px; background:rgba(0,0,0,.25)}
.pp-b b{display:block; font-family:var(--font); font-size:14.5px; line-height:1.1; word-break:break-word}
.pp-b small{display:block; font-size:10px; font-weight:800; opacity:.85}
.pp-b.pop{animation:ppop 260ms ease forwards}
@keyframes ppop{to{transform:scale(1.5); opacity:0}}
.pp-b.gone{opacity:0; transition:opacity 200ms}

/* ---- 🐾 Mochi Says ---- */
.sy{display:flex; flex-direction:column; gap:12px}
.sy-stage{display:flex; gap:6px; justify-content:center; min-height:14px}
.sy-pip{width:11px; height:11px; border-radius:50%; background:var(--line)}
.sy-pip.on{background:var(--green); transform:scale(1.15)}
.sy-grid{display:grid; grid-template-columns:1fr 1fr; gap:9px}
.sy-card{
  padding:12px 10px; border-radius:18px; background:var(--card); box-shadow:var(--shadow-sm);
  border:2px solid transparent; text-align:center; min-height:78px;
  transition:transform 150ms var(--spring), border-color 150ms, background 150ms;
}
.sy-card b{display:block; font-family:var(--font); font-size:16px; line-height:1.15; word-break:break-word}
.sy-card small{display:block; font-size:11px; font-weight:800; color:var(--ink-3)}
.sy-card em{display:block; font-style:normal; font-size:11.5px; font-weight:800; color:var(--ink-2); margin-top:3px}
.sy-card:active{transform:scale(.96)}
.sy-card.lit{border-color:var(--blue); background:rgba(59,130,246,.13)}
.sy-card.bust{border-color:var(--red); animation:rlbust 400ms ease}

/* ---- ⭐ My Words (assets/js/mywords.js) ---- */
.mw-add{display:flex; gap:8px; align-items:stretch}
.mw-add .teach-input{flex:1; min-width:0}
.mw-rom{color:var(--ink-3); font-style:italic}

/* ---- game speed chooser (shown on every game's opening screen) ---- */
.g-speed{margin:4px 0 14px; text-align:center}
.g-speed-lbl{
  display:block; font-family:var(--font); font-size:14px;
  color:var(--ink-2); margin-bottom:6px;
}
.g-speed .setup-seg{margin:0 auto; max-width:340px}
.g-speed-note{display:block; margin-top:6px; font-size:11.5px; font-weight:800; color:var(--ink-3)}

/* What this game is about to play with. Games no longer ask which words — the
   Words tab already decided — so this states the answer instead. An invisible
   filter reads as a broken one. */
.g-deck{
  display:flex; align-items:center; gap:12px; padding:14px 16px; margin:2px 0 10px;
  border-radius:var(--r-lg); background:linear-gradient(140deg,
    rgba(255,200,0,.20), rgba(139,92,246,.14));
}
.g-deck-em{font-size:28px; flex:0 0 auto}
.g-deck-txt{min-width:0}
.g-deck-txt b{display:block; font-family:var(--font); font-size:16px}
.g-deck-txt small{display:block; font-size:12.5px; font-weight:800; color:var(--ink-2); margin-top:2px}

/* a custom word that has a real neural recording, not just the device voice */
.stu-act.mw-voiced{background:rgba(88,204,2,.16); color:var(--green-d)}

/* ==========================================================================
   THE SHELL  (assets/js/shell.js) — Avatar · Language · Words · Learn
   ========================================================================== */

/* ---- the avatar, wearing what it was bought ---- */
/* Sized in `em` so the dressed avatar drops into any call site and scales with
   the surrounding font-size, exactly the way the bare emoji it replaced did. */
.av{position:relative; display:inline-block; width:1em; height:1em; line-height:1; vertical-align:middle}
.av-face{font-size:1em; line-height:1; display:block}
.av-face svg{width:1em; height:1em; display:block}
/* WORN, not carried.
   These used to sit off in the corners at .40em — technically "on" the avatar,
   but what it looked like was three little stickers parked beside a face, and
   a coat you bought read as an extra icon rather than something the companion
   had put on. Each layer now goes where that thing actually goes on a body:

     outfit   centred UNDER the face and big enough to be a torso, overlapping
              the chin so the face sits on it like a head on shoulders
     item     on the CROWN, centred, tipped slightly, overlapping the hair
     pet      down at the feet, off to one side, still bobbing

   The box stays exactly 1em so every existing call site keeps its layout. */
.av-face{position:relative; z-index:2}
.av-outfit{
  position:absolute; left:50%; bottom:-.30em; z-index:1;
  font-size:.68em; transform:translateX(-50%);
}
/* an accessory goes where that accessory goes — see `slot` in LTG_SHOP */
.av-item{position:absolute; z-index:3; font-size:.52em}
.av-item--head{left:50%; top:-.30em; transform:translateX(-52%) rotate(-9deg)}
.av-item--eyes{left:50%; top:.30em; font-size:.46em; transform:translateX(-50%)}
/* the neck is BELOW the chin, not on it — a scarf centred on the face read as
   the dog eating a scarf */
.av-item--neck{left:50%; bottom:-.20em; font-size:.42em; transform:translateX(-50%)}
.av-item--side{left:-.28em; bottom:-.14em; font-size:.42em; transform:rotate(-12deg)}
.av-pet{
  position:absolute; right:-.30em; bottom:-.22em; z-index:3;
  font-size:.38em; animation:bob 2.6s ease-in-out infinite;
}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-14%)}}

.av-hero{
  text-align:center; padding:20px 16px 18px; border-radius:var(--r-xl); margin-bottom:18px;
  background:linear-gradient(160deg, rgba(139,92,246,.16), rgba(59,130,246,.12));
}
.av-name b{display:block; font-family:var(--font); font-size:22px; margin-top:10px}
.av-name small{display:block; font-size:13px; font-weight:800; color:var(--ink-2); margin-top:2px}
.av-xp{height:12px; border-radius:99px; background:var(--bg-2); overflow:hidden; margin:12px auto 0; max-width:240px}
.av-xp > i{display:block; height:100%; border-radius:99px; background:linear-gradient(90deg,var(--green),#8fe34a); transition:width 420ms var(--spring)}
.av-stats{display:flex; gap:8px; justify-content:center; margin-top:12px; flex-wrap:wrap}

.av-shelf{margin-bottom:14px}
.av-shelf-h{display:flex; align-items:center; justify-content:space-between; margin-bottom:6px}
.av-shelf-h b{font-family:var(--font); font-size:15px}
.linkish{background:none; border:0; font:inherit; font-weight:800; font-size:12.5px;
  color:var(--purple); text-decoration:underline; cursor:pointer; padding:2px 4px}
/* a horizontal rack: everything for sale is visible without a separate screen */
.av-rack{
  display:flex; gap:8px; overflow-x:auto; padding:4px 2px 8px;
  scroll-snap-type:x proximity; width:100%; max-width:100%; min-width:0;
  overscroll-behavior-x:contain; -webkit-overflow-scrolling:touch;
}
.av-thing{
  flex:0 0 88px; width:88px; max-width:88px; min-width:0;
  scroll-snap-align:start; padding:10px 6px; border-radius:18px;
  background:var(--card); box-shadow:var(--shadow-sm); border:2px solid transparent;
  text-align:center; transition:transform 150ms var(--spring), border-color 150ms;
  overflow:hidden;
}
.av-thing:active{transform:scale(.95)}
.av-thing.worn{border-color:var(--purple); background:rgba(139,92,246,.1)}
.av-thing.locked{opacity:.72}
.th-em{display:block; font-size:28px}
.th-nm{display:block; font-size:11px; font-weight:800; margin-top:3px; line-height:1.2;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%}
.th-tag{display:block; font-size:10.5px; font-weight:900; color:var(--ink-3); margin-top:3px}
.av-thing.worn .th-tag{color:var(--purple)}

/* ---- language ---- */
.wcard{
  display:flex; align-items:center; gap:13px; width:100%; text-align:left; margin-bottom:10px;
  padding:15px 14px; border-radius:var(--r-lg); background:var(--card); box-shadow:var(--shadow);
  border:2px solid transparent; transition:transform 150ms var(--spring), border-color 150ms;
}
.wcard:active{transform:scale(.985)}
.wcard.on{border-color:var(--purple); background:rgba(139,92,246,.08)}
.w-fl{font-size:32px; line-height:1}
.w-tx{flex:1; min-width:0}
.w-tx b{display:block; font-family:var(--font); font-size:19px}
.w-tx small{display:block; font-size:12.5px; font-weight:800; color:var(--ink-3); margin-top:2px}
.w-go{font-size:13px; font-weight:900; color:var(--orange); flex:0 0 auto}
.wcard.on .w-go{color:var(--purple)}

/* ---- words: the rung ---- */
.lv-seg{display:grid; grid-template-columns:repeat(3,1fr); gap:8px}
.lv-seg button{
  padding:12px 6px; border-radius:20px; background:var(--card); box-shadow:var(--shadow-sm);
  border:2px solid transparent; text-align:center;
  transition:transform 150ms var(--spring), border-color 150ms, background 150ms;
}
.lv-seg button:active{transform:scale(.96)}
.lv-seg button.on{border-color:var(--purple); background:rgba(139,92,246,.1)}
.lv-em{display:block; font-size:24px}
.lv-seg b{display:block; font-family:var(--font); font-size:14px; margin-top:2px}
.lv-seg small{display:block; font-size:11px; font-weight:800; color:var(--ink-3); margin-top:1px}

.deckbar{
  margin:14px 0 4px; padding:14px; border-radius:var(--r); text-align:center;
  background:linear-gradient(160deg, rgba(88,204,2,.16), rgba(88,204,2,.06));
}
.deckbar b{font-family:var(--font); font-size:26px; color:var(--green-d)}
.deckbar small{display:block; font-size:12px; font-weight:800; color:var(--ink-2); margin-top:2px}

.packbar{display:flex; gap:10px; margin-bottom:8px}
.prow{
  display:flex; align-items:center; gap:11px; padding:12px 13px; border-radius:18px;
  background:var(--card); box-shadow:var(--shadow-sm); margin-bottom:8px;
}
.p-em{font-size:22px}
.p-tx{flex:1; min-width:0}
.p-tx b{display:block; font-family:var(--font); font-size:15.5px}
.p-tx small{display:block; font-size:11.5px; font-weight:800; color:var(--ink-3)}

/* ---- learn: what you are studying, always visible ---- */
.ctxbar{display:grid; grid-template-columns:repeat(3,1fr); gap:8px; margin-bottom:16px}
.ctx{
  padding:10px 6px; border-radius:18px; background:var(--card); box-shadow:var(--shadow-sm);
  text-align:center; transition:transform 150ms var(--spring);
}
.ctx:active{transform:scale(.96)}
.c-em{display:block; font-size:22px}
.ctx b{display:block; font-family:var(--font); font-size:14px; margin-top:2px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.ctx small{display:block; font-size:10.5px; font-weight:900; color:var(--ink-3);
  text-transform:uppercase; letter-spacing:.4px; margin-top:1px}
.cta-flat{position:static; margin:0 0 8px}
.wayscard[disabled]{opacity:.45}

/* ---- 🚀 AsterWords ---- */
.as{display:flex; flex-direction:column; min-height:0}
.as-ask{text-align:center; margin-bottom:6px}
.as-ask small{display:block; font-size:12px; font-weight:800; color:var(--ink-3)}
.as-ask b{font-family:var(--font); font-size:25px; line-height:1.2}
.as-field{
  position:relative; flex:1; min-height:0; overflow:hidden; border-radius:20px;
  background:radial-gradient(circle at 50% 50%, #1b1f3d 0%, #0d1024 100%);
}
/* a few stars, drawn with gradients rather than an image request */
.as-field::before{
  content:''; position:absolute; inset:0; opacity:.5;
  background-image:radial-gradient(1.5px 1.5px at 20% 30%, #fff, transparent),
                   radial-gradient(1.5px 1.5px at 70% 20%, #fff, transparent),
                   radial-gradient(1px 1px at 40% 70%, #fff, transparent),
                   radial-gradient(1.5px 1.5px at 85% 60%, #fff, transparent),
                   radial-gradient(1px 1px at 15% 85%, #fff, transparent);
}
.as-ship{
  position:absolute; left:50%; top:50%; width:52px; height:52px; margin:-26px 0 0 -26px;
  display:grid; place-items:center; font-size:38px; z-index:3;
  transition:transform 120ms var(--spring); filter:drop-shadow(0 0 10px rgba(139,92,246,.8));
}
/* A word you have to READ while it moves needs more than a word sitting still:
   full-opacity white (a translucent tile picked up whatever drifted behind it),
   a border to hold the edge against the dark field, and type big enough to take
   in at a glance. 15px on a moving tile was the complaint, and it was fair. */
.as-rock{
  position:absolute; left:0; top:0; padding:9px 13px; border-radius:14px; z-index:2;
  background:#fff; color:var(--ink); border:2px solid rgba(139,92,246,.55);
  box-shadow:0 4px 16px rgba(0,0,0,.4);
  text-align:center; max-width:54%; will-change:transform;
}
.as-rock b{
  display:block; font-family:var(--font); font-size:20px; font-weight:800;
  line-height:1.2; word-break:break-word;
}
.as-rock small{display:block; font-size:12px; font-weight:800; color:var(--ink-2); margin-top:1px}
.as-rock.boom{animation:asboom 260ms ease forwards}
@keyframes asboom{to{transform:scale(1.6); opacity:0}}
.as-beam{
  position:absolute; left:50%; top:50%; width:3px; transform-origin:top center; z-index:1;
  background:linear-gradient(180deg, rgba(139,92,246,1), rgba(139,92,246,0));
  animation:asbeam 220ms ease-out forwards;
}
@keyframes asbeam{from{opacity:1}to{opacity:0}}
.as-field.shake{animation:rlbust 420ms ease}

/* ---- 📺 Watch & Learn (assets/js/video.js) ---- */
/* 16:9 with padding-top rather than aspect-ratio: an old iOS Safari that does
   not know aspect-ratio would otherwise collapse the player to nothing. */
.vid-frame{
  position:relative; display:block; width:100%; padding:0; padding-top:56.25%;
  border:0; border-radius:var(--r-lg); overflow:hidden; background:#000;
  box-shadow:var(--shadow); cursor:pointer;
}
.vid-frame iframe{position:absolute; inset:0; width:100%; height:100%; border:0}
.vid-poster{position:absolute; inset:0; width:100%; height:100%; object-fit:cover}
/* the play badge, over the poster — gone once the player is in */
.vid-go{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  width:66px; height:66px; border-radius:50%; display:grid; place-items:center;
  background:rgba(0,0,0,.62); color:#fff; font-size:26px; padding-left:4px;
  box-shadow:0 6px 20px rgba(0,0,0,.45); transition:transform 160ms var(--spring);
}
.vid-frame:active .vid-go{transform:translate(-50%,-50%) scale(.92)}
.vid-frame.playing .vid-go{display:none}
.vid-who{margin:0 0 6px; font-size:12.5px; font-weight:800; color:var(--ink-3)}
/* a reel: the word being hunted, over the moment that says it */
.reel-head{text-align:center; margin:12px 0 4px}
.reel-head b{display:block; font-family:var(--font); font-size:15px; color:var(--ink-2)}
.reel-head .reel-t{display:block; font-family:var(--font); font-size:26px; margin-top:2px}
.reel-head small{display:block; font-size:13px; font-weight:800; color:var(--ink-3)}
/* a scene from our own stories, reused as a reel frame */
.reel-panel{margin:10px 0 6px; border-radius:var(--r-lg); overflow:hidden}
/* where you are in the reel — it plays itself, so this is the only progress */
.reel-dots{display:flex; gap:6px; justify-content:center; margin:8px 0 2px; flex-wrap:wrap}
.reel-dots i{
  width:8px; height:8px; border-radius:50%; background:var(--bg-2);
  transition:transform 200ms var(--spring), background 200ms;
}
.reel-dots i.done{background:rgba(139,92,246,.45)}
.reel-dots i.on{background:var(--purple); transform:scale(1.5)}
.vid-out{display:block; text-align:center; text-decoration:none; line-height:1.2}
.vid-pack{display:block; color:var(--purple); font-weight:800; margin-top:3px}
.vidcard .way-em{font-size:30px}
/* A show has no single thumbnail to poster with — it is a channel. A big tile
   says "a whole show lives behind this" and costs no network at all. */
.vid-tile{
  background:linear-gradient(150deg, rgba(139,92,246,.20), rgba(255,138,203,.20));
}
/* Absolutely placed, NOT a grid item: .vid-go is already centred by its own
   translate, so leaving both in flow stacked the play button above the show
   instead of on it. The emoji is the poster; the button sits on top of it. */
/* A channel that still has everything but has stopped adding to it. Said
   plainly, because an app that quietly serves a dead feed looks abandoned. */
.vid-arch{color:#b26a00 !important}
html[data-theme="dark"] .vid-arch{color:#ffc061 !important}
.vid-archive{
  border-radius:var(--r); padding:11px 13px; margin:8px 0 4px;
  background:rgba(255,179,0,.13); border:2px solid rgba(255,179,0,.34);
  font-size:12.5px; font-weight:700; color:var(--ink-2); line-height:1.45;
}
/* an episode row on a show screen */
.epcard .way-em{font-size:17px; flex:0 0 32px; color:var(--purple)}
.epcard .way-txt b{font-size:15px}

/* subtitle language, chosen on the episode itself rather than buried in
   Settings - it is a per-watch decision, not a preference you set once */
.ep-subs{margin:0 0 12px}
.ep-subs > b{display:block; font-size:12.5px; margin-bottom:7px; color:var(--ink-2)}
.ep-subs .segs{margin-bottom:6px}
.ep-subs > small{display:block; color:var(--ink-3); font-weight:700; font-size:11.5px}

/* the few words our own vocabulary recognised in the episode title */
.ep-titlewords{
  border-radius:var(--r); padding:11px 13px; margin:0 0 10px;
  background:rgba(139,92,246,.11); border:2px solid rgba(139,92,246,.26);
}
.ep-titlewords b{display:block; font-size:12.5px; margin-bottom:7px; color:var(--ink-2)}
.ep-chips{display:flex; flex-wrap:wrap; gap:6px}
.ep-chip{
  display:inline-flex; align-items:baseline; gap:5px;
  padding:5px 10px; border-radius:999px; background:var(--card);
  font-size:12.5px; font-weight:800; box-shadow:var(--shadow-sm);
}
/* how many times it is actually said - the reason this word is on the card */
.ep-chip i{font-style:normal; font-size:10.5px; font-weight:900; color:var(--purple)}

.vid-tile-em{
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  font-size:96px; line-height:1; opacity:.45;
  filter:drop-shadow(0 6px 12px rgba(0,0,0,.18));
}

/* ---- 🎵 Songs (assets/js/songs.js) ---- */
.sg-style{
  text-align:center; padding:16px; border-radius:var(--r-lg); margin-bottom:12px;
  background:linear-gradient(160deg, rgba(236,72,153,.18), rgba(139,92,246,.14));
}
.sg-note{font-size:32px; display:block; animation:bob 2.2s ease-in-out infinite}
.sg-style b{display:block; font-family:var(--font); font-size:19px; margin-top:4px}
.sg-style small{display:block; font-size:12.5px; font-weight:800; color:var(--ink-2); margin-top:2px}

.sg{display:flex; flex-direction:column; min-height:0; height:100%}
.sg-head{text-align:center; margin-bottom:8px}
.sg-head b{font-family:var(--font); font-size:20px}
.sg-head small{display:block; font-size:12px; font-weight:800; color:var(--ink-3)}
/* which arrangement this module sings in — Chant, Call & Response, Ladder… */
.sg-form{
  display:inline-block; margin-top:6px; padding:4px 10px; border-radius:999px;
  background:rgba(139,92,246,.14); color:var(--ink-2);
  font-size:11.5px; font-weight:800; max-width:100%;
}
/* a song that will play with nobody singing over it — say so, do not let the
   learner sit through a silent chorus wondering what broke */
.sg-warn{
  border-radius:var(--r); padding:14px; margin:0 0 12px;
  background:rgba(255,179,0,.14); border:2px solid rgba(255,179,0,.4);
  text-align:center;
}
.sg-warn b{display:block; font-family:var(--font); font-size:15px; line-height:1.25}
.sg-warn p{
  margin:6px 0 10px; font-size:12.5px; font-weight:700; color:var(--ink-2); line-height:1.4;
}
.sg-warn .btn{padding:12px 16px; font-size:14px}

/* a bar of dancing lights — cheap, and it makes the beat visible */
.sg-viz{display:flex; gap:3px; align-items:flex-end; justify-content:center; height:34px; margin-bottom:10px}
.sg-viz i{
  width:5px; border-radius:3px; background:linear-gradient(180deg,var(--pink),var(--purple));
  height:30%; transition:height 120ms ease;
}
.sg-viz.hit i:nth-child(2n){height:100%}
.sg-viz.hit i:nth-child(3n){height:75%}
.sg-viz.hit i:nth-child(5n){height:55%}
.sg-lyrics{flex:1; min-height:0; overflow-y:auto; display:flex; flex-direction:column; gap:7px; padding:4px}
.sg-line{
  padding:11px 12px; border-radius:16px; background:var(--card); box-shadow:var(--shadow-sm);
  text-align:center; border:2px solid transparent; opacity:.6;
  transition:transform 180ms var(--spring), opacity 180ms, border-color 180ms, background 180ms;
}
.sg-line b{display:block; font-family:var(--font); font-size:18px; line-height:1.2; word-break:break-word}
.sg-line small{display:block; font-size:12px; font-weight:800; color:var(--ink-3); margin-top:2px}
.sg-line.on{
  opacity:1; border-color:var(--pink); background:rgba(236,72,153,.12);
  transform:scale(1.03);
}

/* ---- excluded words ---- */
/* A flex item in .fc-meta, NOT absolute: .fc-meta is not a positioned
   ancestor, so `position:absolute` anchored this to the overlay and dropped it
   on top of the "1 / 360" card counter in the header. */
.fc-x{
  flex:0 0 auto; width:34px; height:34px; border-radius:12px;
  background:var(--bg-2); font-size:14px; opacity:.55; display:grid; place-items:center;
  transition:opacity 150ms, transform 150ms var(--spring);
}
.fc-x:hover, .fc-x:active{opacity:1; transform:scale(1.08)}
.exlist{display:flex; flex-wrap:wrap; gap:7px; margin-bottom:6px}
.exchip{
  display:inline-flex; align-items:center; gap:6px; padding:8px 12px; border-radius:99px;
  background:var(--bg-2); color:var(--ink-2); font-weight:800; font-size:13px;
  border:2px dashed var(--line);
}
.exchip span{color:var(--purple); font-weight:900}
.exchip:active{transform:scale(.95)}


/* --- arcade playability (2026-09-15 dogfood) --- */
.pp-b{
  min-height:88px; padding:10px 6px;
  touch-action:manipulation; cursor:pointer;
  z-index:3;
}
.pp-sky{touch-action:manipulation}
.as-rock{
  touch-action:manipulation; cursor:pointer;
  padding:12px 16px; z-index:3;
  min-width:72px;
}
.as-field{touch-action:manipulation}
.rl-cell.near{
  border-color:var(--green);
  box-shadow:0 0 0 4px rgba(88,204,2,.35), 0 4px 0 rgba(31,35,64,.12);
  animation:rlnear 900ms ease-in-out infinite;
  z-index:2;
}
.rl-cell.reach-bad{opacity:.85; border-color:transparent}
.rl-cell:disabled{cursor:not-allowed}
@keyframes rlnear{
  0%,100%{transform:scale(1)}
  50%{transform:scale(1.04)}
}
/* Red light: keep words readable (dim) instead of pure ? mystery */
.is-red .rl-face{visibility:visible; opacity:.22}
.is-red .rl-back{display:none}
.rl-board.is-red .rl-back{display:none}


/* --- Japanese long-tile readability (2026-09-16) --- */
.pp-b{
  min-height:96px; max-height:42%; overflow:hidden;
  align-content:center;
}
.pp-b b{
  font-size:clamp(11px, 3.2vw, 14.5px);
  line-height:1.15;
  max-height:3.6em; overflow:hidden;
}
.pp-b small{
  font-size:clamp(9px, 2.6vw, 11px);
  line-height:1.1;
  max-height:2.4em; overflow:hidden;
}
.as-rock{
  max-width:min(70%, 240px);
  max-height:38%;
  overflow:hidden;
}
.as-rock b{
  font-size:clamp(14px, 4.2vw, 20px);
  line-height:1.15;
  max-height:2.6em; overflow:hidden;
}
.as-rock small{
  font-size:clamp(10px, 2.8vw, 12px);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.rl-face b{
  font-size:clamp(11px, 3.1vw, 14px);
}
.rl-face small{
  font-size:clamp(9px, 2.4vw, 11px);
  line-height:1.1;
}
.sy-card b{
  font-size:clamp(13px, 3.6vw, 16px);
  line-height:1.2;
}

/* --- JA arcade feel (2026-09-16 overnight) --- */
.pp-b.pp-b-wide{
  width:28%;
  min-height:108px;
  padding:12px 8px;
}
.pp-b.pp-b-wide b{
  font-size:clamp(13px, 3.8vw, 17px);
}
.pp-b.pp-b-wide small{
  font-size:clamp(10px, 2.8vw, 12px);
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.rl-cell{
  min-height:54px;
  padding:7px 4px;
}
.rl-face b{
  font-size:clamp(12px, 3.4vw, 16px);
}
.rl-face small{
  font-size:clamp(10px, 2.6vw, 12px);
}
.sy-card{
  min-height:88px;
  padding:14px 12px;
}
.sy-card b{
  font-size:clamp(14px, 4vw, 18px);
}
.sy-card small{
  font-size:clamp(11px, 3vw, 13px);
}


/* game speak / replay control */
.gm-speak{
  display:inline-flex; align-items:center; justify-content:center;
  margin-top:8px; width:44px; height:44px; border-radius:50%;
  background:var(--bg-2); border:2px solid var(--line);
  font-size:20px; cursor:pointer; touch-action:manipulation;
}
.gm-speak:active{transform:scale(.94)}
.sp-word .gm-speak{margin-top:10px}
#rlspeak{margin-left:8px; vertical-align:middle}
