      :root {
        --bg: #d8f3ff;
        --bg-soft: #fff3cf;
        --card: #ffffff;
        --ink: #233246;
        --ink-soft: #51637a;
        --line: #a5dcff;
        --cat: #ff8a3d;
        --cat-dark: #e56f1d;
        --teal: #0dc2ab;
        --teal-dark: #07897a;
        --coral: #ff6b6b;
        --coral-dark: #e04e4e;
        --sun: #ffd23c;
        --sun-dark: #dd9a06;
        --sky: #2f9dff;
        --sky-dark: #1b6ac9;
        --pink: #ff8fb2;
        --shadow: 0 6px 0 rgba(30, 90, 140, 0.16);
        --radius: 26px;
        /* App cho bé luôn dùng theme sáng, bất kể cài đặt hệ thống của máy */
        color-scheme: light;
      }
      * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
      html, body { margin: 0; padding: 0; }
      /* Kid-proofing (v18): the app is a game surface, not a document —
         no pull-to-refresh / scroll chaining, no double-tap zoom delay,
         no long-press callout, no text selection or image dragging in
         the kid area. The parent zone (#screen-parent) and any form
         field keep normal document behavior. Companion JS guards live
         in the "kid-guard" script at the end of body. */
      html, body { overscroll-behavior: none; }
      body { touch-action: manipulation; -webkit-touch-callout: none; }
      #screen-parent { -webkit-touch-callout: default; }
      body { user-select: none; -webkit-user-select: none; }
      #screen-parent, #screen-parent *, input, textarea, [contenteditable="true"] { user-select: text; -webkit-user-select: text; }
      img, svg, canvas { -webkit-user-drag: none; }
      .chart-overlay { overscroll-behavior: contain; }
      body {
        font-family: "Baloo 2", "M PLUS Rounded 1c", system-ui, sans-serif;
        /* v87 addendum 2 (bi photo QA 07:15): the yellow sun blob and
           the pink/green corner circles showed OUTSIDE the centred
           app column at wide frames as strange colour streaks at the
           screen edges ("vệt màu lạ ở mép"). The page backdrop is now
           one plain sky — clouds only, no coloured blobs; every
           screen paints its own scenery inside the app. */
        background:
          radial-gradient(ellipse 190px 54px at 14% 3%, rgba(255, 255, 255, 0.95) 58%, rgba(255, 255, 255, 0) 62%),
          radial-gradient(ellipse 150px 44px at 86% 9%, rgba(255, 255, 255, 0.9) 58%, rgba(255, 255, 255, 0) 62%),
          linear-gradient(180deg, #8fd8ff 0%, #c4efff 30%, #eafcff 55%, #fff6d8 82%, #e6fbdc 100%);
        color: var(--ink);
        min-height: 100dvh;
      }
      button { font-family: inherit; cursor: pointer; border: none; background: none; color: inherit; }
      button:focus-visible { outline: 4px solid var(--sky); outline-offset: 2px; }

      .wrap { max-width: 760px; margin: 0 auto; padding: 14px 14px 40px; }

      /* ---------- Header: stickers + language ---------- */
      .topbar {
        display: flex; align-items: center; justify-content: space-between; gap: 10px;
        margin-bottom: 12px;
      }
      .sticker-box {
        display: flex; align-items: center; gap: 10px;
        background: var(--card); border: 3px solid var(--sun); border-radius: 999px;
        padding: 6px 16px 6px 8px; box-shadow: var(--shadow);
      }
      .sticker-box .s-ico { width: 40px; height: 40px; display: block; }
      .sticker-box .s-num { font-size: 30px; font-weight: 800; line-height: 1; color: var(--cat-dark); }
      .sticker-box .s-label { font-size: 14px; font-weight: 700; color: var(--ink-soft); line-height: 1.05; }
      .sticker-box.pop { animation: pop .45s ease; }
      @keyframes pop { 0% { transform: scale(1); } 40% { transform: scale(1.14) rotate(-2deg); } 100% { transform: scale(1); } }

      .home-btn {
        display: none; align-items: center; gap: 8px;
        background: var(--card); border: 3px solid var(--line); border-radius: 999px;
        padding: 10px 18px; font-size: 19px; font-weight: 800; box-shadow: var(--shadow);
        min-height: 56px;
      }
      .home-btn.show { display: inline-flex; }
      .home-btn:active { transform: translateY(3px); box-shadow: none; }

      .langbar { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; margin-bottom: 18px; }
      .lang-btn {
        min-height: 64px; border-radius: 20px; font-size: 21px; font-weight: 800;
        background: linear-gradient(180deg, #ffffff, #eef9ff); border: 3px solid var(--line); color: var(--ink-soft);
        box-shadow: var(--shadow); padding: 8px 4px; line-height: 1.1;
      }
      .lang-btn small { display: block; font-size: 13px; font-weight: 700; opacity: .75; }
      /* Japanese sub-label must stay on one line: CJK text wraps anywhere,
         which split にほんごで まなぶ mid-phrase (…まな / ぶ). Shrink + nowrap. */
      .lang-btn[data-lang="ja"] small { font-size: 11px; white-space: nowrap; letter-spacing: -.02em; }
      .lang-btn.active[data-lang="vi"] { background: var(--coral); border-color: var(--coral-dark); color: #fff; }
      .lang-btn.active[data-lang="en"] { background: var(--sky); border-color: var(--sky-dark); color: #fff; }
      .lang-btn.active[data-lang="ja"] { background: var(--teal); border-color: var(--teal-dark); color: #fff; }
      .lang-btn:active { transform: translateY(3px); box-shadow: none; }
      /* v56 (Addendum 7): flag + localized name on every language
         label. The name is set in the CURRENT UI language (JA names
         are pure hiragana so the child can read all three). On
         narrow rows the name yields and the flag alone carries the
         button — the active colour still marks the current one. */
      .lang-flag { margin-right: 5px; }
      /* v57: the flags are inline SVG (emoji flags degrade to
         letter codes on Windows). Sized in em so each control's
         own font-size scales its flag; the hairline ring keeps the
         white JP flag visible on white buttons. */
      .lang-flag svg { width: 1.3em; height: 0.98em; display: inline-block; vertical-align: -0.14em; border-radius: 2.5px; box-shadow: 0 0 0 1px rgba(35, 50, 70, .16); }
      .lang-btn .lang-name, .lang-opt .lang-name { white-space: nowrap; }
      /* flags-only below 360px: at 360+ the fit-text helper shrinks
         the name to fit (verified by screenshot); below that the
         three names cannot stay readable even at the minimum size */
      @media (max-width: 359px) {
        .lang-btn .lang-name { display: none; }
        .lang-btn .lang-flag { margin-right: 0; font-size: 24px; }
        .lang-pop-cur .lang-name { display: none; }
        .lang-pop-cur .lang-flag { margin-right: 0; }
      }
      #menuLangCur { white-space: nowrap; }

      /* Compact language popover (v15, real-device feedback #7): on the
         pet screen at phone widths the full langbar row collapses into
         one compact language button in the topbar — same popover
         pattern as the pet colour picker — so the freed row goes to
         the play panel. The wide layout and the home screen keep the
         full langbar. (v56 addendum: the button shows flag + name
         only — the decorative 🌐 prefix was removed as redundant.) */
      .lang-pop-wrap { position: relative; display: none; }
      .lang-pop-btn { display: inline-flex; align-items: center; gap: 5px; border-radius: 999px; }
      .lang-pop-cur { font-size: 14px; font-weight: 800; line-height: 1; }
      .lang-pop {
        position: absolute; top: calc(100% + 8px); right: 0; z-index: 90;
        display: flex; flex-direction: column; gap: 6px; padding: 8px; min-width: 176px;
        background: rgba(255, 255, 255, .97); border: 2.5px solid var(--line);
        border-radius: 18px; box-shadow: var(--shadow);
      }
      .lang-pop[hidden] { display: none; }
      .lang-opt {
        min-height: 44px; padding: 6px 12px; border-radius: 12px; text-align: left;
        font-size: 16px; font-weight: 800; color: var(--ink-soft);
        background: #fff; border: 2.5px solid var(--line); cursor: pointer;
      }
      .lang-opt.active[data-lang="vi"] { background: var(--coral); border-color: var(--coral-dark); color: #fff; }
      .lang-opt.active[data-lang="en"] { background: var(--sky); border-color: var(--sky-dark); color: #fff; }
      .lang-opt.active[data-lang="ja"] { background: var(--teal); border-color: var(--teal-dark); color: #fff; }
      @media (max-width: 600px) {
        body.on-pet .langbar { display: none; }
        body.on-pet .lang-pop-wrap { display: block; }
      }

      /* ---------- Screens ---------- */
      .screen { display: none; }
      .screen.active { display: block; animation: fadein .25s ease; }
      @keyframes fadein { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

      .hero {
        background: linear-gradient(135deg, #fff3b8 0%, #ffe3f0 52%, #d6f2ff 100%); border: 3px solid #ffb84d; border-radius: var(--radius);
        box-shadow: var(--shadow); padding: 18px; display: flex; align-items: center; gap: 16px;
        margin-bottom: 16px;
      }
      .hero .cat { width: 128px; height: 128px; flex: 0 0 auto; }
      .hero h1 { font-size: 30px; margin: 0 0 4px; line-height: 1.15; }
      .hero p { margin: 0; font-size: 18px; color: var(--ink-soft); font-weight: 600; line-height: 1.35; }

      .menu { display: grid; gap: 12px; margin-top: 14px; }
      .menu-btn {
        display: flex; align-items: center; gap: 16px; text-align: left;
        background: var(--card); border: 3px solid var(--line); border-radius: var(--radius);
        box-shadow: var(--shadow); padding: 16px 18px; min-height: 96px; width: 100%;
      }
      .menu-btn:active { transform: translateY(3px); box-shadow: none; }
      .menu-btn .m-ico {
        width: 64px; height: 64px; flex: 0 0 auto; border-radius: 20px;
        display: flex; align-items: center; justify-content: center; font-size: 36px;
        background: #ffd9a8;
      }
      .menu-btn .m-name { font-size: 25px; font-weight: 800; line-height: 1.15; }
      .menu-btn .m-desc { font-size: 16px; font-weight: 600; color: var(--ink-soft); line-height: 1.3; }

      /* ---------- Pet farm (home) ---------- */
      .farm-title { font-size: 26px; font-weight: 800; margin: 4px 0 12px; text-align: center; }
      .pet-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
      .pet-card {
        background: var(--card); border: 3px solid var(--line); border-radius: var(--radius);
        box-shadow: var(--shadow); padding: 16px 10px 14px; text-align: center; width: 100%;
      }
      .pet-card:active { transform: translateY(3px); box-shadow: none; }
      .pet-grid .pet-card:nth-child(1) { border-color: #ff9f45; background: linear-gradient(180deg, #ffffff, #fff3e2); }
      .pet-grid .pet-card:nth-child(2) { border-color: #4db2ff; background: linear-gradient(180deg, #ffffff, #e8f6ff); }
      .pet-grid .pet-card:nth-child(3) { border-color: #ff8fb2; background: linear-gradient(180deg, #ffffff, #ffedf4); }
      .pet-grid .pet-card:nth-child(4) { border-color: #3ecf5a; background: linear-gradient(180deg, #ffffff, #e9fbe9); }
      .pet-card .p-face { width: 118px; height: 118px; margin: 0 auto; border-radius: 50%; }
      /* Live PixiJS mini pets on the home screen (hero + pet cards):
         a transparent host overlays the static SVG art; once a live
         renderer is ready the wrapper gets .has-live and the static
         art hides. If Pixi/WebGL never comes up, the static art stays. */
      #heroCat { position: relative; }
      .pet-card .p-face { position: relative; }
      .pet-mini-host { position: absolute; inset: 0; }
      .pet-mini-host canvas { display: block; }
      #heroCat.has-live > svg, .pet-card .p-face.has-live > svg, #shopPreviewFace.has-live > svg, .sc-face.has-live > svg { display: none; }
      .pet-card .p-name { font-size: 27px; font-weight: 800; line-height: 1.15; margin-top: 4px; }
      .pet-card .p-food { display: flex; align-items: center; justify-content: center; gap: 7px; font-size: 17px; font-weight: 700; color: var(--ink-soft); margin-top: 2px; }
      .pet-card .p-food svg { width: 34px; height: 26px; }
      .pet-card .p-hearts { font-size: 19px; letter-spacing: 2px; margin-top: 6px; min-height: 24px; }
      .pet-card .p-cta { font-size: 15px; font-weight: 800; color: var(--cat-dark); margin-top: 2px; }

      /* ---------- Game common ---------- */
      .panel {
        background: linear-gradient(180deg, #ffffff, #f2fbff); border: 3px solid var(--line); border-radius: var(--radius);
        box-shadow: var(--shadow); padding: 20px 16px; text-align: center;
      }
      .task { font-size: 27px; font-weight: 800; line-height: 1.3; margin: 0 0 4px; }
      .task-sub { font-size: 16px; font-weight: 600; color: var(--ink-soft); margin: 0 0 14px; }
      .speaker-btn {
        display: inline-flex; align-items: center; gap: 10px;
        background: linear-gradient(180deg, #ffd93c, #ffb52e); border: 3px solid var(--sun-dark); color: #4a3200;
        border-radius: 999px; padding: 12px 26px; font-size: 22px; font-weight: 800;
        box-shadow: 0 5px 0 rgba(35,50,70,.15); min-height: 64px;
      }
      .speaker-btn:active { transform: translateY(3px); box-shadow: none; }
      .speaker-btn svg { width: 30px; height: 30px; }
      .speaker-btn.huge { font-size: 26px; padding: 18px 34px; min-height: 84px; }
      .speaker-btn.huge svg { width: 40px; height: 40px; }

      .msg { min-height: 40px; font-size: 24px; font-weight: 800; margin: 12px 0 0; }
      .msg.good { color: var(--teal-dark); }
      .msg.try { color: var(--coral-dark); }

      /* v69: the win presentation is ONE slim horizontal bar in every
         mode — praise text on the left, the big Next button on the
         right. The old stacked banner (26px text over a 64px button,
         205-248px tall) swallowed the lower part of the panel and
         covered the child's finished work; the celebration itself is
         carried by confetti + the flying sticker + the pet. */
      .win-banner {
        display: none; margin-top: 16px; background: linear-gradient(180deg, #fff8cf, #ffeeb0);
        border: 3px dashed var(--sun-dark); border-radius: var(--radius); padding: 8px 12px;
      }
      /* grow-in only (never past scale 1): the shared `pop` keyframes
         overshoot to 1.14 + tilt, which would paint the bar outside
         its box — over the artwork's edge — for a few frames. */
      .win-banner.show { display: flex; align-items: center; gap: 10px; animation: winBarIn .45s ease; }
      @keyframes winBarIn { 0% { transform: scale(.92); opacity: .4; } 100% { transform: scale(1); opacity: 1; } }
      .win-banner .w-text { font-size: 15px; font-weight: 800; line-height: 1.22; margin: 0; flex: 1 1 auto; text-align: left; }
      .win-banner .next-btn {
        min-height: 50px; padding: 6px 14px; font-size: 17px; flex: 0 0 auto;
      }
      .next-btn {
        background: var(--teal); border: 3px solid var(--teal-dark); color: #fff;
        border-radius: 999px; padding: 14px 32px; font-size: 23px; font-weight: 800;
        box-shadow: 0 5px 0 rgba(35,50,70,.18); min-height: 64px;
      }
      .next-btn:active { transform: translateY(3px); box-shadow: none; }

      .shake { animation: shake .4s ease; }
      @keyframes shake { 0%,100% { transform: translateX(0); } 25% { transform: translateX(-8px); } 75% { transform: translateX(8px); } }
      .bounce { animation: bounce .6s ease; }
      @keyframes bounce { 0%,100% { transform: translateY(0); } 35% { transform: translateY(-16px); } 65% { transform: translateY(2px); } }
      .phr { white-space: nowrap; }

/* v91 ART: art-first glyphs (renderer helpers.js picHTML/artImgHTML). */
.art-pic { width: 1.22em; height: 1.22em; object-fit: contain; vertical-align: -0.18em; }
/* v91 choreography: HUD flips in place on screen switch (nav.js showScreen
   retriggers .nav-flip on body; the topbar itself never unmounts). */
@keyframes hudFlip { 0% { opacity: 1; transform: translateY(0); } 40% { opacity: .3; transform: translateY(-5px); } 100% { opacity: 1; transform: translateY(0); } }
body.nav-flip .topbar { animation: hudFlip .4s ease; }
@media (prefers-reduced-motion: reduce) {
  body.nav-flip .topbar { animation: none; }
}
