/* ==========================================================================
   Seven17 Auto & Aero Spa — THE WALL (light ground)
   Source world: a stacked archive of labelled units, pulled out and opened.
   Ground is light because the client's vehicles are black and silver: they
   merge into a dark ground and separate cleanly on a light one.
   See DESIGN.md.

   Rules that are easy to break and expensive to fix:
   1. Every colour derives from the five :root tokens. No one-off hex.
   2. TWO REDS, AND THE SIZE DECIDES.
      --accent (#ED1C24) is the brand red: rules, focus rings, small marks,
      and large display characters. It is 3.1:1 on this ground — fine for
      non-text and large text, and it FAILS AA at label or body size.
      --accent-ink (#B3141B) is the text-safe variant, 4.9:1 at the binding
      point. Any red carrying text at label or body size uses it.
      Never darken --accent to fix a contrast failure — reach for --accent-ink.
      Neither red ever fills a region or becomes a background.
   3. Boxes are keylines and fills — never shadows, never glass, never glow.
   ========================================================================== */

:root {
  /* ---- palette ------------------------------------------------------- */
  --ground:  #E4E4E0;   /* the field — a material grey, not white */
  --surface: #F4F4F1;   /* plates and open units; the lighter plane */
  --display: #14161A;   /* ink */
  --quiet:   #4E545C;   /* 5.4:1 at the ground's darkest point */
  --accent:     #ED1C24;   /* brand red — rules, focus, small marks, large display */
  --accent-ink: #B3141B;   /* text-safe red — ANY red at label or body size */

  --ink-rgb:    20 22 26;
  --accent-rgb: 237 28 36;

  --keyline:      rgb(var(--ink-rgb) / 0.22);
  --keyline-soft: rgb(var(--ink-rgb) / 0.10);

  /* ---- type ---------------------------------------------------------- */
  --face-display: "Big Shoulders Display", "Arial Narrow", sans-serif;
  --face-mono:    "Spline Sans Mono", ui-monospace, monospace;   /* unused, kept for a future narrow/numeric need — see DESIGN.md */
  /* Body/nav/label voice. Real Inter if installed; otherwise the platform's
     own UI grotesk (San Francisco / Segoe UI / Roboto), so the pairing still
     reads as condensed-display-over-clean-sans with zero added network
     requests. See DESIGN.md, Type. */
  --face-body: "Inter", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --t-hero:    clamp(2.25rem, 6vw, 6rem);
  --t-unit:    clamp(1.75rem, 4.2vw, 3.25rem);
  --t-section: clamp(1.75rem, 4vw, 2.75rem);
  --t-body:    0.9375rem;
  --t-label:   0.75rem;
  --t-micro:   0.6875rem;

  /* ---- rhythm -------------------------------------------------------- */
  --s1: 0.375rem;
  --s2: 0.75rem;
  --s3: 1.25rem;
  --s4: 2rem;
  --s5: 3rem;
  --s6: 4.5rem;

  --gutter: clamp(1rem, 3vw, 2.5rem);
  --column: 96rem;

  --dur-1: 160ms;
  --dur-2: 340ms;
  --dur-3: 700ms;
  --dur-4: 6s;   /* ambient drift only — the hero-card photo zoom, never a UI response */
  --ease:  cubic-bezier(0.16, 1, 0.3, 1);
}

@font-face {
  font-family: "Big Shoulders Display";
  src: url("../fonts/big-shoulders-display.woff2") format("woff2-variations");
  font-weight: 300 900;
  font-display: swap;
}
@font-face {
  font-family: "Spline Sans Mono";
  src: url("../fonts/spline-sans-mono.woff2") format("woff2-variations");
  font-weight: 300 700;
  font-display: swap;
}

/* ==========================================================================
   Ground
   ========================================================================== */

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

html { background: var(--ground); -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--display);
  font-family: var(--face-body);
  font-size: var(--t-body);
  font-weight: 400;
  line-height: 1.55;
  overflow-x: hidden;
}

/* Material, retuned for light: a soft pool of hangar light from the upper
   left, and weight settling into the lower right. Low amplitude — it should
   read as a surface, not as a gradient. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -2;
  background:
    radial-gradient(75% 60% at 20% 0%, rgb(255 255 255 / 0.75) 0%, transparent 62%),
    radial-gradient(85% 70% at 92% 100%, rgb(var(--ink-rgb) / 0.07) 0%, transparent 60%);
}

/* Metallic-fleck paint texture, same --ground colour family, no gradient —
   the DESIGN.md-compliant reading of "car paint": under flat/diffuse light
   (no direct specular streak) what paint actually shows is fine granular
   fleck, not a light sweep. Desaturated so it's tonal variation within the
   ground colour, not colour noise; the alpha contrast boost (feFuncA) turns
   smooth turbulence into distinct light/dark specks instead of soft grain,
   which is what reads as "fleck" rather than "fog" at normal viewing
   distance. Behind all content. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.15;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='3' intercept='-0.9'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ==========================================================================
   Primitives
   ========================================================================== */

h1, h2, h3 { margin: 0; font-weight: 800; }

.display {
  font-family: var(--face-display);
  font-weight: 800;
  line-height: 0.84;
  letter-spacing: 0.005em;
  text-transform: uppercase;
  color: var(--display);
}

p { margin: 0; }
a { color: inherit; }

.label {
  font-family: var(--face-body);
  font-weight: 600;
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--quiet);
}

/* the one place a hairline is allowed to carry the accent */
.rule { flex: 1; height: 1px; background: var(--keyline-soft); }

.shell { max-width: var(--column); margin: 0 auto; padding-inline: var(--gutter); }

.skip-link {
  position: absolute;
  left: var(--gutter);
  top: -4rem;
  z-index: 30;
  padding: var(--s2) var(--s3);
  background: var(--display);
  color: var(--ground);
  font-size: var(--t-label);
  text-decoration: none;
  transition: top var(--dur-1) var(--ease);
}
.skip-link:focus { top: var(--s2); }

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

/* --- buttons ---------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  font-family: var(--face-body);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid var(--display);
  transition: background var(--dur-1) var(--ease),
              color var(--dur-1) var(--ease),
              border-color var(--dur-1) var(--ease),
              transform var(--dur-1) var(--ease);
}
.btn:hover { transform: translateY(-3px); }
.btn:active { transform: translateY(-1px) scale(0.97); }
.btn--primary { background: var(--display); color: var(--ground); }
.btn--primary:hover { border-color: var(--accent); }
.btn--ghost { background: transparent; color: var(--display); }
.btn--ghost:hover { border-color: var(--accent); color: var(--accent-ink); }
.btn__arrow { width: 1.5rem; height: 0.5rem; flex: none; }

/* ==========================================================================
   Intro overlay
   One-time full-screen video intro, played before the homepage. Hidden by
   default (opacity 0 + visibility hidden) so a page with JS disabled, or
   where the play-once/reduced-motion checks in intro.js bail out, never
   shows a stuck overlay or blocks interaction with the real page — visibility
   hidden also drops it out of hit-testing and the tab order automatically.
   The video's own background (see the ffmpeg build) is filled with this
   same --ground colour so the video-to-header handoff move in intro.js can
   shrink/fade the whole element without a visible background seam. */

.intro-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--ground);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-2) var(--ease);
}
.intro-overlay.is-visible { opacity: 1; visibility: visible; }
.intro-overlay.is-leaving { opacity: 0; }
/* Slightly slower than the default leave, to match the video's own
   transform duration for the logo-to-header handoff (see intro.js) — the
   parent's fade is what actually hides the video's opaque background
   during that move, since the video itself only transforms, it doesn't
   fade on its own. */
.intro-overlay.is-continuity { transition: opacity 450ms var(--ease); }

.intro-overlay__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform-origin: 50% 50%;
}
.intro-overlay__video.is-moving { transition: transform 450ms var(--ease); }

.intro-overlay__skip {
  position: absolute;
  right: var(--gutter);
  bottom: var(--gutter);
  padding: var(--s2);
  background: none;
  border: 0;
  color: var(--quiet);
  font: inherit;
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-2) var(--ease), color var(--dur-1) var(--ease);
}
.intro-overlay__skip.is-visible { opacity: 1; pointer-events: auto; }
.intro-overlay__skip:hover,
.intro-overlay__skip:focus-visible { color: var(--accent-ink); }

/* ==========================================================================
   Masthead
   ========================================================================== */

.masthead {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding-block: var(--s3);
  border-bottom: 1px solid var(--keyline);
  position: relative;
  z-index: 20;
  background: var(--ground);
}

.wordmark { display: block; position: relative; width: fit-content; line-height: 0; flex: none; }
.wordmark picture { display: block; }
.wordmark__logo { display: block; width: clamp(8.5rem, 12.5vw, 11.5rem); height: auto; }

/* The logo is untouched except for one thing: "17" pulses between darker
   and lighter. This is a duplicate of the logo's own pixels, masked down
   to just the "17" glyphs (right 30% — measured off the file itself:
   "SEVEN" ends at 70.6% width, "17" begins at 71.1%), sitting exactly on
   top of the real artwork and animating brightness/saturation. Nothing
   else about the wordmark changes — no sweep, no blur, no halo. */
.wordmark__glow {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: url("../img/logo-wordmark-dark.png");
  background-size: 100% 100%;
  background-repeat: no-repeat;
  -webkit-mask-image: url("../img/logo-wordmark-dark.png");
  mask-image: url("../img/logo-wordmark-dark.png");
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  clip-path: inset(0 0 0 70%);   /* right 30% — "17" only */
  animation: wordmark-pulse 2.4s ease-in-out infinite;
}

@keyframes wordmark-pulse {
  0%, 100% { filter: brightness(0.78) saturate(0.85); }
  50%      { filter: brightness(1.3) saturate(1.25); }
}

@media (prefers-reduced-motion: reduce) {
  .wordmark__glow { animation: none; }
}

.masthead__nav { display: flex; align-items: center; gap: var(--s4); flex: none; }
.masthead__nav a:not(.btn) {
  position: relative;
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--quiet);
  transition: color var(--dur-1) var(--ease);
}
.masthead__nav a:not(.btn)::after {
  content: "";
  position: absolute;
  left: 0;
  right: 100%;
  bottom: -0.375rem;
  height: 1px;
  background: var(--accent);
  transition: right var(--dur-2) var(--ease);
}
.masthead__nav a:not(.btn):hover,
.masthead__nav a:not(.btn):focus-visible { color: var(--accent-ink); }
.masthead__nav a:not(.btn):hover::after,
.masthead__nav a:not(.btn):focus-visible::after { right: 0; }

.nav-toggle {
  display: none;
  position: relative;
  z-index: 30;
  align-items: center;
  gap: var(--s2);
  min-height: 44px;
  padding: var(--s2) 0;
  margin-inline-start: auto;
  background: none;
  border: 0;
  color: var(--quiet);
  font: inherit;
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
}
.nav-toggle__glyph { stroke: currentColor; stroke-width: 1.5; }

/* ==========================================================================
   Hero
   ========================================================================== */

.hero {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: var(--s5);
  align-items: end;
  padding-block: clamp(var(--s5), 6vw, var(--s6)) var(--s6);
  border-bottom: 1px solid var(--keyline);
}

.hero__claim { font-size: var(--t-hero); }
/* The break is authored, not left to the browser: each line holds as one
   unit so the block keeps its shape at every width. */
.hero__claim span { display: block; white-space: nowrap; }
/* the accent as a single mark, not a region — the site-wide idiom for a
   red full stop, not scoped to the hero. (.close__title's "done." already
   used this class before this rule covered anything outside .hero__claim;
   generalizing it here is what actually turns that on.) */
.mark {
  display: inline-block;
  font-style: normal;
  color: var(--accent);
  animation: markPulse 2.4s var(--ease) infinite;
}
@keyframes markPulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.2); }
}

.hero__sub { margin-top: var(--s4); max-width: 44ch; color: var(--quiet); }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s4); }

/* ==========================================================================
   HUD panel list — category selector
   Six collapsed rows stacked beside the hero claim; one grows taller (photo
   revealed) on hover/focus/tap. Rows are a normal horizontal line at every
   state — title left, tag+arrow right, never rotated — so it reads in a
   glance instead of needing to be puzzled out. Photo-reveal reuses the same
   --tile-photo + dark-overlay + Ken Burns idiom the old hero stack carried.
   See the HTML comment above .hud in index.html for the full mechanics
   rundown.
   ========================================================================== */

.hud {
  display: flex;
  flex-direction: column;
  height: clamp(24rem, 40vw, 32rem);
  border: 1px solid var(--keyline);
}

.hud__panel {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  border: 0;
  border-block-end: 1px solid var(--keyline);
  background: var(--surface);
  font: inherit;
  text-align: start;
  cursor: pointer;
  transition: flex var(--dur-3) cubic-bezier(0.16, 1, 0.3, 1);
}
.hud__panel:last-child { border-block-end: 0; }

.hud__panel--aircraft    { --tile-photo: url("../img/hud/aircraft.jpg"); }
.hud__panel--exotic      { --tile-photo: url("../img/hud/exotic.jpg"); }
.hud__panel--dailydriven { --tile-photo: url("../img/hud/dailydriven.jpg"); }
.hud__panel--offroad     { --tile-photo: url("../img/hud/offroad.jpg"); }
.hud__panel--boat        { --tile-photo: url("../img/hud/boat.jpg"); }
.hud__panel--motorcycle  { --tile-photo: url("../img/hud/motorcycle.jpg"); }

.hud__panel::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgb(var(--ink-rgb) / 0.55), rgb(var(--ink-rgb) / 0.55)),
    var(--tile-photo, none);
  background-size: cover;
  background-position: center;
  opacity: 0;
  transform: scale(1);
  will-change: transform;
  transition: opacity var(--dur-2) var(--ease), transform var(--dur-4) ease-out;
}
.hud__panel:hover, .hud__panel:focus-visible, .hud__panel.is-pinned { flex: 4; }
.hud__panel:hover::before, .hud__panel:focus-visible::before, .hud__panel.is-pinned::before {
  opacity: 1;
  transform: scale(1.12);
}
/* the other five compress once one panel is active — reads as a HUD taking
   a selection, not just one row growing. Falls back gracefully without
   :has() support: the active row still expands, siblings just don't
   compress in tandem. */
.hud:has(.hud__panel:hover) .hud__panel:not(:hover),
.hud:has(.hud__panel:focus-visible) .hud__panel:not(:focus-visible),
.hud:has(.hud__panel.is-pinned) .hud__panel:not(.is-pinned) { flex: 0.5; }

.hud__title, .hud__tag {
  position: relative;
  z-index: 1;
}

.hud__title {
  font-family: var(--face-display);
  font-size: clamp(1.1rem, 2vw, 1.75rem);
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
  color: var(--display);
  transition: color var(--dur-2) var(--ease);
}
.hud__panel:hover .hud__title, .hud__panel:focus-visible .hud__title, .hud__panel.is-pinned .hud__title {
  color: var(--surface);
}

.hud__tag {
  margin-inline-start: auto;
  font-family: var(--face-body);
  font-weight: 600;
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-ink);
  display: inline-flex;
  align-items: center;
  flex: none;
  transition: color var(--dur-2) var(--ease);
}
.hud__tag::before {
  content: "";
  width: 0.4rem;
  height: 0.4rem;
  margin-inline-end: var(--s2);
  background: var(--accent);
  flex: none;
}
.hud__panel:hover .hud__tag, .hud__panel:focus-visible .hud__tag, .hud__panel.is-pinned .hud__tag { color: var(--surface); }

/* HUD flourish: corner brackets + the pulsing dot, both accent-only and
   only ever shown on the active row. The dot reuses .mark's existing
   markPulse animation rather than inventing a second pulse. */
.hud__bracket {
  position: absolute;
  z-index: 2;
  width: 1rem;
  height: 1rem;
  border-color: var(--accent);
  border-style: solid;
  border-width: 0;
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease);
  pointer-events: none;
}
.hud__bracket--tl { top: var(--s3); left: var(--s3); border-top-width: 2px; border-inline-start-width: 2px; }
.hud__bracket--tr { top: var(--s3); right: var(--s3); border-top-width: 2px; border-inline-end-width: 2px; }
.hud__bracket--bl { bottom: var(--s3); left: var(--s3); border-bottom-width: 2px; border-inline-start-width: 2px; }
.hud__bracket--br { bottom: var(--s3); right: var(--s3); border-bottom-width: 2px; border-inline-end-width: 2px; }

.hud__dot {
  position: absolute;
  top: calc(var(--s3) + 0.875rem);
  right: calc(var(--s3) + 0.875rem);
  z-index: 2;
  width: 0.5rem;
  height: 0.5rem;
  background: var(--accent);
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease);
}
.hud__panel:hover .hud__bracket, .hud__panel:focus-visible .hud__bracket, .hud__panel.is-pinned .hud__bracket,
.hud__panel:hover .hud__dot, .hud__panel:focus-visible .hud__dot, .hud__panel.is-pinned .hud__dot {
  opacity: 1;
}
.hud__panel:hover .hud__dot, .hud__panel:focus-visible .hud__dot, .hud__panel.is-pinned .hud__dot {
  animation: markPulse 2.4s var(--ease) infinite;
}

/* ==========================================================================
   Selected work — the unit rows
   ========================================================================== */

.work__head {
  display: flex;
  align-items: baseline;
  gap: var(--s4);
  padding-block: var(--s5) var(--s4);
}
.work__title { font-size: var(--t-section); }

/* --- drag gallery ------------------------------------------------------- */

.gallery { padding-bottom: var(--s5); }

.gallery__filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-bottom: var(--s4);
}
.gallery__filter {
  padding: var(--s2) var(--s3);
  font-family: var(--face-body);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--quiet);
  background: transparent;
  border: 1px solid var(--keyline);
  cursor: pointer;
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.gallery__filter:hover { border-color: var(--accent); color: var(--accent-ink); }
.gallery__filter.is-active { background: var(--display); color: var(--ground); border-color: var(--display); }

.gallery__viewport { position: relative; }

.gallery-track {
  display: flex;
  gap: 1.5rem;
  padding-block: var(--s2);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  cursor: grab;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.gallery-track::-webkit-scrollbar { display: none; }
.gallery-track.is-dragging { cursor: grabbing; scroll-snap-type: none; }
.gallery-track.is-settling { scroll-snap-type: none; }
.gallery-track:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

.gallery-card {
  position: relative;
  flex: 0 0 21.25rem;   /* 340px */
  height: 27.5rem;      /* 440px */
  overflow: hidden;
  border: 1px solid var(--keyline);
  background: var(--surface);
  scroll-snap-align: start;
  transition: border-color var(--dur-2) var(--ease);
}
.gallery-card[data-hidden="true"] { display: none; }
.gallery-card:hover,
.gallery-card:focus-within { border-color: var(--accent); }

/* Full colour always — these are finished paint and metal, the whole point
   is to show it. The "quiet -> present" hover payoff other raster assets
   on this site use (see .colophon__credit-logo) comes from a slight
   brightness/contrast dip at rest instead of desaturating the work itself. */
.gallery-card img,
.gallery-card video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.93) contrast(0.97);
  transform: scale(1);
  transition: filter var(--dur-3) ease, transform var(--dur-3) ease;
  -webkit-user-drag: none;
  user-select: none;
}
.gallery-card:hover img,
.gallery-card:focus-within img,
.gallery-card:hover video,
.gallery-card:focus-within video {
  filter: brightness(1) contrast(1);
  transform: scale(1.05);
}

.gallery-card__tag {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  padding: var(--s3);
  color: var(--surface);
  background: linear-gradient(to top, rgb(var(--ink-rgb) / 0.7), transparent);
}
.gallery-card__tag::before {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  margin-inline-end: var(--s2);
  background: var(--accent);
  flex: none;
}

.gallery__nav {
  position: absolute;
  top: 50%;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid var(--keyline);
  background: var(--surface);
  color: var(--display);
  cursor: pointer;
  transform: translateY(-50%);
  transition: opacity var(--dur-2) var(--ease), border-color var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.gallery__nav:hover { border-color: var(--accent); color: var(--accent-ink); }
.gallery__nav[data-hidden="true"] { opacity: 0; pointer-events: none; }
.gallery__nav--prev { left: 0.5rem; }
.gallery__nav--next { right: 0.5rem; }
.gallery__nav-arrow { width: 1.25rem; height: 0.45rem; flex: none; }
.gallery__nav--prev .gallery__nav-arrow { transform: rotate(180deg); }

.wall__lead { margin-block: var(--s4); }

.wall { border-top: 1px solid var(--keyline); }
.unit { border-bottom: 1px solid var(--keyline); }

.unit__end {
  display: flex;
  align-items: baseline;
  gap: var(--s4);
  padding: var(--s4) var(--s3);
  border-inline-start: 2px solid transparent;
  cursor: pointer;
  list-style: none;
  transition: background var(--dur-2) var(--ease),
              padding-inline-start var(--dur-2) var(--ease),
              border-color var(--dur-2) var(--ease);
}
.unit__end::-webkit-details-marker { display: none; }
.unit__end:hover,
.unit[open] > .unit__end {
  background: var(--surface);
  padding-inline-start: var(--s5);   /* the unit slides proud of the stack */
  border-inline-start-color: var(--accent);   /* the elevation cue: a border darkens, never a shadow */
}
.unit__end:hover .unit__name,
.unit[open] > .unit__end .unit__name { color: var(--accent); }

.unit__name {
  font-family: var(--face-display);
  font-size: var(--t-unit);
  text-transform: uppercase;
  line-height: 0.9;
  transition: color var(--dur-2) var(--ease);
}
.unit__meta { margin-left: auto; display: flex; align-items: baseline; gap: var(--s4); }
.unit__state { color: var(--accent-ink); display: inline-flex; align-items: center; }
.unit__state::before {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  margin-inline-end: var(--s2);
  background: var(--accent);
  flex: none;
}

.unit__body {
  padding: 0 var(--s3) var(--s5) var(--s5);
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: var(--s4);
  align-items: start;
}
.unit__plate { border: 1px solid var(--keyline-soft); background: var(--surface); }
.unit__plate img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; }

/* honest empty: a plate that states what is missing */
.unit__pending {
  aspect-ratio: 3 / 2;
  display: grid;
  place-items: center;
  text-align: center;
  padding: var(--s4);
  color: var(--quiet);
  background: repeating-linear-gradient(
    -45deg,
    transparent 0 10px,
    rgb(var(--ink-rgb) / 0.035) 10px 20px);
}

.unit__note { color: var(--quiet); }
.unit__link {
  display: inline-block;
  margin-top: var(--s3);
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  padding-bottom: 3px;
  border-bottom: 1px solid var(--accent);
  transition: color var(--dur-1) var(--ease);
}
.unit__link:hover { color: var(--accent-ink); }

/* ==========================================================================
   Close, colophon
   ========================================================================== */

.close {
  padding-block: var(--s6);
  border-top: 1px solid var(--keyline);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s5);
  align-items: start;
}
/* 52ch cap — without it this column stretches to the full grid track
   (wider than the text actually is), so centering .close__mark with
   margin:auto centers it under empty track space to the right of the
   text instead of under the text itself. */
.close__intro { display: grid; gap: var(--s3); align-content: start; max-width: 52ch; }
.close__title { font-size: clamp(2.5rem, 6.5vw, 5rem); max-width: 18ch; }
/* Decorative — sits in the text column next to the form, centered under
   the title/note/price above it, filling the space that column leaves
   next to the taller form beside it. Not informational (the wordmark up
   top already carries the brand), so alt="" and hidden from AT.
   height:auto (not a fixed square) since the source crop isn't
   guaranteed to stay 1:1. */
.close__mark {
  width: clamp(14rem, 30vw, 30rem);
  height: auto;
  margin: var(--s5) auto 0;
}

/* --- inline lead form ----------------------------------------------------
   Homepage teaser only — three fields, not the full quote form. Framed
   with the HUD panel's corner brackets (reused, not reinvented) as a
   static "instrument panel" edge instead of a plain boxed form; .lead is
   the positioned ancestor .hud__bracket's absolute corners anchor to, and
   .lead .hud__bracket overrides their normal hover-only opacity:0 since
   here they're a fixed framing detail, not a reveal state. */
.lead {
  position: relative;
  display: grid;
  gap: var(--s3);
  padding: var(--s4);
  border: 1px solid var(--keyline);
  background: var(--surface);
}
.lead .hud__bracket { opacity: 1; }

.lead__status {
  display: none;
  color: var(--accent-ink);
  font-size: var(--t-label);
}
.lead__status.is-visible { display: block; }

.lead__fields { display: grid; gap: var(--s3); }

.lead__thankyou { display: none; gap: var(--s2); }
.lead__thankyou.is-visible { display: grid; }
.lead__thankyou-title { font-size: clamp(1.5rem, 3vw, 2rem); }
.lead__thankyou p:not(.lead__thankyou-title) { color: var(--quiet); }

/* Off-screen, not display:none/type=hidden — some bots skip fields that
   never render at all, fewer skip ones that are merely visually clipped. */
.lead__hp {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

.lead__field { display: grid; gap: var(--s1); }
.lead__field-label {
  font-family: var(--face-body);
  font-weight: 600;
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--quiet);
}
.lead__field input,
.lead__field textarea {
  font: inherit;
  font-size: var(--t-body);
  color: var(--display);
  background: var(--ground);
  border: 1px solid var(--keyline);
  padding: var(--s2) var(--s3);
  transition: border-color var(--dur-1) var(--ease);
}
.lead__field textarea { resize: vertical; }
.lead__field input:focus-visible,
.lead__field textarea:focus-visible { border-color: var(--accent); }

/* Radio group — the required auto-vs-aircraft service-track selector on
   the full quote form. Reuses .lead__field's caption via .lead__field-label;
   the options themselves are plain body text, not the caption style. */
.lead__radios { display: flex; flex-wrap: wrap; gap: var(--s3); }
.lead__radio {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-size: var(--t-body);
  color: var(--display);
  cursor: pointer;
}
.lead__radio input { accent-color: var(--accent); width: 1rem; height: 1rem; flex: none; }

.lead .btn { justify-self: start; }

/* ==========================================================================
   contact.html — quote page
   ========================================================================== */

/* Same text-left/form-right pattern as .close on the homepage — the form
   is reliably the taller column, so the shorter text column gets a photo
   (.quote__photo) filling what would otherwise be dead space beneath it. */
.quote {
  padding-block: clamp(var(--s5), 6vw, var(--s6)) var(--s5);
  border-bottom: 1px solid var(--keyline);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s5);
  align-items: start;
}
.quote__head { display: grid; gap: var(--s3); align-content: start; }
.quote__title { font-size: clamp(2.5rem, 6.5vw, 5rem); }
.quote__note { color: var(--quiet); }
.quote__photo {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border: 1px solid var(--keyline);
  margin-top: var(--s3);
}

/* Living inside .quote__head now, not its own section — sized down from
   the section-level heading it used to borrow (.work__title) so it reads
   as a sub-block under "Request a quote", not a second competing headline.
   Pushed down with extra margin rather than sitting flush under the photo,
   so it settles roughly centered in the leftover space below the shorter
   photo column instead of reading as an afterthought stacked right under it. */
.quote__location-title { font-size: clamp(1.25rem, 2.5vw, 1.75rem); margin-top: var(--s6); }

.quote-location__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s4);
  margin-top: var(--s2);
}
.quote-location__item p:last-child { color: var(--quiet); }
.quote-location__item a:hover, .quote-location__item a:focus-visible { color: var(--accent-ink); }

/* ==========================================================================
   about.html — about page
   ========================================================================== */

/* Same text-left/photo-right shape as .quote, but the photo is the
   informational subject here (Mitch, not decorative filler), and there's
   no form — the column ends in a plain CTA pair instead. */
.about {
  padding-block: clamp(var(--s5), 6vw, var(--s6)) var(--s6);
  border-bottom: 1px solid var(--keyline);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s5);
  align-items: start;
}
.about__head { display: grid; gap: var(--s3); align-content: start; }
.about__title { font-size: clamp(2.5rem, 6.5vw, 5rem); }
.about__tag { color: var(--accent-ink); }
.about__story { color: var(--quiet); max-width: 60ch; }
/* Portrait, not the gallery's 3:2 — the source photo is itself close to
   square with Mitch and the aircraft nose both filling the frame, so a
   wide crop would cut into one or the other. */
.about__photo {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border: 1px solid var(--keyline);
}

.colophon {
  border-top: 1px solid var(--keyline);
  padding-block: var(--s6) var(--s5);
  display: grid;
  gap: var(--s5);
}
.colophon__top {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: var(--s5);
}
.colophon__brand { display: grid; gap: var(--s3); align-content: start; }
.colophon__name { font-family: var(--face-display); font-size: 1.5rem; text-transform: uppercase; }
.colophon__tag { color: var(--quiet); max-width: 32ch; }

.colophon__heading { margin: 0 0 var(--s3); }

.colophon__nav ul,
.colophon__block ul { display: flex; flex-direction: column; gap: var(--s2); list-style: none; margin: 0; padding: 0; }
.colophon__nav a:not(.btn),
.colophon__block a:not(.btn),
.colophon__block span {
  position: relative;
  display: inline-block;
  width: fit-content;
  font-size: var(--t-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--quiet);
}
.colophon__nav a:not(.btn)::after,
.colophon__block a:not(.btn)::after {
  content: "";
  position: absolute;
  left: 0;
  right: 100%;
  bottom: -0.25rem;
  height: 1px;
  background: var(--accent);
  transition: right var(--dur-2) var(--ease);
}
.colophon__nav a:not(.btn):hover, .colophon__nav a:not(.btn):focus-visible,
.colophon__block a:not(.btn):hover, .colophon__block a:not(.btn):focus-visible { color: var(--accent-ink); }
.colophon__nav a:not(.btn):hover::after, .colophon__nav a:not(.btn):focus-visible::after,
.colophon__block a:not(.btn):hover::after, .colophon__block a:not(.btn):focus-visible::after { right: 0; }

.colophon__block .btn { margin-top: var(--s2); }

/* Icon-only, so no underline-sweep (that's a text-link affordance) — same
   quiet -> accent-ink hover as everything else in this footer, just colour,
   no fill or circle behind the glyph (never a filled accent region). Each
   link's tap target is grown with padding + an offsetting negative margin
   rather than a visible box, so it doesn't change how the row looks. Gap
   is --s4, not --s3 — the padding trick eats 0.625rem off each tap target's
   inside edge, so at --s3 the two enlarged tap targets end up touching
   (0px between them); --s4 keeps real breathing room once expanded. */
.colophon__social { display: flex; align-items: center; gap: var(--s4); margin-top: var(--s3); }
.colophon__social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.625rem;
  margin: -0.625rem;
  color: var(--quiet);
  transition: color var(--dur-1) var(--ease);
}
.colophon__social a:hover, .colophon__social a:focus-visible { color: var(--accent-ink); }
.colophon__social-icon { width: 1.125rem; height: 1.125rem; flex: none; }

.colophon__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding-top: var(--s4);
  border-top: 1px solid var(--keyline-soft);
}
.colophon__legal { font-size: var(--t-micro); color: var(--quiet); }

/* Studio credit. The logo asset is its own baked-in gold/silver PNG — its
   lightest tones (the "VERTEX OPS" wordmark) sit close to --ground's own
   value, so on transparent it was reading as functionally invisible. Fix
   is a soft dark drop-shadow directly on the transparent PNG — bleeds a
   little contrast around the pale lettering on every side without a
   background plate behind it. Deliberate, acknowledged exception to
   DESIGN.md's "no shadows" rule for this one raster credit mark, not a
   precedent for shadows elsewhere. */
.colophon__credit {
  display: inline-flex;
  align-items: center;
  gap: var(--s3);
  font-size: var(--t-micro);
  color: var(--quiet);
  text-decoration: none;
  transition: color var(--dur-1) var(--ease);
}
.colophon__credit:hover, .colophon__credit:focus-visible { color: var(--accent-ink); }
.colophon__credit-logo {
  display: block;
  height: 44px;
  width: auto;
  filter: drop-shadow(0 0 1px rgb(0 0 0 / 0.4)) drop-shadow(0 1px 2px rgb(0 0 0 / 0.28)) drop-shadow(0 0 5px rgb(0 0 0 / 0.18));
}

/* ==========================================================================
   Motion — scroll reveal, scroll progress
   All driven by assets/js/motion.js. Every hidden-by-default state below is
   only ever applied by the script itself, right before it starts observing,
   so JS-off or no-IntersectionObserver renders everything visible and static.
   ========================================================================== */

.reveal {
  transition: opacity var(--dur-3) var(--ease), transform var(--dur-3) var(--ease);
  transition-delay: calc(var(--stagger, 0) * 90ms);
}
.reveal.reveal--pending { opacity: 0; transform: translateY(20px); }
.reveal.is-visible { opacity: 1; transform: none; }

.scroll-progress {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  height: 3px;
  z-index: 40;
  background: var(--keyline-soft);
}
.scroll-progress__bar {
  height: 100%;
  width: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
}

/* ==========================================================================
   Mobile
   ========================================================================== */

@media (max-width: 60rem) {
  .hero { grid-template-columns: 1fr; align-items: start; }
  .close { grid-template-columns: 1fr; }
  .quote { grid-template-columns: 1fr; }
  .about { grid-template-columns: 1fr; }
  .unit__body { grid-template-columns: 1fr; }
  .colophon__top { grid-template-columns: 1fr 1fr; }
}

/* The list is already a vertical stack of horizontal rows at every width —
   nothing structural needs to change here, just tighten it up for a
   touch-comfortable row on a narrow screen. Tap-to-expand (hud.js) already
   works at any width; it isn't gated to this breakpoint. */
@media (max-width: 43.75rem) {
  .hud { height: clamp(20rem, 100vw, 26rem); }
  .hud__panel { padding: var(--s2) var(--s3); }
  .hud__title { font-size: clamp(1rem, 5.5vw, 1.4rem); }

  /* .hud__panel's padding just shrank above, which pulls card text in to
     var(--s3) from the edge — the same inset the brackets already sit at.
     Pull the brackets in further so their 1rem width doesn't reach the text. */
  .hud__bracket--tl, .hud__bracket--bl { left: var(--s2); }
  .hud__bracket--tr, .hud__bracket--br { right: var(--s2); }
  .hud__bracket--tl, .hud__bracket--tr { top: var(--s2); }
  .hud__bracket--bl, .hud__bracket--br { bottom: var(--s2); }
}

@media (max-width: 30rem) {
  .gallery-card { flex-basis: 17.5rem; height: 23rem; }   /* 280 / 368 */
  .gallery__nav { width: 2.25rem; height: 2.25rem; }
  .colophon__top { grid-template-columns: 1fr; }
  .quote-location__grid { grid-template-columns: 1fr; }
}

@media (max-width: 46rem) {
  .nav-toggle { display: inline-flex; }
  .masthead .rule { display: none; }

  .masthead__nav {
    position: fixed;
    inset: 0;
    z-index: 10;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: var(--s4);
    padding: var(--gutter);
    background: var(--ground);
    visibility: hidden;
    opacity: 0;
    transition: opacity var(--dur-2) var(--ease), visibility var(--dur-2) var(--ease);
  }
  .masthead__nav[data-open="true"] { visibility: visible; opacity: 1; }
  /* :not(.btn) to match the base rule's specificity (0,2,1) — a plain
     ".masthead__nav a" here loses to that always-on desktop rule regardless
     of this media query, since specificity decides the winner before
     media-query nesting or source order ever come into it. Without this,
     the overlay's links silently keep the small desktop label style. */
  .masthead__nav a:not(.btn) {
    font-family: var(--face-display);
    font-size: clamp(2.5rem, 11vw, 4rem);
    letter-spacing: 0.01em;
    text-transform: uppercase;
    color: var(--display);
  }
  .masthead__nav .btn { font-size: var(--t-label); }

  .work__head { flex-direction: column; align-items: flex-start; gap: var(--s2); }
  .work__head .rule { display: none; }

  .unit__end { gap: var(--s3); padding: var(--s3) var(--s2); flex-wrap: wrap; }
  .unit__meta { width: 100%; margin-left: 0; }
  .unit__body { padding-inline: 0 0; }
  .unit__end:hover, .unit[open] > .unit__end { padding-inline-start: var(--s2); }
}

body[data-nav-open="true"] { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* belt-and-braces: motion.js already skips the pending state under
     reduced motion, this just guarantees content can never be caught mid-fade */
  .reveal, .reveal.reveal--pending { opacity: 1; transform: none; }
}
