/* ============================================================================
   game-outrank.css — visual layer owned exclusively by outrank.
   Loaded only on outrank pages, after site.css / themes.css / games.css, so rules
   here win without touching any shared stylesheet.
   Direction: a TV game-show podium reveal running at arcade speed.
   ========================================================================== */

/* ============================================================================
   0. THE SET
   Two divs on a page become two podiums on a stage: a dark studio backdrop
   with a vignette, a horizon where the cyclorama meets the floor, a lit floor
   the podiums cast a contact shadow onto, and a spotlight pool behind each.

   #stage has its innerHTML replaced every round, so the set is built entirely
   from the element's own background layers plus ::before — both survive.
   Colours are mixed off --bg-deep / --surface-2 / --accent / --good, so the
   set darkens in noir, goes hot in neon and becomes a grey daytime studio in
   paper, without a single per-theme override.
   ========================================================================== */
body[data-game=outrank] #stage.duel-stage{
  --set-back:color-mix(in oklch, var(--bg-deep), black 14%);
  --set-floor:color-mix(in oklch, var(--surface-2), black 8%);
  --set-pool:color-mix(in oklch, var(--accent), transparent 84%);
  --set-vig:color-mix(in oklch, black, transparent 62%);
  position:relative;overflow:hidden;
  padding:clamp(1.1rem,3vw,1.9rem) clamp(.9rem,2.4vw,1.5rem) clamp(1.7rem,4vw,2.5rem);
  background:
    /* spotlight pools washing the floor behind each podium */
    radial-gradient(46% 40% at 27% 62%, var(--set-pool), transparent 72%),
    radial-gradient(46% 40% at 73% 62%, var(--set-pool), transparent 72%),
    /* the floor, catching more light than the wall */
    linear-gradient(to bottom,
      transparent 0 58%,
      color-mix(in oklch,var(--set-floor),transparent 24%) 58.4%,
      var(--set-floor) 100%),
    /* horizon: where the cyclorama meets the deck */
    linear-gradient(to bottom,
      transparent calc(58% - 1px),
      color-mix(in oklch,var(--line),transparent 15%) 58%,
      transparent calc(58% + 1px)),
    /* vignette + backdrop */
    radial-gradient(125% 105% at 50% 34%, transparent 38%, var(--set-vig) 100%),
    linear-gradient(to bottom, var(--set-back), color-mix(in oklch,var(--set-back),var(--surface) 26%));
}
/* ARM C is a DAYTIME studio: a light cyclorama, a barely-there rig and a
   whisper of a pool. Darkening the set the way noir and neon do would drop the
   divider's muted type below AA against a light wall, so paper inverts the
   direction of every wash instead of inheriting it. */
:root[data-theme="c"] body[data-game=outrank] #stage.duel-stage{
  --set-back:var(--surface);
  --set-floor:color-mix(in oklch, var(--surface-2), var(--surface) 40%);
  --set-pool:color-mix(in oklch, var(--accent), transparent 93%);
  --set-vig:color-mix(in oklch, black, transparent 91%);
}
:root[data-theme="c"] body[data-game=outrank] #stage.duel-stage::before{opacity:.3}
@keyframes or-rig-paper{
  0%,100%{opacity:.20;transform:scaleX(1)}
  50%{opacity:.36;transform:scaleX(1.05)}
}
@media (prefers-reduced-motion: no-preference){
  :root[data-theme="c"] body[data-game=outrank]:not([data-fx=off]) #stage.duel-stage::before{
    animation-name:or-rig-paper;
  }
}
/* the lighting rig: two soft cones from above, gently breathing */
body[data-game=outrank] #stage.duel-stage::before{
  content:'';position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(38% 62% at 27% 6%, color-mix(in oklch,var(--accent),transparent 82%), transparent 74%),
    radial-gradient(38% 62% at 73% 6%, color-mix(in oklch,var(--good),transparent 86%), transparent 74%);
  opacity:.72;
}
@media (prefers-reduced-motion: no-preference){
  body[data-game=outrank]:not([data-fx=off]) #stage.duel-stage::before{
    animation:or-rig 9.5s ease-in-out infinite;
  }
}
@keyframes or-rig{
  0%,100%{opacity:.52;transform:scaleX(1)}
  50%{opacity:.88;transform:scaleX(1.05)}
}
/* podiums: lit from above, planted on the floor with a contact shadow.
   NB: background is deliberately left alone — games.css repaints it on
   [data-state=high|low] and that reveal must keep winning. */
body[data-game=outrank] .pick{
  z-index:1;
  border-bottom-width:5px;
  box-shadow:
    var(--edge),
    inset 0 16px 26px -16px color-mix(in oklch,white,transparent 74%),
    0 20px 26px -16px rgb(0 0 0/.55),
    var(--sh-2);
}
body[data-game=outrank] .pick:hover{
  box-shadow:
    var(--edge),
    inset 0 16px 26px -16px color-mix(in oklch,white,transparent 66%),
    0 24px 30px -16px rgb(0 0 0/.6),
    var(--sh-3),var(--glow);
}
/* the plinth each podium stands on */
body[data-game=outrank] .pick::before{
  content:'';position:absolute;z-index:-1;
  left:7%;right:7%;bottom:-9px;height:11px;
  border-radius:0 0 var(--r-m) var(--r-m);
  background:linear-gradient(to bottom,
    color-mix(in oklch,var(--surface),black 18%),
    color-mix(in oklch,var(--bg-deep),black 26%));
  box-shadow:0 8px 14px -6px rgb(0 0 0/.6);
}
/* stacked phone layout puts the podiums nose-to-tail — a plinth would hang
   over the card below it, so the stage keeps only its contact shadow there */
@media(max-width:560px){
  body[data-game=outrank] .pick::before{display:none}
}
/* the divider is set dressing, not floor — keep it above the rig */
body[data-game=outrank] .or{position:relative;z-index:1}
body[data-game=outrank] #prompt{position:relative;z-index:1}

/* ---------- 1. permanent rule strip (kills first-timer ambiguity) ---------- */
.or-rule{
  text-align:center;font-family:var(--mono);font-size:.68rem;font-weight:600;
  letter-spacing:.22em;text-transform:uppercase;color:var(--muted);
  margin:0 0 .55rem;user-select:none;
}
.or-rule b{color:var(--good);font-weight:700}

/* ---------- 2. value-bar duel under each .pick-val ---------- */
.pick-bar{
  display:block;width:min(78%,180px);height:6px;border-radius:var(--r-pill);
  margin-top:.4rem;overflow:hidden;
  background:color-mix(in oklch,var(--line),transparent 45%);
}
.pick-bar i{
  display:block;height:100%;border-radius:inherit;background:var(--line);
  transform:scaleX(0);transform-origin:left center;
  transition:transform 620ms cubic-bezier(.22,1,.36,1);
  will-change:transform;
}
.pick[data-state=high] .pick-bar i{background:var(--good);box-shadow:0 0 8px color-mix(in oklch,var(--good),transparent 45%)}
.pick[data-state=low]  .pick-bar i{background:var(--line)}

/* ---------- 3. staged reveal — winner pops, loser fades to grey ---------- */
/* winner value finishing pop (added by JS when the count-up lands) */
.pick-val.val-pop{animation:orValPop 220ms var(--ease-pop)}
@keyframes orValPop{0%{transform:scale(1)}50%{transform:scale(1.18)}100%{transform:scale(1)}}

/* winner card flash: 2px --good ring + 12px glow for 500ms, then relaxes */
.pick{transition:transform var(--t-base) var(--ease-out),border-color var(--t-base),
  box-shadow 320ms ease,background var(--t-base),filter 400ms ease,opacity 400ms ease}
.pick.win-flash{
  border-color:var(--good);
  box-shadow:0 0 0 1px var(--good),0 0 12px color-mix(in oklch,var(--good),transparent 40%),var(--edge);
}
/* loser desaturates on top of games.css opacity:.72 */
.pick[data-state=low]{filter:saturate(.4)}

/* ---------- 4. wrong-answer world dim ---------- */
#stage{transition:filter 400ms ease}
#stage.world-dim{filter:saturate(.25) brightness(.88)}

/* ---------- 5. pips: taller, verdict glyphs, live pulse ---------- */
.pip{width:24px;height:8px;display:grid;place-items:center;position:relative}
.pip .pip-g{
  font-size:8px;line-height:1;font-family:var(--mono);font-weight:700;
  color:oklch(0.14 0.02 var(--hue, 255));pointer-events:none;
}
.pip[data-s=now]{animation:orPipNow 900ms ease-in-out infinite}
@keyframes orPipNow{
  0%,100%{transform:scaleY(1);box-shadow:0 0 10px var(--accent)}
  50%{transform:scaleY(1.35);box-shadow:0 0 16px var(--accent)}
}

/* clean-sweep gold ripple, staggered 40ms per pip via --i (set inline by JS) */
.pip.gold{
  background:var(--gold);box-shadow:0 0 12px var(--gold);
  animation:orPipGold 420ms var(--ease-pop) both;
  animation-delay:calc(var(--i,0)*40ms);
}
@keyframes orPipGold{
  0%{transform:scale(1)}
  45%{transform:scale(1.6)}
  100%{transform:scale(1)}
}

/* ---------- 6. streak escalation: combo ≥5 cards enter with a Y-flip ---------- */
#stage.hot{perspective:900px}
#stage.hot .pick{
  animation:orFlipIn 280ms var(--ease-pop) both;
  backface-visibility:hidden;
}
#stage.hot .pick[data-k=b]{animation-delay:60ms}
@keyframes orFlipIn{
  0%{transform:rotateY(90deg);opacity:0}
  70%{transform:rotateY(-8deg);opacity:1}
  100%{transform:rotateY(0)}
}

/* ---------- 7. signature moment: CLEAN SWEEP overlay ---------- */
.sweep{position:fixed;inset:0;z-index:70;display:grid;place-items:center;pointer-events:none}
.sweep-txt{animation:orSweep 900ms var(--ease-pop) both}
.sweep-txt>span{font-size:clamp(2.2rem,9vw,3.2rem);white-space:nowrap}
@keyframes orSweep{
  0%{transform:scale(.4);opacity:0}
  16%{transform:scale(1.12);opacity:1}
  26%{transform:scale(1)}
  78%{transform:scale(1);opacity:1}
  100%{transform:scale(1.05);opacity:0}
}

/* ============================================================================
   FX gates — every decorative move dies under reduced-motion or data-fx=off.
   Value bars still snap to their (informative) final width; nothing animates.
   ========================================================================== */
@media (prefers-reduced-motion: reduce){
  .pick-val.val-pop,.pip[data-s=now],.pip.gold,#stage.hot .pick,.sweep-txt{animation:none !important}
  .pick-bar i{transition:none}
  .pick{transition-property:border-color,box-shadow}
  .pick[data-state=low]{filter:none}
  #stage{transition:none}
  #stage.world-dim{filter:none}
}
body[data-fx="off"] .pick-val.val-pop,
body[data-fx="off"] .pip[data-s=now],
body[data-fx="off"] .pip.gold,
body[data-fx="off"] #stage.hot .pick,
body[data-fx="off"] .sweep-txt{animation:none !important}
body[data-fx="off"] .pick-bar i{transition:none}
body[data-fx="off"] .pick{transition-property:border-color,box-shadow}
body[data-fx="off"] .pick[data-state=low]{filter:none}
body[data-fx="off"] #stage{transition:none}
body[data-fx="off"] #stage.world-dim{filter:none}

/* ---------- 8. margin readout in the divider (the round's verdict) ---------- */
.or[data-band]{gap:.28rem;line-height:1.15}
.or .or-gap{font-size:.9rem;font-weight:700;letter-spacing:.04em;color:var(--text)}
.or .or-band{font-size:.6rem;letter-spacing:.18em;text-transform:uppercase;color:var(--muted)}
.or[data-band=coin] .or-gap{color:var(--gold)}
.or[data-band=coin] .or-band{color:var(--gold)}
.or[data-band=clear] .or-gap{color:var(--good)}
.or .or-next{
  margin-top:.35rem;font-size:.55rem;letter-spacing:.16em;text-transform:uppercase;
  color:var(--muted);opacity:.72;
}
@media(prefers-reduced-motion:no-preference){
  body:not([data-fx=off]) .or .or-next{animation:or-cue 1.6s ease-in-out infinite}
  @keyframes or-cue{0%,100%{opacity:.35}50%{opacity:.85}}
}

/* ---------- 9. per-round accounting on the result sheet ---------- */
.sheet .or-misses{margin:.5rem 0 0;line-height:1.45}
.sheet .or-misses b{font-family:var(--mono)}
.sheet .or-row{display:block;margin:.3rem 0;line-height:1.4}
.sheet .or-mark{display:inline-block;width:1.1em;font-weight:700;color:var(--muted)}
.sheet .or-row[data-got=y] .or-mark{color:var(--good)}
.sheet .or-row[data-got=n] .or-mark{color:var(--danger)}
.sheet .or-side.win{color:var(--text);font-weight:600}
.sheet .or-side:not(.win){opacity:.62}
.sheet .or-rowgap{font-family:var(--mono);font-size:.82em;color:var(--muted);white-space:nowrap}
.sheet .or-row[data-band=coin] .or-rowgap{color:var(--gold)}
