/* Living Room Aquarium: the site's one stylesheet, in grunge: a salvage zine.
   Dark grainy concrete, aged paper scraps, photos taped on as prints, rusted riveted plates for the app's menus,
   ripped paper between sections. The beads keep the app's icons and mode colours (Assets/TInfinity/Controls),
   gritted up; the textures are SVG noise drawn inline, so the site carries no texture images. */

@font-face {
  font-family: "Rubik Dirt";
  src: url("../fonts/rubik-dirt.woff2") format("woff2");
  font-display: swap;
}

@font-face {
  font-family: "Special Elite";
  src: url("../fonts/special-elite.woff2") format("woff2");
  font-display: swap;
}

@font-face {
  font-family: "Permanent Marker";
  src: url("../fonts/permanent-marker.woff2") format("woff2");
  font-display: swap;
}

@font-face {
  font-family: "Courier Prime";
  src: url("../fonts/courier-prime-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: "Courier Prime";
  src: url("../fonts/courier-prime-700.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}

@font-face {
  font-family: "Courier Prime";
  src: url("../fonts/courier-prime-400-italic.woff2") format("woff2");
  font-style: italic;
  font-display: swap;
}

:root {
  color-scheme: dark;

  /* Concrete, soot and rust. */
  --ink: #0f0e0c;
  --soot: #171512;
  --concrete: #23201b;
  --steel: #3a352c;
  --rust: #b8532a;
  --rust-deep: #7a3218;
  --verdigris: #5fb3a6;

  /* Aged paper, and the ink on it. */
  --paper: #e4d9bf;
  --paper-dark: #cdbf9f;
  --on-paper: #1f1b14;
  --on-paper-muted: #4d4536;
  --tape: rgba(226, 214, 176, 0.62);

  --text: #ebe4d2;
  --muted: #b0a68f;
  --faint: #7c7462;
  --line: rgba(235, 228, 210, 0.16);
  --line-strong: rgba(235, 228, 210, 0.32);

  /* The menus' plate (BeadPainter.MenuPlateColour), here a scrap of dark iron. */
  --plate: #12100d;

  /* The app's colours, converted from its Color values. */
  --bead: #9ee6ff;        /* WristBead.BeadColour */
  --neutral: #9edbff;     /* CircularControl.Neutral */
  --school: #ffcc66;      /* gold: school mode's, before hero mode replaced it */
  --menu: #fff2db;        /* the menu bead, Stay */
  --gun: #ff9ecc;         /* gun mode's rose */
  --feed: #b8ff8c;        /* feed mode's green */
  --hero: #e6dbff;        /* hero mode's lavender */
  --exit: #ff7361;        /* Exit */
  --reset: #ffcc73;       /* reset: the circular control's reset amber */
  --window: #99f2e6;      /* window mode */
  --room: #ffb86b;        /* the room's lamplight amber */
  --reef: #66f2e6;        /* the coral reef's sea turquoise */
  --grotto: #73b3ff;      /* the sunlit grotto */
  --ocean: #8cf299;       /* the open ocean */
  --hollow: #ff998c;      /* the hollow's soft coral */
  --grooves: #8c99ff;     /* the coral grooves' periwinkle */
  --guide: #ffd98c;       /* ControlsGuide.GuideColour */
  --restart: #ffd14d;     /* SystemBead.RestartColour: restart's warning yellow */
  --hints: #8cf2b3;       /* HoverHintsSwitch.BubbleColour */
  --science: #ff996b;     /* ScienceGunSwitch.Colour */
  --music: #e0d6ff;       /* MusicMenu.MusicColour */
  --ambience: #99f2d9;    /* MusicMenu.AmbienceColour */

  /* The Forces rings, inner to outer. */
  --coral: #ff8066;
  --teal: #59ffc7;
  --sky: #73bfff;
  --gold: #ffd166;

  --display: "Rubik Dirt", Impact, "Arial Black", sans-serif;
  --type: "Courier Prime", "Courier New", monospace;
  --label: "Special Elite", "Courier New", monospace;
  --marker: "Permanent Marker", "Comic Sans MS", cursive;

  /* Fine grain over everything. */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  /* Large stains: water damage and rust blooms. */
  --mottle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='700' height='700'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.008' numOctaves='4' seed='4' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .42 0 0 0 0 .22 0 0 0 0 .09 1.6 0 0 0 -.62'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23m)'/%3E%3C/svg%3E");
  /* Dark specks: dirt and flecks of ink. */
  --speckle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='s'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.55' numOctaves='1' seed='9' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 -7.1'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23s)'/%3E%3C/svg%3E");
  /* Worn ink: a mask with holes, for stamps and labels. */
  --worn: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='w'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.6' numOctaves='2' seed='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -9 0 0 0 6.6'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23w)'/%3E%3C/svg%3E");
  /* Ripped edges and a marker scrawl, used as masks. */
  --torn-strip: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 40' preserveAspectRatio='none'%3E%3Cpath d='M0 2.3 L8 4.6 L16 3.8 L27 0.4 L42 0.3 L54 0.5 L62 3.0 L81 0.9 L91 4.4 L112 4.0 L124 6.8 L131 6.0 L142 1.0 L150 2.2 L169 1.3 L184 4.5 L196 3.8 L203 0.4 L212 4.8 L225 2.2 L240 3.2 L251 5.6 L268 1.7 L284 3.7 L304 5.1 L314 6.9 L322 2.9 L340 1.1 L354 0.3 L371 5.4 L386 6.1 L397 4.9 L412 4.1 L426 5.9 L447 3.3 L463 0.4 L481 4.5 L502 5.8 L513 2.7 L530 0.2 L543 1.2 L551 0.4 L569 0.9 L579 2.7 L599 0.6 L612 3.8 L633 5.7 L652 1.9 L665 2.5 L685 6.7 L694 1.2 L703 1.6 L717 4.1 L727 0.0 L740 2.6 L755 6.7 L772 3.6 L788 4.7 L795 6.3 L813 6.1 L832 2.7 L844 0.7 L861 0.4 L868 1.5 L876 2.4 L883 0.0 L891 0.7 L903 0.2 L923 4.3 L932 1.8 L943 2.5 L951 5.9 L973 3.3 L987 0.6 L994 2.4 L1005 5.8 L1013 0.2 L1035 3.7 L1043 3.8 L1049 3.7 L1071 6.0 L1088 1.8 L1100 1.2 L1118 3.7 L1137 2.3 L1146 5.7 L1168 6.0 L1187 5.7 L1200 1.6 L1200 36.4 L1188 39.8 L1182 38.0 L1172 35.2 L1150 36.9 L1129 33.1 L1108 37.4 L1099 38.4 L1089 38.6 L1073 33.7 L1054 36.6 L1038 34.4 L1030 35.4 L1010 34.5 L992 36.7 L983 34.5 L971 34.4 L950 37.2 L938 33.4 L920 38.8 L912 38.9 L891 34.4 L883 34.2 L861 35.4 L850 36.2 L842 39.9 L820 35.5 L806 33.5 L793 33.9 L774 38.5 L764 37.9 L754 35.9 L744 37.1 L735 33.6 L724 36.8 L708 33.7 L696 33.6 L682 36.3 L667 39.9 L654 38.7 L648 34.4 L639 36.7 L622 36.1 L611 36.4 L596 34.5 L588 36.1 L578 38.1 L560 36.4 L545 34.7 L524 36.9 L508 36.5 L494 35.2 L481 36.3 L467 33.4 L450 33.9 L429 38.2 L414 33.4 L395 39.0 L387 36.9 L379 38.3 L372 35.3 L354 33.7 L345 35.0 L329 39.0 L309 33.2 L299 33.3 L287 36.6 L265 34.2 L256 37.0 L242 37.6 L233 37.8 L215 39.9 L201 36.9 L194 37.7 L178 36.4 L171 33.1 L153 33.2 L145 38.1 L138 34.5 L128 39.1 L115 33.6 L96 38.2 L88 33.6 L73 35.1 L65 39.6 L48 37.0 L41 33.4 L25 34.4 L17 34.0 L10 34.0 L0 37.6 Z'/%3E%3C/svg%3E");
  --torn-edge: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 24' preserveAspectRatio='none'%3E%3Cpath d='M0 5.0 L21 2.4 L29 4.7 L39 1.0 L47 0.5 L57 2.8 L67 6.8 L78 4.5 L87 3.1 L93 2.3 L99 6.6 L114 1.7 L128 8.4 L136 7.4 L148 4.5 L168 3.5 L182 6.2 L204 3.1 L223 6.4 L239 3.6 L251 0.5 L259 0.6 L277 2.3 L285 0.8 L305 7.8 L321 2.5 L331 2.6 L345 1.4 L358 2.4 L379 8.8 L394 2.2 L415 2.8 L427 0.0 L439 4.3 L453 1.8 L467 0.0 L478 0.8 L490 0.4 L496 2.7 L506 5.3 L520 6.8 L537 6.4 L557 3.5 L568 8.9 L577 6.5 L593 0.4 L612 8.0 L628 6.6 L647 1.3 L662 4.5 L681 7.2 L700 5.3 L721 6.1 L738 2.1 L744 1.2 L756 0.9 L775 5.0 L791 5.6 L808 4.4 L814 7.2 L832 4.5 L847 5.9 L854 6.6 L864 0.7 L874 6.6 L883 6.7 L905 4.4 L917 4.3 L934 6.9 L950 5.8 L957 1.3 L967 6.7 L978 5.1 L984 0.5 L995 6.0 L1012 6.1 L1022 4.6 L1036 4.2 L1044 8.0 L1053 8.8 L1074 0.2 L1087 7.4 L1109 4.0 L1119 1.9 L1140 1.9 L1155 1.3 L1170 8.6 L1178 7.4 L1192 8.0 L1200 2.1 L1200 24.0 L0 24.0 Z'/%3E%3C/svg%3E");
  --scribble: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 20' preserveAspectRatio='none'%3E%3Cpath d='M3 13 C 40 6, 90 9, 140 7 S 190 9, 197 6 M10 16 C 60 11, 120 14, 192 11' fill='none' stroke='black' stroke-width='3.2' stroke-linecap='round'/%3E%3C/svg%3E");
  --wrap: 1180px;
  --gutter: clamp(16px, 4vw, 40px);
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

/* Anchors land below the sticky header. */
[id],
[data-choices] {
  scroll-margin-top: 110px;
}

body {
  margin: 0;
  background-color: var(--ink);
  /* A few faint stains on soot; the fine grain lies over everything (body::after). */
  background-image:
    radial-gradient(40% 30% at 12% 18%, rgba(120, 72, 34, 0.12), transparent 70%),
    radial-gradient(35% 25% at 88% 46%, rgba(95, 179, 166, 0.06), transparent 70%),
    radial-gradient(45% 30% at 30% 78%, rgba(120, 72, 34, 0.1), transparent 70%),
    radial-gradient(120% 60% at 50% 0%, #2a2620 0%, transparent 60%),
    linear-gradient(180deg, var(--soot), var(--ink));
  background-attachment: fixed;
  color: var(--text);
  font-family: var(--type);
  font-size: 17px;
  line-height: 1.7;
  overflow-x: hidden;
}

/* Concrete: one stretched layer of stains behind everything, so it never shows a tile's seam. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--mottle) center / cover no-repeat;
  opacity: 0.32;
}

/* Grain and specks over the whole page, never in the way of a click. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
  background-image: var(--speckle), var(--grain);
  background-size: 300px 300px, 240px 240px;
  opacity: 0.18;
  mix-blend-mode: overlay;
}

img {
  max-width: 100%;
  display: block;
}

a {
  color: var(--verdigris);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

a:hover {
  color: var(--text);
  text-decoration-color: var(--rust);
}

h1,
h2,
h3 {
  font-family: var(--display);
  font-weight: 400;
  line-height: 1.02;
  margin: 0 0 0.45em;
  text-wrap: balance;
  text-transform: uppercase;
  letter-spacing: 0.01em;
}

h1 {
  font-size: clamp(2.8rem, 7.5vw, 6.2rem);
}

h2 {
  font-size: clamp(2.1rem, 4.4vw, 3.5rem);
}

h3 {
  font-size: 1.55rem;
}

p {
  margin: 0 0 1em;
  text-wrap: pretty;
}

b,
strong {
  font-weight: 700;
}

.wrap {
  width: min(100% - 2 * var(--gutter), var(--wrap));
  margin-inline: auto;
}

/* A strip of label-maker tape, in the colour of what it names. */
.eyebrow {
  display: inline-block;
  font-family: var(--label);
  font-size: 0.88rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--accent, var(--paper));
  padding: 4px 12px 3px;
  margin: 0 0 1.1rem;
  transform: rotate(-1.2deg);
  box-shadow: 2px 3px 0 rgba(0, 0, 0, 0.45);
  -webkit-mask: var(--worn) 0 0 / 180px 180px;
  mask: var(--worn) 0 0 / 180px 180px;
}

.lede {
  font-size: clamp(1.08rem, 1.5vw, 1.25rem);
  color: var(--text);
  max-width: 40em;
}

.muted {
  color: var(--muted);
}

.skip {
  position: absolute;
  left: -999px;
}

.skip:focus {
  left: 16px;
  top: 16px;
  z-index: 200;
  background: var(--paper);
  color: var(--on-paper);
  padding: 8px 14px;
}

:focus-visible {
  outline: 2px dashed var(--rust);
  outline-offset: 4px;
}

/* ------------------------------------------------------------------ beads */

/* A bead wears the app's icon in its colour (BeadPainter.DrawIconBead): faint and breathing while what it stands for
   is off; brighter, ringed, while it is on. Here the plate is a disc of dark iron and the ring is scrawled in marker. */
.bead {
  --c: var(--bead);
  --size: 64px;
  position: relative;
  display: inline-grid;
  place-items: center;
  width: var(--size);
  height: var(--size);
  flex: none;
  border-radius: 50%;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: inherit;
  background:
    var(--grain) 0 0 / 120px 120px,
    radial-gradient(circle at 38% 32%, #2b2721 0%, var(--plate) 70%);
  background-blend-mode: soft-light, normal;
  box-shadow:
    inset 0 0 0 2px rgba(0, 0, 0, 0.6),
    inset 0 2px 0 rgba(255, 255, 255, 0.07),
    0 3px 0 rgba(0, 0, 0, 0.5),
    0 0 calc(var(--size) * 0.3) color-mix(in srgb, var(--c) 12%, transparent);
  transition: box-shadow 0.3s var(--ease), transform 0.3s var(--ease);
}

.bead::before {
  content: "";
  width: 80%;
  height: 80%;
  background: var(--c);
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
  opacity: 0.74;
  animation: breathe 3.9s ease-in-out infinite;
  transition: opacity 0.3s;
}

/* The ring a bead wears while it is on: a quick loop of marker. */
.bead::after {
  content: "";
  position: absolute;
  inset: -7px;
  border-radius: 50%;
  border: 3px solid var(--c);
  border-left-color: transparent;
  filter: url(#rough);
  opacity: 0;
  transform: rotate(-30deg) scale(0.9);
  transition: opacity 0.3s var(--ease), transform 0.4s var(--ease);
}

a.bead:hover::before,
button.bead:hover::before {
  opacity: 0.98;
}

.bead.is-on {
  box-shadow:
    inset 0 0 0 2px rgba(0, 0, 0, 0.6),
    0 3px 0 rgba(0, 0, 0, 0.5),
    0 0 calc(var(--size) * 0.55) color-mix(in srgb, var(--c) 30%, transparent);
}

.bead.is-on::before {
  opacity: 1;
  animation: none;
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--c) 60%, transparent));
}

.bead.is-on::after {
  opacity: 0.95;
  transform: rotate(12deg) scale(1);
}

/* A touch's flash. */
.bead.flash::before {
  animation: flash 0.5s ease-out;
}

.bead--sm {
  --size: 44px;
}

.bead--lg {
  --size: 92px;
}

.bead--xl {
  --size: 132px;
}

/* A bead without an icon: a glow, like the wrist's plain bead. */
.bead--plain::before {
  -webkit-mask: none;
  mask: none;
  width: 34%;
  height: 34%;
  border-radius: 50%;
  box-shadow: 0 0 14px var(--c);
}

@keyframes breathe {
  0%,
  100% {
    opacity: 0.62;
  }
  50% {
    opacity: 0.84;
  }
}

@keyframes flash {
  0% {
    opacity: 1;
    filter: brightness(2.2) drop-shadow(0 0 10px var(--c));
  }
  100% {
    opacity: 1;
    filter: none;
  }
}

/* ------------------------------------------------------------------ header */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background:
    var(--grain) 0 0 / 240px 240px,
    linear-gradient(180deg, #1c1915, #121009);
  background-blend-mode: soft-light, normal;
}

/* The header's ripped bottom edge. */
.site-header::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  height: 12px;
  background: #121009;
  -webkit-mask: var(--torn-edge) 0 0 / 100% 100%;
  mask: var(--torn-edge) 0 0 / 100% 100%;
  transform: scaleY(-1);
  filter: drop-shadow(0 -3px 2px rgba(0, 0, 0, 0.5));
}

.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 72px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--text);
  text-decoration: none;
  font-family: var(--display);
  font-size: 1.45rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.brand:hover {
  color: var(--paper);
}

.brand .bead {
  --size: 42px;
  pointer-events: none;
}

.nav {
  display: flex;
  gap: 6px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav a {
  position: relative;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 12px 6px 6px;
  color: var(--muted);
  text-decoration: none;
  font-family: var(--label);
  font-size: 0.95rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: color 0.2s;
}

.nav a:hover {
  color: var(--text);
}

/* The page you're on is underlined in marker. */
.nav a[aria-current="page"] {
  color: var(--text);
}

.nav a[aria-current="page"] > span:not(.bead)::after {
  content: "";
  position: absolute;
  left: 46px;
  right: 6px;
  bottom: 0;
  height: 9px;
  background: var(--rust);
  -webkit-mask: var(--scribble) 0 0 / 100% 100%;
  mask: var(--scribble) 0 0 / 100% 100%;
}

.nav .bead {
  --size: 34px;
  pointer-events: none;
}

@media (max-width: 920px) {
  .nav a > span:not(.bead) {
    display: none;
  }

  .nav a {
    padding: 4px;
  }
}

@media (max-width: 560px) {
  /* The name breaks onto two lines on phones, so the menu keeps its room. */
  .brand {
    font-size: 1.15rem;
    gap: 9px;
    white-space: normal;
    line-height: 1.05;
  }

  .brand .bead {
    --size: 34px;
  }

  .nav {
    gap: 0;
  }

  .nav a {
    padding: 3px;
  }

  .nav .bead {
    --size: 32px;
  }
}

@media (max-width: 360px) {
  .brand > span {
    display: none;
  }
}

/* ------------------------------------------------------------------ hero */

.hero {
  position: relative;
  min-height: min(92vh, 900px);
  display: grid;
  align-items: end;
  overflow: hidden;
  isolation: isolate;
  padding: 130px 0 90px;
}

.hero__media,
.hero__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.hero__media {
  z-index: -2;
}

/* The photo, printed on cheap stock: harder contrast, less colour, a brown cast. */
.hero__media img {
  object-fit: cover;
  filter: contrast(1.18) saturate(0.7) sepia(0.22) brightness(0.92);
  transform: scale(1.04);
  animation: drift 30s ease-in-out infinite alternate;
}

/* Soot from the edges, film scratches, and heavy grain. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    var(--speckle) 0 0 / 300px 300px,
    repeating-linear-gradient(90deg, transparent 0 211px, rgba(235, 228, 210, 0.06) 211px 212px, transparent 212px 397px, rgba(0, 0, 0, 0.25) 397px 398px),
    linear-gradient(180deg, rgba(15, 14, 12, 0.6) 0%, transparent 28%, transparent 42%, rgba(15, 14, 12, 0.88) 80%, var(--ink) 100%),
    radial-gradient(120% 90% at 50% 40%, transparent 50%, rgba(0, 0, 0, 0.65) 100%);
}

/* The hero's bottom is ripped off. */
.hero::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 22px;
  z-index: 1;
  background: var(--ink);
  -webkit-mask: var(--torn-edge) 0 0 / 100% 100%;
  mask: var(--torn-edge) 0 0 / 100% 100%;
}

.hero h1 {
  text-shadow: 3px 4px 0 rgba(0, 0, 0, 0.55);
}

/* The words that matter, scrawled over in marker. */
.hero h1 em {
  position: relative;
  display: inline-block;
  font-family: var(--marker);
  font-style: normal;
  text-transform: none;
  color: var(--reef);
  transform: rotate(-2.5deg);
  padding-bottom: 0.08em;
}

.hero h1 em::after {
  content: "";
  position: absolute;
  left: 2%;
  right: 0;
  bottom: -0.06em;
  height: 0.2em;
  background: var(--rust);
  -webkit-mask: var(--scribble) 0 0 / 100% 100%;
  mask: var(--scribble) 0 0 / 100% 100%;
}

.hero .lede {
  color: var(--text);
  text-shadow: 0 2px 6px rgba(0, 0, 0, 0.9);
}

.hero--page {
  min-height: min(70vh, 640px);
}

/* On a phone the text covers most of the picture: darken it more. */
@media (max-width: 700px) {
  .hero::after {
    background:
      var(--speckle) 0 0 / 300px 300px,
      linear-gradient(180deg, rgba(15, 14, 12, 0.4) 0%, rgba(15, 14, 12, 0.6) 35%, rgba(15, 14, 12, 0.9) 75%, var(--ink) 100%);
  }
}

@keyframes drift {
  from {
    transform: scale(1.04) translate3d(0, 0, 0);
  }
  to {
    transform: scale(1.1) translate3d(-1.5%, -1%, 0);
  }
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 30px;
}

/* A button is a stencilled tag of card nailed to the wall. */
.button {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 7px 20px 7px 7px;
  background:
    var(--grain) 0 0 / 240px 240px,
    var(--paper);
  background-blend-mode: multiply, normal;
  color: var(--on-paper);
  text-decoration: none;
  font-family: var(--label);
  font-size: 1rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  box-shadow: 3px 4px 0 rgba(0, 0, 0, 0.55);
  transform: rotate(-1deg);
  transition: transform 0.2s var(--ease), background-color 0.2s;
}

.button:nth-child(even) {
  transform: rotate(0.8deg);
}

.button:hover {
  color: var(--on-paper);
  transform: rotate(0deg) translateY(-2px);
  background-color: #f0e6cc;
}

.button .bead {
  --size: 42px;
  pointer-events: none;
}

/* ------------------------------------------------------------------ sections */

.section {
  padding: clamp(72px, 10vw, 130px) 0;
  position: relative;
}

.section--tight {
  padding-top: 0;
}

.section-head {
  max-width: 780px;
  margin-bottom: clamp(36px, 5vw, 60px);
}

.section-head--center {
  margin-inline: auto;
  text-align: center;
}

.section-head--center .lede {
  margin-inline: auto;
}

/* Between sections, a strip of ripped paper. */
.divider {
  height: 26px;
  width: 104%;
  margin: 0 -2%;
  border: 0;
  background:
    var(--grain) 0 0 / 240px 240px,
    linear-gradient(180deg, var(--paper), var(--paper-dark));
  background-blend-mode: multiply, normal;
  -webkit-mask: var(--torn-strip) 0 0 / 100% 100%;
  mask: var(--torn-strip) 0 0 / 100% 100%;
  transform: rotate(-0.6deg);
  opacity: 0.9;
}

.divider:nth-of-type(even) {
  transform: rotate(0.5deg);
  background:
    var(--grain) 0 0 / 240px 240px,
    linear-gradient(180deg, #c76a3c, var(--rust-deep));
  background-blend-mode: multiply, normal;
  height: 18px;
}

/* A two-column feature: picture and words. */
.feature {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: clamp(32px, 5vw, 76px);
  align-items: center;
}

.feature + .feature {
  margin-top: clamp(72px, 9vw, 130px);
}

.feature--flip .feature__media {
  order: 2;
}

.feature__media {
  position: relative;
}

.feature h3 {
  font-size: clamp(1.7rem, 2.8vw, 2.4rem);
}

.feature__head {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 18px;
}

.feature__head .eyebrow {
  margin: 0;
}

@media (max-width: 820px) {
  .feature {
    grid-template-columns: 1fr;
  }

  .feature--flip .feature__media {
    order: 0;
  }
}

/* A screenshot is a print taped to the wall: a paper border, a strip of tape, a little crooked. */
.shot {
  position: relative;
  margin: 0;
  padding: 10px 10px 0;
  background:
    var(--grain) 0 0 / 240px 240px,
    var(--paper);
  background-blend-mode: multiply, normal;
  box-shadow: 6px 10px 0 rgba(0, 0, 0, 0.45), 0 30px 60px -20px rgba(0, 0, 0, 0.8);
  transform: rotate(-1deg);
}

.feature--flip .shot,
.strip .shot:nth-child(even) {
  transform: rotate(1.1deg);
}

.shot::before {
  content: "";
  position: absolute;
  z-index: 2;
  top: -13px;
  left: 50%;
  width: 118px;
  height: 30px;
  margin-left: -59px;
  background: var(--tape);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  transform: rotate(-3deg);
  clip-path: polygon(2% 8%, 8% 0, 15% 9%, 23% 1%, 31% 7%, 42% 0, 55% 6%, 66% 0, 77% 8%, 88% 1%, 97% 7%, 100% 92%, 92% 100%, 83% 92%, 71% 99%, 60% 92%, 47% 100%, 35% 93%, 23% 100%, 12% 92%, 0 99%);
  pointer-events: none;
}

.shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  aspect-ratio: 16 / 9;
  filter: contrast(1.1) saturate(0.82) sepia(0.14);
}

.shot--tall img {
  aspect-ratio: 4 / 3;
}

.shot figcaption {
  font-family: var(--marker);
  font-size: 0.98rem;
  line-height: 1.35;
  color: var(--on-paper);
  padding: 10px 6px 12px;
  transform: rotate(-0.6deg);
}

.shot:not(:has(figcaption)) {
  padding-bottom: 10px;
}

.shot-stack {
  position: relative;
}

.shot-stack .shot + .shot {
  position: absolute;
  width: 46%;
  right: -5%;
  bottom: -16%;
  transform: rotate(4deg);
  box-shadow: 6px 10px 0 rgba(0, 0, 0, 0.5), 0 24px 50px -10px rgba(0, 0, 0, 0.9);
}

.shot-stack .shot + .shot::before {
  width: 80px;
  margin-left: -40px;
  transform: rotate(6deg);
}

@media (max-width: 820px) {
  .shot-stack .shot + .shot {
    right: 3%;
  }
}

/* How to do it: a typed list, each line's label stamped in red. */
.how {
  list-style: none;
  margin: 24px 0 0;
  padding: 0;
  display: grid;
  gap: 0;
  border-top: 1px dashed var(--line-strong);
}

.how li {
  display: grid;
  grid-template-columns: 120px 1fr;
  gap: 14px;
  align-items: baseline;
  padding: 11px 4px;
  border-bottom: 1px dashed var(--line-strong);
  font-size: 0.96rem;
}

.how li > b {
  font-family: var(--label);
  font-weight: 400;
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--c, var(--rust));
}

@media (max-width: 480px) {
  .how li {
    grid-template-columns: 1fr;
    gap: 2px;
  }
}

/* A rubber stamp, its ink worn. */
.tag {
  display: inline-block;
  font-family: var(--label);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 3px 10px 2px;
  border: 2px solid var(--c, var(--rust));
  color: var(--c, var(--rust));
  vertical-align: middle;
  transform: rotate(-4deg);
  -webkit-mask: var(--worn) 0 0 / 120px 120px;
  mask: var(--worn) 0 0 / 120px 120px;
}

/* A stamp on a strip of label tape is inked straight onto the tape. */
.eyebrow .tag {
  border: 0;
  border-left: 2px solid var(--ink);
  color: var(--ink);
  padding: 0 0 0 8px;
  margin-left: 4px;
  font-size: inherit;
  letter-spacing: inherit;
  transform: none;
  -webkit-mask: none;
  mask: none;
}

/* ------------------------------------------------------------------ cards */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 26px 22px;
}

/* A card is a scrap of stained paper. */
.card {
  --c: var(--bead);
  position: relative;
  padding: 28px 24px 26px;
  background:
    var(--speckle) 0 0 / 300px 300px,
    var(--mottle) 0 0 / 700px 700px,
    var(--grain) 0 0 / 240px 240px,
    linear-gradient(170deg, var(--paper), var(--paper-dark));
  background-blend-mode: normal, multiply, multiply, normal;
  color: var(--on-paper);
  text-decoration: none;
  box-shadow: 5px 8px 0 rgba(0, 0, 0, 0.5);
  clip-path: polygon(0 2%, 4% 0, 30% 1.5%, 58% 0, 86% 1.2%, 100% 0, 99% 30%, 100% 62%, 98.6% 100%, 70% 98.5%, 41% 100%, 12% 98.8%, 0 100%, 1.2% 66%, 0 34%);
  transform: rotate(-0.8deg);
  transition: transform 0.3s var(--ease);
}

.card:nth-child(even) {
  transform: rotate(0.9deg);
}

.card:nth-child(3n) {
  transform: rotate(-0.3deg);
}

a.card:hover {
  color: var(--on-paper);
  transform: rotate(0deg) translateY(-4px);
}

a.card:hover .bead::before {
  opacity: 1;
}

.card .bead {
  margin-bottom: 18px;
}

.card h3 {
  font-size: 1.4rem;
  margin-bottom: 0.35em;
}

.card p {
  color: var(--on-paper-muted);
  font-size: 0.95rem;
  margin: 0;
}

/* ------------------------------------------------------------------ the app's menus, on iron plates */

/* The plate a floating menu stands on: a scrap of rusted iron, riveted at the corners. */
.main-menu,
.fish-menu,
.music-page {
  background:
    radial-gradient(circle at 14px 14px, #8a8170 0 2.5px, #2a2620 3.5px, transparent 4.5px),
    radial-gradient(circle at calc(100% - 14px) 14px, #8a8170 0 2.5px, #2a2620 3.5px, transparent 4.5px),
    radial-gradient(circle at 14px calc(100% - 14px), #8a8170 0 2.5px, #2a2620 3.5px, transparent 4.5px),
    radial-gradient(circle at calc(100% - 14px) calc(100% - 14px), #8a8170 0 2.5px, #2a2620 3.5px, transparent 4.5px),
    var(--mottle) 0 0 / 500px 500px,
    var(--grain) 0 0 / 240px 240px,
    linear-gradient(160deg, #3a352d, #221f19 60%, #1a1712);
  background-blend-mode: normal, normal, normal, normal, normal, soft-light, normal;
  border: 2px solid #0b0a08;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), inset 0 -2px 0 rgba(0, 0, 0, 0.4), 6px 10px 0 rgba(0, 0, 0, 0.5);
}

/* A wrist's menu beside what its beads do. */
.wrist {
  display: grid;
  grid-template-columns: minmax(280px, 440px) 1fr;
  gap: clamp(32px, 5vw, 68px);
  align-items: start;
}

@media (max-width: 820px) {
  .wrist {
    grid-template-columns: 1fr;
  }
}

.mode-panels {
  position: relative;
  min-height: 420px;
}

.mode-panel {
  display: none;
}

.mode-panel.is-shown {
  display: block;
  animation: rise 0.45s var(--ease);
}

.mode-panel .shot {
  margin-top: 20px;
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/*
 * The left wrist's main menu, laid out as the app does (SystemBead.MenuLayout): three centred rows, the places on top,
 * the settings in their fixed slots under them, restart and Exit at the foot. The grid's columns are half a bead's pitch
 * wide; each bead spans two (its column is set on the page).
 */
.main-menu {
  --pitch: 92px;
  display: grid;
  grid-template-columns: repeat(16, calc(var(--pitch) / 2));
  justify-content: center;
  row-gap: 22px;
  padding: 30px 34px 24px;
  width: fit-content;
  max-width: 100%;
  margin: 0 auto;
}

.main-menu__places,
.main-menu__tools,
.main-menu__foot {
  display: contents;
}

.main-menu__places > figure {
  grid-row: 2;
}

.main-menu__tools figure {
  grid-row: 2;
}

.main-menu__foot > figure {
  grid-row: 3;
}

/* The hints' switch stands in the settings' row through its own group. */
.main-menu__hints {
  display: contents;
}

/* While Exit or restart asks, the menu is away and only its question shows, in the menu's place. */
.main-menu.is-asking > .main-menu__places,
.main-menu.is-asking > .main-menu__tools,
.main-menu.is-asking > .main-menu__foot {
  display: none;
}

.main-menu > .confirm {
  grid-column: 1 / -1;
  grid-row: 1 / span 3;
  justify-content: center;
  align-self: center;
}

.main-menu figure,
.fish-menu figure {
  margin: 0;
  display: grid;
  justify-items: center;
  gap: 8px;
}

/* Each bead's name on a strip of label tape. */
.main-menu figcaption,
.fish-menu figcaption {
  font-family: var(--label);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--paper);
  padding: 1px 7px;
  white-space: nowrap;
  transform: rotate(-1.5deg);
  -webkit-mask: var(--worn) 0 0 / 140px 140px;
  mask: var(--worn) 0 0 / 140px 140px;
}

/* Too narrow for the app's layout: the rows simply wrap. */
@media (max-width: 820px) {
  .main-menu {
    display: grid;
    grid-template-columns: 1fr;
    justify-items: center;
    padding: 24px 14px 20px;
    row-gap: 18px;
  }

  .main-menu__places,
  .main-menu__tools,
  .main-menu__foot {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 14px 18px;
  }

  .main-menu__places > figure,
  .main-menu__tools figure,
  .main-menu__foot > figure {
    grid-column: auto !important;
    grid-row: auto !important;
  }

  .main-menu > .confirm {
    grid-column: 1;
    grid-row: 1;
  }

  .main-menu .bead--lg {
    --size: 68px;
  }

  .main-menu figcaption {
    font-size: 0.66rem;
  }
}

/* The right wrist's fish menu (WristBead.MenuLayout): the fish on top, the modes below, four to a row. */
.fish-menu {
  display: grid;
  gap: 18px;
  justify-items: center;
  align-content: center;
  padding: 30px 26px 24px;
  width: fit-content;
  max-width: 100%;
  margin: 0 auto;
}

.fish-menu .bead--lg {
  --size: 76px;
}

.fish-menu__row {
  display: flex;
  justify-content: center;
  gap: 16px;
}

/* What the size chosen means, under the menu. */
.fish-menu__size {
  margin-top: 22px;
  text-align: center;
}

@media (max-width: 480px) {
  .fish-menu {
    padding: 24px 14px 20px;
  }

  .fish-menu .bead--lg {
    --size: 60px;
  }

  .fish-menu__row {
    gap: 10px;
  }

  .fish-menu figcaption {
    font-size: 0.62rem;
    letter-spacing: 0.04em;
  }
}

.confirm {
  display: none;
  gap: 18px;
  align-items: center;
}

.confirm.is-shown {
  display: flex;
  animation: rise 0.35s var(--ease);
}

.place-view {
  margin-top: 48px;
  position: relative;
}

.place-view .shot {
  transform: rotate(-0.5deg);
  transition: opacity 0.5s;
}

.place-view.is-fading .shot {
  opacity: 0;
}

.place-view__text {
  max-width: 760px;
  margin: 34px auto 0;
  text-align: center;
}

/* A place with no picture yet shows its bead on an iron plate instead. */
.place-view__icon {
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 7;
  margin: 0;
  background:
    var(--mottle) 0 0 / 500px 500px,
    var(--grain) 0 0 / 240px 240px,
    radial-gradient(circle at 50% 45%, #3a352d, #1a1712 75%);
  background-blend-mode: normal, soft-light, normal;
  border: 2px solid #0b0a08;
  box-shadow: 6px 10px 0 rgba(0, 0, 0, 0.5);
}

/* The music page: rows of beads, the volumes as rows of pips. */
.music-page {
  display: grid;
  gap: 16px;
  padding: 26px 28px 22px;
  width: fit-content;
  max-width: 100%;
  margin: 0 auto;
}

.music-page__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}

.music-page .pip {
  --size: 24px;
}

/* ------------------------------------------------------------------ legend */

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  margin-top: 18px;
  font-family: var(--label);
  font-size: 0.85rem;
  color: var(--muted);
}

.legend span::before {
  content: "";
  display: inline-block;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--c);
  margin-right: 8px;
  vertical-align: -1px;
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.6);
}

/* ------------------------------------------------------------------ species */

.species {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 30px 22px;
}

/* A species card is an instant photo, its name written on in marker. */
.species article {
  position: relative;
  padding: 10px 10px 0;
  background:
    var(--grain) 0 0 / 240px 240px,
    var(--paper);
  background-blend-mode: multiply, normal;
  color: var(--on-paper);
  box-shadow: 5px 8px 0 rgba(0, 0, 0, 0.5);
  transform: rotate(-1.2deg);
}

.species article:nth-child(even) {
  transform: rotate(1deg);
}

.species article:nth-child(3n) {
  transform: rotate(-0.4deg);
}

.species img {
  aspect-ratio: 16 / 10;
  object-fit: cover;
  width: 100%;
  filter: contrast(1.08) saturate(0.85) sepia(0.12);
}

.species .species__swatch {
  aspect-ratio: 16 / 10;
  display: grid;
  place-items: center;
  background: var(--ink);
}

.species div.species__text {
  padding: 12px 6px 16px;
}

.species h3 {
  font-family: var(--marker);
  text-transform: none;
  font-size: 1.3rem;
  margin: 0 0 2px;
}

.species p {
  font-size: 0.88rem;
  color: var(--on-paper-muted);
  margin: 0;
}

.species .latin {
  font-family: var(--label);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--rust-deep);
  margin-bottom: 6px;
}

/* ------------------------------------------------------------------ pictures that open full size */

.zoom {
  position: relative;
  display: block;
  overflow: hidden;
  cursor: zoom-in;
}

.zoom img {
  transition: transform 0.6s var(--ease), filter 0.3s;
}

/* On hover, the print comes back to full colour. */
.zoom:hover img {
  transform: scale(1.035);
  filter: none;
}

/* A small stamp in the corner says the picture opens. */
.zoom::after {
  content: "";
  position: absolute;
  right: 10px;
  top: 10px;
  width: 34px;
  height: 34px;
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ebe4d2' stroke-width='2.2' stroke-linecap='square'%3E%3Cpath d='M14 4h6v6M10 20H4v-6M20 4l-6.5 6.5M4 20l6.5-6.5'/%3E%3C/svg%3E") center / 16px no-repeat,
    var(--ink);
  box-shadow: 2px 3px 0 rgba(0, 0, 0, 0.5);
  opacity: 0;
  transform: rotate(-6deg) scale(0.85);
  transition: opacity 0.25s, transform 0.25s var(--ease);
}

.zoom:hover::after,
.zoom:focus-visible::after {
  opacity: 1;
  transform: rotate(-6deg);
}

.zoom:focus-visible {
  outline-offset: -4px;
}

.lightbox {
  width: 100vw;
  height: 100dvh;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text);
  overflow: hidden;
}

.lightbox[open] {
  display: grid;
  place-items: center;
  animation: lightbox-in 0.35s var(--ease);
}

.lightbox::backdrop {
  background:
    var(--speckle) 0 0 / 300px 300px,
    rgba(12, 11, 9, 0.95);
}

.lightbox__figure {
  margin: 0;
  display: grid;
  justify-items: center;
  gap: 16px;
  padding: 72px 88px 56px;
  max-width: 100%;
}

/* At full size the picture is printed straight, in its real colours, with a slim paper border. */
.lightbox__figure img {
  max-width: min(100%, 1600px);
  max-height: calc(100dvh - 250px);
  width: auto;
  height: auto;
  object-fit: contain;
  border: 10px solid var(--paper);
  box-shadow: 8px 12px 0 rgba(0, 0, 0, 0.6);
  transition: opacity 0.25s;
  touch-action: pan-y;
}

.lightbox.is-changing .lightbox__figure img {
  opacity: 0;
}

.lightbox figcaption {
  max-width: 62ch;
  text-align: center;
  font-family: var(--marker);
  font-size: 1.05rem;
  line-height: 1.4;
  color: var(--paper);
}

.lightbox__nav {
  position: absolute;
  top: 50%;
  width: 52px;
  height: 52px;
  margin-top: -26px;
  border: 0;
  background:
    var(--grain) 0 0 / 240px 240px,
    var(--paper);
  background-blend-mode: multiply, normal;
  box-shadow: 3px 4px 0 rgba(0, 0, 0, 0.6);
  color: var(--on-paper);
  cursor: pointer;
  display: grid;
  place-items: center;
  transform: rotate(-3deg);
  transition: transform 0.2s var(--ease), background-color 0.2s;
}

.lightbox__next {
  transform: rotate(3deg);
}

.lightbox__nav:hover {
  background-color: #f0e6cc;
  transform: rotate(0deg) scale(1.05);
}

.lightbox__nav svg {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 3;
  stroke-linecap: square;
  stroke-linejoin: miter;
}

.lightbox__prev {
  left: 20px;
}

.lightbox__next {
  right: 20px;
}

.lightbox__nav[hidden] {
  display: none;
}

.lightbox__close {
  position: absolute;
  top: 16px;
  right: 20px;
  --size: 50px;
}

.lightbox__count {
  position: absolute;
  top: 24px;
  left: 24px;
  margin: 0;
  font-family: var(--label);
  font-size: 0.85rem;
  letter-spacing: 0.14em;
  color: var(--ink);
  background: var(--paper);
  padding: 2px 9px;
  transform: rotate(-2deg);
  font-variant-numeric: tabular-nums;
}

.lightbox__count:empty {
  display: none;
}

@media (max-width: 700px) {
  .lightbox__figure {
    padding: 72px 12px 96px;
  }

  .lightbox__figure img {
    max-height: calc(100dvh - 280px);
    border-width: 6px;
  }

  .lightbox__nav {
    top: auto;
    bottom: 22px;
    margin-top: 0;
  }

  .lightbox__prev {
    left: calc(50% - 64px);
  }

  .lightbox__next {
    right: calc(50% - 64px);
  }
}

@keyframes lightbox-in {
  from {
    opacity: 0;
    transform: scale(0.97) rotate(-0.5deg);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ------------------------------------------------------------------ gallery strip */

/* A row of prints, taped up side by side. */
.strip {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(280px, 34%);
  gap: 26px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding: 26px 12px 26px;
  scrollbar-width: thin;
  scrollbar-color: var(--rust) transparent;
}

.strip .shot {
  scroll-snap-align: start;
}

@media (max-width: 600px) {
  .strip {
    grid-auto-columns: 82%;
  }
}

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

.site-footer {
  position: relative;
  padding: 56px 0 60px;
  color: var(--faint);
  font-size: 0.9rem;
  background:
    var(--grain) 0 0 / 240px 240px,
    #0b0a08;
  background-blend-mode: soft-light, normal;
}

/* The footer's ripped top edge. */
.site-footer::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 16px;
  background: #0b0a08;
  -webkit-mask: var(--torn-edge) 0 0 / 100% 100%;
  mask: var(--torn-edge) 0 0 / 100% 100%;
}

.site-footer .wrap {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 24px;
}

.site-footer strong {
  font-family: var(--display);
  font-weight: 400;
  font-size: 1.3rem;
  text-transform: uppercase;
}

.site-footer nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  font-family: var(--label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.site-footer__credits {
  flex-basis: 100%;
  margin: 10px 0 0;
  padding-top: 16px;
  border-top: 1px dashed var(--line);
  font-size: 0.8rem;
  line-height: 1.6;
  color: var(--faint);
}

.site-footer a {
  color: var(--muted);
  text-decoration: none;
}

.site-footer a:hover {
  color: var(--text);
}

/* ------------------------------------------------------------------ reveal on scroll */

/* ------------------------------------------------------------------ the controllers */

/* The controllers' drawing, its buttons lettered over it, beside the legend of what each does. */
.controller-map {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(32px, 5vw, 68px);
  align-items: start;
}

@media (max-width: 860px) {
  .controller-map {
    grid-template-columns: 1fr;
  }
}

.controller-map__board {
  position: relative;
}

/* The drawing is a whole page of its own, not a cropped screenshot. */
.controller-map__art img {
  aspect-ratio: auto;
  filter: none;
}

/* A key, stamped like a keycap in the colour of what it does. It lights up while it, or its line in the legend, is
   under the pointer (--lit, set by the rules below). */
.keycap {
  display: inline-grid;
  place-items: center;
  width: clamp(22px, 1.6vw + 12px, 32px);
  height: clamp(22px, 1.6vw + 12px, 32px);
  border-radius: 50%;
  font-family: var(--label);
  font-size: 0.95rem;
  line-height: 1;
  color: var(--ink);
  background: var(--c);
  box-shadow:
    0 0 0 2px var(--on-paper),
    0 2px 0 rgba(0, 0, 0, 0.45),
    0 0 calc(var(--lit, 0) * 18px) var(--c);
  transform: scale(calc(1 + var(--lit, 0) * 0.2));
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}

.controller-map__board .keycap {
  position: absolute;
  translate: -50% -50%;
  cursor: default;
}

.controller-map__legend h3 {
  font-size: 1.15rem;
  color: var(--muted);
  margin: 28px 0 6px;
}

.controller-map__legend h3:first-child {
  margin-top: 0;
}

.controller-map__legend ul {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px dashed var(--line-strong);
}

.controller-map__legend li {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 10px 6px;
  border-bottom: 1px dashed var(--line-strong);
  font-size: 0.95rem;
  line-height: 1.5;
  background: color-mix(in srgb, var(--c) calc(var(--lit, 0) * 12%), transparent);
  transition: background 0.2s;
}

.controller-map__legend li b {
  display: block;
  font-family: var(--label);
  font-weight: 400;
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--c);
}

.controller-map__legend li .bead {
  cursor: default;
}

/* A key and its line in the legend light up together. */
.controller-map:has([data-key="menu"]:hover) [data-key="menu"],
.controller-map:has([data-key="y"]:hover) [data-key="y"],
.controller-map:has([data-key="x"]:hover) [data-key="x"],
.controller-map:has([data-key="left-stick"]:hover) [data-key="left-stick"],
.controller-map:has([data-key="b"]:hover) [data-key="b"],
.controller-map:has([data-key="a"]:hover) [data-key="a"],
.controller-map:has([data-key="right-stick"]:hover) [data-key="right-stick"],
.controller-map:has([data-key="meta"]:hover) [data-key="meta"],
.controller-map:has([data-key="trigger"]:hover) [data-key="trigger"],
.controller-map:has([data-key="grip"]:hover) [data-key="grip"] {
  --lit: 1;
}

.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.8s var(--ease), transform 0.8s var(--ease);
}

.reveal.is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }

  .reveal {
    opacity: 1;
    transform: none;
  }
}
