/* glorp-web · shared stylesheet for index.html and overlay.html
   Look: "Pure Phosphor" monochrome green terminal (design preview V2/V2B).
   Everything is styled through classes — there are no inline styles and
   no style attributes anywhere; the backend CSP forbids them. */

@font-face {
  font-family: "PxPlus IBM VGA 8x16";
  src: url("PxPlus_IBM_VGA_8x16.woff2") format("woff2");
  font-display: swap;
}

:root {
  --void:     #050804;
  --phosphor: #7dff66;
  --mid:      #4ab53a;
  --dim:      #245c1e;
  --faint:    #12300f;
  --cell: 8px;
  --font: "PxPlus IBM VGA 8x16", ui-monospace, "Cascadia Mono", Consolas, "Liberation Mono", monospace;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html.crt { background: var(--void); }
html.clear { background: transparent; }

body {
  font-family: var(--font);
  font-size: 16px;
  line-height: 24px;
  color: var(--phosphor);
}

/* ── full page (index.html) ─────────────────────────────────────── */
body.page {
  background: radial-gradient(ellipse at 50% 40%, #081207 0%, var(--void) 75%);
  min-height: 100vh;
  display: flex;
  justify-content: center;
  padding: calc(var(--cell) * 4) var(--cell);
  text-shadow: 0 0 8px rgba(125, 255, 102, 0.45);
}
/* scanlines — index only. Composited over a live video feed they look
   like an encoding fault, so the overlay page never gets them. */
body.page::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0,0,0,0.3) 0px, rgba(0,0,0,0.3) 1px,
    transparent 1px, transparent 3px
  );
}

.screen {
  display: flex;
  gap: calc(var(--cell) * 6);
  align-items: flex-start;
  width: 100%;
  max-width: 960px;
  justify-content: center;
}
main { width: 100%; max-width: 640px; }

/* ── the field manual: rank ladder, pinned left (index only) ────── */
/* Owner-requested sidebar (design preview V2B). Static reference card
   only — the markup in index.html mirrors the backend rank config and
   is display-only; board.js never reads or writes it. */
aside.ladder {
  position: sticky;
  top: calc(var(--cell) * 4);
  width: 248px;
  flex-shrink: 0;
  border: 1px solid var(--faint);
  padding: calc(var(--cell) * 2);
  font-size: 13px;
  line-height: 20px;
  text-shadow: none;
}
.ladder-title {
  color: var(--phosphor);
  letter-spacing: 4px;
  font-weight: bold;
  text-shadow: 0 0 8px rgba(125,255,102,0.45);
  margin-bottom: 2px;
}
.ladder-sub {
  color: var(--dim);
  margin-bottom: calc(var(--cell) * 2);
}
.ladder ol { list-style: none; }
.ladder li {
  display: grid;
  grid-template-columns: 6ch 1fr;
  gap: var(--cell);
  padding: 1px 0;
}
.ladder .thr { color: var(--dim); text-align: right; }
.ladder .rk { text-transform: lowercase; }
/* tier brightness: higher tier = brighter phosphor, same scale as
   ranks.css uses for the board table */
.ladder .t5 .rk { color: var(--phosphor); font-weight: bold; text-shadow: 0 0 8px rgba(125,255,102,0.45); }
.ladder .t4 .rk { color: var(--phosphor); }
.ladder .t3 .rk { color: var(--mid); font-weight: bold; }
.ladder .t2 .rk { color: var(--mid); }
.ladder .t1 .rk { color: #2f7a27; }
.ladder .t0 .rk { color: var(--dim); }
/* the throne rank gets the same inverse-video treatment as the throne */
.ladder li.throne-rank {
  background: var(--phosphor);
  color: var(--void);
  padding: 2px 6px;
  margin: 0 -6px calc(var(--cell)) -6px;
  box-shadow: 0 0 18px rgba(125,255,102,0.3);
}
.ladder li.throne-rank .thr, .ladder li.throne-rank .rk {
  color: var(--void); font-weight: bold;
}
.ladder .throne-note {
  display: block;
  color: var(--dim);
  margin: -4px 0 var(--cell) 0;
  font-size: 12px;
}
.ladder .rule { color: var(--faint); margin: var(--cell) 0 2px; }
@media (max-width: 1100px) { aside.ladder { display: none; } }

/* ── boot line & header ─────────────────────────────────────────── */
.statusbar {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: calc(var(--cell) * 2);
  margin-bottom: calc(var(--cell) * 2);
}
.statusbar .boot { margin-bottom: 0; }
.boot {
  color: var(--dim);
  font-size: 13px;
  margin-bottom: calc(var(--cell) * 2);
  text-shadow: none;
}

/* ── reception meter (index only) ───────────────────────────────── */
/* Owner-requested (design preview V2B, spec §4.9.3). board.js drives
   the rx-0/rx-1/rx-2 state from active_glorpers; only these three
   classes and the three fixed labels ever appear here. */
.reception {
  display: flex;
  align-items: flex-end;
  gap: var(--cell);
  font-size: 12px;
  letter-spacing: 2px;
  white-space: nowrap;
  text-shadow: none;
}
.reception .bars { display: inline-flex; align-items: flex-end; gap: 3px; }
.reception .bars i {
  display: inline-block;
  width: 7px;
  border: 1px solid var(--dim);
  background: transparent;
}
.reception .bars .b1 { height: 8px; }
.reception .bars .b2 { height: 16px; }
.reception .rx-label { line-height: 14px; }
.reception.rx-0 .rx-label { color: var(--dim); }
.reception.rx-1 .bars .b1 { background: var(--mid); border-color: var(--mid); }
.reception.rx-1 .rx-label { color: var(--mid); }
.reception.rx-2 .bars .b1,
.reception.rx-2 .bars .b2 {
  background: var(--phosphor);
  border-color: var(--phosphor);
  box-shadow: 0 0 8px rgba(125, 255, 102, 0.55);
}
.reception.rx-2 .rx-label {
  color: var(--phosphor);
  font-weight: bold;
  text-shadow: 0 0 8px rgba(125, 255, 102, 0.45);
  animation: rxpulse 1.6s ease-in-out infinite;
}
@keyframes rxpulse { 50% { opacity: 0.65; } }
.nojs {
  color: var(--phosphor);
  font-weight: bold;
  letter-spacing: 1px;
  margin-bottom: calc(var(--cell) * 2);
}
header.bigtype {
  margin-bottom: calc(var(--cell) * 3);
  display: flex;
  gap: calc(var(--cell) * 2);
  align-items: flex-end;
}
header.bigtype img {
  width: 112px; height: 112px;
  object-fit: cover;
  image-rendering: pixelated;
  filter: brightness(1.1) saturate(1.2);
  border: 1px solid var(--mid);
  box-shadow: 0 0 24px rgba(125,255,102,0.25);
}
header.bigtype .title {
  font-size: 34px;
  line-height: 36px;
  font-weight: bold;
  letter-spacing: 2px;
}
header.bigtype .sub { color: var(--mid); margin-top: 4px; }

/* ── transmission banner (MOTD) ─────────────────────────────────── */
.transmission {
  border-top: 1px dashed var(--mid);
  border-bottom: 1px dashed var(--mid);
  padding: var(--cell) 0;
  margin-bottom: calc(var(--cell) * 3);
  opacity: 1;
  transition: opacity 200ms;
}
.transmission.fading { opacity: 0; }
.transmission .head {
  font-size: 13px;
  color: var(--mid);
  letter-spacing: 3px;
  display: flex;
  justify-content: space-between;
  text-shadow: none;
}
/* fixed two-line height: 200 chars wrap to at most two lines on this
   grid; pinning the height stops the board jumping when the text changes */
.transmission .text {
  height: 48px;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow-wrap: anywhere;
  color: var(--phosphor);
}
.transmission .text::before { content: "▸ "; }

/* ── throne — inverse video, the classic terminal emphasis ──────── */
.throne {
  background: var(--phosphor);
  color: var(--void);
  text-shadow: none;
  padding: calc(var(--cell) * 2);
  margin-bottom: calc(var(--cell) * 3);
  box-shadow: 0 0 32px rgba(125, 255, 102, 0.35);
}
.throne .paneltitle { font-size: 13px; letter-spacing: 6px; opacity: 0.75; }
/* fixed body height so the vacant and occupied states occupy the same
   space — the frame must not jump when the GlorpLord appears */
.throne .body { min-height: calc(var(--cell) * 11); }
.throne .lordname {
  font-size: 22px;
  font-weight: bold;
  margin-top: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.throne .lordrow {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-top: 4px;
  font-weight: bold;
  letter-spacing: 2px;
}
.throne .lordrank { text-transform: uppercase; }
/* the static ∞ (owner decision 2026-08-15) — sized to read as a glyph,
   not a digit (design preview V2B) */
.throne .lordscore {
  font-variant-numeric: tabular-nums;
  font-size: 28px;
  line-height: 1;
  font-weight: bold;
}
/* owner-requested caption under the eternal count (design preview V2B) */
.throne .eternal {
  font-size: 12px;
  letter-spacing: 3px;
  opacity: 0.65;
  margin-top: 2px;
  text-align: right;
}
.throne .vacant {
  margin-top: 4px;
  padding-top: calc(var(--cell) * 3);
  text-align: center;
  font-weight: bold;
  letter-spacing: 1px;
}

/* ── the board ──────────────────────────────────────────────────── */
table { width: 100%; border-collapse: collapse; }
caption.sr-only { caption-side: top; }
thead th {
  color: var(--dim);
  font-size: 13px;
  font-weight: normal;
  text-transform: uppercase;
  letter-spacing: 2px;
  text-align: left;
  text-shadow: none;
  border-bottom: 1px solid var(--faint);
  padding: 0 var(--cell) 4px 0;
}
thead th.score { text-align: right; padding-right: 0; }
td { padding: 3px var(--cell) 3px 0; }
tbody tr { border-bottom: 1px solid var(--faint); }
td.pos { color: var(--dim); width: 5ch; text-shadow: none; }
td.name { color: var(--phosphor); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 25ch; }
td.rank { color: var(--mid); text-transform: lowercase; font-size: 14px; width: 18ch; }
td.score { text-align: right; padding-right: 0; width: 8ch; }
tbody tr.entry:first-child td.score::after { content: " ▲"; font-size: 11px; }
tbody tr.ph td { color: var(--dim); text-shadow: none; }
td.empty { padding: calc(var(--cell) * 2) 0; color: var(--phosphor); letter-spacing: 1px; }

/* score-change flash: hold at --dim for 300ms, then decay */
@keyframes rowflash {
  0%, 50% { background-color: var(--dim); }
  100%    { background-color: transparent; }
}
tbody tr.flash { animation: rowflash 600ms ease-out; }

/* ── stale line & footer ────────────────────────────────────────── */
.stale {
  color: var(--phosphor);
  font-weight: bold;
  letter-spacing: 1px;
  margin-top: calc(var(--cell) * 2);
}
.stale:empty { display: none; margin: 0; }

footer {
  margin-top: calc(var(--cell) * 3);
  color: var(--dim);
  font-size: 14px;
  text-shadow: none;
}
/* --mid, not --dim: the data notice must clear contrast at this size */
footer .notice { display: block; margin-bottom: 4px; color: var(--mid); }
.prompt { color: var(--phosphor); }
.carrier { color: var(--phosphor); font-weight: bold; }
.cursor { animation: blink 1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* ── overlay variant (overlay.html) ─────────────────────────────── */
body.overlay {
  background: transparent;
  padding: var(--cell);
  text-shadow: none;
  /* hard dark outline so text survives arbitrary gameplay footage */
  -webkit-text-stroke: 4px var(--void);
  paint-order: stroke fill;
}
body.overlay main { max-width: 640px; }
.overlay .throne { -webkit-text-stroke: 0; }
.overlay .transmission { margin-bottom: var(--cell); padding: 4px 0; }
.overlay .transmission .text {
  display: block;
  height: 24px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.overlay-stale {
  color: var(--phosphor);
  font-weight: bold;
  font-size: 14px;
  letter-spacing: 2px;
  margin-bottom: var(--cell);
}
.overlay-stale:empty { display: none; margin: 0; }

/* ── utilities & quality floor ──────────────────────────────────── */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
:focus-visible { outline: 2px solid var(--phosphor); outline-offset: 2px; }

@media (max-width: 480px) {
  body { font-size: 14px; line-height: 20px; }
  header.bigtype img { width: 80px; height: 80px; }
  header.bigtype .title { font-size: 24px; line-height: 26px; }
  td.rank { width: 12ch; font-size: 12px; }
  td.name { max-width: 14ch; }
  .transmission .text { height: 40px; }
}

@media (prefers-reduced-motion: reduce) {
  .cursor { animation: none; }
  tbody tr.flash { animation: none; }
  .transmission { transition: none; }
  .reception.rx-2 .rx-label { animation: none; }
}
