/* ==========================================================================
   Weissach Dev — site stylesheet
   Hand-written. No framework, no build step.
   Type: Fraunces (display), Inter (text), Inconsolata (data) — all OFL.
   Inconsolata is the logotype's own face, so the wordmark is live text, not art.
   ========================================================================== */

/* --- Fonts ---------------------------------------------------------------- */

@font-face {
  font-family: 'Fraunces';
  src: url('../fonts/fraunces-latin-var.woff2') format('woff2-variations');
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-latin-var.woff2') format('woff2-variations');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

/* The wordmark in the logo is set in Inconsolata. Shipping the real face means the
   lockup in the masthead is selectable text at the correct letterforms rather than
   a picture of them — and every spec label inherits the logotype. */
@font-face {
  font-family: 'Inconsolata';
  src: url('../fonts/inconsolata-latin-var.woff2') format('woff2-variations');
  font-weight: 200 900;
  font-style: normal;
  font-display: swap;
}

/* --- Tokens --------------------------------------------------------------- */

:root {
  color-scheme: dark;

  /* Surfaces — cold graphite, never pure black */
  --ink:        #07090b;
  --ink-raised: #0d1115;
  --ink-panel:  #11171c;

  /* Hairlines */
  --line:        rgba(255, 255, 255, 0.085);
  --line-strong: rgba(255, 255, 255, 0.17);

  /* Text */
  --text:   #edf1f3;
  --text-2: #94a1a9;
  /* Tertiary carries the ~10px mono legend, so it is pinned to the dimmest
     value that still clears 4.5:1 on the graphite field (4.90:1). The older
     #626f77 looked right and measured 3.86:1 — under AA at the size it is
     actually used. */
  --text-3: #76838b;

  /* Signal — brass, from the game's own UI and key art */
  --brass:    #d99b32;
  --brass-hi: #f2bb62;
  --brass-dim: rgba(217, 155, 50, 0.22);

  /* Supporting — the key art's sunset and water */
  --ember: #f2772b;
  --teal:  #37969c;
  --teal-deep: #0a2f35;

  /* Identity — the logomark's own navy. Only the mark and its plate use it. */
  --navy:      #192a3e;
  --navy-ink:  #1c2d40;
  --navy-pale: #e7ebee;

  /* The badge, as the master artwork draws it for this field: navy plate,
     ink that inherits the running text. The light field inverts both. */
  --plate:     var(--navy);
  --plate-ink: currentColor;

  /* Ink laid *on* brass — the button fill, the skip link, a selection. */
  --on-brass: #140d02;

  /* Fields that are not the page: the grid behind it, the stuck masthead,
     the ignition cover's unlit geometry. */
  --grid:  rgba(255, 255, 255, 0.016);
  --scrim: rgba(7, 9, 11, 0.82);
  --ghost: rgba(237, 241, 243, 0.13);

  /* Captions sitting on photography. Pinned: the art underneath is dark in
     both themes, so these must not follow the page. */
  --on-art:     #edf1f3;
  --on-art-2:   rgba(237, 241, 243, 0.72);
  --art-scrim:  rgba(7, 9, 11, 0.92);
  --art-scrim-2: rgba(7, 9, 11, 0.85);

  /* Type */
  --display: 'Fraunces', 'Iowan Old Style', Georgia, serif;
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --mono: 'Inconsolata', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;

  /* Metrics */
  --gutter: clamp(1.25rem, 5vw, 4.5rem);
  --measure: 68ch;
  --rail: 2.75rem;

  /* Motion — mechanical easing, not bouncy */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-sharp: cubic-bezier(0.65, 0.05, 0.36, 1);
}

/* --- The light field ------------------------------------------------------
   The same instrument read in daylight: a pale aluminium face rather than a
   lit panel. Nothing below this block knows which field it is on — only these
   tokens change — so the two themes cannot drift apart.

   The field colour is #e7ebee because that is the exact plate the logomark is
   drawn on in logomark-on-light.svg. The page becomes the logo's own paper.

   Brass cannot stay lit gold here: #d99b32 on pale reads at 2.3:1. It darkens
   to bronze, which holds the same signal role and clears 4.5:1 on every size
   it is used at. Set by boot.js before first paint; dark remains default. */

:root[data-theme='light'] {
  color-scheme: light;

  --ink:        #e7ebee;
  --ink-raised: #f3f6f7;
  --ink-panel:  #f8fafb;

  --line:        rgba(20, 29, 38, 0.14);
  --line-strong: rgba(20, 29, 38, 0.28);

  --text:   #141d26;
  --text-2: #4a565e;
  --text-3: #58646b;

  --brass:     #8f5d0d;
  --brass-hi:  #7a4f08;
  --brass-dim: rgba(143, 93, 13, 0.3);
  --on-brass:  #fff8ec;

  /* The badge inverts, exactly as the on-light master draws it. */
  --plate:     var(--navy-pale);
  --plate-ink: var(--navy-ink);

  --grid:  rgba(20, 29, 38, 0.042);
  --scrim: rgba(231, 235, 238, 0.84);
  --ghost: rgba(20, 29, 38, 0.11);
}

/* The sunset bleed has to work against paper, not against graphite: warmer,
   and carried by the ember rather than the brass. */
:root[data-theme='light'] .hero::after {
  background: radial-gradient(circle,
    rgba(242, 119, 43, 0.16) 0%,
    rgba(217, 155, 50, 0.1) 35%,
    transparent 68%);
}

:root[data-theme='light'] .note {
  background: linear-gradient(to right, rgba(143, 93, 13, 0.1), transparent 65%);
}

/* --- Reset ---------------------------------------------------------------- */

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

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

body {
  margin: 0;
  background: var(--ink);
  color: var(--text);
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.65;
  font-variant-ligatures: common-ligatures;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
button { font: inherit; color: inherit; }

::selection { background: var(--brass); color: var(--on-brass); }

/* Faint engineering grid, fixed behind everything */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image:
    linear-gradient(to right, var(--grid) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid) 1px, transparent 1px);
  background-size: 5rem 5rem;
  mask-image: radial-gradient(ellipse 120% 80% at 50% 0%, #000 20%, transparent 85%);
  -webkit-mask-image: radial-gradient(ellipse 120% 80% at 50% 0%, #000 20%, transparent 85%);
}

/* --- Typography ----------------------------------------------------------- */

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 600;
  font-variation-settings: 'SOFT' 0, 'WONK' 1, 'opsz' 110;
  letter-spacing: -0.022em;
  line-height: 1.04;
  margin: 0;
  text-wrap: balance;
}

.display {
  font-size: clamp(2.9rem, 9.5vw, 8.5rem);
  font-variation-settings: 'SOFT' 0, 'WONK' 1, 'opsz' 144;
  letter-spacing: -0.035em;
  line-height: 0.92;
}

.h2 { font-size: clamp(2rem, 4.6vw, 3.6rem); }
.h3 { font-size: clamp(1.35rem, 2.2vw, 1.85rem); letter-spacing: -0.015em; }

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

.lede {
  font-size: clamp(1.1rem, 1.9vw, 1.4rem);
  line-height: 1.55;
  color: var(--text-2);
  max-width: 46ch;
}

.measure { max-width: var(--measure); }

a { color: var(--brass-hi); text-decoration-thickness: 1px; text-underline-offset: 0.22em; }
a:hover { color: var(--text); }

/* Mono micro-labels — the instrument legend */
.label {
  font-family: var(--mono);
  font-size: 0.665rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-3);
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0 0 1.75rem;
}

.label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--line);
}

.label--plain::after { display: none; }
.label .idx { color: var(--brass); }

/* --- Layout --------------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: 82rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
  position: relative;
  z-index: 1;
}

section { position: relative; z-index: 1; }

.band {
  padding-block: clamp(4.5rem, 11vw, 9.5rem);
  border-top: 1px solid var(--line);
}

.band--flush { border-top: 0; }

/* --- Scroll rail (the brass thread) --------------------------------------- */

.rail {
  position: fixed;
  left: calc(var(--gutter) / 2);
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--line);
  z-index: 40;
  pointer-events: none;
}

.rail__fill {
  position: absolute;
  inset: 0 0 auto 0;
  height: 0;
  background: linear-gradient(to bottom, var(--brass-dim), var(--brass));
  will-change: height;
}

.rail__node {
  position: absolute;
  left: 50%;
  top: 0;
  width: 5px;
  height: 5px;
  margin-left: -2px;
  background: var(--brass-hi);
  border-radius: 50%;
  box-shadow: 0 0 0 3px rgba(217, 155, 50, 0.16), 0 0 14px 2px rgba(242, 187, 98, 0.5);
  will-change: top;
}

/* Mobile fallback: a top progress bar */
.topbar {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 0;
  background: var(--brass);
  z-index: 60;
  display: none;
}

@media (max-width: 920px) {
  .rail { display: none; }
  .topbar { display: block; }
}

/* --- Header --------------------------------------------------------------- */

.masthead {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  border-bottom: 1px solid transparent;
  transition: background-color 0.4s var(--ease), border-color 0.4s var(--ease),
              backdrop-filter 0.4s var(--ease);
}

.masthead.is-stuck {
  background: var(--scrim);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  border-bottom-color: var(--line);
}

.masthead__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  height: 4.5rem;
}

/* Nav and the field switch travel together on the right. The switch sits
   outside the <nav> landmark — it is a control, not a destination. */
.masthead__right {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.4vw, 2.1rem);
}

/* --- Field switch ---------------------------------------------------------
   A half-filled disc: the dark half shows the field you are on, and the
   quarter-turn on change reads as a switch being thrown rather than a state
   quietly swapping. Hidden without JS, where it could not do anything. */

.themer {
  display: none;
  place-items: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  flex: none;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease),
              transform 0.45s var(--ease);
}

.js .themer { display: inline-grid; }

.themer:hover { color: var(--brass-hi); border-color: var(--brass); }
.themer svg { width: 15px; height: 15px; }
.themer__ring { fill: none; stroke: currentColor; stroke-width: 1.3; }
.themer__half { fill: currentColor; }

:root[data-theme='light'] .themer { transform: rotate(180deg); }

/* --- Lockup ---------------------------------------------------------------
   The identity, assembled live: the hexagon badge as inline SVG, the wordmark
   as real text in Inconsolata — the face the logo was drawn in. Set at weight
   400 with no added tracking it is dimensionally identical to the outlined
   master in /assets/img/brand/, so this is the logo, not a copy of it.
   Monochrome by design; the badge inherits currentColor and the only colour
   that ever enters is the brass on the W, and only on hover. */

/* One knob: the lockup's font-size. The badge and the gap are expressed in em
   of it, so every instance keeps the same proportions as the master artwork.
   The badge rides taller than the word here than it does in the primary lockup
   — that one is drawn badge-dominant and will not sit in a 4.5rem bar. */
.lockup {
  display: inline-flex;
  align-items: center;
  gap: 0.42em;
  font-size: 1.02rem;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  line-height: 1;
}

.lockup__mark {
  display: block;
  height: 2.2em;
  width: auto;
  flex: none;
  overflow: visible;
}

.lockup__plate { fill: var(--plate); }
.lockup__ring,
.lockup__w { fill: var(--plate-ink); }

.lockup__w {
  transition: fill 0.4s var(--ease);
}

.lockup__word {
  font-family: var(--mono);
  font-size: 1em;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  /* Inconsolata's x-height sits low against the badge; nudge to the optical centre. */
  transform: translateY(0.035em);
}

.lockup:hover .lockup__w,
.lockup:focus-visible .lockup__w { fill: var(--brass-hi); }

.lockup:focus-visible {
  outline: 1px solid var(--brass);
  outline-offset: 6px;
}

.lockup--lg { font-size: 1.3rem; }

.nav {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.4vw, 2.1rem);
}

.nav a {
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-2);
  text-decoration: none;
  position: relative;
  padding-block: 0.35rem;
  transition: color 0.25s var(--ease);
}

.nav a::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--brass);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s var(--ease);
}

.nav a:hover,
.nav a[aria-current='page'] { color: var(--text); }
.nav a:hover::after,
.nav a[aria-current='page']::after { transform: scaleX(1); }

@media (max-width: 560px) {
  .nav { gap: 1rem; }
  .nav a { font-size: 0.62rem; letter-spacing: 0.12em; }
  .lockup { font-size: 0.88rem; }
  .lockup--lg { font-size: 1.1rem; }
  .masthead__right { gap: 0.9rem; }
  .themer { width: 1.75rem; height: 1.75rem; }
  .themer svg { width: 13px; height: 13px; }
}

/* Below this the wordmark and the nav start to collide, so the badge carries the
   identity alone. The word is hidden visually rather than removed, so the link
   keeps "weissach.dev" as its accessible name instead of becoming nameless. */
@media (max-width: 400px) {
  .masthead .lockup__word {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* --- Hero ----------------------------------------------------------------- */

.hero {
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding-block: 9rem 5rem;
  position: relative;
  overflow: hidden;
}

/* Warm light bleeding in from the lower right — the key art's sunset */
.hero::after {
  content: '';
  position: absolute;
  z-index: 0;
  right: -10%;
  bottom: -30%;
  width: 70vw;
  height: 70vw;
  background: radial-gradient(circle,
    rgba(242, 119, 43, 0.12) 0%,
    rgba(217, 155, 50, 0.06) 35%,
    transparent 68%);
  pointer-events: none;
}

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: center;
  width: 100%;
  position: relative;
  z-index: 1;
}

@media (max-width: 900px) {
  .hero { min-height: auto; padding-block: 8rem 3.5rem; }
  .hero__grid { grid-template-columns: 1fr; }
}

.hero__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.4rem;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 2rem;
}

.hero__meta .on { color: var(--brass); }

/* --- Buttons -------------------------------------------------------------- */

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  margin-top: 2.5rem;
}

.btn {
  --btn-fg: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.85rem 1.5rem;
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--btn-fg);
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: color 0.3s var(--ease), border-color 0.3s var(--ease);
}

/* Fill wipes in from the left on hover */
.btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--brass);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.42s var(--ease-sharp);
  z-index: 0;
}

.btn > * { position: relative; z-index: 1; }

.btn:hover { color: var(--on-brass); border-color: var(--brass); }
.btn:hover::before { transform: scaleX(1); }

.btn--primary {
  border-color: var(--brass);
  color: var(--brass-hi);
}

.btn .arrow { transition: transform 0.35s var(--ease); }
.btn:hover .arrow { transform: translateX(3px); }

.btn[aria-disabled='true'] {
  opacity: 0.45;
  pointer-events: none;
}

/* --- Panels with registration ticks --------------------------------------- */

.panel {
  position: relative;
  background: var(--ink-raised);
  border: 1px solid var(--line);
}

/* Corner registration marks, like a drawing frame.
   Inset rather than outset so a frame with overflow:hidden can't clip them. */
.ticks::before,
.ticks::after {
  content: '';
  position: absolute;
  z-index: 2;
  width: 13px;
  height: 13px;
  border: 1px solid var(--brass);
  opacity: 0.85;
  pointer-events: none;
}

.ticks::before {
  top: 0; left: 0;
  border-right: 0; border-bottom: 0;
}

.ticks::after {
  bottom: 0; right: 0;
  border-left: 0; border-top: 0;
}

/* --- Key art frame -------------------------------------------------------- */

.artframe {
  position: relative;
  overflow: hidden;
  background: var(--teal-deep);
  border: 1px solid var(--line);
}

.artframe img {
  width: 100%;
  display: block;
  transform: scale(1.03);
  transition: transform 1.2s var(--ease);
}

.artframe:hover img { transform: scale(1.065); }

.artframe__caption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 1.5rem;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 1rem;
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--on-art-2);
  background: linear-gradient(to top, var(--art-scrim), transparent);
  pointer-events: none;
}

/* --- Spec sheet ----------------------------------------------------------- */

.spec {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--mono);
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
}

.spec th,
.spec td {
  text-align: left;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--line);
  vertical-align: baseline;
}

.spec th {
  font-weight: 500;
  font-size: 0.66rem;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--text-3);
  width: 13rem;
}

.spec td { color: var(--text); }
.spec tr:last-child th,
.spec tr:last-child td { border-bottom: 0; }
.spec .hl { color: var(--brass-hi); }

@media (max-width: 560px) {
  .spec th { width: 9.5rem; font-size: 0.6rem; letter-spacing: 0.12em; }
  .spec td { font-size: 0.72rem; }
}

/* --- Figures (rolling counters) ------------------------------------------- */

.figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
  border-top: 1px solid var(--line);
}

.figure {
  padding: 1.75rem 1.5rem 1.75rem 0;
  border-bottom: 1px solid var(--line);
}

.figure__n {
  font-family: var(--display);
  font-size: clamp(2.4rem, 5vw, 3.6rem);
  font-weight: 600;
  font-variation-settings: 'SOFT' 0, 'WONK' 0, 'opsz' 144;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--brass-hi);
  letter-spacing: -0.03em;
}

.figure__l {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-top: 0.65rem;
}

/* --- Location / card grid ------------------------------------------------- */

.cards {
  display: grid;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}

.card {
  background: var(--ink);
  padding: clamp(1.5rem, 3vw, 2.25rem);
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  transition: background-color 0.4s var(--ease);
}

.card:hover { background: var(--ink-raised); }

.card__n {
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.2em;
  color: var(--brass);
}

.card h3 { font-size: 1.3rem; }
.card p { color: var(--text-2); font-size: 0.93rem; margin: 0; }

/* --- Screenshot strip ----------------------------------------------------- */

.shots {
  display: grid;
  gap: clamp(1rem, 2.5vw, 2rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr));
}

.shot {
  position: relative;
  border: 1px solid var(--line);
  overflow: hidden;
  background: var(--teal-deep);
}

.shot img { width: 100%; }

/* Lead shot runs the full width — an establishing frame before the pairs.
   Also stops an odd-numbered gallery from leaving an orphan on the last row. */
@media (min-width: 60rem) {
  .shots--lead > :first-child { grid-column: 1 / -1; }
}

.shot figcaption {
  position: absolute;
  left: 0; bottom: 0;
  padding: 1.75rem 1.25rem 1rem;
  width: 100%;
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--on-art);
  background: linear-gradient(to top, var(--art-scrim-2), transparent);
}

/* --- Prose (legal / support pages) ---------------------------------------- */

.prose {
  max-width: var(--measure);
  color: var(--text-2);
  font-size: 1.02rem;
}

.prose h2 {
  font-size: clamp(1.4rem, 2.6vw, 1.9rem);
  color: var(--text);
  margin: 3.25rem 0 1rem;
}

.prose h2:first-child { margin-top: 0; }

.prose h3 {
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brass);
  margin: 2.25rem 0 0.75rem;
}

.prose ul { padding-left: 1.1rem; margin: 0 0 1.15em; }
.prose li { margin-bottom: 0.5rem; }
.prose li::marker { color: var(--brass); }
.prose strong { color: var(--text); font-weight: 600; }

.prose code {
  font-family: var(--mono);
  font-size: 0.85em;
  background: var(--ink-panel);
  border: 1px solid var(--line);
  padding: 0.1em 0.4em;
  color: var(--text);
}

/* Callout — the one thing we most want read */
.note {
  border-left: 2px solid var(--brass);
  background: linear-gradient(to right, rgba(217, 155, 50, 0.07), transparent 65%);
  padding: 1.25rem 1.5rem;
  margin: 2rem 0;
  color: var(--text);
}

/* --- FAQ ------------------------------------------------------------------ */

.faq { border-top: 1px solid var(--line); max-width: var(--measure); }

.faq details {
  border-bottom: 1px solid var(--line);
}

.faq summary {
  list-style: none;
  cursor: pointer;
  padding: 1.35rem 2.5rem 1.35rem 0;
  position: relative;
  font-weight: 500;
  color: var(--text);
  transition: color 0.25s var(--ease);
}

.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--brass-hi); }

.faq summary::after {
  content: '';
  position: absolute;
  right: 0.35rem;
  top: 50%;
  width: 9px;
  height: 9px;
  margin-top: -6px;
  border-right: 1px solid var(--brass);
  border-bottom: 1px solid var(--brass);
  transform: rotate(45deg);
  transition: transform 0.3s var(--ease);
}

.faq details[open] summary::after { transform: rotate(-135deg); margin-top: -2px; }

.faq .answer {
  padding: 0 0 1.5rem;
  color: var(--text-2);
  max-width: 62ch;
}

/* --- Download list (press) ------------------------------------------------ */

.dl { border-top: 1px solid var(--line); }

.dl a {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.1rem 0;
  border-bottom: 1px solid var(--line);
  text-decoration: none;
  color: var(--text);
  transition: color 0.25s var(--ease), padding-left 0.3s var(--ease);
}

.dl a:hover { color: var(--brass-hi); padding-left: 0.6rem; }

.dl .meta {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-3);
  white-space: nowrap;
}

/* --- Brand plates (press) -------------------------------------------------
   Each variant shown on the field it was drawn for, so a journalist can see at
   a glance which file to take rather than reading the filename and guessing. */

/* Two columns, always: the four plates are two pairs, and an auto-fit grid
   leaves a hole in the sheet at three across. */
.brandset {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  margin-bottom: clamp(2.5rem, 5vw, 3.5rem);
}

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

.brandplate {
  position: relative;
  display: grid;
  place-items: center;
  padding: clamp(2.25rem, 5vw, 3.5rem);
  min-height: 11rem;
}

.brandplate--dark  { background: var(--navy); }
.brandplate--paper { background: var(--navy-pale); }

.brandplate img { width: min(100%, 15rem); }
.brandplate--mark img { width: min(100%, 5.5rem); }

.brandplate__tag {
  position: absolute;
  left: 1rem;
  bottom: 0.75rem;
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.brandplate--dark  .brandplate__tag { color: rgba(255, 255, 255, 0.42); }
.brandplate--paper .brandplate__tag { color: rgba(28, 45, 64, 0.48); }

/* --- Footer --------------------------------------------------------------- */

.foot {
  border-top: 1px solid var(--line);
  padding-block: 4rem 3rem;
  margin-top: 2rem;
}

.foot__grid {
  display: flex;
  flex-wrap: wrap;
  gap: 2.5rem;
  justify-content: space-between;
  align-items: flex-start;
}

.foot__links {
  display: flex;
  flex-wrap: wrap;
  gap: 1.75rem;
}

/* Footer links, but not the lockup — it is a logo that happens to sit in the
   footer, and these rules would shrink it, dim it and uppercase it. */
.foot a:not(.lockup) {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-2);
  text-decoration: none;
  transition: color 0.25s var(--ease);
}

.foot a:not(.lockup):hover { color: var(--brass-hi); }

.foot__fine {
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.1em;
  color: var(--text-3);
  margin-top: 2.5rem;
  line-height: 1.9;
}

/* --- Reveal on scroll -----------------------------------------------------
   Two separate guarantees, because they answer two different questions.

   `.js` (set by boot.js) proves scripting is enabled, so with JS off nothing
   is ever hidden. But it does NOT prove site.js arrived — a dropped request
   would leave the page hidden forever. So the hidden state also carries a
   failsafe that reveals it on its own, and `.js-live` (set by site.js as its
   first act) cancels that failsafe once the real observer is in charge. */

.js .rv {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.9s var(--ease), transform 0.9s var(--ease);
  animation: rv-failsafe 0.01s linear 2.5s forwards;
}

.js .rv.is-in { opacity: 1; transform: none; }

/* Stagger children */
.js .rv-stagger > * {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.75s var(--ease), transform 0.75s var(--ease);
  animation: rv-failsafe 0.01s linear 2.5s forwards;
}

.js .rv-stagger.is-in > * { opacity: 1; transform: none; }

/* site.js is running, so the scroll observer owns the reveal from here. */
.js-live .rv,
.js-live .rv-stagger > * { animation: none; }

@keyframes rv-failsafe {
  to { opacity: 1; transform: none; }
}
.rv-stagger.is-in > *:nth-child(1) { transition-delay: 0.00s; }
.rv-stagger.is-in > *:nth-child(2) { transition-delay: 0.07s; }
.rv-stagger.is-in > *:nth-child(3) { transition-delay: 0.14s; }
.rv-stagger.is-in > *:nth-child(4) { transition-delay: 0.21s; }
.rv-stagger.is-in > *:nth-child(5) { transition-delay: 0.28s; }
.rv-stagger.is-in > *:nth-child(6) { transition-delay: 0.35s; }

/* --- Ignition sweep (first load only) ------------------------------------- */

.ignition {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--ink);
  /* Hidden by default: an opaque cover must never outlive the script that
     clears it. Without JS there is nothing to reveal it, and nothing to hide. */
  display: none;
  place-items: center;
  transition: opacity 0.5s var(--ease), visibility 0.5s;
}

/* Shown only once boot.js has proved scripting is alive. The failsafe retires
   the cover on its own if site.js never loads, so a dropped request costs a
   visitor the sweep, not the whole site. */
.js .ignition {
  display: grid;
  /* Long enough to clear the full sweep (900ms) plus the mark's flip and fade,
     so the failsafe only ever fires when the script really is gone. */
  animation: ignition-failsafe 0.01s linear 3.2s forwards;
}

@keyframes ignition-failsafe {
  to { opacity: 0; visibility: hidden; }
}

.ignition.is-done { opacity: 0; visibility: hidden; }

.ignition__stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.4rem;
}

/* The needle does not climb next to the mark, it fills it: the badge is the
   gauge. Ghost geometry underneath, brass wipe rising through it, and a flip
   to white at 100 before the cover lifts. */
.ignition__mark {
  width: clamp(3rem, 7vw, 4.25rem);
  height: auto;
}

.ignition__ghost { fill: var(--ghost); }
.ignition__lit   { fill: var(--brass); transition: fill 0.25s var(--ease); }
.ignition.is-lit .ignition__lit { fill: var(--text); }

.ignition__bar {
  width: min(22rem, 60vw);
  height: 1px;
  background: var(--line);
  position: relative;
}

.ignition__bar i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background: var(--brass);
  display: block;
}

.ignition__n {
  position: absolute;
  top: 1.1rem;
  right: 0;
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.2em;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}

/* --- Reticle cursor (fine pointers only) ---------------------------------- */

.reticle {
  position: fixed;
  top: 0; left: 0;
  width: 26px;
  height: 26px;
  margin: -13px 0 0 -13px;
  z-index: 90;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s var(--ease), width 0.3s var(--ease),
              height 0.3s var(--ease), margin 0.3s var(--ease);
  will-change: transform;
}

.reticle::before,
.reticle::after {
  content: '';
  position: absolute;
  background: var(--brass);
}

/* Two opposing corner brackets */
.reticle::before {
  top: 0; left: 0;
  width: 7px; height: 1px;
  box-shadow: 0 0 0 0 transparent;
}

.reticle::after {
  bottom: 0; right: 0;
  width: 7px; height: 1px;
}

.reticle i {
  position: absolute;
  inset: 0;
}

.reticle i::before,
.reticle i::after {
  content: '';
  position: absolute;
  background: var(--brass);
  width: 1px;
  height: 7px;
}

.reticle i::before { top: 0; left: 0; }
.reticle i::after { bottom: 0; right: 0; }

.reticle.is-on { opacity: 1; }

.reticle.is-hot {
  width: 42px;
  height: 42px;
  margin: -21px 0 0 -21px;
}

@media (hover: none), (pointer: coarse) {
  .reticle { display: none; }
}

/* --- Accessibility -------------------------------------------------------- */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--brass);
  color: var(--on-brass);
  padding: 0.75rem 1.25rem;
  z-index: 200;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.skip:focus { left: 0; }

:focus-visible {
  outline: 2px solid var(--brass-hi);
  outline-offset: 3px;
}

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

/* --- Reduced motion ------------------------------------------------------- */

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

  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  .js .rv, .js .rv-stagger > * { opacity: 1; transform: none; }
  .reticle { display: none; }
  /* Must out-specify `.js .ignition` above, or reduced-motion users get the
     cover anyway. */
  .ignition, .js .ignition { display: none; animation: none; }
  .artframe img { transform: none; }
}
