@font-face {
  font-family: "Overpass";
  src: url("/fonts/overpass-latin.woff2") format("woff2");
  font-weight: 600 900;
  font-display: swap;
}

:root {
  --wall: #D6DDD5;
  --wall-dim: #A9B3A8;
  --glass: #F4F5F1;
  --ink: #000;
  --box: min(80vw, 52svh, 380px);
}

/* Call points come in standard colours; each alarm takes one. */

.station-ceo {
  --body-hi: #E2252B;
  --body: #D2141B;
  --body-lo: #B80F15;
  --recess: #8C0C11;
  --edge: #7E0A0E;
  --print: #FFF;
  --title: 0.1;
  --lens-off: #B8231C, #7A100D;
  --lens-on: #FFF1DC 0 10%, #FF7050 32%, #FF4A36 55%, #C21510 100%;
  --beam: 255 60 40;
}

.station-doomscroll {
  --body-hi: #2F74DA;
  --body: #1D5FC4;
  --body-lo: #164FA6;
  --recess: #0C3372;
  --edge: #0B2D63;
  --print: #FFF;
  --title: 0.078;
  --lens-off: #2A5DAE, #12305F;
  --lens-on: #EAF4FF 0 10%, #8CC2FF 32%, #3D8BFF 55%, #1446A0 100%;
  --beam: 60 130 255;
}

.station-evaluation {
  --body-hi: #FFD83A;
  --body: #F6C200;
  --body-lo: #DEA800;
  --recess: #7A5C00;
  --edge: #A07C00;
  --print: #000;
  --title: 0.088;
  --lens-off: #C27C10, #7A4A05;
  --lens-on: #FFF6D6 0 10%, #FFE08A 32%, #FFB21E 55%, #C77800 100%;
  --beam: 255 170 30;
}

html,
body {
  margin: 0;
}

body {
  background: var(--wall);
  color: var(--ink);
  font-family: "Overpass", system-ui, sans-serif;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 0.4s;
}

body.is-ringing {
  background: var(--wall-dim);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.wall {
  position: relative;
  box-sizing: border-box;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--box) * 0.3);
  padding: calc(var(--box) * 0.12) 16px calc(24px + env(safe-area-inset-bottom));
  overflow: hidden;
}

.wall.is-shaking {
  animation: shake 0.8s linear both;
}

.station {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--box) * 0.07);
}

/* Sounder beacon mounted above each call point. Its beam is what lights the wall. */

.beacon {
  position: relative;
  width: calc(var(--box) * 0.26);
  height: calc(var(--box) * 0.2);
  display: flex;
  flex-direction: column;
  align-items: center;
}

.lens {
  position: relative;
  z-index: 1;
  width: 78%;
  flex: 1;
  border-radius: 50% 50% 6% 6% / 100% 100% 6% 6%;
  background:
    radial-gradient(ellipse at 34% 30%, rgb(255 255 255 / 0.45), transparent 34%),
    linear-gradient(var(--lens-off));
  box-shadow: inset 0 -3px 0 rgb(0 0 0 / 0.25);
}

.beacon-base {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 28%;
  border-radius: 3px 3px 5px 5px;
  background:
    repeating-linear-gradient(90deg, transparent 0 3px, rgb(0 0 0 / 0.32) 3px 4px) 50% 50% / 58% 46% no-repeat,
    linear-gradient(#EEF0EB, #C9CEC7);
  box-shadow: 0 6px 10px -6px rgb(0 0 0 / 0.45);
}

.beam {
  position: absolute;
  z-index: 0;
  left: 50%;
  top: 40%;
  width: 180vmax;
  height: 180vmax;
  translate: -50% -50%;
  pointer-events: none;
  background: conic-gradient(
    rgb(var(--beam) / 0.8) 0deg,
    rgb(var(--beam) / 0.3) 8deg,
    transparent 18deg 162deg,
    rgb(var(--beam) / 0.3) 172deg,
    rgb(var(--beam) / 0.8) 180deg,
    rgb(var(--beam) / 0.3) 188deg,
    transparent 198deg 342deg,
    rgb(var(--beam) / 0.3) 352deg,
    rgb(var(--beam) / 0.8) 360deg
  );
  -webkit-mask-image: radial-gradient(circle, #000 3%, rgb(0 0 0 / 0.55) 22%, transparent 55%);
  mask-image: radial-gradient(circle, #000 3%, rgb(0 0 0 / 0.55) 22%, transparent 55%);
  opacity: 0;
  transition: opacity 0.3s;
}

.station.is-ringing .beam {
  opacity: 1;
  animation: sweep 1.2s linear infinite;
}

.station.is-ringing .lens {
  background: radial-gradient(ellipse at 50% 85%, var(--lens-on));
  box-shadow: 0 0 calc(var(--box) * 0.14) calc(var(--box) * 0.03) rgb(var(--beam) / 0.6);
  animation: throb 0.6s ease-in-out infinite alternate;
}

/* The manual call point */

.callpoint {
  position: relative;
  z-index: 1;
  box-sizing: border-box;
  width: var(--box);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(var(--box) * 0.035);
  padding: calc(var(--box) * 0.06) calc(var(--box) * 0.13) calc(var(--box) * 0.13);
  border-radius: calc(var(--box) * 0.07);
  background: linear-gradient(170deg, var(--body-hi), var(--body) 40%, var(--body-lo));
  box-shadow:
    inset 0 2px 1px rgb(255 255 255 / 0.28),
    inset 0 -4px 2px rgb(0 0 0 / 0.2),
    0 3px 0 var(--edge),
    0 24px 40px -18px rgb(30 40 30 / 0.6);
}

/* Each name is sized to fit its box (--title, a fraction of the box width); the block's fixed
   height and the fixed-size "alarm" line keep the three glass panels level. */
.callpoint-title {
  box-sizing: border-box;
  height: calc(var(--box) * 0.17);
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--print);
  font-size: calc(var(--box) * var(--title));
  font-weight: 900;
  line-height: 0.95;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  text-shadow: 0 -1px 0 rgb(0 0 0 / 0.25), 0 1px 0 rgb(255 255 255 / 0.25);
  white-space: nowrap;
}

.callpoint-title span {
  margin-top: calc(var(--box) * 0.01);
  font-size: calc(var(--box) * 0.062);
  letter-spacing: 0.08em;
}

.recess {
  box-sizing: border-box;
  width: 100%;
  aspect-ratio: 1;
  padding: calc(var(--box) * 0.02);
  border-radius: calc(var(--box) * 0.02);
  background: var(--recess);
  box-shadow: inset 0 3px 6px rgb(0 0 0 / 0.45), 0 1px 0 rgb(255 255 255 / 0.2);
}

.glass {
  appearance: none;
  position: relative;
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: calc(var(--box) * 0.012);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5%;
  background: var(--glass);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
  box-shadow: inset 0 0 0 2px rgb(0 0 0 / 0.07), 0 4px 0 #C9CCC4, 0 6px 8px rgb(0 0 0 / 0.35);
  transition: translate 0.08s, box-shadow 0.08s;
}

.glass::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(125deg, rgb(255 255 255 / 0.85) 0 11%, transparent 12%);
  pointer-events: none;
}

.glass:active,
.station.is-ringing .glass {
  translate: 0 3px;
  box-shadow: inset 0 0 0 2px rgb(0 0 0 / 0.07), 0 1px 0 #C9CCC4, 0 1px 2px rgb(0 0 0 / 0.35);
}

.glass:focus-visible {
  outline: 4px solid var(--print);
  outline-offset: 3px;
}

.pictogram {
  width: 46%;
  fill: var(--ink);
}

.glass-label {
  font-size: calc(var(--box) * 0.085);
  font-weight: 900;
  line-height: 1;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.crack {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: rgb(25 25 25 / 0.6);
  stroke-width: 0.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 1px 0 rgb(255 255 255 / 0.9));
  opacity: 0;
  transition: opacity 0.6s;
}

.crack path {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 0s 0.6s;
}

.station.is-ringing .crack {
  opacity: 1;
  transition: none;
}

.station.is-ringing .crack path {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 0.22s ease-out;
}

.screw {
  position: absolute;
  bottom: calc(var(--box) * 0.045);
  width: calc(var(--box) * 0.05);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #F2F2EE, #A7ABA4 60%, #7C807A);
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.25), 0 1px 0 rgb(255 255 255 / 0.25);
}

.screw::after {
  content: "";
  position: absolute;
  inset: 44% 16%;
  border-radius: 1px;
  background: rgb(0 0 0 / 0.5);
}

.screw-left { left: calc(var(--box) * 0.06); rotate: 35deg; }
.screw-right { right: calc(var(--box) * 0.06); rotate: -20deg; }

.status {
  position: relative;
  z-index: 1;
  margin: 0;
  max-width: 30ch;
  min-height: 2.6em;
  font-size: clamp(1rem, 1.6vw + 0.7rem, 1.25rem);
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
  text-wrap: balance;
}

.credits {
  position: relative;
  z-index: 1;
  margin-top: auto;
  color: #2E382F;
  font-size: 0.8125rem;
  font-weight: 600;
}

.credits:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

/* The evaluation alarm's bomb: flash, fireball, smoke, and a scorch mark that fades. */

.station-evaluation .callpoint {
  z-index: 2;
}

.station-evaluation .callpoint::after {
  content: "";
  position: absolute;
  inset: -8% -10% -12%;
  z-index: 2;
  border-radius: 40% 40% 50% 50% / 55% 55% 45% 45%;
  background:
    radial-gradient(ellipse 52% 58% at 50% 46%, rgb(22 15 8 / 0.95), rgb(22 15 8 / 0.6) 45%, transparent 72%),
    radial-gradient(ellipse 28% 42% at 50% 18%, rgb(22 15 8 / 0.7), transparent 70%);
  mix-blend-mode: multiply;
  pointer-events: none;
  opacity: 0;
  transition: opacity 2.5s;
}

.station-evaluation.is-exploded .callpoint::after {
  opacity: 1;
  transition: opacity 0.15s;
}

.blast {
  position: absolute;
  z-index: 3;
  left: 50%;
  top: 55%;
  width: calc(var(--box) * 1.3);
  aspect-ratio: 1;
  translate: -50% -50%;
  pointer-events: none;
}

.fireball {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
}

.smoke {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 40%;
  aspect-ratio: 1;
  border-radius: 50%;
  translate: -50% -50%;
  background: radial-gradient(circle, rgb(55 52 48 / 0.8), rgb(55 52 48 / 0) 70%);
  opacity: 0;
}

.is-exploded .fireball {
  animation: fireball 1s ease-out forwards;
}

.is-exploded .smoke {
  animation: smoke 2.4s ease-out forwards;
}

.flash {
  position: fixed;
  inset: 0;
  z-index: 10;
  pointer-events: none;
  background: radial-gradient(circle at var(--fx, 50%) var(--fy, 50%), #FFFBEA 0, rgb(255 214 120 / 0.9) 18%, rgb(255 140 30 / 0.45) 42%, transparent 75%);
  opacity: 0;
}

.flash.is-flashing {
  animation: flash 0.9s ease-out;
}

/* One signature move per alarm while it rings. */

/* CEO: the boss gets closer, step by step, arriving as the voice shouts. */
.station-ceo .pictogram {
  transform-origin: 50% 100%;
}

.station-ceo.is-ringing .pictogram {
  animation:
    loom var(--ring, 7s) cubic-bezier(0.7, 0, 0.95, 0.45) forwards,
    stride 0.7s ease-in-out infinite alternate;
}

/* Doom scroll: the feed on the phone never ends. */
.station-doomscroll.is-ringing .feed {
  animation: doomscroll 0.9s linear infinite;
}

/* Evaluation: the fuse burns down to the bomb, which swells, then is gone at the boom. */
.station-evaluation .fuse {
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
}

.station-evaluation .spark > * {
  transform-box: fill-box;
  transform-origin: center;
}

.station-evaluation .pictogram {
  transition: opacity 0.6s 0.4s;
}

.station-evaluation.is-fused .fuse { animation: burn var(--fuse, 1.3s) linear forwards; }
.station-evaluation.is-fused .spark { animation: travel var(--fuse, 1.3s) linear forwards; }
.station-evaluation.is-fused .spark > * { animation: flicker 0.3s ease-in-out infinite alternate; }
.station-evaluation.is-fused .pictogram { animation: swell var(--fuse, 1.3s) cubic-bezier(0.85, 0, 1, 0.4) forwards; }

.station-evaluation.is-exploded .pictogram {
  opacity: 0;
  animation: none;
  transition: none;
}

@keyframes loom {
  to { scale: 1.3; }
}

@keyframes stride {
  from { translate: -2.5% 0; rotate: -2deg; }
  to { translate: 2.5% 0; rotate: 2deg; }
}

@keyframes doomscroll {
  to { transform: translateY(-72px); } /* one screen of posts, in SVG units */
}

@keyframes burn {
  to { stroke-dashoffset: 1; }
}

@keyframes travel {
  50% { transform: translate(-7px, 8px); }
  100% { transform: translate(-12px, 17px); }
}

@keyframes flicker {
  from { scale: 0.8; rotate: -12deg; }
  to { scale: 1.3; rotate: 12deg; }
}

@keyframes swell {
  to { scale: 1.14; }
}

@keyframes sweep {
  to { rotate: 1turn; }
}

@keyframes throb {
  from { filter: brightness(0.85); }
  to { filter: brightness(1.15); }
}

@keyframes fireball {
  0% { opacity: 1; scale: 0.1; }
  30% { opacity: 1; scale: 1.1; }
  100% { opacity: 0; scale: 1.35; }
}

@keyframes smoke {
  0% { opacity: 0; transform: translate(0, 0) scale(0.3); }
  15% { opacity: 0.9; }
  100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(1.8); }
}

@keyframes flash {
  0% { opacity: 0; }
  6% { opacity: 1; }
  100% { opacity: 0; }
}

@keyframes shake {
  8% { translate: -12px 6px; }
  20% { translate: 10px -5px; }
  34% { translate: -7px 3px; }
  50% { translate: 5px -2px; }
  68% { translate: -3px 1px; }
  84% { translate: 1px 0; }
  100% { translate: 0 0; }
}

@keyframes fade-out {
  0%, 40% { opacity: 1; }
  100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .station.is-ringing .beam {
    animation: none;
    background: radial-gradient(circle, rgb(var(--beam) / 0.4), transparent 30%);
  }

  .station.is-ringing .lens,
  .wall.is-shaking,
  .flash.is-flashing,
  .is-exploded .smoke,
  .station-doomscroll.is-ringing .feed,
  .station-evaluation.is-fused .spark > *,
  .station-evaluation.is-fused .pictogram {
    animation: none;
  }

  /* The boss still arrives, just without walking. */
  .station-ceo.is-ringing .pictogram {
    animation: none;
    scale: 1.2;
    transition: scale 0.5s;
  }

  .is-exploded .fireball {
    animation: fade-out 1.2s ease-out forwards;
  }

  .glass,
  .crack,
  .crack path,
  .station.is-ringing .crack path {
    transition: none;
  }
}
