/* =====================================================================
   wordlab-native.css  —  bottom tab bar, Records, Settings, parent modal
   Matches the existing Comic Neue / bright game aesthetic (game.css vars).
   ===================================================================== */

/* leave room above the fixed tab bar (incl. iPad home-indicator inset).
   --wl-tabbar-h is republished by wordlab-shell.js from the bar's REAL measured
   height, because the bar now wraps to 2-3 rows on narrow phones.
   --wl-readbar-h is the SAME deal for the floating read-aloud bar that sits just
   above it (fix 2026-07-28). This used to be a hardcoded 74px, but that bar wraps
   too — it measures ~166px on a 375px phone — so the last row of the page, and any
   lesson control button that had wrapped onto it, ended up underneath a fixed
   z-index:901 element and could not be tapped at all. Measure, never guess. */
:root { --wl-tabbar-h: 76px; --wl-readbar-h: 74px; }
.app { padding-bottom: calc(var(--wl-tabbar-h, 76px) + var(--wl-readbar-h, 74px)) !important; } /* clears tab bar + floating reading bar */

/* ---------------- bottom tab bar ----------------
   RESPONSIVE CONTRACT (fix 2026-07-24): every tab must be reachable at every
   viewport — phone/tablet/desktop, portrait/landscape, any window size.
     · flex-wrap:wrap  — the bar grows to 2-3 rows rather than pushing tabs off
       screen, so all buttons stay visible on a portrait phone.
     · justify-content: safe center — plain `center` overflows in BOTH
       directions when the row is too wide, and html/body have overflow-x:hidden,
       so the first tabs (Home, Subjects) became permanently unreachable. `safe`
       falls back to flex-start the moment the content stops fitting.
     · overflow:auto — last-resort scroll (short landscape screens force one
       row) so nothing is ever clipped-and-unreachable, only scrolled-to. */
.wl-tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 900;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  justify-content: safe center;
  align-content: center;
  align-content: safe center;   /* same trap vertically: plain `center` pushes
                                   the first ROW above the scroll origin when
                                   the bar hits its max-height */
  gap: 4px 6px;
  padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px));
  max-height: 42vh;
  overflow: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(10px);
  border-top: 3px solid rgba(46, 155, 255, 0.25);
  box-shadow: 0 -4px 18px rgba(41, 51, 92, 0.12);
}
.wl-tabbar::-webkit-scrollbar { width: 0; height: 0; }
.wl-tab {
  /* max-width 110 (was 150): when the bar wraps, the last row has spare space
     and its few tabs grow into it — capping growth keeps the rows even */
  flex: 1 1 auto; min-width: 60px; max-width: 110px; min-height: 44px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  border: none; background: transparent; cursor: pointer;
  padding: 6px 2px; border-radius: 16px;
  color: #7a86ad; font-weight: 700; font-size: 0.72rem;
  transition: transform 0.08s ease, background 0.15s ease, color 0.15s ease;
}
.wl-tab-lbl { line-height: 1.12; text-align: center; }
.wl-tab .wl-tab-ico { font-size: 1.4rem; line-height: 1; filter: grayscale(0.4); transition: filter 0.15s; }
.wl-tab:active { transform: scale(0.92); }

/* Permanent legacy-bar retirement (fix 2026-09-01). The old union-of-tabs
   buttons stay in the DOM as compatibility targets for older modules, but the
   grouped index bar must NEVER paint them. The previous ordinary `display:none`
   boot guard lost to later inline `display:flex` writes from role/module code,
   which is why the duplicate bar kept returning after session changes.

   The contract is explicit and page-scoped:
     · index.html marks its grouped bar with data-navmode="groups";
     · only destinations already covered by a group carry data-nav-legacy;
     · !important defeats every legacy inline visibility writer;
     · old-only bars on curio.html have no grouped marker and remain untouched.
   Dictionary, Research Library, Author Workshop, Kindred Hall, Read, Notes and
   the student's temporary Settings entry are intentionally not retired here. */
#wl-tabbar[data-navmode="groups"] .wl-tab[data-nav-legacy="covered"] {
  display: none !important;
}

/* ⚙️ Settings and 🔧 Admin sit at the FAR RIGHT of the bar, always (owner call
   2026-08-18). DOM order alone cannot hold that: the new nav-group buttons are
   declared BEFORE the old individual tabs in index.html, so the three buttons
   that survive the group redesign for every role — 📖 Dictionary, 📚 Research
   Library and the runtime-injected "Read" launcher (game-core.js inserts it
   immediately before the old settings tab) — all rendered to the RIGHT of
   Settings/Admin. `order` on a flex container fixes the visual position
   without moving markup any module might be querying, and it holds no matter
   what else is inserted into the bar later (Studio, Play and Hearth Board all
   arrive at runtime). Everything else stays at the default order:0.
   Both id shapes are covered: the group buttons a grown-up sees, and the old
   `data-tab` buttons a student still sees (settings is the student's
   documented temporary 6th tab). */
#wl-tabbar .wl-navgroup[data-navgroup="settings"],
#wl-tabbar .wl-tab[data-tab="settings"] { order: 90; }
#wl-tabbar .wl-navgroup[data-navgroup="admin"],
#wl-tabbar .wl-tab[data-tab="admin"] { order: 91; }
.wl-tab.active { color: var(--blue-dark); background: rgba(46, 155, 255, 0.13); }
.wl-tab.active .wl-tab-ico { filter: none; transform: translateY(-1px); }

/* Portrait phones: shrink each tab so a whole role's tab set fits in 2 rows
   instead of 3-4. `anywhere` lets a long single word (Hearthstone, Dictionary)
   stop dictating the minimum tab width. */
@media (max-width: 560px) {
  .wl-tabbar { gap: 3px 4px; padding: 6px 6px calc(6px + env(safe-area-inset-bottom, 0px)); }
  /* flex-basis:0 (not auto) so long labels stop inflating their tab and the
     row packs to the most tabs it can hold — fewer rows, less screen eaten */
  .wl-tab { flex: 1 1 0; min-width: 50px; padding: 4px 2px; border-radius: 12px; font-size: 0.62rem; }
  .wl-tab .wl-tab-ico { font-size: 1.18rem; }
  /* explicit: game.css's max-640px rule also sets .wl-tab-lbl font-size */
  .wl-tab .wl-tab-lbl { font-size: 0.62rem; overflow-wrap: anywhere; }
  /* "Hearthstone Valley" is the one label long enough to get hyphen-broken
     mid-word ("Hearthston/e Valley") — give it the width to break on the space */
  .wl-tab[data-tab="hearthstone"] { min-width: 64px; }
  .wl-tab[data-tab="hearthstone"] .wl-tab-lbl { overflow-wrap: normal; }
}
@media (max-width: 380px) {
  .wl-tab { min-width: 46px; }
  .wl-tab .wl-tab-lbl { font-size: 0.58rem; }
  .wl-tab .wl-tab-ico { font-size: 1.08rem; }
}

/* Short viewports (phone in landscape, small desktop windows): vertical space
   is the scarce resource, so squash the bar down — smaller icons, no tab
   min-height — and hard-cap it at 32vh. These screens are wide, so a whole
   role's tab set still fits in 1-2 rows. If it ever doesn't, the bar scrolls
   rather than clipping. */
@media (max-height: 520px) {
  .wl-tabbar { max-height: 32vh; gap: 3px 4px; padding-top: 4px; padding-bottom: calc(4px + env(safe-area-inset-bottom, 0px)); }
  .wl-tab { flex: 1 1 0; min-width: 56px; min-height: 0; padding: 3px 6px; }
  .wl-tab .wl-tab-ico { font-size: 1.05rem; }
  .wl-tab .wl-tab-lbl { font-size: 0.6rem; }
}

/* ---------------- shared page wrapper ---------------- */
.wl-page { max-width: 760px; margin: 0 auto; }
/* 📄 Records + report screens stretch to the whole window (owner, 2026-08-17):
   the shared 760px column wasted most of a desktop window and made the report
   feel cramped. Scoped to #records-root so Revision/Save-work/Settings keep
   their narrow column. The huge full-width download button is reined in too —
   its width:100% is inline in lock-protected wordlab-records.js, so the
   override lives here. */
#records-root .wl-page { max-width: none; padding: 0 8px; }
/* .subject-btn is the HOME-SCREEN TILE class (22px padding, 1.25rem); reused
   inside Records it rendered as a giant slab. Scope it back to a normal,
   centred button here. */
#records-root .subject-btn {
  width: auto !important; display: block; margin: 0 auto; padding: 9px 22px;
  font-size: 0.95rem; border-radius: 999px !important;
  min-height: 0; /* game.css:2559 blankets .subject-btn with min-height:142px */
}
#records-root .subject-btn:hover { transform: none; filter: brightness(1.05); }
.wl-empty {
  text-align: center; color: #7a86ad; font-weight: 700;
  background: var(--card); border-radius: var(--radius);
  padding: 30px 20px; box-shadow: var(--shadow); margin-top: 14px;
}

/* ---------------- Records tab ---------------- */
.wl-recstats { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin: 10px 0 16px; }
.wl-pill {
  background: var(--card); border-radius: 999px; padding: 6px 14px;
  font-weight: 700; font-size: 0.85rem; box-shadow: var(--shadow); color: var(--ink);
}
.wl-pill.good { background: #e7f9ee; color: var(--green-dark); }
.wl-pill.bad  { background: #fff1e6; color: var(--orange-dark); }

/* level tabs — tidy wrapping box (matches .wl-areabar) */
.wl-levels {
  display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin: 0 0 12px;
  padding: 8px 10px; background: #f3faf8; border: 1.5px solid #d7ece7; border-radius: 14px;
  box-shadow: inset 0 1px 0 #ffffff;
}
.wl-level-tab {
  border: 2px solid #d6e2f5; background: var(--card); color: #6c7799;
  border-radius: 999px; padding: 4px 12px; font-family: inherit; font-weight: 700;
  font-size: 0.82rem; cursor: pointer; transition: transform 0.08s ease;
}
.wl-level-tab:active { transform: scale(0.94); }
.wl-level-tab.on { border-color: var(--blue); background: var(--blue); color: #fff; box-shadow: var(--shadow); }

/* date groups within a level */
.wl-date-group { margin: 16px 0; }
.wl-date-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  position: sticky; top: 0; z-index: 5;
  background: linear-gradient(180deg, var(--paper) 70%, transparent);
  padding: 6px 4px 8px; margin-bottom: 4px;
}
.wl-date-head > span:first-child {
  font-weight: 700; font-size: 1.15rem; color: var(--blue-dark);
  background: rgba(46, 155, 255, 0.12); border-radius: 999px; padding: 4px 14px;
}
.wl-date-count { font-size: 0.78rem; color: #6c7799; font-weight: 700; white-space: nowrap; }

/* subject sub-groups within a date */
.wl-subject-group { margin: 10px 0 14px; }
.wl-subject-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin: 0 4px 7px; padding-bottom: 4px; border-bottom: 2px solid rgba(46, 155, 255, 0.18);
}
.wl-subject-name { font-weight: 700; font-size: 0.98rem; color: var(--ink); }
.wl-subject-name::before { content: '📂 '; }
.wl-subject-count { font-size: 0.78rem; color: #6c7799; font-weight: 700; white-space: nowrap; }

.wl-rec-level {
  background: #eef2fb; color: #6c7799; border-radius: 999px;
  padding: 1px 8px; font-weight: 700; font-size: 0.72rem;
}
.wl-rec-review {
  background: #fff3d6; color: #b8860b; border-radius: 999px;
  padding: 1px 9px; font-weight: 700; font-size: 0.72rem;
}
.wl-rec.rev { border-left-style: dashed; }

.wl-reclist { display: flex; flex-direction: column; gap: 10px; }
.wl-rec {
  background: var(--card); border-radius: 16px; padding: 12px 14px;
  box-shadow: var(--shadow); border-left: 6px solid var(--green);
}
.wl-rec.no { border-left-color: var(--orange); }
.wl-rec-top {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  font-size: 0.78rem; color: #7a86ad; margin-bottom: 6px;
}
.wl-rec-mark { font-size: 1rem; }
.wl-rec-lesson { font-weight: 700; color: var(--ink); }
.wl-rec-topic {
  background: rgba(160, 92, 224, 0.14); color: var(--purple-dark);
  border-radius: 999px; padding: 1px 9px; font-weight: 700;
}
.wl-rec-time { margin-left: auto; }
.wl-rec-q { font-weight: 700; margin: 2px 0 4px; }
.wl-rec-a { word-break: break-word; white-space: pre-wrap; }
.wl-rec-correct { margin-top: 4px; color: var(--green-dark); font-weight: 700; font-size: 0.9rem; }
.wl-rec-del {
  border: none; background: #ffe3e3; color: var(--red-dark);
  border-radius: 10px; padding: 3px 9px; cursor: pointer; font-size: 0.95rem;
}
.wl-rec-del:active { transform: scale(0.9); }
/* 📌 evidence pin (grown-ups only). Off state is deliberately faint so an unpinned
   row reads exactly as it did before; pinned is amber and full-strength. */
.wl-rec-pin {
  border: none; background: transparent; opacity: 0.35; filter: grayscale(1);
  border-radius: 10px; padding: 3px 7px; cursor: pointer; font-size: 0.95rem;
}
.wl-rec-pin.on { opacity: 1; filter: none; background: #fff3d6; }
.wl-rec-pin:active { transform: scale(0.9); }

/* ---------------- Records mode tabs ---------------- */
.wl-modes { display: flex; gap: 6px; justify-content: center; margin: 6px 0 12px; flex-wrap: wrap; }
.wl-mode-tab {
  border: 2px solid #d6e2f5; background: var(--card); color: #6c7799;
  border-radius: 999px; padding: 5px 13px; font-family: inherit; font-weight: 700;
  font-size: 0.84rem; cursor: pointer; transition: transform 0.08s ease;
}
.wl-mode-tab:active { transform: scale(0.94); }
.wl-mode-tab.on { border-color: var(--purple); background: var(--purple); color: #fff; box-shadow: var(--shadow); }
/* subject filter chips (Records & Revision) */
.wl-subjects { display: flex; gap: 5px; justify-content: center; margin: 0 0 12px; flex-wrap: wrap; }
.wl-subj-tab {
  border: 2px solid #d6e2f5; background: var(--card); color: #6c7799;
  border-radius: 999px; padding: 4px 11px; font-family: inherit; font-weight: 700;
  font-size: 0.78rem; cursor: pointer; transition: transform 0.08s ease;
}
.wl-subj-tab:active { transform: scale(0.94); }
.wl-subj-tab.on { border-color: var(--teal, #14b8a6); background: var(--teal, #14b8a6); color: #fff; box-shadow: var(--shadow); }

/* === clear Subject ▸ Subheading hierarchy (Records & Revision) === */
/* main row = SUBJECTS (strictly learning areas) — tidy wrapping box, all subjects visible */
.wl-areabar { display: flex; gap: 6px; justify-content: center; flex-wrap: wrap; margin: 0 0 12px; padding: 8px 10px; background: #f3faf8; border: 1.5px solid #d7ece7; border-radius: 14px; box-shadow: inset 0 1px 0 #ffffff; }
.wl-areabar .wl-subj-tab { flex: 0 0 auto; white-space: nowrap; font-size: 0.84rem; padding: 5px 12px; border-color: #bfe3dd; background: #fff; }
.wl-areabar .wl-subj-tab.on { border-color: var(--teal, #14b8a6); background: var(--teal, #14b8a6); color: #fff; }
/* nested panel = this subject's SUBHEADINGS + per-subject views */
.wl-subpanel { background: #f3faf8; border: 1.5px solid #d7ece7; border-radius: 16px; padding: 11px 12px 12px; margin: 0 0 16px; }
.wl-subpanel-label { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase; color: #5a8079; margin: 0 0 8px; text-align: center; }
.wl-subpanel .wl-subjects { margin: 0; }
.wl-subpanel .wl-subj-tab { font-size: 0.76rem; }
/* per-subject "views" (Progress · Reflections · Report · Revisions) — own sub-row */
.wl-views { display: flex; gap: 6px; justify-content: center; flex-wrap: wrap; margin: 9px 0 0; padding-top: 9px; border-top: 1px dashed #d7ece7; }
.wl-views .wl-subj-tab { background: #eef4ff; border-color: #c9d8f3; color: #41577f; }
.wl-views .wl-subj-tab.on { border-color: var(--purple, #7c5cff); background: var(--purple, #7c5cff); color: #fff; }

/* ---------------- Revision tab ---------------- */
.wl-revlist { display: flex; flex-direction: column; gap: 10px; }
.wl-revcard-wrap { display: flex; flex-direction: column; gap: 4px; }
.wl-revcard {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; text-align: left; cursor: pointer;
  background: var(--card); border: none; border-left: 6px solid var(--orange);
  border-radius: 16px; padding: 13px 15px; box-shadow: var(--shadow);
  font-family: inherit; transition: transform 0.08s ease;
}
.wl-rev-delete {
  align-self: flex-end; border: 0; background: transparent; color: #7a5a75;
  font: inherit; font-size: .78rem; font-weight: 700; cursor: pointer; padding: 3px 8px;
}
.wl-rev-delete:hover { text-decoration: underline; }
.wl-rev-delete.pending { color: #53708a; cursor: default; text-decoration: none; }
.wl-revcard:active { transform: scale(0.98); }
.wl-revcard.done { border-left-color: var(--green); opacity: 0.92; }
.wl-revcard-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.wl-revcard-name { font-weight: 700; color: var(--ink); font-size: 1.02rem; }
.wl-revcard-meta { font-size: 0.78rem; color: #7a86ad; font-weight: 700; }
.wl-revcard-count {
  white-space: nowrap; font-weight: 700; font-size: 0.85rem; color: var(--orange-dark);
  background: #fff1e6; border-radius: 999px; padding: 5px 12px;
}
.wl-revcard-count.ok { color: var(--green-dark); background: #e7f9ee; }
.wl-mastered { margin-top: 16px; }
.wl-mastered > summary {
  cursor: pointer; font-weight: 700; color: var(--green-dark);
  background: #e7f9ee; border-radius: 999px; padding: 8px 16px; display: inline-block; margin-bottom: 10px;
}

/* Practice is a work queue, not a table of every filter at once. Keep the full
   subject and Foundation–10 choices, but put each family on one labelled rail
   instead of allowing 20+ chips to build a tall wrapped wall on phones. Records
   keeps its existing wrapping controls; these rules are intentionally scoped to
   #screen-revision only. */
#screen-revision .wl-areabar,
#screen-revision .wl-levels,
#screen-revision .wl-subpanel .wl-subjects {
  justify-content: flex-start;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-inline: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scroll-snap-type: inline proximity;
}
#screen-revision .wl-areabar .wl-subj-tab,
#screen-revision .wl-levels .wl-level-tab,
#screen-revision .wl-subpanel .wl-subj-tab {
  flex: 0 0 auto;
  white-space: nowrap;
  scroll-snap-align: start;
}
#screen-revision #wl-repair-practice {
  width: auto !important;
  min-height: 0 !important;
  padding: 8px 14px !important;
  border-radius: 999px !important;
  font-size: 0.86rem !important;
}
#screen-revision .wl-revcard { min-width: 0; }
#screen-revision .wl-revcard-count {
  max-width: 46%;
  white-space: normal;
  text-align: right;
  line-height: 1.25;
}
@media (max-width: 520px) {
  /* The fixed student navigation covers the lower viewport. Reserve its
     height when a Practice control is scrolled into view. */
  html:has(#screen-revision.active) { scroll-padding-bottom: 260px; }
  #screen-revision .wl-revcard {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 8px;
    padding: 11px 12px;
  }
  #screen-revision .wl-revcard-count {
    max-width: 100%;
    justify-self: start;
    text-align: left;
  }
}

/* ---------------- Report mode ---------------- */
.wl-report-card {
  background: var(--card); border-radius: var(--radius); padding: 16px 18px;
  box-shadow: var(--shadow); margin: 12px 0;
}
.wl-report-card h3 { margin: 0 0 12px; }
.wl-bigstat { display: flex; align-items: center; gap: 16px; margin-bottom: 12px; }
.wl-bignum { font-size: 3rem; font-weight: 700; color: var(--blue-dark); line-height: 1; }
.wl-biglbl { color: #6c7799; font-weight: 700; }
.wl-summary { font-size: 1.02rem; line-height: 1.6; margin: 0; }
.wl-bars { display: flex; flex-direction: column; gap: 9px; }
.wl-bar-row { display: flex; align-items: center; gap: 10px; }
.wl-bar-name { flex: 0 0 38%; font-weight: 700; font-size: 0.9rem; color: var(--ink); }
.wl-bar-track { flex: 1; height: 14px; background: #eef2fb; border-radius: 999px; overflow: hidden; }
.wl-bar-fill { display: block; height: 100%; border-radius: 999px; }
.wl-bar-fill.good { background: linear-gradient(90deg, var(--green), var(--teal)); }
.wl-bar-fill.bad { background: linear-gradient(90deg, var(--orange), var(--red)); }
.wl-bar-pct { flex: 0 0 auto; font-weight: 700; font-size: 0.85rem; color: #6c7799; width: 38px; text-align: right; }
.wl-misslist { display: flex; flex-direction: column; gap: 7px; }
.wl-missrow {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 12px; background: #fff7f7; border-radius: 12px; font-weight: 700;
}
.wl-missrow > span:first-child { color: var(--ink); }

/* ============== Kindred Village: fitted wearables + games ============== */
/* refined emoji-slot positioning (overrides game.css) so pieces sit right */
.kv-wear.hat  { top: -14px; font-size: 2.7rem; animation: kvHatBob 3s ease-in-out infinite; }
.kv-wear.face { top: 30%; font-size: 2rem; }
.kv-wear.neck { top: 54%; bottom: auto; font-size: 1.85rem; animation: kvDangle 3.4s ease-in-out infinite; transform-origin: 50% 0; }
.kv-wear.held { right: -18px; bottom: 20px; font-size: 2.3rem; }
.kv-wear.back { top: 28%; left: 50%; transform: translateX(-50%); font-size: 2.5rem; z-index: -1; }
@keyframes kvHatBob { 0%,100% { transform: translateX(-50%) translateY(0); } 50% { transform: translateX(-50%) translateY(-3px); } }
@keyframes kvDangle { 0%,100% { transform: translateX(-50%) rotate(-4deg); } 50% { transform: translateX(-50%) rotate(4deg); } }

/* ===== geometry auto-fit wearables (wordlab-kindred-fit.js) ===== */
.kv-fitwrap { position: relative; }
.kv-fit { position: absolute; left: 0; top: 0; pointer-events: none; line-height: 1; z-index: 3; will-change: transform; }
.kv-fit .kv-bob, .kv-fit .kv-anim { display: inline-block; }
/* wearables gently bob in time with the body's idle so they never detach */
.kv-bob { animation: kvWearBob 3.2s ease-in-out infinite; }
@keyframes kvWearBob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
/* animated accessories (props only) */
.kv-anim.sway { animation: kvSway 2.6s ease-in-out infinite; transform-origin: 50% 8%; }
.kv-anim.bob  { animation: kvBob 2.2s ease-in-out infinite; }
.kv-anim.spin { animation: kvSpin 4.5s linear infinite; }
.kv-anim.idle { animation: kvWearBob 3.6s ease-in-out infinite; }
@keyframes kvSway { 0%, 100% { transform: rotate(-9deg); } 50% { transform: rotate(9deg); } }
@keyframes kvBob  { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes kvSpin { from { transform: rotate(0); } to { transform: rotate(360deg); } }

/* CSS-drawn fitted WINGS — big, behind the body, flapping */
.kv-fx-wings { top: 34%; left: 50%; transform: translate(-50%, -50%); width: 118%; height: 72%; font-size: 0; z-index: -1; }
.kv-fx-wings .kw {
  position: absolute; top: 6%; width: 50%; height: 88%;
  background: linear-gradient(150deg, var(--w1), var(--w2));
  border-radius: 92% 58% 72% 22% / 100% 64% 80% 26%;
  box-shadow: inset 6px -4px 10px rgba(255,255,255,.45), 0 3px 5px rgba(0,0,0,.14);
  opacity: 0.95;
}
.kv-fx-wings .kw.l { left: -4%; transform-origin: 96% 46%; animation: kvFlapL 1.3s ease-in-out infinite; }
.kv-fx-wings .kw.r { right: -4%; transform: scaleX(-1); transform-origin: 96% 46%; animation: kvFlapR 1.3s ease-in-out infinite; }
@keyframes kvFlapL { 0%,100% { transform: rotate(-12deg); } 50% { transform: rotate(10deg); } }
@keyframes kvFlapR { 0%,100% { transform: scaleX(-1) rotate(-12deg); } 50% { transform: scaleX(-1) rotate(10deg); } }

/* CSS-drawn fitted CAPE — draped behind, gently swaying */
.kv-fx-cape { top: 30%; left: 50%; transform: translateX(-50%); width: 74%; height: 64%; font-size: 0; z-index: -1; }
.kv-fx-cape .kc {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, var(--c1), var(--c2));
  clip-path: polygon(16% 0, 84% 0, 100% 96%, 50% 86%, 0 96%);
  box-shadow: inset 0 8px 14px rgba(255,255,255,.28), 0 5px 7px rgba(0,0,0,.14);
  transform-origin: 50% 6%; animation: kvCapeSway 2.8s ease-in-out infinite;
}
.kv-fx-cape.rainbow .kc { background: linear-gradient(180deg, #ff5d5d, #ff9f2e, #ffd93d, #3ecf6a, #2e9bff, #a05ce0); }
@keyframes kvCapeSway { 0%,100% { transform: rotate(-2.8deg); } 50% { transform: rotate(2.8deg); } }

/* aura glow */
.kvw-aura { font-size: 3rem !important; opacity: .85; animation: kvAura 2.4s ease-in-out infinite; }
@keyframes kvAura { 0%,100% { transform: translateX(-50%) scale(1); opacity: .65; } 50% { transform: translateX(-50%) scale(1.12); opacity: .95; } }

/* Games menu */
.act-games { background: linear-gradient(180deg, #ff8fd0, #d4509a) !important; color: #fff !important; }
.kv-game-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-top: 6px; }
.kv-game-btn {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  border: none; background: var(--card); box-shadow: var(--shadow); cursor: pointer;
  border-radius: 16px; padding: 12px 8px; font-family: inherit;
}
.kv-game-btn:active { transform: scale(0.95); }
.kv-game-emoji { font-size: 2rem; line-height: 1; }
.kv-game-name { font-weight: 700; color: var(--ink); font-size: 0.95rem; }
.kv-game-rew { font-size: 0.72rem; color: #6c7799; font-weight: 700; }

/* ============== Kindred Arcade (retro mini-games) ============== */
.kv-arc-back {
  position: fixed; inset: 0; z-index: 1100; display: flex; align-items: center; justify-content: center;
  background: rgba(20, 28, 56, 0.6); padding: 14px;
}
.kv-arc-card {
  background: var(--card); border-radius: var(--radius); width: 100%; max-width: 540px;
  max-height: 92vh; overflow-y: auto; box-shadow: 0 18px 50px rgba(20, 28, 56, 0.45);
  padding: 14px 16px 18px;
}
.kv-arc-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.kv-arc-title { font-weight: 700; font-size: 1.2rem; color: var(--ink); }
.kv-arc-score { margin-left: auto; font-weight: 700; color: var(--blue-dark); font-size: 0.95rem; }
.kv-arc-x { border: none; background: #eef2fb; width: 34px; height: 34px; border-radius: 50%; cursor: pointer; font-size: 1rem; color: var(--ink); flex-shrink: 0; }
.kv-arc-x:active { transform: scale(0.9); }
.kv-arc-stage { text-align: center; }
.kv-arc-hint { font-size: 0.9rem; color: #6c7799; margin: 2px 0 12px; }
.kv-arc-end h3 { margin: 6px 0; }
.kv-arc-reward { background: #f3f8ff; border-radius: 14px; padding: 12px; font-weight: 700; color: var(--ink); margin: 10px 0; }
.kv-arc-reward span { font-weight: 400; color: #6c7799; font-size: 0.9rem; }
.kv-arc-endbtns { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }

.kv-arc-menu { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.kv-arc-game {
  display: flex; flex-direction: column; align-items: center; gap: 5px; cursor: pointer;
  border: none; background: var(--card); box-shadow: var(--shadow); border-radius: 16px; padding: 14px 6px;
  font-family: inherit; font-weight: 700; color: var(--ink); font-size: 0.82rem;
}
.kv-arc-game:active { transform: scale(0.95); }
.kv-arc-emoji { font-size: 2.1rem; line-height: 1; }
.kv-arc-price { font-size: 0.72rem; font-weight: 700; color: var(--orange-dark); background: #fff1e6; border-radius: 999px; padding: 1px 8px; }
.kv-arc-price.free { color: var(--green-dark); background: #e7f9ee; }

/* Tic-Tac-Toe */
.ttt-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; max-width: 280px; margin: 0 auto; }
.ttt-cell { aspect-ratio: 1; border: 3px solid #d6e2f5; background: #f8fbff; border-radius: 14px; font-size: 2.4rem; cursor: pointer; }
.ttt-cell.taken { cursor: default; }

/* Memory Match */
.mem-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; max-width: 320px; margin: 0 auto; }
.mem-card { aspect-ratio: 1; border: none; border-radius: 12px; cursor: pointer; position: relative;
  background: linear-gradient(150deg, var(--purple), var(--blue)); font-size: 1.9rem; }
.mem-card::before { content: '❔'; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 1.6rem; }
.mem-card .mem-face { display: none; }
.mem-card.flip, .mem-card.done { background: #fff; box-shadow: inset 0 0 0 3px #d6e2f5; }
.mem-card.flip::before, .mem-card.done::before { display: none; }
.mem-card.flip .mem-face, .mem-card.done .mem-face { display: block; }
.mem-card.done { box-shadow: inset 0 0 0 3px var(--green); }

/* Snake / canvas + d-pad */
.kv-canvas { border-radius: 14px; box-shadow: var(--shadow); touch-action: none; max-width: 100%; }
.kv-dpad { display: flex; flex-direction: column; align-items: center; gap: 6px; margin: 12px auto 0; width: 170px; }
.kv-dpad-mid { display: flex; gap: 44px; }
.kv-dpad button { width: 50px; height: 44px; border: none; background: #eef2fb; border-radius: 12px; font-size: 1.1rem; cursor: pointer; color: var(--ink); }
.kv-dpad button:active { transform: scale(0.92); background: rgba(46,155,255,.18); }

/* Typing Race */
.typ-target {
  font-size: 1.2rem; line-height: 2.1; text-align: left; letter-spacing: 0.3px;
  white-space: pre-wrap; overflow-wrap: break-word; word-break: break-word;
  background: #f8fbff; border: 2px solid #d6e2f5; border-radius: 14px; padding: 14px 16px; margin-bottom: 10px;
}
.typ-target .ok { color: var(--green-dark); }
.typ-target .bad { color: #fff; background: var(--red); border-radius: 4px; }
.typ-target .cur { background: rgba(46, 155, 255, 0.3); border-radius: 4px; }
.typ-stats { font-weight: 700; color: var(--blue-dark); margin-bottom: 8px; font-size: 1rem; }
.typ-input {
  width: 100%; min-height: 72px; border: 2.5px solid #d6e2f5; border-radius: 14px;
  padding: 10px 12px; font-family: inherit; font-size: 1.1rem; color: var(--ink); resize: none; background: #fff;
}
.typ-input:focus { border-color: var(--blue); outline: none; }
.typ-input:disabled { background: #eef2fb; }

/* Whack-a-Mole */
.mole-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; max-width: 300px; margin: 0 auto; }
.mole-hole { aspect-ratio: 1; border: none; border-radius: 50%; cursor: pointer; overflow: hidden; position: relative;
  background: radial-gradient(ellipse at 50% 120%, #7a5a3a 0 60%, #b98a5a 62%); }
.mole-hole .mole { position: absolute; left: 0; right: 0; bottom: -100%; font-size: 2.4rem; transition: bottom 0.12s ease; }
.mole-hole.up .mole { bottom: 8%; }

/* Word Maker */
.wm-letters { display: flex; flex-wrap: wrap; gap: 7px; justify-content: center; margin: 4px 0 12px; }
.wm-tile {
  width: 42px; height: 46px; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(160deg, #fff3d6, #ffd79a); border: 2px solid #e0a94e;
  border-radius: 10px; font-weight: 700; font-size: 1.4rem; color: #7c5a18; box-shadow: 0 3px 0 rgba(0,0,0,.1);
}
.wm-row { display: flex; gap: 8px; max-width: 360px; margin: 0 auto 8px; }
.wm-input { flex: 1; border: 2.5px solid #d6e2f5; border-radius: 12px; padding: 10px 12px; font-family: inherit; font-size: 1.1rem; text-transform: uppercase; letter-spacing: 1px; }
.wm-input:focus { border-color: var(--blue); outline: none; }
.wm-msg { font-weight: 700; color: #6c7799; min-height: 1.3em; font-size: 0.9rem; margin-bottom: 8px; }
.wm-found { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; max-height: 30vh; overflow-y: auto; }
.wm-found em { color: #9aa6c6; }
.wm-word { background: #e7f9ee; color: var(--green-dark); border-radius: 999px; padding: 4px 12px; font-weight: 700; font-size: 0.9rem; }

/* Tetris */
.tet-levels { font-weight: 700; color: #6c7799; margin-bottom: 8px; }
.tet-lv { width: 34px; height: 34px; border: 2px solid #d6e2f5; background: #f3f8ff; color: var(--ink); border-radius: 10px; font-weight: 700; cursor: pointer; margin-left: 5px; }
.tet-lv.on { border-color: var(--blue); background: var(--blue); color: #fff; }
.tet-ctrls { display: flex; gap: 8px; justify-content: center; margin-top: 12px; }
.tet-ctrls button { width: 52px; height: 46px; border: none; background: #eef2fb; border-radius: 12px; font-size: 1.2rem; cursor: pointer; color: var(--ink); }
.tet-ctrls button:active { transform: scale(0.92); background: rgba(46,155,255,.18); }

/* reward gains */
.kv-arc-gains { display: flex; flex-direction: column; gap: 3px; margin: 8px 0 4px; font-weight: 700; }
.kv-arc-gains b { color: var(--green-dark); }
.kv-arc-msg { color: #6c7799; font-weight: 400; font-size: 0.92rem; }

/* ============== Song Maker ============== */
.sm-back { position: fixed; inset: 0; z-index: 1100; display: flex; align-items: center; justify-content: center; background: rgba(20,28,56,0.6); padding: 12px; }
.sm-card { background: var(--card); border-radius: var(--radius); width: 100%; max-width: 640px; max-height: 94vh; overflow-y: auto; box-shadow: 0 18px 50px rgba(20,28,56,0.45); padding: 14px 16px 18px; }
.sm-head { display: flex; align-items: center; margin-bottom: 8px; }
.sm-title { font-weight: 700; font-size: 1.25rem; color: var(--ink); flex: 1; }
.sm-stage { display: flex; align-items: center; gap: 14px; margin-bottom: 8px; }
.sm-kwrap { width: 70px; flex-shrink: 0; text-align: center; }
.sm-kwrap .kart-mini { width: 64px; }
.sm-dance { animation: smDance 0.5s ease-in-out infinite; }
@keyframes smDance { 0%,100% { transform: rotate(-6deg) translateY(0); } 50% { transform: rotate(6deg) translateY(-6px); } }

/* in-app save dialog (replaces window.prompt) */
.sm-dialog { position: absolute; inset: 0; z-index: 5; display: flex; align-items: center; justify-content: center; background: rgba(20,28,56,0.45); border-radius: var(--radius); }
.sm-dialog-box { background: var(--card); border-radius: 16px; padding: 18px; width: 86%; max-width: 340px; text-align: center; box-shadow: 0 12px 30px rgba(20,28,56,0.35); }
.sm-dialog-box h3 { margin: 4px 0 10px; }
.sm-dialog-box .wl-text-input { width: 100%; margin-bottom: 12px; }
.sm-dialog-btns { display: flex; gap: 8px; justify-content: center; }

/* Hearthstone Valley Dance Hall (now powered by the Song Maker) */
.dh-card { text-align: center; }
.dh-stage { margin: 10px auto; min-height: 110px; display: flex; align-items: flex-end; justify-content: center; }
.dh-kwrap { width: 130px; }
.dh-kwrap .kart-med { width: 120px; }
.dh-empty { font-size: 3rem; }
.dh-ctrls { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
.dh-songs { max-width: 420px; margin: 6px auto 0; text-align: left; }
.sm-transport { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.sm-controls { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 10px; font-weight: 700; color: #6c7799; font-size: 0.85rem; }
.sm-controls input[type=range] { vertical-align: middle; }
.sm-instr { display: inline-flex; gap: 6px; }
.sm-ibtn { border: 2px solid #d6e2f5; background: #f3f8ff; color: var(--ink); border-radius: 10px; padding: 6px 10px; font-family: inherit; font-weight: 700; font-size: 0.8rem; cursor: pointer; }
.sm-ibtn.on { border-color: var(--purple); background: var(--purple); color: #fff; }

.sm-gridwrap { overflow-x: auto; border-radius: 12px; }
#sm-grids { min-width: 460px; }
.sm-grid { display: flex; flex-direction: column; gap: 3px; }
.sm-melody { margin-bottom: 6px; }
.sm-drums { padding-top: 6px; border-top: 2px dashed #d6e2f5; }
.sm-row { display: flex; gap: 3px; }
.sm-cell { flex: 1 1 0; aspect-ratio: 1; min-width: 22px; border: 1px solid #e3ebf8; background: #f8fbff; border-radius: 5px; cursor: pointer; padding: 0; }
.sm-cell.bar { border-left: 2px solid #cdd9ef; }
.sm-cell.on { background: hsl(var(--hue, 210), 78%, 58%); border-color: hsl(var(--hue, 210), 60%, 45%); }
.sm-cell.drum.on { background: #3a4663; border-color: #29335c; }
.sm-cell.now { box-shadow: inset 0 0 0 2px rgba(46,155,255,0.55); }
.sm-drumrow .sm-cell { background: #eef2fb; }

.sm-saved { margin-top: 12px; }
.sm-saved h4 { margin: 0 0 6px; }
.sm-song { display: flex; align-items: center; gap: 6px; padding: 7px 8px; background: #f3f8ff; border-radius: 12px; margin-bottom: 6px; }
.sm-song-name { flex: 1; font-weight: 700; color: var(--ink); font-size: 0.9rem; }
.act-song { background: linear-gradient(180deg, #b388f0, #7c3aed) !important; color: #fff !important; }

/* ---------------- Admin tab (student profiles) ---------------- */
.wl-prof { padding: 14px 16px; }
.wl-prof.active { border: 2px solid var(--blue); box-shadow: 0 6px 0 rgba(46, 155, 255, 0.25); }
.wl-prof-head { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.wl-prof-av { font-size: 2.2rem; line-height: 1; }
.wl-prof-meta { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.wl-prof-name { font-weight: 700; font-size: 1.1rem; color: var(--ink); }
.wl-prof-badge { font-size: 0.7rem; color: var(--blue-dark); font-weight: 700; }
.wl-prof-sub { font-size: 0.82rem; color: #6c7799; font-weight: 700; }
.wl-prof-note { font-size: 0.82rem; color: #6c7799; }
.wl-prof-actions { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; }
.wl-prof-here { font-weight: 700; color: var(--green-dark); font-size: 0.85rem; background: #e7f9ee; border-radius: 999px; padding: 6px 12px; }
.wl-mini {
  border: 2px solid #d6e2f5; background: #f3f8ff; color: var(--ink);
  border-radius: 10px; padding: 7px 11px; font-family: inherit; font-weight: 700;
  font-size: 0.82rem; cursor: pointer;
}
.wl-mini:active { transform: scale(0.94); }
.wl-mini.danger { background: #ffe3e3; color: var(--red-dark); border-color: #ffd0d0; }
.wl-create > summary { cursor: pointer; font-weight: 700; color: var(--blue-dark); font-size: 1.05rem; }
.wl-create[open] > summary { margin-bottom: 10px; }
.wl-avgrid { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 5px; }
.wl-avbtn {
  width: 44px; height: 44px; border: 2px solid #d6e2f5; background: #f8fbff;
  border-radius: 12px; font-size: 1.4rem; cursor: pointer; line-height: 1;
}
.wl-avbtn.on { border-color: var(--blue); background: rgba(46, 155, 255, 0.14); }

/* Wardrobe grouped by category */
.kv-ward-cat { margin-bottom: 12px; }
.kv-ward-h { margin: 4px 0 6px; font-size: 0.95rem; color: var(--blue-dark); border-bottom: 2px solid rgba(46,155,255,0.18); padding-bottom: 3px; }

/* Decorations (scene objects in My Kindred) */
.act-decor { background: linear-gradient(180deg, #6fd0c0, #1aa3a0) !important; color: #fff !important; }
.kv-stage .kv-avatar { z-index: 3; }
.kv-decor { position: absolute; z-index: 1; pointer-events: none; font-size: 2.6rem; line-height: 1; }
.kv-decor.big { font-size: 5.6rem; }
.kv-decor.pos-behind { left: 50%; top: 2%; transform: translateX(-50%); }
.kv-decor.big.pos-behind { left: 25%; top: 0; transform: translateX(-50%); }   /* big items off-centre so they peek out */
.kv-decor.pos-left  { left: 3%;  bottom: 4%; }
.kv-decor.pos-right { right: 3%; bottom: 4%; }
.kv-xmas { position: absolute; }
.kv-xmas.big { filter: drop-shadow(0 0 9px rgba(255, 226, 120, 0.55)); animation: xmasGlow 2.6s ease-in-out infinite; }
@keyframes xmasGlow { 0%, 100% { filter: drop-shadow(0 0 8px rgba(255, 226, 120, 0.45)); } 50% { filter: drop-shadow(0 0 18px rgba(255, 226, 120, 0.9)); } }
.kv-xmas .xb { position: absolute; width: 8px; height: 8px; border-radius: 50%; box-shadow: 0 0 7px currentColor; animation: xbTwinkle 1.4s ease-in-out infinite; }
@keyframes xbTwinkle { 0%, 100% { opacity: 0.5; transform: scale(0.75); } 50% { opacity: 1; transform: scale(1.3); } }

/* Decorate panel */
.wl-decor-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; max-height: 60vh; overflow-y: auto; }
.wl-decor-item { background: #f8fbff; border: 2px solid #e3ebf8; border-radius: 14px; padding: 9px 10px; }
.wl-decor-item.big { border-color: var(--orange); }
.wl-decor-top { display: flex; align-items: center; gap: 7px; margin-bottom: 7px; }
.wl-decor-emoji { font-size: 1.7rem; }
.wl-decor-name { font-weight: 700; font-size: 0.85rem; color: var(--ink); flex: 1; }
.wl-decor-price { font-size: 0.72rem; font-weight: 700; color: var(--orange-dark); }
.wl-decor-actions { display: flex; flex-wrap: wrap; gap: 5px; }

/* Writing samples (Records → Writing) */
.wl-write { background: var(--card); border-radius: 16px; padding: 12px 14px; box-shadow: var(--shadow); border-left: 6px solid var(--orange); margin-bottom: 10px; }
.wl-write-head { font-weight: 700; color: var(--ink); font-size: 0.9rem; margin-bottom: 4px; }
.wl-write-prompt { font-size: 0.85rem; color: #6c7799; font-style: italic; margin-bottom: 6px; }
.wl-write-body { white-space: pre-wrap; word-break: break-word; line-height: 1.5; }

/* Reflections (Records → Reflections) */
.wl-refl-date { font-weight: 500; color: #8a93b5; font-size: 0.78rem; }
.wl-refl-qa { margin: 8px 0 0; padding: 8px 10px; background: #f4f0ff; border-radius: 10px; }
.wl-refl-q { font-weight: 700; color: #5b4b9e; font-size: 0.86rem; margin-bottom: 3px; }
.wl-refl-a { white-space: pre-wrap; word-break: break-word; line-height: 1.45; color: var(--ink); }
.wl-write.refl, .wl-write[data-refl] { border-left-color: var(--purple, #8b5cf6); }

.wl-report-dates { text-align: center; font-size: 0.85rem; color: #6c7799; margin: 6px 0 2px; }
/* English Skills Record — term summary */
.wl-report-actions { text-align: center; margin: 0 0 10px; }
.wl-report-doc { background: var(--card); border-radius: 16px; box-shadow: var(--shadow); padding: 18px 24px; max-width: none; margin: 0 auto; }
.wl-rep-title { text-align: center; font-size: 1.15rem; letter-spacing: 0.5px; margin: 0 0 6px; color: var(--ink); }
.wl-rep-meta { text-align: center; font-size: 0.85rem; color: #51607f; border-bottom: 2px solid #e7ecf6; padding-bottom: 12px; margin-bottom: 8px; }
.wl-rep-section { border-bottom: 1px solid #eef1f8; padding: 10px 0; }
.wl-rep-section h3 { margin: 0 0 4px; font-size: 0.95rem; color: var(--purple, #8b5cf6); letter-spacing: 0.4px; }
.wl-rep-h { margin: 12px 0 4px; font-size: 0.95rem; color: var(--purple, #8b5cf6); letter-spacing: 0.4px; }
.wl-rep-fold { border: 1.5px solid #e7def7; border-radius: 12px; margin: 8px 0; overflow: hidden; background: #fcfaff; }
.wl-rep-fold > summary { display: flex; align-items: center; justify-content: space-between; gap: 10px; cursor: pointer; padding: 11px 13px; color: var(--purple, #8b5cf6); font-weight: 800; font-size: 0.94rem; letter-spacing: 0.35px; list-style-position: inside; }
.wl-rep-fold[open] > summary { border-bottom: 1px solid #eee7f8; background: #f8f4ff; }
.wl-rep-fold-count { margin-left: auto; color: #6c7799; background: #fff; border: 1px solid #e2d9f2; border-radius: 999px; padding: 2px 9px; font-size: 0.73rem; letter-spacing: 0; white-space: nowrap; }
.wl-rep-fold-body { padding: 9px 13px 12px; }
.wl-rep-lesson { border: 1px solid #e8edf6; border-radius: 10px; margin: 7px 0; background: #fff; }
.wl-rep-lesson > summary { cursor: pointer; padding: 8px 10px; font-weight: 750; color: #41506f; }
.wl-rep-lesson .wl-rep-body { border-top: 1px solid #eef1f7; padding: 9px 11px; margin: 0; }
.wl-rep-lesson-title { margin: 10px 0 2px; color: #41506f; font-size: .92rem; }
.wl-rep-li { font-size: 0.9rem; line-height: 1.5; color: var(--ink); padding-left: 6px; }
.wl-rep-rule { border: none; border-top: 1px solid #eef1f8; margin: 8px 0; }
.wl-rep-desc { font-size: 0.82rem; font-style: italic; color: #6c7799; margin: 0 0 6px; }
.wl-rep-body { font-size: 1.08rem; line-height: 1.6; color: var(--ink); margin: 4px 0; }
.wl-rep-li { font-size: 1.06rem !important; line-height: 1.6; color: var(--ink); padding-left: 8px; margin: 3px 0; }
.wl-rep-input { font-family: inherit; font-size: 0.95rem; font-weight: 700; color: var(--ink); border: 2px solid #cdd8ee; border-radius: 8px; padding: 3px 8px; min-width: 130px; background: #fbfdff; }
.wl-rep-input:focus { outline: none; border-color: var(--purple, #8b5cf6); }
.wl-skill-h { font-weight: 800; margin: 6px 0 2px; font-size: 0.85rem; color: #51607f; }
.wl-skills { margin: 0; padding-left: 20px; }
.wl-skills li { margin: 2px 0; }
.wl-rep-sign { margin-top: 14px; font-size: 0.85rem; color: #51607f; }
@media print {
  body * { visibility: hidden; }
  .wl-report-doc, .wl-report-doc * { visibility: visible; }
  .wl-report-doc { position: absolute; left: 0; top: 0; box-shadow: none; max-width: 100%; }
  .wl-tabbar, .wl-modes, .wl-report-actions { display: none !important; }
  .wl-rep-fold, .wl-rep-lesson { display: block; }
  .wl-rep-fold > summary, .wl-rep-lesson > summary { display: none; }
  .wl-rep-fold-body { display: block; padding: 0; }
}
.wl-word-chip { display: inline-block; background: #fff4e6; color: #b3600a; border-radius: 999px; padding: 0 9px; font-size: 0.74rem; font-weight: 800; }
.wl-writing-total { text-align: center; background: var(--card); border-radius: 14px; box-shadow: var(--shadow); padding: 10px 14px; margin: 4px 0 12px; font-size: 1rem; color: var(--ink); }

/* Speaking recordings (Records → 🎙️ Speaking) */
.wl-rec-controls { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.wl-rec-btn {
  border: none; border-radius: 999px; padding: 7px 16px; font-family: inherit;
  font-weight: 700; font-size: 0.85rem; cursor: pointer; color: #fff;
  box-shadow: 0 2px 0 rgba(0,0,0,.15);
}
.wl-rec-btn.play { background: var(--green, #22c55e); }
.wl-rec-btn.stop { background: var(--orange, #f59e0b); }
.wl-rec-btn.del  { background: #ef4444; }
.wl-rec-btn:active { transform: translateY(1px); box-shadow: none; }

/* ---------------- Settings tab ----------------
   Grouped Settings chrome (2026-08-11): the find bar (search + jump chips) and
   the labelled group sections that replaced the flat eleven-card scroll. The
   cards themselves are untouched — everything below only frames them. */
/* ⚠ NOT position:sticky, and not by oversight. The settings screen's own
   wrapper (#screen-settings.qb-destination, questbyte-destinations.css) carries
   `overflow-x: clip`, which makes it the sticky scrollport — and it never
   scrolls, so a sticky bar inside it silently pins to a container that stays
   put and scrolls away exactly like a static one. Measured 2026-08-11 at
   390×844: the bar's top read 276px → −624px → −1924px as the page scrolled,
   i.e. the sticky did nothing at all. A bar that LOOKS sticky in the source and
   isn't on screen is the worse outcome, so this is deliberately static. */
.wl-set-find { margin: 0 0 6px; padding: 2px 0 8px; }
.wl-set-searchwrap { position: relative; display: block; }
.wl-set-searchico {
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  font-size: 1rem; pointer-events: none; opacity: .75;
}
.wl-set-search {
  width: 100%; box-sizing: border-box;
  border: 2.5px solid #d6e2f5; border-radius: 999px;
  padding: 11px 16px 11px 40px;
  font-family: inherit; font-size: 1rem; color: var(--ink);
  background: #fff; outline: none;
}
.wl-set-search:focus { border-color: var(--blue); }
.wl-set-search::-webkit-search-cancel-button { cursor: pointer; }
.wl-set-jump { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 9px; }
.wl-set-jbtn {
  border: 2px solid #d6e2f5; background: #fff; color: #51607f;
  border-radius: 999px; padding: 7px 13px;
  font-family: inherit; font-weight: 800; font-size: 0.84rem;
  cursor: pointer; white-space: nowrap;
}
.wl-set-jbtn:hover { border-color: var(--blue); color: var(--blue-dark, #1668b0); }
.wl-set-jbtn:active { transform: translateY(1px); }
/* The selected tab (2026-08-25: chips switch sections one-at-a-time, like
   Teacher Reports' views) reads as pressed-in and stays obvious at a glance. */
.wl-set-jbtn-on, .wl-set-jbtn-on:hover {
  background: var(--blue); border-color: var(--blue); color: #fff;
}
.wl-set-group { margin: 0 0 6px; scroll-margin-top: 96px; border-radius: 18px; }
.wl-set-gh {
  margin: 20px 0 2px; font-size: 0.86rem; font-weight: 900;
  text-transform: uppercase; letter-spacing: .07em; color: #51607f;
}
.wl-set-gsub { margin: 0 0 2px; color: #8a93ad; font-size: 0.86rem; line-height: 1.4; }
/* A jumped-to group pulses once, so a parent can see WHERE the chip landed
   them — a silent scroll on a page of near-identical cards reads as nothing
   having happened. */
.wl-set-flash { animation: wl-set-flash 1.4s ease; }
@keyframes wl-set-flash {
  0%, 100% { box-shadow: 0 0 0 0 rgba(46, 155, 255, 0); }
  18%      { box-shadow: 0 0 0 6px rgba(46, 155, 255, .22); }
}
.wl-set-none {
  margin: 18px 2px; color: #6c7799; font-size: 0.95rem; text-align: center;
}
@media (prefers-reduced-motion: reduce) { .wl-set-flash { animation: none; } }

.wl-card {
  background: var(--card); border-radius: var(--radius); padding: 16px 18px;
  box-shadow: var(--shadow); margin: 14px 0;
}
.wl-card h3 { margin: 0 0 10px; }
.wl-muted { color: #6c7799; font-size: 0.92rem; margin: 0 0 12px; }
.wl-profile { display: flex; flex-direction: column; gap: 8px; }
.wl-prow {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 7px 0; border-bottom: 1px dashed rgba(41, 51, 92, 0.12);
}
.wl-prow:last-child { border-bottom: none; }
.wl-prow span { color: #6c7799; }

/* ---------------- parent modal ---------------- */
.wl-modal-back {
  position: fixed; inset: 0; z-index: 1000;
  display: none; align-items: center; justify-content: center;
  background: rgba(20, 28, 56, 0.55); padding: 18px;
}
.wl-modal-back.show { display: flex; }
.wl-modal-card {
  background: var(--card); border-radius: var(--radius);
  padding: 22px 22px 24px; max-width: 460px; width: 100%;
  max-height: 88vh; overflow-y: auto; position: relative;
  box-shadow: 0 18px 50px rgba(20, 28, 56, 0.4); text-align: center;
}
.wl-modal-card h2 { margin: 4px 0 8px; }
.wl-modal-emoji { font-size: 2.6rem; }
.wl-modal-sub { color: #6c7799; font-size: 0.95rem; margin: 0 0 14px; }
.wl-modal-x {
  position: absolute; top: 10px; right: 12px; border: none; background: #eef2fb;
  width: 34px; height: 34px; border-radius: 50%; cursor: pointer; font-size: 1rem; color: var(--ink);
}
.wl-modal-x:active { transform: scale(0.9); }

.wl-field {
  display: block; text-align: left; font-weight: 700; color: var(--ink);
  font-size: 0.9rem; margin: 10px 0;
}
.wl-pin-input, .wl-text-input {
  display: block; width: 100%; margin-top: 5px;
  border: 2.5px solid #d6e2f5; border-radius: 14px;
  padding: 12px 14px; font-family: inherit; font-size: 1.1rem; color: var(--ink);
  background: #f8fbff; outline: none;
}
.wl-pin-input { letter-spacing: 0.4em; text-align: center; font-size: 1.5rem; }
.wl-pin-input:focus, .wl-text-input:focus { border-color: var(--blue); background: #fff; }
.wl-pin-msg { color: var(--red-dark); font-weight: 700; min-height: 1.2em; margin: 8px 0; font-size: 0.92rem; }
.wl-hr { border: none; border-top: 2px dashed rgba(41, 51, 92, 0.15); margin: 16px 0; }

.wl-verify-tabs { display: flex; gap: 8px; margin: 8px 0 12px; }
.wl-vtab {
  flex: 1; border: 2px solid #d6e2f5; background: #f3f8ff; color: #6c7799;
  border-radius: 12px; padding: 9px; font-weight: 700; cursor: pointer; font-size: 0.85rem;
}
.wl-vtab.active { border-color: var(--blue); background: rgba(46, 155, 255, 0.12); color: var(--blue-dark); }

/* parent records view */
.wl-parent-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.wl-parent-head h2 { margin: 0; }
.wl-parent-count { text-align: left; color: #6c7799; font-weight: 700; font-size: 0.85rem; margin: 8px 0; }
.wl-filters {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end;
  text-align: left; margin: 12px 0; padding: 12px; background: #f3f8ff; border-radius: 14px;
}
.wl-filters label { display: flex; flex-direction: column; font-size: 0.74rem; font-weight: 700; color: #6c7799; gap: 3px; }
.wl-filters input, .wl-filters select {
  border: 2px solid #d6e2f5; border-radius: 10px; padding: 7px 9px;
  font-family: inherit; font-size: 0.9rem; color: var(--ink); background: #fff;
}
.wl-clearf {
  border: none; background: #eef2fb; color: var(--ink); border-radius: 10px;
  padding: 8px 12px; font-weight: 700; cursor: pointer; align-self: flex-end;
}
.wl-danger {
  border: none; background: #ffe3e3; color: var(--red-dark); border-radius: 12px;
  padding: 8px 14px; font-weight: 700; cursor: pointer; font-size: 0.85rem;
}
.wl-danger:active, .wl-clearf:active { transform: scale(0.94); }
.wl-reclist.wl-admin { max-height: 46vh; overflow-y: auto; }

/* 🎧 Spell-by-ear grid (Records → Spell the word you heard) */
.wl-spell-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.wl-spell { display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  background: var(--card); border-radius: 12px; padding: 8px 12px; box-shadow: var(--shadow);
  border-left: 6px solid var(--green, #3ecf6a); }
.wl-spell.no { border-left-color: var(--orange, #ff9f2e); }
.wl-spell-mark { font-size: 1rem; }
.wl-spell-word { font-weight: 800; font-size: 1.05rem; color: var(--ink); }
.wl-spell-typed { font-size: 0.78rem; color: #b25b00; width: 100%; }

/* ===== Dance Hall — merged from anam-vale-claude-merge zip 2026-06-21 ===== */
.dh-fullstage {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, 340px); gap: 14px;
  min-height: min(78vh, 760px);
}
.dh-stage-panel { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.dh-zone-tabs { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.dh-zone-tab {
  border: 2px solid #d9d3f4; border-radius: 10px; background: #fff; color: #3f3568;
  box-shadow: 0 3px 0 rgba(62,50,90,.16); padding: 9px 14px; font: inherit; font-weight: 700; cursor: pointer;
}
.dh-zone-tab.on { background: linear-gradient(180deg,#ef5a9b,#d83b82); color: #fff; border-color: #b82c6a; }
.dh-zone-tab:active { transform: translateY(2px); box-shadow: 0 1px 0 rgba(62,50,90,.18); }
.dh-floor {
  position: relative; min-height: 560px; overflow: hidden; border: 3px solid #4e3474;
  border-radius: 14px; background-position: center; background-size: cover; background-repeat: no-repeat;
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.36), 0 8px 0 rgba(57,35,74,.18);
  outline: none;
}
.dh-floor.dh-zone-main {
  background-image:
    linear-gradient(180deg, rgba(28,18,48,.08), rgba(24,12,36,.22)),
    url("anam/images/area-interiors-storybook-hq/dance_hall_empty_floor.png");
}
.dh-floor.dh-zone-upstairs {
  background-image:
    linear-gradient(180deg, rgba(28,18,48,.04), rgba(24,12,36,.16)),
    url("anam/images/dance/dance-hall-upper-gallery.png");
}
.dh-floor:focus-visible { box-shadow: inset 0 0 0 2px rgba(255,255,255,.36), 0 8px 0 rgba(57,35,74,.18), 0 0 0 4px rgba(104,214,205,.45); }
.dh-floor::after {
  content: ""; position: absolute; inset: auto 0 0; height: 42%; pointer-events: none;
  background: radial-gradient(ellipse at 48% 80%, rgba(255,232,137,.34), transparent 62%);
}
.dh-floor-glow {
  position: absolute; inset: 0; pointer-events: none; opacity: .65;
  background:
    radial-gradient(circle at 48% 64%, rgba(255,243,174,.35), transparent 18%),
    radial-gradient(circle at 74% 34%, rgba(184,134,255,.24), transparent 20%),
    radial-gradient(circle at 24% 38%, rgba(96,227,255,.18), transparent 22%);
}
.dh-performance {
  position: absolute; z-index: 4; left: 48%; top: 66%; width: clamp(170px, 20vw, 250px);
  transform: translate(-50%, -50%); pointer-events: none;
}
.dh-performance .dh-kwrap { width: 100%; position: relative; z-index: 2; }
.dh-performance #dh-kindred { position: relative; z-index: 3; transform-origin: 50% 92%; }
.dh-performance #dh-kindred .kart-med { width: clamp(160px, 18vw, 230px); }
.dh-performance #dh-kindred>.kart { transform: scaleX(var(--dh-face-x, 1)); transform-origin: 50% 100%; }
.dh-performance.is-walking #dh-kindred { animation: dhKindredWalk .38s ease-in-out infinite; }
.dh-performance #dh-kindred.sm-dance { animation: dhKindredDance .62s ease-in-out infinite; }
.dh-performance #dh-kindred.sm-dance .kart { filter: drop-shadow(0 13px 10px rgba(255,220,104,.34)); }
.dh-performance #dh-kindred.sm-dance::before,
.dh-performance #dh-kindred.sm-dance::after {
  content: ""; position: absolute; inset: 9% 5% 2%; z-index: -1; border-radius: 50%;
  background: radial-gradient(circle, rgba(255,232,130,.34), rgba(170,108,255,.12) 44%, transparent 70%);
  transform: rotate(-13deg); animation: dhDanceAura .62s ease-in-out infinite;
}
.dh-performance #dh-kindred.sm-dance::after { animation-delay: -.31s; transform: rotate(15deg) scale(.9); opacity: .55; }
.dh-stage-shadow {
  position: absolute; left: 50%; bottom: 3%; z-index: 1; width: 58%; height: 16px;
  transform: translateX(-50%); border-radius: 50%; background: rgba(36,20,30,.25); filter: blur(5px);
}
.dh-floor-caption {
  position: absolute; left: 18px; bottom: 16px; z-index: 5; max-width: 360px; padding: 10px 13px;
  border: 2px solid rgba(255,255,255,.38); border-radius: 11px; color: #fff;
  background: rgba(40,24,62,.52); box-shadow: 0 5px 18px rgba(21,12,36,.2);
  display: none;
}
.dh-floor-caption h2 { margin: 0 0 3px; font-size: clamp(1.45rem, 2.8vw, 2.2rem); color: #fff; }
.dh-floor-caption p { margin: 0; font-size: .9rem; }
.dh-sidebar {
  display: flex; flex-direction: column; gap: 12px; min-width: 0; padding: 13px;
  border: 3px solid #ddcfef; border-radius: 14px; background: linear-gradient(180deg,#fff,#f8f3ff);
  box-shadow: 0 5px 0 rgba(74,52,112,.13);
}
.dh-dj-card {
  display: grid; grid-template-columns: 132px minmax(0,1fr); gap: 10px; align-items: center;
  padding: 9px; border-radius: 12px; background: linear-gradient(145deg,#fffaf0,#efe9ff);
  border: 2px solid #e5d6f4;
}
.dh-dj-card h3 { margin: 0 0 4px; color: #3f3568; }
.dh-dj-card p { margin: 0; color: #695f88; font-size: .82rem; line-height: 1.25; }
.dh-dj-illustration { position: relative; height: 132px; overflow: hidden; border-radius: 12px; background: #21152f; box-shadow: inset 0 0 0 2px rgba(255,255,255,.2); }
.dh-dj-image { display:block; width:100%; height:100%; object-fit:cover; }
.dh-dj-avatar { position: absolute; left: 50%; bottom: 36px; width: 76px; transform: translateX(-50%); z-index: 2; }
.dh-dj-avatar .kv-avatar { padding: 0; background: none; border: 0; box-shadow: none; }
.dh-dj-avatar .kart-mini { width: 74px; filter: drop-shadow(0 6px 5px rgba(0,0,0,.28)); }
.dh-turntables {
  position: absolute; left: 9px; right: 9px; bottom: 10px; height: 38px; border-radius: 13px;
  background: linear-gradient(180deg,#f3d58b,#916646); border: 2px solid rgba(255,255,255,.45);
  box-shadow: inset 0 3px 0 rgba(255,255,255,.3);
}
.dh-turntables span {
  position: absolute; top: 6px; width: 24px; height: 24px; border-radius: 50%;
  background: radial-gradient(circle at 50% 50%,#fff8d2 0 14%,#4d365c 15% 42%,#1e1830 43%);
}
.dh-turntables span:first-child { left: 14px; }
.dh-turntables span:last-child { right: 14px; }
.dh-sidebar .dh-ctrls { justify-content: stretch; }
.dh-sidebar .dh-ctrls .anam-btn { flex: 1; min-width: 126px; }
.dh-songs-title { margin: 0 2px; color: #3f3568; }
.dh-sidebar .dh-songs { max-width: none; margin: 0; }
.dh-song { background: #f5f1ff; border: 2px solid #e4d8f5; border-radius: 12px; }
.dh-song .wl-mini { white-space: nowrap; }
@keyframes dhKindredDance {
  0%,100% { transform: rotate(-6deg) translateY(0) scale(1); }
  25% { transform: rotate(4deg) translateY(-13px) scale(1.04,.96); }
  50% { transform: rotate(8deg) translateY(-2px) scale(.98,1.03); }
  75% { transform: rotate(-4deg) translateY(-9px) scale(1.03,.98); }
}
@keyframes dhKindredWalk {
  0%,100% { transform: translateY(0) rotate(-1deg); }
  50% { transform: translateY(-7px) rotate(1deg); }
}
@keyframes dhDanceAura {
  0%,100% { opacity: .26; scale: .92; }
  50% { opacity: .58; scale: 1.1; }
}
@media(max-width:850px) {
  .dh-fullstage { grid-template-columns: 1fr; min-height: 0; }
  .dh-floor { min-height: clamp(360px, 72vw, 560px); }
  .dh-sidebar { order: 2; }
}

/* APP-LIKE SHELL: editable fields retain selection; controls tap promptly;
   gameplay alone contains zoom; touch devices avoid costly fixed blur/paint. */

/* never let iOS bump font sizes on rotate; keeps the app layout stable */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* Suppress stray selection, then restore it on real editing surfaces. */
body {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
input, textarea, select,
[contenteditable="true"], [contenteditable=""], [contenteditable] *,
.wl-text-selectable, .wl-text-selectable * {
  -webkit-user-select: text;
  user-select: text;
  -webkit-touch-callout: default;
}

/* Fast taps; game drag zones can override this with touch-action:none. */
a, button, label,
[role="button"], [onclick],
input, select, textarea,
.wl-tab, .choice-btn, .topic-btn, .card, .stat-chip, .home-btn,
.subject-btn, .go-btn, .pw-tab, .exit-home-btn, .wl-logout-btn {
  touch-action: manipulation;
}

/* Gameplay only: pages remain zoomable; wrappers pan vertically; play surfaces
   own gestures. Suffixes cover Arcade/Zh Arcade, Drawing and Science Lab. */
:is(.screen[id$="arcade"],.screen[id$="drawing"],.screen[id$="lab"],#screen-math2,#screen-studios,#screen-sciinquiry,#screen-wordgym,#screen-hearthboard,#screen-anamvale,#screen-kindredvillage){touch-action:pan-y}
:is(.screen[id$="arcade"],.screen[id$="drawing"],.screen[id$="lab"],#screen-math2,#screen-studios,#screen-sciinquiry,#screen-wordgym,#screen-hearthboard,#screen-anamvale,#screen-kindredvillage) canvas,#screen-lesson.active #step-area canvas,:is(#screen-anamvale,#screen-kindredvillage) .ow-viewport{touch-action:none}
#screen-lesson.active:has(#step-area canvas) .lesson-shell{touch-action:pan-y}
@supports selector(body:has(.screen.active)){body:has(:is(.screen[id$="arcade"],.screen[id$="drawing"],.screen[id$="lab"],#screen-math2,#screen-studios,#screen-sciinquiry,#screen-wordgym,#screen-hearthboard,#screen-anamvale,#screen-kindredvillage).active),body:has(#screen-lesson.active #step-area canvas){touch-action:pan-y}}

/* 3 — perf pass, TOUCH DEVICES ONLY (desktop keeps the glassy look).
   backdrop-filter on a fixed, always-visible bar + a fixed-attachment body
   background are the two effects that force a full-screen repaint on every
   scroll frame — the classic source of jank on older iPads. */
@media (hover: none) and (pointer: coarse) {
  .wl-tabbar {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: #fff;            /* was rgba(255,255,255,.92) + blur */
  }
  /* loaded after game.css, so equal-specificity theme selectors are overridden
     by source order — no !important needed. */
  body,
  body.th_ocean, body.th_space, body.th_jungle, body.th_candy {
    background-attachment: scroll;
  }

  /* 4 — kill :hover effects on touch. There is no real hover on a touchscreen, but
     iOS fires the :hover state on every tap — so these hover transforms/filters/glint
     animations run a GPU repaint + composite on each tap BEFORE the tap resolves,
     which reads as "the button is laggy" on an older iPad. Neutralising them makes a
     tap go straight to the :active press feedback (kept — that's the useful one).
     Same-specificity + source-order beats game.css; no !important needed. */
  .subject-btn:hover, .go-btn:hover, .say-btn:hover, .pw-tab:hover,
  .topbar .home-btn:hover, .topic-btn:hover, .choice-btn:hover,
  .word-tile:hover, .match-tile:hover, .story-opt:hover, .sort-item:hover, .card:hover {
    transform: none;
    filter: none;
  }
  .subject-btn:hover::after { animation: none; }
  /* remove the grey iOS tap-flash on the common controls; the :active press state
     is the deliberate, instant feedback instead. */
  a, button, [role="button"], [onclick],
  .subject-btn, .go-btn, .say-btn, .pw-tab, .home-btn,
  .topic-btn, .choice-btn, .wl-tab, .stat-chip, .card {
    -webkit-tap-highlight-color: transparent;
  }
}

/* ── "Not saved to the cloud" banner (2026-07-28) ─────────────────────────────
   Raised only after bounded quiet recovery fails (or a permanent save problem).
   Deliberately at
   the TOP: the bottom of the screen already carries the tab bar (z-index 900)
   and the floating read-aloud bar (901), and putting one more fixed element
   down there is exactly how the 2026-07-28 "Finish never got the tap" bug
   happened. Sits below overlays (1000) and modals (1100) so it can never
   swallow a dialog's buttons. */
.wl-sync-banner {
  position: fixed; left: 0; right: 0; top: 0; z-index: 995;
  padding: calc(8px + env(safe-area-inset-top, 0px)) 10px 8px;
  background: #7a2e2e; color: #fff;
  box-shadow: 0 2px 10px rgba(0,0,0,0.28);
  font-size: 0.86rem; line-height: 1.35;
}
.wl-sync-banner-in {
  max-width: 820px; margin: 0 auto;
  display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap;
}
.wl-sync-banner-icon { font-size: 1.15rem; line-height: 1.2; }
.wl-sync-banner-text { flex: 1 1 260px; min-width: 0; }
.wl-sync-banner-text small { display: block; margin-top: 4px; opacity: 0.82; font-size: 0.76rem; }
.wl-sync-banner-steps { margin-top: 7px; }
.wl-sync-banner-steps ol { margin: 5px 0 4px; padding-left: 1.25rem; }
.wl-sync-banner-steps li { margin: 2px 0; }
.wl-sync-banner-btn,
.wl-sync-banner-x {
  flex: 0 0 auto; cursor: pointer;
  border: 1px solid rgba(255,255,255,0.55); border-radius: 8px;
  background: rgba(255,255,255,0.12); color: #fff;
  font: inherit; font-weight: 700;
  padding: 7px 12px; min-height: 40px;   /* a real finger target, not a 20px chip */
  touch-action: manipulation;
}
.wl-sync-banner-x { padding: 7px 10px; font-weight: 400; }
.wl-sync-banner-btn:disabled { opacity: 0.6; cursor: default; }
@media (max-width: 480px) { .wl-sync-banner { font-size: 0.8rem; } }

/* 🔁 Practice — competence pulse + short-session progress (review §9d, 2026-08-24) */
.wl-rev-pulse { text-align: center; margin: 2px auto 10px; font-size: .95rem; color: var(--ink, #2b3a55); }
.wl-rev-pulse strong { color: var(--green-dark, #1f7a1f); }
.rv-progress { height: 10px; border-radius: 6px; background: #e6ebf5; margin: 4px 0 10px; overflow: hidden; }
.rv-progress > i { display: block; height: 100%; border-radius: 6px; background: linear-gradient(90deg, #4caf50, #8bc34a); transition: width .3s; }
.rv-coach { background: #fffbe6; border: 1px solid #f0dd8c; border-radius: 10px; padding: 8px 10px; margin: 0 0 10px; font-size: .92rem; }
.rv-coach b { color: #7a5a00; }
.rv-coach .rv-last { color: #7a2f2f; }

/* 🗂 Record Keeping — the three early-return empty states (2026-08-25).
   render() emits these BEFORE .wrk-wrap exists ("Grown-ups only", "Add a learner
   first", "Loading learners…"), so BOTH de-bold rules in wordlab-recordkeeping.js
   — .wrk-wrap :is(h1,h2,h3,h4) and .wrk-wrap b,strong,th,summary — miss them and
   the <h2> fell back to the UA default 700 while its own <p> sat at 400. Measured
   live on questbyte.org at 700 on a student's refusal screen and on a new parent's
   first Record Keeping screen. It lives HERE, not in the module, because
   wordlab-recordkeeping.js is reporting-lock protected: editing it turns the lock
   RED and re-blocks EVERY lane's deploy for a cosmetic change. No .css file is
   lock-protected. Fold it into the module's own style block on the next blessed
   RK change and delete this. */
.wrk-empty h2 { font-weight: 400; }

/* 📔 Record Keeping — full-window phone workspace (2026-08-31).
   The Record Keeping module already owns a bounded inner workspace, but the
   site chrome around it still consumed most of a phone viewport: the global
   top bar wrapped to three rows and the grown-up destination bar wrapped to
   two. The module's final visual layer also changed its six-section phone grid
   back into a horizontal strip after the earlier "all sections visible" rule,
   so a family with several learners could see only learner chips and none of
   Today / History / Coverage / Samples / Documents / Files.

   This is deliberately presentation-only and scoped to the ACTIVE Record
   Keeping screen. It does not change the tab markup, role gates, handlers,
   learner selection, record/planner data, Teacher Reports, Records, Practice,
   sync or storage. The fixed destination bar remains fully reachable as one
   labelled horizontal rail; its measured height is still published through
   --wl-tabbar-h, so the module's existing sizeWorkspace() calculation remains
   the single source of truth for the usable height. */
@media (max-width: 820px) {
  body:has(#screen-recordkeeping.screen.active) .topbar {
    display: none !important;
  }

  body:has(#screen-recordkeeping.screen.active) .app {
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 0 !important;
  }

  #screen-recordkeeping.screen.active {
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 0 !important;
  }

  #screen-recordkeeping #recordkeeping-root,
  #screen-recordkeeping .wrk-wrap {
    width: 100%;
    max-width: none;
  }

  #screen-recordkeeping .wrk-wrap {
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  /* One compact, scrollable row keeps every global destination reachable
     without making Record Keeping pay for a two-row navigation tray. */
  body:has(#screen-recordkeeping.screen.active) #wl-tabbar {
    flex-wrap: nowrap;
    justify-content: flex-start;
    align-content: center;
    gap: 2px;
    max-height: none;
    padding: 4px 6px calc(4px + env(safe-area-inset-bottom, 0px));
    overflow-x: auto;
    overflow-y: hidden;
  }

  body:has(#screen-recordkeeping.screen.active) #wl-tabbar .wl-tab {
    flex: 0 0 58px;
    min-width: 58px;
    max-width: 58px;
    min-height: 52px;
    padding: 3px 1px;
  }

  body:has(#screen-recordkeeping.screen.active) #wl-tabbar .wl-tab-ico {
    font-size: 1.05rem;
  }

  body:has(#screen-recordkeeping.screen.active) #wl-tabbar .wl-tab-lbl {
    font-size: .58rem;
    line-height: 1.05;
  }

  /* Identity stays compact, and the currently selected learner is not repeated
     as a chip directly below the same name. Selecting another learner makes
     the previous learner available in the switch row immediately. */
  #screen-recordkeeping .wrk-journal-header {
    padding: 9px 11px 6px;
  }

  #screen-recordkeeping .wrk-journal-header h2 {
    font-size: 19px;
  }

  #screen-recordkeeping .wrk-journal-header .wrk-navadd {
    flex-basis: 36px;
    width: 36px;
    min-width: 36px;
    height: 36px;
    min-height: 36px;
    font-size: 20px !important;
  }

  #screen-recordkeeping .wrk-navrow,
  #screen-recordkeeping .wrk-navrow.one {
    display: flex !important;
    grid-template-columns: none !important;
    flex-wrap: wrap;
    gap: 5px !important;
    padding: 6px 8px 0 !important;
    overflow: visible !important;
  }

  #screen-recordkeeping .wrk-navrow .wrk-kids {
    display: flex;
    flex: 0 0 100%;
    gap: 5px;
    max-width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
  }

  #screen-recordkeeping .wrk-navrow .wrk-kids::-webkit-scrollbar {
    display: none;
  }

  #screen-recordkeeping .wrk-navrow:not(.one) .wrk-kids button.on {
    display: none;
  }

  #screen-recordkeeping .wrk-kids button {
    flex: 0 0 auto;
    min-height: 34px;
    padding: 3px 8px 3px 4px;
    font-size: 13px !important;
  }

  /* Five persistent destinations match the approved compact design. Documents
     and Files stay one tap away inside More; their compatibility routes and
     pane ids remain unchanged. */
  #screen-recordkeeping .wrk-navrow .wrk-panebar {
    display: grid !important;
    flex: 0 0 100%;
    grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
    gap: 0 !important;
    width: 100%;
    margin: 0 !important;
    padding: 0 !important;
  }

  #screen-recordkeeping .wrk-navrow .wrk-pane {
    width: 100% !important;
    min-width: 0 !important;
    min-height: 54px !important;
    padding: 5px 2px !important;
    justify-content: center;
    font-size: 12px !important;
    overflow: hidden !important;
    text-overflow: ellipsis;
  }

  #screen-recordkeeping .wrk-plan-mid {
    padding: 11px 12px;
  }

  #screen-recordkeeping .wrk-journal-pagehead h3 {
    font-size: 20px;
  }

  #screen-recordkeeping .wrk-journal-pagehead .wrk-view-switch button {
    padding: 5px 7px;
    font-size: 14px !important;
  }

  /* Three summary facts belong on one compact line, not a two-column block
     with the third fact stranded underneath. */
  #screen-recordkeeping .wrk-insights {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px;
    margin: 10px 0 12px;
    padding: 9px 0;
  }

  #screen-recordkeeping .wrk-insights > div:last-child {
    grid-column: auto;
  }

  #screen-recordkeeping .wrk-insights .wrk-ins-big b {
    font-size: 23px;
  }

  #screen-recordkeeping .wrk-insights b,
  #screen-recordkeeping .wrk-insights .wrk-ins-stat b {
    font-size: 17px;
  }

  #screen-recordkeeping .wrk-insights small,
  #screen-recordkeeping .wrk-insights .wrk-ins-big small,
  #screen-recordkeeping .wrk-insights .wrk-ins-stat small {
    font-size: 11px !important;
    line-height: 1.22 !important;
  }

  #screen-recordkeeping .wrk-journal-section {
    margin-top: 12px;
  }

  #screen-recordkeeping .wrk-journal-section-head {
    gap: 8px;
    margin-bottom: 5px;
  }

  #screen-recordkeeping .wrk-journal-section-head h3 {
    font-size: 18px;
  }

  #screen-recordkeeping .wrk-journal-section-head button {
    flex: 0 0 auto;
    font-size: 14px !important;
    white-space: nowrap;
  }

  /* The empty state previously offered "Record learning" twice in the same
     eight-line area. Keep the clear section action and reduce the body to its
     useful status sentence. */
  #screen-recordkeeping .wrk-journal-actual .wrk-note {
    margin: 0;
    padding: 4px 0;
    line-height: 1.35 !important;
  }

  #screen-recordkeeping .wrk-journal-actual .wrk-note .wrk-link {
    display: none;
  }
}

/* The same five destinations stay stable on a portrait tablet. */
@media (min-width: 701px) and (max-width: 820px) {
  #screen-recordkeeping .wrk-navrow .wrk-panebar {
    grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
  }
}

/* ── 📓 Teacher Reports — hold the panel to its two-weight scale (2026-08-25) ────────────
   The de-bold took `wordlab-teacher-report.js` from 8 weights to 2 (400 body / 700
   structure), but that swept only the TR module's OWN css. The panel EMBEDS other
   modules, so the RUNNING page still carried six weights. Measured on the artefacts
   view (📄 Reports & archive, 361 painted text elements):
       400 x260 · 600 x22 · 700 x69 · 800 x5 · 850 x2 · 900 x3
   Two different causes, so two different kinds of rule below.

   (1) The 900s were nobody's decision. They come from the user agent's own
       `strong, b { font-weight: bolder }`, which is RELATIVE: 400 -> 700 (on scale) but
       700 -> 900 wherever an emphasis tag sits inside an already-bold parent — here a
       <b> inside `.wt-report-ed summary{font-weight:700}`. Grep can never find it: it is
       in no stylesheet on disk. `:where()` carries ZERO specificity, so this displaces
       only the UA default and every explicit rule (e.g. `.tr-index-row strong{...:400}`)
       still wins. The owner's 41 <strong> + 82 <b> semantic tags are KEPT — this changes
       what they weigh, never whether they exist.

   (2) The 600s/800s are `wordlab-nsw.js`'s own authored scale, which predates the
       de-bold. Mapped onto the two weights by role, matching what Teacher Reports uses
       for the same job: controls 400 (TR's own `.wt-tool`/`.wt-primary`/`.wt-send` are
       400), body text 400, status marks 700. Scoped to `#teacher-root` so the NSW module
       is unchanged on every other surface.

   NOT changed, deliberately: the two `.go-btn` primary buttons that compute 850 from
   `.qb-destination .go-btn{font-weight:850 !important}` in questbyte-destinations.css.
   That is the SITE-WIDE primary-button identity; overriding it only inside Teacher
   Reports would make TR's primary buttons disagree with every other destination — a
   bigger inconsistency than the one it would fix. One line here if that call changes.

   Verified on the running page: TR off-scale 32 -> 2, the 30 fixed and nothing else
   moved. Gate: tools/measure-tr-emphasis-weight-cdp.js */
:where(#teacher-root) :where(b, strong) { font-weight: 700; }
#teacher-root .wl-nsw-lev { font-weight: 400; }
#teacher-root .wl-nsw-row .wl-nsw-rt { font-weight: 400; }
#teacher-root .wl-nsw-grid .d { font-weight: 400; }
#teacher-root .wl-nsw-tick { font-weight: 700; }
