/*
 * Title cards — the "moment" component.
 *
 * Retheme phases 2 through 5 all wanted the same thing: a full-bleed card that
 * names what just happened and gets out of the way. The descent beginning, a
 * tier turning over, the last Ancient falling. Building them as one component
 * rather than four is the whole reason they could ship together.
 *
 * Rules it follows:
 *  · It NEVER blocks input. Pointer-events are off and the game stays live
 *    underneath — a card game with a modal between turns is a slideshow.
 *  · It is skippable by existing: it fades on a timer, and any click or key
 *    dismisses it early.
 *  · Colour comes from theme tokens, so a moment looks like the skin it
 *    interrupted. The one exception is Consumed, which is fixed red for the
 *    same reason the defeat screen is.
 */

.moment {
  position: fixed; inset: 0; z-index: 55;
  display: grid; place-items: center;
  pointer-events: none;
  text-align: center;
  padding: 2rem;
}
.moment__veil {
  position: absolute; inset: 0;
  /* Darker than it was (.92/.5). A moment never blocks input, so the board
     stays live underneath it -- which means the veil is the only thing making
     the card readable against a busy table. */
  background:
    radial-gradient(58% 44% at 50% 50%, rgb(var(--ui-900-rgb) / .97) 0%, transparent 74%),
    rgb(var(--ui-900-rgb) / .72);
  animation: moment-veil var(--moment-life, 3.4s) ease-out both;
}
.moment__inner { position: relative; animation: moment-rise var(--moment-life, 3.4s) ease-out both; }

.moment__kick {
  font-size: .68rem; letter-spacing: .38em; text-transform: uppercase;
  color: rgb(var(--ui-accent-rgb));
  margin-bottom: .9rem;
}
.moment__title {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 8vw, 4.6rem);
  line-height: 1; font-weight: 600; letter-spacing: -.02em;
  color: rgb(var(--ui-text-100-rgb));
  margin: 0;
  text-shadow: 0 0 40px rgb(var(--ui-900-rgb)), 0 2px 4px rgb(0 0 0 / .5);
}
.moment__line {
  margin: 1rem auto 0; max-width: 30rem;
  font-size: 1.05rem; line-height: 1.55;
  color: rgb(var(--ui-text-300-rgb));
}
.moment__rule {
  width: 7rem; height: 1px; margin: 1.5rem auto 0;
  background: rgb(var(--ui-accent-rgb) / .55);
}

/* Victory earns the accent; the tiers stay in the text ramp. */
.moment--win .moment__title { color: rgb(var(--ui-accent-hi-rgb)); }

/* A RULE, THE FIRST TIME YOU MEET IT. Quieter and smaller than a tier card,
   and it sits at the FOOT of the screen rather than over the middle of it: a
   tier moment announces something that has happened to the board, and this
   explains something the board is already showing you. It must not cover the
   thing it is describing.
   It never blocks input either -- `.moment` is `pointer-events: none` and the
   board stays live underneath, which is the rule the whole component runs on. */
.moment--rule { align-items: flex-end; padding-bottom: 6.5rem; }
.moment--rule .moment__veil { opacity: .35; }
.moment--rule .moment__inner { max-width: 30rem; }
.moment--rule .moment__title { font-size: 1.5rem; }
.moment--rule .moment__line { font-size: .9375rem; }
@media (max-width: 46rem) {
  .moment--rule { padding-bottom: 9rem; }
}

@keyframes moment-veil {
  0% { opacity: 0 } 12% { opacity: 1 } 72% { opacity: 1 } 100% { opacity: 0 }
}
@keyframes moment-rise {
  0%   { opacity: 0; transform: translateY(1.1rem) scale(.97); }
  14%  { opacity: 1; transform: none; }
  72%  { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateY(-.7rem) scale(1.01); }
}

@media (prefers-reduced-motion: reduce) {
  .moment__veil, .moment__inner { animation-duration: var(--moment-life, 3.4s); animation-timing-function: steps(1); }
}

/* ── Consumed: what is left of you ──────────────────────────────────────────
 *
 * The same figure that sat beside your name all game, coming apart. It burns
 * off from the FEET UP, which is the direction that reads as collapse — top
 * down reads as a curtain, and a straight fade reads as a bug.
 *
 * The mask does the disappearing and a blur does the smoke, so there is no
 * particle system and nothing to keep in memory: four motes drift off, the
 * crumbs settle, and the whole thing is over in two and a half seconds and
 * never loops. Death should not be a spinner. */
.dust {
  position: relative;
  width: 7.5rem; height: 9.8rem;
  margin: 0 auto 1.5rem;
}
/* Specific enough to beat .unbound's token width. The figure shares that
   class on purpose — it is the same drawing — but at portrait size it must
   fill the frame, and `width: 1.6rem` was quietly winning. */
.dust .dust__figure {
  position: absolute; inset: 0; width: 100%; height: 100%;
  color: #e9c9c4;
}
.dust .dust__figure svg { display: block; width: 100%; height: 100%; }

/* The figure is a crowd of points, so it does not need a mask sliding over it
   to come apart — the points simply leave, each on its own drift and its own
   delay. That is the whole reason this drawing replaced the silhouette: the
   dissolve is now the thing itself rather than an effect applied to it.
   --i, --dx and --dy are carried by every circle from unbound.js. */
.dust .dust__figure circle {
  animation: dot-leave 1.7s cubic-bezier(.32, 0, .6, 1) forwards;
  animation-delay: calc(var(--i) * 8ms + .35s);
}
@keyframes dot-leave {
  0%   { transform: none;                              opacity: 1; }
  35%  { opacity: .95; }
  100% { transform: translate(var(--dx), var(--dy));   opacity: 0; }
}

/* What comes off it. Four, not forty — enough to read as matter leaving. */
.dust__mote {
  position: absolute; bottom: 18%;
  width: 3px; height: 3px; border-radius: 50%;
  background: #d9b6b0; opacity: 0;
  animation: mote 2.6s ease-out forwards;
}
.dust__mote--1 { left: 32%; animation-delay: .7s; }
.dust__mote--2 { left: 46%; animation-delay: 1.1s; width: 2px; height: 2px; }
.dust__mote--3 { left: 58%; animation-delay: .95s; }
.dust__mote--4 { left: 41%; animation-delay: 1.45s; width: 2px; height: 2px; }
@keyframes mote {
  0%   { transform: none; opacity: 0; }
  18%  { opacity: .8; }
  100% { transform: translate(var(--drift, 14px), -68px); opacity: 0; }
}
.dust__mote--2 { --drift: -18px; }
.dust__mote--4 { --drift: -9px; }

/* And what stays. It arrives as the figure goes and then does not move --
 * the screen should settle on the leavings, not on the leaving. */
/* What stays. Distinct bits, not a bar: the first version scaled a set of
   gradients on X, which squashed them into one smear. They fade up in place
   instead, and the sizes are uneven because a tidy row of four reads as a
   pattern rather than as debris. */
.dust__crumbs {
  position: absolute; left: 50%; bottom: 3%;
  width: 66%; height: 12%;
  transform: translateX(-50%);
  opacity: 0;
  background:
    radial-gradient(ellipse 9% 22% at 14% 62%, #c9a49e 0 100%, transparent 0),
    radial-gradient(ellipse 6% 15% at 28% 84%, #a8837d 0 100%, transparent 0),
    radial-gradient(ellipse 13% 30% at 44% 70%, #b8938d 0 100%, transparent 0),
    radial-gradient(ellipse 5% 12% at 58% 88%, #d3aca6 0 100%, transparent 0),
    radial-gradient(ellipse 10% 24% at 71% 64%, #c0968f 0 100%, transparent 0),
    radial-gradient(ellipse 4% 10% at 86% 80%, #a8837d 0 100%, transparent 0);
  filter: blur(.3px);
  animation: crumbs 1.6s 1.35s ease-out forwards;
}
@keyframes crumbs {
  0%   { opacity: 0; }
  100% { opacity: .9; }
}

@media (prefers-reduced-motion: reduce) {
  .dust .dust__figure circle { animation: none; opacity: .3; }
  .dust__mote { display: none; }
  .dust__crumbs { animation: none; opacity: .85; transform: translateX(-50%); }
}


/* The hand that banished it, between the name and the line. Real chips rather
   than a sentence naming cards: the deck already knows how to draw one, and a
   moment that says "6S + AC" is asking the reader to translate. */
.moment__cards {
  display: flex; justify-content: center; flex-wrap: wrap; gap: .35rem;
  margin: .9rem 0 0;
}
.moment__cards .chip { font-size: 1rem; padding: .25em .5em; }
