/* Shelf — a contact sheet for 780-odd Mac games.
   The palette runs cool so the posters (which are almost all warm) carry the colour.
   Two accents, each with exactly one job: amber = capacity, teal = your choices. */

:root {
  --ink:      #10141c;   /* ground */
  --ink-2:    #171d28;   /* raised surface */
  --ink-3:    #202836;   /* hairline */
  --ink-4:    #2b3546;   /* hairline, brighter */
  --chalk:    #e8ecf2;
  --mute:     #8b96a8;
  /* Lifted from #5d6779, which only reached 2.7:1 on the ground. This clears 4.5:1
     against both --ink and --ink-2, and carries the card size/hours line. */
  --mute-dim: #78859c;
  --amber:    #f0a02a;   /* capacity, gauges, warnings */
  --teal:     #5fd4d0;   /* selection, focus, links */
  --rose:     #e0645a;   /* weak scores */

  --pad: clamp(14px, 3.2vw, 30px);
  --gut: 10px;
  --r: 3px;

  --ui: 'Archivo', system-ui, -apple-system, sans-serif;
  --num: 'Martian Mono', ui-monospace, 'SF Mono', monospace;

  --lift: 180ms cubic-bezier(.2, .7, .3, 1);
}

* { box-sizing: border-box; }

/* Several layout rules below set `display: flex` on elements that get toggled with
   the `hidden` attribute, which would otherwise out-specify the UA's [hidden] rule. */
[hidden] { display: none !important; }

html {
  scroll-behavior: smooth;
  /* Clears the sticky header so the skip link doesn't land the first row underneath it. */
  scroll-padding-top: 210px;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--chalk);
  font: 400 15px/1.5 var(--ui);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

button, input, select { font: inherit; color: inherit; }

:where(a) { color: var(--teal); text-decoration-thickness: 1px; text-underline-offset: 2px; }

:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 2px;
  border-radius: 2px;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 60;
  background: var(--teal); color: var(--ink); padding: 10px 16px; font-weight: 600;
}
.skip:focus { left: 8px; top: 8px; }

/* Small uppercase labels are set in the mono so every readout on the page reads
   like it came off the same instrument. */
.lbl {
  font: 500 9.5px/1 var(--num);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--mute-dim);
  white-space: nowrap;
}

/* ── header ─────────────────────────────────────────────────────────────── */

/* One sticky block. Two separately-stuck bars would pile up at top: 0. */
.top {
  position: sticky; top: 0; z-index: 30;
  background: color-mix(in srgb, var(--ink) 92%, transparent);
  backdrop-filter: blur(20px) saturate(140%);
  border-bottom: 1px solid var(--ink-3);
}

.bar__row {
  display: flex; align-items: center; gap: clamp(12px, 2vw, 26px);
  padding: 11px var(--pad) 9px;
}

/* Width contrast rather than a second family: Archivo pulled wide and heavy. */
.wordmark {
  margin: 0;
  font: 700 19px/1 var(--ui);
  font-stretch: 125%;
  letter-spacing: -.005em;
  flex: none;
}

.find {
  position: relative;
  display: flex; align-items: center;
  flex: 1 1 auto; max-width: 520px;
}
.find__icon {
  position: absolute; left: 11px; width: 15px; height: 15px;
  color: var(--mute-dim); pointer-events: none;
}
.find input {
  width: 100%;
  padding: 9px 40px 9px 33px;
  background: var(--ink-2);
  border: 1px solid var(--ink-3);
  border-radius: var(--r);
  transition: border-color var(--lift), background var(--lift);
}
.find input::placeholder { color: var(--mute-dim); }
.find input:focus { border-color: var(--ink-4); background: #1b2230; outline: none; }
.find input:focus-visible { outline: 2px solid var(--teal); outline-offset: 1px; }
.find input::-webkit-search-cancel-button { filter: invert(.6); }

.find__kbd {
  position: absolute; right: 9px;
  font: 500 10px/1 var(--num);
  color: var(--mute-dim);
  border: 1px solid var(--ink-4); border-radius: 3px;
  padding: 3px 5px;
  pointer-events: none;
}
.find:focus-within .find__kbd { opacity: 0; }

.tally {
  font: 400 11px/1.35 var(--num);
  color: var(--mute);
  text-align: right;
  flex: none;
  min-width: 8ch;
}
.tally b { color: var(--chalk); font-weight: 500; }

/* ── the gauge (signature) ──────────────────────────────────────────────── */

.gauge {
  display: flex; align-items: center; gap: clamp(14px, 2.4vw, 30px);
  padding: 0 var(--pad) 10px;
  flex-wrap: wrap;
}

.gauge__set { display: flex; align-items: center; gap: 10px; flex: none; }

.numfield { position: relative; display: flex; align-items: center; }
.numfield input {
  width: 82px;
  padding: 6px 30px 6px 9px;
  font: 500 14px/1 var(--num);
  background: var(--ink-2);
  border: 1px solid var(--ink-3); border-radius: var(--r);
}
/* The native stepper collides with the GB suffix; typing is the only path here. */
.numfield input::-webkit-inner-spin-button,
.numfield input::-webkit-outer-spin-button { appearance: none; margin: 0; }
.numfield input { -moz-appearance: textfield; }
.numfield input:focus { border-color: var(--amber); outline: none; }
.numfield input:focus-visible { outline: 2px solid var(--amber); outline-offset: 1px; }
.numfield__unit {
  position: absolute; right: 9px;
  font: 500 10px/1 var(--num); color: var(--mute-dim); pointer-events: none;
}

.gauge__hint { margin: 0; font-size: 12.5px; color: var(--mute-dim); }

.gauge__meter { flex: 1 1 260px; display: flex; align-items: center; gap: 12px; min-width: 220px; }

.track {
  flex: 1 1 auto; height: 7px;
  background: var(--ink-2);
  border: 1px solid var(--ink-3);
  border-radius: 999px;
  overflow: hidden;
}
.track__fill {
  height: 100%; width: 0;
  background: linear-gradient(90deg, var(--amber), color-mix(in srgb, var(--amber) 62%, var(--rose)));
  transition: width 320ms cubic-bezier(.2, .7, .3, 1), background 200ms;
  border-radius: 999px;
}
.track.is-over .track__fill { background: var(--rose); }

.track__read {
  margin: 0; flex: none;
  font: 500 11px/1 var(--num);
  color: var(--amber);
}
.track__read.is-over { color: var(--rose); }

.gauge__list { display: flex; align-items: center; gap: 10px; flex: none; }

.picks { display: flex; gap: 4px; }
.picks button {
  width: 26px; height: 39px; padding: 0;
  border: 1px solid var(--ink-4); border-radius: 2px;
  background: var(--ink-2) center / cover no-repeat;
  cursor: pointer; position: relative;
  transition: transform var(--lift);
}
.picks button:hover { transform: translateY(-2px); border-color: var(--rose); }
.picks button::after {
  content: '×';
  position: absolute; inset: 0;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--ink) 72%, transparent);
  color: var(--rose); font-size: 15px; font-weight: 700;
  opacity: 0; transition: opacity var(--lift);
}
.picks button:hover::after, .picks button:focus-visible::after { opacity: 1; }

/* ── buttons ────────────────────────────────────────────────────────────── */

.btn {
  padding: 7px 13px;
  background: var(--ink-2);
  border: 1px solid var(--ink-4);
  border-radius: var(--r);
  font-size: 13px; font-weight: 500;
  cursor: pointer; white-space: nowrap;
  transition: border-color var(--lift), background var(--lift), color var(--lift);
}
.btn:hover { border-color: var(--teal); color: var(--teal); }
.btn--ghost { background: none; border-color: transparent; color: var(--mute); }
.btn--ghost:hover { color: var(--rose); border-color: transparent; }

.linkish {
  background: none; border: 0; padding: 0;
  color: var(--teal); cursor: pointer;
  text-decoration: underline; text-underline-offset: 2px;
}

/* ── filters ────────────────────────────────────────────────────────────── */

.filters { border-top: 1px solid var(--ink-3); }

.filters__scroll { overflow-x: auto; scrollbar-width: none; }
.filters__scroll::-webkit-scrollbar { display: none; }

.chips {
  display: flex; gap: 5px;
  padding: 9px var(--pad);
  width: max-content; min-width: 100%;
}

.chip {
  padding: 5px 11px;
  background: none;
  border: 1px solid var(--ink-3);
  border-radius: 999px;
  font-size: 12.5px; color: var(--mute);
  cursor: pointer; white-space: nowrap;
  transition: border-color var(--lift), color var(--lift), background var(--lift);
}
.chip:hover { color: var(--chalk); border-color: var(--ink-4); }
.chip[aria-pressed='true'] {
  background: var(--teal); border-color: var(--teal); color: var(--ink); font-weight: 600;
}
.chip__n { font: 500 10px/1 var(--num); opacity: .55; margin-left: 5px; }

.filters__row {
  display: flex; align-items: center; gap: clamp(10px, 1.6vw, 20px);
  padding: 0 var(--pad) 10px;
  flex-wrap: wrap;
}

.pick { display: flex; align-items: center; gap: 7px; }
.pick select {
  padding: 6px 8px;
  background: var(--ink-2);
  border: 1px solid var(--ink-3);
  border-radius: var(--r);
  font-size: 13px;
  cursor: pointer;
}
.pick select:hover { border-color: var(--ink-4); }

.toggle { display: flex; align-items: center; gap: 7px; font-size: 13px; color: var(--mute); cursor: pointer; }
.toggle:has(input:checked) { color: var(--chalk); }

/* A default checkbox renders near-white here and steals the page's brightest value
   from the posters, so it's drawn to match the other controls. */
.toggle input {
  appearance: none;
  width: 15px; height: 15px; margin: 0;
  background: var(--ink-2);
  border: 1px solid var(--ink-4); border-radius: 3px;
  cursor: pointer;
  display: grid; place-items: center;
  transition: background var(--lift), border-color var(--lift);
}
.toggle input:hover { border-color: var(--teal); }
.toggle input:checked { background: var(--teal); border-color: var(--teal); }
.toggle input:checked::after {
  content: '';
  width: 8px; height: 5px;
  border-left: 1.8px solid var(--ink); border-bottom: 1.8px solid var(--ink);
  transform: rotate(-45deg) translate(1px, -1px);
}

.filters__end { display: flex; gap: 8px; margin-left: auto; }

/* ── the wall ───────────────────────────────────────────────────────────── */

.wall {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(clamp(112px, 14vw, 168px), 1fr));
  gap: var(--gut) calc(var(--gut) - 2px);
  padding: var(--pad) var(--pad) 0;
  align-items: start;
}

/* The grid item. Holds two sibling buttons — the card and the wishlist heart —
   because nesting a button inside a button is invalid and gets dropped. */
.cell {
  position: relative;
  animation: rise 300ms both;
}

.card {
  display: flex; flex-direction: column; gap: 7px;
  width: 100%;
  padding: 0; background: none; border: 0;
  text-align: left; cursor: pointer;
  color: inherit;
}

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

/* ── wishlist heart ─────────────────────────────────────────────────────── */

.wish {
  position: absolute; top: 4px; left: 4px; z-index: 2;
  width: 30px; height: 30px; padding: 0;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--ink) 62%, transparent);
  backdrop-filter: blur(6px);
  border: 1px solid transparent;
  border-radius: var(--r);
  color: var(--chalk);
  cursor: pointer;
  /* Hidden until you go looking for it, so the wall stays about the posters.
     Anything already wishlisted stays visible. */
  opacity: 0;
  transition: opacity var(--lift), color var(--lift), border-color var(--lift), transform var(--lift);
}
.wish svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.6px; }

.cell:hover .wish,
.wish:focus-visible { opacity: 1; }
.wish:hover { color: var(--rose); border-color: color-mix(in srgb, var(--rose) 45%, transparent); transform: scale(1.08); }

.wish.is-on { opacity: 1; color: var(--rose); }
.wish.is-on svg { fill: currentColor; stroke: currentColor; }
.wish.is-on:hover { color: color-mix(in srgb, var(--rose) 75%, #fff); }

/* Touch devices have no hover, so the control has to be permanently visible
   and big enough to hit. */
@media (hover: none) {
  .wish { opacity: 1; width: 38px; height: 38px; }
  .wish svg { width: 20px; height: 20px; }
}

.card__art {
  position: relative;
  aspect-ratio: 2 / 3;
  border-radius: var(--r);
  overflow: hidden;
  background: var(--ink-2);
  box-shadow: 0 1px 0 var(--ink-3);
  transition: transform var(--lift), box-shadow var(--lift);
}
.card:hover .card__art,
.card:focus-visible .card__art {
  transform: translateY(-3px);
  box-shadow: 0 10px 24px -8px #000, 0 0 0 1px var(--ink-4);
}

.card__art img {
  position: relative;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}

/* Sources disagree on shape: Steam library art is 2:3, App Store icons are square,
   Steam headers are 16:7. Anything that isn't a true poster is letterboxed over a
   blurred copy of itself so the grid stays even without cropping art to pieces. */
.card__art--pad img { object-fit: contain; }
.card__art--pad::before {
  content: '';
  position: absolute; inset: -18%;
  background: var(--bg) center / cover no-repeat;
  filter: blur(26px) saturate(130%) brightness(.55);
}

.card__art--none {
  display: grid; place-items: center;
  border: 1px dashed var(--ink-4);
}
.card__art--none span {
  font: 500 9px/1.4 var(--num);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--mute-dim); text-align: center; padding: 8px;
}

.score {
  position: absolute; top: 5px; right: 5px;
  min-width: 24px; padding: 3px 4px;
  font: 600 10.5px/1 var(--num);
  text-align: center;
  border-radius: 2px;
  background: color-mix(in srgb, var(--ink) 78%, transparent);
  backdrop-filter: blur(6px);
  border: 1px solid transparent;
}
.score--high { color: var(--teal);  border-color: color-mix(in srgb, var(--teal) 42%, transparent); }
.score--mid  { color: var(--chalk); border-color: var(--ink-4); }
.score--low  { color: var(--rose);  border-color: color-mix(in srgb, var(--rose) 42%, transparent); }

/* Won't fit the stated budget: hatched and dimmed, still clickable. */
.card--tight .card__art { opacity: .3; }
.card--tight .card__art::after {
  content: '';
  position: absolute; inset: 0;
  background: repeating-linear-gradient(-45deg, transparent 0 5px, color-mix(in srgb, var(--rose) 26%, transparent) 5px 6px);
}
.card--tight .card__name { color: var(--mute-dim); }
.card--tight .card__data { color: var(--rose); }

.card__name {
  font-size: 12.5px; font-weight: 500; line-height: 1.25;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

.card__data {
  font: 400 10px/1.3 var(--num);
  color: var(--mute-dim);
  display: flex; gap: 6px; flex-wrap: wrap;
}
.card__data i { font-style: normal; }

/* Marks a card whose art and numbers came from a title we matched only loosely. */
.card__doubt {
  color: var(--amber);
  border: 1px solid color-mix(in srgb, var(--amber) 40%, transparent);
  border-radius: 2px;
  padding: 0 3px;
  cursor: help;
  font-weight: 600;
}

.sentinel { height: 1px; }

.void { padding: 60px var(--pad); color: var(--mute); text-align: center; }

.foot {
  max-width: 62ch;
  margin: 56px auto 0;
  padding: 26px var(--pad) 60px;
  border-top: 1px solid var(--ink-3);
  color: var(--mute-dim);
  font-size: 12.5px;
}
.foot p { margin: 0 0 9px; }
.foot__thin { line-height: 1.6; }

/* ── detail sheet ───────────────────────────────────────────────────────── */

.scrim {
  position: fixed; inset: 0; z-index: 40;
  background: color-mix(in srgb, #05070b 68%, transparent);
  backdrop-filter: blur(3px);
  animation: fade 200ms both;
}
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

.sheet {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 41;
  width: min(460px, 100vw);
  background: var(--ink-2);
  border-left: 1px solid var(--ink-4);
  overflow-y: auto; overscroll-behavior: contain;
  animation: slide 260ms cubic-bezier(.2, .7, .3, 1) both;
}
@keyframes slide { from { transform: translateX(24px); opacity: 0; } to { transform: none; opacity: 1; } }

/* Sticky, not absolute: .sheet is the scroll container, so an absolutely-positioned
   close button scrolls out of reach on a long detail panel. */
.sheet__close {
  position: sticky; top: 12px; float: right; margin-right: 12px; z-index: 2;
  width: 32px; height: 32px; padding: 0;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--ink) 62%, transparent);
  backdrop-filter: blur(8px);
  border: 1px solid var(--ink-4); border-radius: var(--r);
  cursor: pointer;
}
.sheet__close:hover { color: var(--rose); border-color: var(--rose); }
.sheet__close svg { width: 15px; height: 15px; }

.hero { position: relative; aspect-ratio: 16 / 8; background: var(--ink-3); }
.hero img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hero::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(to top, var(--ink-2) 2%, transparent 72%);
}

/* ── trailer ────────────────────────────────────────────────────────────── */

.hero--play { cursor: pointer; }

.play {
  position: absolute; left: 16px; bottom: 14px; z-index: 2;
  display: flex; align-items: center; gap: 7px;
  padding: 8px 14px 8px 11px;
  background: color-mix(in srgb, var(--ink) 58%, transparent);
  backdrop-filter: blur(10px);
  border: 1px solid color-mix(in srgb, var(--chalk) 26%, transparent);
  border-radius: 999px;
  color: var(--chalk);
  font: 500 12.5px/1 var(--ui);
  cursor: pointer;
  transition: background var(--lift), border-color var(--lift), transform var(--lift);
}
.play svg { width: 15px; height: 15px; fill: currentColor; }
.hero--play:hover .play { background: var(--teal); border-color: var(--teal); color: var(--ink); transform: scale(1.03); }

/* Once playing, the video replaces the still and the gradient must not sit over it. */
.hero.is-playing { aspect-ratio: 16 / 9; cursor: default; }
.hero.is-playing::after { display: none; }
.hero.is-playing img,
.hero.is-playing .play { display: none; }
.hero video { width: 100%; height: 100%; display: block; background: #000; }

.hero__note {
  position: absolute; inset: auto 16px 14px; z-index: 2; margin: 0;
  padding: 8px 11px;
  background: color-mix(in srgb, var(--ink) 78%, transparent);
  backdrop-filter: blur(8px);
  border-left: 2px solid var(--amber);
  font-size: 12.5px; color: #d6c9ae;
}

/* ── screenshots ────────────────────────────────────────────────────────── */

.shots {
  display: grid; grid-auto-flow: column;
  grid-auto-columns: 62%;
  gap: 7px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.shots::-webkit-scrollbar { display: none; }
.shots img {
  width: 100%; aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--r);
  border: 1px solid var(--ink-3);
  scroll-snap-align: start;
  display: block;
}

.sheet__body > section { padding: 0 22px; }
.sheet__body > section + section { margin-top: 26px; }

/* The title overlaps the still image on purpose. Once a trailer is playing that
   negative margin would sit on top of the video's control bar, so drop it. */
.sheet__head { position: relative; margin-top: -46px; z-index: 1; }
.hero.is-playing + .sheet__head { margin-top: 16px; }
.sheet__head h2 {
  margin: 0 0 5px;
  font: 700 25px/1.12 var(--ui);
  font-stretch: 112%;
  letter-spacing: -.015em;
}
.sheet__sub { margin: 0; font-size: 13px; color: var(--mute); }
.sheet__blurb { margin: 14px 0 0; font-size: 14px; line-height: 1.6; color: #c3cbd8; }

.stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 1px;
  background: var(--ink-3);
  border: 1px solid var(--ink-3); border-radius: var(--r);
  overflow: hidden;
}
.stat { padding: 11px 12px; background: var(--ink-2); }
.stat b {
  display: block; margin-top: 5px;
  font: 500 17px/1 var(--num);
  font-weight: 500;
}
.stat small { display: block; margin-top: 4px; font-size: 11px; color: var(--mute-dim); }

.rows { display: flex; flex-direction: column; gap: 1px; background: var(--ink-3); border-radius: var(--r); overflow: hidden; }
.row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  padding: 10px 12px; background: var(--ink-2);
  font-size: 13px;
}
.row span { color: var(--mute); }
.row b { font: 500 13px/1 var(--num); font-weight: 500; text-align: right; }

.sheet h3 { margin: 0 0 10px; font: 500 9.5px/1 var(--num); letter-spacing: .14em; text-transform: uppercase; color: var(--mute-dim); }

.taglist { display: flex; flex-wrap: wrap; gap: 5px; }
.taglist span {
  padding: 4px 9px;
  border: 1px solid var(--ink-4); border-radius: 999px;
  font-size: 12px; color: var(--mute);
}

/* Needs to out-specify `.sheet__body > section { padding: 0 22px }`, whose shorthand
   would otherwise reset the bottom padding to zero. */
.sheet__body > section.sheet__acts { display: flex; gap: 8px; flex-wrap: wrap; padding-bottom: 44px; }
.sheet__acts .btn { flex: 1 1 auto; text-align: center; text-decoration: none; }
.btn--on { background: var(--teal); border-color: var(--teal); color: var(--ink); font-weight: 600; }
.btn--on:hover { background: color-mix(in srgb, var(--teal) 82%, #fff); border-color: var(--teal); color: var(--ink); }

.warn {
  margin: 12px 0 0; padding: 9px 11px;
  border-left: 2px solid var(--amber);
  background: color-mix(in srgb, var(--amber) 8%, transparent);
  font-size: 12.5px; color: #d6c9ae;
}

/* ── smaller screens ────────────────────────────────────────────────────── */

@media (max-width: 720px) {
  :root { --pad: 13px; --gut: 8px; }

  .bar__row { flex-wrap: wrap; gap: 10px; }
  .find { order: 3; flex-basis: 100%; max-width: none; }
  .tally { margin-left: auto; }
  .find__kbd { display: none; }

  /* Four rows of chrome is most of a phone screen, so let it scroll away rather
     than pinning it over the posters. */
  .top { position: static; }
  html { scroll-padding-top: 0; }

  /* `flex: none` made this block as wide as its hint sentence, pushing the whole
     document ~160px wider than the viewport. */
  .gauge { gap: 9px 12px; }
  .gauge__set { flex: 1 1 100%; min-width: 0; flex-wrap: wrap; }
  .gauge__hint { flex: 1 1 100%; font-size: 12px; }
  .gauge__meter { flex-basis: 100%; }
  .gauge__list { flex: 1 1 100%; }
  .picks { flex-wrap: wrap; }

  .filters__row { gap: 9px 14px; }
  .filters__end { margin-left: 0; }

  .sheet { width: 100vw; }
  .sheet__body > section { padding: 0 16px; }
  /* Four stats in a 3-up grid leaves a dead cell; 2x2 reads better on a phone. */
  .stats { grid-template-columns: repeat(2, 1fr); }
}

/* Very narrow phones. The select labels stay: three of these controls read only
   "Any" on their own, so the label is the whole meaning. */
@media (max-width: 400px) {
  .wall { grid-template-columns: repeat(auto-fill, minmax(102px, 1fr)); }
  .pick { gap: 5px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    transition-duration: 1ms !important;
  }
}
