/* ============================================================================
 * style.css — a warm yellow room with a big friendly face in it.
 *
 * Deliberate constraints:
 *  - Nothing on screen strobes. Background changes ease over 0.5s and there is
 *    no full-screen flash, because fast full-field luminance flicker is a real
 *    photosensitivity risk for small children.
 *  - Everything is enormous. A 16-month-old is looking at shape and colour from
 *    across a lap, not reading.
 *  - No scrollbars, no selection, no text cursor, no drag ghosts. There is
 *    nothing here she can put into a broken state.
 * ========================================================================== */

:root {
  --bg: #FFD93D;
  --accent: #FF6BAA;
  --ink: #34314C;
  --font: 'Segoe UI Rounded', 'Arial Rounded MT Bold', 'Segoe UI Variable Display',
          'Segoe UI', system-ui, sans-serif;
  --emoji: 'Segoe UI Emoji', 'Apple Color Emoji', 'Noto Color Emoji', sans-serif;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  width: 100%; height: 100%;
  overflow: hidden;
  background: var(--bg);
  font-family: var(--font);
  color: var(--ink);
  cursor: none;                 /* the pointer itself is a distraction */
  user-select: none;
  -webkit-user-select: none;
  -webkit-user-drag: none;
}

img { -webkit-user-drag: none; pointer-events: none; }
.hidden { display: none !important; }

/* --- boot screen ---------------------------------------------------------- */

#loading {
  position: fixed; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 26px;
  background: var(--bg);
  z-index: 100;
}
.load-emoji { font-family: var(--emoji); font-size: 120px; animation: bob 1.6s ease-in-out infinite; }
.load-title { font-size: 42px; font-weight: 900; color: #E8557F; }
.load-bar {
  width: min(560px, 60vw); height: 26px;
  background: #fff6; border: 5px solid #fff; border-radius: 999px; overflow: hidden;
}
.load-fill { height: 100%; width: 0%; background: #FF6BAA; border-radius: 999px; transition: width .18s ease; }
.load-count { font-size: 22px; font-weight: 700; color: #B4763A; }

/* --- stage ---------------------------------------------------------------- */

#stage {
  position: fixed; inset: 0;
  background: var(--bg);
  transition: background-color .5s ease;   /* never a hard flash */
  overflow: hidden;
}

/* Soft cyan blobs, echoing the show's backdrop. Slow drift keeps the frame
   alive without competing with the card for attention. */
#blob, #blob2 {
  position: absolute;
  background: #4FC3E8;
  opacity: .55;
  border-radius: 46% 54% 58% 42% / 52% 44% 56% 48%;
  filter: blur(2px);
}
#blob  { width: 62vw; height: 74vh; left: 18vw; top: 12vh; animation: drift 22s ease-in-out infinite; }
#blob2 { width: 22vw; height: 24vh; right: 6vw; bottom: 8vh; opacity: .38; animation: drift 17s ease-in-out infinite reverse; }

@keyframes drift {
  0%, 100% { transform: translate(0,0) rotate(0deg) scale(1); }
  33%      { transform: translate(2.5vw,-2vh) rotate(6deg) scale(1.05); }
  66%      { transform: translate(-2vw,2.5vh) rotate(-5deg) scale(.96); }
}

#paint, #fx { position: absolute; inset: 0; pointer-events: none; }
#paint { z-index: 1; }
#fx    { z-index: 4; }

/* --- the teaching card ---------------------------------------------------- */

#card {
  position: absolute;
  left: 50%; top: 46%;
  /* Base scale lives in a variable so the press animations can wobble around
     whatever the current scale is — song mode shrinks the card, and a nudge
     must not snap it back to full size. */
  --card-scale: 1;
  transform: translate(-50%, -50%) scale(var(--card-scale));
  z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 44px 76px;
  background: #fff;
  border: 14px solid var(--accent);
  border-radius: 56px;
  box-shadow: 0 22px 0 rgba(0,0,0,.10), 0 0 0 10px #ffffff88;
  min-width: 30vw;
}

/* While a song is on, the card lifts and shrinks so the troupe below is the
   thing she is actually looking at. */
#stage.song-mode #card {
  top: 38%;
  --card-scale: .86;
  transition: top .4s ease, transform .4s ease;
}

#card.pop { animation: pop .42s cubic-bezier(.2,1.5,.4,1); }
@keyframes pop {
  0%   { transform: translate(-50%,-50%) scale(calc(var(--card-scale) * .55)) rotate(-7deg); }
  65%  { transform: translate(-50%,-50%) scale(calc(var(--card-scale) * 1.09)) rotate(2.5deg); }
  100% { transform: translate(-50%,-50%) scale(var(--card-scale)) rotate(0deg); }
}

/* Pressing while the lesson is locked: a small wobble that says "I heard you"
   without replacing what she is being taught. */
#card.nudge { animation: nudge .34s cubic-bezier(.3,1.5,.5,1); }
@keyframes nudge {
  0%   { transform: translate(-50%,-50%) scale(var(--card-scale)) rotate(0deg); }
  45%  { transform: translate(-50%,-50%) scale(calc(var(--card-scale) * 1.055)) rotate(-1.6deg); }
  100% { transform: translate(-50%,-50%) scale(var(--card-scale)) rotate(0deg); }
}

/* A held key shouldn't relaunch the card; it should feel like it's humming. */
#card.holding { animation: hum .55s ease-in-out infinite; }
@keyframes hum {
  0%,100% { transform: translate(-50%,-50%) scale(var(--card-scale)) rotate(0deg); }
  50%     { transform: translate(-50%,-50%) scale(calc(var(--card-scale) * 1.045)) rotate(1.2deg); }
}

#glyph {
  font-size: clamp(120px, 21vw, 300px);
  font-weight: 900;
  line-height: .96;
  color: var(--accent);
  text-shadow: 0 8px 0 rgba(0,0,0,.10);
}
#glyph:empty { display: none; }

#objects {
  font-family: var(--emoji);
  font-size: clamp(50px, 8vw, 116px);
  line-height: 1.1;
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  justify-content: center; max-width: 62vw;
}
/* The fewer the objects, the bigger they get. A lone animal should fill the
   card; ten counting objects still need to fit on one screen. */
#objects[data-count="1"] { font-size: clamp(110px, 17vw, 250px); }
#objects[data-count="2"] { font-size: clamp(90px, 13vw, 190px); }
#objects[data-count="3"] { font-size: clamp(76px, 11vw, 160px); }
#objects:empty { display: none; }
#objects span { display: inline-block; animation: popIn .4s cubic-bezier(.2,1.6,.4,1) backwards; }
@keyframes popIn { from { transform: scale(0) rotate(-40deg); } to { transform: scale(1) rotate(0); } }

#word {
  font-size: clamp(34px, 5.4vw, 82px);
  font-weight: 900;
  color: var(--ink);
  letter-spacing: .5px;
}
#word:empty { display: none; }

/* --- the teacher ---------------------------------------------------------- */

#character {
  position: absolute;
  left: 1.5vw; bottom: 0;
  height: min(66vh, 620px);
  z-index: 3;
  transform-origin: bottom center;
  animation: bob 2.8s ease-in-out infinite;
  filter: drop-shadow(0 10px 14px rgba(0,0,0,.16));
}
@keyframes bob {
  0%,100% { transform: translateY(0) rotate(0deg); }
  50%     { transform: translateY(-13px) rotate(-1.2deg); }
}

#character.react { animation: react .55s cubic-bezier(.2,1.4,.4,1); }
@keyframes react {
  0%   { transform: scale(1) rotate(0deg); }
  35%  { transform: scale(1.10) rotate(4deg) translateY(-16px); }
  70%  { transform: scale(.98) rotate(-3deg) translateY(2px); }
  100% { transform: scale(1) rotate(0deg); }
}

/* --- the song cast -------------------------------------------------------- */

/* Friends and themed animals line up beside the teacher during a song. Each is
   two nested spans so the entrance and the bounce can both use transform
   without one clobbering the other. */
#cast {
  position: absolute;
  /* Starts clear of the teacher and stops clear of the right edge, so nobody
     is ever half off the screen. */
  left: 30vw; right: 2vw; bottom: 1.5vh;
  height: 23vh;
  display: flex; align-items: flex-end; justify-content: space-evenly;
  z-index: 5;                 /* in front of the card, never clipped by it */
  pointer-events: none;
}
.cast-slot {
  display: inline-block;
  animation: castIn .55s cubic-bezier(.2,1.5,.4,1) backwards;
}
.cast-emoji {
  display: inline-block;
  font-family: var(--emoji);
  font-size: clamp(46px, 6.4vw, 104px);
  filter: drop-shadow(0 8px 10px rgba(0,0,0,.18));
  animation: castBounce 1.05s ease-in-out infinite;
}
/* A six-animal farm needs to be smaller than a three-friend singalong. */
#cast[data-count="5"] .cast-emoji { font-size: clamp(44px, 5.8vw, 94px); }
#cast[data-count="6"] .cast-emoji { font-size: clamp(40px, 5.2vw, 86px); }
@keyframes castIn {
  from { transform: translateY(140px) scale(.35); opacity: 0; }
  to   { transform: translateY(0) scale(1); opacity: 1; }
}
@keyframes castBounce {
  0%, 100% { transform: translateY(0) rotate(-4deg); }
  50%      { transform: translateY(-26px) rotate(4deg); }
}
.cast-slot.leaving { animation: castOut .4s ease-in forwards; }
@keyframes castOut {
  to { transform: translateY(120px) scale(.4); opacity: 0; }
}

/* While a song plays the teacher dances a little harder. */
#character.singing { animation: sing 1.05s ease-in-out infinite; }
@keyframes sing {
  0%, 100% { transform: translateY(0) rotate(-3deg) scale(1); }
  50%      { transform: translateY(-24px) rotate(3deg) scale(1.04); }
}

/* --- parent exit handshake ------------------------------------------------ */

#exitHint {
  position: absolute; right: 34px; bottom: 30px; z-index: 20;
  display: flex; align-items: center; gap: 14px;
  background: #000000AA; color: #fff;
  padding: 14px 22px; border-radius: 999px;
}
.exit-ring { width: 44px; height: 44px; border-radius: 50%; background: #ffffff33; overflow: hidden; position: relative; }
.exit-fill { position: absolute; bottom: 0; left: 0; width: 100%; height: 0%; background: #FF6BAA; transition: height .1s linear; }
.exit-text { font-size: 22px; font-weight: 800; }

/* ==========================================================================
 * MOBILE — phones and tablets.
 *
 * The desktop layout assumes a wide, short 16:9 frame with a keyboard. A phone
 * held upright is the opposite, so the whole composition is restacked: the card
 * moves up and grows, the teacher shrinks into the bottom corner, and the song
 * bar tucks along the top out of a toddler's natural hand position.
 * ========================================================================== */

/* Nothing about the page should scroll, bounce, zoom or select under a finger. */
body.touch,
body.touch #stage {
  touch-action: none;
  -webkit-touch-callout: none;
  overscroll-behavior: none;
}

/* --- the song bar (touch only) -------------------------------------------- */

#songbar { display: none; }

body.touch #songbar {
  display: flex;
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 10px);
  left: 50%;
  transform: translateX(-50%);
  gap: 10px;
  z-index: 30;
  padding: 8px 12px;
  background: #ffffff8c;
  border-radius: 999px;
  backdrop-filter: blur(6px);
}

.song-btn {
  width: 62px; height: 62px;
  border: none;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 4px 0 rgba(0,0,0,.14);
  font-family: var(--emoji);
  font-size: 32px;
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
  display: flex; align-items: center; justify-content: center;
}
.song-btn:active { transform: translateY(3px); box-shadow: 0 1px 0 rgba(0,0,0,.14); }

/* --- portrait phones and small tablets ------------------------------------ */

@media (orientation: portrait), (max-width: 860px) {
  #card {
    top: 38%;
    min-width: 80vw;
    max-width: 94vw;
    padding: 26px 30px;
    border-width: 10px;
    border-radius: 40px;
    gap: 6px;
  }
  #stage.song-mode #card { top: 34%; }

  #glyph   { font-size: clamp(96px, 30vw, 240px); }
  #objects { font-size: clamp(46px, 15vw, 120px); max-width: 82vw; }
  #objects[data-count="1"] { font-size: clamp(110px, 34vw, 260px); }
  #objects[data-count="2"] { font-size: clamp(84px, 26vw, 200px); }
  #objects[data-count="3"] { font-size: clamp(70px, 21vw, 170px); }
  #word    { font-size: clamp(30px, 8.5vw, 64px); }

  /* She sits in the corner so the card and the tap area own the screen. On a
     narrow phone she is deliberately smaller than on the desktop: at full size
     she is 60% of the width and the cast ends up hidden behind her. */
  #character {
    height: min(26vh, 230px);
    left: 0; bottom: calc(env(safe-area-inset-bottom, 0px));
  }

  /* Portrait has no room for a row beside the teacher, so the cast gets its own
     full-width band directly above her. */
  #cast {
    left: 2vw; right: 2vw;
    /* Clears her STATIC height plus the ~26px her bob/sing animation lifts her,
       plus a margin — measured, not guessed. */
    bottom: calc(env(safe-area-inset-bottom, 0px) + min(26vh, 230px) + 48px);
    height: 13vh;
    justify-content: space-evenly;
  }
  .cast-emoji                       { font-size: clamp(38px, 12vw, 78px); }
  #cast[data-count="5"] .cast-emoji { font-size: clamp(34px, 10.5vw, 70px); }
  #cast[data-count="6"] .cast-emoji { font-size: clamp(30px, 9vw, 62px); }

  .song-btn { width: 54px; height: 54px; font-size: 27px; }
  #songbar  { gap: 7px; padding: 6px 9px; }

  .load-title { font-size: 26px; text-align: center; padding: 0 20px; }
  .load-emoji { font-size: 84px; }
}

/* A phone turned sideways is the hardest frame: ~390px tall. The portrait rules
   above also match it (it is under 860px wide), so this block has to re-place
   every element rather than just resize them — otherwise the card sits behind
   the song bar and the cast lands on top of the teacher.

   The song bar becomes a vertical strip on the right edge, and the cast gets
   the floor between the teacher and that strip. */
@media (orientation: landscape) and (max-height: 520px) {
  body.touch #songbar {
    top: 50%;
    left: auto;
    right: calc(env(safe-area-inset-right, 0px) + 8px);
    transform: translateY(-50%);
    flex-direction: column;
    gap: 6px;
    padding: 7px 6px;
  }
  .song-btn { width: 42px; height: 42px; font-size: 21px; }

  #card {
    top: 46%;
    min-width: 34vw;
    max-width: 58vw;
    padding: 12px 22px;
    border-width: 8px;
    border-radius: 30px;
  }
  #stage.song-mode #card { top: 44%; }

  #glyph   { font-size: clamp(56px, 20vh, 120px); }
  #objects { font-size: clamp(34px, 13vh, 90px); }
  #objects[data-count="1"] { font-size: clamp(60px, 26vh, 150px); }
  #objects[data-count="2"] { font-size: clamp(48px, 20vh, 120px); }
  #objects[data-count="3"] { font-size: clamp(40px, 16vh, 100px); }
  #word    { font-size: clamp(20px, 6.5vh, 40px); }

  #character { height: min(56vh, 250px); }

  /* Floor strip: starts clear of the teacher, stops clear of the song bar. */
  #cast {
    left: 27vw;
    right: 9vw;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 2px);
    height: 32vh;
  }
  .cast-emoji                       { font-size: clamp(24px, 9vh, 54px); }
  #cast[data-count="5"] .cast-emoji { font-size: clamp(22px, 8vh, 48px); }
  #cast[data-count="6"] .cast-emoji { font-size: clamp(20px, 7vh, 44px); }
}

/* The parent exit handshake is keyboard-only, so it has no place on a tablet —
   there the OS does the locking (iOS Guided Access / Android screen pinning). */
body.touch #exitHint { display: none !important; }

/* Large portrait tablets: the phone caps leave the teacher stranded small in a
   lot of empty yellow, so let her (and the cast) grow into the space. */
@media (orientation: portrait) and (min-width: 700px) {
  #character { height: min(31vh, 430px); }
  #cast {
    bottom: calc(env(safe-area-inset-bottom, 0px) + min(31vh, 430px) + 40px);
    height: 15vh;
  }
  .cast-emoji                       { font-size: clamp(52px, 9vw, 104px); }
  #cast[data-count="5"] .cast-emoji { font-size: clamp(46px, 8vw, 92px); }
  #cast[data-count="6"] .cast-emoji { font-size: clamp(42px, 7vw, 82px); }
  .song-btn { width: 66px; height: 66px; font-size: 33px; }
}

/* --- always-visible exit reminder ----------------------------------------- */

/* The app is deliberately inescapable for a toddler, which makes it essential
   that an adult can always see the way out without remembering it. Small and
   faint so it never competes with the card. */
#exitLabel {
  position: absolute;
  right: calc(env(safe-area-inset-right, 0px) + 12px);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 8px);
  z-index: 25;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .3px;
  color: #00000038;
  pointer-events: none;
  user-select: none;
}

/* On a tablet the OS does the locking, so there is no in-app shortcut to show. */
body.touch #exitLabel { display: none !important; }

/* ==========================================================================
 * SETUP / SETTINGS
 *
 * The only adult-facing surface in the app. It has to scroll and accept typing,
 * which the play surface deliberately forbids, so it overrides those rules for
 * itself. Reached on first launch, or later only via a 1.5s press-and-hold.
 * ========================================================================== */

.sheet {
  position: fixed; inset: 0;
  z-index: 200;
  background: #FFF8E1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  touch-action: auto;
  overscroll-behavior: contain;
  cursor: auto;
  padding: calc(env(safe-area-inset-top, 0px) + 28px) 20px
           calc(env(safe-area-inset-bottom, 0px) + 36px);
}
.sheet * { touch-action: auto; }

.sheet-inner { max-width: 760px; margin: 0 auto; }

.sheet h1 {
  font-size: clamp(28px, 5vw, 44px);
  font-weight: 900;
  color: #E8557F;
  margin-bottom: 6px;
}
.sheet .sub { font-size: clamp(15px, 2.2vw, 19px); color: #7a6a52; margin-bottom: 26px; }

.sheet .field { margin-bottom: 26px; }
.sheet .field > label {
  display: block;
  font-size: 13px; font-weight: 800; letter-spacing: .10em;
  text-transform: uppercase; color: #9a8a6e;
  margin-bottom: 10px;
}
.sheet .field small { display: block; margin-top: 7px; font-size: 13px; color: #9a8a6e; }

.sheet input[type="text"] {
  width: 100%;
  font: inherit; font-size: 20px; font-weight: 700;
  padding: 14px 16px;
  border: 3px solid #F0E2C0;
  border-radius: 16px;
  background: #fff;
  color: var(--ink);
  cursor: text;
  user-select: text; -webkit-user-select: text;
}
.sheet input[type="text"]:focus { outline: none; border-color: #FF6BAA; }

.opts { display: flex; flex-wrap: wrap; gap: 12px; }

.opt {
  flex: 1 1 140px;
  min-width: 128px;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 14px 10px;
  background: #fff;
  border: 3px solid #F0E2C0;
  border-radius: 20px;
  cursor: pointer;
  font: inherit; color: var(--ink);
  transition: border-color .15s ease, transform .1s ease;
}
.opt:active { transform: scale(.97); }
.opt.on { border-color: #FF6BAA; box-shadow: 0 0 0 4px #FF6BAA22; }
.opt img { width: 74px; height: 74px; object-fit: contain; object-position: top; }
.opt .opt-dot { font-family: var(--emoji); font-size: 34px; line-height: 1; }
.opt strong { font-size: 16px; font-weight: 800; }
.opt small { font-size: 12px; color: #9a8a6e; text-align: center; }

.sheet .cta {
  width: 100%;
  margin-top: 8px;
  padding: 18px;
  font: inherit; font-size: 21px; font-weight: 900;
  color: #fff; background: #FF6BAA;
  border: none; border-radius: 999px;
  box-shadow: 0 6px 0 #D4487F;
  cursor: pointer;
}
.sheet .cta:active { transform: translateY(4px); box-shadow: 0 2px 0 #D4487F; }

/* --- the parent gate ------------------------------------------------------ */

#settingsBtn {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 10px);
  right: calc(env(safe-area-inset-right, 0px) + 10px);
  width: 46px; height: 46px;
  z-index: 40;
  border: none; border-radius: 50%;
  background: #ffffff55;
  display: grid; place-items: center;
  cursor: pointer;
  opacity: .4;
  transition: opacity .2s ease;
}
#settingsBtn.holding { opacity: 1; background: #ffffffcc; }
#settingsBtn .gear { font-family: var(--emoji); font-size: 21px; line-height: 1; }
/* Fills up as the parent holds, so the gesture is discoverable. */
#settingsBtn .ring {
  position: absolute; inset: 0;
  border-radius: 50%;
  background: conic-gradient(#FF6BAA var(--pct, 0%), transparent 0);
  opacity: .55;
  pointer-events: none;
}

/* On touch the song bar sits top-centre, so nudge the gear clear of it. */
body.touch #settingsBtn { top: calc(env(safe-area-inset-top, 0px) + 6px); }

/* --- legal links + the grown-ups-only gate -------------------------------- */

.legal-links {
  margin-top: 22px;
  text-align: center;
  font-size: 14px;
  color: #9a8a6e;
}
.legal-links a { color: #C2185B; text-decoration: underline; cursor: pointer; }
.legal-links small { display: inline-block; margin-top: 6px; font-size: 13px; }

.gate {
  position: fixed; inset: 0;
  z-index: 300;
  background: #00000066;
  display: grid; place-items: center;
  padding: 20px;
  cursor: auto;
}
.gate-box {
  background: #fff;
  border-radius: 24px;
  padding: 28px 26px;
  width: min(400px, 100%);
  text-align: center;
  box-shadow: 0 18px 50px rgba(0,0,0,.3);
}
.gate-box h2 { font-size: 24px; font-weight: 900; color: #E8557F; margin-bottom: 6px; }
.gate-box p { color: #6f6580; font-size: 15px; margin-bottom: 10px; }
.gate-q { font-size: 34px; font-weight: 900; color: var(--ink); margin: 12px 0 14px; }
.gate-in {
  width: 100%; font: inherit; font-size: 24px; font-weight: 800; text-align: center;
  padding: 12px; border: 3px solid #F0E2C0; border-radius: 14px;
  user-select: text; -webkit-user-select: text; cursor: text;
}
.gate-in:focus { outline: none; border-color: #FF6BAA; }
.gate-err { color: #D4145A; font-weight: 700; font-size: 14px; margin-top: 8px; }
.gate-actions { display: flex; gap: 10px; margin-top: 16px; }
.gate-actions button {
  flex: 1; font: inherit; font-size: 16px; font-weight: 800;
  padding: 13px; border-radius: 999px; border: none; cursor: pointer;
}
.gate-cancel { background: #F0E2C0; color: #6f6580; }
.gate-ok { background: #FF6BAA; color: #fff; }
