/* =========================================================================
   THE LAB — the interactive activities.

   Shares the book's palette and type. Everything here is sized for a finger
   first: the smallest thing a child has to hit is 44px, tiles are bigger
   than that, and nothing depends on hover. Animations respect
   prefers-reduced-motion, which for a children's product is not a nicety —
   some children cannot use a page that moves.
   ====================================================================== */

.lgl-lab {
  --ink: #26313F; --ink-soft: #5C6B7E; --ink-faint: #8A97A6;
  --blue: #2F6FEB; --teal: #12A594; --coral: #FF6B4A; --sun: #FFC53D;
  --grape: #8B5CF6; --sky: #9CC9FF;
  --paper: #FFFCF5; --mist: #EEF2F7; --ghost: #E9EDF2; --line: #C8D0DA;
  --r: 16px;
  font-family: "LGL Body", system-ui, -apple-system, "Segoe UI", sans-serif;
  color: var(--ink);
  max-width: 1040px;
  margin-inline: auto;
  padding: 16px;
}
.lgl-lab *, .lgl-lab *::before, .lgl-lab *::after { box-sizing: border-box; }
.lgl-lab h1, .lgl-lab h2, .lgl-lab h3, .lgl-lab b {
  font-family: "LGL Display", "Trebuchet MS", sans-serif; font-weight: 400;
}

.lgl-loading, .lgl-oops { text-align: center; padding: 60px 20px; color: var(--ink-soft); }

/* ------------------------------------------------------------ picker --- */
.lab-head { display: flex; gap: 16px; align-items: flex-start; margin-bottom: 14px; }
.lab-head h1 { margin: 0; font-size: clamp(1.7rem, 1.2rem + 2vw, 2.6rem); }
.lab-head__sub { margin: 4px 0 0; color: var(--ink-soft); font-size: .95rem; max-width: 52ch; }
.lab-jar {
  margin-left: auto; text-align: center; background: #fff; border: 2px solid var(--ink);
  border-radius: 999px; padding: 8px 18px; box-shadow: 0 3px 0 var(--ink); flex: none;
}
.lab-jar b { display: block; font-size: 1.5rem; line-height: 1; color: var(--sun);
  -webkit-text-stroke: .6px var(--ink); }
.lab-jar span { font-size: .66rem; text-transform: uppercase; letter-spacing: .09em;
  color: var(--ink-soft); }

.lab-progress { height: 10px; background: var(--ghost); border-radius: 99px;
  overflow: hidden; margin-bottom: 16px; }
.lab-progress i { display: block; height: 100%; background: var(--teal);
  border-radius: 99px; transition: width .6s cubic-bezier(.22,1,.36,1); }

.lab-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
.lab-tab {
  border: 2px solid var(--ghost); background: #fff; border-radius: 999px;
  padding: 9px 16px; font: inherit; font-size: .88rem; font-weight: 600;
  color: var(--ink-soft); cursor: pointer; min-height: 40px;
}
.lab-tab.is-on { border-color: var(--ink); color: var(--ink); background: var(--sun); }

.lab-grid { display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 210px), 1fr)); }
.lab-card {
  display: flex; flex-direction: column; gap: 3px; text-align: left;
  background: #fff; border: 2px solid var(--ghost); border-left-width: 7px;
  border-radius: var(--r); padding: 13px 14px; font: inherit; cursor: pointer;
  transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
}
.lab-card:hover { transform: translateY(-3px); border-color: var(--line);
  box-shadow: 0 8px 20px rgba(38,49,63,.10); }
.lab-card--match  { border-left-color: var(--blue); }
.lab-card--circle { border-left-color: var(--coral); }
.lab-card--drag   { border-left-color: var(--teal); }
.lab-card--trace  { border-left-color: var(--grape); }
.lab-card--maze   { border-left-color: var(--sun); }
.lab-card--tap    { border-left-color: #0EA5A0; }
.lab-card__top { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.lab-card__top b { font-size: .8rem; color: var(--ink-soft); }
.lab-card__kind { font-size: .68rem; text-transform: uppercase; letter-spacing: .07em;
  color: var(--ink-faint); }
.lab-card__title { font-family: "LGL Display", sans-serif; font-size: 1.06rem; line-height: 1.2; }
.lab-card__skill { font-size: .8rem; color: var(--ink-soft); }
.lab-card__stars { margin-top: 5px; letter-spacing: 2px; color: var(--ghost); font-style: normal; }
.lab-card__stars i { font-style: normal; }
.lab-card__stars i.is-on { color: var(--sun); }
.lab-card.is-played { background: #FBFDFF; }

/* A locked card is still legible — the title is the advertisement — but it
   is plainly not a thing to press. The padlock sits where the stars would,
   so the grid keeps its rhythm. */
.lab-card.is-locked { background: var(--mist); border-left-color: var(--ghost);
  color: var(--ink-soft); }
.lab-card.is-locked:hover { transform: none; box-shadow: none; }
.lab-card.is-locked .lab-card__title { color: var(--ink-soft); }
.lab-card__lock { margin-top: 5px; font-size: .95rem; opacity: .65; }

.lab-card.is-free { border-left-color: var(--teal); }
.lab-card__free { margin-top: 5px; align-self: flex-start; font-size: .66rem;
  text-transform: uppercase; letter-spacing: .07em; font-weight: 800;
  color: #0B7A6E; background: var(--teal-92); border-radius: 999px;
  padding: 3px 9px; }

.lab-head__join { align-self: center; font-weight: 700; white-space: nowrap; }

.lab-who { display: flex; align-items: center; gap: 8px; align-self: center; }
.lab-who__l { font-size: .84rem; color: var(--ink-soft); white-space: nowrap; }
.lab-who__s { font: inherit; font-size: .92rem; color: inherit; background: #fff;
  border: 2px solid var(--line); border-radius: 12px; padding: 8px 12px;
  min-height: 44px; }
.lab-who__s:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }

/* -------------------------------------------------------------- shell -- */
.lgl-play { display: flex; flex-direction: column; min-height: 70vh; }
.lgl-play__bar { display: flex; gap: 12px; align-items: center; margin-bottom: 10px; }
.lgl-play__title { flex: 1; min-width: 0; }
.lgl-play__title b { display: block; font-size: clamp(1.15rem, .9rem + 1vw, 1.6rem);
  line-height: 1.15; }
.lgl-play__title span { font-size: .8rem; color: var(--ink-soft); }
.lgl-round {
  width: 46px; height: 46px; flex: none; border-radius: 999px; border: 2px solid var(--ink);
  background: #fff; cursor: pointer; font-size: 1.1rem; line-height: 1;
  display: grid; place-items: center; box-shadow: 0 3px 0 var(--ink);
}
.lgl-round:active { transform: translateY(3px); box-shadow: none; }
.lgl-jar { display: flex; gap: 5px; align-items: center; background: var(--sun);
  border: 2px solid var(--ink); border-radius: 999px; padding: 6px 13px;
  box-shadow: 0 3px 0 var(--ink); flex: none; }
.lgl-jar__star { font-size: .95rem; }
.lgl-jar__n { font-size: 1.05rem; }

.lgl-play__say {
  background: #fff; border: 2px solid var(--ghost); border-radius: var(--r);
  padding: 13px 16px; margin: 0 0 12px; font-size: clamp(.98rem, .9rem + .4vw, 1.12rem);
  line-height: 1.45; min-height: 52px;
}
.lgl-play__say.is-note { border-color: var(--sun); background: #FFF8E6; }

.lgl-stage { flex: 1; background: var(--paper); border: 2px solid var(--ghost);
  border-radius: 22px; padding: clamp(12px, 2.5vw, 22px); position: relative; }

.lgl-play__foot { display: flex; gap: 10px; justify-content: flex-end; margin-top: 12px; }
.lgl-btn {
  border: 2px solid var(--ink); background: var(--coral); color: #fff;
  border-radius: 999px; padding: 12px 24px; font: inherit; font-weight: 700;
  cursor: pointer; box-shadow: 0 4px 0 var(--ink); min-height: 48px;
}
.lgl-btn:active { transform: translateY(4px); box-shadow: none; }
.lgl-btn--ghost { background: #fff; color: var(--ink); }

/* ------------------------------------------------------------- match -- */
.m-wrap { display: flex; flex-direction: column; gap: 8px; }
.m-heads { display: flex; justify-content: space-between; font-size: .7rem;
  font-weight: 700; letter-spacing: .09em; color: var(--ink-soft); padding: 0 6px; }
.m-board { position: relative; display: flex; justify-content: space-between;
  gap: clamp(30px, 12vw, 130px); }
.m-ink { position: absolute; inset: 0; pointer-events: none; }
.m-col { display: flex; flex-direction: column; gap: clamp(6px, 1.4vw, 14px);
  flex: 0 0 auto; }
.m-cell {
  display: flex; align-items: center; gap: 8px; background: #fff;
  border: 2px solid var(--ghost); border-radius: 14px; padding: 8px 12px;
  cursor: grab; font: inherit; min-height: 62px; min-width: 96px;
  transition: transform .12s ease, border-color .12s ease, background .2s ease;
  --pair: var(--teal);
}
.m-cell .lgl-i { width: clamp(34px, 6vw, 46px); height: clamp(34px, 6vw, 46px); flex: none; }
.m-lab { font-size: .78rem; color: var(--ink-soft); }
.m-word { font-family: "LGL Display", sans-serif; font-size: 1.05rem; }
.m-dots { display: grid; grid-template-columns: repeat(3, 9px); gap: 4px; }
.m-dots i { width: 9px; height: 9px; border-radius: 99px; background: var(--blue); }
.m-cell.is-holding { cursor: grabbing; border-color: var(--blue); transform: scale(1.04); }
.m-cell.is-target { border-color: var(--teal); background: #EEFAF8; transform: scale(1.06); }
.m-cell.is-done { border-color: var(--pair); background: #fff; cursor: default; }
.m-cell.is-done .m-lab { color: var(--pair); font-weight: 700; }
.m-cell.is-hinted { opacity: .72; }

/* ------------------------------------------------------------ circle -- */
.c-wrap { display: flex; flex-direction: column; gap: 12px; }
.c-letter { display: flex; gap: 8px; align-items: baseline; justify-content: center;
  background: #FFF1EE; border: 2px dashed #FFC9BC; border-radius: 14px; padding: 6px 18px;
  align-self: center; }
.c-letter b { font-family: "LGL Display", sans-serif; font-size: 2rem; color: var(--coral); }
.c-letter span { font-family: "LGL Display", sans-serif; font-size: 1.5rem; color: var(--coral); }
.c-want { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
.c-want__it { display: flex; gap: 5px; align-items: center; background: #fff;
  border: 2px solid var(--ghost); border-radius: 999px; padding: 5px 13px 5px 7px; }
.c-want__it .lgl-i { width: 26px; height: 26px; }
.c-want__it.is-done { border-color: var(--teal); background: #EEFAF8; opacity: .65; }
.c-board { position: relative; display: grid; gap: clamp(8px, 1.6vw, 16px);
  grid-template-columns: repeat(var(--cols, 4), 1fr); min-height: 260px; }
.c-board--rows { display: flex; flex-direction: column; gap: 12px; }
.c-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px;
  background: #fff; border: 2px solid var(--ghost); border-radius: 14px; padding: 8px; }
.c-board--scene { display: block; min-height: min(62vh, 440px); background: #fff;
  border: 2px solid var(--ghost); border-radius: 18px; }
.c-ink { position: absolute; inset: 0; touch-action: none; }
.c-tile { position: relative; display: flex; flex-direction: column; align-items: center;
  gap: 2px; padding: 8px 4px; border-radius: 12px; transition: transform .14s ease; }
.c-tile .lgl-i { width: clamp(42px, 8vw, 62px); height: clamp(42px, 8vw, 62px); }
.c-tile--free { position: absolute; padding: 0; }
.c-tile--free .lgl-i { width: clamp(34px, 6vw, 48px); height: clamp(34px, 6vw, 48px); }
.c-lab { font-size: .74rem; color: var(--ink-soft); }
.c-tile.is-found { background: #EEFAF8; }
.c-tile.is-found .c-lab { color: var(--teal); font-weight: 700; }
.c-tile.is-hinted { opacity: .7; }
.c-mark { position: absolute; top: 4px; right: 8px; width: 12px; height: 12px; }
.c-mark--star::before, .c-mark--star_dot::before, .c-mark--twostars::before {
  content: "★"; color: var(--sun); font-size: .8rem; }
.c-mark--dot::before, .c-mark--band_dot::before {
  content: "●"; color: var(--coral); font-size: .7rem; }
.c-mark--band::before { content: "▬"; color: var(--grape); font-size: .7rem; }
.c-mark--cap::before  { content: "▲"; color: var(--blue); font-size: .7rem; }
.c-mark--twostars::after { content: "★"; color: var(--sun); font-size: .8rem; margin-left: -2px; }

/* -------------------------------------------------------------- drag -- */
.d-wrap { display: flex; flex-direction: column; gap: 14px; }
.d-tray { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;
  background: var(--mist); border-radius: 16px; padding: 12px; min-height: 90px; }
.d-tile { display: flex; flex-direction: column; align-items: center; gap: 2px;
  background: #fff; border: 2px solid var(--ghost); border-radius: 14px;
  padding: 8px 10px; cursor: grab; touch-action: none; min-width: 66px;
  transition: transform .12s ease, opacity .2s ease; }
.d-tile .lgl-i { width: clamp(36px, 6vw, 50px); height: clamp(36px, 6vw, 50px); }
.d-tile__lab { font-size: .72rem; color: var(--ink-soft); }
.d-tile--num b { font-family: "LGL Display", sans-serif; font-size: 1.5rem; }
.d-tile.is-lifting { opacity: .25; }
.d-tile.is-used { opacity: 0; pointer-events: none; width: 0; min-width: 0;
  padding: 0; margin: -5px; border: 0; }
.d-ghost { position: fixed; z-index: 90; pointer-events: none; transform: scale(1.1) rotate(-3deg);
  box-shadow: 0 12px 26px rgba(38,49,63,.24); cursor: grabbing; }
.d-bins { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.d-bin { background: #fff; border: 3px dashed var(--line); border-radius: 18px;
  padding: 10px; min-height: 140px; transition: border-color .15s ease, background .15s ease; }
.d-bin__lab { display: block; text-align: center; font-size: .9rem; margin-bottom: 8px; }
.d-bin__in { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.d-bin.is-over { border-color: var(--teal); background: #EEFAF8; }
.d-line { display: flex; gap: 8px; align-items: center; justify-content: center;
  flex-wrap: wrap; }
.d-line__end { font-size: .7rem; text-transform: uppercase; letter-spacing: .08em;
  color: var(--ink-soft); }
.d-slot { display: grid; place-items: center; min-width: 74px; min-height: 74px;
  border: 3px dashed var(--line); border-radius: 14px; background: #fff;
  transition: border-color .15s ease, background .15s ease; }
.d-slot--sq { min-width: 58px; min-height: 58px; }
.d-slot.is-over { border-color: var(--teal); background: #EEFAF8; }
.d-slot.is-full { border-style: solid; border-color: var(--teal); }
.d-slot.is-hinted { opacity: .75; }
.d-slot__n { color: var(--ink-faint); font-size: .95rem; }
.d-rows { display: flex; flex-direction: column; gap: 10px; }
.d-row { display: flex; gap: 6px; align-items: center; flex-wrap: wrap;
  background: #fff; border: 2px solid var(--ghost); border-radius: 14px; padding: 8px; }
.d-row__icon .lgl-i { width: 34px; height: 34px; }
.d-cell { display: grid; place-items: center; min-width: 52px; min-height: 52px; }
.d-cell .lgl-i { width: 40px; height: 40px; }
.d-cell--num { font-family: "LGL Display", sans-serif; font-size: 1.3rem; }
.d-tile.is-set { border-color: var(--teal); background: #EEFAF8; cursor: default; }

/* ------------------------------------------------------------- trace -- */
.t-wrap { display: flex; flex-direction: column; gap: 10px; }
.t-lane { display: flex; gap: 10px; align-items: center; background: #fff;
  border: 2px solid var(--ghost); border-radius: 14px; padding: 6px 10px; }
.t-lane.is-done { border-color: var(--teal); background: #F6FEFD; }
.t-lane.is-hinted { opacity: .8; }
.t-end .lgl-i { width: 40px; height: 40px; }
.t-mid { position: relative; flex: 1; height: 78px; }
.t-mid--shape { height: 128px; }
.t-ghost { position: absolute; inset: 0; width: 100%; height: 100%; opacity: .12; }
/* width and height as well as inset, because a canvas is a replaced element:
   with `width: auto` it falls back to its intrinsic 300x150 rather than to
   its container, which is how an empty grey rectangle ends up hanging off the
   side of a phone whenever the container measures smaller than that. */
.t-ink { position: absolute; inset: 0; width: 100%; height: 100%;
  touch-action: none; cursor: crosshair; }
.t-name { font-size: .8rem; color: var(--ink-soft); min-width: 62px; }

/* Trace-and-copy: the lane stacks, so the drawing box is the full width of
   the lane and a fixed height.

   Both parts matter and both were missing. Turning the lane into a column
   makes its cross axis horizontal, and `align-items: center` above then sizes
   the box to its content — which is nothing, because the ghost picture and
   the canvas are both absolutely positioned. And `.t-mid` carries `flex: 1`,
   whose `flex-basis: 0` wins over the height once the lane is a column.

   The box therefore came out 0 x 0. The engine measures it before sizing its
   canvas and gives up when the width is zero, so the dotted picture was never
   drawn and the canvas sat at the browser's default 300x150 — an empty grey
   rectangle hanging off the side of a phone. */
.t-lane--shape { flex-direction: column; align-items: stretch; }
.t-lane--shape .t-mid--shape { flex: none; width: 100%; height: 128px; }
.t-lane--shape .t-name { text-align: center; }

/* -------------------------------------------------------------- maze -- */
.z-wrap { display: flex; flex-direction: column; gap: 10px; }
.z-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.z-end { display: flex; gap: 6px; align-items: center; font-size: .68rem;
  letter-spacing: .08em; color: var(--ink-soft); }
.z-end .lgl-i { width: 36px; height: 36px; }
.z-end--start b { color: var(--teal); }
.z-end--finish b { color: var(--coral); }
.z-got { background: var(--sun); border: 2px solid var(--ink); border-radius: 999px;
  padding: 4px 13px; font-size: .9rem; }
.z-board { position: relative; width: 100%; aspect-ratio: 1; max-height: 64vh;
  margin-inline: auto; }
.z-ink { position: absolute; inset: 0; touch-action: none; cursor: crosshair; }

/* --------------------------------------------------------------- tap -- */
.p-wrap { display: flex; flex-direction: column; gap: 14px; }
.p-scatter { position: relative; min-height: min(46vh, 330px); background: #fff;
  border: 2px solid var(--ghost); border-radius: 18px; }
.p-dot { position: absolute; border: 0; background: none; padding: 4px; cursor: pointer;
  border-radius: 12px; transition: transform .12s ease; }
.p-dot .lgl-i { width: clamp(30px, 5.4vw, 44px); height: clamp(30px, 5.4vw, 44px); }
.p-dot.is-marked { background: #EEFAF8; outline: 3px solid var(--teal); }
.p-dot.is-marked::after { content: "✓"; position: absolute; top: -4px; right: -4px;
  background: var(--teal); color: #fff; width: 18px; height: 18px; border-radius: 99px;
  font-size: .7rem; line-height: 18px; }
.p-asks { display: flex; flex-direction: column; gap: 8px; }
.p-ask { display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  background: #fff; border: 2px solid var(--ghost); border-radius: 14px; padding: 8px 10px; }
.p-ask.is-done { border-color: var(--teal); background: #F6FEFD; }
.p-ask__k { display: flex; gap: 6px; align-items: center; min-width: 140px; }
.p-ask__k .lgl-i { width: 32px; height: 32px; }
.p-ask__k b { font-size: .92rem; }
.p-pad { display: flex; gap: 6px; flex-wrap: wrap; }
.p-num, .p-opt {
  min-width: 48px; min-height: 48px; border: 2px solid var(--ghost); background: #fff;
  border-radius: 12px; font: inherit; font-family: "LGL Display", sans-serif;
  font-size: 1.15rem; cursor: pointer; padding: 6px 12px;
}
.p-num.is-right, .p-opt.is-right { border-color: var(--teal); background: #EEFAF8;
  color: var(--teal); }
.p-sums { display: flex; flex-direction: column; gap: 10px; }
.p-sum { display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  background: #fff; border: 2px solid var(--ghost); border-radius: 14px; padding: 8px 10px; }
.p-sum.is-done { border-color: var(--teal); background: #F6FEFD; }
.p-blob { display: flex; flex-wrap: wrap; gap: 2px; max-width: 148px; }
.p-blob .lgl-i { width: 26px; height: 26px; }
.p-op { font-family: "LGL Display", sans-serif; font-size: 1.3rem; color: var(--ink-soft); }
.p-study { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap;
  background: #fff; border: 2px solid var(--ghost); border-radius: 18px; padding: 20px;
  transition: opacity .5s ease, filter .5s ease; }
.p-study .lgl-i { width: clamp(44px, 8vw, 68px); height: clamp(44px, 8vw, 68px); }
.p-study.is-hidden { opacity: 0; filter: blur(18px); pointer-events: none; height: 0;
  padding: 0; margin: 0; border: 0; overflow: hidden; }
.p-timer { position: relative; height: 12px; background: var(--ghost); border-radius: 99px; }
.p-timer__bar { display: block; height: 100%; background: var(--sun); border-radius: 99px;
  transform-origin: left center; }
.p-timer__n { position: absolute; right: 8px; top: -22px; font-size: .9rem; color: var(--ink-soft); }
.p-q { background: #fff; border: 2px solid var(--ghost); border-radius: 16px; padding: 14px; }
.p-q__t { margin: 0 0 10px; font-size: 1.05rem; }
.p-q__opts { display: flex; gap: 8px; flex-wrap: wrap; }
.p-opt { display: flex; gap: 6px; align-items: center; font-size: .95rem;
  font-family: inherit; }
.p-opt .lgl-i { width: 32px; height: 32px; }

/* ----------------------------------------------------------- rewards -- */
.lgl-flystar { position: fixed; z-index: 120; pointer-events: none; font-size: 26px;
  color: var(--sun); text-shadow: 0 2px 0 rgba(38,49,63,.35);
  transition: transform 1s cubic-bezier(.3,-.2,.5,1), opacity 1s ease; }
.lgl-confetti { position: absolute; top: -12px; width: 9px; height: 15px;
  border-radius: 2px; opacity: .9; animation: lgl-fall 2.2s ease-in forwards; z-index: 2; }
@keyframes lgl-fall {
  to { transform: translateY(90vh) rotate(540deg); opacity: 0; }
}
.lgl-well { position: fixed; inset: 0; z-index: 110; background: rgba(38,49,63,.55);
  display: grid; place-items: center; padding: 16px; opacity: 0; transition: opacity .25s ease; }
.lgl-well.is-in { opacity: 1; }
.lgl-well__card { background: #fff; border-radius: 26px; padding: 26px 24px; text-align: center;
  max-width: 400px; width: 100%; box-shadow: 0 24px 60px rgba(38,49,63,.35);
  transform: scale(.92); transition: transform .35s cubic-bezier(.22,1.4,.4,1); }
.lgl-well.is-in .lgl-well__card { transform: scale(1); }
.lgl-well__char { width: 92px; height: 92px; }
.lgl-well__card h2 { margin: 4px 0 8px; font-size: 1.7rem; }
.lgl-well__stars { display: flex; gap: 8px; justify-content: center; margin: 6px 0 10px; }
.lgl-well__star { font-size: 2.1rem; color: var(--ghost); }
.lgl-well__star.is-on { color: var(--sun); animation: lgl-star .5s cubic-bezier(.22,1.6,.4,1) both; }
@keyframes lgl-star {
  from { transform: scale(0) rotate(-120deg); opacity: 0; }
  to   { transform: scale(1) rotate(0); opacity: 1; }
}
.lgl-well__note { margin: 0 0 4px; color: var(--ink-soft); }
.lgl-well__tiny { margin: 0 0 16px; font-size: .78rem; color: var(--ink-faint); }
.lgl-well__btns { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }

.is-pop { animation: lgl-pop .34s cubic-bezier(.22,1.5,.4,1); }
@keyframes lgl-pop { 0% { transform: scale(1); } 45% { transform: scale(1.16); }
  100% { transform: scale(1); } }
.is-shake { animation: lgl-shake .36s ease; }
@keyframes lgl-shake { 0%,100% { transform: translateX(0); }
  20% { transform: translateX(-6px); } 40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); } 80% { transform: translateX(4px); } }

/* ------------------------------------------------------------ slider -- */
/* Built into every screen size, but only a slider on a narrow one. On a
   laptop the track is an ordinary column and the arrows and dots are gone,
   so there is one layout to reason about rather than two. */

.lgl-slider__nav { display: none; }

@media (max-width: 640px) {

  .lgl-slider__track {
    display: flex;
    flex-direction: row;
    gap: 0;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* Vertical panning stays with the page, sideways panning with the track:
       a child sweeping a finger diagonally gets one or the other, never a
       fight between them. */
    touch-action: pan-x pan-y;
  }

  .lgl-slider__track::-webkit-scrollbar { display: none; }

  .lgl-slide {
    flex: 0 0 100%;
    max-width: 100%;
    scroll-snap-align: center;
    scroll-snap-stop: always;
  }

  .lgl-slider__nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    margin-top: 12px;
  }

  .lgl-slider.is-single .lgl-slider__nav { display: none; }

  .lgl-slider__arrow {
    width: 46px; height: 46px; flex: none;
    border-radius: 999px; border: 2px solid var(--ink); background: #fff;
    font-size: 1.5rem; line-height: 1; cursor: pointer;
    display: grid; place-items: center;
    box-shadow: 0 3px 0 var(--ink);
  }

  .lgl-slider__arrow:active { transform: translateY(3px); box-shadow: none; }

  /* Faded rather than gone: a control that disappears at the end of a track
     makes the other one jump sideways under a finger that is already moving. */
  .lgl-slider__arrow:disabled { opacity: .3; box-shadow: none; cursor: default; }

  .lgl-slider__dots { display: flex; gap: 8px; align-items: center; }

  .lgl-slider__dot {
    width: 12px; height: 12px; padding: 0; flex: none;
    border-radius: 999px; border: 2px solid var(--line); background: #fff;
    cursor: pointer;
  }

  .lgl-slider__dot.is-on { background: var(--ink); border-color: var(--ink); transform: scale(1.25); }
  .lgl-slider__dot.is-done { background: var(--teal); border-color: var(--teal); }

  /* A bigger invisible target than the dot itself — twelve pixels is a
     reasonable thing to look at and an unreasonable thing to hit. */
  .lgl-slider__dot::after {
    content: ""; display: block; position: relative;
    width: 34px; height: 34px; margin: -13px 0 0 -13px;
  }
}

/* ----------------------------------------------------------- mobile --- */
@media (max-width: 640px) {
  .lgl-lab { padding: 10px; }
  .lab-head { flex-wrap: wrap; }
  .m-board { gap: 18px; }
  .m-cell { min-width: 74px; padding: 6px 8px; }
  .m-lab { display: none; }
  .d-bins { grid-template-columns: 1fr; }
  .lgl-play__foot { justify-content: stretch; }
  .lgl-play__foot .lgl-btn { flex: 1; }
  .c-board { gap: 6px; }

  /* The pieces stay within reach.

     A drag activity is a set of rows and a tray of tiles underneath them. On
     a phone the rows fill the screen and the tray is below the fold, so
     picking up a tile scrolls the target out of sight and finding the target
     scrolls the tile out of sight. A child cannot do it at all.

     A slider would not help here — it would put the tile on one slide and the
     hole it belongs in on another. What helps is the tray never leaving: it
     sticks to the bottom of the screen and the rows scroll behind it. */
  .d-wrap .d-tray {
    position: sticky;
    bottom: 0;
    z-index: 6;
    margin: 0 -10px -10px;
    padding: 10px;
    background: rgba(255, 255, 255, .96);
    backdrop-filter: blur(6px);
    border-top: 2px solid var(--ghost);
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -6px 18px rgba(38, 49, 63, .07);
    /* Never more than about a third of the screen, so it can never be the
       thing that hides the row it is meant to fill. */
    max-height: 34vh;
    overflow-y: auto;
  }

  /* Which edge it sticks to follows where it sits in the activity, because
     two of the four drag layouts put the tray above the targets and two put
     it below. Pinning a tray to the bottom when it belongs at the top leaves
     it floating over the very bins it is meant to fill, and there is nowhere
     left to drop anything. `:first-child` says exactly what is meant — the
     pieces come before the places they go — without the engine having to
     tell the stylesheet anything. */
  .d-wrap .d-tray:first-child {
    top: 0;
    bottom: auto;
    margin: -10px -10px 0;
    border-top: 0;
    border-bottom: 2px solid var(--ghost);
    border-radius: 0 0 16px 16px;
    box-shadow: 0 6px 18px rgba(38, 49, 63, .07);
  }

  /* Enough room below the last row to scroll it clear of a tray pinned along
     the bottom. Without it the bottom row can never be brought out from
     under the tray, which would make the last few answers the hardest ones
     for no reason a child could possibly understand. */
  .d-wrap .d-rows { padding-bottom: 36vh; }
}

/* A page for children that moves less when the machine asks it to. */
@media (prefers-reduced-motion: reduce) {
  .lgl-lab *, .lgl-lab *::before, .lgl-lab *::after {
    animation-duration: .001s !important; transition-duration: .001s !important;
  }
  .lgl-confetti { display: none; }
}

/* ------------------------------------------------------ locked panel --- */
/* Shown when a child presses a card they cannot open. It covers the Lab
   rather than replacing it, so the way back is the obvious thing on screen
   and the activities are still visible behind. */
.lab-lock {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  background: rgba(38, 49, 63, .45);
  animation: lab-lock-in .16s ease-out;
}
.lab-lock__box {
  background: var(--paper); border: 2px solid var(--ink); border-radius: var(--r);
  box-shadow: 0 6px 0 var(--ink);
  padding: 22px 20px 20px; max-width: 26rem; width: 100%;
  text-align: center;
}
.lab-lock__pad { font-size: 2rem; line-height: 1; margin-bottom: 6px; }
.lab-lock__h { font-size: 1.4rem; margin: 0 0 6px; }
.lab-lock__which { margin: 0 0 10px; color: var(--ink-soft); font-size: .92rem; }
.lab-lock__say { margin: 0 0 10px; font-size: 1rem; line-height: 1.45; }
/* The sentence for the child, and the reason the buy button is not the
   loudest thing here. */
.lab-lock__ask { margin: 0 0 16px; color: var(--ink-soft); font-size: .86rem; }
/* Stacked, and reversed, on every size. The way out is the bottom button
   because the bottom of a panel is the easiest thing on a phone to press by
   accident, and the one that must never be pressed by accident is the one
   that spends money. "See the plans" is still the loud one; it is simply
   not the one under the thumb. */
.lab-lock__ways { display: flex; flex-direction: column-reverse; gap: 10px; }
.lab-lock__ways .lgl-btn { width: 100%; text-align: center; text-decoration: none;
  display: inline-flex; align-items: center; justify-content: center; }

@keyframes lab-lock-in { from { opacity: 0 } to { opacity: 1 } }
@media (prefers-reduced-motion: reduce) { .lab-lock { animation: none; } }

