/* ==========================================================================
   base.css — design tokens and every shared component.

   Everything in here is used by more than one page: the homepage, the game
   shell (header, stage, overlays) and the furniture the games stand on.
   A game's own layout lives in games/<game>/game.css; for the dress-up game
   that is the doll artwork, its animations and the studio's inner canvas.

   Two rules govern this file:
     1. no raw value in any rule that has a token;
     2. no colour literal outside :root — the theme files in shared/themes/
        redefine exactly the colour tokens below and nothing else.
   ========================================================================== */

:root{
  /* ---- Colour ------------------------------------------------------------
     A wooden toy shop: warm, desaturated chrome. Saturated colour is
     reserved for the toys themselves, so the toys stand out from the
     furniture. Nothing here is grey. */
  --cream:#fdf3e7;            /* page background — the wall of the room */
  --card:#fffdf9;             /* anything that lifts off the page */
  --wood:#f7e2c8;             /* shelf and tray surfaces — the furniture */
  --text:#a26b47;             /* all UI text and icon strokes */
  --text-soft:#7a5c40;        /* body copy in the parents panel */
  --accent:#e88bb4;           /* selection, the valance, primary highlight */
  --accent-deep:#d46a9a;      /* ledge under an accent surface, pressed state */
  --accent-tint:#fdeef5;      /* background of a selected card */

  /* A ledge is always a darker tint of the surface the object stands on —
     never black, never transparent. Hence two tokens: the same button needs
     a different ledge on cream than it does on wood. */
  --ledge-button:#e8d5c0;     /* under a --card button standing on --cream */
  --ledge-card:#e3cba9;       /* under a card standing on --wood */

  /* Exactly one confirm colour in the whole product (the studio's checkmark).
     Every theme repeats these three unchanged: if green stopped meaning
     "done" from one age group to the next, the one word the interface says
     without text would stop being reliable. */
  --go:#93c47d;
  --go-deep:#6d9c55;
  --go-text:#ffffff;

  /* The two thumb-corner buttons are the only gradients in the interface,
     because they have to read as "the fun ones". One illustration colour
     each, two stops, plus its own ledge. */
  --corner-left-1:#f5b8d4;
  --corner-left-2:#e88bb4;
  --corner-left-ledge:#c9639a;
  --corner-right-1:#ffd97a;
  --corner-right-2:#f5a25d;
  --corner-right-ledge:#d98a3f;

  --scrim:#00000055;          /* behind a modal floating over the game */

  /* Soft blobs painted on the wall so the background is never a flat fill. */
  --blob-1:#fbe3ee;
  --blob-2:#fdeccf;
  --blob-3:#e4f2e2;
  --blob-4:#e7ecf9;

  /* ---- Spacing — 4px grid ----------------------------------------------
     Every margin, padding and gap is one of these six. */
  --space-1:4px;
  --space-2:8px;
  --space-3:12px;
  --space-4:16px;
  --space-5:24px;
  --space-6:32px;

  /* ---- Radius ----------------------------------------------------------
     The bigger the object, the bigger the radius. Circles use --radius-pill
     rather than 50%, so a shape stays round when its box is not square. */
  --radius-xs:4px;            /* tiny artwork only, e.g. the flag swatch */
  --radius-sm:12px;
  --radius-md:20px;
  --radius-lg:26px;
  --radius-pill:999px;

  /* ---- Elevation — solid, never blurred -------------------------------- */
  --ledge-1:0 3px 0;          /* --tap buttons */
  --ledge-2:0 4px 0;          /* cards, big round buttons */
  --ledge-pressed:0 1px 0;    /* the :active counterpart of both */
  /* The only two blurred shadows in the product, both deliberate: a modal
     floats rather than rests, and the cabinet is a piece of furniture
     standing in front of the wall rather than an object lying on it. */
  --overlay-shadow:0 12px 40px #00000033;
  --surface-lift:0 -4px 14px #0000000d;

  /* ---- Motion ---------------------------------------------------------- */
  --press:.12s;
  --pop:.45s;
  --spin:.6s;

  /* ---- Touch ----------------------------------------------------------- */
  /* The doll's cheeks: young by default, toned down by the older themes. */
  --blush:#f5a09a;
  --blush-strength:.55;

  --tap:64px;                 /* the minimum for any target */
  --tap-lg:72px;              /* the two thumb-corner buttons */
  --tap-sm:44px;              /* adult-only controls — see #parents-button */

  /* The selected-state border. Always present and transparent until needed,
     so selecting a card never reflows the row it sits in. */
  --ring:4px;

  /* ---- Z-order — fixed and documented ---------------------------------
     studio 55 → parents 60 → rotate notice 70. The rotate notice has to sit
     above everything, including the parents panel: a phone held sideways
     must not be able to hide it behind another overlay. */
  --z-studio:55;
  --z-discard:56;             /* the "throw this away?" question: over the shelf
                                 and the studio, under the time-up screen, so a
                                 spent budget still wins */
  --z-won:57;                 /* the tick when a game is finished: over the game
                                 and over the discard question, under the
                                 time-up screen -- a spent budget still wins */
  --z-timeup:58;              /* over the studio, under the parents panel:
                                 a parent must be able to open the panel on top
                                 of it to grant more time */
  --z-parents:60;
  --z-rotate:70;
}

/* ==========================================================================
   Reset and document
   ========================================================================== */

*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}

html,body{height:100%;overflow:hidden;overscroll-behavior:none}

body{
  /* System fonts only. The CSP is default-src 'none' with font-src 'none',
     and the game has to work on a plane. */
  font-family:ui-rounded,"SF Pro Rounded","Segoe UI",system-ui,sans-serif;
  background:
    radial-gradient(circle at 15% 20%, var(--blob-1) 0 90px, transparent 91px),
    radial-gradient(circle at 85% 12%, var(--blob-2) 0 70px, transparent 71px),
    radial-gradient(circle at 90% 55%, var(--blob-3) 0 55px, transparent 56px),
    radial-gradient(circle at 8% 62%, var(--blob-4) 0 45px, transparent 46px),
    var(--cream);
  height:100vh;
  height:100dvh;              /* dvh where it exists; vh above as the fallback */
  display:flex;
  flex-direction:column;
  user-select:none;
  -webkit-user-select:none;
  -webkit-touch-callout:none;
  touch-action:manipulation;
}

/* The button rules below set display:flex, which would otherwise out-rank the
   browser's own [hidden] styling — and then the fullscreen button would stay
   visible on iPhone Safari, which has no Fullscreen API. A button that does
   nothing must not exist, so [hidden] wins here. */
[hidden]{display:none !important}

/* ==========================================================================
   Header — the shell's top bar, and the studio's own header
   ========================================================================== */

/* Symmetric vertical padding. This is where that rule came from: the header
   used to be padding:10px 16px 4px, which with align-items:center left 10px
   above the buttons and 4px below and tipped the whole bar upward. The studio
   header had the same fault (10px above, 0 below). */
header,
#studio-header{
  display:flex;
  align-items:center;
  padding:var(--space-3) var(--space-4);
}
#studio-header{justify-content:space-between}

h1{
  display:flex;align-items:center;gap:var(--space-2);
  font-size:1.3rem;color:var(--text);
  letter-spacing:.2px;font-weight:800;
}
/* Sized to the logo drawing's own proportions, not to the spacing grid. */
h1 .logo{width:30px;height:33px;flex:0 0 auto}

/* Parents button: deliberately small and dull — not a play button, no
   attractive nuisance. The reading gate is the second lock; this one is the
   first. It is the only control allowed under --tap, because it is aimed at
   an adult fingertip (--tap-sm is the platform minimum) and a child failing
   to notice it is the entire point. */
#parents-button{
  width:var(--tap-sm);height:var(--tap-sm);
  margin-left:var(--space-1);
  border:none;border-radius:var(--radius-sm);
  background:transparent;
  font-size:15px;
  opacity:.45;
  cursor:pointer;
}

/* The row of tool buttons, pushed to the trailing edge of the header.
   --space-3 is the closest two targets may sit: adjacent targets nearer than
   that get mis-hit by a small hand (the gap used to be 10px). */
.buttons{
  display:flex;
  gap:var(--space-3);
  margin-left:auto;
}

/* Three --tap buttons plus the parents button no longer fit beside the title
   on a phone. The interface is textless anyway, so the logo wins over the
   words — never shrink a target to make room. */
@media (max-width:520px){
  h1 #title-text{display:none}
}

/* ==========================================================================
   Buttons — three kinds, and no more

   Pressing any of them moves the object down onto its ledge. The travel
   always equals the ledge height minus the pressed height, otherwise the
   object looks like it sinks into the page instead of onto its shelf.
   ========================================================================== */

/* 1. Tool button — header and studio header. Never carries a text label.
   The :where() keeps these container fallbacks at element specificity, so the
   variants further down (confirm) still win without needing !important. */
.tool,
.tool-button,
:where(.buttons, #studio-header) button{
  width:var(--tap);height:var(--tap);
  border:none;border-radius:var(--radius-md);
  background:var(--card);
  box-shadow:var(--ledge-1) var(--ledge-button);
  font-size:28px;
  color:var(--text);
  cursor:pointer;
  display:flex;align-items:center;justify-content:center;
}
.tool:active,
.tool-button:active,
:where(.buttons, #studio-header) button:active{
  transform:translateY(2px);
  box-shadow:var(--ledge-pressed) var(--ledge-button);
}

#flag svg{
  /* 3:2, the proportion of both flags in the language pack. */
  width:32px;height:22px;
  border-radius:var(--radius-xs);
  pointer-events:none;
}

/* Fullscreen button: two icons inside one button. data-on decides which one
   you see, so the icon follows the real state — including when the user drops
   out of fullscreen with Escape or a system gesture instead of the button. */
#fullscreen svg{width:30px;height:30px;display:block;pointer-events:none}
#fullscreen .fs-close{display:none}
#fullscreen[data-on="yes"] .fs-open{display:none}
#fullscreen[data-on="yes"] .fs-close{display:block}

/* 2. Corner button — the two thumb corners over the stage. */
/* Selecteer op de class die game-shell.js echt zet ('corner corner-left' /
   'corner corner-right'), niet op een id. De shell noemt zijn knoppen
   <action>-button, juist omdat id="studio" al de atelier-overlay is; een
   selector op #surprise miste daardoor volledig en die knop kwam als 21x19px
   statisch onder de scene-SVG terecht. */
.corner{
  position:absolute;
  z-index:2;                  /* over the scene (0) and the doll (1) */
  /* Asymmetric on purpose: an object on a --ledge-2 carries visible weight
     along its bottom edge, so it needs a little more room underneath than
     beside it. It used to be 14px on both sides and sat visibly low. */
  bottom:var(--space-4);
  width:var(--tap-lg);height:var(--tap-lg);
  border:none;border-radius:var(--radius-pill);
  font-size:34px;
  cursor:pointer;
}
.corner:active{transform:translateY(3px) scale(.95)}

.corner-left{
  left:var(--space-3);
  background:linear-gradient(160deg,var(--corner-left-1),var(--corner-left-2));
  box-shadow:var(--ledge-2) var(--corner-left-ledge);
}
.corner-left:active{box-shadow:var(--ledge-pressed) var(--corner-left-ledge)}

.corner-right{
  right:var(--space-3);
  background:linear-gradient(160deg,var(--corner-right-1),var(--corner-right-2));
  box-shadow:var(--ledge-2) var(--corner-right-ledge);
}
.corner-right:active{box-shadow:var(--ledge-pressed) var(--corner-right-ledge)}

/* The TOP corners of the stage: for what belongs to the game but is not play.
   Deliberately the quiet tool geometry instead of the big round thumb buttons --
   sharing is something a grown-up reaches over to do, and it must not compete
   with the two things a child is meant to press. Still a full --tap target: not
   competing is about weight, never about being harder to hit. */
.corner-top{
  top:var(--space-3);bottom:auto;
  width:var(--tap);height:var(--tap);
  border-radius:var(--radius-md);
  font-size:26px;
  background:var(--card);
  box-shadow:var(--ledge-1) var(--ledge-button);
}
.corner-top:active{
  transform:translateY(2px);   /* the tool press, not the springy thumb-button one */
  box-shadow:var(--ledge-pressed) var(--ledge-button);
}
.corner-top-left{left:var(--space-3)}
.corner-top-right{right:var(--space-3)}

/* 3. Confirm button — the studio's checkmark, and nothing else in the whole
   product. Keeps the tool button's geometry, swaps in the confirm colour. */
.confirm-button,
#studio-done{
  background:var(--go);
  color:var(--go-text);
  box-shadow:var(--ledge-2) var(--go-deep);
}
.confirm-button:active,
#studio-done:active{
  transform:translateY(3px);
  box-shadow:var(--ledge-pressed) var(--go-deep);
}

/* ==========================================================================
   Stage — the play area the shell hands to the game
   ========================================================================== */

#stage{
  flex:1;
  display:flex;
  align-items:center;justify-content:center;
  min-height:0;
  /* No horizontal padding: the scene behind the doll is painted edge to edge.
     Vertically it used to be 4px above and 8px below. */
  padding:var(--space-2) 0;
  position:relative;          /* the corner buttons anchor to this */
}

/* ==========================================================================
   Cards — garments, scenes, patterns, games, age groups
   ========================================================================== */

.card,
.category,
.swatch,
.base-card{
  border:var(--ring) solid transparent;
  background:var(--card);
  cursor:pointer;
  transition:transform var(--press);
}

.card{
  flex:0 0 auto;
  /* The shelf-card box. Both numbers sit on the 4px grid; the height used to
     be 118px, which did not. */
  width:96px;height:120px;
  border-radius:var(--radius-md);
  box-shadow:var(--ledge-2) var(--ledge-card);
  padding:var(--space-2);
  position:relative;          /* anchors the star on own creations */
}
.card svg{width:100%;height:100%;pointer-events:none}
.card:active{transform:scale(.94)}

/* Selection is colour and border, never a checkmark: a four-year-old reads
   the highlight, not the symbol. The ledge switches to the accent as well, so
   a selected card reads as one solid object rather than a card with a hat on. */
.card.on{
  border-color:var(--accent);
  background:var(--accent-tint);
  box-shadow:var(--ledge-2) var(--accent-deep);
}

/* Own creations get a little star on the card, and nothing else. */
.card.own::after{
  content:"⭐";
  position:absolute;top:var(--space-1);right:var(--space-1);
  font-size:15px;
}

.category{
  flex:0 0 auto;
  width:var(--tap);height:var(--tap);
  border-radius:var(--radius-pill);
  box-shadow:var(--ledge-1) var(--ledge-card);
  padding:var(--space-2);
}
.category svg{width:100%;height:100%;pointer-events:none}
.category:active{transform:scale(.94)}
.category.active{border-color:var(--accent);background:var(--accent-tint)}

.swatch{
  width:var(--tap);height:var(--tap);
  /* The ring is card-coloured, not accent: it separates the pattern inside
     from the wood behind without competing with the selected state. */
  border-color:var(--card);
  border-radius:var(--radius-pill);
  box-shadow:var(--ledge-1) var(--ledge-card);
  overflow:hidden;
}
.swatch svg{width:100%;height:100%;display:block;pointer-events:none}
.swatch:active{transform:scale(.92)}
/* The chosen colour is marked by its ring turning dark and a second ring OUTSIDE the box
   -- a box-shadow, which takes no layout space. It used to grow by scale(1.1), which put
   3px of a --tap swatch over the 12px gap its neighbour is entitled to; designtest
   measures neighbours in a row and says so. A selection marker may not change the size of
   the thing it marks. */
.swatch.on{
  border-color:var(--accent-deep);
  box-shadow:var(--ledge-1) var(--ledge-card), 0 0 0 3px var(--accent-deep);
}

.base-card{
  border-radius:var(--radius-md);
  box-shadow:var(--ledge-2) var(--ledge-card);
  padding:var(--space-3);
  min-height:0;
}
.base-card svg{width:100%;height:100%}
.base-card:active{transform:scale(.96)}

/* ==========================================================================
   Rows of cards — shelf, categories, tray

   One gap token on the row axis. The scrollbar is hidden: a child scrolls by
   dragging, and a visible bar is one more thing to poke at.
   ========================================================================== */

.card-row,
#shelf,
#categories{
  display:flex;
  gap:var(--space-3);
  overflow-x:auto;
  scrollbar-width:none;
}
.card-row::-webkit-scrollbar,
#shelf::-webkit-scrollbar,
#categories::-webkit-scrollbar,
#studio-tray::-webkit-scrollbar{display:none}

/* ...except on a machine with a mouse. Hiding the bar was reasoned about a
   finger: you drag the row and a bar is one more thing to poke at. A mouse
   cannot drag it and has no sideways wheel, so with the bar hidden as well the
   far end of the row is simply unreachable. shared/rows.js turns a vertical
   wheel into sideways movement; this puts back the hint that there IS more.
   Slim, and in the ledge colour of the surface it lies on, so it reads as part
   of the furniture rather than as browser chrome. */
@media (hover:hover) and (pointer:fine){
  .card-row,
  #shelf,
  #categories,
  #studio-tray{
    scrollbar-width:thin;
    scrollbar-color:var(--ledge-card) transparent;
  }
  .card-row::-webkit-scrollbar,
  #shelf::-webkit-scrollbar,
  #categories::-webkit-scrollbar,
  #studio-tray::-webkit-scrollbar{display:block;height:8px}
  .card-row::-webkit-scrollbar-track,
  #shelf::-webkit-scrollbar-track,
  #categories::-webkit-scrollbar-track,
  #studio-tray::-webkit-scrollbar-track{background:transparent}
  .card-row::-webkit-scrollbar-thumb,
  #shelf::-webkit-scrollbar-thumb,
  #categories::-webkit-scrollbar-thumb,
  #studio-tray::-webkit-scrollbar-thumb{
    background:var(--ledge-card);
    border-radius:var(--radius-sm);
  }
}

/* Centre while the row fits, scroll as soon as it no longer does. */
.card-row>:first-child,
#shelf>:first-child,
#categories>:first-child{margin-inline-start:auto}
.card-row>:last-child,
#shelf>:last-child,
#categories>:last-child{margin-inline-end:auto}

#shelf{padding:var(--space-3) var(--space-4)}

/* Asymmetric on purpose: the shelf above already contributes --space-3 of
   separation, and repeating it here would push the stage up for nothing. The
   bottom picks up the home-indicator inset, because this row sits exactly
   where an iPhone draws it. */
#categories{padding:0 var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom))}

/* ==========================================================================
   Surfaces — the furniture
   ========================================================================== */

/* Wood, rounded along the top only: a surface stands on the bottom edge of
   the screen, so its lower corners have nothing to round off against. */
.surface,
#cabinet,
#studio-tray{
  background:var(--wood);
  border-radius:var(--radius-lg) var(--radius-lg) 0 0;
}

#cabinet{
  box-shadow:var(--surface-lift);
  position:relative;          /* the valance is painted on this box */
  /* Asymmetric on purpose: top only. Clearance for the valance bar
     (--space-3 tall) plus --space-1, so the scalloped fringe never touches a
     card. The rows inside carry their own bottom padding, safe-area included. */
  padding-top:calc(var(--space-3) + var(--space-1));
}

/* The puppet-theatre valance: an accent bar with a scalloped fringe, like a
   little toy shop. It is the one decorative flourish in the product, and it
   works precisely because it is the only one — do not add a second elsewhere. */
#cabinet::before{
  content:"";
  position:absolute;top:0;left:0;right:0;
  height:var(--space-3);
  background:var(--accent);
  border-radius:var(--radius-lg) var(--radius-lg) 0 0;
}
#cabinet::after{
  content:"";
  position:absolute;
  /* Overlaps the bar above by 1px. Without that overlap a hairline of wood
     shows through between bar and fringe at fractional device pixel ratios. */
  top:calc(var(--space-3) - 1px);
  left:var(--space-4);right:var(--space-4);
  /* 20x10 tile with a 9px circle: scallop geometry, not spacing. */
  height:10px;
  background:radial-gradient(circle at 10px 0,var(--accent) 0 9px,transparent 10px) top left/20px 10px repeat-x;
  pointer-events:none;
}

/* The three chips above the studio tray (paint, patterns, stickers). Deliberately the
   same row of pills as #categories above the shelf: it is the one navigation idea in the
   product and a child who has used the shelf has already learnt it. Centred, because
   three chips never overflow -- the shelf's categories can. */
#studio-kinds{
  display:flex;
  justify-content:center;
  gap:var(--space-3);
  padding:var(--space-2) var(--space-4);
}
#studio-kinds:empty{display:none}

#studio-tray{
  /* Two rows: patterns and stickers both turn up on this second screen. */
  display:grid;
  grid-auto-flow:column;
  grid-template-rows:var(--tap) var(--tap);
  gap:var(--space-3);
  overflow-x:auto;
  scrollbar-width:none;
  /* Asymmetric on purpose: the bottom adds the home-indicator inset. The
     centre-while-it-fits trick from the flex rows is left out here — auto
     margins do not centre grid tracks, and justify-content:center would make
     the leading swatches unreachable once the row overflows. */
  padding:var(--space-3) var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom));
}

/* ==========================================================================
   Overlays — parents panel, studio, rotate notice
   ========================================================================== */

.overlay,
#parents{
  position:fixed;inset:0;
  display:none;               /* the shell flips this to flex */
  align-items:center;justify-content:center;
  background:var(--scrim);
  /* --space-4 rather than --space-5: the panel is max-width 440px and 100%
     wide below that, so on a small phone every pixel here is one the text
     loses. */
  padding:var(--space-4);
}
#parents{z-index:var(--z-parents)}

.overlay-panel,
#parents-content{
  background:var(--card);
  border-radius:var(--radius-lg);
  padding:var(--space-5);
  max-width:440px;width:100%;
  max-height:85vh;max-height:85dvh;   /* dvh where it exists, vh as fallback */
  overflow-y:auto;
  box-shadow:var(--overlay-shadow);
}

#parents-content h2{color:var(--text);margin-bottom:var(--space-3)}
/* Asymmetric on purpose: a heading belongs to the paragraph beneath it, so it
   keeps more air above than below. */
#parents-content h3{color:var(--text);margin:var(--space-4) 0 var(--space-2);font-size:1rem}
#parents-content p{color:var(--text-soft);line-height:1.5;margin-bottom:var(--space-3);font-size:.95rem}

/* Asymmetric on purpose: the left margin is the list indent, not spacing
   around the block. */
.offline-steps{
  margin:0 0 var(--space-3) var(--space-5);
  color:var(--text-soft);line-height:1.6;font-size:.95rem;
}

.gate-question{font-size:1.1rem}
.gate-numbers{display:flex;gap:var(--space-3);justify-content:center;padding:var(--space-2) 0}
.gate-number{
  /* On the grid and comfortably over --tap: the gate is answered by an adult
     under time pressure from a child pulling at their arm. */
  width:84px;height:84px;
  font-size:1.6rem;font-weight:700;color:var(--text);
  border:none;border-radius:var(--radius-md);
  background:var(--wood);
  box-shadow:var(--ledge-2) var(--ledge-card);
  cursor:pointer;
}
.gate-number:active{transform:translateY(3px);box-shadow:var(--ledge-pressed) var(--ledge-card)}

.panel-buttons{display:flex;gap:var(--space-3);flex-wrap:wrap;margin-top:var(--space-2)}
.panel-buttons button{
  flex:1;
  min-height:var(--tap);
  border:none;border-radius:var(--radius-md);
  background:var(--wood);
  box-shadow:var(--ledge-1) var(--ledge-card);
  cursor:pointer;
  font-size:1rem;color:var(--text);
  padding:var(--space-2) var(--space-3);
}
.panel-buttons button:active{transform:translateY(2px);box-shadow:var(--ledge-pressed) var(--ledge-card)}

#rotate-notice{
  position:fixed;inset:0;
  display:none;
  align-items:center;justify-content:center;
  flex-direction:column;gap:var(--space-3);
  background:var(--cream);
  z-index:var(--z-rotate);    /* over every overlay, studio and gate included */
}
#rotate-notice span{font-size:64px}
#rotate-notice p{font-size:1rem;color:var(--text)}

@media (orientation:landscape) and (max-height:520px){
  #rotate-notice{display:flex}
}

/* ==========================================================================
   Homepage — age-group picker and game grid

   Built from the same components: every tile is a .card. The body is locked
   against scrolling for the games, so the homepage scrolls inside .page.
   ========================================================================== */

.page{
  flex:1;
  min-height:0;
  overflow-y:auto;
  display:flex;
  flex-direction:column;
  gap:var(--space-5);
  padding:var(--space-4) var(--space-4) calc(var(--space-5) + env(safe-area-inset-bottom));
}

/* Parent-facing: the child navigates by the drawings. */
.page-title{
  color:var(--text);
  font-size:1.1rem;font-weight:700;
  text-align:center;
}

.card-grid{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(120px,1fr));
  gap:var(--space-3);
  width:100%;max-width:440px;
  margin-inline:auto;
}
/* In the grid a card is square and sized by its cell rather than by the fixed
   shelf-card box, and it stacks its drawing over its caption. */
.card-grid .card{
  width:auto;height:auto;
  aspect-ratio:1;
  display:flex;flex-direction:column;align-items:center;
  gap:var(--space-1);
}
.card-grid .card svg{flex:1;min-height:0}

/* The numerals under an age-group tile: small, for the parent. A three-year-old
   cannot read "3-6", which is why the drawing above carries the meaning. */
.card-caption{color:var(--text-soft);font-size:.8rem}

/* "Play without ads" is a promise to the parent, not a brand for the child:
   it appears here and in the parents panel, nowhere else. */
.brand{
  margin-top:auto;
  color:var(--text-soft);
  font-size:.85rem;
  text-align:center;
}

/* ==========================================================================
   Reduced motion — one blanket rule, deliberately absolute
   ========================================================================== */

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none !important;transition:none !important}
}

/* On a 320px phone the header needs 361px: five controls at --tap with --space-3
   between them simply do not fit. DESIGN-PROTOCOL rule 4 says never shrink a
   target to make room — hide the least important thing instead. So the game's
   logo drawing goes (the title text is already hidden below 520px), and with it
   the full-screen button: it is a convenience, iPhone Safari has no Fullscreen
   API anyway, and the game plays identically without it. Everything a child
   needs to play and to get home stays at 64px. */
@media (max-width:360px){
  h1 .logo{display:none}
  #fullscreen{display:none}
}


/* ---- Parental choice rows -------------------------------------------------
   The age toggles and the play-time budget. These were falling through to the
   browser's own button: 19px tall, grey and square-cornered — grey is forbidden
   outright by DESIGN-PROTOCOL, and 19px is too small even for an adult thumb.
   Adult-only controls, so --tap-sm rather than --tap. */
.choice-row,
.ages-list{
  display:flex;flex-wrap:wrap;
  gap:var(--space-2);
  margin-bottom:var(--space-3);
}
.choice,
.age-toggle{
  min-height:var(--tap-sm);
  padding:0 var(--space-4);
  border:var(--ring) solid transparent;
  border-radius:var(--radius-pill);
  background:var(--wood);
  box-shadow:var(--ledge-1) var(--ledge-card);
  color:var(--text);
  font:inherit;
  cursor:pointer;
}
.choice:active,
.age-toggle:active{transform:translateY(2px);box-shadow:var(--ledge-pressed) var(--ledge-card)}
/* Selected reads exactly like a chosen card: accent border, tinted fill, and the
   ledge switches to the accent so it is one solid object. */
.choice.on,
.age-toggle.on{
  border-color:var(--accent);
  background:var(--accent-tint);
  box-shadow:var(--ledge-1) var(--accent-deep);
}
.choice:disabled,
.age-toggle:disabled,
.panel-buttons button:disabled{opacity:.45;box-shadow:none;cursor:default}

/* The honest small print under a parental control. It follows a row of buttons,
   which carry their own visual weight, so it needs air above it. */
.panel-note{color:var(--text-soft);font-size:.85rem;margin-top:var(--space-3)}

/* ==========================================================================
   The studio -- shared

   Moved here when a second game started using it. The markup, the behaviour and
   now the styling are one thing: leaving the styling behind meant the car studio
   opened with its studio ALREADY on screen, because the `display:none` that keeps
   it shut lived in the other game's stylesheet.

   A full screen of its own rather than a modal: the child is making something
   here, so nothing of the game behind it should show through. Its header, its
   tray and its cards are the shared components; the canvas in the middle is
   what this game adds.
   ========================================================================== */

#studio{
  position:fixed;inset:0;
  display:none;               /* studio.js flips this to flex */
  flex-direction:column;
  background:var(--cream);
  z-index:var(--z-studio);    /* under the parents panel and the rotate notice */
}

#studio-stage{
  flex:1;
  display:flex;
  align-items:center;justify-content:center;
  min-height:0;               /* a flex child may shrink below its content */
  padding:var(--space-3);
}
/* The garment is cropped art: it may use all the height it can get, but stays
   clear of the sides for the same reason the doll does. */
#studio-stage svg{height:100%;max-height:100%;max-width:92vw}

/* The preview needs the full WIDTH as well. studio.js sets width/height
   attributes from the thumb crop because Safari gives an attribute-less svg a
   width of 0 inside a flex container — but those attributes then also decided
   the box width, so preserveAspectRatio="meet" scaled the artwork down to it and
   every base rendered at 1:1. The boots showed up 190px tall on a 624px stage:
   far too small a target for a four-year-old. Two ids, to outrank the rule
   above without touching the base-picker cards. */
#studio-stage #studio-preview{width:100%}

/* The whole preview is the tap target — tap a spot on the garment and it takes
   the colour, pattern or sticker that is selected in the tray. Which paths
   actually catch a tap is decided in studio.js, because only the recolourable
   zones and the stickers may. */
#studio-preview{cursor:pointer}

/* The base silhouettes to choose from, two per row, so they all fit on screen
   without scrolling — checked down to 320px. The width is capped by the artwork
   rather than by the spacing scale: beyond ~420px the silhouettes stop growing
   and only the gaps would. */
#base-grid{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:var(--space-3);         /* the same gap as every other row of cards */
  width:min(420px,88vw);
  height:100%;max-height:520px;
}
/* An odd number of bases leaves the last one alone in a corner. Centre it, at
   the same width as the others, so the grid reads as a deliberate shape instead
   of a gap. */
#base-grid .base-card:last-child:nth-child(odd){
  grid-column:1 / -1;
  width:calc(50% - var(--space-3) / 2);
  justify-self:center;
}

/* ---- Throwing one thing away -- shared --------------------------------------------
   Reached by holding something the child made on the shelf. Shared, because the
   car studio asks the same question about a painted car, in the same words -- of
   which there are none. Same language as the
   time-up screen: solid --cream rather than a dark scrim, because nothing here
   is a punishment, and no words, because the audience cannot read them.

   The design is shown large so a child can see exactly which one is at stake,
   and the two answers stand on their own: back, or the bin. */
#discard{
  position:fixed;inset:0;
  z-index:var(--z-discard);
  display:flex;flex-direction:column;
  align-items:center;justify-content:center;
  gap:var(--space-5);
  background:var(--cream);
  padding:var(--space-4);
}
#discard .discard-card{
  width:min(52vw,240px);
  aspect-ratio:1;
  display:flex;align-items:center;justify-content:center;
  background:var(--card);
  border-radius:var(--radius-lg);
  box-shadow:var(--ledge-2) var(--ledge-card);
  padding:var(--space-4);
}
#discard .discard-card svg{width:100%;height:100%}
#discard .discard-choices{
  display:flex;
  gap:var(--space-6);
}
/* Both answers are full --tap targets, and the bin is not made louder than the
   way back: the safe answer must never be the harder one to hit. */
#discard .discard-choices button{
  width:var(--tap);height:var(--tap);
}

/* ---- Finished -------------------------------------------------------------
   A game that can be won says so here. Solid --cream and not a dark scrim, the
   same reasoning as the play-time screen below: finishing is not a failure and a
   black veil reads as one. No words -- a tick, and the two things a child might
   want next. */
/* The doll's cheeks. Two pink circles are most of what says "toddler", and a
   nine-year-old notices that before anything else, so a theme may tone them down
   through the two tokens above. The drawing carries the young values as plain
   attributes, so a browser that does not understand a variable in a presentation
   attribute still gets cheeks rather than two black circles; this rule is what a theme
   overrides, and a CSS property beats an attribute. */
.blush{fill:var(--blush);opacity:var(--blush-strength)}

/* ==========================================================================
   The counter

   From the second age group upwards a game that can be won counts what it took
   (shared/count.js decides who counts and what). This is a READOUT and not a
   control: no --tap floor, because nothing is pressed here, and pointer-events
   off, so a card that ends up under it stays as tappable as it was.

   It sits first on the tray, the row a child already looks at to choose things.
   Over the stage is where it started, and that was wrong: the corner of the stage
   is a card in memory and a picture in spot the differences, so the readout ended
   up on top of the very thing it was counting. On the tray it has its own space --
   and the tray may wrap, because at 320px the score and three choices and a button
   do not fit on one line. Wrapping costs the board a little height; the cards are
   measured after it and stay at --tap.
   ========================================================================== */
/* Its own line, above the choices, at every width. Sharing the line only works on a
   wide screen: at 320px the score plus three choices plus a button is one item too many,
   and letting it wrap by itself made three ragged rows out of one tidy one. */
/* A tighter gap between the choices while the score is there, so the choices and the
   new-round button still share ONE line at 320px. Left at --space-5 they wrapped as
   well, and three rows of tray took 204px of a 568px screen away from the board. */
/* A tighter gap and a narrower side padding while the score is there, so the choices
   and the new-round button still share ONE line at 320px: three 64px choices plus their
   own two gaps is 216, the button is 64, and with the ordinary 16px sides that came to
   292 in 288 -- four pixels short, which turned the tray into three rows and took 196px
   of a 568px screen away from the board. */
#tray.counting{
  flex-wrap:wrap;
  gap:var(--space-2) var(--space-3);
  padding-left:var(--space-2);padding-right:var(--space-2);
}

/* On a phone the score takes its own line above the choices. Left to wrap by itself it
   made the new-round button sit alone on a line of its own, which reads as something
   having gone wrong rather than as a row. Above 430px there is room for all of it side
   by side, and a full-width pill with one small number in the middle of a tablet is a
   lot of pill for very little number. */
@media (max-width:430px){
  #tray.counting #count{flex:1 0 100%;justify-content:center}
}
#count{
  display:flex;align-items:center;gap:var(--space-3);
  padding:var(--space-1) var(--space-3);
  border-radius:var(--radius-md);
  background:var(--card);
  box-shadow:var(--ledge-1) var(--ledge-card);
  color:var(--text-soft);
  font-size:1.1rem;font-weight:800;
  /* Tabular figures, or the number jiggles sideways every time a digit changes and
     the corner of the screen starts twitching while a child is trying to look. */
  font-variant-numeric:tabular-nums;
  pointer-events:none;
}
#count span{display:flex;align-items:center;gap:var(--space-1)}
#count svg{width:20px;height:20px;flex:0 0 auto}
#count .count-best{opacity:.7}
/* A flex child ignores the hidden attribute, and the best is hidden until there is
   one to beat. */
#count [hidden]{display:none}

#won{
  position:fixed;inset:0;
  z-index:var(--z-won);
  display:flex;flex-direction:column;
  align-items:center;justify-content:center;
  gap:var(--space-6);
  background:var(--cream);
  padding:var(--space-4);
}
#won .won-tick{
  width:min(44vw,180px);height:auto;
  animation:pop .45s ease;
}
#won .won-choices{
  display:flex;
  gap:var(--space-6);
}

/* What it took, under the tick: the score, then either a star on its own for a new
   best or the star with the best that still stands beside it. */
#won .won-count{
  display:flex;align-items:center;gap:var(--space-3);
  margin:0;
  font-size:1.6rem;font-weight:800;
  color:var(--text);
  font-variant-numeric:tabular-nums;
}
#won .won-count svg{width:28px;height:28px;flex:0 0 auto;color:var(--text-soft)}
#won .won-count.record svg:last-of-type{color:var(--go);width:34px;height:34px}
#won .won-count span{color:var(--text-soft);font-weight:700}
/* The same big round buttons as over the stage, so "again" is the shape a child
   already presses for "again". Reversed in source order so the likely answer sits
   under the thumb on the right. */
#won .won-choices .corner{
  position:static;
  bottom:auto;
}
@keyframes pop{
  0%{transform:scale(.6);opacity:0}
  60%{transform:scale(1.06);opacity:1}
  100%{transform:scale(1);opacity:1}
}

/* ---- Play time is over ---------------------------------------------------
   Solid --cream and not a dark scrim: the game must be gone, but nothing here is
   a punishment and a black veil would read as one. No words either — the child
   cannot read them. A moon and three stars say "finished for now". */
#time-up{
  position:fixed;inset:0;
  z-index:var(--z-timeup);
  display:flex;
  align-items:center;justify-content:center;
  background:var(--cream);
  padding:var(--space-4);
}
#time-up .time-up-art{
  width:min(60vw,260px);height:auto;
  animation:float 4s ease-in-out infinite;
}
/* The only way back in: a parent granting more time. Same tool button as
   everywhere else, in the corner the parents button already lives in. */
#time-up #time-up-parents{
  position:absolute;
  top:var(--space-3);left:var(--space-4);
  opacity:.45;
  background:transparent;
  box-shadow:none;
  font-size:15px;
  width:var(--tap-sm);height:var(--tap-sm);
}
@keyframes float{
  0%,100%{transform:translateY(0)}
  50%{transform:translateY(-10px)}
}
