/* Palette of the CEPT teletext attributes used by early-80s videotex terminals. */
:root {
  --black: #000; --red: #f00; --green: #0f0; --yellow: #ff0;
  --blue: #00f; --magenta: #f0f; --cyan: #0ff; --white: #fff;
  --row: 1.2em;        /* one character row */
  --row-time: .2s;     /* build-up time per row, like a slow modem line */
  --fs: min(calc(96vw / 25), calc(96vh / 29.5), 30px);
}
* { box-sizing: border-box; margin: 0; }
html, body { height: 100%; }
body {
  display: grid; place-items: center;
  background: #111; color: var(--white);
  font: 700 var(--fs)/1.2 Menlo, Consolas, "DejaVu Sans Mono", "Courier New", monospace;
}
/* 40 x 24 character screen with faint CRT scanlines on top. */
main { position: relative; width: 40ch; height: calc(24 * var(--row)); background: var(--black); overflow: hidden; }
main::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(transparent 0 2px, rgb(0 0 0 / .18) 2px 4px);
}
.r {
  display: flex; justify-content: space-between; align-items: center;
  height: var(--row); white-space: pre;
  /* Rows appear left to right, one character at a time, top to bottom. */
  animation: reveal var(--row-time) steps(40) both;
  animation-delay: calc(var(--n, 0) * var(--row-time));
}
.c { justify-content: center; }
.bl { background: var(--blue); }
.ma { background: var(--magenta); }
.ye { color: var(--yellow); }
.cy { color: var(--cyan); }
.gr { color: var(--green); }
.logo { font-size: inherit; height: calc(4 * var(--row)); }
.logo svg { display: block; width: 39ch; height: 100%; fill: var(--yellow); }
/* Double-height characters, a stock attribute of the videotex standard. */
.dh { height: calc(2 * var(--row)); align-items: flex-start; }
.dh span { display: inline-block; transform: scaleY(2); transform-origin: top; }
.stripes {
  background: linear-gradient(90deg,
    var(--red) 0 14.28%, var(--green) 0 28.57%, var(--yellow) 0 42.85%, var(--blue) 0 57.14%,
    var(--magenta) 0 71.42%, var(--cyan) 0 85.71%, var(--white) 0);
}
.cursor { display: inline-block; width: 1ch; height: 1em; vertical-align: -.1em; background: var(--white); animation: blink 1s steps(1) infinite; }
@keyframes reveal { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .r, .cursor { animation: none; }
}

/* Navigation: selectable rows, footer links and status line. */
main:focus { outline: none; }
a { color: inherit; text-decoration: none; }
a:focus-visible { outline: 2px solid var(--yellow); outline-offset: -2px; }
.ma { color: var(--black); }
.ma a { text-decoration: underline; }
.link:hover { background: var(--white); color: var(--black); }
.link { justify-content: flex-start; }
.key { color: var(--yellow); }
.link:hover .key { color: inherit; }
.status { justify-content: flex-start; }

/* Section colours of the page banners. */
.gn { background: #006000; }
.re { background: #a00000; }
.mg { background: #800080; }
h1 { font-size: inherit; }

/* Footer options; whitespace between flex items would collapse, so use gap. */
.options { justify-content: flex-start; gap: 2ch; padding-left: 1ch; }

/* Redraws of the running game appear at once, without the build-up. */
.instant .r { animation: none; }
[data-key] { cursor: pointer; }
