/* The matchbox menu: the box of matches of a candle maker on a black page. Closed it is a small box, the menu
   button; open, it is picked up and its tray slides out with the matches, one per section. Everything inside the box
   is drawn in box pixels: the script scales the whole box (--u is the size of one pixel of the drawing on this screen,
   --k the scale of the box right now) and moves the tray, the matches and the one in the hand. */
:root {
  --page: #000000;          /* the page */
  --paper: #f0e5cc;         /* the label printed on the sleeve */
  --print: #8e2417;         /* the ink of the label */
  --striker: #6c4228;       /* the brown striker along the sides */
  --tray: #c99f6a;          /* the kraft of the tray */
  --wood: #ead09e;          /* the match sticks */
  --head: #c22b1e;          /* the match heads */
  --burnt: #231b17;         /* a burnt head */
  --ink: #3e2716;           /* the names printed on the sticks */
  --warm: #b0400f;          /* the name of the section you are on, warmed by its flame */
  --focus: #ffcf70;         /* the ring of the keyboard focus */
}

* {
  box-sizing: border-box;
}

html {
  touch-action: manipulation;
}

html,
body {
  margin: 0;
  overflow-x: clip;
}

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

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

a {
  color: inherit;
  text-decoration: none;
}

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

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

/* schermo basso: la scatola scende un poco, così la fiamma del fiammifero acceso e il suo alone (la tela sopra la
   scatola) restano dentro lo schermo */
@media (max-height: 520px) {
  .stage {
    padding: 72px 16px 16px;
  }
}

/* ---------------------------------------------------------------- the room the box needs */
/* closed, the box sits in the middle of it; open, the box and its tray fill it. The match in the hand, its flame and
   its smoke rise above it */
.mb {
  --u: 1px;                 /* set by the script */
  --k: 1;                   /* set by the script */
  position: relative;
  width: calc(var(--u) * 396);
  height: calc(var(--u) * 172);
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* where the poster and the preview look: the box and the air above it, where a match burns */
.mb__frame {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--u) * -60);
  bottom: 0;
  pointer-events: none;
  visibility: hidden;
}

/* the box: drawn in its own pixels, scaled and placed by the script */
.mb__box {
  position: absolute;
  left: 0;
  top: 0;
  width: 196px;
  height: 149px;
  transform-origin: 0 0;
  will-change: transform;
}

/* ---------------------------------------------------------------- the sleeve: the menu button */
.sleeve {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 3;
  display: block;
  width: 196px;
  height: 149px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 3px;
  background: none;
  color: var(--print);
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}

.sleeve:focus-visible {
  outline: calc(2px / var(--k)) solid var(--focus);
  outline-offset: calc(5px / var(--k));
}

/* pressed, the box gives a little under the thumb */
.sleeve:active .sleeve__face,
.sleeve:active .sleeve__side {
  filter: brightness(0.96);
}

/* the top side, seen from above: brown sandpaper, a little narrower at its far edge */
.sleeve__side {
  position: absolute;
  left: 0;
  top: 0;
  width: 196px;
  height: 14px;
  overflow: hidden;
  clip-path: polygon(3px 0, calc(100% - 3px) 0, 100% 100%, 0 100%);
  background:
    linear-gradient(180deg, rgba(255, 225, 190, 0.16), rgba(255, 225, 190, 0) 40%, rgba(0, 0, 0, 0.18)),
    var(--striker);
}

.sleeve__grain {
  display: block;
  width: 100%;
  height: 100%;
}

/* the label, wrapped round the sleeve; a fold of light where it meets the side */
.sleeve__face {
  position: absolute;
  left: 0;
  top: 13px;
  width: 196px;
  height: 132px;
  overflow: hidden;
  box-shadow:
    inset 0 1px 0 rgba(255, 250, 235, 0.75),
    inset -1px 0 0 rgba(70, 40, 15, 0.18),
    inset 1px 0 0 rgba(70, 40, 15, 0.12);
}

.label {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}

.label__paper {
  fill: var(--paper);
}

.label__rule {
  fill: none;
  stroke: var(--print);
  stroke-width: 1.5;
}

.label__rule--fine {
  stroke-width: 0.6;
}

.moth__wing,
.moth__body {
  fill: var(--print);
}

.moth__vein,
.moth__eye,
.moth__rings {
  fill: none;
  stroke: var(--paper);
  stroke-width: 0.9;
  stroke-linecap: round;
}

.moth__eye {
  stroke-width: 1.3;
}

.moth__feeler {
  fill: none;
  stroke: var(--print);
  stroke-width: 1.1;
  stroke-linecap: round;
}

.label__brand,
.label__line {
  position: absolute;
  left: 18px;
  white-space: nowrap;
  text-transform: uppercase;
  pointer-events: none;
}

.label__brand {
  top: 22px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.34em;
  line-height: 1;
}

.label__line {
  top: 101px;
  font-size: 8.6px;
  font-weight: 560;
  letter-spacing: 0.2em;
  line-height: 1;
}

/* the big word: Menu, or Close while the box is open. The old word leaves before the new one comes in */
.label__word {
  position: absolute;
  left: 14px;
  top: 42px;
  display: grid;
  width: 106px;
  height: 52px;
  overflow: hidden;
  font-family: 'Fraunces Variable', Georgia, serif;
  font-style: italic;
  font-size: 41px;
  font-weight: 560;
  font-variation-settings: 'opsz' 144, 'SOFT' 100, 'WONK' 1;
  line-height: 52px;
  letter-spacing: -0.01em;
  pointer-events: none;
}

.label__w {
  grid-area: 1 / 1;
  display: block;
  padding-left: 3px;
  white-space: nowrap;
}

/* the bottom side: only its edge shows */
.sleeve__edge {
  position: absolute;
  left: 1px;
  right: 1px;
  top: 145px;
  height: 4px;
  border-radius: 0 0 2px 2px;
  background:
    linear-gradient(180deg, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.45)),
    var(--striker);
}

/* ---------------------------------------------------------------- the tray */
.tray {
  position: absolute;
  left: 3px;
  top: 15px;
  z-index: 1;
  width: 190px;
  height: 128px;
  will-change: transform;
}

/* the kraft floor, its long walls seen from above, and the shadow the top wall throws on the floor */
.tray__floor {
  position: absolute;
  inset: 0;
  border-radius: 1.5px;
  background:
    linear-gradient(180deg, rgba(255, 238, 205, 0.55) 0, rgba(255, 238, 205, 0.55) 2.5px, rgba(70, 40, 12, 0.42) 3px, rgba(70, 40, 12, 0) 16px),
    linear-gradient(0deg, rgba(255, 236, 200, 0.5) 0, rgba(255, 236, 200, 0.18) 4px, rgba(60, 34, 10, 0.12) 4.5px, rgba(60, 34, 10, 0) 9px),
    repeating-linear-gradient(90deg, rgba(90, 55, 20, 0.05) 0 1px, rgba(255, 240, 210, 0.04) 1px 3px, rgba(90, 55, 20, 0) 3px 7px),
    var(--tray);
  box-shadow:
    inset 0 0 0 0.6px rgba(60, 34, 10, 0.4);
}

/* the end wall, where the tray stops against the sleeve */
.tray__rim {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  border-radius: 0 1.5px 1.5px 0;
  background:
    linear-gradient(90deg, rgba(60, 34, 10, 0.25), rgba(255, 236, 200, 0.45) 45%, rgba(255, 236, 200, 0.2)),
    var(--tray);
  pointer-events: none;
}

.tray__list {
  position: absolute;
  inset: 0;
}

/* the sleeve throws a shadow on the tray where the tray comes out of it */
.mb__shade {
  position: absolute;
  left: 196px;
  top: 15px;
  z-index: 2;
  width: 16px;
  height: 128px;
  background: linear-gradient(90deg, rgba(25, 12, 2, 0.5), rgba(25, 12, 2, 0.16) 45%, rgba(25, 12, 2, 0));
  opacity: 0;
  pointer-events: none;
}

/* ---------------------------------------------------------------- the matches */
/* a slot is a lane of the tray; the script places it and gives it its own little slant */
.slot {
  position: absolute;
  left: 0;
  top: 0;
  width: 190px;
  height: 22px;
}

.match {
  position: absolute;
  left: 6px;
  top: 0;
  display: block;
  width: 180px;
  height: 22px;
  border-radius: 9px;
  outline: none;
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}

.match:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
  box-shadow: 0 0 0 4.5px rgba(44, 20, 4, 0.55);
}

.match.is-away:focus-visible {
  outline-color: transparent;
  box-shadow: none;
}

html[data-using='pointer'] .match:focus-visible {
  outline: none;
  box-shadow: none;
}

/* the drawing of the match: the script moves it (it lifts and rolls under the pointer, it jostles when the tray
   stops); a copy of it is what the hand takes out */
.match__art {
  --lift: 0;
  --roll: 0;
  --sheen: -1;
  --sear: 0;
  position: absolute;
  left: 0;
  top: 3px;
  display: block;
  width: 180px;
  height: 16px;
  filter: drop-shadow(calc(1px + var(--lift) * 1.5px) calc(1.2px + var(--lift) * 3.4px) calc(0.8px + var(--lift) * 2.6px) rgba(48, 24, 6, calc(0.5 - var(--lift) * 0.14)));
  pointer-events: none;
}

.match.is-away .match__art {
  visibility: hidden;
}

/* the stick: round wood, lit from above, with its grain running along it */
.match__stick {
  position: absolute;
  left: 0;
  top: 1.5px;
  width: 166px;
  height: 13px;
  overflow: hidden;
  border-radius: 1.6px 4px 4px 1.6px;
  background:
    linear-gradient(180deg, rgba(255, 252, 240, 0.65) calc(14% + var(--roll) * 10%), rgba(255, 252, 240, 0) calc(42% + var(--roll) * 10%), rgba(70, 40, 12, 0) 58%, rgba(70, 40, 12, 0.38) 100%),
    repeating-linear-gradient(180deg, rgba(120, 76, 30, 0.13) calc(var(--roll) * 3px) calc(0.6px + var(--roll) * 3px), rgba(120, 76, 30, 0) calc(0.6px + var(--roll) * 3px) calc(2.3px + var(--roll) * 3px)),
    linear-gradient(90deg, rgba(130, 85, 35, 0.4), rgba(130, 85, 35, 0) 2.2px),
    var(--wood);
}

/* the light running along the stick under the pointer */
.match__stick::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 46px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 252, 235, 0.55), rgba(255, 255, 255, 0));
  transform: translateX(calc(var(--sheen) * 190px));
  opacity: calc(1 - var(--sheen) * var(--sheen));
}

/* burnt: the wood darkens back from the head */
.match__stick::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: calc(var(--sear) * 26px);
  background: linear-gradient(90deg, rgba(40, 22, 10, 0), rgba(52, 28, 12, 0.75) 45%, rgba(26, 16, 10, 0.95));
}

/* the name, printed along the stick; it rolls with it */
.match__name {
  position: absolute;
  left: 54px;
  top: 1.5px;
  height: 13px;
  color: var(--ink);
  font-size: 12px;
  font-weight: 640;
  line-height: 13.6px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  transform: translateY(calc(var(--roll) * -2px)) scaleY(calc(1 - var(--roll) * 0.14));
  transform-origin: 50% 0;
  transition: color 0.6s ease, text-shadow 0.6s ease;
}

.match.is-current .match__name,
.match__art.is-warm .match__name {
  color: var(--warm);
}

.match__art.is-lit .match__name {
  text-shadow: 0 0 5px rgba(255, 170, 70, 0.55);
}

/* the head: red, round, with its shine; burnt, it is charcoal and a little smaller */
.match__head {
  --bill: 0deg;
  position: absolute;
  left: 158px;
  top: 0;
  width: 22px;
  height: 16px;
  border-radius: 40% 58% 58% 40% / 46% 50% 50% 46%;
  background:
    radial-gradient(ellipse 30% 20% at 40% 26%, rgba(255, 214, 196, 0.42), rgba(255, 214, 196, 0)),
    radial-gradient(circle at 62% 38%, rgba(255, 190, 170, 0.22) 0 0.6px, rgba(0, 0, 0, 0) 1px),
    radial-gradient(circle at 30% 64%, rgba(60, 6, 2, 0.28) 0 0.7px, rgba(0, 0, 0, 0) 1.1px),
    radial-gradient(circle at 74% 70%, rgba(60, 6, 2, 0.25) 0 0.6px, rgba(0, 0, 0, 0) 1px),
    radial-gradient(ellipse 70% 80% at 38% 36%, color-mix(in srgb, var(--head) 86%, #ff8f72) 0%, var(--head) 46%, color-mix(in srgb, var(--head) 58%, #2a0603) 100%);
  box-shadow:
    inset -1.2px -1.4px 2px rgba(40, 4, 2, 0.5),
    inset 1px 0 1px rgba(255, 170, 150, 0.15);
  transform: rotateY(var(--bill)) scale(calc(1 - var(--sear) * 0.09));
}

.match__sear {
  position: absolute;
  inset: -0.5px;
  border-radius: inherit;
  background:
    radial-gradient(ellipse 30% 22% at 38% 30%, rgba(170, 160, 150, 0.5), rgba(170, 160, 150, 0)),
    radial-gradient(circle at 70% 60%, rgba(120, 112, 104, 0.35) 0 1px, rgba(0, 0, 0, 0) 1.6px),
    radial-gradient(circle at 30% 70%, rgba(120, 112, 104, 0.3) 0 0.8px, rgba(0, 0, 0, 0) 1.4px),
    radial-gradient(ellipse 80% 90% at 42% 38%, #4a403a 0%, var(--burnt) 55%, #0c0806 100%);
  opacity: calc(var(--sear) * 1.4 - 0.2);
}

/* the section you are on: its match is burnt */
/* ---------------------------------------------------------------- the hand */
.hand {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 4;
  width: 196px;
  height: 149px;
  pointer-events: none;
}

/* the match in the hand: its shadow grows the higher it is held */
.hand__lift {
  position: absolute;
  inset: 0;
  perspective: 900px;
}

.hand__match {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 0 0;
  transform-style: preserve-3d;
  will-change: transform;
}

.hand__match .match__art {
  position: relative;
  top: 0;
  filter: none;
  transform-style: preserve-3d;
}

.hand__match .match__name {
  transition: none;
}

/* ---------------------------------------------------------------- the flame, the sparks, the smoke, the light */
.fx {
  position: absolute;
  left: calc(var(--u) * -48);
  top: calc(var(--u) * -200);
  width: calc(var(--u) * 492);
  height: calc(var(--u) * 372);
  pointer-events: none;
  mix-blend-mode: screen;
}

.fx--shade {
  mix-blend-mode: multiply;
}

/* still motion: nothing slides or turns; the box fades open, the flame fades in and out where the match lies */
@media (prefers-reduced-motion: reduce) {
  .match__name {
    transition: none;
  }

  .match__stick::before {
    display: none;
  }

  /* under the pointer a match brightens instead of lifting */
  .match.is-up .match__stick {
    filter: brightness(1.08);
  }

  .match.is-up .match__name {
    color: color-mix(in srgb, var(--ink) 70%, var(--warm));
  }
}
