@font-face {
  font-family: "Bedstead";
  src: url("/assets/fonts/bedstead.woff2") format("woff2");
  font-display: block;
}

/* The broadcast eight. */
:root {
  --k: #000000;
  --r: #ff0000;
  --g: #00ff00;
  --y: #ffff00;
  --b: #0000ff;
  --m: #ff00ff;
  --c: #00ffff;
  --w: #ffffff;
  --cw: 0.6em; /* one teletext cell is 0.6em wide and 1em tall */
  color-scheme: dark;
  background: var(--k);
  scrollbar-color: var(--b) var(--k);
}

*,
*::before,
*::after { box-sizing: border-box; }

html,
body {
  margin: 0;
  background: var(--k);
  color: var(--w);
}

body {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  font-family: "Bedstead", monospace;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

::selection { background: var(--y); color: var(--k); }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Sizing: the whole set lives on one cell lattice. Font size is the row
   height; it snaps to 5px steps so cells land on whole pixels and the
   mosaics tile without seams. */
.set {
  --X: min(calc((100dvh - 2rem) / 25), calc((100vw - 2rem) / 33));
  --f: max(round(down, var(--X), 5px), round(down, min(var(--X), 15px), 1px));
  font-size: var(--X);
  display: flex;
  align-items: flex-start;
  gap: calc(2 * var(--cw));
  padding: 1rem;
}

@supports (width: round(down, 10px, 5px)) {
  .set { font-size: var(--f); }
}

/* The screen: 40 columns by 25 rows, nothing outside the lattice. */
.tv {
  position: relative;
  flex: none;
  width: calc(40 * var(--cw));
  height: 25em;
  overflow: hidden;
  background: var(--k);
  line-height: 1;
}

.row {
  display: block;
  width: calc(40 * var(--cw));
  height: 1em;
  margin: 0;
  overflow: hidden;
  font: inherit;
  line-height: 1;
  white-space: pre;
}

h1,
h2,
p { margin: 0; font: inherit; }

.dh { height: 2em; }
.dh > .dht {
  display: inline-block;
  transform: scaleY(2);
  transform-origin: 0 0;
}

/* Foreground colours. */
.k { color: var(--k); }
.r { color: var(--r); }
.g { color: var(--g); }
.y { color: var(--y); }
.b { color: var(--b); }
.m { color: var(--m); }
.c { color: var(--c); }
.w { color: var(--w); }

/* Background colours fill whole cells. */
.bg-r { background: var(--r); }
.bg-b { background: var(--b); }
.bg-m { background: var(--m); }

/* Pages: one on air at a time. Without JS, :target switches them. */
.page { display: none; height: 21em; overflow: hidden; }
.page.on { display: block; }
.tv:not(.js) .page:target { display: block; }
.tv:not(.js):not(:has(.page:target)) #p100 { display: block; }

.sub[hidden],
[hidden] { display: none !important; }

/* Flash attribute: four cycles on arrival, then steady (WCAG 2.2.2). */
.fl { animation: flash 1s steps(1, end) 4; }
@keyframes flash {
  0% { visibility: visible; }
  66% { visibility: hidden; }
}

/* Rows paint top to bottom as the page arrives. */
.page.paint .row {
  animation: rowin 0s linear both;
  animation-delay: calc(var(--i, 0) * 22ms);
}
@keyframes rowin {
  from { visibility: hidden; }
  to { visibility: visible; }
}

/* Concealed text waits for REVEAL. */
.cz { visibility: hidden; }
.tv.revealed .cz { visibility: visible; }

/* Links are whole rows or cells; hover takes the navigation blue. */
a { color: inherit; text-decoration: none; }
.lnk { cursor: pointer; }
.lnk:focus-visible {
  outline: 2px solid var(--y);
  outline-offset: -2px;
}
.fx:focus-visible {
  background: var(--k);
  color: var(--fx);
  outline: 2px solid var(--w);
  outline-offset: -2px;
}

/* Status line and Fastext bar. */
.st { color: var(--w); }
.fastext { display: flex; width: calc(40 * var(--cw)); height: 2em; }
.fx {
  --fx: var(--r);
  display: block;
  flex: none;
  width: calc(10 * var(--cw));
  height: 2em;
  background: var(--fx);
  color: var(--k);
}
.fx .row { width: auto; }
.fr { --fx: var(--r); }
.fg { --fx: var(--g); }
.fy { --fx: var(--y); }
.fc { --fx: var(--c); }

/* Hover only where a pointer can hover; on touch it would stick. */
@media (hover: hover) {
  .lnk:hover { background: var(--b); }
  .fx:hover { background: var(--k); color: var(--fx); }
  .key:hover { background: var(--w); color: var(--b); }
  .rv:hover,
  .hd:hover { background: var(--k); color: var(--w); border-color: var(--w); }
  .fxk .key:hover { background: var(--k); box-shadow: inset 0 0 0 0.12em var(--fx); }
}

/* Mosaics: a hairline of stroke closes sub-pixel seams between cells. */
.mz .row { -webkit-text-stroke: 0.5px currentColor; }

/* A faint raster, only where cells are large enough not to shimmer. */
@media (min-height: 700px) and (min-aspect-ratio: 1/1) {
  .tv::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: repeating-linear-gradient(to bottom, transparent 0 2px, rgb(0 0 0 / 0.16) 2px 3px);
  }
}

/* The remote control, drawn on the same lattice. */
.remote {
  flex: none;
  display: grid;
  grid-template-columns: calc(13 * var(--cw));
  grid-template-rows: 2em 1em 11em 1em 2em 1em 2em;
  grid-template-areas: "entry" "." "pad" "." "fn" "." "fx";
  line-height: 1;
}

.entry {
  grid-area: entry;
  display: flex;
  align-items: center;
  padding-left: var(--cw);
  border: 0.08em solid var(--w);
  color: var(--w);
  overflow: hidden;
}
.entry .dht {
  display: inline-block;
  transform: scaleY(2);
}
/* Key labels grow evenly: double height turns 0 and arrows into lozenges. */
.key .dht {
  display: inline-block;
  transform: scale(1.35);
}
.entry.typing #ed::after {
  content: "▌";
  color: var(--y);
  animation: flash 1s steps(1, end) infinite;
}

.pad {
  grid-area: pad;
  display: grid;
  grid-template-columns: repeat(3, calc(3 * var(--cw)));
  grid-auto-rows: 2em;
  column-gap: calc(2 * var(--cw));
  row-gap: 1em;
}
.fn {
  grid-area: fn;
  display: grid;
  grid-template-columns: calc(7 * var(--cw)) calc(5 * var(--cw));
  column-gap: var(--cw);
}
.fxk {
  grid-area: fx;
  display: grid;
  grid-template-columns: repeat(4, calc(2.5 * var(--cw)));
  column-gap: var(--cw);
}

.key {
  display: grid;
  place-items: center;
  height: 2em;
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--b);
  color: var(--y);
  font: inherit;
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}
.key:active,
.key.on { background: var(--y); color: var(--b); }
.key:focus-visible { outline: 0.1em solid var(--w); outline-offset: 0.08em; }

.rv { background: var(--k); color: var(--r); border: 0.08em solid var(--r); }
.rv[aria-pressed="true"] { background: var(--r); color: var(--k); }
.hd { background: var(--k); color: var(--y); border: 0.08em solid var(--y); }
.hd[aria-pressed="true"] { background: var(--y); color: var(--k); }

.fxk .key { background: var(--fx); }
.fxk .key:active,
.fxk .key.on { background: var(--k); box-shadow: inset 0 0 0 0.12em var(--fx); }

/* Portrait: the screen fills the width; the remote sits below it,
   with keys big enough for thumbs (44px and up). */
@media (max-aspect-ratio: 1/1) {
  .set {
    --X: calc(100vw / 24);
    flex-direction: column;
    align-items: center;
    gap: 1.25em;
    padding: max(0.75rem, env(safe-area-inset-top)) 0 max(1.5rem, env(safe-area-inset-bottom));
  }
  .remote {
    font-size: calc(5em / 3); /* 24 remote cells = 40 screen cells */
    grid-template-columns: calc(11 * var(--cw)) calc(2 * var(--cw)) calc(11 * var(--cw));
    grid-template-rows: 2em 1em 2em 1em 2em 1em 2em;
    grid-template-areas:
      "pad . entry"
      "pad . ."
      "pad . rv"
      "pad . ."
      "pad . hd"
      "pad . ."
      "pad . fx";
  }
  .pad { column-gap: var(--cw); }
  .fn { display: contents; }
  .rv { grid-area: rv; }
  .hd { grid-area: hd; }
  .fxk { grid-template-columns: repeat(4, calc(2 * var(--cw))); }
}

/* Short landscape screens: less padding so the cell snaps to 15px. */
@media (min-aspect-ratio: 1/1) and (max-height: 500px) {
  .set {
    --X: min(calc((100dvh - 0.8rem) / 25), calc((100vw - 2rem) / 33));
    padding-block: 0.4rem;
  }
}

/* Phones on their side: the remote gets as tall as the screen allows. */
@media (min-aspect-ratio: 1/1) and (pointer: coarse) and (max-height: 600px) {
  .remote { font-size: min(calc((100dvh - 2rem) / 20), 26px); }
}

@media (prefers-reduced-motion: reduce) {
  .fl,
  .entry.typing #ed::after { animation: none; }
  .page.paint .row { animation: none; }
}
