/*
 * Kentasmic Games: a dark arcade with a neon sign on the back wall and a row of
 * stand-up cabinets and pinball machines on the cosmic carpet. The machines are
 * drawn in CSS and sized in cqi, so each one scales as a whole with its own width.
 */

.arcade-hall {
  background: #0b0718;
  overflow-x: clip;
}

.arcade-hall .footer a { color: var(--ink); }

/* While a game is on, the page holds still and the footer steps out of shot. */
.arcade-playing { overflow: hidden; }
.arcade-playing body { overflow: hidden; }
.arcade-hall .footer { transition: opacity 500ms ease; }
.arcade-playing .footer { opacity: 0; }

.arcade { position: relative; }

.arcade__room {
  position: relative;
  isolation: isolate;
  transform-origin: 0 0;
  min-height: calc(100svh - 70px);
  display: grid;
  grid-template-rows: auto 1fr;
  padding: 0 var(--gutter);
  background:
    /* The back wall, with a few faint panels, meets the carpet near the bottom. */
    linear-gradient(to bottom, transparent 0 62%, rgb(0 0 0 / 0.55) 62%, transparent 64%),
    radial-gradient(60% 40% at 50% 22%, rgb(255 61 168 / 0.16), transparent 70%),
    radial-gradient(50% 30% at 50% 62%, rgb(95 243 255 / 0.10), transparent 70%),
    repeating-linear-gradient(90deg, rgb(255 255 255 / 0.025) 0 2px, transparent 2px 120px);
  overflow: clip;
}

/* The cosmic carpet: scattered neon shapes on near-black. */
.arcade__room::before {
  content: "";
  position: absolute;
  inset: 63% 0 0;
  background-color: #120a24;
  background-image:
    radial-gradient(circle, #ff3da8 0 2px, transparent 3px),
    radial-gradient(circle, #5ff3ff 0 2px, transparent 3px),
    radial-gradient(circle, #ffe45f 0 1.5px, transparent 2.5px),
    linear-gradient(35deg, transparent 46%, rgb(107 255 176 / 0.55) 47% 53%, transparent 54%),
    linear-gradient(to bottom, rgb(0 0 0 / 0.65), transparent 40%);
  background-size: 46px 46px, 62px 62px, 38px 38px, 74px 74px, 100% 100%;
  background-position: 0 0, 20px 30px, 12px 8px, 30px 10px, 0 0;
  z-index: -1;
}

.arcade__sign {
  padding: clamp(24px, 5vw, 56px) 0 clamp(16px, 3vw, 28px);
  text-align: center;
  transition: opacity 600ms ease;
}

.arcade__sign h1 {
  font-family: "Tilt Neon", var(--font-display);
  font-weight: 400;
  font-size: clamp(2.4rem, 8vw, 5.5rem);
  line-height: 1;
  letter-spacing: 0.02em;
}

.arcade__neon { display: inline-block; color: #fff4fb; }
.arcade__neon--pink {
  --glow: #ff3da8;
  text-shadow: 0 0 2px #fff, 0 0 8px var(--glow), 0 0 18px var(--glow), 0 0 42px var(--glow);
}
.arcade__neon--cyan {
  --glow: #2fe6ff;
  color: #effeff;
  text-shadow: 0 0 2px #fff, 0 0 8px var(--glow), 0 0 18px var(--glow), 0 0 42px var(--glow);
}

.arcade__lede { margin-top: 10px; color: var(--ink-soft); }

kbd {
  display: inline-block;
  padding: 1px 7px;
  border: 1px solid currentColor;
  border-bottom-width: 2px;
  border-radius: 5px;
  font: 600 0.8em / 1.4 var(--font-body);
}

/* ---------- The cabinets ---------- */

.arcade__floor {
  list-style: none;
  margin: 0;
  padding: 0 0 clamp(20px, 4vw, 40px);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: end;
  gap: clamp(20px, 4vw, 48px) clamp(8px, 3vw, 48px);
  perspective: 1400px;
}

.cabinet {
  --body: #17121f;
  --trim: color-mix(in oklab, var(--neon) 80%, black);
  position: relative;
  container-type: inline-size;
  /* About 2.4 times as tall as it is wide, so it also has to fit under the sign. */
  width: clamp(64px, min(19vw, (100svh - 260px) / 2.4), 250px);
  transition: transform 1s cubic-bezier(0.55, 0, 0.2, 1), opacity 700ms ease, filter 700ms ease;
}

/* The outer two turn in toward the middle, like a row along a wall. */
.cabinet:first-child:not(:only-child) { transform: rotateY(14deg); }
.cabinet:last-child:not(:only-child) { transform: rotateY(-14deg); }

/* A shadow pooled on the carpet under each cabinet. */
.cabinet::after {
  content: "";
  position: absolute;
  inset: auto -8% -4cqi;
  height: 10cqi;
  background: radial-gradient(closest-side, rgb(0 0 0 / 0.8), transparent);
  z-index: -1;
}

.cabinet__link {
  display: flex;
  flex-direction: column;
  color: inherit;
  text-decoration: none;
  border-radius: 3cqi 3cqi 1cqi 1cqi;
  background:
    linear-gradient(90deg, rgb(255 255 255 / 0.06), transparent 12% 88%, rgb(0 0 0 / 0.35)),
    var(--body);
  /* T-molding down both edges, lit in the game's color. */
  box-shadow:
    inset 1.6cqi 0 0 -0.4cqi var(--trim),
    inset -1.6cqi 0 0 -0.4cqi var(--trim),
    0 0 0 0.6cqi #07050b,
    0 3cqi 8cqi -2cqi rgb(0 0 0 / 0.8);
  transition: transform 200ms ease, box-shadow 200ms ease;
}

.cabinet__link:hover, .cabinet__link:focus-visible {
  transform: translateY(-1.5cqi);
  box-shadow:
    inset 1.6cqi 0 0 -0.4cqi var(--neon),
    inset -1.6cqi 0 0 -0.4cqi var(--neon),
    0 0 0 0.6cqi #07050b,
    0 3cqi 8cqi -2cqi rgb(0 0 0 / 0.8),
    0 0 10cqi -2cqi var(--neon);
}

.cabinet__link:focus-visible { outline-color: var(--neon); outline-offset: 6px; }

/* The backlit marquee across the top. */
.cabinet__marquee {
  display: grid;
  place-items: center;
  min-height: 24cqi;
  margin: 0 -2cqi;
  padding: 3cqi 6cqi;
  border-radius: 3cqi 3cqi 0 0;
  background:
    linear-gradient(to bottom, rgb(255 255 255 / 0.35), transparent 40%),
    radial-gradient(90% 120% at 50% 50%, color-mix(in oklab, var(--neon) 35%, white), var(--neon) 70%, color-mix(in oklab, var(--neon) 70%, black));
  border: 1cqi solid #07050b;
  box-shadow: 0 0 9cqi -1cqi var(--neon);
}

.cabinet__name {
  font: 900 13cqi / 0.9 var(--font-display);
  text-transform: uppercase;
  text-align: center;
  letter-spacing: 0.02em;
  color: #0b0718;
  text-shadow: 0 0.6cqi 0 rgb(255 255 255 / 0.55);
  text-wrap: balance;
}

/* The bezel and screen sit back inside the cabinet. */
.cabinet__bezel {
  display: block;
  margin: 4cqi 6cqi 0;
  padding: 5cqi;
  border-radius: 3cqi;
  background: linear-gradient(to bottom, #050308, #1b1624);
  box-shadow: inset 0 1.5cqi 3cqi rgb(0 0 0 / 0.9);
}

.cabinet__screen {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: 4cqi / 5cqi;
  background: #000;
  box-shadow: 0 0 6cqi -1cqi color-mix(in oklab, var(--neon) 60%, transparent);
}

.cabinet__shot { width: 100%; height: 100%; object-fit: cover; filter: saturate(1.15) brightness(0.9); transition: filter 200ms ease; }

.cabinet__link:hover .cabinet__shot { filter: saturate(1.25) brightness(1.05); }

/* Scanlines and the curved glass of a CRT. */
.cabinet__screen::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(160deg, rgb(255 255 255 / 0.16), transparent 32%),
    repeating-linear-gradient(to bottom, rgb(0 0 0 / 0.22) 0 1px, transparent 1px 3px),
    radial-gradient(120% 120% at 50% 50%, transparent 55%, rgb(0 0 0 / 0.55));
  pointer-events: none;
  transition: opacity 600ms ease;
}

/* The control panel juts out under the screen: a stick and three buttons. */
.cabinet__panel {
  position: relative;
  display: flex;
  align-items: center;
  gap: 5cqi;
  margin: 5cqi -3cqi 0;
  padding: 6cqi 14cqi 5cqi;
  background: linear-gradient(to bottom, #2b2436, #1a1522 70%, #0d0a12);
  border-top: 1.4cqi solid var(--trim);
  clip-path: polygon(4% 0, 96% 0, 100% 100%, 0 100%);
}

.cabinet__stick {
  position: relative;
  width: 6cqi;
  height: 6cqi;
  margin-right: auto;
  border-radius: 50%;
  background: #0a0710;
}

.cabinet__stick::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 50%;
  width: 1.6cqi;
  height: 9cqi;
  translate: -50% 0;
  background: #bbb3c9;
  border-radius: 1cqi;
}

.cabinet__stick::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 9cqi;
  width: 8cqi;
  height: 8cqi;
  translate: -50% 0;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, color-mix(in oklab, var(--neon) 40%, white), var(--neon) 55%, color-mix(in oklab, var(--neon) 50%, black));
}

.cabinet__button {
  width: 7cqi;
  height: 7cqi;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fff 0 8%, var(--neon) 30%, color-mix(in oklab, var(--neon) 45%, black));
  box-shadow: 0 0.8cqi 0 #07050b;
}

.cabinet__button:nth-of-type(3) { --neon: #ffe45f; }
.cabinet__button:nth-of-type(4) { --neon: #5ff3ff; }

/* The lower body: the game's pitch and a coin door. */
.cabinet__body {
  display: grid;
  gap: 6cqi;
  justify-items: center;
  padding: 7cqi 9cqi 9cqi;
  border-top: 0.6cqi solid #07050b;
}

.cabinet__tagline {
  font-size: max(11px, 6cqi);
  line-height: 1.35;
  text-align: center;
  color: var(--ink-soft);
}

.cabinet__coins {
  display: flex;
  gap: 4cqi;
  padding: 4cqi 5cqi;
  border-radius: 1.5cqi;
  background: linear-gradient(to bottom, #3a3346, #221d2b);
  box-shadow: inset 0 0 0 0.6cqi #4c4458;
}

.cabinet__coins span {
  padding: 1cqi 2.4cqi;
  border-radius: 1cqi;
  background: #3b0a0a;
  color: #ff5a4a;
  font: 700 5cqi / 1.2 var(--font-display);
  text-shadow: 0 0 2cqi #ff3b2a;
  box-shadow: 0 0 3cqi -0.5cqi #ff3b2a;
}

/* Too narrow for the pitch on small phones; the marquee says enough. */
@container (max-width: 150px) {
  .cabinet__tagline { display: none; }
}

/* ---------- The pinball machine ---------- */

/* Wider than an upright and about as tall, with the backbox reaching up to the marquees. */
.cabinet--pinball {
  width: clamp(88px, min(25vw, (100svh - 260px) / 1.85), 320px);
}

.pinball {
  display: flex;
  flex-direction: column;
  align-items: center;
  background: none;
  box-shadow: none;
  border-radius: 0;
}

.pinball:hover, .pinball:focus-visible { box-shadow: none; }

/* The backbox: a lit backglass with the game's name, and a dot-matrix display under it. */
.pinball__backbox {
  position: relative;
  display: grid;
  gap: 2.5cqi;
  width: 86cqi;
  padding: 3cqi;
  border-radius: 3cqi 3cqi 1cqi 1cqi;
  background: linear-gradient(90deg, rgb(255 255 255 / 0.06), transparent 15% 85%, rgb(0 0 0 / 0.35)), var(--body);
  box-shadow:
    inset 1.4cqi 0 0 -0.4cqi var(--trim),
    inset -1.4cqi 0 0 -0.4cqi var(--trim),
    0 0 0 0.5cqi #07050b;
  transition: opacity 600ms ease 300ms, transform 200ms ease;
}

.pinball__glass {
  display: grid;
  place-items: center;
  aspect-ratio: 5 / 3;
  padding: 4cqi;
  border-radius: 1.5cqi;
  border: 0.8cqi solid #07050b;
  background:
    radial-gradient(circle at 22% 30%, #fff 0 0.5cqi, transparent 0.8cqi),
    radial-gradient(circle at 78% 22%, #fff 0 0.4cqi, transparent 0.7cqi),
    radial-gradient(circle at 64% 80%, #fff 0 0.35cqi, transparent 0.6cqi),
    radial-gradient(circle at 12% 76%, #fff 0 0.3cqi, transparent 0.6cqi),
    radial-gradient(circle at 80% 72%, #ffcf8a 0 7cqi, #e2507a 11cqi, transparent 11.5cqi),
    radial-gradient(70% 90% at 30% 40%, color-mix(in oklab, var(--neon) 65%, transparent), transparent 70%),
    radial-gradient(60% 80% at 80% 20%, rgb(255 61 168 / 0.45), transparent 70%),
    #0b0520;
  box-shadow: 0 0 9cqi -1cqi var(--neon);
}

.cabinet--pinball .cabinet__name {
  font-size: 15cqi;
  color: #fff6e0;
  text-shadow: 0 0 1cqi #fff, 0 0 3cqi #ff9b3d, 0 0 7cqi #ff3d8a;
  font-style: italic;
}

.pinball__dmd {
  padding: 1.5cqi;
  border-radius: 1cqi;
  background:
    radial-gradient(circle, transparent 0.3cqi, #1b0a04 0.45cqi) 0 0 / 1.2cqi 1.2cqi,
    #ff7a1a;
  background-clip: padding-box;
  color: transparent;
  font: 900 6cqi / 1 var(--font-display);
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  box-shadow: inset 0 0 0 10cqi #1b0a04;
  position: relative;
}

/* The display's lit letters, seen through the dot grid. */
.pinball__dmd::before {
  content: "Insert coin";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #ff8a2a;
  text-shadow: 0 0 2cqi #ff7a1a;
  -webkit-mask: radial-gradient(circle, #000 0.4cqi, transparent 0.5cqi) 0 0 / 1.2cqi 1.2cqi;
  mask: radial-gradient(circle, #000 0.4cqi, transparent 0.5cqi) 0 0 / 1.2cqi 1.2cqi;
}

/* The playfield slopes away from you; the camera sees it end-on until it flies overhead. */
.pinball__table {
  position: relative;
  z-index: 1;
  width: 100cqi;
  height: 46cqi;
  margin-top: -2cqi;
  perspective: 90cqi;
  perspective-origin: 50% 0%;
}

/* The cabinet's sides, flaring out toward the front. */
.pinball__table::before {
  content: "";
  position: absolute;
  inset: 0;
  clip-path: polygon(7% 0, 93% 0, 100% 100%, 0 100%);
  background: linear-gradient(90deg, var(--trim) 0 4%, var(--body) 4% 96%, var(--trim) 96%);
}

.pinball__playfield {
  position: absolute;
  left: 7cqi;
  right: 7cqi;
  bottom: 2cqi;
  aspect-ratio: 480 / 1000;
  border-radius: 1cqi;
  transform-origin: 50% 100%;
  transform: rotateX(64deg);
  box-shadow: 0 0 6cqi -1cqi color-mix(in oklab, var(--neon) 60%, transparent);
}

/* Glass over the playfield, not a CRT. */
.pinball__playfield::after {
  background: linear-gradient(170deg, rgb(255 255 255 / 0.18), transparent 30% 70%, rgb(255 255 255 / 0.06));
}

/* The front of the cabinet: lockdown bar, flipper buttons and the coin door. */
.pinball__front {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: start;
  justify-content: space-between;
  width: 100cqi;
  border-top: 2.4cqi solid #c9c4d6;
  background: linear-gradient(to bottom, #241d2e, var(--body) 30%, #0d0a12);
  box-shadow:
    inset 1.6cqi 0 0 -0.4cqi var(--trim),
    inset -1.6cqi 0 0 -0.4cqi var(--trim),
    0 3cqi 8cqi -2cqi rgb(0 0 0 / 0.8);
}

.pinball__front .cabinet__body {
  flex: 1;
  border-top: 0;
  padding: 4cqi 4cqi 6cqi;
  gap: 4cqi;
}

.cabinet--pinball .cabinet__tagline { font-size: max(11px, 5cqi); }

.pinball__button {
  width: 5cqi;
  height: 7cqi;
  margin-top: 5cqi;
  background: radial-gradient(circle at 40% 35%, #fff 0 10%, var(--neon) 40%, color-mix(in oklab, var(--neon) 45%, black));
}

.pinball__button:first-child { border-radius: 0 50% 50% 0; }
.pinball__button:last-child { border-radius: 50% 0 0 50%; }

/* Chrome legs, splayed a little. */
.pinball__legs {
  position: relative;
  width: 100cqi;
  height: 20cqi;
}

.pinball__legs::before, .pinball__legs::after {
  content: "";
  position: absolute;
  top: 0;
  width: 6cqi;
  height: 100%;
  background: linear-gradient(90deg, #6d6878, #e9e6f0 40%, #8a8596);
  clip-path: polygon(0 0, 100% 0, 85% 100%, 15% 100%);
}

.pinball__legs::before { left: 4cqi; transform: skewX(6deg); }
.pinball__legs::after { right: 4cqi; transform: skewX(-6deg); }

.pinball:hover .pinball__backbox, .pinball:focus-visible .pinball__backbox {
  transform: translateY(-1.5cqi);
}

.pinball:hover .pinball__glass, .pinball:focus-visible .pinball__glass {
  box-shadow: 0 0 14cqi 0 var(--neon);
}

@container (max-width: 190px) {
  .cabinet--pinball .cabinet__tagline { display: none; }
}

/* ---------- Swooping in ---------- */

/* The chosen cabinet turns to face the camera and the rest of the room goes dark. */
.arcade-playing .cabinet--chosen { transform: none; }
.arcade-playing .cabinet:not(.cabinet--chosen) { opacity: 0.25; filter: brightness(0.5); }
.arcade-playing .arcade__sign { opacity: 0.2; }
.arcade-playing .cabinet--chosen .cabinet__screen::after { opacity: 0; }
.arcade-playing .cabinet__link { transform: none; transition: none; }

/* Flying up over a pinball machine, the backbox drops out of shot behind the camera. */
.arcade-playing .cabinet--chosen .pinball__backbox { opacity: 0; transform: none; }

.arcade__stage {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: #000;
}

.arcade__stage[hidden] { display: none; }

.arcade__game {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: #000;
}

/* The tube warms up from a bright line when the game switches on, and
   collapses back to one when it switches off. */
@media (prefers-reduced-motion: no-preference) {
  .arcade__stage { animation: crt-on 420ms cubic-bezier(0.2, 0.7, 0.2, 1) both; }
  .arcade__stage--off { animation: crt-off 260ms ease-in both; }

  @keyframes crt-on {
    0%   { clip-path: inset(49.6% 0); filter: brightness(4); }
    55%  { clip-path: inset(0 0); filter: brightness(1.8); }
    100% { clip-path: inset(0 0); filter: none; }
  }

  @keyframes crt-off {
    0%   { clip-path: inset(0 0); filter: none; }
    60%  { clip-path: inset(49.6% 0); filter: brightness(3); }
    100% { clip-path: inset(49.6% 50%); filter: brightness(3); }
  }

  /* A pinball game isn't a picture tube: the lights just come up, and go down again. */
  .arcade__stage--overhead { animation: lights-on 380ms ease-out both; }
  .arcade__stage--overhead.arcade__stage--off { animation: lights-off 260ms ease-in both; }

  @keyframes lights-on {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  @keyframes lights-off {
    from { opacity: 1; }
    to   { opacity: 0; }
  }
}

/* A quiet way back for screens without an Esc key. */
.arcade__exit {
  position: absolute;
  left: 50%;
  bottom: max(10px, env(safe-area-inset-bottom));
  translate: -50% 0;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
  padding: 6px 14px;
  border: 1px solid rgb(255 255 255 / 0.35);
  border-radius: 999px;
  background: rgb(11 7 24 / 0.7);
  color: #f1ecff;
  font: 600 var(--step--1) / 1 var(--font-body);
  opacity: 0.55;
  cursor: pointer;
  transition: opacity 150ms ease;
}

.arcade__exit:hover, .arcade__exit:focus-visible { opacity: 1; }

/* On touch screens the game is played with taps along its bottom edge, so the
   button shrinks to an arrow in the top corner, out in the black bars beside the game. */
@media (hover: none) {
  .arcade__exit {
    left: max(8px, env(safe-area-inset-left));
    top: max(8px, env(safe-area-inset-top));
    bottom: auto;
    translate: none;
    justify-content: center;
    width: 36px;
    padding: 0;
  }

  .arcade__exit::before { content: "←"; font-size: 18px; }
  .arcade__exit kbd { display: none; }

  .arcade__exit-label {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap;
  }
}
