/* Shareboard display.
   Read at 3-5 metres by people who aren't trying to read it. Every size below is
   derived from --u so the layout holds at any panel resolution; at 1920x1080,
   1u = 19.2px. Body text lands at ~36px and headlines at ~80px, which is the
   floor for this viewing distance.

   Deliberately no webfont. Village-hall wifi drops, and a kiosk that waits on
   fonts.googleapis.com renders nothing, so the typeface choices in the admin are
   all stacks that resolve locally.

   Colours, typeface and text scale all arrive as tokens in the board payload
   and are set on :root by app.js. The values below are only what paints before
   the first fetch returns. */

:root {
  /* Scale by the limiting dimension so 16:9 proportions survive an odd panel. */
  --u: min(1vw, 1.7778vh);

  --ground: #0E1613;
  --surface: #172320;
  --surface-2: #1F2E2A;
  --text: #EDF2EF;
  --text-2: #C3D0CA;
  --dim: #82988F;
  --line: #2A3A35;
  --local: #6FBE9C;
  --network: #7CB2D4;
  --brass: #D2AA55;

  /* Everything above is overwritten from the board payload once it arrives.
     These are the fallbacks for the very first paint. */
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
          "DejaVu Sans", "Liberation Sans", sans-serif;
  --type-scale: 1;
  /* Headlines are already enormous, so they take half the boost. Body text is
     what is actually hard to read from the back of a hall. */
  --title-scale: calc(1 + (var(--type-scale) - 1) * 0.5);
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  background: var(--ground);
  color: var(--text);
}

body {
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  cursor: none;                 /* nobody touches this screen */
  user-select: none;
}

.screen {
  height: 100%;
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: calc(var(--u) * 2.2) calc(var(--u) * 3);
  gap: calc(var(--u) * 1.6);
}

/* ---------- top bar: never rotates ---------- */

.topbar {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: calc(var(--u) * 3);
  padding-bottom: calc(var(--u) * 1.4);
  border-bottom: 1px solid var(--line);
}

.centre-name {
  font-size: calc(var(--u) * 1.5 * var(--type-scale));
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text);
}

.centre-strap {
  font-size: calc(var(--u) * 1.05 * var(--type-scale));
  color: var(--dim);
  margin-top: calc(var(--u) * .5);
}

.tb-right {
  text-align: right;
  display: grid;
  gap: calc(var(--u) * .35);
  justify-items: end;
}

.date {
  font-size: calc(var(--u) * 1.25 * var(--type-scale));
  color: var(--text-2);
}

.clock {
  font-size: calc(var(--u) * 4.2 * var(--title-scale));
  font-weight: 300;
  line-height: .95;
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
}

.weather {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * .7);
  font-size: calc(var(--u) * 1.15 * var(--type-scale));
  color: var(--text-2);
  margin-top: calc(var(--u) * .3);
}

.weather.stale { color: var(--dim); }

.wx-icon svg {
  width: calc(var(--u) * 1.8);
  height: calc(var(--u) * 1.8);
  display: block;
}

.wx-temp { font-weight: 600; color: var(--text); }
.wx-desc { color: var(--text-2); }
.wx-range { color: var(--dim); font-variant-numeric: tabular-nums; }

/* ---------- stage: one card at a time ---------- */

.stage {
  position: relative;
  min-height: 0;
}

.card {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 600ms ease;
  pointer-events: none;
  display: flex;
}

.card.showing { opacity: 1; }

.card-inner {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: calc(var(--u) * .5);
  padding: calc(var(--u) * 3) calc(var(--u) * 3.6);
  width: 100%;
  display: grid;
  grid-template-columns: 1fr;
  align-items: center;
  gap: calc(var(--u) * 3);
  min-height: 0;
}

/* Set by app.js rather than using :has(), so this does not depend on whatever
   Chromium happens to be on the Pi. */
.card.has-qr .card-inner { grid-template-columns: 1fr auto; }

.card-main {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: calc(var(--u) * 1.2);
  min-width: 0;
}

/* Always dark-on-white, whatever the centre chose for its theme. An inverted
   code fails on a good number of phone cameras, and this gets one attempt from
   someone walking past. */
.qr {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--u) * .7);
  flex: none;
}

.qr-code {
  background: #FFFFFF;
  padding: calc(var(--u) * .7);
  border-radius: calc(var(--u) * .4);
  line-height: 0;
}

.qr-code svg {
  width: calc(var(--u) * 11);
  height: calc(var(--u) * 11);
  display: block;
}

.qr-host {
  font-size: calc(var(--u) * 1.1 * var(--type-scale));
  color: var(--dim);
  max-width: calc(var(--u) * 13);
  text-align: center;
  overflow-wrap: anywhere;
}

/* A card that arrived over the network reads differently at a glance. */
.card.is-network .card-inner {
  background: linear-gradient(180deg, #16242C 0%, var(--surface) 55%);
  border-color: #2A4150;
}

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--u) * 2);
  min-height: calc(var(--u) * 2);
}

.eyebrow {
  font-size: calc(var(--u) * 1.1 * var(--type-scale));
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--brass);
}

.badge {
  font-size: calc(var(--u) * 1 * var(--type-scale));
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--network);
  border: 1px solid var(--network);
  border-radius: 999px;
  padding: calc(var(--u) * .35) calc(var(--u) * 1.1);
  white-space: nowrap;
}

.title {
  font-size: calc(var(--u) * 4.6 * var(--title-scale));
  font-weight: 700;
  line-height: 1.03;
  letter-spacing: -.015em;
  margin: 0;
  text-wrap: balance;
}

.body {
  font-size: calc(var(--u) * 1.95 * var(--type-scale));
  line-height: 1.4;
  color: var(--text-2);
  margin: 0;
  /* Short measure reads faster at distance, but too short leaves the card
     looking half-empty on a wide panel. 40ch is the compromise. */
  max-width: 40ch;
}

.meta {
  font-size: calc(var(--u) * 1.35 * var(--type-scale));
  color: var(--dim);
  padding-top: calc(var(--u) * 1.1);
  border-top: 1px solid var(--line);
  font-variant-numeric: tabular-nums;
}

/* ---------- idle: no notices at all ---------- */

.idle {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(var(--u) * 1);
}

body.is-idle .idle { display: flex; }
body.is-idle .card { opacity: 0 !important; }
body.is-idle .rail { visibility: hidden; }

.idle-clock {
  font-size: calc(var(--u) * 17 * var(--title-scale));
  font-weight: 200;
  line-height: .9;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}

.idle-date {
  font-size: calc(var(--u) * 2.2 * var(--type-scale));
  color: var(--dim);
}

/* ---------- rail ---------- */

.rail {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--u) * 2);
  padding-top: calc(var(--u) * 1.2);
  border-top: 1px solid var(--line);
}

.dots {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 1);
}

.dot {
  width: calc(var(--u) * .62);
  height: calc(var(--u) * .62);
  border-radius: 50%;
  background: var(--line);
  transition: background 300ms ease, transform 300ms ease;
}

.dot.on {
  background: var(--local);
  transform: scale(1.5);
}

.dot.on.net { background: var(--network); }

.rail-right {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 1.6);
}

.position {
  font-size: calc(var(--u) * 1.05 * var(--type-scale));
  color: var(--dim);
  font-variant-numeric: tabular-nums;
}

.offline-flag {
  font-size: calc(var(--u) * 1.05 * var(--type-scale));
  color: var(--brass);
}

/* Nothing flashes into view on load; the first frame is already correct. */
body.booting .card,
body.booting .rail { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .card { transition: none; }
  .dot { transition: none; }
}
