/* ============================================================
   Jugs — Celebration: GRADE CLEARED ("the board completes")
   Fires when a climber clears EVERY route of a grade at a gym.
   The board fills jug by jug in a wave — each cell is the route's
   own riso jug sticker (already wearing its sent check) — then
   the whole board gives one soft completion pulse and the payoff
   lands on N / N.

   Adapted from design_handoff_celebration_board_complete: the
   tape-cell + check grid is replaced by the app's real jug
   stickers (rendered app-side via holdHTML and handed in as
   data.jugs), so the moment shows the actual holds you cleared.

   Self-contained: all tokens it needs are defined here under
   .cscene.grade. Jug sizing / non-interactivity lives in the
   app-side .cboard-overlay block (it references the app's own
   .hold/.jug classes). Markup is produced by celebration-board.js.
   ============================================================ */

.cscene.grade {
  /* local tokens (subset of the Jugs palette) */
  --ink:     #1F1A14;
  --muted:   #847B6B;
  --green-d: #1F7A3F;
  --disp: "Bricolage Grotesque", system-ui, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* guard against mobile font boosting inflating the small mono text */
  -webkit-text-size-adjust: 100%; text-size-adjust: 100%;

  position: absolute; inset: 0; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 64px 30px 78px; padding-top: 40px;
  font-family: var(--mono);
  background: radial-gradient(circle at 50% 32%, #FFFFFF, #F1EAD8 78%);
}

/* ---- eyebrow: EVERY ROUTE · GRADE N ---- */
.grade .g-eyebrow { font-size: 10.5px; font-weight: 700; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--muted); }

/* ---- the board: one cell = one cleared route's jug ----
   grid-template-columns is set inline by celebration-board.js so the
   column count tracks the route total. The jug sticker itself is
   placed inside each cell by the app; this just lays out + waves them.
   overflow stays visible so the sent check / grade sticker can poke
   past the hold's corner, exactly like the live map. */
/* The scroll window. Jugs stay roped-size; a band taller than this is panned by
   play()'s autoScroll, so rows fade out at the TOP as they leave while new rows
   arrive crisp at the bottom — "scrolled into invisibility" rather than shrunk
   to fit. Horizontal padding (cancelled by the negative margin so the grid keeps
   full width) gives the bottom-right grade stickers room to overhang without the
   clip cropping the last column. overflow:hidden (not auto) means no scrollbar
   and the dismiss-tap is never eaten by a scroll gesture. */
.grade .g-window { position: relative; width: 100%; margin: 26px -20px 0;
  /* padding-bottom keeps the true last row clear of the bottom fade band, so a
     fully-shown band ends crisp; the fade only softens partial rows mid-scroll.
     Fixed-px mask stops (not %) so that clearance holds at any window height. */
  padding: 4px 20px 16px; max-height: 40vh; overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 44px, #000 calc(100% - 8px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 44px, #000 calc(100% - 8px), transparent 100%); }
.grade .g-grid { display: grid; gap: 12px; width: 100%;
  align-items: center; justify-items: center; }
.gcell { aspect-ratio: 1; position: relative; width: 100%;
  display: flex; align-items: center; justify-content: center; }

/* ---- payoff ---- */
.grade .g-head { font-family: var(--disp); font-weight: 800; font-size: 38px;
  line-height: 1.04; letter-spacing: -0.03em; color: var(--ink); margin-top: 30px; }
.grade .g-head em { font-style: normal; color: var(--green-d); }
/* inline grade sticker in the headline — the app's band tag, sized up as a hero
   on its own line. --sc (fill) / --sfg (ink) are set inline by the app from the
   grade band; the defaults below cover the plain fallback. Mirrors the jug's
   .t-tag print language: ink border + offset plate shadow + a slight tilt. */
.grade .g-head .g-tag { --sc: #fde047; --sfg: var(--ink);
  display: inline-block; margin: 0.16em 0; font-size: 0.92em; line-height: 1;
  font-weight: 800; letter-spacing: -0.02em; color: var(--sfg); background: var(--sc);
  padding: 0.12em 0.3em 0.16em; border-radius: 0.16em;
  border: 0.06em solid var(--ink-plate); transform: rotate(-3deg);
  box-shadow: 0.07em 0.09em 0 0 color-mix(in srgb, var(--sc) 52%, var(--ink-plate)); }
.grade .g-sub { font-size: 11px; font-weight: 600; letter-spacing: 0.06em;
  color: var(--muted); margin-top: 12px; }
.grade .g-sub b { color: var(--ink); }

/* ============================================================
   Motion. Content is fully visible AT REST (robust for print,
   capture, and reduced motion). Adding .play to the screen
   container (re)runs the entrance; per-cell delays are inline,
   computed by celebration-board.js from the route count so the
   wave scales with the data.
   ============================================================ */
/* `both` fill: while a cell waits out its stagger delay it holds the 0%
   keyframe (invisible) — the board fills one jug at a time, a true
   ripple, rather than every cell popping in place. */
.play .grade .g-eyebrow { animation: rise 600ms ease-out both; }
/* will-change promotes each cell to its own layer so the pop SCALE composites
   instead of repainting the riso hold's mask + gradients every frame — the
   stutter at the start of the wave. The overlay is removed on dismiss, so the
   layers are short-lived. */
.play .grade .gcell { animation: cellPop 420ms cubic-bezier(0.2, 1.3, 0.4, 1) both;
  will-change: transform, opacity; }
.play .grade .g-head { animation: rise 700ms ease-out both; }
.play .grade .g-sub { animation: rise 700ms ease-out both; }

@keyframes cellPop { 0% { opacity: 0; transform: scale(0.4); }
  100% { opacity: 1; transform: scale(1); } }
@keyframes rise { 0% { opacity: 0; transform: translateY(14px); }
  100% { opacity: 1; transform: translateY(0); } }

@media (prefers-reduced-motion: reduce) {
  .play .grade .g-eyebrow, .play .grade .gcell,
  .play .grade .g-head, .play .grade .g-sub { animation: none !important; opacity: 1 !important; }
}
