/* ===================== the celebrations · the eighteen ====================
   The full-screen takeover that plays when one of the in-game eggs is found.
   Built to sit next to secret 2's X-ray flip without looking cheaper than it.

   The centrepiece is a SPLIT-FLAP DEPARTURE BOARD: `.cel-flap` cells that
   riffle through glyphs and land on the right letter, driven from
   js/secrets/celebrate.js because a CSS animation cannot be re-run per cell
   reliably and gets switched off wholesale under reduced-motion — the same trap
   that once made the fly-past invisible.

   Everything is positioned against the viewport, never the page, so a
   celebration during a game does not care what is scrolled where.

   --cel-hue is set per egg by the script. Nothing here hard-codes an accent.
   ========================================================================= */

.cel {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: clamp(14px, 5vw, 40px);
  overflow: hidden;
  background:
    radial-gradient(80% 60% at 50% 40%,
      color-mix(in srgb, var(--cel-hue) 26%, #04121D) 0%, #04121D 70%),
    #04121D;
  animation: celin 300ms ease-out both;
  cursor: pointer;
}
.cel.out { animation: celout 400ms ease-in both; }

@keyframes celin  { from { opacity: 0; } to { opacity: 1; } }
@keyframes celout { to { opacity: 0; } }

/* A slow breathe under the whole takeover. It is a separate layer rather than an
   animation on `.cel` itself, because `.cel` already animates its own opacity in
   and out and one element cannot run two animations on the same property. */
.cel::after {
  content: "";
  position: absolute;
  inset: -20%;
  z-index: 0;
  background: radial-gradient(closest-side,
    color-mix(in srgb, var(--cel-hue) 30%, transparent), transparent 70%);
  opacity: .45;
  animation: celbreathe 4.2s ease-in-out infinite;
  pointer-events: none;
}
@keyframes celbreathe {
  0%, 100% { transform: scale(.86); opacity: .30; }
  50%      { transform: scale(1.06); opacity: .55; }
}

/* ---------------------------------------------------------------- the card */
.cel-card {
  position: relative;
  z-index: 3;
  width: min(560px, 100%);
  display: grid;
  justify-items: center;
  gap: clamp(10px, 2.6vw, 18px);
  text-align: center;
  animation: celcard 460ms cubic-bezier(.16, 1.1, .3, 1) both;
}
@keyframes celcard {
  from { transform: translateY(-26px) scale(.94); opacity: 0; }
  to   { transform: none;                         opacity: 1; }
}

/* the strip along the top: what kind, and the running tally */
.cel-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  width: 100%;
  padding-bottom: 8px;
  border-bottom: 1px solid color-mix(in srgb, var(--cel-hue) 45%, transparent);
  font-size: clamp(9.5px, 2.6vw, 11px);
  font-weight: 800;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--cel-hue) 70%, #FFFFFF);
}
.cel-tally {
  font-variant-numeric: tabular-nums;
  letter-spacing: .16em;
  color: #FFFFFF;
}

.cel-glyph {
  font-size: clamp(40px, 13vw, 68px);
  line-height: 1;
  color: var(--cel-hue);
  filter: drop-shadow(0 0 18px color-mix(in srgb, var(--cel-hue) 60%, transparent));
  animation: celglyph 620ms cubic-bezier(.2, 1.8, .35, 1) both 140ms;
}
@keyframes celglyph {
  from { transform: scale(2.4) rotate(-14deg); opacity: 0; }
  to   { transform: none;                      opacity: 1; }
}

/* -------------------------------------------------------- the flap board */
.cel-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(2px, .7vw, 4px);
}

/* the plate the flaps are bolted to, so the row reads as one object rather than
   as a line of loose tiles */
.cel-name {
  padding: clamp(6px, 1.8vw, 10px) clamp(8px, 2.2vw, 13px);
  border-radius: 6px;
  background: rgba(0, 0, 0, .34);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .06),
              inset 0 2px 14px rgba(0, 0, 0, .55);
  position: relative;
  overflow: hidden;
}
/* one specular pass across the board once every flap has landed. Added by
   script, because when that happens depends on how long the name is. */
.cel-name.lit::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 38%,
    color-mix(in srgb, var(--cel-hue) 42%, #FFFFFF) 50%, transparent 62%);
  opacity: .5;
  transform: translateX(-120%);
  animation: celsheen 900ms cubic-bezier(.3, 0, .3, 1) 1 both;
  pointer-events: none;
}
@keyframes celsheen { to { transform: translateX(120%); } }
.cel-flap {
  --flap: clamp(19px, 5.4vw, 30px);
  position: relative;
  display: inline-grid;
  place-items: center;
  width: var(--flap);
  height: calc(var(--flap) * 1.42);
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: calc(var(--flap) * .82);
  font-weight: 700;
  color: #F2F7FB;
  background: linear-gradient(#1B2A36 0 49%, #0E1A24 51% 100%);
  border-radius: 3px;
  /* the seam across the middle, which is what makes it read as a flap */
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .07),
              0 1px 0 rgba(0, 0, 0, .5);
  overflow: hidden;
}
.cel-flap::after {                       /* the hinge line */
  content: "";
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 1px;
  background: rgba(0, 0, 0, .55);
}
.cel-flap.gap {
  background: none;
  box-shadow: none;
  width: calc(var(--flap) * .5);
}
.cel-flap.gap::after { display: none; }

/* One turn of one flap, re-applied per riffle by the script.

   THE PERSPECTIVE IS THE WHOLE ILLUSION, and it is written into the transform
   rather than set on the row. A bare rotateX is an orthographic squash — the
   cell just gets shorter and springs back, which reads as a glitch rather than
   as a fold. Doing it per-cell also avoids putting `perspective` on the same
   element as the plate's `overflow: hidden`, which some engines flatten, and it
   gives every cell its own vanishing point — which is what a real board does,
   since each character is its own little housing. */
.cel-flap.turn { animation: flapturn 90ms ease-out; }
@keyframes flapturn {
  0%   { transform: perspective(300px) rotateX(-58deg); filter: brightness(.55); }
  100% { transform: perspective(300px) rotateX(0deg);   filter: none; }
}

/* the letter it settled on. The landing gets its OWN, longer turn with a small
   overshoot and a flash, so the last flip of each cell is the one you notice —
   a row of them settling left to right is the whole point of the effect.
   `.set` is written after `.turn` deliberately: same specificity, so this wins
   on the frame both classes arrive together. */
.cel-flap.set {
  color: #FFFFFF;
  background: linear-gradient(
    color-mix(in srgb, var(--cel-hue) 34%, #1B2A36) 0 49%,
    color-mix(in srgb, var(--cel-hue) 18%, #0E1A24) 51% 100%);
  animation: flapset 380ms cubic-bezier(.2, 1.4, .35, 1);
}
@keyframes flapset {
  0%   { transform: perspective(300px) rotateX(-64deg); filter: brightness(.45); }
  58%  { transform: perspective(300px) rotateX(7deg);   filter: brightness(1.55); }
  100% { transform: perspective(300px) rotateX(0deg);   filter: none; }
}

/* the how-you-did-it, which arrives after the board has finished clacking */
.cel-how {
  margin: 0;
  max-width: 34ch;
  font-size: clamp(11.5px, 3.2vw, 13.5px);
  line-height: 1.5;
  letter-spacing: .04em;
  color: #9FB6C6;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 420ms ease, transform 420ms ease;
}
.cel-how.in { opacity: 1; transform: none; }

/* the hard ones get a gold rule and a heavier tally */
.cel.hard .cel-bar { border-bottom-width: 2px; }
.cel.hard .cel-tally { color: #F0D68A; }

/* --------------------------------------------------------- the flourishes */
/* radar: a beam sweeping the whole screen from the centre */
.cel-radar {
  position: absolute;
  z-index: 1;
  left: 50%; top: 50%;
  width: 220vmax; height: 220vmax;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: conic-gradient(from 0deg,
    color-mix(in srgb, var(--cel-hue) 40%, transparent) 0deg,
    transparent 34deg, transparent 360deg);
  opacity: .5;
  animation: celradar 2.6s linear 2;
  pointer-events: none;
}
@keyframes celradar { to { transform: translate(-50%, -50%) rotate(360deg); } }

/* scan: the X-ray raster and sweep line, on purpose the same idiom as secret 2 */
.cel.cel-scan::before,
.cel.k-scan::before {
  content: "";
  position: absolute; inset: 0;
  background: repeating-linear-gradient(0deg,
    rgba(150, 225, 255, .06) 0 2px, transparent 2px 5px);
  pointer-events: none;
}
.cel-scanbar {
  position: absolute;
  z-index: 1;
  left: 0; right: 0; top: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, #8FE9FF, transparent);
  box-shadow: 0 0 16px 3px rgba(120, 225, 255, .5);
  animation: celscan 1.7s linear infinite;
  pointer-events: none;
}
@keyframes celscan { from { top: -2%; } to { top: 102%; } }

/* slam: one shockwave ring hammering outward, the passport-stamp feeling */
.cel-ring {
  position: absolute;
  z-index: 1;
  left: 50%; top: 50%;
  width: 12vmin; height: 12vmin;
  margin: -6vmin 0 0 -6vmin;
  border: 3px solid var(--cel-hue);
  border-radius: 50%;
  opacity: 0;
  animation: celring 900ms cubic-bezier(.15, .85, .2, 1) 3 both 120ms;
  pointer-events: none;
}
@keyframes celring {
  0%   { transform: scale(.2); opacity: .85; }
  100% { transform: scale(7);  opacity: 0; }
}

/* burst: particles thrown outward on --dx / --dy, set per particle by script */
.cel-spark {
  position: absolute;
  z-index: 1;
  left: 50%; top: 50%;
  width: 7px; height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border-radius: 50%;
  background: #FFFFFF;
  opacity: 0;
  animation: celspark 1150ms cubic-bezier(.1, .7, .2, 1) both;
  pointer-events: none;
}
@keyframes celspark {
  0%   { transform: none;                              opacity: 1; }
  100% { transform: translate(var(--dx), var(--dy)) scale(.2); opacity: 0; }
}

/* the finale wears both countries' colours in its ground */
.cel.finale {
  background:
    radial-gradient(85% 65% at 50% 38%, rgba(200, 162, 39, .30) 0%, #04121D 72%),
    #04121D;
}
.cel.finale .cel-glyph { animation-duration: 900ms; }

/* ---------------------------------------------------------------- calm --- */
/* A celebration you earned is content you asked for, so the board still spells
   the name and the sounds still fire. What goes is the involuntary motion: the
   sweeps, the loops and the things that fly. */
:root[data-motion="reduce"] .cel { animation: celin 200ms ease-out both; }
/* the wash stays, the breathe goes */
:root[data-motion="reduce"] .cel::after { animation: none; opacity: .34; }
:root[data-motion="reduce"] :is(.cel-card, .cel-glyph) { animation: none; }
:root[data-motion="reduce"] :is(.cel-flap.turn, .cel-flap.set) { animation: none; }
:root[data-motion="reduce"] .cel-name.lit::after { display: none; }
:root[data-motion="reduce"] :is(.cel-radar, .cel-scanbar, .cel-ring, .cel-spark) { display: none; }
