/* PLN second screen, in the show's own Stamped Ledger language.
 *
 * The page is held in one hand, in a dark room, beside a television running
 * the broadcast package. Every panel here is the same lot ticket the overlay
 * uses: solid plate, hairline border, a hard offset shadow with no blur, a
 * perforated left edge, and no rounded corners anywhere. Radius zero is part
 * of the language, not an oversight.
 *
 * The palette is semantic and never decorative (docs/design/stamped-ledger-
 * handoff.md). Cyan is platform truth, red is the Broker, gold is money,
 * purple is the crowd. This page IS the crowd, so purple carries every
 * interactive weight: the vote buttons, the countdown, the fill behind each
 * option, and every percentage the page works out for itself. Cyan and gold
 * appear only where the page is handing the platform's own numbers back.
 */

:root {
  --bg: #0a0d16;
  --plate: #0e1016;
  --strip: #12141b;
  --rule: #2a3347;
  --edge: #3d4a66;
  --ink: #e8ecf2;
  --dim: #7d8797;
  --truth: #3fd8ff;
  --truth-ink: #062733;
  --broker: #ff2e55;
  --gold: #ffc63d;
  --gold-ink: #17130a;
  --crowd: #b45bff;
  --ok: #43e39a;
  --dust: #8a919d;
  --common: #e8ecf2;
  --rare: #3f8cff;
  --epic: #b45bff;
  --grail: #ffc63d;

  --display: "Anton", "Haettenschweiler", "Franklin Gothic Medium", "Archivo Narrow", sans-serif;
  --mono: "IBM Plex Mono", Consolas, "Courier New", monospace;
  --sans: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* The handoff's corner cut, at phone scale. */
  --cut: polygon(0 0, 100% 0, 100% calc(100% - 18px), calc(100% - 18px) 100%, 0 100%);
}

* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  min-height: 100dvh;
  font-size: 15px;
  line-height: 1.4;
}

.hidden { display: none !important; }

/* Every state on this page is legible without colour: a stamp carries a word,
   a source tag carries a glyph and a word, a rank carries a number and a row
   of filled squares. This is the class that lets the second half of each of
   those reach a screen reader without reaching the layout. */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ── the lot ticket ── */

.plate {
  background: var(--plate);
  border: 2px solid var(--edge);
  box-shadow: 6px 6px 0 rgba(0, 0, 0, 0.5);
}

/* The perforated edge, in the panel's own accent. Every ticket sets --accent. */
.ticket {
  border-left: 4px dotted var(--accent, var(--edge));
}

/* A clip-path eats a real box-shadow: the shadow is drawn on the border box,
   then the clip cuts it away with the corner. So a cut plate hands its offset
   shadow to a wrapper, which draws it as a filter over the clipped silhouette
   and therefore follows the same cut. No blur in either direction. */
.cut-wrap {
  filter: drop-shadow(6px 6px 0 rgba(0, 0, 0, 0.5));
}
.plate.cut {
  clip-path: var(--cut);
  box-shadow: none;
}

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border-bottom: 2px solid var(--rule);
  padding-bottom: 8px;
  margin-bottom: 12px;
}
.panel-title {
  font-family: var(--display);
  font-size: 17px;
  letter-spacing: 2px;
  color: var(--crowd);
}

/* ── rubber stamps ── */

.stamp {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--display);
  font-size: 13px;
  letter-spacing: 2px;
  text-transform: uppercase;
  border: 2px solid currentColor;
  background: var(--plate);
  padding: 3px 8px;
  transform: rotate(-3deg);
}

/* ── source tags ──
   Every number on this page is either the crowd's own or the platform's, and
   the two must never be mistakable for each other. The tag carries a glyph
   AND a word AND the colour, so colour alone never does the work. */

.src {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  border: 1px solid currentColor;
  padding: 1px 5px;
  white-space: nowrap;
}
.src .g { width: 7px; height: 7px; fill: currentColor; flex: none; }
.src-crowd { color: var(--crowd); }
.src-verified { color: var(--truth); }
.src-broker { color: var(--broker); }

/* ── the show bug ── */

.bug {
  margin: 0 auto;
  max-width: 520px;
  padding: 12px 14px 0;
}
.bug-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.bug-under {
  margin-top: 8px;
  justify-content: space-between;
}
.pln {
  font-family: var(--display);
  font-size: 19px;
  letter-spacing: 1px;
  background: var(--gold);
  color: var(--gold-ink);
  border: 2px solid var(--gold-ink);
  padding: 3px 9px;
}
.showname {
  font-family: var(--display);
  font-size: 19px;
  letter-spacing: 3px;
  background: var(--plate);
  border: 2px solid var(--edge);
  border-left: 4px dotted var(--edge);
  padding: 4px 10px;
  color: var(--ink);
}
.live {
  color: var(--broker);
  margin-left: auto;
}
.live .dot {
  width: 8px;
  height: 8px;
  background: currentColor;
  animation: blink 1.6s infinite;
}
.live.off {
  color: var(--dim);
}
.live.off .dot { animation: none; }
@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

.episode {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 2px;
  color: var(--dim);
  text-transform: uppercase;
}
.points {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 1.5px;
  color: var(--truth);
  background: var(--plate);
  border: 2px solid var(--rule);
  padding: 3px 8px;
  font-variant-numeric: tabular-nums;
}
.points b { font-size: 14px; }

main {
  padding: 12px 14px 26px;
  max-width: 520px;
  margin: 0 auto;
}

/* ── the contestant's own ticket ── */

.status-card {
  --accent: var(--gold);
  padding: 12px 14px;
  margin-bottom: 14px;
}
.contestant {
  font-family: var(--display);
  font-size: 30px;
  line-height: 1.05;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.stats {
  margin-top: 10px;
  font-family: var(--mono);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
/* Dotted leader rows, the overlay's own ledger, stacked for one thumb. */
.stats .row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 5px 0;
  border-bottom: 2px dotted var(--rule);
}
.stats .row:last-child { border-bottom: none; }
.stats .k {
  color: var(--dim);
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
}
.stats .v { margin-left: auto; font-weight: 600; }
.stats .money { color: var(--truth); }
.stats .cash { color: var(--gold); }
.stats .pips { display: inline-flex; gap: 5px; margin-left: auto; }
.stats .pips i {
  width: 13px;
  height: 13px;
  border: 2px solid var(--edge);
  display: block;
}
.stats .pips i.on { background: var(--gold); border-color: var(--gold); }

/* ── the poll plate ── */

.poll-card {
  --accent: var(--crowd);
  padding: 16px 14px 18px;
  min-height: 340px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* ── idle: waiting, not broken ── */

.idle { text-align: center; padding: 18px 0; }
.standby {
  width: 54px;
  height: 54px;
  margin: 0 auto 16px;
  border: 2px solid var(--rule);
  display: grid;
  place-items: center;
}
.standby-dot {
  width: 16px;
  height: 16px;
  background: var(--crowd);
  animation: breathe 2.4s ease-in-out infinite;
}
@keyframes breathe { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
.idle-head {
  font-family: var(--display);
  font-size: 24px;
  letter-spacing: 5px;
  color: var(--ink);
}
.idle-text {
  margin: 10px auto 0;
  max-width: 300px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--dim);
}

/* ── question, advice line, countdown ── */

.poll-question {
  font-family: var(--display);
  font-size: 27px;
  line-height: 1.08;
  letter-spacing: 1px;
  text-transform: uppercase;
  font-weight: 400;
}
.advice {
  margin-top: 8px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--dim);
}

.cd { margin: 14px 0 14px; }
.cd-track {
  height: 10px;
  border: 2px solid var(--rule);
  background: var(--strip);
}
.cd-fill {
  height: 100%;
  width: 100%;
  background: var(--crowd);
  transition: width 0.25s linear;
}
.cd-label {
  margin-top: 6px;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--crowd);
  font-variant-numeric: tabular-nums;
  min-height: 15px;
}

.chip-crowd {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.5px;
  color: var(--crowd);
  border: 2px solid var(--crowd);
  padding: 2px 7px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── vote buttons ──
   Full width, stacked, in the lower two thirds where a thumb reaches. The
   crowd's share is drawn as a fill behind the whole button, and the button's
   own percentage is the crowd's, so both are purple. */

.vote-btns { display: flex; flex-direction: column; gap: 10px; }
.vote {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 76px;
  text-align: left;
  border: 2px solid var(--edge);
  border-left: 4px dotted var(--edge);
  background: var(--strip);
  color: var(--ink);
  padding: 12px 12px 12px 14px;
  font: inherit;
  cursor: pointer;
  overflow: hidden;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.5);
  transition: opacity 0.2s linear, border-color 0.2s linear;
}
.vote .v-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--share, 0%);
  background: rgba(180, 91, 255, 0.26);
  border-right: 2px solid var(--crowd);
  transition: width 0.4s ease;
}
.vote > *:not(.v-fill) { position: relative; }
.v-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.v-name {
  font-family: var(--display);
  font-size: 32px;
  line-height: 1;
  letter-spacing: 1px;
}
.v-sub { font-size: 12.5px; color: var(--dim); }
.v-fig {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 3px;
  font-family: var(--mono);
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.v-fig.verified { color: var(--truth); }
.v-fig.broker { color: var(--broker); }
.v-share {
  margin-left: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
  flex: none;
}
.v-pct {
  font-family: var(--display);
  font-size: 30px;
  line-height: 1;
  color: var(--crowd);
  font-variant-numeric: tabular-nums;
}
/* The tag rides in the share column rather than floating over the corner: a
   tag pinned to the corner lands on top of a three digit percentage at
   390px. */
.v-mine,
.r-mine {
  display: none;
  align-items: center;
  gap: 5px;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.5px;
  color: var(--crowd);
  border: 2px solid var(--crowd);
  background: var(--plate);
  padding: 2px 6px;
  white-space: nowrap;
}
.v-mine .g,
.r-mine .g { width: 10px; height: 9px; stroke: currentColor; flex: none; }
.vote.mine {
  border-left: 6px solid var(--crowd);
  border-color: var(--crowd);
  border-left-color: var(--crowd);
}
.vote.mine .v-mine { display: inline-flex; }
.rarity.mine .r-mine { display: inline-flex; }
/* Voted: the choice stands up, the roads not taken recede. */
.vote-btns.voted .vote:not(.mine) { opacity: 0.45; }
.vote:active { border-color: var(--crowd); }

/* ── poll result ── */

.result { text-align: center; }
.r-crowd {
  font-family: var(--display);
  font-size: 40px;
  line-height: 1.05;
  letter-spacing: 2px;
  color: var(--crowd);
}
.r-src { margin-top: 8px; }
.r-verdict {
  display: inline-flex;
  margin-top: 18px;
  font-family: var(--display);
  font-size: 20px;
  letter-spacing: 3px;
  text-transform: uppercase;
  border: 2px solid currentColor;
  background: var(--plate);
  padding: 6px 12px;
  transform: rotate(-4deg);
  color: var(--ink);
}
.r-verdict.with { color: var(--ok); }
.r-verdict.defied { color: var(--broker); }
.r-verdict.pending {
  border-style: dashed;
  color: var(--dim);
  transform: none;
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 2px;
}

/* ── call the hit ── */

.predict-sub {
  font-size: 13px;
  line-height: 1.5;
  color: var(--dim);
  margin-bottom: 12px;
}
/* Before anybody has called there is no denominator, so the market says so in
   words rather than printing five zeroes, which reads as a broken page. */
.no-calls {
  border: 2px dashed var(--rule);
  color: var(--dim);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  letter-spacing: 1px;
  padding: 10px 12px;
  margin-bottom: 12px;
  text-align: center;
}
.rarity-btns { display: flex; flex-direction: column; gap: 8px; }
.rarity {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 56px;
  text-align: left;
  border: 2px solid var(--edge);
  border-left: 4px dotted var(--r, var(--edge));
  background: var(--strip);
  color: var(--ink);
  padding: 10px 12px;
  font: inherit;
  cursor: pointer;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.5);
  transition: opacity 0.2s linear, border-color 0.2s linear;
}
/* Rank never rests on colour: the badge says which of five this tier is, and
   the squares repeat it for anyone who cannot read the hue at all. */
.r-badge {
  font-family: var(--display);
  font-size: 16px;
  letter-spacing: 1px;
  color: var(--r, var(--ink));
  border: 2px solid currentColor;
  padding: 2px 6px;
  flex: none;
}
.r-name {
  font-family: var(--display);
  font-size: 19px;
  letter-spacing: 1.5px;
  color: var(--r, var(--ink));
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.r-rank { display: inline-flex; gap: 3px; flex: none; }
.r-rank i {
  width: 8px;
  height: 8px;
  border: 1px solid var(--edge);
  display: block;
}
.r-rank i.on { background: var(--r, var(--ink)); border-color: var(--r, var(--ink)); }
.r-share {
  margin-left: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  flex: none;
}
.rar-pct {
  font-family: var(--display);
  font-size: 22px;
  color: var(--crowd);
  font-variant-numeric: tabular-nums;
}
.r-first {
  display: none;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1px;
  color: var(--dim);
}
.rarity-btns.empty .r-first { display: inline; }
.rarity.mine {
  border-color: var(--crowd);
  border-left: 6px solid var(--crowd);
}
.rarity-btns.called .rarity:not(.mine) { opacity: 0.45; }
.rarity:active { border-color: var(--crowd); }

.total {
  margin-top: 12px;
  text-align: center;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--dim);
  font-variant-numeric: tabular-nums;
}
/* The empty market's own words are a stamp, the same one the television is
   showing about the same round. */
.total.empty {
  display: block;
  width: fit-content;
  margin: 14px auto 0;
  font-family: var(--display);
  font-size: 15px;
  letter-spacing: 3px;
  color: var(--dim);
  border: 2px solid currentColor;
  background: var(--plate);
  padding: 4px 10px;
  transform: rotate(-4deg);
}

/* ── call result ── */

.predict-result { text-align: center; }
.pr-actual {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 2px;
  color: var(--dim);
  text-transform: uppercase;
}
.pr-actual b {
  display: block;
  margin-top: 6px;
  font-family: var(--display);
  font-size: 40px;
  letter-spacing: 2px;
  font-weight: 400;
}
.pr-src { margin-top: 8px; }
.pr-mine {
  display: inline-flex;
  margin-top: 18px;
  font-family: var(--display);
  font-size: 18px;
  letter-spacing: 2px;
  text-transform: uppercase;
  border: 2px solid currentColor;
  background: var(--plate);
  padding: 5px 11px;
  transform: rotate(-3deg);
  color: var(--dim);
}
.pr-mine.hit { color: var(--ok); }

/* ── the season ledger ── */

.board-card {
  --accent: var(--crowd);
  padding: 12px 14px;
  margin-top: 14px;
}
.board-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  border-bottom: 2px solid var(--rule);
  padding-bottom: 8px;
}
.my-rank {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 1.5px;
  color: var(--crowd);
  font-variant-numeric: tabular-nums;
  text-transform: uppercase;
}
.name-row { display: flex; gap: 8px; margin: 12px 0; }
.name-row input {
  flex: 1;
  min-width: 0;
  min-height: 44px;
  background: var(--strip);
  border: 2px solid var(--rule);
  color: var(--ink);
  padding: 8px 10px;
  font-family: var(--mono);
  font-size: 14px;
}
.name-row input::placeholder { color: var(--dim); }
.name-row input:focus-visible { outline: 2px solid var(--crowd); outline-offset: 2px; }
.name-row button {
  min-height: 44px;
  min-width: 64px;
  background: var(--plate);
  border: 2px solid var(--edge);
  color: var(--ink);
  padding: 8px 14px;
  font-family: var(--display);
  font-size: 15px;
  letter-spacing: 2px;
  cursor: pointer;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.5);
}
.board {
  list-style: none;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
.board li {
  display: flex;
  gap: 10px;
  padding: 7px 2px;
  border-bottom: 2px dotted var(--rule);
  font-size: 13px;
}
.board li:last-child { border-bottom: none; }
.board .b-rank { color: var(--dim); width: 26px; flex: none; }
.board .b-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board .b-pts { color: var(--truth); font-weight: 600; flex: none; }
.board li.top .b-name { color: var(--gold); }
.board .b-empty { color: var(--dim); }

/* ── the tension, in the product's own words ── */

.foot {
  margin-top: 18px;
  padding: 10px 12px;
  border-left: 4px dotted var(--rule);
  color: var(--dim);
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.6;
  letter-spacing: 0.5px;
}
.foot p + p { margin-top: 6px; }
.foot a { color: var(--truth); }

:focus-visible { outline: 2px solid var(--crowd); outline-offset: 2px; }

/* 360px: the narrowest phone that still has to hold a decision. Nothing is
   allowed to overflow, so the option name gives up a little size and the
   rank squares step out of the row rather than squeezing the name. */
@media (max-width: 374px) {
  .v-name { font-size: 27px; }
  .v-pct { font-size: 26px; }
  .r-name { font-size: 17px; }
  .r-rank { display: none; }
  .r-badge::after { content: " / 5"; letter-spacing: 0; }
  .contestant { font-size: 26px; }
  .poll-question { font-size: 24px; }
}

/* The resting state is fully visible outside this query, so a viewer who asks
   for less motion is never left holding a page whose content never arrived.
   All that is here is a pulse and a width, and both simply stop. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
