/* ═══════════════════════════════════════════════════════════════════════════
   patriot.plus LIVE, THE ARCADE.

   The second look a debate can wear (ARCADE.md §2). Loaded after debate.css on
   the projector and on the phone; every class here is prefixed `ar-`, and
   nothing here restyles a `db-` class, so taking this file off a page puts the
   house debate back untouched.

   ── IT IS BUILT FROM THE TOKENS, NOT FROM COLOURS ─────────────────────────
   Not one literal colour is chosen in this file except black and white at low
   alpha for depth, which every theme needs and no theme wants to pick. The
   ground, the ink, the edges, the accent and the two state colours all come
   from themes.css, so an officer running the Committee Room theme gets a sober
   arcade rather than an off-brand one, and a chapter with its own palette gets
   its own. The two SIDE colours come from debate.css's `--db-side`, which is
   set by `.db-s0` / `.db-s1` and never swaps: a room learns which end of the
   wall is which in about four seconds and then stops reading the labels.

   ── THE PROJECTOR IS ALWAYS DARK ──────────────────────────────────────────
   themes.js explains why there is no light projector register. Every `.sky`
   rule below therefore assumes a dark ground and uses the same display-type
   language the rest of the show uses: heavy Oswald, a hard offset in
   `--blue`, and a bloom.

   ── SIZED FOR THE BACK OF THE ROOM ────────────────────────────────────────
   Every projector size is `min(vw, vh)` so a 1280×720 hall projector and a 4K
   panel get the same picture rather than the same pixel counts, and nothing
   may grow past the frame: there is no scrollbar on a wall and nobody near
   enough to reach for one.

   It is the arcade. It is not named after, and does not imitate, any
   particular game.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════ AVATARS ═══════════════════════════
   The box sizes the face, not the other way round: `avatar.js` returns an SVG
   at whatever pixel size it was asked for, and on a wall that number is always
   going to be wrong. Letting CSS own the size means the arcade is correct
   whatever that renderer decides, and correct before it exists at all. */
.ar-ava { display: block; color: var(--db-side); line-height: 0; }
.ar-ava > svg { display: block; width: 100%; height: auto; }
/* The `''` fallback drawn by debate.js: a disc and a letter, in the side's own
   colour through `currentColor`. */
.ar-fallback text {
  font-family: var(--head); font-weight: 700; font-size: 128px;
  fill: currentColor; letter-spacing: .02em;
}

/* ═══════════════════════════ THE PROJECTOR ═══════════════════════════ */
.sky .ar-pj {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2vh; width: 100%; text-align: center;
}
.sky .ar-kick {
  font-family: var(--head); font-weight: 600; letter-spacing: .34em; text-transform: uppercase;
  color: var(--gold); font-size: min(2vw, 3.1vh); text-shadow: 0 2px 12px rgba(0, 0, 0, .9);
}
/* The grid floor is at its brightest along the bottom of the frame, which is
   exactly where this line sits. */
.sky .ar-note {
  font-family: var(--head); letter-spacing: .14em; text-transform: uppercase;
  color: var(--sky-muted); opacity: .82; font-size: min(1.7vw, 2.7vh); max-width: 60ch;
  text-shadow: 0 2px 10px rgba(0, 0, 0, .9);
}

/* ── the display face: gold, skewed, with the house's hard offset ──
   One rule rather than three, so VS, K.O. and the winner's call can never
   drift apart. */
.sky .ar-vs span,
.sky .ar-ko span {
  display: inline-block; transform: skewX(-8deg);
  font-family: var(--head); font-weight: 700; text-transform: uppercase; line-height: .88;
  color: var(--gold); letter-spacing: .02em;
  text-shadow: var(--pj-bloom-gold), .7vh .7vh 0 var(--blue), -.2vh -.2vh 0 rgba(0, 0, 0, .55);
}

/* ═══════════ 1. THE VS SCREEN ═══════════ */
.sky .ar-pick { gap: 2.6vh; }
/* `stretch`, not `center`: two opposed things are the same size, whatever the
   length of the two names. */
.sky .ar-pick-row { display: flex; align-items: stretch; gap: min(2vw, 3vh); width: 100%; }
.sky .ar-fighter {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .7vh; padding: min(2.4vh, 2.4vw) min(1.4vw, 2vh);
  border: .45vh solid var(--db-side); background: var(--sky-card-bg);
  box-shadow: 0 0 6vh rgba(0, 0, 0, .55), inset 0 0 4vh rgba(0, 0, 0, .35);
}
.sky .ar-fighter.ar-empty { border-style: dashed; opacity: .72; }
.sky .ar-player {
  font-family: var(--head); font-weight: 700; letter-spacing: .3em; text-transform: uppercase;
  color: var(--db-side); font-size: min(1.6vw, 2.5vh);
}
.sky .ar-pick .ar-ava-xl { width: min(22vh, 17vw); }
.sky .ar-fighter-name {
  font-family: var(--head); font-weight: 700; text-transform: uppercase; line-height: .96;
  color: var(--show-ink); font-size: min(4.6vw, 7.2vh); width: 100%; overflow-wrap: anywhere;
  text-shadow: var(--pj-bloom), .5vh .5vh 0 var(--blue);
}
.sky .ar-fighter-side {
  width: 100%; font-family: var(--head); font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--db-side); font-size: min(2.2vw, 3.4vh);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The one sentence DEBATE.md §7 asks to be said out loud and then never
   written down. */
.sky .ar-fighter-tag {
  font-family: var(--head); letter-spacing: .16em; text-transform: uppercase;
  color: var(--sky-muted); font-size: min(1.6vw, 2.5vh);
}
.sky .ar-vs { flex: 0 0 auto; align-self: center; }
.sky .ar-vs span { font-size: min(8vw, 12vh); }

/* ═══════════ 2. THE FIGHT ═══════════
   Faces at the outer ends, bars filling outward from the middle, the clock
   between them. The bars are the room's reading and they carry NO caption:
   DEBATE.md §4 and §7, and ARCADE.md §2.1, all for the same reason: a bar
   that says WINNING makes people vote for who they think will win. */
.sky .ar-debate { gap: 2.4vh; }
.sky .ar-hud {
  display: grid; width: 100%; align-items: center;
  grid-template-columns: min(15vh, 11vw) minmax(0, 1fr) auto minmax(0, 1fr) min(15vh, 11vw);
  gap: min(1.4vw, 2.1vh);
}
.sky .ar-hud-p { display: flex; flex-direction: column; align-items: center; gap: .5vh; min-width: 0; }
.sky .ar-hud .ar-ava-md { width: 100%; }
.sky .ar-hud-name {
  width: 100%; font-family: var(--head); font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--show-ink); font-size: min(2vw, 3.1vh); line-height: 1.05;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* WHO HOLDS THE FLOOR. Lit and dimmed rather than a badge, because it has to
   be legible from the back row at a glance and a badge is a thing you read. */
.sky .ar-lit { filter: none; }
.sky .ar-lit .ar-ava { filter: drop-shadow(0 0 1.6vh var(--db-side)); }
.sky .ar-dim { opacity: .38; filter: grayscale(.7); }

.sky .ar-hp { min-width: 0; }
.sky .ar-hp-top {
  display: flex; align-items: baseline; gap: .8vw; margin-bottom: .6vh;
  font-family: var(--head); font-weight: 700; text-transform: uppercase;
}
.sky .ar-hp-label {
  flex: 1 1 auto; min-width: 0; letter-spacing: .1em; color: var(--db-side);
  font-size: min(2.2vw, 3.4vh); text-align: left;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sky .ar-hp-n {
  flex: 0 0 auto; font-variant-numeric: tabular-nums; color: var(--show-ink);
  font-size: min(2.4vw, 3.8vh); text-shadow: .3vh .3vh 0 var(--blue);
}
/* Side two reads outward from the right, so its label and number swap ends and
   the whole strip mirrors. */
.sky .ar-hp1 .ar-hp-top { flex-direction: row-reverse; }
.sky .ar-hp1 .ar-hp-label { text-align: right; }

.sky .ar-hp-track {
  position: relative; display: flex; height: min(5.6vh, 4.4vw); overflow: hidden;
  border: .35vh solid var(--sky-edge-3); background: var(--sky-well-2);
}
/* THE FILL IS ANCHORED AT THE CENTRE OF THE SCREEN and grows outward, towards
   its own fighter. Flex does the anchoring, so there is no absolute
   positioning to fall out of step with the border. */
.sky .ar-hp0 .ar-hp-track { justify-content: flex-end; }
.sky .ar-hp1 .ar-hp-track { justify-content: flex-start; }
.sky .ar-hp-track > i {
  position: relative; display: block; height: 100%; min-width: 0;
  background: var(--db-side); box-shadow: 0 0 2.2vh var(--db-side);
  transition: width .6s cubic-bezier(.2, .8, .2, 1);
}
/* A sheen and a fine rake, so a long flat bar still reads as an object rather
   than a rectangle of colour. */
.sky .ar-hp-track > i::after {
  content: ''; position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .42), rgba(255, 255, 255, 0) 46%,
      rgba(0, 0, 0, .3) 100%),
    repeating-linear-gradient(90deg, rgba(0, 0, 0, .18) 0 2px, rgba(0, 0, 0, 0) 2px 16px);
}
/* Nobody has voted yet: the bar is even and says so by being flat, not by
   being empty. An empty track reads as a broken screen. */
.sky .ar-hp.ar-even .ar-hp-track > i { opacity: .4; box-shadow: none; }

.sky .ar-clock { flex: 0 0 auto; padding: 0 min(1vw, 1.6vh); }
.sky .ar-clock-n {
  display: block; font-family: var(--head); font-weight: 700; font-variant-numeric: tabular-nums;
  line-height: .9; color: var(--show-ink); font-size: min(8vw, 11.5vh);
  text-shadow: var(--pj-bloom), .6vh .6vh 0 var(--blue);
}
.sky .ar-clock-n.db-low { color: var(--gold); }
.sky .ar-clock-n.db-out { color: var(--bad-lift); }
.sky .ar-clock-label {
  font-family: var(--head); letter-spacing: .24em; text-transform: uppercase;
  color: var(--sky-muted); font-size: min(1.5vw, 2.4vh); margin-top: .3vh;
}
.sky .ar-clock.ar-paused .ar-clock-n { opacity: .55; }

.sky .ar-turn {
  width: 100%; padding: min(1.8vh, 1.6vw) min(2vw, 3vh);
  border: .4vh solid var(--db-side); background: var(--sky-card-bg);
}
.sky .ar-turn-seg {
  font-family: var(--head); font-weight: 600; letter-spacing: .24em; text-transform: uppercase;
  color: var(--db-side); font-size: min(1.8vw, 2.8vh);
}
.sky .ar-turn-name {
  font-family: var(--head); font-weight: 700; text-transform: uppercase; line-height: .98;
  color: var(--show-ink); font-size: min(5.6vw, 8.8vh); overflow-wrap: anywhere;
  text-shadow: .5vh .5vh 0 var(--blue);
}
.sky .ar-turn-next {
  margin-top: .6vh; font-family: var(--head); letter-spacing: .12em; text-transform: uppercase;
  color: var(--sky-faint); font-size: min(1.6vw, 2.5vh);
}
.sky .ar-turn-next b { color: var(--sky-muted); font-weight: 700; }
.sky .ar-turn-next-side { color: var(--db-side); font-weight: 700; }

/* ═══════════ 3. THE FINISH ═══════════
   The splash is theatre and it sits ON TOP of the shift readout, never in
   place of it. The fairer measure stays on the wall. */
.sky .ar-verdict { gap: 1vh; }
.sky .ar-ko span { font-size: min(10vw, 13.5vh); }
/* A dead heat is not a smaller win. It gets the same weight and the neutral
   ink, so nothing on the screen implies a result the count did not produce. */
.sky .ar-ko-draw span { color: var(--show-ink); text-shadow: var(--pj-bloom), .7vh .7vh 0 var(--blue); }

.sky .ar-finish, .sky .ar-draw-pair {
  display: flex; align-items: flex-end; justify-content: center; gap: min(3vw, 4vh);
}
.sky .ar-draw-pair { align-items: flex-start; }
.sky .ar-winner, .sky .ar-loser { display: flex; flex-direction: column; align-items: center; gap: .4vh; min-width: 0; }
.sky .ar-winner .ar-ava-lg { width: min(24vh, 18vw); }
.sky .ar-loser .ar-ava-sm { width: min(11vh, 8vw); }
.sky .ar-loser { opacity: .42; filter: grayscale(.75); }
.sky .ar-winner-name {
  font-family: var(--head); font-weight: 700; text-transform: uppercase; line-height: 1;
  color: var(--show-ink); font-size: min(4vw, 6.2vh); overflow-wrap: anywhere;
  text-shadow: var(--pj-bloom-gold), .4vh .4vh 0 var(--blue);
}
.sky .ar-winner-side, .sky .ar-loser-name {
  font-family: var(--head); font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--db-side); font-size: min(1.6vw, 2.5vh);
}
.sky .ar-call {
  font-family: var(--head); font-weight: 700; letter-spacing: .22em; text-transform: uppercase;
  color: var(--gold); font-size: min(3vw, 4.6vh); line-height: 1;
  text-shadow: .4vh .4vh 0 var(--blue);
}
/* The shift block is debate.css's and is not restyled here beyond fitting it
   under a splash: the numbers a room argues about afterwards must look the
   same whichever look the officer chose. */
.sky .ar-verdict .db-shift { max-width: 1000px; }
.sky .ar-verdict .db-shift-row { font-size: min(2vw, 3.1vh); }
.sky .ar-verdict .db-moved { font-size: min(1.9vw, 2.9vh); }
/* The disclaimer is the last line in the tallest state on the shortest wall,
   so it is the one that has to give way. Wider measure, smaller face, and it
   fits on two lines instead of three. */
.sky .ar-verdict .db-note { font-size: min(1.5vw, 2.3vh); max-width: 78ch; }

/* ═══════════════════════════ THE PHONE ═══════════════════════════
   The paper register. The vote buttons themselves are debate.css's, unchanged:
   they are the one control in this product that has to work first time in the
   dark, and they have already been tuned for it. */
.ar-strip { gap: 8px; }
/* An explicit colour, not the side's: the strip belongs to neither side and
   `--db-side` is not set on it, so relying on the inherited value would leave
   the one face on this screen that is nobody's opponent taking whatever colour
   happened to be above it. */
.ar-ava-me { flex: 0 0 auto; width: 34px; color: var(--ink-2); }
.ar-ph-fighters { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.ar-ph-f {
  display: flex; align-items: center; gap: 8px; min-width: 0; padding: 6px 8px;
  border: 2px solid var(--db-side); background: var(--paper);
}
.ar-ph-f .ar-ava-ph { flex: 0 0 auto; width: 40px; }
.ar-ph-f-name {
  flex: 1 1 auto; min-width: 0; font: 700 .82rem var(--head); letter-spacing: .04em;
  text-transform: uppercase; color: var(--db-side);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Whose turn it is, on a handset: the same lit-and-dimmed as the wall, so a
   student glancing down sees the same thing they just looked up at. */
.ar-ph-f.ar-dim { opacity: .5; filter: grayscale(.6); }
.ar-ph-f.ar-lit { box-shadow: 3px 3px 0 var(--ink); }

.ar-ph-call {
  font-family: var(--head); font-weight: 700; font-size: 1.6rem; line-height: 1.05;
  text-transform: uppercase; letter-spacing: .06em;
}
.ar-ph-won {
  font: 700 .9rem var(--head); letter-spacing: .08em; text-transform: uppercase;
  color: var(--db-side);
}

/* ═══════════════════════════ MOTION ═══════════════════════════
   Two moments earn an animation: two fighters arriving from opposite sides of
   a wall, and the blow landing. Everything else moves because a number
   changed. `dbInLeft` / `dbInRight` are debate.css's and are reused, so the
   pick reads the same in both looks. */
@keyframes arSlam {
  0% { opacity: 0; transform: scale(2.6) skewX(-8deg); }
  55% { opacity: 1; transform: scale(.92) skewX(-8deg); }
  100% { opacity: 1; transform: scale(1) skewX(-8deg); }
}
@keyframes arPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
.sky .ar-ko span { animation: arSlam .5s cubic-bezier(.2, .9, .2, 1) both; }
.sky .ar-clock-n.db-out { animation: arPulse 1.1s steps(1, end) infinite; }

@media (prefers-reduced-motion: reduce) {
  .sky .ar-ko span, .sky .ar-clock-n.db-out { animation: none !important; }
  .sky .ar-hp-track > i { transition: none !important; }
}

/* ── a short wall (720p is the one this is actually shown on) ──
   The verdict carries the most: a splash, two faces, the call, two shift rows
   and two lines of small print. It is the state that decides the budget. */
@media (max-height: 800px) {
  .sky .ar-pj { gap: 1.6vh; }
  .sky .ar-verdict { gap: .9vh; }
  .sky .ar-ko span { font-size: min(8vw, 11vh); }
  .sky .ar-winner .ar-ava-lg { width: min(18vh, 14vw); }
  .sky .ar-loser .ar-ava-sm { width: min(9vh, 7vw); }
  .sky .ar-pick .ar-ava-xl { width: min(20vh, 15vw); }
}
