/* levelup.css - the two moments worth stopping for.
 *
 * Loaded after juice.css. Everything here lives in one fixed-position overlay
 * that is display:none until levelup.js shows it, so it can neither push a
 * pixel of the app nor add a scrollbar. Only transform and opacity animate -
 * this runs on an iPad mini and a layout animation there is a stutter.
 *
 * Every color is a token from styles.css, with one exception stated below: the
 * three trophy metals, which have to match the trophy case exactly.
 */

.cinema {
  /* Bronze, silver and gold are the only literal colors in this file. They are
     the same values .badge.t1/.t2/.t3 uses in styles.css, because the medal in
     this overlay and the tile in the trophy case are the same trophy. */
  --metal-1: #a9703f;
  --metal-2: #b9c2cc;
  --metal-3: #f4c04a;
  --metal: var(--line);
  --metal-was: var(--line);

  position: fixed;
  inset: 0;
  /* Over every other celebration layer - confetti 50, juice canvas 52, flash
     55, toast 60, banner 70, tint 95 - but under the vignette (98) and the CRT
     scanlines (99), so the skin still reads across the moment. */
  z-index: 96;
  display: none;
  place-items: center;
  padding: 24px;
  overflow: hidden;
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
  cursor: pointer;
}
.cinema.on { display: grid; }
/* On its way out it stops taking taps. The fade is a quarter of a second, and a
   quarter of a second of an invisible overlay eating the press that was meant
   for the button underneath is the same dead button, just briefer. */
.cinema.out { animation: cin-out 260ms linear forwards; pointer-events: none; }
@keyframes cin-out { to { opacity: 0; } }

/* The tier medal starts in the metal he had and finishes in the one he just
   earned, so the promotion is a change of metal rather than a new object. */
.cinema[data-tier="1"] { --metal: var(--metal-1); --metal-was: var(--line); }
.cinema[data-tier="2"] { --metal: var(--metal-2); --metal-was: var(--metal-1); }
.cinema[data-tier="3"] { --metal: var(--metal-3); --metal-was: var(--metal-2); }

/* One overlay, two moments. The one that is not playing is not in the box. */
.cinema[data-kind="level"] .cin-tier,
.cinema[data-kind="tier"] .cin-level { display: none; }

/* ----------------------------------------------------------------- backdrop */

.cin-back {
  position: absolute;
  inset: 0;
  background: var(--page);
  opacity: .97;                 /* not solid: the app is still there behind him */
  animation: cin-fade 220ms ease-out both;
}
@keyframes cin-fade { from { opacity: 0; } }

/* The ground each moment stands on, and the quickest way to tell them apart
   before a word is read: the level up turns a wheel of spokes, the tier up
   lights one spot and holds still under it. */
.cin-field {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

.cinema[data-kind="level"] .cin-field {
  /* Huge, so no edge of the wheel can ever come into shot. */
  width: 200vmax;
  height: 200vmax;
  background: repeating-conic-gradient(from 0deg, var(--shade) 0deg 4deg, transparent 4deg 16deg);
  animation: cin-spin 26s linear infinite;
}
/* The middle is emptied out so the number sits on quiet ground. */
.cinema[data-kind="level"] .cin-field::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(closest-side, var(--bg) 7%, transparent 40%);
}
@keyframes cin-spin {
  from { transform: translate(-50%, -50%) rotate(0deg); }
  to   { transform: translate(-50%, -50%) rotate(360deg); }
}

.cinema[data-kind="tier"] .cin-field {
  width: 150vmin;
  height: 150vmin;
  background: radial-gradient(closest-side, var(--shade) 0%, transparent 68%);
  animation: cin-bloom 900ms cubic-bezier(.2, .8, .25, 1) both;
}
@keyframes cin-bloom { from { transform: translate(-50%, -50%) scale(.45); opacity: 0; } }

/* The confetti canvas lives at z-index 50, which is under this overlay, so
   while a moment is playing it is lifted over the backdrop - and back down
   afterwards. Still under the vignette and the scanlines. */
body.cinema-on .confetti { z-index: 97; }

/* -------------------------------------------------------------------- stage */

.cin-stage {
  position: relative;
  width: 100%;
  max-width: min(92vw, 620px);
  max-height: 100%;
  text-align: center;
}

/* Each moment stacks its own pieces, so the panel that is not playing takes no
   room and neither of them has to know about the other. */
.cin-level { display: grid; justify-items: center; gap: 12px; }
/* A little more air than the level panel: every line here is a different kind
   of thing - a medal, a rank of three, a metal, a trophy, a count. */
.cin-tier { display: grid; justify-items: center; gap: 14px; }

/* Every animation below starts from a keyframe and ends at the element's own
   style, so with motion off - where styles.css kills animation outright - the
   panel is already in its finished state. Nothing here is hidden by default. */

.cin-kicker {
  font-family: var(--pixel);
  /* The pixel face loses its strokes below 12px, so that is the floor rather
     than the 10px a short viewport used to fall to. */
  font-size: clamp(12px, 2.1vmin, 14px);
  line-height: 1;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--on-bright);
  background: var(--hot);
  padding: 8px 14px;
  border: 2px solid var(--drop);
  border-radius: var(--radius);
  box-shadow: 0 4px 0 var(--drop);
  animation: cin-drop 360ms cubic-bezier(.2, .9, .25, 1) both;
}
@keyframes cin-drop { from { transform: translateY(-18px) scale(.86); opacity: 0; } }

/* ------------------------------------------------------- 1. level up: arrival */

/* The number lands. It comes in far too big and slams down to size, which is
   the whole idea of the moment: he has arrived somewhere. */
.cin-num {
  font-family: var(--num);
  font-variation-settings: var(--num-set);
  font-variant-numeric: tabular-nums;
  font-weight: 900;
  font-size: clamp(72px, 26vmin, 190px);
  line-height: .96;
  color: var(--turq);
  text-shadow: var(--glow), 0 6px 0 var(--drop);
  animation: cin-slam 520ms cubic-bezier(.16, 1.35, .3, 1) 140ms both;
}
@keyframes cin-slam { from { transform: scale(2.7); opacity: 0; } }

.cin-rank {
  font-family: var(--pixel);
  font-size: clamp(15px, 4.1vmin, 29px);
  line-height: 1.35;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink);
  text-shadow: 0 4px 0 var(--drop);
  max-width: 100%;
  /* "Hall of fame" is the longest rank there is. It wraps rather than clips,
     because a clipped rank name is worse than a rank name on two lines. */
  overflow-wrap: break-word;
  animation: cin-rise 420ms cubic-bezier(.2, .8, .25, 1) 420ms both;
}
@keyframes cin-rise { from { transform: translateY(24px); opacity: 0; } }

.cin-bar {
  width: min(280px, 70%);
  height: 4px;
  background: var(--turq);
  box-shadow: var(--glow);
  border-radius: 2px;
  animation: cin-wipe 420ms cubic-bezier(.2, .8, .25, 1) 520ms both;
}
@keyframes cin-wipe { from { transform: scaleX(0); } }

.cin-from {
  font-family: var(--body);
  font-size: clamp(15px, 2.4vmin, 19px);
  color: var(--muted);
  animation: cin-rise 380ms ease-out 700ms both;
}

/* --------------------------------------------------- 2. tier up: a promotion */

/* Not a slam. The medal lifts into place and the new metal floods up over the
   old one, so it reads as the same trophy being upgraded, not a new one won. */
.cin-medal {
  position: relative;
  width: clamp(120px, 32vmin, 220px);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: var(--sunk);
  border: 3px solid var(--drop);
  box-shadow: 0 8px 0 var(--drop), 0 0 34px var(--shade);
  animation: cin-lift 480ms cubic-bezier(.2, .9, .25, 1) both;
}
@keyframes cin-lift { from { transform: translateY(46px) scale(.8); opacity: 0; } }

.cin-was { position: absolute; inset: 0; background: var(--metal-was); }
.cin-now {
  position: absolute;
  inset: 0;
  background: var(--metal);
  transform-origin: 50% 100%;
  animation: cin-promote 560ms cubic-bezier(.3, .9, .2, 1) 320ms both;
}
@keyframes cin-promote { from { transform: scaleY(0); } }

.cin-icon {
  position: relative;
  font-size: clamp(48px, 14vmin, 100px);
  line-height: 1;
  filter: drop-shadow(0 3px 0 var(--drop));
}

/* The struck-metal sweep, once the fill has finished. It ends off the medal. */
.cin-shine {
  position: absolute;
  top: -30%;
  bottom: -30%;
  left: 0;
  right: 0;
  background: linear-gradient(115deg, transparent 38%, var(--ink) 50%, transparent 62%);
  opacity: .4;
  /* A sheen is something to look through, not something to hit. It is laid over
     the badge and the tier name for the length of its sweep, so without this it
     is what a tap on the trophy lands on. */
  pointer-events: none;
  transform: translateX(130%);
  animation: cin-shine 760ms ease-in-out 700ms both;
}
@keyframes cin-shine {
  from { transform: translateX(-130%); }
  to   { transform: translateX(130%); }
}

/* Three of three. The pips say how far up the trophy he is, which is the part
   a single toast never told him. */
.cin-pips { display: flex; gap: 12px; }
.cin-pips i {
  width: 16px;
  height: 16px;
  border-radius: 3px;
  background: var(--sunk);
  border: 2px solid var(--line);
}
.cin-pips i:nth-child(1) { background: var(--metal-1); border-color: var(--metal-1); }
.cinema[data-tier="2"] .cin-pips i:nth-child(2),
.cinema[data-tier="3"] .cin-pips i:nth-child(2) { background: var(--metal-2); border-color: var(--metal-2); }
.cinema[data-tier="3"] .cin-pips i:nth-child(3) { background: var(--metal-3); border-color: var(--metal-3); }

/* Only the pip he just lit pops. */
.cinema[data-tier="1"] .cin-pips i:nth-child(1),
.cinema[data-tier="2"] .cin-pips i:nth-child(2),
.cinema[data-tier="3"] .cin-pips i:nth-child(3) {
  animation: cin-pop 360ms cubic-bezier(.2, 1.4, .3, 1) 820ms both;
}
@keyframes cin-pop { from { transform: scale(.2); opacity: 0; } }

.cin-tier-name {
  font-family: var(--pixel);
  font-size: clamp(12px, 2.6vmin, 18px);
  line-height: 1;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--on-bright);
  background: var(--metal);
  padding: 9px 16px;
  border: 2px solid var(--drop);
  border-radius: var(--radius);
  box-shadow: 0 4px 0 var(--drop);
  animation: cin-rise 380ms cubic-bezier(.2, .8, .25, 1) 620ms both;
}

.cin-trophy {
  font-family: var(--pixel);
  font-size: clamp(13px, 3.1vmin, 22px);   /* pixel face, already over the floor */
  line-height: 1.4;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink);
  text-shadow: 0 4px 0 var(--drop);
  max-width: 100%;
  overflow-wrap: break-word;
  animation: cin-rise 380ms ease-out 720ms both;
}

.cin-count {
  font-family: var(--body);
  font-size: clamp(15px, 2.4vmin, 19px);
  color: var(--muted);
  animation: cin-rise 380ms ease-out 820ms both;
}
.cin-count b {
  font-family: var(--num);
  font-variation-settings: var(--num-set);
  font-variant-numeric: tabular-nums;
  font-weight: 900;
  font-size: 1.25em;
  color: var(--ink);
}

.cin-hide { display: none; }

/* --------------------------------------------------------------- tap to skip */

/* Said out loud, because a cutscene he cannot leave is a tax on the sixth set
   of the night. */
.cin-tap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: max(16px, env(safe-area-inset-bottom));
  text-align: center;
  font-family: var(--body);
  /* "Tap to skip" is the only way out of a cutscene, so it cannot be the
     smallest thing on it. */
  font-size: clamp(15px, 2vmin, 17px);
  letter-spacing: .08em;
  color: var(--muted);
  animation: cin-fade 400ms ease-out 900ms both;
}

/* ------------------------------------------------------------ motion off */

/* The same thing styles.css does everywhere else, chosen rather than inherited.
   styles.css already kills every animation under [data-motion="off"], so all
   that is left is to take away the two pieces that are only motion: the
   spinning spokes and the metal sweep. What he gets is a still panel he taps. */
:root[data-motion="off"] .cin-field,
:root[data-motion="off"] .cin-shine { display: none; }

@media (prefers-reduced-motion: reduce) {
  .cin-field, .cin-shine { display: none; }
  .cinema, .cinema * { animation: none !important; transition: none !important; }
}
