/* ==========================================================================
   Featured Aircraft showcase — redesign prototype, Version 2
   Loaded only by /fleet-preview/. Shares tokens.css; adds nothing global.

   The aircraft is a stack of self-masked copies of one PNG (see the note in
   src/fleet-showcase.mjs). Depth comes from three nested transform layers:
     .fs__scene     pointer yaw/pitch + drift          (all jets, damped in JS)
     .fs__jet       enter / leave pose                 (per jet, CSS transition)
     .fs__jet-body  scroll depth (translateZ) + float  (active jet)
   and from the ground shadow moving against the pointer, the studio light
   moving with it far more slowly.
   ========================================================================== */

@property --atmo {
  syntax: '<color>';
  inherits: true;
  initial-value: #e7eef4;
}

.fs {
  position: relative;
  overflow: hidden;
  padding-block: var(--section-lg);
  background: var(--white);
  --atmo: #e7eef4;
  transition: --atmo 1100ms var(--ease-inout);

  /* Pointer state, written by JS. --mx/--my: plane and shadow (fast damping).
     --bx/--by: studio light (slow damping). All in [-1, 1]. --enter: scroll
     depth 0 → 1. */
  --mx: 0; --my: 0; --bx: 0; --by: 0; --enter: 1;
}

/* --- Header ------------------------------------------------------------- */
.fs__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-lg);
  margin-bottom: var(--space-lg);
}

.fs__eyebrow { margin: 0 0 var(--space-sm); }
.fs__title { margin: 0; }

.fs__nav {
  display: flex;
  gap: var(--space-2xs);
  padding-bottom: 0.4em;
}

.fs__arrow {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  padding: 0;
  border: var(--hairline) solid var(--dark-30);
  border-radius: 50%;
  background: transparent;
  color: var(--black);
  cursor: pointer;
  transition: border-color var(--dur-md) var(--ease-lux),
              background-color var(--dur-md) var(--ease-lux);
}

.fs__arrow svg {
  width: 1.125rem;
  height: 1.125rem;
  transition: transform var(--dur-md) var(--ease-lux);
}

.fs__arrow:hover { border-color: var(--black); }
.fs__arrow--next:hover svg { transform: translateX(2px); }
.fs__arrow--prev:hover svg { transform: translateX(-2px); }
.fs__arrow:active { background: var(--dark-05); }

.fs__arrow:focus-visible,
.fs__pick:focus-visible,
.fs__stage:focus-visible {
  outline: 2px solid var(--brand-light);
  outline-offset: 4px;
}

/* --- Stage -------------------------------------------------------------- */
.fs__stage {
  position: relative;
  aspect-ratio: 16 / 7.2;
  min-height: 22rem;
  max-height: 40rem;
  perspective: 1100px;
  perspective-origin: 50% 42%;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
  cursor: grab;
}

.fs__stage:active { cursor: grabbing; }

/* Studio. White, a pale reflected-light pool behind the aircraft, a floor
   that only exists as falloff. Everything dissolves before the stage edge. */
.fs__atmo {
  position: absolute;
  inset: -8% -4%;
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image:
    linear-gradient(to right, transparent, #000 18%, #000 82%, transparent),
    linear-gradient(to bottom, transparent, #000 16%, #000 80%, transparent);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right, transparent, #000 18%, #000 82%, transparent),
    linear-gradient(to bottom, transparent, #000 16%, #000 80%, transparent);
  mask-composite: intersect;
}

.fs__atmo > * {
  position: absolute;
  display: block;
}

/* Reflected light behind the aircraft, drifting slowly with the pointer. */
.fs__atmo-light {
  inset: -20% -10%;
  background: radial-gradient(
    ellipse 50% 54% at calc(50% + var(--bx) * 4%) calc(56% + var(--by) * -3%),
    var(--atmo) 0%,
    color-mix(in srgb, var(--atmo) 72%, transparent) 36%,
    color-mix(in srgb, var(--atmo) 24%, transparent) 68%,
    transparent 100%
  );
}

/* Floor falloff: the sweep meeting the ground, no line. */
.fs__atmo-floor {
  inset: 0;
  background: linear-gradient(
    to bottom,
    transparent 52%,
    color-mix(in srgb, var(--atmo) 60%, white) 80%,
    color-mix(in srgb, var(--atmo) 20%, white) 92%,
    transparent 100%
  );
  -webkit-mask-image: radial-gradient(ellipse 58% 110% at 50% 84%, #000 26%, transparent 100%);
  mask-image: radial-gradient(ellipse 58% 110% at 50% 84%, #000 26%, transparent 100%);
}

.fs__atmo-grain {
  inset: 0;
  opacity: 0.035;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.2 0 0 0 0 0.25 0 0 0 0 0.3 0 0 0 1 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 160px 160px;
  -webkit-mask-image: radial-gradient(ellipse 60% 70% at 50% 55%, #000 30%, transparent 100%);
  mask-image: radial-gradient(ellipse 60% 70% at 50% 55%, #000 30%, transparent 100%);
}

/* --- Label -------------------------------------------------------------- */
.fs__label {
  position: absolute;
  top: 5%;
  left: 4%;
  z-index: 3;
  max-width: 60%;
  pointer-events: none;
}

.fs__cat {
  margin: 0 0 0.35rem;
  font-size: var(--text-sm);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--dark-70);
}

.fs__name {
  margin: 0;
  font-size: clamp(2.5rem, 4.9vw, 4.5rem);
  line-height: 1;
  letter-spacing: -0.015em;
}

.fs__label > * {
  transition: opacity 560ms var(--ease-lux), transform 560ms var(--ease-lux);
}

.fs__name { transition-delay: 60ms; }

.fs__label.is-out > * {
  opacity: 0;
  transform: translateY(-0.45rem);
  transition: opacity 240ms var(--ease-inout), transform 240ms var(--ease-inout);
}

.fs__label.is-out .fs__name { transition-delay: 0ms; }

/* --- Scene -------------------------------------------------------------- */
.fs__scene {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  /* Yaw up to ±6°, pitch ±3°, lateral drift. The object turns toward the
     pointer the way a heavy thing on a turntable would. */
  transform:
    translate3d(calc(var(--mx) * 1.6%), calc(var(--my) * -0.8%), 0)
    rotateY(calc(var(--mx) * 6deg))
    rotateX(calc(var(--my) * 3deg));
  will-change: transform;
}

/* --- WebGL relief (preferred path) --------------------------------------- */
.fs__canvas {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: none;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* Once the renderer has a first aircraft, it owns the stage: the CSS layer
   stacks hide (they remain the texture sources), the CSS scene tilt is off
   (rotation happens in the renderer, where it is real), and the CSS AO is
   replaced by the rendered contact shadow. */
.fs.is-gl .fs__canvas { display: block; }
.fs.is-gl .fs__jet { display: none; }
.fs.is-gl .fs__scene { transform: none; }
.fs.is-gl .fs__ground { bottom: -8%; height: 20%; }
.fs.is-gl .fs__shadow--soft { opacity: 0.7; }

/* --- Aircraft (CSS fallback) --------------------------------------------- */
.fs__jet {
  position: absolute;
  inset: auto 0 6%;
  z-index: 2;
  width: min(92%, 70rem);
  margin: 0 auto;
  transform-style: preserve-3d;
  opacity: 0;
  visibility: hidden;
  /* A switch is a fly-past. The aircraft face right, so "away" is forward
     and up, shrinking into the distance; the next one arrives from behind
     on the left, a little low, and decelerates onto its mark.

     Waiting pose: well back on the left, slightly small, out of focus. */
  transform: translate3d(-70%, 4%, -420px) rotateY(14deg) rotate(1.5deg);
  filter: blur(4px);
  transition: transform 1050ms var(--ease-glide),
              filter 1050ms var(--ease-glide),
              opacity 380ms var(--ease-inout),
              visibility 0s linear 1050ms;
  will-change: transform, opacity, filter;
}

.fs__jet.is-active {
  opacity: 1;
  visibility: visible;
  /* On its mark. Scroll depth rides here: --enter 0 → 1 brings the aircraft
     forward from 260px back, on the same eased transition. */
  transform: translate3d(0, calc((1 - var(--enter)) * 1.5%), calc((1 - var(--enter)) * -260px));
  filter: blur(0);
  transition-delay: 160ms, 160ms, 160ms, 0s;
}

/* Leaving: nose up, throttle on — accelerates out of frame to the right,
   climbing and receding, and only fades once it is already moving fast. */
.fs__jet.is-leaving {
  opacity: 0;
  visibility: hidden;
  transform: translate3d(80%, -12%, -380px) rotateY(-10deg) rotate(-3deg);
  filter: blur(5px);
  transition: transform 760ms cubic-bezier(0.55, 0, 0.85, 0.4),
              filter 760ms cubic-bezier(0.55, 0, 0.85, 0.4),
              opacity 360ms var(--ease-inout) 340ms,
              visibility 0s linear 760ms;
}

.fs__jet-body {
  position: relative;
  transform-style: preserve-3d;
  will-change: transform;
}

.fs__jet-img {
  display: block;
  width: 100%;
  height: auto;
  filter: contrast(calc(0.92 + var(--enter) * 0.08)) saturate(calc(0.94 + var(--enter) * 0.06));
}

/* Hover. The active aircraft is never quite still: a slow figure-of-eight
   in yaw, pitch and roll, so its form keeps revealing itself. */
.fs__jet.is-active .fs__jet-body {
  animation: fs-hover 9s var(--ease-inout) infinite;
}

@keyframes fs-hover {
  0%, 100% { transform: translate3d(0, 0, 0) rotateY(0deg) rotateX(0deg) rotate(0deg); }
  25%      { transform: translate3d(0.5%, -0.9%, 8px) rotateY(2.6deg) rotateX(0.9deg) rotate(-0.4deg); }
  50%      { transform: translate3d(0, -0.3%, 0) rotateY(0deg) rotateX(-0.7deg) rotate(0deg); }
  75%      { transform: translate3d(-0.5%, -1%, 8px) rotateY(-2.6deg) rotateX(0.7deg) rotate(0.4deg); }
}

/* Every lighting layer is the aircraft's own silhouette. */
.fs__jet-light,
.fs__jet-ao-fill {
  position: absolute;
  inset: 0;
  pointer-events: none;
  -webkit-mask-image: var(--jet);
  -webkit-mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-image: var(--jet);
  mask-size: 100% 100%;
  mask-repeat: no-repeat;
}

/* Underside: the belly, engine nacelles and lower wing surfaces fall into
   shadow. Multiply keeps the livery colours; it only takes light away. */
.fs__jet-light--shade {
  background: linear-gradient(
    to bottom,
    transparent 28%,
    rgb(60 80 110 / 0.06) 44%,
    rgb(18 30 48 / 0.16) 62%,
    rgb(18 30 48 / 0.34) 82%,
    rgb(18 30 48 / 0.50) 100%
  );
  mix-blend-mode: multiply;
  opacity: calc(0.7 + var(--enter) * 0.3);
}

/* Key light: a broad softbox above and slightly ahead of the nose. The upper
   fuselage and the top of the tail catch it; it is gone by mid-body. */
.fs__jet-light--key {
  background: linear-gradient(
    172deg,
    rgb(255 255 255 / 0.62) 0%,
    rgb(255 255 255 / 0.34) 22%,
    rgb(255 255 255 / 0.08) 44%,
    transparent 54%
  );
  mix-blend-mode: soft-light;
  opacity: calc(0.75 + var(--enter) * 0.25);
}

/* Fill: a low, cool bounce from the floor so the underside keeps detail. */
.fs__jet-light--fill {
  background: linear-gradient(
    to top,
    rgb(214 226 238 / 0.34) 0%,
    rgb(214 226 238 / 0.10) 26%,
    transparent 40%
  );
  mix-blend-mode: screen;
}

/* Specular: one soft reflection sliding along the upper fuselage with the
   pointer. Small, blurred, never a spot. */
.fs__jet-light--spec {
  background: radial-gradient(
    ellipse 26% 30% at calc(58% + var(--mx) * 14%) calc(36% + var(--my) * -6%),
    rgb(255 255 255 / 0.40) 0%,
    rgb(255 255 255 / 0.12) 45%,
    transparent 100%
  );
  mix-blend-mode: screen;
  filter: blur(6px);
  opacity: 0.9;
}

/* Rim: the silhouette minus the same silhouette nudged down, leaving only
   the top edges — fuselage crown, tail cap, wing and stabiliser leading
   surfaces. Then blurred slightly so it reads as light, not a line. */
.fs__jet-light--rim {
  background: linear-gradient(to bottom, rgb(255 255 255 / 0.95) 0%, rgb(255 255 255 / 0.55) 55%, rgb(255 255 255 / 0.2) 100%);
  -webkit-mask-image: var(--jet), var(--jet);
  -webkit-mask-size: 100% 100%, 100% 100%;
  -webkit-mask-position: 0 0, 0 1%;
  -webkit-mask-repeat: no-repeat, no-repeat;
  -webkit-mask-composite: source-out;
  mask-image: var(--jet), var(--jet);
  mask-size: 100% 100%, 100% 100%;
  mask-position: 0 0, 0 1%;
  mask-repeat: no-repeat, no-repeat;
  mask-composite: subtract;
  mix-blend-mode: screen;
  filter: blur(0.8px);
  opacity: 0.75;
}

/* Ambient occlusion: the aircraft's own silhouette, squashed to a band and
   pressed just under the belly, so the shadow under a Gulfstream is long and
   under a CJ3 short — no ellipse can do that. The squash happens in the
   mask (mask-size), the blur on the wrapper, so the blur is applied AFTER
   the squash and stays soft in both axes. */
.fs__jet-ao {
  position: absolute;
  inset: 0;
  pointer-events: none;
  transform: translate3d(calc(var(--mx) * -1.1%), 4.5%, -1px);
  filter: blur(12px);
  opacity: calc(0.16 + var(--enter) * 0.12);
  transition: opacity 600ms var(--ease-inout);
}

.fs__jet-ao-fill {
  background: rgb(14 24 40);
  -webkit-mask-size: 93% 22%;
  -webkit-mask-position: 50% 97%;
  mask-size: 93% 22%;
  mask-position: 50% 97%;
}

/* --- Ground shadow (primary + atmospheric) ----------------------------- */
.fs__ground {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -3%;
  z-index: 1;
  height: 16%;
  pointer-events: none;
  /* Moves against the pointer: the light is on the pointer's side. */
  transform:
    translate3d(calc(var(--mx) * -4%), calc(var(--my) * 1%), 0)
    scale(calc(1.14 - var(--enter) * 0.14), calc(1.1 - var(--enter) * 0.1));
  opacity: calc(0.55 + var(--enter) * 0.45);
  transition: opacity 600ms var(--ease-inout);
  will-change: transform;
}

.fs__stage.is-swapping .fs__ground {
  opacity: 0.4;
  transform: scale(1.06, 0.96);
  transition: opacity 500ms var(--ease-inout), transform 700ms var(--ease-glide);
}

.fs__shadow {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  border-radius: 50%;
}

.fs__shadow--soft {
  width: 64%;
  height: 70%;
  background: radial-gradient(ellipse at center, rgb(16 28 46 / 0.22), rgb(16 28 46 / 0.07) 50%, transparent 72%);
  filter: blur(14px);
  animation: fs-shadow-hover 9s var(--ease-inout) infinite;
}

/* The floor shadow breathes against the hover: aircraft up, shadow softer. */
@keyframes fs-shadow-hover {
  0%, 100% { scale: 1 1; opacity: 1; }
  25%      { scale: 1.03 0.94; opacity: 0.82; }
  50%      { scale: 1 1; opacity: 0.96; }
  75%      { scale: 1.03 0.94; opacity: 0.8; }
}

/* Foreground haze, in front of the aircraft's lower half. */
.fs__haze {
  position: absolute;
  left: -4%;
  right: -4%;
  bottom: -6%;
  z-index: 3;
  height: 34%;
  pointer-events: none;
  background: linear-gradient(to top, rgb(255 255 255 / 0.55) 0%, rgb(255 255 255 / 0.22) 40%, transparent 100%);
  transform: translate3d(calc(var(--mx) * 2.2%), 0, 0);
  will-change: transform;
}

.fs__shadow--atmos {
  width: 96%;
  height: 160%;
  background: radial-gradient(ellipse at center, rgb(16 28 46 / 0.07), transparent 70%);
  filter: blur(22px);
}

/* --- Picker ------------------------------------------------------------- */
.fs__picker { margin-top: var(--space-md); }

.fs__picker-track {
  position: relative;
  display: flex;
  justify-content: center;
  gap: clamp(0.25rem, 1.2vw, 1.25rem);
  padding-bottom: 0.25rem;
}

.fs__pick {
  position: relative;
  flex: 0 1 9.75rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0.75rem 0.5rem 1.75rem;
  border: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.fs__pick img {
  display: block;
  width: 100%;
  height: auto;
  opacity: 0.34;
  filter: grayscale(1);
  transform: scale(0.94);
  transition: opacity var(--dur-md) var(--ease-lux),
              filter var(--dur-md) var(--ease-lux),
              transform var(--dur-md) var(--ease-lux);
}

.fs__pick:hover img,
.fs__pick:focus-visible img {
  opacity: 0.72;
  filter: grayscale(0.35);
  transform: scale(1);
}

.fs__pick.is-on img {
  opacity: 1;
  filter: none;
  transform: scale(1.08);
}

.fs__pick-name {
  position: absolute;
  bottom: 0.55rem;
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--dark-70);
  white-space: nowrap;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity var(--dur-md) var(--ease-lux), transform var(--dur-md) var(--ease-lux);
}

.fs__pick:hover .fs__pick-name,
.fs__pick:focus-visible .fs__pick-name,
.fs__pick.is-on .fs__pick-name { opacity: 1; transform: none; }

.fs__pick.is-on .fs__pick-name { color: var(--black); }

.fs__picker-marker {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: var(--w, 0px);
  background: var(--brand-light);
  transform: translateX(var(--x, 0px));
  transition: transform 720ms var(--ease-glide), width 720ms var(--ease-glide);
}

/* --- Specifications ----------------------------------------------------- */
.fs__specs {
  display: flex;
  align-items: center;
  gap: var(--space-xl);
  margin-top: var(--space-lg);
  padding-block: var(--space-md);
  border-top: var(--hairline) solid var(--dark-15);
  border-bottom: var(--hairline) solid var(--dark-15);
}

.fs__spec-list {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  margin: 0;
}

.fs__spec {
  padding-inline: var(--space-md);
  border-left: var(--hairline) solid var(--dark-15);
}

.fs__spec:first-child {
  padding-left: 0;
  border-left: 0;
}

.fs__spec-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.625rem;
  font-size: var(--text-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--neutral-medium);
}

.fs__spec-icon { display: inline-flex; color: var(--neutral-medium); }
.fs__spec-icon svg { width: 1.25rem; height: auto; display: block; }

.fs__spec-value {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 0.45rem;
  margin: 0;
}

.fs__spec-primary {
  font-size: clamp(1.375rem, 1.7vw, 1.75rem);
  font-weight: var(--w-light);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--black);
  font-variant-numeric: tabular-nums;
}

.fs__spec-secondary {
  font-size: var(--text-sm);
  font-weight: var(--w-light);
  color: var(--dark-70);
}

[data-fs-spec] {
  display: inline-block;
  transition: opacity 260ms var(--ease-inout), transform 260ms var(--ease-inout);
  transition-delay: calc(var(--n, 0) * 40ms);
}

[data-fs-spec].is-out {
  opacity: 0;
  transform: translateY(0.3rem);
}

.fs__cta { flex: none; }

.fs__cta-arrow {
  display: inline-flex;
  margin-left: 0.125rem;
  transition: transform var(--dur-md) var(--ease-lux);
}

.fs__cta-arrow svg { width: 1rem; height: 1rem; }
.fs__cta:hover .fs__cta-arrow { transform: translateX(3px); }

.fs .spec-note { margin-top: var(--space-md); }

/* --- Entrance ----------------------------------------------------------- */
.js .fs [data-fs-in] {
  opacity: 0;
  transform: translateY(1.25rem);
  transition: opacity 1000ms var(--ease-lux) var(--d, 0ms),
              transform 1000ms var(--ease-lux) var(--d, 0ms);
}

/* The stage only fades: its depth is the scroll's job. */
.js .fs [data-fs-stage][data-fs-in] { transform: none; }

.js .fs.is-in [data-fs-in] {
  opacity: 1;
  transform: none;
}

/* --- Single-aircraft hero (aircraft detail pages) ------------------------ */
.fs-hero {
  position: relative;
  aspect-ratio: 1713 / 505;
  margin-bottom: var(--space-lg);
}

.fs-hero__canvas {
  position: absolute;
  inset: -24% 0;
  width: 100%;
  height: 148%;
  display: none;
  pointer-events: none;
}

.fs-hero__img {
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 24px 40px rgb(0 0 0 / 0.16));
}

.fs-hero.is-gl { cursor: grab; }
.fs-hero.is-gl .fs-hero__canvas { display: block; pointer-events: auto; }
.fs-hero.is-gl .fs-hero__img { visibility: hidden; }

/* --- Preview page chrome ------------------------------------------------ */
.fs-preview-note {
  padding-block: var(--space-sm);
  background: var(--neutral-lightest);
  border-bottom: var(--hairline) solid var(--dark-10);
  font-size: var(--text-sm);
  color: var(--dark-70);
}

.fs-preview-note p { margin: 0; }
.fs-preview-note a { color: var(--brand-medium); text-decoration: underline; text-underline-offset: 0.15em; }

/* --- Breakpoints -------------------------------------------------------- */
@media (max-width: 1024px) {
  .fs__stage { aspect-ratio: 16 / 8.6; }
  .fs__jet { width: 94%; }
  .fs__spec { padding-inline: var(--space-sm); }
  .fs__specs { gap: var(--space-lg); }
}

@media (max-width: 860px) {
  .fs__specs { flex-wrap: wrap; }

  .fs__spec-list {
    flex: 1 1 100%;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    row-gap: var(--space-md);
  }

  .fs__spec:nth-child(4) { padding-left: 0; border-left: 0; }
}

@media (max-width: 700px) {
  .fs__head {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-md);
    margin-bottom: var(--space-lg);
  }

  .fs__nav { padding-bottom: 0; }

  .fs__stage {
    aspect-ratio: 4 / 3.1;
    min-height: 0;
    margin-inline: calc(-1 * var(--gutter));
  }

  .fs__label {
    top: 6%;
    left: var(--gutter);
    max-width: calc(100% - 2 * var(--gutter));
  }

  .fs__name { font-size: clamp(2rem, 9.5vw, 2.75rem); }

  /* No pointer on a phone: the scene does not turn and the shadow does not
     slide, but the hover, the fly-past and the lighting stack all remain. */
  .fs__scene { transform: none; }
  .fs__ground { transform: scale(calc(1.14 - var(--enter) * 0.14), calc(1.1 - var(--enter) * 0.1)); bottom: -1%; height: 14%; }
  .fs__haze { transform: none; }
  .fs__jet { width: 100%; inset: auto 0 8%; }
  .fs__jet-light--spec { display: none; }

  .fs__picker { margin-top: var(--space-sm); }

  .fs__picker-track {
    justify-content: flex-start;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    padding-inline: 0.25rem;
  }

  .fs__picker-track::-webkit-scrollbar { display: none; }

  .fs__pick {
    flex: 0 0 7.25rem;
    scroll-snap-align: center;
  }

  .fs__specs {
    gap: var(--space-md);
    margin-top: var(--space-lg);
  }

  .fs__spec-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: var(--space-md);
  }

  .fs__spec { padding-inline: var(--space-sm); }
  .fs__spec:nth-child(4) { padding-left: var(--space-sm); border-left: var(--hairline) solid var(--dark-15); }
  .fs__spec:nth-child(odd) { padding-left: 0; border-left: 0; }

  .fs__cta {
    flex: 1 1 100%;
    justify-content: center;
  }
}

@media (max-width: 400px) {
  .fs__title { font-size: 1.875rem; }
  .fs__pick { flex-basis: 6.25rem; }
  .fs__spec-primary { font-size: 1.25rem; }
}

/* --- Reduced motion ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .fs,
  .fs * {
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    animation: none !important;
  }

  .fs { --enter: 1; --mx: 0; --my: 0; --bx: 0; --by: 0; }
  .js .fs [data-fs-in] { opacity: 1; transform: none; }
  .fs__scene { transform: none; }
}

/* --- Lineup renders (FLEET_MODE 'lineup', 2026-09-24) --------------------
   Static side-profile renders stand in for the WebGL models. They face LEFT
   and stand on their wheels, which changes the choreography: nothing floats
   (no hover bob, no pointer tilt — a flat image turned in 3D reads as a
   card), a switch is a taxi along the ground in the direction of the nose,
   and the polished apron below the horizon reflects the gear and belly.
   All seven share one canvas, so the size hierarchy comes from the files. */
.fs--lineup .fs__scene { transform: none; }

.fs--lineup .fs__jet {
  /* centred by margin rather than left/right, so a light jet eased up past
     the stage width (--k) still centres */
  --w: calc(min(100%, 80rem) * var(--k, 1));
  inset: auto auto 15% 50%;
  width: var(--w);
  margin: 0 0 0 calc(var(--w) / -2);
  /* waiting: back along the taxiway, to the right (behind the tail) */
  transform: translate3d(38%, 0, 0);
  filter: none;
  transition: transform 1100ms var(--ease-glide),
              opacity 520ms var(--ease-inout),
              visibility 0s linear 1100ms;
  will-change: transform, opacity;
}

.fs--lineup .fs__jet.is-active {
  transform: translate3d(0, 0, calc((1 - var(--enter)) * -140px));
  transition-delay: 140ms, 140ms, 0s;
}

/* leaving: rolls off nose-first to the left, accelerating */
.fs--lineup .fs__jet.is-leaving {
  transform: translate3d(-46%, 0, 0);
  transition: transform 820ms cubic-bezier(0.55, 0, 0.85, 0.4),
              opacity 380ms var(--ease-inout) 260ms,
              visibility 0s linear 820ms;
}

.fs--lineup .fs__jet.is-active .fs__jet-body { animation: none; }

.fs--lineup .fs__jet-img {
  filter: drop-shadow(0 0.5rem 0.8rem rgb(4 14 28 / 0.2));
  -webkit-box-reflect: below 1px linear-gradient(transparent 62%, rgb(255 255 255 / 0.2));
}

/* contact shadow on the apron, centred on the wheel line */
.fs--lineup .fs__ground,
.v2 .fs--lineup .fs__ground { bottom: 10%; height: 10%; transform: none; }
.fs--lineup .fs__shadow--soft { width: 62%; height: 60%; animation: none; }

@media (max-width: 700px) {
  .fs--lineup .fs__jet { --w: calc(100% * var(--k, 1)); inset: auto auto 17% 50%; }
  .fs--lineup .fs__ground,
  .v2 .fs--lineup .fs__ground { bottom: 12%; }
}

/* --- Apron backdrop (lineup mode, 2026-09-24) -----------------------------
   The sunset apron photo behind every aircraft, in place of the cloud sky.
   assets/img/backdrops/apron-sunset.webp has its sky extended upward into a
   flat zenith blue (src/source-art/extend-apron-sunset.py), so anything above
   the photo is that colour, and its horizon sits at 77.5% of its height —
   background-position-y 77.5% puts the horizon at 77.5% of any box. */

/* Homepage showcase: the photo runs from behind the heading down past the
   stage, horizon behind the lower fuselage, and dissolves into the navy the
   picker and figures sit on. ::before is now the navy slab and ::after the
   photo, so the photo can fade out over it. */
.v2 .fs--lineup { background: rgb(16 52 92); }
.v2 .fs--lineup .fs__atmo { display: none; }
.v2 .fs--lineup .fs__stage::before {
  left: calc(50% - 50vw); right: calc(50% - 50vw);
  top: 92%;
  height: 400vh;
  background: var(--navy-900);
}
.v2 .fs--lineup .fs__stage::after {
  left: calc(50% - 50vw); right: calc(50% - 50vw);
  top: -60%;
  height: 172%;
  background: url("/assets/img/backdrops/apron-sunset.webp") 18% 77.5% / cover no-repeat;
  -webkit-mask-image: linear-gradient(to bottom, #000 84%, transparent);
  mask-image: linear-gradient(to bottom, #000 84%, transparent);
}
.v2 .fs--lineup .fs__eyebrow { color: rgb(255 255 255 / 0.72); }
.v2 .fs--lineup .fs__title { color: var(--white); }
.v2 .fs--lineup .fs__arrow { color: var(--white); border-color: rgb(255 255 255 / 0.45); }
.v2 .fs--lineup .fs__arrow:hover { background: var(--white); border-color: var(--white); color: var(--ink); }
.v2 .fs--lineup .fs__cat { color: rgb(255 255 255 / 0.8); }
.v2 .fs--lineup .fs__name { color: var(--white); text-shadow: 0 1px 24px rgb(8 28 52 / 0.35); }

@media (max-width: 700px) {
  .v2 .fs--lineup .fs__stage::after { background-image: url("/assets/img/backdrops/apron-sunset-1200.webp"); }
}

/* Aircraft pages: the pinned stage. fleet-showcase.js sets --sky-y/--sky-h so
   the horizon lands just above the aircraft's wheels at any viewport; below
   the photo is navy, and a light scrim top and bottom carries the type. */
.v2 .stage--photo .stage__sticky { background: var(--navy-900); }
.stage__backdrop {
  position: absolute;
  left: 0; right: 0;
  top: var(--sky-y, 0px);
  height: var(--sky-h, 100%);
  background: url("/assets/img/backdrops/apron-sunset.webp") 18% 77.5% / cover no-repeat;
  -webkit-mask-image: linear-gradient(to bottom, #000 90%, transparent);
  mask-image: linear-gradient(to bottom, #000 90%, transparent);
}
.stage--photo .stage__sky::after {
  background:
    linear-gradient(to bottom, rgb(6 16 26 / 0.38) 0%, rgb(6 16 26 / 0) 26%),
    linear-gradient(to top, rgb(6 16 26 / 0.55) 0%, rgb(6 16 26 / 0) 32%);
}
.stage--photo .stage__horizon { display: none; }
.stage--photo .stage__head .eyebrow { color: rgb(255 255 255 / 0.72); }
.stage--photo .stage__head .h2 { color: var(--white); }
.stage--photo .stage__cat { color: rgb(255 255 255 / 0.78); }
.stage--photo .stage__name { color: var(--white); }
.stage--photo .stage__list { border-top-color: rgb(255 255 255 / 0.22); }
.stage--photo .stage__spec { border-bottom-color: rgb(255 255 255 / 0.16); }
.stage--photo .stage__spec dt { color: rgb(255 255 255 / 0.66); }
.stage--photo .stage__spec dd { color: var(--white); }

/* Parked: a lineup render stands on the scene floor and rolls in nose-first
   as the stage pins, instead of descending from the sky like the 3D hero. */
.v2 .stage--parked .stage__jet { align-items: end; }
/* The render fits the scene both ways (a definite row is what lets
   max-height: 100% resolve), and height auto keeps the box the jet's own
   shape — as a fixed height the attribute letterboxed it inside a taller box,
   and the backdrop is lined up against this box. */
.v2 .stage--parked .stage__jet { justify-items: center; grid-template-rows: minmax(0, 1fr); }
.stage--parked .stage__lineup { width: 100%; height: auto; max-height: 100%; object-fit: contain; object-position: 50% 100%; }

/* Desktop: the parked jet takes the full width of the stage; the figures move
   down beside the name instead of boxing the aircraft into the left column. */
@media (min-width: 1025px) {
  .v2 .stage--parked .stage__grid {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "head head"
      "scene scene"
      "label specs";
  }
  /* on wide screens the aircraft may run past the text column, up to 100rem */
  .v2 .stage--parked .stage__scene {
    margin-bottom: var(--space-lg);
    margin-inline: min(0px, calc((100% - min(100vw - 6rem, 100rem)) / 2));
  }
  /* one row of five, label above figure, so the strip costs ~4rem of height */
  .v2 .stage--parked .stage__specs { justify-self: end; }
  .v2 .stage--parked .stage__list { display: flex; border-top: 0; }
  .v2 .stage--parked .stage__spec {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.35rem;
    padding: 0.15rem clamp(1rem, 2vw, 1.75rem);
    border-bottom: 0;
    border-left: 1px solid rgb(255 255 255 / 0.18);
  }
  .v2 .stage--parked .stage__spec dd { text-align: left; white-space: nowrap; }
}
.v2 .stage--parked .stage__jet.is-on img {
  transform: translate3d(calc((1 - var(--arrive)) * 12%), 0, 0) scale(calc(0.84 + var(--arrive) * 0.16));
  transform-origin: 50% 100%;
  filter: blur(calc((1 - var(--arrive)) * 3px)) drop-shadow(0 0.5rem 0.8rem rgb(4 14 28 / 0.22));
  -webkit-box-reflect: below 1px linear-gradient(transparent 62%, rgb(255 255 255 / 0.2));
}
.stage--parked .stage__shadow { bottom: -3%; height: 8%; }
