/* lanhouse: a lan house in a neon night city. The brand fuchsia is the lead light, a cold
   cyan is the second one, ultraviolet only on the playWAR screen. Panels are cut at 45
   degrees, like the letters of the display face (Chakra Petch); thin lines, tick rulers and
   micro-labels make the HUD. Dark only, on purpose: the night is the brand.
   Every path is absolute from the root, because the sites module answers /games/playra and
   /games/playra/ with the same file. */

/* lets the cut edge of a panel fade between colours on hover */
@property --edge {
  syntax: "<color>";
  inherits: false;
  initial-value: #2b2338;
}

:root {
  color-scheme: dark;

  --night: #07060b;
  --panel: #100c18;
  --panel-hi: #161120;
  --line: #2b2338;
  --line-hi: #463a5c;

  /* contrast on --panel-hi, the lightest ground with text */
  --ink: #f0ebf6;         /* 15.8:1 */
  --ink-soft: #c3b9d2;    /*  9.9:1 */
  --ink-dim: #a397b5;     /*  6.7:1, labels only */

  --pink: #c43fd0;        /* brand fuchsia: lines, fills, glow; never text */
  --pink-text: #de82e6;   /* fuchsia text, 7.4:1 */
  --pink-core: #ffe4fb;   /* the white-hot core of the tube */
  --cyan: #1fd6ec;
  --cyan-text: #7ee9f7;   /* 13.1:1 */
  --violet: #8d7dff;
  --violet-text: #b2a8ff; /* 8.8:1 */

  --gutter: 16px;

  --font-body: "Barlow", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --font-hud: "Chakra Petch", "Bahnschrift", "DIN Alternate", "Roboto Condensed", "Arial Narrow", system-ui, sans-serif;
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background: var(--night);
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--night);
  color: var(--ink);
  font: 400 1.0625rem/1.6 var(--font-body);
  overflow-wrap: break-word;
}

main { flex: 1 0 auto; }

a { color: var(--pink-text); text-underline-offset: .2em; text-decoration-thickness: 1px; }
a:hover { color: var(--pink-core); }
:focus-visible { outline: 2px solid var(--cyan-text); outline-offset: 3px; }

::selection { background: var(--pink); color: var(--night); }

.wrap {
  width: 100%;
  max-width: 72rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

@media (min-width: 48rem) {
  .wrap { padding-inline: 2rem; }
}

/* ---------- the cut panel ----------
   Two corners cut at 45 degrees (top right, bottom left). The 1px edge follows the cut:
   the border draws the straight sides, two gradients draw the diagonals. Each panel sets
   --cut, --edge and --fill. Glow goes on a parent with drop-shadow, because the clip
   would cut a box-shadow. */

.skip,
.kicker,
.blade,
.screen,
.desk,
.status,
.tag,
.spec,
.machines a,
.bar-link,
.play {
  --cut: 12px;
  --fill: var(--panel);
  border: 1px solid var(--edge);
  clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, var(--cut) 100%, 0 calc(100% - var(--cut)));
  background:
    linear-gradient(225deg, var(--edge) calc(var(--cut) * .7071 + 1px), transparent 0) border-box,
    linear-gradient(45deg, var(--edge) calc(var(--cut) * .7071 + 1px), transparent 0) border-box,
    var(--fill) border-box;
  transition: --edge .2s ease;
}

.skip {
  --cut: 8px;
  --edge: var(--pink);
  --fill: var(--pink);
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10;
  padding: .6rem .9rem;
  color: var(--night);
  font: 600 .875rem/1.2 var(--font-hud);
  letter-spacing: .06em;
  text-transform: uppercase;
  text-decoration: none;
}
.skip:focus { left: var(--gutter); top: var(--gutter); color: var(--night); }

/* ---------- labels: the small technical type of the HUD ---------- */

.hud,
.kicker,
.osd,
.genre,
.pc,
.counter,
.status,
.tag,
.spec h2,
.spec dt,
.machines,
.bar-link,
.play,
.no-signal {
  font-family: var(--font-hud);
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
}

/* a ruler: one thin line with ticks under it */
.pc::after,
.room-head::before,
.spec h2::after {
  content: "";
  display: block;
  height: 6px;
  background:
    linear-gradient(var(--line-hi), var(--line-hi)) left top / 100% 1px no-repeat,
    repeating-linear-gradient(to right, var(--line-hi) 0 1px, transparent 1px 8px) left top / 100% 4px no-repeat;
}

/* ---------- the sign ---------- */

.sign {
  font-family: var(--font-hud);
  font-weight: 700;
  line-height: .95;
  letter-spacing: -.01em;
  color: #ffd6f9;
  text-shadow:
    -.025em 0 0 rgba(31, 214, 236, .55),
    0 0 2px #fff,
    0 0 8px var(--pink-text),
    0 0 20px var(--pink),
    0 0 44px var(--pink),
    0 0 96px rgba(196, 63, 208, .7);
}

/* ---------- home: the street outside ---------- */

.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(1.25rem, 3vw, 2rem) clamp(9.5rem, 24vw, 17rem);
  background:
    radial-gradient(80% 60% at 50% 100%, rgba(196, 63, 208, .38), transparent 72%),
    radial-gradient(40% 45% at 92% 18%, rgba(31, 214, 236, .12), transparent 70%),
    linear-gradient(to bottom, var(--night) 0, #0d0915 60%, #170c21 100%);
}

/* the city, sitting on a fuchsia street line: a box as wide as the street (58rem at least,
   centred) and as tall as the art. city.svg is the still picture; each span draws one layer of
   lights over it at the same size (tools/city.py draws them all), and only its opacity moves */
.city {
  position: absolute;
  z-index: -1;
  bottom: 0;
  left: min(0px, 50% - 29rem);
  width: max(100%, 58rem);
  aspect-ratio: 1600 / 260;
  background: url("/img/skyline/city.svg") 0 0 / 100% 100% no-repeat;
}
.city > span {
  position: absolute;
  inset: 0;
  background-size: 100% 100%;
  background-repeat: no-repeat;
}
.lights--1 { background-image: url("/img/skyline/lights-1.svg"); }
.lights--2 { background-image: url("/img/skyline/lights-2.svg"); }
.lights--3 { background-image: url("/img/skyline/lights-3.svg"); }
.lights--4 { background-image: url("/img/skyline/lights-4.svg"); }
.lights--5 { background-image: url("/img/skyline/lights-5.svg"); }
.lights--6 { background-image: url("/img/skyline/lights-6.svg"); }
.signs--a { background-image: url("/img/skyline/signs-a.svg"); }
.signs--b { background-image: url("/img/skyline/signs-b.svg"); }
.beacons { background-image: url("/img/skyline/beacons.svg"); }
/* groups 4 to 6 are dark windows that light up now and then: off while the city stands still */
.lights--4,
.lights--5,
.lights--6 { opacity: 0; }

/* the rain, in front of the city and behind the words: three tiles of vertical drops, far
   (short, faint, steep, slow) to near (long, leaning with the wind, fast). The skew slants each
   tile, and the fall moves it down by exactly one tile, so the loop never jumps. Each layer
   starts one tile above the street and runs 10rem past each side, enough for the slant */
.rain {
  position: absolute;
  z-index: -1;
  inset: 0;
}
.rain > span {
  position: absolute;
  top: calc(-1 * var(--tile));
  bottom: 0;
  left: -10rem;
  right: -10rem;
  background-size: var(--tile) var(--tile);
}
.rain-far { --tile: 140px; background-image: url("/img/rain/far.svg"); transform: skewX(6deg); }
.rain-mid { --tile: 200px; background-image: url("/img/rain/mid.svg"); transform: skewX(9deg); }
.rain-near { --tile: 300px; background-image: url("/img/rain/near.svg"); transform: skewX(12deg); }

/* scanlines over the city and the rain */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, .28) 0 1px, transparent 1px 3px);
}

.hero-in { position: relative; }

/* brand names live in the HUD strip and the machine links: no upper case there */
.hud,
.machines { text-transform: none; }

.hud {
  display: flex;
  align-items: center;
  gap: .9rem;
  margin-bottom: clamp(2.5rem, 9vw, 5.5rem);
  color: var(--ink-dim);
  font-size: .6875rem;
  line-height: 1;
  white-space: nowrap;
}
.hud-rule {
  flex: 1;
  height: 6px;
  background:
    linear-gradient(var(--line-hi), var(--line-hi)) left top / 100% 1px no-repeat,
    repeating-linear-gradient(to right, var(--line-hi) 0 1px, transparent 1px 8px) left top / 100% 4px no-repeat;
}

.kicker {
  --cut: 8px;
  --edge: rgba(31, 214, 236, .5);
  --fill: rgba(31, 214, 236, .07);
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  margin: 0;
  padding: .45rem .8rem .45rem .65rem;
  color: var(--cyan-text);
  font-size: .75rem;
  line-height: 1.3;
}
@media (max-width: 24rem) {
  .kicker { font-size: .6875rem; letter-spacing: .1em; }
}
.kicker::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  background: var(--cyan);
  box-shadow: 0 0 8px var(--cyan);
}

.sign--hero {
  position: relative;
  margin: clamp(.75rem, 2.5vw, 1.25rem) 0 clamp(1.25rem, 3.5vw, 2rem);
  font-size: clamp(3.6rem, 17vw, 10.5rem);
}

.lead {
  margin: 0;
  max-width: 34rem;
  font-size: clamp(1.125rem, 2.4vw, 1.375rem);
  font-weight: 500;
  line-height: 1.5;
}
.hero .lead {
  padding-left: 1rem;
  border-left: 2px solid var(--pink);
  text-shadow: 0 1px 12px var(--night);
}

/* the vertical blade sign on the building, wide screens only */
.blade {
  --cut: 10px;
  --edge: rgba(31, 214, 236, .55);
  --fill: linear-gradient(to bottom, rgba(31, 214, 236, .1), rgba(7, 6, 11, .9));
  display: none;
}

@media (min-width: 62rem) {
  .blade {
    display: block;
    position: absolute;
    right: 2rem;
    top: 4.75rem;
    margin: 0;
    padding: 1.1rem .7rem;
    writing-mode: vertical-rl;
    text-orientation: upright;
    color: #e3fdff;
    font: 700 2.25rem/1 var(--font-hud);
    letter-spacing: .08em;
    text-transform: uppercase;
    text-shadow: 0 0 2px #fff, 0 0 10px var(--cyan), 0 0 24px var(--cyan);
  }
}

/* the sign catching power: two stutters and a short glitch on load, then the tube (the span
   holding the word) hums and the glitch comes back now and then. The two copies come from
   data-text and are hidden from screen readers; each shows one band of the word (its clip) and
   only its opacity and transform move. One animation per element, on purpose: Chrome leaves two
   animations of the same property on one element to the main thread, every frame, so the
   power-up is on the h1 and the hum on the tube, and each copy's glitch is a single loop whose
   cycle starts with the glitch of the load. */
.sign--hero .tube { display: block; }
.sign--hero::before,
.sign--hero::after {
  content: attr(data-text);
  content: attr(data-text) / "";
  position: absolute;
  z-index: 1;
  inset: 0;
  opacity: 0;
  pointer-events: none;
}
.sign--hero::before { color: #c8f8ff; text-shadow: 0 0 12px var(--cyan); clip-path: inset(14% 0 62% 0); }
.sign--hero::after { color: var(--pink-core); text-shadow: 0 0 14px var(--pink); clip-path: inset(66% 0 10% 0); }

@media (prefers-reduced-motion: no-preference) {
  .sign--hero { animation: ignite 1.6s steps(1, end) .2s backwards; }
  .sign--hero .tube { animation: hum 37s ease-in-out 1.8s infinite; }
  .sign--hero::before { animation: glitch-a 67s steps(1, end) .3s infinite; }
  .sign--hero::after { animation: glitch-b 67s steps(1, end) .3s infinite; }
}

@keyframes ignite {
  0%   { opacity: .1; }
  10%  { opacity: 1; }
  16%  { opacity: .2; }
  24%  { opacity: 1; }
  46%  { opacity: .65; }
  50%  { opacity: 1; }
  100% { opacity: 1; }
}

/* the glitch: in the first 3 s (the load), then once more at 58% of the 67 s cycle, so it
   comes back 38 s and 29 s apart, each time for about a quarter of a second */
@keyframes glitch-a {
  0%     { opacity: 0; transform: none; }
  1.01%  { opacity: 1; transform: translateX(-.05em); }
  1.16%  { opacity: 1; transform: translateX(.035em); }
  1.31%  { opacity: 0; transform: none; }
  2.74%  { opacity: 1; transform: translateX(-.03em); }
  2.86%  { opacity: 0; transform: none; }
  58%    { opacity: 1; transform: translateX(-.05em); }
  58.15% { opacity: 1; transform: translateX(.035em); }
  58.3%  { opacity: 0; transform: none; }
  100%   { opacity: 0; transform: none; }
}

@keyframes glitch-b {
  0%     { opacity: 0; transform: none; }
  1.09%  { opacity: 1; transform: translateX(.05em); }
  1.24%  { opacity: 1; transform: translateX(-.025em); }
  1.36%  { opacity: 0; transform: none; }
  58.07% { opacity: 1; transform: translateX(.04em); }
  58.22% { opacity: 1; transform: translateX(-.03em); }
  58.4%  { opacity: 0; transform: none; }
  100%   { opacity: 0; transform: none; }
}

/* ---------- the room: one station per game ---------- */

.room {
  position: relative;
  padding-block: clamp(2.5rem, 6vw, 3.75rem) clamp(3.5rem, 8vw, 5.5rem);
  background: linear-gradient(to bottom, rgba(196, 63, 208, .07), transparent 14rem);
}

.room-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem 1.5rem;
  margin-bottom: 2.25rem;
}
.room-head::before { flex: 1 0 100%; margin-bottom: 1rem; }

.room-head h2 {
  margin: 0;
  color: var(--pink-text);
  font: 700 clamp(1.875rem, 5vw, 2.5rem)/1.1 var(--font-hud);
  text-shadow: 0 0 18px rgba(196, 63, 208, .45);
}

.counter {
  margin: 0;
  color: var(--ink-dim);
  font-size: .75rem;
}
.counter span { white-space: nowrap; color: var(--ink-soft); }

.stations {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 2.75rem clamp(1.5rem, 3vw, 2.25rem);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr));
}

.stations > li { display: flex; }

/* the two thin mounts between the monitor and the desk are the station's own background */
.station {
  flex: 1;
  display: flex;
  flex-direction: column;
  color: inherit;
  text-decoration: none;
  background:
    linear-gradient(var(--line-hi), var(--line-hi)) 26% 0 / 1px 100% no-repeat,
    linear-gradient(var(--line-hi), var(--line-hi)) 74% 0 / 1px 100% no-repeat;
  transition: filter .2s ease;
}
.station:hover { color: inherit; }
.station:focus-visible { outline-offset: 8px; }
.station:hover,
.station:focus-visible { filter: drop-shadow(0 0 16px rgba(196, 63, 208, .4)); }

/* the monitor */
.screen {
  --cut: 18px;
  --glow: rgba(196, 63, 208, .45);
  --hud: rgba(222, 130, 230, .75);
  --osd: var(--pink-text);
  --art: none;
  --art-size: contain;
  --art-pos: center;
  --light: radial-gradient(90% 85% at 75% 45%, var(--glow), transparent 70%);
  --edge: var(--line-hi);
  --fill: #050409;
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 12rem;
  aspect-ratio: 16 / 10;
  padding: 1rem 1.25rem 1.1rem;
}

.screen::before,
.screen::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* the light of the screen: its art over its glow, one layer, so the screen hums by opacity */
.screen::before {
  background: var(--art) var(--art-pos) / var(--art-size) no-repeat, var(--light);
}

/* glass: scanlines, dark corners, a shade for the title, and the two HUD brackets on the
   corners that are not cut */
.screen::after {
  background:
    linear-gradient(var(--hud), var(--hud)) left 9px top 9px / 18px 1px no-repeat,
    linear-gradient(var(--hud), var(--hud)) left 9px top 9px / 1px 18px no-repeat,
    linear-gradient(var(--hud), var(--hud)) right 9px bottom 9px / 18px 1px no-repeat,
    linear-gradient(var(--hud), var(--hud)) right 9px bottom 9px / 1px 18px no-repeat,
    repeating-linear-gradient(to bottom, rgba(255, 255, 255, .04) 0 1px, transparent 1px 3px),
    radial-gradient(ellipse at center, transparent 55%, rgba(0, 0, 0, .5) 100%),
    linear-gradient(to top, rgba(5, 4, 9, .9) 0, transparent 50%);
}

.osd {
  position: absolute;
  z-index: 1;
  top: .85rem;
  left: 1.25rem;
  margin: 0;
  color: var(--osd);
  font-size: .6875rem;
  line-height: 1;
}

.screen-title {
  position: relative;
  z-index: 1;
  margin: 0;
  color: #fff;
  font: 700 clamp(2rem, 7vw, 2.5rem)/1 var(--font-hud);
  letter-spacing: -.005em;
  text-shadow: 0 0 6px var(--glow), 0 0 20px var(--glow);
}

.screen--playra {
  --glow: rgba(31, 214, 236, .3);
  --hud: rgba(126, 233, 247, .75);
  --osd: var(--cyan-text);
  --art: url("/img/radar.svg");
  --art-size: auto 118%;
  --art-pos: right -1.5rem center;
}

.screen--playwar {
  --glow: rgba(141, 125, 255, .34);
  --hud: rgba(178, 168, 255, .75);
  --osd: var(--violet-text);
  --art: url("/img/isometric.svg");
  --art-size: cover;
  --art-pos: 70% 40%;
}

.screen--lurex {
  --art: url("/img/d20.svg");
  --art-size: auto 88%;
  --art-pos: right 1.25rem center;
}

.station:hover .screen,
.station:focus-visible .screen { --edge: var(--pink); }

.station:hover .screen-title,
.station:focus-visible .screen-title {
  text-shadow:
    -2px 0 0 rgba(31, 214, 236, .8),
    2px 0 0 rgba(196, 63, 208, .8),
    0 0 20px var(--glow);
}

/* the desk card under the monitor */
.desk {
  --edge: var(--line);
  --fill: linear-gradient(to bottom, var(--panel-hi), var(--panel));
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: .6rem;
  margin-top: 1.1rem;
  padding: 1rem 1.25rem 1.2rem;
}

.desk p { margin: 0; }

.genre {
  color: var(--ink-dim);
  font-size: .6875rem;
  line-height: 1.3;
}

.plates {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
  margin-top: auto;
  padding-top: .5rem;
}

/* the status plate: a square LED and the word */
.status {
  --cut: 7px;
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  margin: 0;
  padding: .32rem .7rem .32rem .6rem;
  font-size: .75rem;
  line-height: 1.2;
}

.led {
  flex: none;
  width: 7px;
  height: 7px;
  background: currentColor;
  box-shadow: 0 0 5px currentColor, 0 0 12px currentColor;
}

/* on the air: a steady cyan light (nothing blinks), for a game you can play now */
.status--live {
  --edge: rgba(31, 214, 236, .55);
  --fill: rgba(31, 214, 236, .08);
  color: var(--cyan-text);
}

/* work in progress: the plate carries fuchsia hazard stripes */
.status--dev {
  --edge: rgba(196, 63, 208, .65);
  --fill: repeating-linear-gradient(135deg, rgba(196, 63, 208, .16) 0 6px, transparent 6px 12px) var(--panel);
  color: var(--pink-text);
}

/* a tag says what the game is. Lower case, because a tag can hold a name (OpenRA) */
.tag {
  --cut: 7px;
  --edge: var(--line-hi);
  --fill: transparent;
  margin: 0;
  padding: .32rem .65rem;
  color: var(--ink-soft);
  font-size: .75rem;
  letter-spacing: .06em;
  line-height: 1.2;
  text-transform: none;
}

/* ---------- the play button: the one call to play, for a game on the air ----------
   Light fuchsia fill with dark text (8.1:1), cut like every panel. The glow is a
   drop-shadow on .play-slot, since the clip cuts a box-shadow, and the focus ring is drawn
   inside, in the dark ink, for the same reason. 2.75rem tall: a full touch target. */
.play-slot {
  margin: 0;
  filter: drop-shadow(0 0 10px rgba(196, 63, 208, .55));
}

.play {
  --cut: 10px;
  --edge: var(--pink-text);
  --fill: var(--pink-text);
  display: inline-flex;
  align-items: center;
  gap: .65rem;
  min-height: 2.75rem;
  padding: 0 1.5rem 0 1.15rem;
  color: var(--night);
  font-size: .9375rem;
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
}
.play:hover,
.play:focus-visible { --edge: var(--pink-core); --fill: var(--pink-core); color: var(--night); }
.play:focus-visible { outline: 2px solid var(--night); outline-offset: -5px; }

.play-icon {
  flex: none;
  width: .6rem;
  height: .7rem;
  background: currentColor;
  clip-path: polygon(0 0, 100% 50%, 0 100%);
}

/* a station with a play button: the card is one link and a link cannot hold another, so
   the button sits next to it in the list item, over room kept free at the foot of the desk */
.stations > li.has-play { position: relative; }
.has-play .desk { padding-bottom: calc(1.2rem + 2.75rem + .9rem); }
.has-play .play-slot {
  position: absolute;
  z-index: 1;
  left: 1.25rem;
  bottom: 1.2rem;
}

/* words for screen readers only ("Jogar playRA" on the card); names keep their case */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
  text-transform: none;
}

/* ---------- a game's own page ---------- */

.bar {
  position: relative;
  border-bottom: 1px solid var(--line);
  background:
    repeating-linear-gradient(to bottom, rgba(0, 0, 0, .25) 0 1px, transparent 1px 3px),
    radial-gradient(60% 140% at 0% 0%, rgba(196, 63, 208, .14), transparent 70%),
    var(--night);
}
.bar::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -1px;
  width: min(14rem, 40%);
  height: 1px;
  background: linear-gradient(to right, var(--pink), transparent);
}

.bar-in {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .75rem 1.5rem;
  min-height: 4.25rem;
  padding-block: .6rem;
}

.bar-sign {
  font-size: 1.875rem;
  text-decoration: none;
  text-shadow:
    -.025em 0 0 rgba(31, 214, 236, .5),
    0 0 2px #fff,
    0 0 7px var(--pink-text),
    0 0 16px var(--pink),
    0 0 30px rgba(196, 63, 208, .6);
}
.bar-sign:hover,
.bar-sign:focus-visible {
  color: #fff;
  text-shadow:
    -.06em 0 0 rgba(31, 214, 236, .8),
    .04em 0 0 rgba(196, 63, 208, .9),
    0 0 7px var(--pink-text),
    0 0 18px var(--pink);
}

.bar-link {
  --cut: 7px;
  --edge: rgba(31, 214, 236, .5);
  --fill: rgba(31, 214, 236, .06);
  padding: .45rem .8rem;
  color: var(--cyan-text);
  font-size: .75rem;
  line-height: 1.2;
  text-decoration: none;
}
.bar-link:hover,
.bar-link:focus-visible { --edge: var(--cyan); color: #e3fdff; }

/* the clip would cut a focus ring drawn outside the panel, so a cut link draws it inside */
.bar-link:focus-visible,
.machines a:focus-visible {
  outline: 2px solid var(--cyan-text);
  outline-offset: -5px;
}

.game {
  padding-block: 1.75rem clamp(3.5rem, 8vw, 5.5rem);
  background:
    radial-gradient(60% 26rem at 85% 0, rgba(31, 214, 236, .06), transparent 70%),
    radial-gradient(70% 30rem at 10% 0, rgba(196, 63, 208, .09), transparent 70%);
  background-repeat: no-repeat;
}

/* "PC 01" followed by a ruler */
.pc {
  display: flex;
  align-items: center;
  gap: .9rem;
  margin: 0;
  color: var(--ink-dim);
  font-size: .75rem;
  line-height: 1;
}
.pc::after { flex: 1; transform: translateY(1px); }

.game .screen {
  --cut: 26px;
  margin-block: 1rem 1.5rem;
  min-height: 13rem;
  padding: clamp(1.1rem, 3vw, 2rem);
}

@media (min-width: 48rem) {
  .game .screen { aspect-ratio: 21 / 8; }
}

.game .screen-title {
  font-size: clamp(3rem, 12vw, 6rem);
  text-shadow:
    -.02em 0 0 rgba(31, 214, 236, .45),
    0 0 8px var(--glow),
    0 0 28px var(--glow);
}

.game-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .6rem;
  margin-bottom: 2.25rem;
}
.game-meta .play-slot { margin-right: .6rem; }

.game-body {
  display: grid;
  gap: 2.5rem;
  align-items: start;
}

@media (min-width: 54rem) {
  .game-body { grid-template-columns: minmax(0, 1fr) 19rem; gap: 4rem; }
}

.prose { max-width: 38rem; }
.prose > * { margin-block: 0 1.1rem; }
.prose .lead { margin-bottom: 1.5rem; }

.prose h2 {
  margin: 2.25rem 0 1rem;
  color: var(--pink-text);
  font: 700 1.625rem/1.2 var(--font-hud);
}
.prose h2::before {
  content: "// ";
  content: "// " / "";
  color: var(--cyan-text);
  font-weight: 500;
}

.prose ul { list-style: none; padding-left: 0; }
.prose li {
  position: relative;
  margin-bottom: .5rem;
  padding-left: 1.4rem;
}
.prose li::before {
  content: "";
  position: absolute;
  left: .15rem;
  top: .62em;
  width: 7px;
  height: 7px;
  background: var(--pink);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 30% 100%, 0 70%);
}
.prose strong { color: #fff; font-weight: 600; }

/* the spec sheet on the side of the machine */
.spec {
  --cut: 16px;
  --edge: var(--line-hi);
  --fill: linear-gradient(to bottom, var(--panel-hi), var(--panel));
  padding: 1.1rem 1.25rem 1.2rem;
  font-size: .9375rem;
}

.spec h2 {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin: 0 0 .5rem;
  color: var(--cyan-text);
  font-size: .75rem;
  line-height: 1;
}
.spec h2::after { flex: 1; transform: translateY(1px); }

.spec dl { margin: 0; }

.spec dl > div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding-block: .6rem;
  border-top: 1px dashed var(--line);
}
.spec dl > div:first-child { border-top: 0; }

.spec dt {
  flex: none;
  padding-top: .2em;
  color: var(--ink-dim);
  font-size: .6875rem;
  line-height: 1.4;
}
.spec dd { margin: 0; text-align: right; }
.nowrap { white-space: nowrap; }

.machines {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: .75rem 1.5rem;
  margin-top: 3.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  font-size: .8125rem;
  letter-spacing: .06em;
}

.machines a {
  --cut: 9px;
  --edge: var(--line-hi);
  --fill: var(--panel);
  padding: .7rem 1rem;
  color: var(--pink-text);
  text-decoration: none;
}
.machines a:hover,
.machines a:focus-visible { --edge: var(--pink); color: var(--pink-core); }

/* ---------- 404: a machine with no signal ---------- */

/* a screen that is off: the glow stays on the glass, the static is still and dim */
.screen--off {
  --glow: rgba(70, 58, 92, .5);
  --hud: rgba(163, 151, 181, .6);
  --art: url("/img/static.svg");
  --art-size: 240px 240px;
  --art-pos: 0 0;
  --fill: var(--light) #050409;
  align-items: center;
  justify-content: center;
}
.screen--off::before { background: var(--art) var(--art-pos) / var(--art-size) repeat; opacity: .55; }

.no-signal {
  position: relative;
  z-index: 1;
  margin: 0;
  padding: .4rem .8rem;
  background: rgba(5, 4, 9, .85);
  color: var(--ink);
  font-size: .875rem;
  letter-spacing: .3em;
  text-shadow: -2px 0 0 rgba(31, 214, 236, .7), 2px 0 0 rgba(196, 63, 208, .7);
}

.lost h1 {
  margin: 0 0 .75rem;
  color: var(--pink-text);
  font: 700 clamp(2.25rem, 8vw, 3.5rem)/1.1 var(--font-hud);
  text-shadow: 0 0 18px rgba(196, 63, 208, .45);
}

.lost ul { list-style: none; padding: 0; }
.lost li { margin-bottom: .5rem; }
.lost .pc { display: inline-block; min-width: 4.5rem; }
.lost .pc::after { content: none; }

/* ---------- footer ---------- */

.site-foot {
  flex: none;
  position: relative;
  padding-block: 2rem 2.5rem;
  border-top: 1px solid var(--line);
  background: linear-gradient(to bottom, rgba(196, 63, 208, .05), transparent);
  color: var(--ink-soft);
  font-size: .9375rem;
}
.site-foot::before {
  content: "";
  position: absolute;
  top: -1px;
  right: 0;
  width: min(14rem, 40%);
  height: 1px;
  background: linear-gradient(to left, var(--cyan), transparent);
}

.site-foot .wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: .5rem 2rem;
}

.site-foot p { margin: 0; }

.foot-sign {
  color: var(--pink-text);
  font: 700 1.5rem/1 var(--font-hud);
  text-shadow: 0 0 12px rgba(196, 63, 208, .6);
}

/* ---------- the street moves ----------
   The rain falls, the signs hum, the windows of the city go on and off. Every loop moves only
   opacity or transform, so the browser runs it on the compositor: no layout, no paint and no
   filter per frame, and it stops while the tab is hidden. The long cycles are all different
   prime numbers of seconds, started at negative delays, so nothing ticks like a metronome. A
   flicker has at most two dark beats in a second (WCAG 2.3.1 allows three flashes). The LED of
   the "no ar" plate is not here: it is a steady light. */

@media (prefers-reduced-motion: no-preference) {
  .rain-far { animation: rain-far .6s linear infinite; }
  .rain-mid { animation: rain-mid .38s linear infinite; }
  .rain-near { animation: rain-near .3s linear infinite; }

  .lights--1 { animation: out-long 31s linear -9s infinite; }
  .lights--2 { animation: out-twice 43s linear -27s infinite; }
  .lights--3 { animation: out-long 53s linear -40s infinite; }
  .lights--4 { animation: on-long 41s linear -4s infinite; }
  .lights--5 { animation: on-twice 47s linear -18s infinite; }
  .lights--6 { animation: on-long 59s linear -33s infinite; }
  .signs--a { animation: buzz 11s ease-in-out -3s infinite; }
  .signs--b { animation: buzz 19s ease-in-out -12s infinite; }
  .beacons { animation: beacon 2.6s ease-in-out infinite; }

  .blade { animation: hum 29s ease-in-out -11s infinite; }
  .bar-sign { animation: hum 43s ease-in-out -17s infinite; }
  .bar-sign:hover,
  .bar-sign:focus-visible { animation: none; }

  .screen:not(.screen--off)::before { animation: glow 13s ease-in-out infinite; }
  .stations > li:nth-child(3n + 2) .screen::before { animation-duration: 17s; animation-delay: -6s; }
  .stations > li:nth-child(3n) .screen::before { animation-duration: 23s; animation-delay: -15s; }
}

/* each tile falls by exactly its own height, slanted by its own skew */
@keyframes rain-far {
  from { transform: skewX(6deg) translateY(0); }
  to   { transform: skewX(6deg) translateY(140px); }
}
@keyframes rain-mid {
  from { transform: skewX(9deg) translateY(0); }
  to   { transform: skewX(9deg) translateY(200px); }
}
@keyframes rain-near {
  from { transform: skewX(12deg) translateY(0); }
  to   { transform: skewX(12deg) translateY(300px); }
}

/* a neon tube: it breathes, and twice a cycle it stutters */
@keyframes hum {
  0%    { opacity: 1; }
  9%    { opacity: .92; }
  17%   { opacity: 1; }
  21%   { opacity: 1; }
  21.2% { opacity: .35; }
  21.4% { opacity: .9; }
  21.7% { opacity: .5; }
  22%   { opacity: 1; }
  33%   { opacity: .9; }
  45%   { opacity: .98; }
  52%   { opacity: .92; }
  64%   { opacity: 1; }
  64.2% { opacity: .45; }
  64.5% { opacity: 1; }
  77%   { opacity: .9; }
  88%   { opacity: 1; }
  94%   { opacity: .94; }
  100%  { opacity: 1; }
}

/* the light of a game screen: a deeper breath and one stutter */
@keyframes glow {
  0%    { opacity: 1; }
  23%   { opacity: .78; }
  41%   { opacity: .95; }
  57%   { opacity: .82; }
  57.4% { opacity: .4; }
  57.8% { opacity: .9; }
  58.3% { opacity: .55; }
  59%   { opacity: .95; }
  78%   { opacity: .8; }
  100%  { opacity: 1; }
}

/* the small signs on the towers */
@keyframes buzz {
  0%    { opacity: 1; }
  30%   { opacity: .7; }
  52%   { opacity: 1; }
  70%   { opacity: 1; }
  70.5% { opacity: .15; }
  71%   { opacity: 1; }
  71.6% { opacity: .25; }
  72.2% { opacity: 1; }
  88%   { opacity: .75; }
  100%  { opacity: 1; }
}

/* the warning lights on the antennas */
@keyframes beacon {
  0%, 100% { opacity: .15; }
  12%, 40% { opacity: 1; }
  58%      { opacity: .15; }
}

/* lit windows that go dark for a while */
@keyframes out-long {
  0%, 46%     { opacity: 1; }
  46.4%, 79%  { opacity: 0; }
  79.4%, 100% { opacity: 1; }
}

/* lit windows that go dark twice, briefly */
@keyframes out-twice {
  0%, 17%     { opacity: 1; }
  17.4%, 31%  { opacity: 0; }
  31.4%, 70%  { opacity: 1; }
  70.4%, 77%  { opacity: 0; }
  77.4%, 100% { opacity: 1; }
}

/* dark windows that light up for a while, the tube stuttering as it catches */
@keyframes on-long {
  0%, 38%     { opacity: 0; }
  38.3%       { opacity: .7; }
  38.6%       { opacity: .1; }
  39%, 71%    { opacity: 1; }
  71.4%, 100% { opacity: 0; }
}

/* dark windows that light up twice */
@keyframes on-twice {
  0%, 12%     { opacity: 0; }
  12.4%, 33%  { opacity: 1; }
  33.4%, 61%  { opacity: 0; }
  61.4%, 84%  { opacity: 1; }
  84.4%, 100% { opacity: 0; }
}

/* ---------- no motion when asked ---------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }
}
