/* The slide projector gallery: a pull-down screen at the top, a carousel projector at the bottom throwing its slide
   up through a beam of dusty light, and the corded remote beside it. All of it sits on a black page: the light
   comes from the lamp. */
:root {
  --page: #000000;          /* the page: the dark room */
  --cloth: #ece8df;         /* the screen's cloth where the light falls */
  --cloth-dark: #121212;    /* and where it does not */
  --roller: #2c2c2f;        /* the screen's roller case and its bar */
  --lamp: #ffd394;          /* the tungsten lamp */
  --lamp-deep: #ff9a3d;     /* its glow through the vents */
  --body: #574a40;          /* the projector's warm brown plastic */
  --body-dark: #251e1a;
  --deck: #a9a398;          /* its satin aluminium deck */
  --deck-dark: #5a554d;
  --tray: #1d1b1a;          /* the round tray, black plastic */
  --tray-edge: #5a5652;
  --mount: #f1eee7;         /* a white plastic slide mount */
  --mount-card: #e7dbc0;    /* a cardboard one */
  --mount-grey: #d3d2cd;    /* a grey one */
  --pen: #2a3c8f;           /* the ballpoint that wrote the captions */
  --pen-felt: #26232b;      /* the felt tip */
  --remote: #3a2a21;        /* the remote's chocolate plastic */
  --remote-face: #d8cdb9;   /* its cream face */
  --key: #efe9dd;           /* its keys */
  --key-press: #d9d0c0;
  --label: #5b4a3d;         /* the words on the remote */
  --ring: #ffc56e;          /* the ring of the focus from the keys */
}

* {
  box-sizing: border-box;
}

html {
  touch-action: manipulation;
}

html,
body {
  margin: 0;
}

body {
  min-height: 100svh;
  background: var(--page);
  color: var(--cloth);
  font-family: 'Archivo Variable', system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.stage {
  min-height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
  padding: 28px 16px;
}

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

/* ---------------------------------------------------------------- the box: drawn at one size, scaled to fit */
.show {
  position: relative;
  width: var(--fit-w, 620px);
  height: var(--fit-h, 572px);
  max-width: 100%;
  touch-action: pan-y;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
}

.show__fit {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--design-w, 620px);
  height: var(--design-h, 572px);
  transform-origin: 0 0;
  transform: scale(var(--s, 1));
}

/* ---------------------------------------------------------------- the screen */
.screen {
  position: absolute;
  margin: 0;
  left: var(--scr-x);
  top: var(--scr-y);
  width: var(--scr-w);
  height: var(--scr-h);
}

.screen__roller {
  position: absolute;
  left: -14px;
  right: -14px;
  top: -12px;
  height: 15px;
  border-radius: 8px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0) 45%, rgba(0, 0, 0, 0.5)),
    var(--roller);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.04);
}

.screen__roller::before,
.screen__roller::after {
  content: '';
  position: absolute;
  top: 2px;
  width: 9px;
  height: 11px;
  border-radius: 3px;
  background: linear-gradient(180deg, #4a4a4e, #1b1b1d);
}

.screen__roller::before {
  left: 0;
}

.screen__roller::after {
  right: 0;
}

.screen__cloth {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--cloth-dark);
}

/* the light the slide's mount lets past its edges, soft on the cloth round the picture */
.screen__spill {
  position: absolute;
  left: calc(var(--ap-x) - 40px);
  top: calc(var(--ap-y) - 40px);
  width: calc(var(--ap-w) + 80px);
  height: calc(var(--ap-h) + 80px);
  border-radius: 30px;
  background: radial-gradient(closest-side, rgba(255, 226, 180, 0.2), rgba(255, 226, 180, 0.05) 70%, rgba(255, 226, 180, 0));
  opacity: var(--lit, 0);
}

.screen__gate {
  position: absolute;
  left: var(--ap-x);
  top: var(--ap-y);
  width: var(--ap-w);
  height: var(--ap-h);
  overflow: hidden;
  border-radius: 3px;
  background: #050403;
  will-change: filter;
}

.screen__pic {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  display: block;
}

.screen__pic--fade {
  opacity: 0;
}

/* the tungsten lamp warms every colour a little */
.screen__warm {
  position: absolute;
  inset: 0;
  background: var(--lamp);
  mix-blend-mode: multiply;
  opacity: var(--warmth, 0.35);
  pointer-events: none;
}

.screen__vignette {
  position: absolute;
  inset: 0;
  background: radial-gradient(farthest-corner at 50% 48%, rgba(0, 0, 0, 0) 38%, rgba(10, 5, 0, 0.42) 82%, rgba(6, 3, 0, 0.78));
  opacity: var(--vignette, 0.55);
  pointer-events: none;
}

/* the hot spot where the lamp is brightest */
.screen__hot {
  position: absolute;
  inset: 0;
  background: radial-gradient(52% 58% at 50% 46%, rgba(255, 244, 222, 0.22), rgba(255, 244, 222, 0));
  mix-blend-mode: screen;
  pointer-events: none;
}

/* the matte weave of the cloth, over everything on it */
.screen__weave {
  position: absolute;
  inset: 0;
  background-image:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.025) 0 1px, rgba(0, 0, 0, 0.03) 1px 2px),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.02) 0 1px, rgba(0, 0, 0, 0.025) 1px 2px);
  pointer-events: none;
}

.screen__batten {
  position: absolute;
  left: -4px;
  right: -4px;
  bottom: -9px;
  height: 10px;
  border-radius: 3px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0) 50%, rgba(0, 0, 0, 0.45)),
    var(--roller);
}

.screen__pull {
  position: absolute;
  left: 50%;
  top: 8px;
  width: 22px;
  height: 14px;
  margin-left: -11px;
  border: 3px solid #3a3a3e;
  border-top: 0;
  border-radius: 0 0 12px 12px;
}

/* ---------------------------------------------------------------- the beam and the cord */
.beam {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  mix-blend-mode: screen;
}

.cord {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.cord path {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.cord path:first-child {
  stroke: #17110d;
  stroke-width: 6;
}

.cord path:last-child {
  stroke: rgba(255, 214, 160, 0.16);
  stroke-width: 1.4;
}

/* ---------------------------------------------------------------- the projector, in CSS 3D */
.room {
  position: absolute;
  inset: 0;
  perspective: var(--persp, 1150px);
  perspective-origin: var(--eye-x) var(--eye-y);
  pointer-events: none;
}

.world,
.world .g {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  transform-style: preserve-3d;
}

.world {
  left: var(--eye-x);
  top: var(--eye-y);
}

.world .f {
  position: absolute;
  left: 0;
  top: 0;
}

/* the warm pool the lamp throws on the table round the projector */
.pool {
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 168, 82, 0.16), rgba(255, 150, 70, 0.05) 55%, rgba(255, 140, 60, 0));
  opacity: var(--lamp-on, 1);
}

.body__top {
  border-radius: 14px;
  background:
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 0 1px, rgba(0, 0, 0, 0.04) 1px 3px),
    radial-gradient(120% 60% at 50% 0%, rgba(214, 226, 240, 0.35), rgba(214, 226, 240, 0) 60%),
    linear-gradient(180deg, #8a857c 0%, var(--deck) 30%, #8f897f 62%, var(--deck-dark) 100%);
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.18), inset 0 2px 0 3px rgba(255, 255, 255, 0.12);
}

/* the round seat of the tray, cut in the deck */
.body__seat {
  border-radius: 50%;
  background: radial-gradient(closest-side, #1a1715 88%, #3c3833 96%, rgba(60, 56, 51, 0));
}

.body__rear {
  border-radius: 6px 6px 3px 3px;
  background: linear-gradient(180deg, #6a5b4f 0%, var(--body) 18%, #43382f 80%, var(--body-dark) 100%);
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.12);
}

.body__side {
  border-radius: 6px 6px 3px 3px;
  background: linear-gradient(180deg, #43382f, var(--body-dark));
}

.body__side--lit {
  background: linear-gradient(180deg, #5d4f44, #2c241f);
}

/* the vents on the back, with the lamp glowing through them */
.vents {
  position: absolute;
  display: grid;
  gap: 4px;
}

.vents span {
  display: block;
  height: 4px;
  border-radius: 2px;
  background: #120d0a;
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.6);
  position: relative;
  overflow: hidden;
}

.vents span::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(255, 150, 60, 0.15), var(--lamp-deep) 35%, var(--lamp) 50%, var(--lamp-deep) 65%, rgba(255, 150, 60, 0.15));
  opacity: calc(var(--lamp-on, 1) * 0.85);
}

.socket {
  position: absolute;
  width: 16px;
  height: 16px;
  border-radius: 4px;
  background: radial-gradient(circle at 50% 50%, #0b0807 34%, #2b2420 38%, #3d332c 70%, #221c18);
}

.badge {
  position: absolute;
  font-size: 7.5px;
  font-weight: 600;
  font-stretch: 80%;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(225, 210, 190, 0.5);
  white-space: nowrap;
}

/* the tray: black plastic */
.tray__floor {
  border-radius: 50%;
  background: radial-gradient(closest-side, #2b2826 30%, var(--tray) 62%, #121110 97%, #2e2b29);
}

.tray__wall {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0) 30%), var(--tray);
}

.tray__rim {
  border-radius: 50%;
  border: 4px solid #2d2a28;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07), 0 0 0 1px rgba(0, 0, 0, 0.6);
}

.tray__hub {
  background: linear-gradient(180deg, #3b3835, #191716);
}

.tray__cap {
  border-radius: 50%;
  background:
    repeating-conic-gradient(from 0deg, rgba(255, 255, 255, 0.07) 0 4deg, rgba(0, 0, 0, 0.12) 4deg 8deg),
    radial-gradient(closest-side, #4b4744 0 40%, #2e2b29 70%, #3f3b38 92%, #1a1817);
}

/* the arrow moulded on the cap, which turns with the tray */
.tray__cap::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 6px;
  width: 4px;
  height: 14px;
  margin-left: -2px;
  border-radius: 2px;
  background: #c9c2b5;
  opacity: 0.8;
}

.tray__rib {
  background: linear-gradient(180deg, #34312e, #151413);
}

/* the gate: where the slide in the projector sits, with the lamp's light coming up round it */
.gate-glow {
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 196, 120, 0.55), rgba(255, 160, 80, 0.18) 55%, rgba(255, 150, 70, 0));
  opacity: var(--lamp-on, 1);
}

/* the slot in the floor the slide drops through, lit from the lamp below */
.gate-slot {
  border-radius: 2px;
  background: linear-gradient(180deg, #fff0d0, #ffc27a 45%, #ff8f3a);
  box-shadow: 0 0 8px 2px rgba(255, 170, 90, 0.7);
  opacity: var(--lamp-on, 1);
}

/* ---------------------------------------------------------------- the slides */
.slide {
  position: absolute;
  left: 0;
  top: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transform-style: preserve-3d;
  pointer-events: auto;
  outline: none;
  -webkit-tap-highlight-color: transparent;
}

.slide[aria-current='true'] {
  cursor: default;
}

/* one face each side; the window shows the mount above the tray floor and cuts it where it sinks into the gate */
.slide__side {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.slide__side--lamp {
  transform: translateZ(0.6px);
}

.slide__side--lens {
  transform: rotateY(180deg) translateZ(0.6px);
}

.mount {
  position: absolute;
  left: 0;
  bottom: 0;
  width: var(--mount-s);
  height: var(--mount-s);
  border-radius: 5px;
  background: var(--paper, var(--mount));
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08), inset 0 -10px 16px -10px rgba(0, 0, 0, 0.18);
}

/* how the light falls on it as the tray turns: set by the script */
.mount::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(180deg, rgba(255, 210, 150, var(--warm, 0)), rgba(255, 170, 90, calc(var(--warm, 0) * 0.6)) 100%), rgba(4, 3, 2, var(--shade, 0.3));
  pointer-events: none;
}

.mount__chip {
  position: absolute;
  left: 18.5%;
  top: 26%;
  width: 63%;
  height: 48%;
  border-radius: 2px;
  overflow: hidden;
  background: #2b2522;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35);
}

.mount__chip canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* the film seen from the lamp's side is the picture the other way round */
.slide__side--lamp .mount__chip canvas {
  transform: scaleX(-1);
}

/* the lamp behind the chip of the slide in the gate */
.mount__chip::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(closest-side, rgba(255, 236, 200, 0.5), rgba(255, 220, 170, 0));
  mix-blend-mode: screen;
  opacity: var(--glow, 0);
}

.mount__words {
  position: absolute;
  left: 7%;
  right: 7%;
  top: 4%;
  height: 21%;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  font-family: 'Nothing You Could Do', 'Bradley Hand', cursive;
  font-size: var(--hand, 13px);
  line-height: 1;
  color: var(--ink, var(--pen));
  white-space: nowrap;
  transform: rotate(var(--tilt, -1.5deg));
}

.mount__date {
  position: absolute;
  left: 8%;
  right: 8%;
  bottom: 5%;
  height: 18%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Nothing You Could Do', 'Bradley Hand', cursive;
  font-size: calc(var(--hand, 13px) * 0.82);
  line-height: 1;
  color: var(--ink, var(--pen));
  opacity: 0.85;
  white-space: nowrap;
}

/* the lens side: the lab's print and the month it was developed */
.mount__print {
  position: absolute;
  left: 0;
  right: 0;
  top: 9%;
  text-align: center;
  font-size: 6px;
  font-weight: 600;
  font-stretch: 75%;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: rgba(60, 50, 40, 0.55);
  white-space: nowrap;
}

.mount__print--low {
  top: auto;
  bottom: 9%;
}

/* the ring of the focus from the keys, on the mount itself */
.slide:focus-visible .mount {
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08), 0 0 0 3px var(--ring);
}

/* ---------------------------------------------------------------- the lens */
.lens__ring {
  background: linear-gradient(180deg, #4a4642, #2a2725 30%, #1b1918 80%, #34302d);
}

.lens__band {
  background: repeating-linear-gradient(180deg, #b9b3a8 0 1px, #77726a 1px 2px);
}

/* ---------------------------------------------------------------- the remote */
.remote {
  position: absolute;
  z-index: 2;
  left: var(--rem-x);
  top: var(--rem-y);
  width: 136px;
  height: 156px;
  perspective: 500px;
  transform: rotate(var(--rem-turn, -8deg));
}

.remote__body {
  position: absolute;
  inset: 0;
  border-radius: 20px 20px 26px 26px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0) 12%),
    linear-gradient(90deg, rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0) 14%, rgba(0, 0, 0, 0) 86%, rgba(0, 0, 0, 0.4)),
    var(--remote);
  box-shadow:
    0 10px 0 -2px #1d140f,
    0 11px 0 -1px rgba(255, 200, 140, 0.08),
    0 22px 28px -8px rgba(255, 150, 70, 0.08);
  transform: rotateX(32deg);
  transform-origin: 50% 100%;
}

/* the cord's strain relief at the top */
.remote__grip {
  position: absolute;
  left: 50%;
  top: -10px;
  width: 16px;
  height: 16px;
  margin-left: -8px;
  border-radius: 5px 5px 3px 3px;
  background: linear-gradient(90deg, #1b130e, #3c2d23 50%, #1b130e);
}

.remote__keys {
  position: absolute;
  left: 11px;
  right: 11px;
  top: 16px;
  bottom: 34px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 7px;
  padding: 8px 7px 7px;
  border-radius: 13px 13px 15px 15px;
  background: linear-gradient(180deg, #e3d9c6, var(--remote-face));
  box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.35), inset 0 -1px 0 rgba(255, 255, 255, 0.4);
}

.key {
  position: relative;
  display: grid;
  grid-template-rows: 1fr auto;
  justify-items: center;
  gap: 5px;
  padding: 0 0 4px;
  border: 0;
  background: none;
  font: inherit;
  color: var(--label);
  cursor: pointer;
  outline: none;
  -webkit-tap-highlight-color: transparent;
}

.key__cap {
  display: grid;
  place-items: center;
  width: 100%;
  min-height: 52px;
  border-radius: 10px 10px 12px 12px;
  background: linear-gradient(180deg, #fbf7ef, var(--key) 55%, #ddd4c4);
  box-shadow:
    0 5px 0 #a69a87,
    0 6px 0 rgba(0, 0, 0, 0.35),
    0 8px 8px -2px rgba(0, 0, 0, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.9);
  transition: transform 0.12s cubic-bezier(0.23, 1, 0.32, 1), box-shadow 0.12s cubic-bezier(0.23, 1, 0.32, 1), background-color 0.2s;
}

.key__cap svg {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: #4a3a2f;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.key__name {
  font-size: 8.5px;
  font-weight: 650;
  font-stretch: 68%;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1;
}

@media (hover: hover) {
  .key:hover .key__cap {
    background: linear-gradient(180deg, #ffffff, #f5efe4 55%, #e3dbcc);
  }

  .key--on:hover .key__cap svg {
    transform: translateX(2px);
  }

  .key--back:hover .key__cap svg {
    transform: translateX(-2px);
  }
}

.key:active .key__cap,
.key.is-down .key__cap {
  transform: translateY(4px);
  background: linear-gradient(180deg, #ede6d9, var(--key-press));
  box-shadow:
    0 1px 0 #a69a87,
    0 2px 0 rgba(0, 0, 0, 0.35),
    0 3px 4px -2px rgba(0, 0, 0, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.6);
}

.key:focus-visible .key__cap {
  box-shadow:
    0 5px 0 #a69a87,
    0 6px 0 rgba(0, 0, 0, 0.35),
    0 0 0 3px var(--remote-face),
    0 0 0 6px var(--ring);
}

.remote__plate {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 13px;
  text-align: center;
  font-size: 8px;
  font-weight: 600;
  font-stretch: 78%;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(232, 214, 190, 0.55);
}

/* ---------------------------------------------------------------- movement reduced */
@media (prefers-reduced-motion: reduce) {
  .key__cap,
  .key__cap svg {
    transition: none;
  }
}
