/* Hardpack Rally, hardpackrally.com
   The game's page since the Steam store page opened (1 Oct 2026): a hero
   with the wishlist button, Vern's note, the four cars, the shots, what is
   in the game, the stream, and the date. Each band is short; the page is
   still a front door to the store, not a manual.

   THE PALETTE IS THE GAME'S OWN SINCE 19 SEP 2026. The owner picked two
   rows off a design canvas that week -- the arcade title for every menu,
   the stage plate for the run -- and asked for the site in the same
   colors ("Can you please update the main site with these colors and
   theme"). So the page is the menus: deep blue, one hot yellow, a cherry
   red that falls behind everything as a hard offset shadow, and the
   checkered strip the title screen carries along its foot. The one warm
   orange is the run's, kept for the things that belong to driving.

   The faces are the game's four, subset to what a web page sets and
   served from this domain (web/fonts, 65 KB the lot): Russo One for the
   big words, Exo 2 italic for the bars and labels, Barlow Condensed for
   numbers, Barlow for reading. The page fetches nothing from anybody
   else, which is how it was built and worth keeping -- but for Twitch's
   player in the live band, which the owner asked for (24 Sep 2026).

   The token NAMES are older than the palette and are kept on purpose:
   /dials, /replay, /feedback and /admin all paint themselves out of
   them, so repointing them here moves the whole site at once. */

@font-face {
  font-family: "Russo One"; src: url("/fonts/russo-one.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Exo 2"; src: url("/fonts/exo2-italic.woff2") format("woff2");
  font-weight: 100 900; font-style: italic; font-display: swap;
}
@font-face {
  font-family: "Barlow Condensed"; src: url("/fonts/barlow-condensed-bold.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Barlow"; src: url("/fonts/barlow-regular.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Barlow"; src: url("/fonts/barlow-semibold.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}
/* Vern's hand: the game's notes are set in Caveat (OFL, The Caveat Project
   Authors), so his lines on the page are too. Pinned to 600 and subset to
   Latin from godot/fonts/Caveat.ttf, its contextual alternates kept so the
   letters vary the way they do on his notes. Not preloaded: nothing above
   the fold uses it. */
@font-face {
  font-family: "Caveat"; src: url("/fonts/caveat.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}

:root {
  --snow:   #14264a;   /* the page: the menus' deep blue */
  --haze:   #0b1630;   /* one step down: the closing band and the footer */
  --face:   #1c2f57;   /* panel and tile faces */
  --line:   rgba(255, 255, 255, 0.16);
  --slate:  #f4f1ec;   /* the text: the menus' warm white */
  --dim:    #9fb0cc;   /* the quieter line */
  --pine:   #ffd21f;   /* the accent, and every link: the menus' yellow */
  --pine-2: #ffe066;   /* hover */
  --sky:    #37c8ff;   /* the map's blue, for a wash */
  --rust:   #e63946;   /* the cherry the menus drop behind everything */
  --orange: #ff7a2f;   /* the run's own accent: driving, and only that */
  --ink:    #0c0e11;   /* the run's plates */
  --skew:   -10deg;
  --display: "Russo One", Impact, "Haettenschweiler", sans-serif;
  --bar-face: "Exo 2", "Segoe UI", system-ui, sans-serif;
  --cond:   "Barlow Condensed", "Arial Narrow", sans-serif;
  --body:   "Barlow", "Segoe UI", system-ui, -apple-system, sans-serif;
  --hand:   "Caveat", "Segoe Print", "Bradley Hand", cursive;
  --bar-h:    58px;
  --pad:      clamp(20px, 5vw, 72px);
  /* One column for the whole page. Every band is full width so its
     background reaches the edges, and every band's content sits inside
     this: the page's own margin until the screen is wider than the
     content, then whatever centers it. The bar, the hero's words, the
     paragraph, the shots and the footer all line up on it. */
  --wrap:     1320px;
  --gutter:   max(var(--pad), calc((100% - var(--wrap)) / 2));
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--snow);
  color: var(--slate);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }

a { color: var(--pine); text-decoration: none; }
a:hover { color: var(--pine-2); }

:focus-visible { outline: 2px solid var(--pine); outline-offset: 3px; }

/* The checkered strip the title screen carries along its foot. It is a
   band of its own so it can close the hero and open the closing note. */
.checker {
  height: 14px;
  background: repeating-conic-gradient(var(--haze) 0 25%, var(--slate) 0 50%) 0 0 / 14px 14px;
}

/* ---------------------------------------------------------------- the bar */

.bar {
  position: sticky; top: 0; z-index: 50;
  height: var(--bar-h);
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 0 var(--gutter);
  background: rgba(11, 22, 48, 0.94);
  backdrop-filter: blur(6px);
  border-bottom: 2px solid var(--pine);
}
.mark {
  font-family: var(--display);
  color: var(--pine); font-size: 17px; letter-spacing: 0.02em;
  white-space: nowrap;
  text-shadow: 2px 2px 0 var(--rust);
}
a.mark:hover { color: var(--pine-2); }
.bar-right { display: flex; align-items: center; gap: 12px; }
/* The pill was plain text kept for the Steam link until the store page
   opened (1 Oct 2026); now it is that link, on every page that has it. */
.pill {
  font-family: var(--bar-face); font-style: italic; font-weight: 700;
  font-size: 11px; letter-spacing: 0.12em; color: var(--haze);
  background: var(--pine);
  transform: skewX(var(--skew));
  padding: 5px 13px; white-space: nowrap;
}
a.pill { color: var(--haze); box-shadow: 3px 3px 0 var(--rust); transition: background 0.2s ease; }
a.pill:hover { color: var(--haze); background: var(--pine-2); }
a.pill > span { display: inline-block; transform: skewX(calc(-1 * var(--skew))); }

/* --------------------------------------------------------------- the hero */

.hero { position: relative; min-height: min(92vh, 860px); display: flex; overflow: hidden; }
.hero-art { position: absolute; inset: 0; }
.hero-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  max-width: none;   /* the page-wide img cap would pin it to the frame */
  object-fit: cover; object-position: 90% 52%;
}
/* The 10 Oct photograph puts the current Hayai at the right of a mountain
   road at sunset. The existing wash keeps the words clear over the hillside. */
/* The breath from the left is a radial one anchored at the bottom left,
   under the lede, the facts and the button: a straight wash from the left
   edge turned the sun, high on that side, into a grey disc (1 Oct 2026). */
.hero::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(to bottom, rgba(20,38,74,0) 0%, rgba(20,38,74,0) 56%,
                    rgba(20,38,74,0.55) 86%, var(--snow) 100%),
    radial-gradient(75% 80% at 0% 100%, rgba(11,22,48,0.74) 0%, rgba(11,22,48,0.42) 45%,
                    rgba(11,22,48,0) 100%);
}
.hero-wrap {
  position: relative; z-index: 2;
  align-self: flex-end;
  padding: clamp(34px, 6vh, 72px) var(--gutter) clamp(56px, 9vh, 110px);
  width: 100%;
}
/* The name as the title screen sets it: two words stacked, the first
   yellow and the second white, each with the cherry dropped hard behind
   it. */
.hero h1 {
  font-family: var(--display);
  font-size: clamp(44px, 9.4vw, 122px);
  line-height: 0.92;
  letter-spacing: 0;
  margin: 0 0 22px;
  color: var(--pine);
  font-weight: 400;
  text-shadow: 6px 6px 0 var(--rust);
}
.hero h1 .two { color: #ffffff; }
.lede {
  margin: 0 0 26px;
  font-size: clamp(16px, 1.7vw, 20px);
  line-height: 1.55;
  max-width: 44ch;
  color: var(--slate);
  text-shadow: 0 2px 14px rgba(11, 22, 48, 0.9);
}
.facts {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 10px;
}
.facts li {
  font-family: var(--bar-face); font-style: italic; font-weight: 700;
  font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase;
  background: rgba(255, 255, 255, 0.12);
  color: var(--slate);
  transform: skewX(var(--skew));
  padding: 7px 15px;
}
.facts li > span { display: inline-block; transform: skewX(calc(-1 * var(--skew))); }
.facts li:first-child { background: var(--pine); color: var(--haze); box-shadow: 5px 5px 0 var(--rust); }

/* Keep the car, at the right of the new photograph, in portrait crops. */
@media (max-width: 1100px) { .hero-img { object-position: 100% 52%; } }
@media (max-width: 700px) {
  /* The portrait photograph leaves sky behind the words and places the
     car on the road below the buttons. */
  .hero { min-height: max(680px, min(82vh, 800px)); }
  .hero-img { object-position: 100% 52%; }
  .hero-wrap { align-self: flex-start; padding-top: clamp(26px, 5vh, 52px); }
  .hero::after {
    background:
      linear-gradient(to bottom, rgba(11,22,48,0.82) 0%, rgba(11,22,48,0.3) 40%,
                      rgba(20,38,74,0.1) 78%, rgba(20,38,74,0.18) 92%, var(--snow) 100%);
  }
  .hero h1 { text-shadow: 4px 4px 0 var(--rust); }
}

/* --------------------------------------------------------- live on Twitch */

/* The owner streams the game driving itself, around the clock, and asked
   for it on the page, "obvious" (24 Sep 2026). A band of its own straight
   under the hero: the words and a button on the left, the player on the
   right, stacked on a narrow screen. The frame is a 16:9 box with the
   cherry dropped behind it like a tile's; site.js puts Twitch's player in
   it where the box can meet Twitch's 400 x 300 minimum, and anywhere
   narrower the card below stays: a picture and a WATCH LIVE row that opens
   Twitch (its app, on a phone). The player is the one thing on this page
   that comes from somebody else's server, by the owner's ask. */
.live {
  scroll-margin-top: var(--bar-h);   /* hardpackrally.com/#live, under the sticky bar */
  padding: clamp(40px, 6vw, 76px) var(--gutter);
  display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  gap: clamp(26px, 3.4vw, 48px); align-items: center;
  background:
    radial-gradient(70% 120% at 85% 50%, rgba(145, 70, 255, 0.10) 0%,
                    rgba(11, 22, 48, 0) 60%),
    var(--haze);
}
.live h2 {
  font-family: var(--display); font-weight: 400; letter-spacing: 0;
  margin: 0 0 16px; color: var(--pine);
  font-size: clamp(28px, 3.3vw, 44px); line-height: 1.05;
  text-shadow: 4px 4px 0 var(--rust);
  display: flex; align-items: center; gap: 0.4em;
}
/* a light, not a claim: it does not blink */
.live-dot {
  width: 0.36em; height: 0.36em; flex: none; border-radius: 50%;
  background: var(--rust); box-shadow: 0 0 0 0.12em rgba(230, 57, 70, 0.28);
}
.live p { margin: 0; max-width: 40ch; }
.live .live-go { margin-top: 28px; }
.live-frame {
  position: relative; aspect-ratio: 16 / 9;
  background: var(--ink); border: 1px solid var(--line);
  box-shadow: 8px 8px 0 var(--rust);
}
.live-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.live-frame.on .live-card { display: none; }
.live-card { position: absolute; inset: 0; display: block; overflow: hidden; }
.live-card img { width: 100%; height: 100%; object-fit: cover; opacity: 0.72; }
.live-play {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%) skewX(var(--skew));
  font-family: var(--bar-face); font-style: italic; font-weight: 800;
  font-size: clamp(15px, 2vw, 19px); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--haze); background: var(--pine);
  box-shadow: 6px 6px 0 var(--rust);
  padding: 14px 26px; white-space: nowrap;
}
.live-play > span { display: inline-block; transform: skewX(calc(-1 * var(--skew))); }
.live-card:hover .live-play { background: var(--pine-2); }
.live.carded .live-go { display: none; }
@media (max-width: 900px) {
  .live { grid-template-columns: 1fr; }
  .live p { max-width: 60ch; }
}

/* ------------------------------------------------------- the hero's button */

.hero-go { margin: 30px 0 0; }
.yt.steam { font-size: 15px; padding: 15px 28px; }
.yt.steam svg { width: 22px; height: 22px; }

/* --------------------------------------------------- the bands' headings */

/* Every band below the hero opens the way the stream's does: the display
   face in yellow with the cherry dropped behind it. */
.story h2, .cars h2, .shots-head h2 {
  font-family: var(--display); font-weight: 400; letter-spacing: 0;
  margin: 0 0 18px; color: var(--pine);
  font-size: clamp(28px, 3.6vw, 46px); line-height: 1.08;
  text-shadow: 4px 4px 0 var(--rust);
}
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------- Vern's note */

/* The store page's opening words beside the note itself, on the Dimmer's
   hood with the keys: the first thing a career shows. */
.story {
  padding: clamp(56px, 8vw, 104px) var(--gutter) clamp(44px, 6vw, 80px);
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: clamp(28px, 4.4vw, 64px); align-items: center;
}
.story p {
  margin: 0 0 16px; max-width: 60ch;
  font-size: clamp(16px, 1.4vw, 18.5px); line-height: 1.75;
}
.story p:last-child { margin-bottom: 0; }
.story .tile { box-shadow: 8px 8px 0 var(--rust); }
.story .tile img { aspect-ratio: 4 / 3; }
@media (max-width: 900px) {
  .story { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------- the cars */

/* Four cards, two by two: the studio portrait, the chapter it opens, the
   name, a line on how it drives, and Vern's own first words about it (his
   line from godot/data/lines/vern.toml), in his hand. */
.cars {
  padding: clamp(44px, 6vw, 84px) var(--gutter) clamp(56px, 8vw, 104px);
  background:
    radial-gradient(80% 90% at 50% 0%, rgba(55, 200, 255, 0.07) 0%, rgba(11, 22, 48, 0) 70%),
    var(--haze);
}
.cars-head { margin-bottom: clamp(26px, 3vw, 40px); }
.cars-head p { margin: 0; max-width: 66ch; font-size: clamp(16px, 1.4vw, 18px); }
.car-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(18px, 2.2vw, 30px); }
.car {
  margin: 0; display: flex; flex-direction: column;
  background: var(--face); border: 1px solid var(--line);
}
.car .tile { border: 0; border-bottom: 1px solid var(--line); }
.car .tile:hover { box-shadow: none; transform: none; }
.car-words { padding: 20px 24px 24px; display: flex; flex-direction: column; flex: 1; }
.car-ch { margin: 0 0 12px; }
.car-ch > span {
  display: inline-block;
  font-family: var(--bar-face); font-style: italic; font-weight: 700;
  font-size: 11.5px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--haze); background: var(--pine);
  transform: skewX(var(--skew)); padding: 4px 12px;
  box-shadow: 4px 4px 0 var(--rust);
}
.car h3 {
  font-family: var(--display); font-weight: 400; letter-spacing: 0;
  margin: 0 0 6px; color: #ffffff; font-size: clamp(22px, 2.2vw, 28px); line-height: 1.1;
}
.car-spec { margin: 0 0 14px; color: var(--dim); font-size: 15.5px; line-height: 1.55; }
.vern { margin: auto 0 0; padding: 0; }
.vern p {
  margin: 0; font-family: var(--hand); font-weight: 600;
  font-size: clamp(22px, 2vw, 26px); line-height: 1.25; color: #fff4dc;
}
/* signed the way his notes are */
.vern::after {
  content: "\2014 Vern"; display: block; margin-top: 4px;
  font-family: var(--hand); font-weight: 600; font-size: 20px; color: var(--pine);
}
@media (max-width: 760px) {
  .car-grid { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------- the shots */

.shots-head { padding: clamp(56px, 8vw, 100px) var(--gutter) clamp(22px, 2.6vw, 34px); }
.shots-head p { margin: 0; max-width: 62ch; font-size: clamp(16px, 1.4vw, 18px); }

/* ------------------------------------------------------- what's in the game */

/* The store page's feature list, six short items on three columns, and the
   one line it closes on. */
.features { padding: 0 var(--gutter) clamp(60px, 8vw, 110px); }
.feat-list {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(18px, 2.2vw, 30px);
}
.feat {
  padding: 22px 24px 24px; background: var(--face);
  border: 1px solid var(--line); border-top: 4px solid var(--rust);
}
.feat h3 {
  font-family: var(--bar-face); font-style: italic; font-weight: 800;
  font-size: 16px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--pine); margin: 0 0 10px; line-height: 1.3;
}
.feat p { margin: 0; font-size: 15.5px; line-height: 1.65; }
.no-ads {
  margin: clamp(26px, 3vw, 38px) 0 0;
  font-family: var(--cond); font-weight: 700; font-size: 19px;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--slate);
}
@media (max-width: 1000px) { .feat-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .feat-list { grid-template-columns: 1fr; } }

/* -------------------------------------------------------------- the shots */

.grid {
  padding: 0 var(--gutter) clamp(56px, 8vw, 104px);
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px;
}
.tile {
  padding: 0; border: 1px solid var(--line); background: var(--face);
  cursor: zoom-in; overflow: hidden; display: block;
  transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
}
.tile img {
  aspect-ratio: 16 / 9; object-fit: cover; width: 100%;
  transition: transform 0.35s ease, opacity 0.35s ease;
}
.tile:hover {
  border-color: var(--pine);
  box-shadow: 7px 7px 0 var(--rust);
  transform: translate(-2px, -2px);
}
.tile:hover img { transform: scale(1.05); opacity: 0.94; }
@media (prefers-reduced-motion: reduce) {
  .tile, .tile img { transition: none; }
  .tile:hover { transform: none; }
}
@media (max-width: 900px) {
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) { .grid { grid-template-columns: 1fr; } }

/* ------------------------------------------------------- the closing note */

.cta {
  padding: clamp(60px, 9vw, 116px) var(--gutter);
  background:
    radial-gradient(90% 140% at 20% 0%, rgba(55, 200, 255, 0.10) 0%,
                    rgba(11, 22, 48, 0) 62%),
    var(--haze);
}
.cta h2 {
  font-family: var(--display);
  margin: 0 0 18px; font-weight: 400; color: var(--pine);
  font-size: clamp(28px, 4.6vw, 52px); letter-spacing: 0;
  text-shadow: 4px 4px 0 var(--rust);
}
.cta p { margin: 0; max-width: 62ch; }
.cta .small { margin-top: 18px; color: var(--dim); font-size: 13.5px; }
/* hardpackrally.com/#count-me-in was said on stream before the store page
   opened; it lands here, clear of the sticky bar */
.cta { scroll-margin-top: var(--bar-h); }
.cta .anchor { display: block; position: relative; top: calc(-1 * var(--bar-h)); }
/* the channels beside the store's button, quieter than it */
.yt.quiet {
  color: var(--slate); background: transparent;
  box-shadow: inset 0 0 0 1px var(--line);
}
.yt.quiet svg { color: var(--slate); }
.yt.quiet:hover { color: var(--haze); background: var(--pine); box-shadow: 6px 6px 0 var(--rust); }
.yt.quiet:hover svg { color: var(--haze); }

/* The channel, the one link that leaves the page. It is a link, not a new
   band (docs/website.md): the bar, a button in the closing block, a word in
   the footer. The mark is drawn inline, so the page still fetches nothing
   from anyone else. The button is a menu row: slanted, yellow, the cherry
   behind it. */
.cta .watch { margin-top: 32px; display: flex; flex-wrap: wrap; gap: 18px 22px; max-width: none; }
.yt {
  display: inline-flex; align-items: center; gap: 11px;
  font-family: var(--bar-face); font-style: italic; font-weight: 800;
  color: var(--haze);
  font-size: 14px; letter-spacing: 0.1em; text-transform: uppercase;
  background: var(--pine);
  transform: skewX(var(--skew));
  box-shadow: 6px 6px 0 var(--rust);
  padding: 13px 24px;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.yt > * { transform: skewX(calc(-1 * var(--skew))); }
.yt svg { width: 20px; height: 20px; flex: none; color: var(--haze); }
.yt:hover {
  color: var(--haze);
  transform: skewX(var(--skew)) translate(-2px, -2px);
  box-shadow: 8px 8px 0 var(--rust);
}
@media (prefers-reduced-motion: reduce) {
  .yt, .yt:hover { transition: none; transform: skewX(var(--skew)); }
}

/* The same link in the bar, where it has to survive a phone: the word
   goes first, then the padding, and the mark stays. */
.yt-top {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--bar-face); font-style: italic; font-weight: 700;
  color: var(--slate);
  font-size: 11.5px; letter-spacing: 0.1em; text-transform: uppercase;
  border: 1px solid var(--line);
  padding: 5px 11px; white-space: nowrap;
}
.yt-top svg { width: 16px; height: 16px; flex: none; color: var(--rust); }
.yt-top:hover {
  color: var(--haze); border-color: var(--pine); background: var(--pine);
}
.yt-top:hover svg { color: var(--haze); }
@media (max-width: 760px) {
  .yt-top .label { display: none; }
  .yt-top { padding: 5px 8px; gap: 0; }
}
/* Twitch's mark is the channel's, drawn the same way, in its own purple */
.tw-top svg { color: #9146ff; }
@media (max-width: 430px) {
  .bar { gap: 10px; }
  .bar-right { gap: 8px; }
  .mark { font-size: 14px; }
  .pill { font-size: 10px; padding: 5px 9px; }
  .pill-more { display: none; }   /* WISHLIST alone fits a phone's bar */
  /* no room for a third thing on a phone's bar; the stream's band is the
     first thing under the hero there anyway */
  .tw-top { display: none; }
}

/* ------------------------------------------------------------ count me in */

/* The wishlist for before there is a Steam page (site.js, "count me in";
   the worker's section of the same name). The boxes are empty in the HTML
   and drawn by the script, so with no worker there is no box and nothing
   moves. The button is a menu row like the channel's; the hero's box sits
   under the facts and the closing block's under its line. */
.wish { margin-top: 26px; }
.wish:empty { display: none; }
/* Since the store page opened (1 Oct 2026) the boxes are gone and only this
   stays in the closing block: an address left before then comes off here */
.wish-off { margin-top: 14px; }
.wish-off:empty { display: none; }
.wish-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 22px; }
.wish-go {
  font-family: var(--bar-face); font-style: italic; font-weight: 800;
  font-size: 14px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--haze); background: var(--pine);
  border: 0; cursor: pointer;
  transform: skewX(var(--skew));
  box-shadow: 6px 6px 0 var(--rust);
  padding: 13px 26px;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.wish-go > span, .wish-in > span { display: inline-block; transform: skewX(calc(-1 * var(--skew))); }
.wish-go:hover:not(:disabled) {
  transform: skewX(var(--skew)) translate(-2px, -2px);
  box-shadow: 8px 8px 0 var(--rust);
}
.wish-go:disabled { opacity: 0.7; cursor: progress; }
.wish-in {
  font-family: var(--bar-face); font-style: italic; font-weight: 800;
  font-size: 13px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--haze); background: var(--pine);
  transform: skewX(var(--skew));
  box-shadow: 5px 5px 0 var(--rust);
  padding: 7px 16px;
}
.wish-count {
  font-family: var(--cond); font-weight: 700;
  font-size: 16px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--slate);
}
.wish-count b { color: var(--pine); font-size: 21px; letter-spacing: 0.02em; }
.wish-note { margin-top: 14px; max-width: 60ch; font-size: 15.5px; line-height: 1.55; }
.wish-note b { font-weight: 600; color: var(--pine); overflow-wrap: anywhere; }
.wish-form {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
  margin-top: 12px; max-width: 560px;
}
.wish-form input[type="email"] {
  flex: 1 1 220px; min-width: 0; height: 46px;
  font-size: 16px;               /* under 16px a phone zooms the page on focus */
  padding: 0 13px; border: 1px solid; border-radius: 0;
}
.wish-send {
  height: 46px; padding: 0 22px;
  font-family: var(--bar-face); font-style: italic; font-weight: 800;
  font-size: 13px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--haze); background: var(--pine); border: 0; cursor: pointer;
}
.wish-send:hover:not(:disabled) { background: var(--pine-2); }
.wish-send:disabled { opacity: 0.7; cursor: progress; }
.wish-link {
  font: inherit; color: var(--pine); background: none; border: 0; padding: 0;
  cursor: pointer; text-align: left;
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px;
}
.wish-link:hover { color: var(--pine-2); }
.wish-link:disabled { opacity: 0.6; cursor: progress; }
.wish-small { margin-top: 10px; max-width: 62ch; color: var(--dim); font-size: 13px; line-height: 1.55; }
.wish-msg { margin-top: 12px; font-size: 14.5px; }
.wish-msg.bad { color: #ff9aa2; }
.wish-pot { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
/* Over the picture the words carry the lede's shadow, and the field a
   darker ground than the page's translucent one, so it reads over snow. */
.hero .wish-count, .hero .wish-note, .hero .wish-small, .hero .wish-msg {
  text-shadow: 0 2px 14px rgba(11, 22, 48, 0.9);
}
.hero .wish-small { color: #c3cee2; }
.hero .wish-form input[type="email"] { background: rgba(11, 22, 48, 0.78) !important; }
@media (prefers-reduced-motion: reduce) {
  .wish-go, .wish-go:hover:not(:disabled) { transition: none; transform: skewX(var(--skew)); }
}

footer {
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  padding: 26px var(--gutter);
  color: var(--dim); font-size: 12.5px; letter-spacing: 0.06em;
  background: var(--haze);
  border-top: 1px solid var(--line);
}
footer .fmark { font-family: var(--display); color: var(--slate); letter-spacing: 0; }

/* ----------------------------------------------------------- the lightbox */

.lightbox {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(7, 12, 26, 0.97);
  display: grid; place-items: center; padding: 3vw;
}
.lightbox[hidden] { display: none; }
.lightbox img {
  max-width: 100%; max-height: 94vh; border: 1px solid var(--line);
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.55);
}
.lightbox .close {
  position: absolute; top: 14px; right: 20px;
  background: none; border: 0; color: var(--slate);
  font-size: 34px; line-height: 1; cursor: pointer; padding: 6px 12px;
  font-family: inherit;
}
.lightbox .close:hover { color: var(--pine); }

/* One shot at a time, but never a dead end: an arrow either side, the
   arrow keys, and a swipe on a phone (site.js builds these, so both pages
   get the same browser). */
.lightbox .nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 54px; height: 76px; padding: 0;
  background: rgba(20, 38, 74, 0.9);
  border: 1px solid var(--line); color: var(--slate);
  font-family: inherit; font-size: 30px; line-height: 1; cursor: pointer;
}
.lightbox .nav:hover { border-color: var(--pine); color: var(--pine); }
.lightbox .prev { left: 14px; }
.lightbox .next { right: 14px; }
.lightbox .count {
  position: absolute; bottom: 14px; left: 50%; transform: translateX(-50%);
  margin: 0; color: var(--dim);
  font-family: var(--cond); font-size: 13px; letter-spacing: 0.12em;
}
@media (max-width: 620px) {
  /* a phone has the swipe, so the arrows step out of the picture's way */
  .lightbox .nav { top: auto; bottom: 12px; transform: none; width: 50px; height: 44px; }
  .lightbox .prev { left: 18px; }
  .lightbox .next { right: 18px; }
  .lightbox .count { bottom: 24px; }
  .lightbox img { max-height: 84vh; }
}

/* ---------------------------------------------------- the vertical shots */

/* /vertical/, the 9:16 set for social. Unlisted on purpose: it is a shelf
   to take pictures off, not part of the teaser. */
.shelf { padding: clamp(40px, 6vw, 72px) var(--gutter) clamp(20px, 3vw, 34px); }
.shelf h1 {
  font-family: var(--display);
  margin: 0 0 18px; font-weight: 400; color: var(--pine);
  font-size: clamp(26px, 4vw, 44px); letter-spacing: 0;
  text-shadow: 3px 3px 0 var(--rust);
}
.shelf p { margin: 0 0 10px; max-width: 72ch; }
.shelf .small { color: var(--dim); font-size: 13px; }

.tall {
  padding: 0 var(--gutter) clamp(56px, 8vw, 104px);
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px;
}
.square {
  padding: 0 var(--gutter) clamp(56px, 8vw, 104px);
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px;
}
.shelf-head { padding: 0 var(--gutter) 14px; }
.shelf-head h2 {
  font-family: var(--cond);
  margin: 0 0 4px; font-weight: 700; color: var(--slate);
  font-size: 17px; letter-spacing: 0.1em; text-transform: uppercase;
}
.shelf-head .small { margin: 0; color: var(--dim); font-size: 12.5px; }

.tall figure, .square figure { margin: 0; }
.tall .tile, .square .tile { width: 100%; }
.tall .tile img { aspect-ratio: 9 / 16; }
.square .tile img { aspect-ratio: 1 / 1; }
.tall figcaption, .square figcaption {
  display: flex; justify-content: space-between; gap: 10px;
  padding: 7px 1px 0; color: var(--dim);
  font-family: var(--cond); font-size: 12.5px; letter-spacing: 0.06em;
}
@media (max-width: 1000px) {
  .tall, .square { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .tall, .square { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 420px) { .tall, .square { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------ the reveals */

.rise { opacity: 0; transform: translateY(16px); }
.rise.in { opacity: 1; transform: none; transition: opacity 0.6s ease, transform 0.6s ease; }
@media (prefers-reduced-motion: reduce) {
  .rise { opacity: 1; transform: none; }
  .rise.in { transition: none; }
}

/* ------------------------------------- the pages that paint from the same
   tokens (/dials, /replay, /feedback, /admin). They were written against a
   pale page and set white card and field faces by hand; on the dark page
   those turned into white slabs with white words on them. These bring
   them back without touching each page's own markup. */
input, textarea, select, button.btn, .box, .card, .panel, .row, .note {
  color-scheme: dark;
}
input:not([type="checkbox"]):not([type="radio"]), textarea, select {
  background: rgba(255, 255, 255, 0.07) !important;
  color: var(--slate) !important;
  border-color: var(--line) !important;
  font-family: var(--body);
}
input::placeholder, textarea::placeholder { color: var(--dim); }
