/* Zovanu playground. Tokens, buttons and the modal come from ../css/style.css */

.pg{
  margin:0;
  height:100svh;
  overflow:hidden;
  background:var(--bg);
  position:relative;
}

/* ── stage fills the window; every control floats over it ─────────── */
.pg__stage{position:fixed;inset:0;z-index:0}
#stage{
  display:block;width:100%;height:100%;
  touch-action:none;
  cursor:grab;
  user-select:none;-webkit-user-select:none;
}
#stage:active{cursor:grabbing}

/* ── load screen ──────────────────────────────────────────────────── */
.pgload{
  position:fixed;inset:0;z-index:60;
  display:grid;place-items:center;
  background:var(--bg);
  transition:opacity .7s var(--ease);
}
.pgload::before{
  content:"";position:absolute;inset:0 0 auto 0;height:46vh;
  background:linear-gradient(to bottom,#E8E6FA,transparent);
  animation:glow-breathe 11s ease-in-out infinite;
}
.is-ready .pgload{opacity:0;pointer-events:none}
.pgload__inner{
  position:relative;
  display:flex;flex-direction:column;align-items:center;gap:40px;
  width:min(300px,72vw);
}
/* The bar and the line naming what it is loading are one unit, held closer
   to each other than to the mark above them. */
.pgload__meter{
  display:flex;flex-direction:column;align-items:center;gap:20px;
  width:100%;
}
/* The burst from the homepage lands on this exact colour, so the loader
   should feel like it is assembling on the same surface rather than being
   swapped in.

   Both animations here drive opacity, and when two do that the later one in
   the list wins while it is running. The breathing loop is deliberately left
   with no fill-mode, so during its delay it contributes nothing and the
   entrance fade owns the property outright; the loop then starts on
   opacity:1, exactly where the fade left off, so the handover is invisible. */
.pgload__mark{
  width:66px;height:66px;
  animation:pgload-fade .5s var(--ease-out) both,
            pgload-breathe 2.8s ease-in-out .5s infinite;
}
@keyframes pgload-breathe{
  0%,100%{opacity:1}
  50%    {opacity:.3}
}
@keyframes pgload-fade{ from{opacity:0} to{opacity:1} }
@keyframes pgload-rise{
  from{opacity:0;transform:translateY(12px)}
  to{opacity:1;transform:none}
}
.pgload__bar{animation:pgload-rise .5s var(--ease-out) .14s both}
.pgload__label{animation:pgload-rise .5s var(--ease-out) .22s both}
.pgload__pct{animation:pgload-rise .5s var(--ease-out) .3s both}
.pgload::before{animation:glow-breathe 11s ease-in-out infinite,
                pgload-fade .8s var(--ease-out) both}
.pgload__label{color:var(--ink-55)}
.pgload.is-done{opacity:0;pointer-events:none}

/* ── name card, over the live scene ──────────────────────────────── */
.pgname{
  position:fixed;inset:0;z-index:50;
  display:grid;place-items:center;
  background:rgba(18,17,24,.44);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  opacity:0;transition:opacity .38s var(--ease);
}
.pgname.is-on{opacity:1}
.pgname__card{
  --card-pad:26px;
  width:min(500px,88vw);padding:28px var(--card-pad) 24px;
  /* full-bleed rows sit exactly on the padding box, so any sideways
     travel here is sub-pixel rounding, never content worth reaching */
  max-height:92svh;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;
  background:#fff;border-radius:24px;text-align:center;
  display:flex;flex-direction:column;align-items:center;gap:20px;
  box-shadow:0 40px 90px -40px rgba(18,17,24,.6);
  transform:translateY(16px) scale(.97);
  transition:transform .44s var(--ease-out);
}
.pgname.is-on .pgname__card{transform:none}
/* head: title with its line 12px under it, as one block */
.pgname__head{display:flex;flex-direction:column;gap:12px;width:100%}
.pgname__h{margin:0;font-size:1.8rem;font-weight:500;letter-spacing:-.04em;line-height:1.05}
.pgname__p{margin:0;font-size:14px;line-height:1.5;color:var(--ink-70)}

/* A centred pill sitting on a full-width rule. The rule is drawn on the
   <p> and the pill knocks it out with an opaque background. */
.pgrule{
  position:relative;margin:0;
  /* pulled out to the card edge: the rule is a divider for the whole
     panel, not for the text column */
  width:calc(100% + var(--card-pad,26px) * 2);
  margin-left:calc(var(--card-pad,26px) * -1);
  margin-right:calc(var(--card-pad,26px) * -1);
  display:flex;align-items:center;justify-content:center;
  text-align:center;
}
.pgrule::before{
  content:"";position:absolute;left:0;right:0;top:50%;
  border-top:1px solid #e5e5e5;
}
.pgrule > span{
  position:relative;
  padding:8px 20px;
  color:#171717;background:var(--bg);
  border:2px solid #fff;
  border-radius:64px;
  letter-spacing:.16em;text-transform:uppercase;
}

/* 64px tile, 28px glyph */
.pgname__mark{
  width:64px;height:64px;flex:0 0 64px;
  display:grid;place-items:center;
  border-radius:50%;
  background:#EBEFFA;
}
.pgname__mark img{width:28px;height:28px;display:block}

/* One row at every width. align-items defaults to stretch, so the two
   cards share whichever is taller and the inner panel fills it. */
.pgname__pick{display:flex;align-items:stretch;gap:12px;width:100%}
.pgpick{position:relative;display:block;cursor:pointer;flex:1 1 0;min-width:0}
.pgpick__in{height:100%}
.pgpick input{position:absolute;opacity:0;inset:0;cursor:pointer;margin:0}
.pgpick__in{
  display:block;
  padding:20px;
  text-align:left;
  border:1px solid var(--line);
  border-radius:16px;
  background:#fff;
  transition:border-color .28s var(--ease),background .28s var(--ease);
}
.pgpick__top{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}

/* 40x40 tile, 18x18 glyph, per the component */
.pgpick__icon{
  width:40px;height:40px;flex:0 0 40px;
  display:grid;place-items:center;
  border-radius:50%;
  background:rgba(23,23,23,.06);
  color:var(--ink-70);
  transition:background .28s var(--ease),color .28s var(--ease);
}
.pgpick__icon svg{width:18px;height:18px;display:block}

/* 20x20 radio, top right */
.pgpick__radio{
  width:20px;height:20px;flex:0 0 20px;margin-top:2px;
  border:1.5px solid rgba(23,23,23,.28);
  border-radius:50%;
  position:relative;
  transition:border-color .28s var(--ease),background .28s var(--ease);
}
.pgpick__radio::after{
  content:"";position:absolute;inset:0;margin:auto;
  width:8px;height:8px;border-radius:50%;
  background:#fff;
  transform:scale(0);
  transition:transform .28s var(--ease-out);
}

.pgpick__title{
  display:block;margin-top:18px;
  font-size:16px;font-weight:500;letter-spacing:-.01em;color:var(--ink);
}
.pgpick__sub{
  display:block;margin-top:4px;
  font-size:14px;line-height:1.45;color:var(--ink-55);
}

/* selected: lavender field, brand border, filled radio */
.pgpick input:checked + .pgpick__in{
  background:#E8E6FA;
  border-color:var(--brand-deep);
}
.pgpick input:checked + .pgpick__in .pgpick__icon{
  background:rgba(118,101,221,.28);
  color:var(--brand-deep);
}
.pgpick input:checked + .pgpick__in .pgpick__radio{
  background:var(--brand-deep);
  border-color:var(--brand-deep);
}
.pgpick input:checked + .pgpick__in .pgpick__radio::after{transform:scale(1)}
.pgpick input:checked + .pgpick__in .pgpick__sub{color:#404040}
.pgpick input:focus-visible + .pgpick__in{outline:2px solid var(--brand);outline-offset:2px}
.pgname__card input{
  width:100%;height:48px;padding:0 20px;
  font:inherit;font-size:16px;font-weight:500;letter-spacing:.1em;text-align:center;
  text-transform:uppercase;color:var(--ink);background:var(--bg);
  border:1px solid var(--line);border-radius:12px;
}
.pgname__card input:focus{outline:none;border-color:var(--brand-deep);
  box-shadow:0 0 0 3px rgba(76,51,188,.14)}
.pgname__card input::placeholder{letter-spacing:.14em;color:var(--ink-38)}
.pgload__bar{
  width:100%;height:4px;border-radius:99px;
  background:rgba(23,23,23,.10);overflow:hidden;
}
.pgload__bar span{
  display:block;height:100%;width:100%;
  transform:scaleX(0);transform-origin:0 50%;
  background:var(--brand-deep);
  transition:transform .35s var(--ease);
}
.pgload__pct{
  position:absolute;
  right:var(--pad,24px);
  bottom:clamp(18px,3vh,32px);
  font-size:clamp(3rem,4.5vw,7.4rem);font-weight:500;
  letter-spacing:-.04em;line-height:1;color:var(--ink-70);
  font-variant-numeric:tabular-nums;
}

/* ── bar ──────────────────────────────────────────────────────────── */
.pg__bar{
  position:fixed;top:0;left:0;right:0;z-index:20;
  display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:12px clamp(14px,2.4vw,22px);
  background:linear-gradient(to bottom,rgba(242,241,239,.82),rgba(242,241,239,0));
  pointer-events:none;
}
.pg__bar > *{pointer-events:auto}
/* same clamp as the homepage nav, so the mark is identical across pages */
.pg__logo{width:clamp(140px,8vw,116px);height:auto;transition:opacity .4s var(--ease)}
.pg__brand:hover .pg__logo{opacity:.62}
.pg__envs{display:flex;gap:8px}
.pg__envs .btn{background:rgba(255,255,255,.7);backdrop-filter:blur(10px)}
.pg__envs .btn[aria-pressed="true"]{--btn-bg:var(--ink);--btn-fg:var(--bg);--btn-bd:var(--ink)}

/* ── floating counter, bottom right ───────────────────────────────── */
.pg__counter{
  position:fixed;right:clamp(12px,2vw,22px);bottom:clamp(12px,2vw,22px);z-index:20;
  width:min(184px,44vw);
  padding:14px 16px 12px;
  border-radius:18px;
  background:rgba(255,255,255,.6);
  backdrop-filter:blur(18px) saturate(1.3);
  -webkit-backdrop-filter:blur(18px) saturate(1.3);
  border:1px solid rgba(255,255,255,.75);
  box-shadow:0 20px 44px -26px rgba(23,23,23,.5);
}
.pg__stat{display:flex;flex-direction:column;gap:1px}
.pg__stat + .pg__stat{margin-top:10px;padding-top:10px;border-top:1px solid rgba(23,23,23,.08)}
.pg__stat strong{
  font-size:clamp(1.3rem,2.2vw,1.7rem);font-weight:500;
  letter-spacing:-.035em;line-height:1.05;
  font-variant-numeric:tabular-nums;
}
.pg__stat .mono{color:var(--ink-55)}
.pg__stat--sm strong{font-size:1.05rem}

/* ── sound toggle ────────────────────────────────────────────────── */
.pg__sound{
  position:fixed;right:clamp(12px,2vw,22px);bottom:clamp(12px,2vw,22px);z-index:22;
  width:74px;height:74px;
  display:grid;place-items:center;
  border:1px solid rgba(255,255,255,.7);border-radius:50%;
  background:rgba(255,255,255,.6);
  backdrop-filter:blur(16px) saturate(1.3);
  -webkit-backdrop-filter:blur(16px) saturate(1.3);
  cursor:pointer;
  box-shadow:0 16px 34px -20px rgba(23,23,23,.55);
  transition:background .3s var(--ease),transform .3s var(--ease);
}
.pg__sound:hover{transform:translateY(-2px);background:rgba(255,255,255,.85)}
.pg__wave{display:flex;align-items:center;gap:3px;height:26px}
.pg__wave i{
  display:block;width:3px;border-radius:99px;
  background:var(--brand-deep);
  height:22px;
  transform-origin:50% 50%;
  animation:pgwave 1s ease-in-out infinite;
}
.pg__wave i:nth-child(1){animation-delay:0s}
.pg__wave i:nth-child(2){animation-delay:.12s}
.pg__wave i:nth-child(3){animation-delay:.24s}
.pg__wave i:nth-child(4){animation-delay:.36s}
.pg__wave i:nth-child(5){animation-delay:.18s}
.pg__wave i:nth-child(6){animation-delay:.30s}
.pg__wave i:nth-child(7){animation-delay:.06s}
@keyframes pgwave{
  0%,100%{transform:scaleY(.22)}
  50%    {transform:scaleY(1)}
}
/* muted: every bar collapses to one flat line */
.pg__sound[aria-pressed="false"] .pg__wave i{
  animation:none;
  transform:scaleY(.09);
  background:var(--ink-38);
}

/* Leaving for the homepage. Same idea as arriving: fade the whole scene to
   the colour the next page is already painted, so the swap is a dissolve
   rather than a flash of white. */
.pg__exit{
  position:fixed;inset:0;z-index:400;
  background:var(--bg);
  opacity:0;pointer-events:none;
  transition:opacity .38s var(--ease);
}
.pg__exit.is-on{opacity:1;pointer-events:auto}

/* ── environment crossfade ───────────────────────────────────────── */
.pg__wipe{
  position:fixed;inset:0;z-index:18;pointer-events:none;
  opacity:0;
  /* blooms from the middle, which is where the cart is */
  background:radial-gradient(circle at 50% 54%,#fff 0%,#fff 42%,rgba(255,255,255,.72) 100%);
  transition:opacity .26s var(--ease);
}
.pg__wipe.is-on{opacity:1}

/* ── toss gauge ──────────────────────────────────────────────────── */
/* The band needs empty room *below* its posts to be pulled into, so the
   svg box carries a tall lower half and sits lower on the screen than the
   arc alone would want. At rest the arc lands about where it always did. */
.pg__gauge{
  position:fixed;left:50%;bottom:clamp(4px,1vw,10px);transform:translateX(-50%);z-index:21;
  width:min(228px,40vw);
  display:flex;flex-direction:column;align-items:center;gap:6px;
  opacity:0;pointer-events:none;
  transition:opacity .22s var(--ease);
}
.pg__gauge.is-on{opacity:1}
.pg__gauge_svg{width:100%;height:auto;display:block;overflow:visible}
.pg__gauge_svg path{fill:none;stroke-linecap:round}
/* the offset copy behind the arc is what gives it depth */
/* --thin is driven from JS: rubber under tension gets visibly narrower,
   and thinning the stroke is the cheapest way to say so. */
.pg__gauge_base{stroke:rgba(23,23,23,.14);stroke-width:calc(6px * var(--thin,1))}
.pg__gauge_track{stroke:rgba(255,255,255,.82);stroke-width:calc(4px * var(--thin,1))}
.pg__gauge_fill{
  stroke:url(#pgGaugeFill);stroke-width:calc(4px * var(--thin,1));
  stroke-dasharray:var(--len,136);
  stroke-dashoffset:calc(var(--len,136) * (1 - var(--p,0)));
}
.pg__gauge_tip{
  fill:#fff;stroke:var(--brand-deep);stroke-width:2;
  filter:drop-shadow(0 2px 6px rgba(76,51,188,.5));
}
/* no transitions on d/cx/cy/dashoffset anywhere above: the frame loop
   writes every one of them each tick, and a transition would just lag
   the spring by its own duration. */

/* ── toss feedback ───────────────────────────────────────────────── */
/* Sticker lettering rather than a plate: white fill with a heavy coloured
   outline, sat straight on the scene. `paint-order` is what makes it work -
   without it the stroke is centred on the glyph edge and eats half the
   letterform, leaving thin mush instead of a fat outline. */
.pg__banner{
  position:fixed;left:50%;top:22%;transform:translate(-50%,0);z-index:24;
  /* the two outlines are thick enough to touch across a small gap */
  display:flex;flex-direction:column;align-items:center;gap:12px;
  pointer-events:none;opacity:0;text-align:center;
  /* scaled about its own middle, which sits on the viewport centre */
  transform-origin:50% 50%;
  will-change:transform,opacity;
}
.pg__banner{--bink:var(--brand-deep)}
.pg__banner strong,
.pg__banner .mono{
  /* A rounded face, and only here. Archivo's flat terminals leave the
     thick outline with square corners and mitre spikes; a rounded one
     gives the outline round ends for free, which is what the sticker
     look is actually made of. */
  font-family:"Fredoka","Baloo 2",var(--font),sans-serif;
  color:#fff;
  paint-order:stroke fill;
  -webkit-text-stroke-color:var(--bink);
  /* Only half of this is visible, the rest sits under the fill. Heavy
     enough that neighbouring letters' outlines overlap rather than leaving
     the scene showing through between them - the outline is meant to read
     as one continuous sticker, the way Duolingo's does. */
  -webkit-text-stroke-width:16px;
}
.pg__banner strong{
  position:relative;display:inline-block;
  font-size:clamp(2.4rem,6.4vw,3.7rem);
  font-weight:700;line-height:1;
  letter-spacing:.1em;
}
/* read by the aria-live region; never painted */
.pgsr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}

/* Two passes over the same word. The first lays down every character's
   outline - filled in the same colour, so no hairline of scene can show
   between stroke and fill - and the second lays the white faces over the
   top. Because all the strokes are painted before any of the faces, a
   character animating in late can never cut into the one before it. */
.pgchars{display:block;white-space:nowrap}
.pgchars--fill{position:absolute;inset:0}
.pgchars i{display:inline-block;font-style:normal;will-change:transform,opacity}
.pg__banner strong .pgchars i{
  color:var(--bink);
  /* text-shadow rather than filter: a filter re-rasterises the element on
     every frame of the stagger, which is what made this judder before. */
  text-shadow:0 4px 0 rgba(28,20,64,.18), 0 9px 20px rgba(28,20,64,.3);
}
.pg__banner strong .pgchars--fill i{
  color:#fff;
  -webkit-text-stroke-width:0;
  text-shadow:none;
}
/* left to right, each character rising as it fades up */
.pg__banner.is-on .pgchars i{
  animation:pgchar .42s var(--ease-out) both;
  animation-delay:calc(var(--i) * 45ms);
}
@keyframes pgchar{
  0%  {opacity:0;transform:translateY(30px) scale(.84)}
  55% {opacity:1;transform:translateY(-5px) scale(1.06)}
  78% {opacity:1;transform:translateY(1px)  scale(.99)}
  100%{opacity:1;transform:none}
}
.pg__banner .mono{
  font-size:clamp(.9rem,2.1vw,1.15rem);
  font-weight:600;letter-spacing:.14em;
  -webkit-text-stroke-width:10px;
  text-shadow:0 3px 0 rgba(28,20,64,.16), 0 7px 16px rgba(28,20,64,.28);
  /* held back until the word above it has finished landing */
  animation:pgsub .4s var(--ease-out) both;
}
.pg__banner.is-on .mono{animation-delay:.3s}
@keyframes pgsub{
  from{opacity:0;transform:translateY(14px)}
  to  {opacity:1;transform:none}
}
/* one custom property now drives both the outline and its filled core */
.pg__banner.is-hot {--bink:#e2892a}
.pg__banner.is-cold{--bink:#6f6f7a}
.pg__banner.is-cold strong{font-size:clamp(1.5rem,3.6vw,2rem)}
.pg__banner.is-on{animation:pgbanner 1.05s var(--ease-out) forwards}
/* The pop is a transform, not a letter-spacing tween.
   Spacing grows the box sideways, which reads as the callout stretching
   out rather than jumping at you - and being a layout property it cannot
   be composited, so it was never going to be as smooth as this. Scale from
   the middle, overshoot, settle, then float up and out. */

/* The container no longer pops - the characters own the entrance now, and
   scaling the whole block on top of them read as a double bounce. All this
   does is hold the callout at centre while the letters land, then float the
   finished word up and out. Opacity starts at 1 because each character
   fades itself in; multiplying the two just greyed out the landing. */
@keyframes pgbanner{
  0%  {opacity:1;transform:translate(-50%,10px)}
  52% {opacity:1;transform:translate(-50%,0)}
  74% {opacity:1;transform:translate(-50%,-16px)}
  100%{opacity:0;transform:translate(-50%,-58px)}
}


.pg__over{
  position:fixed;inset:0;z-index:40;
  display:grid;place-items:center;
  background:rgba(18,17,24,.42);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  opacity:0;transition:opacity .34s var(--ease);
}
.pg__over.is-on{opacity:1}

/* ── the board that swings down over the result ─────────────────── */
.pghang{
  position:absolute;top:0;left:50%;z-index:2;
  width:min(320px,78vw);
  transform:translate(-50%,-135%);
  transform-origin:50% 0;
  transition:transform .8s cubic-bezier(.2,1.3,.36,1);
  pointer-events:none;
}
.pg__over.is-on .pghang{transform:translate(-50%,0)}
/* the rig: two drops from the ceiling to the top corners of the bezel */
.pghang__rig{display:block;height:clamp(18px,5vh,44px);position:relative}
.pghang__rig i{
  position:absolute;top:0;bottom:0;width:2px;
  background:linear-gradient(180deg,rgba(23,23,23,.15),rgba(23,23,23,.55));
}
.pghang__rig i:first-child{left:22%}
.pghang__rig i:last-child{right:22%}
.pghang__board{
  padding:7px;border-radius:12px;
  background:linear-gradient(180deg,#2b2b33,#14141a);
  box-shadow:0 18px 38px -18px rgba(8,4,7,.8),inset 0 1px 0 rgba(255,255,255,.14);
}
.pghang__screen{
  position:relative;overflow:hidden;
  padding:12px 16px 14px;border-radius:7px;
  background:#080407;
  display:flex;flex-direction:column;align-items:center;gap:2px;
  text-align:center;
}
/* The dot grid is what makes it a panel of lamps and not red text. It was
   eating the masthead, though: 1.4px of black every 4px over 10px letters
   leaves nothing to read. Finer pitch, lighter lines, bigger type. */
.pghang__screen::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    repeating-linear-gradient(0deg,rgba(0,0,0,.34) 0 1px,transparent 1px 3px),
    repeating-linear-gradient(90deg,rgba(0,0,0,.34) 0 1px,transparent 1px 3px);
}
.pghang__kicker{
  font-size:13px;font-weight:700;letter-spacing:.2em;
  color:#ffc75a;
  text-shadow:0 0 10px rgba(255,180,58,.55);
}
.pghang__name{
  font-size:clamp(1.5rem,5.4vw,2rem);font-weight:700;letter-spacing:.06em;
  line-height:1.05;color:#ff2f1c;
  text-shadow:0 0 18px rgba(255,47,28,.65);
  word-break:break-word;
}
.pg__over_card{
  --card-pad:26px;
  width:min(500px,86vw);padding:26px var(--card-pad) 22px;
  max-height:92svh;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;
  background:#fff;border-radius:24px;text-align:center;
  box-shadow:0 40px 90px -40px rgba(18,17,24,.6);
  transform:translateY(14px) scale(.97);
  transition:transform .42s var(--ease-out);
}
.pg__over.is-on .pg__over_card{transform:none}
/* Reuses the start card's 64px mark plate. The glyph is asked for by
   name so an iPhone renders its own set rather than a monochrome fallback. */
.pg__over_mark{
  margin:0 auto 14px;
  font-size:32px;line-height:1;
  font-family:"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",
              "Twemoji Mozilla",sans-serif;
}
.pg__over_kicker{display:block;color:var(--ink-38);letter-spacing:.2em}
.pg__over_title{
  margin:8px 0 0;
  font-size:clamp(1.9rem,4.6vw,2.6rem);font-weight:600;
  letter-spacing:-.04em;line-height:1;color:var(--ink);
}

.pg__stats{
  display:grid;grid-template-columns:1fr 1fr;gap:14px 10px;
  width:calc(100% + var(--card-pad,26px) * 2);
  margin:22px calc(var(--card-pad,26px) * -1) 18px;
  padding:18px var(--card-pad,26px) 22px;
  border-top:1px solid var(--line-soft);
}
.pg__stats li{display:flex;flex-direction:column;gap:2px}
.pg__stats li > span:first-child{
  font-size:22px;font-weight:500;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;
}
.pg__stats .mono{font-size:12px;color:var(--ink-38);letter-spacing:.12em}

/* keeps the full-bleed side margins from .pgrule, adds the gap below */
.pg__over_note{margin-bottom:14px}
.pg__over_card .pg__cta{height:48px}
.pg__cta .btn__roll>span{font-size:13px;letter-spacing:.14em}
.pg__over_minor{
  display:flex;align-items:stretch;justify-content:center;gap:12px;
  margin-top:14px;
}
/* text only: it leaves the game, so it should not compete with the two
   buttons that keep the player in it */
.pg__over_card .pg__over_home{
  display:flex;margin:14px auto 0;
  border:0;height:auto;padding:2px 0;
  color:var(--ink-38);
}
.pg__over_home:hover{color:var(--ink)}
.pg__over_home .btn__roll > span{font-size:11px;letter-spacing:.14em}
.pg__over_minor .btn--link{
  flex:1 1 0;min-width:0;height:48px;min-height:48px;
  display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:12px;
}
/* Every CTA the playground itself puts up is 48px. Scoped to the game
   chrome rather than `.pg .btn`, so the shared waitlist panel keeps the
   same button metrics it has on the homepage. */
.pg__bar .btn,
.pgname__card .btn,
.pgcoach__inner .btn,
.pg__over_card .btn:not(.pg__over_home),
.pg__tiltbtn{height:48px}

/* ── environment tabs, bottom left ───────────────────────────────── */
.pg__tabs{
  position:fixed;left:clamp(12px,2vw,22px);bottom:clamp(12px,2vw,22px);z-index:20;
  display:flex;gap:8px;
}
.pg__tab{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  width:74px;height:74px;padding:0;
  border:1px solid rgba(255,255,255,.7);border-radius:50%;
  background:rgba(255,255,255,.55);
  backdrop-filter:blur(16px) saturate(1.3);
  -webkit-backdrop-filter:blur(16px) saturate(1.3);
  color:var(--ink-55);
  cursor:pointer;
  transition:transform .3s var(--ease),background .3s var(--ease),color .3s var(--ease);
}
.pg__tab svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.6}
.pg__tab .mono{font-size:8.5px;letter-spacing:.1em}
.pg__tab:hover{transform:translateY(-3px);background:rgba(255,255,255,.85);color:var(--ink)}
.pg__tab[aria-pressed="true"]{
  background:var(--ink);border-color:var(--ink);color:#fff;
  box-shadow:0 10px 24px -12px rgba(23,23,23,.6);
}
.pg__tab[aria-pressed="true"] .mono{color:#fff}

.pg__tiltbtn{display:none !important;
  /* sits above the tabs and clear of the counter, which both own the
     bottom corners on a phone */
  position:fixed;left:clamp(12px,2vw,22px);bottom:calc(clamp(12px,2vw,22px) + 78px);z-index:21;
  background:rgba(255,255,255,.8);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
}

/* ── hint + splashes ──────────────────────────────────────────────── */
.pg__hint{
  /* Centred with left/right + auto margins rather than left:50% and a
     translate: an absolutely positioned box only gets the space from its
     offset to the container edge, so left:50% halved the width available. */
  position:absolute;left:0;right:0;bottom:16%;
  margin:0 auto;
  /* hugs its copy, and only ever grows to within 8px of each edge */
  width:fit-content;
  max-width:calc(100% - 16px);
  padding:9px 17px;border-radius:99px;
  display:flex;align-items:flex-start;justify-content:center;gap:8px;
  background:rgba(23,23,23,.86);color:var(--bg);
  font-size:14px;line-height:1.35;text-align:left;
  opacity:0;pointer-events:none;
  transition:opacity .45s var(--ease);
}
.pg__hint_i{
  display:flex;flex:0 0 16px;width:16px;height:16px;
  /* nudged onto the first line's baseline now that the text can wrap */
  margin-top:1px;
  color:var(--bg);opacity:.72;
}
.pg__hint_i svg{width:100%;height:100%;display:block}
.pg__hint.is-on{opacity:1}

.pg__splash{
  position:absolute;z-index:15;
  transform:translate(-50%,-50%);
  font-size:22px;font-weight:600;letter-spacing:-.02em;
  /* light, with a dark halo: it lands over the cart, which is now deep
     purple, and dark-on-dark disappeared at the moment it mattered */
  color:#fff;
  pointer-events:none;
  animation:pgsplash 1.1s var(--ease-out) forwards;
  text-shadow:0 2px 14px rgba(28,20,64,.95), 0 0 34px rgba(118,101,221,.85);
}
.pg__splash.is-mult{color:#E8E6FA;font-size:27px}
@keyframes pgsplash{
  0%{opacity:0;transform:translate(-50%,-50%) scale(.7)}
  18%{opacity:1;transform:translate(-50%,-60%) scale(1.06)}
  100%{opacity:0;transform:translate(-50%,-160%) scale(1)}
}

/* ── first-run gesture coach ─────────────────────────────────────── */
.pgcoach{
  position:fixed;inset:0;z-index:45;
  display:grid;place-items:center;
  background:rgba(18,17,24,.55);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);
  opacity:0;transition:opacity .38s var(--ease);
}
.pgcoach.is-on{opacity:1}
.pgcoach__inner{
  --card-pad:26px;
  width:min(380px,86vw);padding:26px var(--card-pad) 22px;
  max-height:92svh;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;
  background:#fff;border-radius:24px;text-align:center;
  transform:translateY(14px) scale(.97);
  transition:transform .42s var(--ease-out);
  box-shadow:0 40px 90px -40px rgba(18,17,24,.6);
}
.pgcoach.is-on .pgcoach__inner{transform:none}
.pgcoach__stage{
  position:relative;height:150px;margin-bottom:6px;
  border-radius:16px;background:var(--bg);overflow:hidden;
}
/* the path the hand traces: down, then a lateral sweep */
.pgcoach__trail{
  position:absolute;left:50%;top:34px;
  width:2px;height:60px;margin-left:-1px;border-radius:2px;
  background:linear-gradient(180deg,rgba(118,101,221,0),var(--brand));
  opacity:.5;
}
.pgcoach__hand{
  position:absolute;left:50%;top:26px;
  width:44px;height:44px;margin-left:-22px;
  color:var(--brand-deep);
  animation:pgcoachhand 3s ease-in-out infinite;
}
.pgcoach__hand svg{width:100%;height:100%;display:block}
@keyframes pgcoachhand{
  0%   {transform:translate(0,0) scale(1);opacity:0}
  10%  {transform:translate(0,0) scale(1);opacity:1}
  32%  {transform:translate(0,56px) scale(.94);opacity:1}
  50%  {transform:translate(-42px,56px) scale(.94);opacity:1}
  68%  {transform:translate(42px,56px) scale(.94);opacity:1}
  84%  {transform:translate(0,56px) scale(.94);opacity:1}
  92%  {transform:translate(0,10px) scale(1.06);opacity:.6}
  100% {transform:translate(0,0) scale(1);opacity:0}
}
.pgcoach__h{margin:10px 0 0;font-size:1.4rem;font-weight:500;letter-spacing:-.03em}
.pgcoach__p{margin:8px 0 18px;font-size:14px;line-height:1.5;color:var(--ink-70)}

/* ── narrow ───────────────────────────────────────────────────────── */
@media (max-width:760px){
  .pg__bar{flex-wrap:wrap;gap:10px;padding-bottom:8px}
  .pg__envs{order:3;width:100%}
  .pg__envs .btn{flex:1 1 0}
  .pg__counter{width:min(180px,44vw);padding:11px 13px 10px}
  .pg__counter_row + .pg__counter_row{display:none}
  .pg__tabs{gap:6px}
  .pg__tab{width:62px;height:62px}
  .pg__tab svg{width:19px;height:19px}
  .pg__sound{width:62px;height:62px}
  .pg__gauge{width:min(178px,42vw);bottom:calc(clamp(6px,1.4vw,12px) + 52px)}
  .pg__hint{bottom:22%;font-size:14px}
}
@media (max-height:660px){
  .pghang{width:min(250px,70vw)}
  .pghang__rig{height:12px}
  .pghang__screen{padding:8px 12px 10px}
}

/* ── mobile: every panel is a bottom sheet ───────────────────────── */
@media (max-width:900px){
  .pgname,.pg__over,.pgcoach{place-items:end stretch}
  .pgname__card,.pg__over_card,.pgcoach__inner{
    width:100%;max-width:none;
    border-radius:24px 24px 0 0;
    max-height:92svh;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;
    padding-bottom:calc(24px + env(safe-area-inset-bottom));
  }
  /* rides up from the edge it is anchored to, not in from the middle */
  .pgname__card,.pg__over_card,.pgcoach__inner{transform:translateY(100%)}
  .pgname.is-on .pgname__card,
  .pg__over.is-on .pg__over_card,
  .pgcoach.is-on .pgcoach__inner{transform:none}
}

@media (max-width:560px){
  /* the two picks stack here, so buy the height back from their padding */
  .pgname__card,.pg__over_card,.pgcoach__inner{--card-pad:18px}
  .pgname__card{padding-top:22px;gap:16px}
  .pgname__h{font-size:1.45rem}
  .pgpick__in{padding:16px}
  .pgpick__title{margin-top:12px}
  .pgpick__sub{font-size:14px}

  /* a column flex would otherwise shrink these on the main axis */
  .pg__over_minor{flex-direction:column}
  .pg__over_minor .btn--link{width:100%;flex:0 0 48px}
  .pg__over_minor .btn__roll > span{font-size:12px;letter-spacing:.1em}
}
@media (max-width:420px){
  .pg__counter{width:min(158px,46vw)}
  .pg__tab,.pg__sound{width:56px;height:56px}
  .pg__gauge{width:min(152px,42vw)}
}

@media (prefers-reduced-motion:reduce){
  .pgload__mark,.pgload::before{animation:none}
  .pg__splash{animation-duration:.01s}
}
