/* ═══════════════════════════════════════════════════════════════════
   FLYSKYMODS — fx.css
   Glass + motion layer. Loaded LAST, after style.css, app.css, theme.css.

   Two jobs:
     A. Bring the page to the reference composition (hero plate, nav,
        trust strip, review card).
     B. Add the frosted-glass surfaces and the motion the brief asked for.

   Rules kept from theme.css:
     - Colour only through the tokens in theme.css :root. Nothing here
       introduces a new brand hue; the additions below are all light.
     - Every animation is switched off under prefers-reduced-motion, at
       the bottom of this file, in one block.
   ═══════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════════
   0. FX TOKENS
   ═══════════════════════════════════════════════════════════════════ */

:root {
  /* Glass: one recipe, three weights. Everything frosted on this site
     uses one of these three and nothing else, or the page stops reading
     as a single material. */
  --glass-1:      rgba(12, 19, 40, .46);   /* lightest — floats over photo */
  --glass-2:      rgba(10, 16, 34, .62);   /* default panel              */
  --glass-3:      rgba(7, 12, 27, .78);    /* heaviest — over bright art */
  --glass-blur:   blur(14px) saturate(150%);
  --glass-blur-lg:blur(20px) saturate(160%);

  /* The hairline that makes glass look like an edge and not a rectangle:
     bright at the top-left, gone by the bottom-right. */
  --glass-edge:   linear-gradient(145deg,
                    rgba(255,255,255,.22) 0%,
                    rgba(255,255,255,.06) 26%,
                    rgba(255,255,255,0)   52%,
                    rgba(214,172,99,.14)  100%);
  --glass-shadow: 0 1px 0 rgba(255,255,255,.06) inset,
                  0 -1px 0 rgba(0,0,0,.35) inset,
                  0 18px 46px rgba(2,4,10,.55);

  --fx-slow:   18s;
  --fx-medium: 9s;
}

/* ═══════════════════════════════════════════════════════════════════
   1. ATMOSPHERE — the animated ground the whole page sits on
   Three fixed layers behind everything: a violet/gold aurora that
   drifts, a fine technical grid that scrolls, and a noise plate that
   stops the gradients banding on cheap panels.
   ═══════════════════════════════════════════════════════════════════ */

body { position: relative; background: var(--ink); }

.fx-atmos {
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  overflow: hidden;
  contain: strict;
}

/* Aurora. These are radial-gradients, which are ALREADY smooth — the
   filter: blur() they used to carry was blurring an analytic gradient,
   and it cost roughly a third of the page's frame budget for no visible
   difference. Measured; do not add it back. Transform-only animation
   keeps them on the compositor. */
.fx-aurora {
  position: absolute;
  border-radius: 50%;
  opacity: .55;
  will-change: transform;
}
.fx-aurora.a1 {
  width: 62vw; height: 62vw; left: -18vw; top: -22vw;
  background: radial-gradient(circle closest-side, var(--glow-indigo) 0%, rgba(34,49,79,.45) 42%, transparent 72%);
  animation: fx-drift-1 var(--fx-slow) ease-in-out infinite alternate;
}
.fx-aurora.a2 {
  width: 52vw; height: 52vw; right: -14vw; top: -6vh;
  background: radial-gradient(circle closest-side, var(--glow-violet) 0%, rgba(90,42,62,.4) 44%, transparent 72%);
  animation: fx-drift-2 calc(var(--fx-slow) * 1.35) ease-in-out infinite alternate;
}
.fx-aurora.a3 {
  width: 44vw; height: 44vw; left: 24vw; bottom: -20vw;
  background: radial-gradient(circle closest-side, var(--glow-gold) 0%, rgba(122,90,36,.3) 40%, transparent 70%);
  opacity: .2;
}

@keyframes fx-drift-1 {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(7vw, 5vh, 0) scale(1.14); }
}
@keyframes fx-drift-2 {
  from { transform: translate3d(0, 0, 0) scale(1.06); }
  to   { transform: translate3d(-6vw, 8vh, 0) scale(.92); }
}

/* Grid + grain in ONE static layer.
   They were two elements, one of them animated and masked. Both are
   decoration that never changes, so they are now a single background
   stack the compositor rasterizes once and caches: same picture, no
   per-frame cost. The drift that used to come from panning the grid now
   comes from the aurora and the particle canvas, which are cheap. */
.fx-grid {
  position: absolute;
  inset: 0;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'200\' height=\'200\'%3E%3Cfilter id=\'n\'%3E%3CfeTurbulence type=\'fractalNoise\' baseFrequency=\'.85\' numOctaves=\'3\' opacity=\'.3\'/%3E%3C/filter%3E%3Crect width=\'200\' height=\'200\' filter=\'url(%23n)\' opacity=\'.05\'/%3E%3C/svg%3E"),
    linear-gradient(rgba(199,206,222,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(199,206,222,.05) 1px, transparent 1px),
    linear-gradient(rgba(199,206,222,.026) 1px, transparent 1px),
    linear-gradient(90deg, rgba(199,206,222,.026) 1px, transparent 1px);
  background-size: 200px 200px, 240px 240px, 240px 240px, 48px 48px, 48px 48px;
  -webkit-mask-image: radial-gradient(120% 90% at 50% 20%, #000 0%, rgba(0,0,0,.5) 48%, transparent 78%);
          mask-image: radial-gradient(120% 90% at 50% 20%, #000 0%, rgba(0,0,0,.5) 48%, transparent 78%);
}

/* Particle field / starfield. Painted by fx.js. */
.fx-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: .8;
}

/* Cursor spotlight. A single element moved by fx.js — cheaper than a
   backdrop-filter that reflows on every mouse move. */
.fx-cursor {
  position: fixed;
  z-index: -1;
  width: 520px; height: 520px;
  margin: -260px 0 0 -260px;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(circle,
    rgba(168,92,114,.13) 0%,
    rgba(214,172,99,.055) 38%,
    transparent 68%);
  transition: opacity .5s var(--ease);
  will-change: transform;
}
body.fx-pointer .fx-cursor { opacity: 1; }

/* Scroll progress — a champagne hairline across the top of the nav. */
.fx-progress {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  z-index: 1200;
  background: linear-gradient(90deg, var(--gold), var(--champagne), var(--violet-lt));
  box-shadow: 0 0 12px rgba(214,172,99,.5);
  will-change: transform;
}

/* ═══════════════════════════════════════════════════════════════════
   2. GLASS — one material, applied to every raised surface
   ═══════════════════════════════════════════════════════════════════ */

/* The gradient hairline is drawn as a masked pseudo-element rather than
   a border, because a border cannot hold a gradient without a second
   background layer fighting the blur. */
.fx-glass {
  position: relative;
  background: var(--glass-2);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  border: 1px solid transparent;
  box-shadow: var(--glass-shadow);
}
.fx-glass::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: var(--glass-edge);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}

/* Apply it to the surfaces that already exist, so no markup has to move.

   IMPORTANT — which elements get backdrop-filter:
   Only the ones there are a FIXED, SMALL number of. A backdrop-filter
   forces the browser to re-blur everything behind that element, and the
   catalogue renders up to forty product cards: putting it on .product-card
   cost roughly two thirds of the frame rate, measured. Cards get a
   slightly more opaque background instead, which is visually almost
   identical over this dark ground and free. */
.hero-panel,
.trust-strip-inner,
.globe-panel,
.fsm-review,
.newsletter-glass,
.partner-strip {
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
}

.trust-strip-inner {
  background: var(--glass-2);
  border-color: rgba(255,255,255,.08);
  box-shadow: var(--glass-shadow);
}
.globe-panel,
.newsletter-glass {
  background: var(--glass-2);
  box-shadow: var(--glass-shadow);
}
/* These three float over the brightest part of the photograph, so they
   take the heaviest glass — at --glass-1 the sub-line disappeared into
   the sunset. */
.hero-panel {
  background: var(--glass-3);
  -webkit-backdrop-filter: var(--glass-blur-lg);
          backdrop-filter: var(--glass-blur-lg);
  box-shadow: var(--glass-shadow);
}
.hero-panel-text { color: var(--text-2); }
/* No backdrop-filter here, by design — see the note above. The extra
   opacity does the same job for a card sitting on a dark ground. */
.product-card,
.cat-card,
.benefit {
  background: rgba(13, 20, 42, .82);
  box-shadow: var(--glass-shadow);
}

/* Specular sweep. A single skewed highlight that crosses the surface on
   hover — the thing that makes glass look like glass rather than like a
   translucent rectangle. */
.product-card,
.cat-card,
.hero-panel,
.benefit,
.fsm-review,
.globe-panel {
  overflow: hidden;
  isolation: isolate;
}
.product-card::after,
.cat-card::after,
.benefit::after,
.fsm-review::after {
  content: '';
  position: absolute;
  top: -60%;
  left: -75%;
  width: 45%;
  height: 220%;
  transform: rotate(18deg) translate3d(0, 0, 0);
  background: linear-gradient(90deg,
    transparent,
    rgba(255,255,255,.075) 42%,
    rgba(242,223,176,.11) 52%,
    transparent);
  opacity: 0;
  pointer-events: none;
  z-index: 3;
}
.product-card:hover::after,
.cat-card:hover::after,
.benefit:hover::after,
.fsm-review:hover::after {
  opacity: 1;
  animation: fx-sheen .85s var(--ease) forwards;
}
@keyframes fx-sheen {
  from { left: -75%; }
  to   { left: 135%; }
}

/* ═══════════════════════════════════════════════════════════════════
   3. HERO — the reference plate
   ═══════════════════════════════════════════════════════════════════ */

/* Taller than theme.css's 542px. The aircraft is a fixed 2.85:1 shape and
   its nose is at the top-right — exactly where the three info cards sit.
   Rather than shrink the aeroplane until it fits beside them, the hero
   grows and the aeroplane flies underneath them. Nothing overlaps. */
.hero { min-height: 720px; }

/* ── The sky plate ──────────────────────────────────────────────────
   No longer a photograph of an aircraft: the aircraft is now its own
   layer (below). This is sky only — generated in the site palette, so
   there is no second aeroplane in the background and no third-party
   photo to license. */
.hero-photo-panel {
  width: 66%;
  top: 0;
  will-change: transform;

  /* Dissolves to TRANSPARENCY, not to a colour. theme.css faded it by
     painting opaque --ink over the left edge, which worked when the page
     ground was flat --ink. It is not any more: the aurora sits behind
     everything, so a wall of opaque --ink read as a hard vertical seam
     exactly where the fade was meant to be invisible. */
  -webkit-mask-image:
    linear-gradient(90deg, transparent 0%, rgba(0,0,0,.05) 10%, rgba(0,0,0,.30) 24%,
                    rgba(0,0,0,.68) 39%, rgba(0,0,0,.93) 52%, #000 62%),
    linear-gradient(180deg, transparent 0%, rgba(0,0,0,.55) 7%, #000 17%),
    linear-gradient(0deg,  transparent 0%, rgba(0,0,0,.5) 8%, #000 22%);
          mask-image:
    linear-gradient(90deg, transparent 0%, rgba(0,0,0,.05) 10%, rgba(0,0,0,.30) 24%,
                    rgba(0,0,0,.68) 39%, rgba(0,0,0,.93) 52%, #000 62%),
    linear-gradient(180deg, transparent 0%, rgba(0,0,0,.55) 7%, #000 17%),
    linear-gradient(0deg,  transparent 0%, rgba(0,0,0,.5) 8%, #000 22%);
  -webkit-mask-composite: source-in;
          mask-composite: intersect;
}

.hero-photo {
  background-image: url('/assets/hero-sky.jpg');
  background-position: 62% 40%;
  filter: none;
  transform: scale(1.06);
  will-change: transform;
}

/* With the panel masked, this only darkens the copy side so the headline
   keeps its contrast and weights the top for the navbar. */
.hero-photo-fade {
  background:
    linear-gradient(90deg,
      rgba(4,7,15,.88) 0%,
      rgba(4,7,15,.66) 14%,
      rgba(4,7,15,.34) 30%,
      rgba(4,7,15,.10) 46%,
      transparent 60%),
    linear-gradient(180deg, rgba(4,7,15,.6) 0%, rgba(4,7,15,.14) 14%, transparent 28%),
    linear-gradient(0deg,  rgba(4,7,15,.8) 0%, rgba(4,7,15,.42) 12%, rgba(4,7,15,.12) 26%, transparent 40%);
}

.hero-photo-tint {
  opacity: .16;
  background:
    radial-gradient(58% 66% at 74% 22%, rgba(168,92,114,.6), transparent 62%),
    radial-gradient(56% 62% at 40% 88%, rgba(255,176,96,.5), transparent 60%);
}

/* ── The aircraft ───────────────────────────────────────────────────
   A cut-out A300-600R, whole airframe — nose, tail, both wings, gear —
   with the port wingtip reconstructed (it ran off the edge of the source
   frame). Sits ABOVE the masked sky panel so nothing eats its wing. */
.hero-craft {
  position: absolute;
  z-index: 1;
  /* Sized and placed so the WHOLE airframe is inside the viewport: the
     port wingtip clears the headline on the left, the nose stops short
     of the right edge. Both are the point of this hero — if either
     leaves the frame the brief is not met. */
  right: 6%;
  top: 64%;
  width: 48%;
  max-width: 940px;
  pointer-events: none;
  will-change: transform;
  /* fx.js writes --px/--py from the pointer. It sets custom properties
     rather than the whole transform, because the cruise animation below
     owns a transform of its own — an inline transform from JS would
     simply cancel it. */
  transform: translate3d(var(--px, 0px), calc(-50% + var(--py, 0px)), 0);
}
.hero-craft picture,
.hero-craft img {
  display: block;
  width: 100%;
  height: auto;
}
.hero-craft img {
  /* One shadow, cast down-left, away from the sun sitting low-right in
     the sky plate. A drop-shadow on a element this large is only cheap
     because it never animates — the float below moves the wrapper. */
  filter: drop-shadow(-14px 26px 34px rgba(2, 4, 12, .55));
}

/* The warm bloom the aircraft sits in. A separate element rather than a
   second drop-shadow: gradients are far cheaper than a 60px blur. */
.hero-craft-glow {
  position: absolute;
  left: 6%;
  top: 8%;
  width: 88%;
  height: 84%;
  border-radius: 50%;
  background:
    radial-gradient(closest-side, rgba(255,186,116,.28), transparent 72%),
    radial-gradient(closest-side at 72% 60%, rgba(255,150,90,.22), transparent 68%);
  filter: blur(26px);
  z-index: -1;
}

/* Gentle bob, so the aircraft reads as flying rather than pasted on.
   It lives on the inner <picture> so the wrapper's transform stays free
   for the pointer parallax. Transform only — stays on the compositor. */
.hero-craft picture { animation: fx-cruise 9s ease-in-out infinite alternate; }
@keyframes fx-cruise {
  from { transform: translate3d(0, -9px, 0) rotate(-.4deg); }
  to   { transform: translate3d(0, 11px, 0) rotate(.4deg); }
}

/* Scan sweep across the plate — one slow pass, the "techy" read the
   brief asked for, kept faint enough not to fight the photograph. */
.hero-photo-panel::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(105deg,
    transparent 38%,
    rgba(217,168,180,.10) 47%,
    rgba(242,223,176,.14) 50%,
    rgba(217,168,180,.10) 53%,
    transparent 62%);
  background-size: 260% 100%;
  animation: fx-scan 7.5s var(--ease) infinite;
  mix-blend-mode: screen;
}
@keyframes fx-scan {
  0%, 62%  { background-position: 190% 0; opacity: 0; }
  70%      { opacity: 1; }
  100%     { background-position: -90% 0; opacity: 0; }
}

/* ── Headline: animated champagne→violet gradient, as in the reference
      where "Flight" is gold and "Experience" violet. The sweep is what
      keeps it from reading as flat coloured text. ── */
.hero-heading .accent-gold,
.hero-heading .accent-violet {
  background-size: 220% 100%;
  animation: fx-gradient-pan 7s var(--ease) infinite alternate;
}
@keyframes fx-gradient-pan {
  from { background-position: 0% 50%; }
  to   { background-position: 100% 50%; }
}

/* Pill: the dot pulses, so the badge reads as live. */
.hero-pill {
  background: var(--glass-1);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
}
.hero-pill .hp-dot { animation: fx-pulse 2.2s ease-in-out infinite; }
@keyframes fx-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(214,172,99,.55); opacity: 1; }
  50%      { box-shadow: 0 0 0 6px rgba(214,172,99,0);  opacity: .72; }
}

/* Hero side panels arrive one after another, right to left. */
.hero-panel { transition: transform .45s var(--ease), border-color var(--t), box-shadow var(--t); }
.hero-panel:hover {
  transform: translateX(-6px);
  box-shadow: var(--glass-shadow), 0 0 0 1px var(--line-gold);
}
.hero-panel-icon { position: relative; overflow: hidden; }
.hero-panel:hover .hero-panel-icon {
  background: rgba(214,172,99,.2);
  box-shadow: 0 0 18px rgba(214,172,99,.28);
}

/* ── Trust avatars: the reference shows overlapping portraits. Painted
      here as gradient discs carrying a silhouette, so there is no photo
      of a person who never bought anything. ── */
.hero-avatar {
  position: relative;
  border: 2px solid rgba(8,12,26,.9);
  box-shadow: 0 2px 8px rgba(2,4,10,.6);
  overflow: hidden;
}
.hero-avatar::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 50% 34%, rgba(255,255,255,.9) 0 17%, transparent 18%),
    radial-gradient(ellipse 62% 44% at 50% 96%, rgba(255,255,255,.85) 0 60%, transparent 62%);
  opacity: .34;
}
.hero-avatars:hover .hero-avatar { transform: translateY(-2px); }
.hero-avatar { transition: transform .3s var(--ease); }

/* ═══════════════════════════════════════════════════════════════════
   4. NAVIGATION — dropdowns, cart badge, auth buttons
   ═══════════════════════════════════════════════════════════════════ */

.navbar {
  -webkit-backdrop-filter: var(--glass-blur-lg);
          backdrop-filter: var(--glass-blur-lg);
}

/* Brand mark gets a slow shimmer so the logo is the one moving thing
   above the fold when the page is idle. */
.nav-brand-mark svg { filter: drop-shadow(0 0 6px rgba(214,172,99,.35)); }
.nav-brand:hover .nav-brand-mark svg { filter: drop-shadow(0 0 12px rgba(214,172,99,.6)); }
.nav-brand-mark svg { transition: filter var(--t), transform var(--t); }
.nav-brand:hover .nav-brand-mark svg { transform: translateX(2px) rotate(-4deg); }

/* ── Dropdown menus ── */
.nav-links li.has-menu { position: relative; }
.nav-links li.has-menu > a { display: inline-flex; align-items: center; gap: 5px; }
.nav-caret {
  width: 9px; height: 9px;
  transition: transform var(--t);
  opacity: .7;
}
.nav-links li.has-menu:hover > a .nav-caret,
.nav-links li.has-menu.open > a .nav-caret { transform: rotate(180deg); opacity: 1; }

.nav-menu {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  min-width: 232px;
  padding: 7px;
  border-radius: var(--radius);
  background: var(--glass-3);
  -webkit-backdrop-filter: var(--glass-blur-lg);
          backdrop-filter: var(--glass-blur-lg);
  box-shadow: var(--glass-shadow);
  border: 1px solid rgba(255,255,255,.08);
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, -8px) scale(.97);
  transition: opacity .2s var(--ease), transform .24s var(--ease), visibility .24s;
  z-index: 60;
}
.nav-links li.has-menu:hover > .nav-menu,
.nav-links li.has-menu.open > .nav-menu {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0) scale(1);
}
/* Keeps the pointer from falling through the gap between link and menu. */
.nav-menu::before {
  content: '';
  position: absolute;
  top: -12px; left: 0; right: 0; height: 12px;
}
.nav-menu a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 11px;
  border-radius: var(--radius-sm);
  font-size: .82rem;
  color: var(--text-2);
  white-space: nowrap;
}
.nav-menu a:hover { color: var(--text); background: rgba(199,206,222,.06); }
.nav-menu a .nm-dot {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--champagne), var(--gold));
  flex-shrink: 0;
  opacity: .75;
}
.nav-menu a:hover .nm-dot { box-shadow: 0 0 8px rgba(214,172,99,.7); opacity: 1; }
.nav-menu .nm-sub {
  display: block;
  font-size: .7rem;
  color: var(--text-3);
  margin-top: 1px;
}

/* Cart badge sits on the button, gold, and pops when the count changes. */
.cart-count {
  box-shadow: 0 0 0 2px rgba(6,10,22,.9), 0 2px 10px rgba(214,172,99,.45);
}
.cart-count.fx-bump { animation: fx-bump .4s var(--ease); }
@keyframes fx-bump {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.42); }
  100% { transform: scale(1); }
}

/* Auth buttons in the reference: ghost "Login", solid champagne
   "Register". api.js injects them; these style whatever it writes. */
#navAuth .btn-primary,
#navAuth .btn-ghost,
.nav-btn-login,
.nav-btn-register {
  padding: 9px 20px !important;
  font-size: .83rem !important;
  border-radius: var(--radius-sm) !important;
}

/* ═══════════════════════════════════════════════════════════════════
   5. CARDS — tilt, glow, badges, rating row
   ═══════════════════════════════════════════════════════════════════ */

.product-card {
  transform-style: preserve-3d;
  transition: transform .3s var(--ease), box-shadow .3s var(--ease), border-color .3s var(--ease);
}
/* will-change is promoted only while the card is actually being tilted.
   Leaving it on every card gives the compositor one layer per card, and
   the catalogue can render forty of them. */
.product-card.fx-tilt { will-change: transform; }
/* fx.js writes --rx/--ry from the pointer position; the fallback keeps
   the card flat when JS has not run. */
.product-card.fx-tilt {
  transform:
    perspective(900px)
    rotateX(var(--rx, 0deg))
    rotateY(var(--ry, 0deg))
    translate3d(0, -5px, 0);
  box-shadow: var(--glass-shadow), 0 30px 70px rgba(2,4,10,.6), 0 0 0 1px var(--line-gold);
}
.product-card .pcard-media { position: relative; overflow: hidden; }
.product-card .pcard-media img { transition: transform .55s var(--ease); }
.product-card:hover .pcard-media img { transform: scale(1.07); }

/* Gold corner ticks — a HUD read that costs nothing and only appears on
   hover, so the resting grid stays calm. */
.product-card .pcard-media::after {
  content: '';
  position: absolute;
  inset: 9px;
  border: 1px solid transparent;
  border-radius: 6px;
  background:
    linear-gradient(var(--gold), var(--gold)) 0 0 / 12px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 0 0 / 1px 12px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 0 / 12px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 0 / 1px 12px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 0 100% / 12px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 0 100% / 1px 12px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 100% / 12px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 100% / 1px 12px no-repeat;
  opacity: 0;
  transition: opacity .3s var(--ease);
  pointer-events: none;
  z-index: 2;
}
.product-card:hover .pcard-media::after { opacity: .55; }

.pcard-badge {
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
  box-shadow: 0 4px 14px rgba(2,4,10,.5);
}

/* Rating row, as in the reference: gold star, score, review count. Only
   rendered by script.js when the product actually carries a rating. */
.pcard-rating {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: .76rem;
  color: var(--text-2);
  margin-top: 6px;
}
.pcard-rating .pr-star { color: var(--gold); font-size: .8rem; line-height: 1; }
.pcard-rating .pr-score { font-weight: 600; color: var(--text); }
.pcard-rating .pr-count { color: var(--text-3); }

.pcard-cart {
  position: relative;
  overflow: hidden;
  transition: transform var(--t), background var(--t), box-shadow var(--t);
}
.pcard-cart:hover {
  box-shadow: 0 0 20px rgba(214,172,99,.35);
  transform: translateY(-1px);
}

/* ═══════════════════════════════════════════════════════════════════
   6. TRUSTED WORLDWIDE — live globe
   ═══════════════════════════════════════════════════════════════════ */

.globe-panel { position: relative; }
.globe-sphere { animation: fx-globe-spin 46s linear infinite; }
@keyframes fx-globe-spin {
  from { background-position: 0 center; }
  to   { background-position: 400px center; }
}
.globe-city { animation: fx-city 3.4s ease-in-out infinite; }
.globe-city:nth-child(2) { animation-delay: .5s; }
.globe-city:nth-child(3) { animation-delay: 1.1s; }
.globe-city:nth-child(4) { animation-delay: 1.7s; }
.globe-city:nth-child(5) { animation-delay: 2.3s; }
@keyframes fx-city {
  0%, 100% { opacity: .35; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.5); }
}
/* The dashed arcs draw themselves, then loop. */
.globe-paths path {
  stroke-dasharray: 3 6;
  animation: fx-arc 5.5s linear infinite;
}
.globe-paths path:nth-child(2) { animation-delay: -1.8s; }
.globe-paths path:nth-child(3) { animation-delay: -3.6s; }
@keyframes fx-arc {
  from { stroke-dashoffset: 0; }
  to   { stroke-dashoffset: -90; }
}
.globe-stat-num {
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 22px rgba(168,92,114,.3);
}

/* ═══════════════════════════════════════════════════════════════════
   7. PARTNER BAND — review card
   ═══════════════════════════════════════════════════════════════════ */

.partner-name {
  transition: color var(--t), text-shadow var(--t), transform var(--t);
}
.partner-name:hover {
  color: var(--text);
  text-shadow: 0 0 18px rgba(214,172,99,.4);
  transform: translateY(-1px);
}

.fsm-review {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 20px;
  border-radius: var(--radius);
  background: var(--glass-2);
  border: 1px solid rgba(255,255,255,.07);
  box-shadow: var(--glass-shadow);
}
.fsm-review-score { flex-shrink: 0; text-align: center; }
.fsm-review-stars {
  color: var(--gold);
  font-size: .82rem;
  letter-spacing: .12em;
  line-height: 1;
}
.fsm-review-word {
  display: block;
  margin-top: 4px;
  font-size: .8rem;
  font-weight: 650;
  color: var(--text);
}
.fsm-review-body { font-size: .78rem; color: var(--text-2); line-height: 1.5; }
.fsm-review-body cite {
  display: block;
  margin-top: 5px;
  font-style: normal;
  font-size: .72rem;
  color: var(--text-3);
}
.fsm-review-rule {
  width: 1px;
  align-self: stretch;
  background: linear-gradient(180deg, transparent, var(--line-2), transparent);
  flex-shrink: 0;
}

/* ═══════════════════════════════════════════════════════════════════
   8. BENEFITS BAND
   ═══════════════════════════════════════════════════════════════════ */

.benefit {
  position: relative;
  border-radius: var(--radius);
  transition: transform var(--t), background var(--t);
}
.benefit:hover { transform: translateY(-3px); }
.benefit-icon { transition: transform var(--t), box-shadow var(--t), background var(--t); }
.benefit:hover .benefit-icon {
  transform: translateY(-2px) scale(1.06);
  box-shadow: 0 0 20px rgba(214,172,99,.3);
}

/* ═══════════════════════════════════════════════════════════════════
   9. BUTTONS — magnetic, with a champagne bloom
   ═══════════════════════════════════════════════════════════════════ */

.btn-primary,
.btn-ghost {
  position: relative;
  overflow: hidden;
  transform: translate3d(var(--mx, 0px), var(--my, 0px), 0);
  transition: transform .25s var(--ease), box-shadow var(--t), background var(--t), border-color var(--t);
}
.btn-primary::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 30%, rgba(255,255,255,.42) 50%, transparent 70%);
  background-size: 240% 100%;
  background-position: 190% 0;
  pointer-events: none;
}
.btn-primary:hover::before { animation: fx-btn-sheen .7s var(--ease) forwards; }
@keyframes fx-btn-sheen {
  from { background-position: 190% 0; }
  to   { background-position: -90% 0; }
}
.btn-primary:hover { box-shadow: var(--shadow-gold), 0 0 34px rgba(214,172,99,.3); }
.btn-ghost:hover  { box-shadow: 0 0 26px rgba(168,92,114,.22); }

/* ═══════════════════════════════════════════════════════════════════
   10. SCROLL REVEAL
   Elements start 22px low and transparent; fx.js adds .fx-in when they
   cross the viewport. If JS never runs, .fx-up is never applied by the
   observer — so the base state must stay visible. fx.js opts each
   element in by adding .fx-up itself.
   ═══════════════════════════════════════════════════════════════════ */

.fx-up {
  opacity: 0;
  transform: translate3d(0, 22px, 0);
  transition: opacity .6s var(--ease), transform .7s var(--ease);
}
.fx-up.fx-in { opacity: 1; transform: none; }

/* Staggered children (product grids, benefit rows). */
.fx-up.fx-d1 { transition-delay: .07s; }
.fx-up.fx-d2 { transition-delay: .14s; }
.fx-up.fx-d3 { transition-delay: .21s; }
.fx-up.fx-d4 { transition-delay: .28s; }
.fx-up.fx-d5 { transition-delay: .35s; }

/* ═══════════════════════════════════════════════════════════════════
   11. WHATSAPP FLOAT — gentle attention loop
   ═══════════════════════════════════════════════════════════════════ */

.whatsapp-float { animation: fx-float 4.5s ease-in-out infinite; }
@keyframes fx-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-6px); }
}
.whatsapp-float::before {
  content: '';
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 1.5px solid rgba(37,211,102,.5);
  animation: fx-ring 2.6s ease-out infinite;
  pointer-events: none;
}
@keyframes fx-ring {
  0%   { transform: scale(.9); opacity: .7; }
  100% { transform: scale(1.5); opacity: 0; }
}

/* ═══════════════════════════════════════════════════════════════════
   12. RESPONSIVE
   ═══════════════════════════════════════════════════════════════════ */

@media (max-width: 1240px) {
  .hero-craft { width: 54%; right: 5%; top: 65%; }
}
@media (max-width: 1100px) {
  .hero-photo-panel { width: 74%; }
  .hero-craft { width: 62%; right: 3%; top: 66%; }
}

@media (max-width: 860px) {
  /* theme.css already restacks the hero here: the photo becomes a band
     above the copy. The parallax transform must not survive that, and
     the left-edge mask makes no sense on a full-width band — only the
     bottom edge still needs to dissolve. */
  .hero-photo-panel {
    width: auto;
    transform: none !important;
    -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 54%, rgba(0,0,0,.35) 84%, transparent 100%);
            mask-image: linear-gradient(180deg, #000 0%, #000 54%, rgba(0,0,0,.35) 84%, transparent 100%);
    -webkit-mask-composite: source-over;
            mask-composite: add;
  }
  /* `.hero-photo { transform: none !important }` used to sit here, to
     cancel an inline transform fx.js wrote on this element. fx.js no
     longer writes one — it sets --sx/--sy and CSS owns the transform —
     so the rule had stopped cancelling a parallax and started cancelling
     the scaleX(-1) that mirrors the plate, un-mirroring the aircraft
     below 860px while it stayed mirrored above. Section 16.8 sets the
     small-screen transform now. */
  /* Stacked layout: the aircraft becomes the band above the copy, centred
     and whole, instead of a slab bleeding off the right edge. */
  .hero-craft {
    position: relative;
    right: auto;
    top: auto;
    /* 100%, not more: on a phone the wingtips are within a few pixels of
       the viewport edge, and any overhang clips the very thing this hero
       exists to show. */
    width: 100%;
    margin: -14px 0 -4px;
    transform: none;
  }
  .fx-cursor { display: none; }
  .fx-grid { opacity: .55; }
  .nav-menu {
    position: static;
    transform: none;
    opacity: 1;
    visibility: visible;
    display: none;
    min-width: 0;
    margin: 4px 0 6px;
    background: rgba(199,206,222,.04);
    box-shadow: none;
    -webkit-backdrop-filter: none;
            backdrop-filter: none;
  }
  .nav-links li.has-menu.open > .nav-menu { display: block; transform: none; }
}

/* Below 768px theme.css puts .nav-actions and .nav-hamburger in the same
   grid cell, so on a 390px screen the burger lands on top of the gold
   Register button. Give the burger its own column and drop the two
   controls the collapsed menu already covers. */
@media (max-width: 768px) {
  .nav-inner {
    grid-template-columns: auto 1fr auto;
    grid-template-areas: 'brand actions burger';
  }
  .nav-hamburger {
    grid-area: burger;
    justify-self: end;
    margin-left: 4px;
  }
}
@media (max-width: 560px) {
  #searchToggle { display: none; }
  .nav-login { display: none !important; }
  .nav-register { padding: 8px 13px; font-size: .76rem; }
  .nav-logo { font-size: .88rem; letter-spacing: .1em; }
  .hero-panels { flex-direction: column; }
}

/* Coarse pointers get no tilt and no cursor light — both are mouse
   affordances and cost frames on a phone. */
@media (hover: none) {
  .fx-cursor { display: none; }
  .product-card.fx-tilt { transform: none; }
}

/* ═══════════════════════════════════════════════════════════════════
   12b. LIGHT BUILD
   fx.js adds .fx-lite to <body> when the device reports few cores or
   little memory, or when the first ninety frames come in slow. It sheds
   the three most expensive things — the particle canvas, the drifting
   aurora and backdrop blur on the large panels — and keeps everything
   that reads as design: the glass tints, the hairlines, the sheen, the
   reveals, the hero.
   ═══════════════════════════════════════════════════════════════════ */

body.fx-lite .fx-canvas { display: none; }
body.fx-lite .fx-aurora { animation: none; }
body.fx-lite .hero-craft-glow { filter: none; }
body.fx-lite .hero-panel,
body.fx-lite .trust-strip-inner,
body.fx-lite .globe-panel,
body.fx-lite .fsm-review,
body.fx-lite .newsletter-glass,
body.fx-lite .partner-strip,
body.fx-lite .nav-menu,
body.fx-lite .navbar {
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
}
/* Without the blur the panels need more of their own body, or they read
   as flat transparent rectangles over the photograph. */
body.fx-lite .hero-panel        { background: rgba(7, 12, 27, .93); }
body.fx-lite .trust-strip-inner,
body.fx-lite .globe-panel,
body.fx-lite .fsm-review,
body.fx-lite .newsletter-glass  { background: rgba(10, 16, 34, .93); }
body.fx-lite .navbar            { background: rgba(5, 9, 20, .95); }

/* ═══════════════════════════════════════════════════════════════════
   13. REDUCED MOTION
   One block, and it turns off everything above. Nothing in this file
   conveys meaning through motion alone, so removing it costs nothing.
   ═══════════════════════════════════════════════════════════════════ */

@media (prefers-reduced-motion: reduce) {
  .fx-aurora,
  .fx-grid,
  .hero-photo-panel::after,
  .hero-heading .accent-gold,
  .hero-heading .accent-violet,
  .hero-pill .hp-dot,
  .globe-sphere,
  .globe-city,
  .globe-paths path,
  .whatsapp-float,
  .whatsapp-float::before,
  .product-card::after,
  .cat-card::after,
  .benefit::after,
  .fsm-review::after,
  .btn-primary::before,
  .cart-count.fx-bump {
    animation: none !important;
  }
  .hero-craft picture { animation: none !important; }
  .fx-up { opacity: 1 !important; transform: none !important; transition: none !important; }
  .fx-cursor, .fx-canvas { display: none !important; }
  .product-card.fx-tilt { transform: translate3d(0, -4px, 0); }
  .btn-primary, .btn-ghost { transform: none !important; }
  .hero-photo { transform: scale(1.03) !important; }
}

/* ═══════════════════════════════════════════════════════════════════
   14. THE OTHER PAGES
   The homepage sets the material; these bring the rest of the store to
   it. Same three glass weights, same hairline, same reveal — no new
   colours and no new components, so a change to section 0 still
   re-skins every page at once.

   Only surfaces that exist in a FIXED, SMALL number get backdrop-filter,
   for the reason documented in section 2. Repeating rows — cart lines,
   download cards, order rows — get opacity instead.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Shared page shells ──────────────────────────────────────────── */
.auth-page,
.pd-page,
.cart-pg,
.co-pg,
.dl-page,
.dash-layout {
  position: relative;
  z-index: 1;                 /* above .fx-atmos, which is at -2 */
}

/* ── 14.1 Auth: login, register, reset, verify ───────────────────── */

/* The card is the only object on the screen, so it gets the heaviest
   treatment on the site: full glass, gold hairline, and a violet bloom
   behind it that the atmosphere shows through. */
.auth-card {
  position: relative;
  background: var(--glass-2);
  -webkit-backdrop-filter: var(--glass-blur-lg);
          backdrop-filter: var(--glass-blur-lg);
  border: 1px solid transparent;
  box-shadow: var(--glass-shadow), 0 40px 90px rgba(2,4,10,.5);
}
.auth-card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: var(--glass-edge);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
}
.auth-page::before {
  content: '';
  position: absolute;
  left: 50%; top: 42%;
  width: min(760px, 92vw);
  height: min(760px, 92vw);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle closest-side,
    rgba(58,42,140,.42) 0%, rgba(46,36,112,.22) 46%, transparent 72%);
  pointer-events: none;
  z-index: -1;
}
.form-input {
  background: rgba(199,206,222,.045);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  transition: border-color var(--t), background var(--t), box-shadow var(--t);
}
.form-input:focus {
  background: rgba(199,206,222,.08);
  border-color: var(--line-gold);
  box-shadow: 0 0 0 3px rgba(214,172,99,.12);
}
.auth-btn { position: relative; overflow: hidden; }
.auth-btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 30%, rgba(255,255,255,.4) 50%, transparent 70%);
  background-size: 240% 100%;
  background-position: 190% 0;
  pointer-events: none;
}
.auth-btn:hover::before { animation: fx-btn-sheen .7s var(--ease) forwards; }

/* ── 14.2 Product detail ─────────────────────────────────────────── */

/* BUG FIX (pre-existing, not introduced by this layer):
   .pd-image-frame is a <button>, so it inherits display:inline-block and
   shrink-to-fit sizing, and the <img> inside it is position:absolute —
   which means the button had nothing to size itself from and collapsed
   to 3x2px. The product page has been shipping with no product image.
   Verified by loading product.html with fx.css blocked: same 3x2px. */
.pd-image-frame {
  display: block;
  width: 100%;
  padding: 0;
  position: relative;
  overflow: hidden;
  background: var(--glass-2);
  box-shadow: var(--glass-shadow);
  cursor: zoom-in;
}
.pd-image-frame img { transition: transform .6s var(--ease); }
.pd-image-frame:hover img { transform: scale(1.045); }
/* Same HUD corner ticks as the catalogue cards, so a product detail
   reads as the same object enlarged rather than a different page. */
.pd-image-frame::after {
  content: '';
  position: absolute;
  inset: 12px;
  border-radius: 7px;
  background:
    linear-gradient(var(--gold), var(--gold)) 0 0 / 16px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 0 0 / 1px 16px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 0 / 16px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 0 / 1px 16px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 0 100% / 16px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 0 100% / 1px 16px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 100% / 16px 1px no-repeat,
    linear-gradient(var(--gold), var(--gold)) 100% 100% / 1px 16px no-repeat;
  opacity: 0;
  transition: opacity .35s var(--ease);
  pointer-events: none;
}
.pd-image-frame:hover::after { opacity: .5; }

.pd-features,
.pd-longtext,
.pd-specs {
  background: rgba(13, 20, 42, .6);
  border-radius: var(--radius);
}
.pd-badge {
  -webkit-backdrop-filter: blur(8px);
          backdrop-filter: blur(8px);
}
.pd-price { text-shadow: 0 0 26px rgba(214,172,99,.22); }

/* ── 14.3 Cart ───────────────────────────────────────────────────── */

/* One panel, so it can afford the blur. */
.cart-summary-card {
  background: var(--glass-2);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-shadow);
  position: relative;
}
/* Repeating rows — opacity only. The cart's row class is .cp-item; it is
   written by cart.js, which is the only place it appears. */
.cp-item,
.cart-trust-strip {
  background: rgba(13, 20, 42, .72);
  border-radius: var(--radius);
  transition: background var(--t), transform var(--t), border-color var(--t);
}
.cp-item:hover {
  background: rgba(17, 26, 54, .85);
  transform: translateX(2px);
}
.cart-empty-pg-icon { animation: fx-float 5s ease-in-out infinite; }

/* The sidebar cart is fixed and singular: glass. */
.cart-sidebar {
  background: var(--glass-3);
  -webkit-backdrop-filter: var(--glass-blur-lg);
          backdrop-filter: var(--glass-blur-lg);
}
.cart-overlay {
  -webkit-backdrop-filter: blur(3px);
          backdrop-filter: blur(3px);
}

/* ── 14.4 Checkout ───────────────────────────────────────────────── */

.co-form-card,
.co-summary-card,
.co-confirmation {
  background: var(--glass-2);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-shadow);
}
.co-order-id-box {
  background: rgba(214,172,99,.07);
  border: 1px solid var(--line-gold);
  border-radius: var(--radius-sm);
}
.co-confirm-icon { animation: fx-pop .5s var(--ease) both; }
@keyframes fx-pop {
  from { transform: scale(.6); opacity: 0; }
  to   { transform: scale(1);  opacity: 1; }
}
.co-submit-btn { position: relative; overflow: hidden; }
.co-submit-btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 30%, rgba(255,255,255,.38) 50%, transparent 70%);
  background-size: 240% 100%;
  background-position: 190% 0;
  pointer-events: none;
}
.co-submit-btn:hover::before { animation: fx-btn-sheen .7s var(--ease) forwards; }

/* ── 14.5 Downloads ──────────────────────────────────────────────── */

.dl-card {
  background: rgba(13, 20, 42, .78);
  border-radius: var(--radius);
  box-shadow: var(--glass-shadow);
  transition: transform var(--t), border-color var(--t), box-shadow var(--t);
  position: relative;
  overflow: hidden;
}
.dl-card:hover {
  transform: translateY(-3px);
  border-color: var(--line-gold);
  box-shadow: var(--glass-shadow), 0 26px 60px rgba(2,4,10,.55);
}
.dl-thumb { overflow: hidden; }
.dl-thumb img { transition: transform .5s var(--ease); }
.dl-card:hover .dl-thumb img { transform: scale(1.06); }
.dl-btn { transition: transform var(--t), box-shadow var(--t), filter var(--t); }
.dl-btn:hover { box-shadow: 0 0 22px rgba(214,172,99,.32); }
.dl-flag.granted { box-shadow: 0 0 14px rgba(52,211,153,.22); }

/* ── 14.6 Dashboard ──────────────────────────────────────────────── */

.dash-sidebar {
  background: var(--glass-2);
  -webkit-backdrop-filter: var(--glass-blur);
          backdrop-filter: var(--glass-blur);
  box-shadow: var(--glass-shadow);
}
.dash-panel {
  background: rgba(13, 20, 42, .66);
  border-radius: var(--radius);
}
.dash-nav-link {
  position: relative;
  transition: background var(--t), color var(--t), padding-left var(--t);
}
.dash-nav-link:hover { padding-left: 20px; }
.dash-nav-link.active::before {
  content: '';
  position: absolute;
  left: 0; top: 50%;
  width: 2px; height: 60%;
  transform: translateY(-50%);
  border-radius: 2px;
  background: linear-gradient(180deg, var(--champagne), var(--gold));
}
.download-card,
.order-row,
.dash-stat {
  background: rgba(13, 20, 42, .72);
  border-radius: var(--radius-sm);
  transition: background var(--t), transform var(--t);
}
.download-card:hover,
.order-row:hover { background: rgba(17, 26, 54, .86); transform: translateY(-2px); }

/* ── 14.7 404 ────────────────────────────────────────────────────── */

.pd-404-num,
.err-code {
  background: linear-gradient(120deg, var(--champagne), var(--gold) 45%, var(--violet-lt));
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
  background-size: 220% 100%;
  animation: fx-gradient-pan 6s var(--ease) infinite alternate;
}

/* ── 14.8 Light build + reduced motion, for everything above ─────── */

body.fx-lite .auth-card,
body.fx-lite .cart-summary-card,
body.fx-lite .cart-sidebar,
body.fx-lite .co-form-card,
body.fx-lite .co-summary-card,
body.fx-lite .co-confirmation,
body.fx-lite .dash-sidebar,
body.fx-lite .form-input,
body.fx-lite .pd-badge,
body.fx-lite .cart-overlay {
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
}
body.fx-lite .auth-card,
body.fx-lite .cart-summary-card,
body.fx-lite .co-form-card,
body.fx-lite .co-summary-card,
body.fx-lite .co-confirmation,
body.fx-lite .dash-sidebar { background: rgba(10, 16, 34, .94); }
body.fx-lite .cart-sidebar { background: rgba(7, 12, 27, .97); }

@media (prefers-reduced-motion: reduce) {
  .cart-empty-pg-icon,
  .co-confirm-icon,
  .auth-btn::before,
  .co-submit-btn::before,
  .pd-404-num,
  .err-code { animation: none !important; }
  .dash-nav-link:hover { padding-left: inherit; }
}

/* ── 14.9 The simpler navs ───────────────────────────────────────────
   404, downloads and verify-email carry a cut-down navbar whose right
   side is a .nav-right div. theme.css lays .nav-inner out as a named
   grid ('brand links actions'), and .nav-right matches none of those
   areas — so it was auto-placed into the brand cell and the account
   chip landed on top of the logo. Give it the actions cell. */
.nav-inner > .nav-right {
  grid-area: actions;
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 10px;
}
@media (max-width: 768px) {
  .nav-inner > .nav-right { grid-area: actions; }
}


/* ═══════════════════════════════════════════════════════════════════
   15. THE REFERENCE PLATE — night storm ramp
   ═══════════════════════════════════════════════════════════════════

   Everything below re-cuts the homepage to the supplied reference: a
   midnight-navy interface, one champagne accent, and a hero set on a wet
   ramp under a storm deck instead of the violet sunset that was here.

   Two rules govern the hero and they are not negotiable:

   1. NOTHING TINTS THE AIRCRAFT. The sky, the weather and the ramp are
      separate layers BEHIND the airframe. There is no filter, no blend
      mode and no overlay on .hero-craft img. Its livery renders exactly
      as it was photographed.

   2. The weather is a real aviation preset, not a light show. One dim
      double-flicker every seventeen seconds, inside the cloud that would
      be producing it. Nothing strobes.

   The sky is painted in gradients rather than loaded as a photograph —
   the plate it replaces was a generated gradient too, so nothing
   licensed is lost, it costs no request, and it stays sharp at any
   width.
   ═══════════════════════════════════════════════════════════════════ */

/* ── 15.1 The storm deck ─────────────────────────────────────────── */

.hero-photo {
  /* Read bottom-up: sky body, the airport's glow on the horizon, the
     dark cloud masses that frame the shot, the lit flanks of the cloud
     nearest the break, and the moonlit break itself.

     The first attempt painted the clouds DARKER than the sky they sat
     on, which is why they were invisible: a cloud deck at night is lit
     from behind, so the masses read as lighter slate against a darker
     sky, not as darker blobs against a lighter one. */
  background-image:
    radial-gradient(30% 26% at 62% 20%, rgba(226,236,252,.34), rgba(176,198,232,.13) 40%, transparent 68%),
    radial-gradient(26% 20% at 49% 27%, rgba(150,174,212,.22), transparent 70%),
    radial-gradient(30% 22% at 77% 24%, rgba(138,162,202,.19), transparent 70%),
    radial-gradient(22% 15% at 36% 17%, rgba(120,144,184,.15), transparent 72%),
    radial-gradient(40% 26% at 25% 13%, rgba(11,19,34,.9), transparent 68%),
    radial-gradient(38% 24% at 89% 9%,  rgba(9,17,30,.9),  transparent 70%),
    radial-gradient(46% 22% at 43% 43%, rgba(13,22,38,.72), transparent 72%),
    radial-gradient(64% 20% at 56% 78%, rgba(196,138,78,.24), transparent 74%),
    linear-gradient(180deg, #04070e 0%, #070d1a 22%, #0a1424 46%, #0e1a2b 66%, #121e2e 100%);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  transform: scale(1.04);
}

/* Second cloud layer, drifting slowly across the first. Two layers at
   different rates is what stops the deck reading as a flat gradient. */
.hero-storm {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .9;
  /* Lighter than the plate beneath, for the same reason: these are the
     lit tops and flanks of the cells, not shadows. */
  background:
    radial-gradient(28% 20% at 33% 21%, rgba(96,120,158,.26), transparent 70%),
    radial-gradient(24% 16% at 58% 13%, rgba(112,138,178,.22), transparent 72%),
    radial-gradient(32% 19% at 81% 25%, rgba(84,106,144,.24), transparent 70%),
    radial-gradient(22% 14% at 15% 36%, rgba(74,94,130,.18), transparent 72%),
    radial-gradient(30% 15% at 68% 37%, rgba(66,86,120,.16), transparent 74%);
  animation: fx-cloud-drift 52s linear infinite alternate;
}
@keyframes fx-cloud-drift {
  from { transform: translate3d(-1.6%, 0, 0) scale(1.02); }
  to   { transform: translate3d(1.6%, .7%, 0) scale(1.05); }
}

/* Sheet lightning inside the cell — never a bolt, never over the
   airframe. Screen-blended so it lights the cloud instead of washing a
   grey rectangle over it. Off for 88% of every cycle. */
.hero-lightning {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  mix-blend-mode: screen;
  background:
    radial-gradient(24% 18% at 69% 19%, rgba(214,230,255,.72), rgba(168,194,238,.2) 46%, transparent 72%),
    radial-gradient(48% 32% at 69% 23%, rgba(148,178,228,.18), transparent 76%);
  animation: fx-sheet-lightning 17s var(--ease) infinite;
}
@keyframes fx-sheet-lightning {
  0%, 88%  { opacity: 0; }
  88.6%    { opacity: .5; }
  89.6%    { opacity: .07; }
  90.4%    { opacity: .38; }
  92.5%    { opacity: 0; }
  100%     { opacity: 0; }
}

/* The tint is on the SKY PANEL only — the aircraft is a later sibling
   and sits above it. Retuned off violet onto navy and wine. */
.hero-photo-tint {
  opacity: .14;
  background:
    radial-gradient(58% 66% at 72% 20%, rgba(96,124,178,.55), transparent 62%),
    radial-gradient(56% 62% at 44% 90%, rgba(168,92,114,.45), transparent 60%);
}

/* Darkens the copy column so the headline holds contrast over weather. */
.hero-photo-fade {
  background:
    linear-gradient(90deg,
      rgba(5,9,18,.9) 0%,
      rgba(5,9,18,.7) 15%,
      rgba(5,9,18,.36) 31%,
      rgba(5,9,18,.1) 47%,
      transparent 61%),
    linear-gradient(180deg, rgba(5,9,18,.62) 0%, rgba(5,9,18,.15) 14%, transparent 28%),
    linear-gradient(0deg,  rgba(5,9,18,.82) 0%, rgba(5,9,18,.44) 12%, rgba(5,9,18,.12) 26%, transparent 40%);
}

/* The scan sweep goes: it was a sci-fi tell, and this hero is now
   supposed to read as weather. */
.hero-photo-panel::after { content: none; }

/* ── 15.2 The wet ramp ───────────────────────────────────────────── */

/* The band runs 418→720 in the 720px hero. Everything inside it is
   positioned against ONE number: the waterline at 42%, which is where
   the aircraft's gear meets the surface. Move the aircraft and this has
   to move with it, or the airframe floats again. */
.hero-ground {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 42%;
  z-index: 0;              /* under .hero-craft (z-index 1) */
  pointer-events: none;
  overflow: hidden;
  /* Fades out under the copy column: reflections behind the headline
     cost readability and buy nothing. */
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, rgba(0,0,0,.28) 18%, rgba(0,0,0,.8) 38%, #000 54%);
          mask-image: linear-gradient(90deg, transparent 0%, rgba(0,0,0,.28) 18%, rgba(0,0,0,.8) 38%, #000 54%);
}

.hero-ground-wet {
  position: absolute;
  inset: 0;
  background:
    /* Distant apron lighting sitting ON the waterline — the horizon the
       eye needs in order to read the lower half as a surface. */
    linear-gradient(180deg,
      transparent 0 40%,
      rgba(214,178,124,.16) 41%,
      rgba(150,178,214,.1) 42.6%,
      transparent 45%),
    /* The surface itself: reflective just below the line, sinking to the
       page ground at the bottom. */
    linear-gradient(180deg,
      transparent 0 41%,
      rgba(28,44,68,.5) 44%,
      rgba(12,21,36,.82) 60%,
      rgba(6,11,22,.95) 80%,
      #050912 100%);
}

/* Approach and taxiway lights smeared vertically in standing water.
   Two repeats at different pitches so the spacing does not read as a
   pattern, blurred because a reflection in moving water has no edge. */
/* Approach and taxiway lights smeared vertically in standing water.
   Starts AT the waterline — a reflection above it would be a light
   hanging in mid-air. */
.hero-ground-lights {
  position: absolute;
  left: 0;
  right: 0;
  top: 42%;
  bottom: 0;
  opacity: .9;
  filter: blur(3px);
  background:
    repeating-linear-gradient(90deg,
      transparent 0 40px, rgba(232,176,102,.3) 40px 44px, transparent 44px 99px),
    repeating-linear-gradient(90deg,
      transparent 0 134px, rgba(176,204,244,.18) 134px 137px, transparent 137px 266px);
  /* A reflection is brightest at its source and dissolves as it comes
     toward the viewer. */
  -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0,0,0,.45) 42%, transparent 86%);
          mask-image: linear-gradient(180deg, #000 0%, rgba(0,0,0,.45) 42%, transparent 86%);
}

/* Pools of apron light on the surface itself, weighted to the right
   where the aircraft and the terminal are. */
.hero-ground::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 41%;
  bottom: 0;
  background:
    radial-gradient(24% 60% at 76% 22%, rgba(230,176,102,.2), transparent 70%),
    radial-gradient(20% 50% at 93% 14%, rgba(208,160,94,.15), transparent 72%),
    radial-gradient(28% 56% at 57% 30%, rgba(150,180,222,.1), transparent 74%);
}

/* ── 15.3 The aircraft ───────────────────────────────────────────── */

/* Lower and larger than before, so it sits ON the ramp rather than
   floating over the middle of the plate. Still whole: both wingtips and
   the nose stay inside the viewport. */
/* top is the airframe's CENTRE (it is translated -50%). Worked back from
   the waterline: the band is 42% of a 720px hero, so the line sits at
   545px; the main gear is ~92% of the way down the cut-out; at 53% width
   the image is 268px tall. 545 - .92*268 = 303 top, +134 = 437 centre,
   which is 61% of the hero. Change the width or the band and this number
   has to be recomputed or the aircraft floats. */
.hero-craft {
  right: 1%;
  top: 61%;
  width: 53%;
  max-width: 1000px;
}

/* Warm ground bounce under the airframe plus a cool rim from the sky
   break. Replaces the sunset bloom, which no longer has a sun. */
.hero-craft-glow {
  background:
    radial-gradient(closest-side, rgba(226,172,104,.2), transparent 72%),
    radial-gradient(closest-side at 66% 74%, rgba(232,158,86,.16), transparent 66%),
    radial-gradient(closest-side at 40% 20%, rgba(160,190,232,.12), transparent 68%);
  filter: blur(30px);
}

/* Shadow cast down onto the wet surface, away from the apron lighting
   low and right. The airframe itself carries no filter. */
.hero-craft img {
  filter: drop-shadow(-10px 30px 38px rgba(2, 4, 12, .62));
}

/* Nearly still: the reference aircraft is on the deck, and a hovering
   airliner is the tell that gives away a pasted cut-out. */
@keyframes fx-cruise {
  from { transform: translate3d(0, -4px, 0) rotate(-.16deg); }
  to   { transform: translate3d(0, 5px, 0) rotate(.16deg); }
}
.hero-craft picture { animation-duration: 13s; }

/* ── 15.4 Hero copy ──────────────────────────────────────────────── */

/* "Flight" champagne, "Experience" muted rose — the reference's pairing.
   Both stay light tints; neither runs to the saturated core hue.

   background-clip is repeated here on purpose. These rules set the
   `background` SHORTHAND, which resets background-clip to border-box —
   so overriding only the colour silently turns the clipped text back
   into two solid rectangles with transparent glyphs punched out of them.
   That is exactly what it did until this line was added. */
.hero-heading .accent-gold,
.hero-heading .accent-violet {
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
}
.hero-heading .accent-gold {
  background: linear-gradient(96deg, var(--champagne) 8%, var(--gold) 92%);
  -webkit-background-clip: text;
          background-clip: text;
}
.hero-heading .accent-violet {
  background: linear-gradient(96deg, var(--violet-lt2) 6%, var(--violet-hi) 94%);
  -webkit-background-clip: text;
          background-clip: text;
}

.hero-pill {
  border-radius: var(--radius-pill);
  background: rgba(214,168,90,.08);
  border-color: rgba(214,168,90,.28);
}

/* Icons inside the two hero buttons, as in the reference. */
.btn-primary, .btn-ghost { display: inline-flex; align-items: center; gap: 9px; }
.btn-ico { flex-shrink: 0; }

.hero-btns .btn-ghost {
  background: rgba(11,18,34,.55);
  border: 1px solid rgba(199,206,222,.18);
}
.hero-btns .btn-ghost:hover { border-color: var(--line-gold); }

/* Trustline: star row over the customer line, avatars to their left. */
.hero-trustline { align-items: center; gap: 13px; }
.hero-trust-lines { display: flex; flex-direction: column; gap: 3px; }
.ht-row { display: flex; align-items: center; gap: 9px; }
.ht-stars { display: inline-flex; gap: 1.5px; color: var(--gold); line-height: 0; }
.ht-star.is-off { color: rgba(199,206,222,.24); }
.ht-score { font-size: .82rem; color: var(--text-2); font-weight: 500; }
.ht-sub   { font-size: .8rem;  color: var(--text-3); }

/* ── 15.5 One benefits card, not three ───────────────────────────── */

/* The reference floats a single glass card with three ruled rows. It was
   built here as three detached cards, which read as three notifications
   rather than one promise. */
.hero-panels {
  top: 112px;
  width: 258px;
  gap: 0;
  padding: 5px;
  border-radius: 16px;
  background: rgba(9,17,31,.72);
  -webkit-backdrop-filter: blur(20px) saturate(145%);
          backdrop-filter: blur(20px) saturate(145%);
  border: 1px solid rgba(214,168,90,.26);
  box-shadow:
    0 20px 54px rgba(2,4,10,.55),
    inset 0 1px 0 rgba(255,255,255,.05);
}
.hero-panel {
  background: none;
  border: 0;
  border-radius: 11px;
  box-shadow: none;
  padding: 12px 12px;
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
}
.hero-panel + .hero-panel { border-top: 1px solid rgba(199,206,222,.09); }
.hero-panel:hover {
  transform: none;
  background: rgba(214,168,90,.06);
  box-shadow: none;
}

/* ── 15.6 Navigation ─────────────────────────────────────────────── */

/* Inline search pill, as in the reference, replacing the magnifier that
   dropped a full-width panel. */
.nav-search {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 38px;
  /* Sized against what is actually left over. The bar is a three-column
     grid (brand | links | actions) capped at 1240px: brand takes ~250,
     the six links ~420, and Login+Register+cart ~230. A 268px pill blew
     that budget and the links column, which had no min-width, overflowed
     underneath it — "About Us" rendered through the pill. */
  width: clamp(150px, 14vw, 218px);
  padding: 0 6px 0 13px;
  border-radius: var(--radius-pill);
  background: rgba(199,206,222,.05);
  border: 1px solid var(--line);
  transition: border-color var(--t), background var(--t);
}
.nav-search:focus-within {
  border-color: var(--line-gold);
  background: rgba(214,168,90,.06);
}
.nav-search .ns-icon { color: var(--text-3); flex-shrink: 0; }
.nav-search input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: none;
  color: var(--text);
  font-family: inherit;
  font-size: .82rem;
}
.nav-search input::placeholder { color: var(--text-3); }
/* The clear button only earns its space once there is something to
   clear; :placeholder-shown is true exactly while the field is empty. */
.nav-search .search-close {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--text-3);
  font-size: .72rem;
  cursor: pointer;
  opacity: 1;
  transition: color var(--t), background var(--t);
}
.nav-search .search-close:hover { color: var(--text); background: rgba(199,206,222,.08); }
.nav-search input:placeholder-shown ~ .search-close { visibility: hidden; }

/* The magnifier is the small-screen affordance only. */
.nav-search-toggle { display: none; }

.nav-actions { gap: 10px; }

/* A grid track at 1fr still refuses to shrink below its content unless
   it is told it may. Without this the links push into the actions
   column instead of tightening their own spacing. */
.nav-links { min-width: 0; }
.nav-inner { max-width: 1320px; }

/* Cart badge: the reference rides a small crimson count on the icon —
   crimson and not champagne, because gold is this page's "act now"
   colour and a count is a status, not an offer. It is always rendered;
   at zero it steps back to a hairline outline rather than vanishing. */
.cart-btn .cart-count {
  opacity: 1;
  transform: none;
  background: #C6343F;
  color: #fff;
  font-weight: 700;
  border: 1.5px solid var(--ink);
  box-shadow: 0 2px 8px rgba(150,26,38,.5);
}
.cart-btn .cart-count.is-empty {
  background: rgba(199,206,222,.14);
  color: var(--text-3);
  box-shadow: none;
}

/* Signed-in chip: avatar, first name, caret — one pill, as in the
   reference. api.js renders the markup; this only dresses it. */
.nav-auth { display: flex; align-items: center; gap: 8px; }
.nav-user-btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 38px;
  padding: 0 13px 0 6px;
  border-radius: var(--radius-pill);
  background: rgba(199,206,222,.05);
  border: 1px solid var(--line);
  color: var(--text);
  font-size: .82rem;
  font-weight: 500;
  text-decoration: none;
  transition: border-color var(--t), background var(--t);
}
.nav-user-btn:hover { border-color: var(--line-gold); background: rgba(214,168,90,.06); }
.nav-user-btn .nav-avatar {
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: linear-gradient(140deg, var(--gold), var(--gold-deep));
  color: var(--on-gold);
  font-size: .66rem;
  font-weight: 700;
  letter-spacing: .02em;
}
.nav-user-btn::after {
  content: '';
  width: 7px;
  height: 7px;
  margin-left: 1px;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  opacity: .5;
}

/* ── 15.7 Featured row ───────────────────────────────────────────── */

.featured-grid { grid-template-columns: repeat(4, 1fr); }

/* Heading gets the reference's gold plane glyph. The dash that used to
   trail the title would now collide with it, so it goes. */
.section-head-title { display: flex; align-items: flex-start; gap: 13px; }
.section-head-ico {
  flex-shrink: 0;
  margin-top: 3px;
  color: var(--gold);
}
.section-title-sm::after { content: none; }

/* Save button, top-right of the card image — mirrors the badge. */
.pcard-save {
  position: absolute;
  right: 10px;
  top: 10px;
  z-index: 2;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(199,206,222,.16);
  background: rgba(5,9,18,.6);
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
  color: var(--text-2);
  cursor: pointer;
  transition: color var(--t), border-color var(--t), background var(--t), transform var(--t);
}
.pcard-save:hover { color: var(--violet-lt); border-color: rgba(168,92,114,.5); transform: scale(1.07); }
.pcard-save.is-on {
  color: var(--violet);
  border-color: rgba(168,92,114,.55);
  background: rgba(168,92,114,.14);
}
.pcard-save.is-on svg { fill: currentColor; }

.pcard-media { position: relative; }

/* Card lift, as specified: 4px, 300ms, with the photograph easing in. */
.product-card { transition: transform .3s var(--ease), border-color .3s var(--ease), box-shadow .3s var(--ease); }
.product-card:hover { transform: translateY(-4px); }
.pcard-media img { transition: transform .45s var(--ease); }
.product-card:hover .pcard-media img { transform: scale(1.05); }

/* ── The trust band ──────────────────────────────────────────────────
   This panel was drawn for a 340px sidebar. Given the full container it
   kept its 340px min-height and its 132%-wide Earth limb, and rendered
   as a tall slab with a planet filling it. Re-proportioned for a band:
   title left, the four figures in a row right, and the limb reduced to
   a horizon arc across the top. */
.globe-section { padding: 0 0 40px; }
.globe-section .featured-layout { grid-template-columns: minmax(0, 1fr); }

.globe-section .globe-panel {
  min-height: 0;
  padding: 26px 30px;
  justify-content: center;
  background: linear-gradient(120deg, rgba(17,27,46,.85) 0%, rgba(11,18,34,.9) 55%, rgba(6,10,20,.94) 100%);
}
/* Pushed further down and made much fainter: at 78% wide and a third of
   the way up it read as a dark wedge across the right of the band, not
   as a horizon. */
.globe-section .globe-sphere {
  top: auto;
  bottom: -26%;
  width: 120%;
  opacity: .32;
}
/* The limb's hard edge cut a visible diagonal straight through the row
   of figures. In a band this shallow the arc reads as a scratch, not as
   a horizon, so only its soft inner glow is kept. */
.globe-section .globe-terminator { display: none; }
.globe-section .globe-sphere {
  background: radial-gradient(circle at 62% 18%, rgba(150,176,220,.16) 0%, rgba(38,58,96,.1) 38%, transparent 62%);
  box-shadow: none;
}

/* .globe-content has three children — title, rule, stats — and a plain
   two-column grid auto-placed them title | rule / stats, which put the
   gold dash in the middle of the band and the figures under the heading.
   Named areas pin each one where it belongs. */
.globe-section .globe-content {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas:
    'title stats'
    'rule  stats';
  align-items: center;
  gap: 6px 44px;
}
.globe-section .globe-title { grid-area: title; margin-bottom: 0; align-self: end; }
.globe-section .globe-rule  { grid-area: rule;  margin-bottom: 0; align-self: start; }
.globe-section .globe-stats {
  grid-area: stats;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px 22px;
}
/* The rose pair reads as a second accent in a row of four; on one line
   they just look like two of them failed to load the gold. */
.globe-section .globe-stat .globe-stat-num {
  background: linear-gradient(120deg, var(--champagne), var(--gold));
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
}

@media (max-width: 860px) {
  .globe-section .globe-content {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: 'title' 'rule' 'stats';
    gap: 8px;
  }
  .globe-section .globe-rule { margin-bottom: 14px; }
  .globe-section .globe-stats { grid-template-columns: repeat(2, 1fr); }
}

/* ── 15.8 Newsletter bar ─────────────────────────────────────────── */

.nl-bar {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) auto auto;
  align-items: center;
  gap: 28px;
  text-align: left;
  padding: 22px 26px;
  /* style.css caps .newsletter-glass at 680px, which was right for the
     old centred column. Three columns do not fit in it: the two auto
     tracks (buttons ~380px, follow ~250px) ate the whole 628px of inner
     width and the copy column collapsed to nothing, so the buttons
     rendered on top of the paragraph. */
  max-width: none;
}
.nl-lead { display: flex; align-items: flex-start; gap: 15px; }
.nl-icon {
  flex-shrink: 0;
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  background: rgba(214,168,90,.1);
  border: 1px solid var(--line-gold);
  color: var(--gold);
}
.nl-bar .nl-heading { font-size: 1.22rem; margin-bottom: 5px; }
.nl-bar .nl-text { font-size: .84rem; margin: 0; max-width: 46ch; }
.nl-bar .nl-actions { margin: 0; display: flex; gap: 10px; flex-wrap: wrap; }
.nl-bar .btn-primary, .nl-bar .btn-ghost { padding: 11px 20px; font-size: .84rem; }

.nl-follow {
  display: flex;
  align-items: center;
  gap: 13px;
  padding-left: 26px;
  border-left: 1px solid var(--line);
}
.nl-follow-label { font-size: .8rem; color: var(--text-3); white-space: nowrap; }
.nl-follow .footer-socials { display: flex; gap: 8px; margin: 0; }

/* ── 15.9 Responsive ─────────────────────────────────────────────── */

/* Wider airframe means a taller one, so its centre rises to keep the
   gear on the same waterline. */
@media (max-width: 1400px) {
  .hero-craft { width: 55%; right: 0; top: 60.5%; }
}

@media (max-width: 1240px) {
  .hero-craft { width: 58%; right: -1%; top: 60%; }
  .hero-panels { width: 236px; top: 104px; }
  .nl-bar { grid-template-columns: minmax(0, 1fr) auto; row-gap: 20px; }
  .nl-follow { grid-column: 1 / -1; padding-left: 0; border-left: 0; border-top: 1px solid var(--line); padding-top: 18px; }
}

@media (max-width: 1180px) {
  .featured-grid { grid-template-columns: repeat(3, 1fr); }
  /* The fourth card would be a lone orphan on the second row. */
  .featured-grid > .product-card:nth-child(4) { display: none; }
}

/* The inline pill costs more width than the bar has once the nav links
   need room; below this it folds back behind the magnifier. */
@media (max-width: 1080px) {
  .nav-search {
    position: absolute;
    top: calc(100% + 8px);
    right: 24px;
    width: min(340px, calc(100vw - 48px));
    height: 42px;
    z-index: 60;
    background: rgba(9,17,31,.96);
    -webkit-backdrop-filter: blur(18px);
            backdrop-filter: blur(18px);
    box-shadow: var(--shadow);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity var(--t), transform var(--t), visibility var(--t);
  }
  .nav-search.open { opacity: 1; visibility: visible; transform: none; }
  .nav-search-toggle { display: grid; }
}

@media (max-width: 900px) {
  .featured-grid { grid-template-columns: repeat(2, 1fr); }
  .featured-grid > .product-card:nth-child(4) { display: block; }
}

@media (max-width: 860px) {
  /* Stacked hero: the ramp becomes a base under the aircraft band rather
     than a strip across the bottom of a section that no longer has one. */
  .hero-ground {
    height: 26%;
    -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0,0,0,.5) 70%, transparent 100%);
            mask-image: linear-gradient(180deg, #000 0%, rgba(0,0,0,.5) 70%, transparent 100%);
  }
  .hero-craft { width: 100%; right: auto; top: auto; }
  /* The benefits card stops floating and becomes a block under the copy,
     full width, still one card. */
  .hero-panels {
    position: static;
    width: auto;
    margin: 22px 0 0;
    top: auto;
    right: auto;
  }
  .hero-inner { flex-direction: column; }
  .nl-bar { grid-template-columns: minmax(0, 1fr); }
  .nl-bar .nl-actions { grid-column: 1; }
}

@media (max-width: 560px) {
  /* Overrides the older rule that hid the magnifier outright — with the
     pill collapsed at this width, hiding it too removes search entirely. */
  #searchToggle { display: grid; }
  .featured-grid { grid-template-columns: 1fr; }
  .hero-panels { flex-direction: column; }
  .nl-lead { flex-direction: column; gap: 12px; }
  .nl-bar .nl-actions { flex-direction: column; align-items: stretch; }
  .nl-bar .btn-primary, .nl-bar .btn-ghost { justify-content: center; }
  .ht-row { flex-wrap: wrap; gap: 6px; }
}

/* Weather is decoration. Anyone who has asked the OS to stop moving
   things gets a still, lit ramp — not a frozen blank one. */
@media (prefers-reduced-motion: reduce) {
  .hero-storm, .hero-lightning, .hero-craft picture { animation: none !important; }
  .hero-lightning { opacity: .1; }
}


/* ═══════════════════════════════════════════════════════════════════
   16. THE REFERENCE HERO — one photograph, furnished at its edges
   ═══════════════════════════════════════════════════════════════════

   Section 15 built the hero as three synthetic layers: a painted storm
   deck, a painted wet ramp, and a cut-out airframe floating between
   them. It was carefully done, but it was always going to lose to the
   thing it was imitating, because a composite has to keep three light
   sources agreeing and a photograph gets that for free.

   So the plate is now a single exposure — a widebody rotating off a wet
   runway at sunset, city skyline behind, terminal and apron lighting to
   one side. It is /assets/hero-sunset.jpg, already in this repo and
   already shipped as the store's own artwork.

   It is MIRRORED. In the source the aircraft climbs to the upper left,
   which puts the cockpit exactly where the headline goes; flipped, it
   climbs to the upper right and the whole left third opens up for type,
   which is the reference's composition. The cost of the flip is that the
   sun break travels to the left with everything else, and the scrim
   below is tuned to pay it: heavy at the left edge, gone by 58%.

   Three rules govern what may sit on the frame:

   1. The centre-right is untouchable. Airframe, engines and the sun
      break carry no text, no panel and no scrim — that region is the
      only reason to run a photograph at all.
   2. Furniture lives in the corners and along the bottom edge. Place
      caption top-right, signature mid-right, runway board bottom-left,
      trust strip and foot rule across the bottom.
   3. Anything laid over the photograph is either hairline-ruled glass
      or plain letter-spaced caps. No filled cards, which is what turned
      the previous hero's benefit list into three floating notifications.
   ═══════════════════════════════════════════════════════════════════ */

/* ── 16.1 The frame ─────────────────────────────────────────────── */

.hero {
  /* Tall enough to be cinematic, capped so a 1440x1080 monitor does not
     get a hero the visitor has to scroll to finish reading. The bottom
     padding is not decoration: it is the room the trust strip and the
     foot rule occupy, both of which are positioned against the bottom
     edge. Shrink it and the copy collides with them. */
  min-height: min(100vh, 902px);
  /* The bottom padding is not decoration: it is the room the runway
     board (196-242px up), the trust strip (96-172px up) and the foot
     rule occupy, all of which are positioned against the bottom edge.
     296 rather than 246 because on a short viewport the hero stops
     being taller than its content and starts being sized BY it — the
     copy then reaches the bottom of its box, and at 246 the runway
     board landed 4px under the trustline. Verified at 1440x700. */
  padding: 104px 0 296px;
  display: flex;
  align-items: center;
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

/* Full-bleed, behind everything, and NOT masked. Section 15's plate was
   masked down its left edge because it was a 66%-wide panel that had to
   dissolve into the page; this one is the page. */
.hero-plate {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

.hero-photo {
  position: absolute;
  inset: 0;
  background-image: url('/assets/hero-sunset.jpg');
  /* `cover`, and it has to stay `cover`. At a 16:10-ish frame this
     2400x1500 file fits almost exactly, so the whole photograph shows:
     nose, both engines, the gear, the city skyline and the wet runway.
     An earlier pass oversized it to 128% to buy slack for
     background-position and cropped straight into the wing — it bought
     a headline some clear sky and threw away everything that makes the
     shot worth running. The headline's contrast is the scrim's job,
     below, not the crop's. */
  background-size: cover;
  /* Read these against the FILE, not the screen: the mirror below flips
     the result, so a crop taken from the source's right arrives on the
     left. They only bite on frames narrower or taller than the file's
     3:2 — at desktop widths there is no slack to spend. */
  background-position: 60% 45%;
  background-repeat: no-repeat;

  /* Order matters. The translate is applied in screen space and must
     come first, or the mirror would send the parallax the wrong way.
     fx.js writes --sx/--sy rather than the whole transform, exactly as
     it already does for other transformed layers — an inline transform
     from JS would silently drop the scaleX(-1) and un-mirror the shot. */
  transform: translate3d(var(--sx, 0px), var(--sy, 0px), 0) scale(1.03) scaleX(-1);
  /* The plate grades magenta out of the box and the reference is gold.
     A small negative hue rotation walks the sunset off violet and onto
     amber without touching the airframe's white, and the brightness lift
     is what keeps the fuselage from going to silhouette once the scrim
     below lands on it. */
  filter: saturate(1.1) contrast(1.05) brightness(1.07) hue-rotate(-20deg);
  will-change: transform;
}

/* Scrim. The left-to-right ramp is the load-bearing one; the rest are
   local pools that buy the four pieces of edge furniture the contrast
   they need, because each of them can land on lit metal depending on
   where the crop falls at a given viewport width. Every pool is a soft
   radial rather than a panel — the reference darkens the sky behind its
   captions, it does not put them in boxes. */
.hero-photo-fade {
  position: absolute;
  inset: 0;
  background:
    /* Behind the place caption, top right. Deep, because at desktop
       widths this corner is lit fuselage, which is the brightest thing
       in the exposure — a light scrim there is no scrim at all. */
    radial-gradient(40% 36% at 97% 11%, rgba(4,7,15,.86), rgba(4,7,15,.4) 52%, transparent 76%),
    /* behind the signature, mid right */
    radial-gradient(30% 26% at 96% 60%, rgba(4,7,15,.72), transparent 76%),
    /* the copy column */
    linear-gradient(90deg,
      rgba(4,7,15,.94) 0%,
      rgba(4,7,15,.88) 14%,
      rgba(4,7,15,.7) 27%,
      rgba(4,7,15,.44) 40%,
      rgba(4,7,15,.16) 52%,
      transparent 62%),
    linear-gradient(180deg, rgba(4,7,15,.8) 0%, rgba(4,7,15,.26) 12%, transparent 26%),
    linear-gradient(0deg,  rgba(4,7,15,.9) 0%, rgba(4,7,15,.6) 12%, rgba(4,7,15,.2) 24%, transparent 38%);
}

/* Pulls the exposure onto the site's axis. Screen, so it adds light
   rather than greying the photograph down: champagne into the sun break
   the aircraft is climbing out of, one cool note in the upper corner so
   the frame is not uniformly warm. */
.hero-photo-tint {
  position: absolute;
  inset: 0;
  mix-blend-mode: screen;
  opacity: .16;
  background:
    radial-gradient(46% 52% at 34% 58%, rgba(255,186,110,.55), transparent 66%),
    radial-gradient(40% 44% at 78% 84%, rgba(214,172,99,.4), transparent 68%),
    radial-gradient(48% 40% at 84% 12%, rgba(138,116,196,.34), transparent 70%);
}

/* Section 15's furniture is gone from the markup; these keep any cached
   copy of the old page from painting a second aeroplane over this one. */
.hero-craft, .hero-ground, .hero-storm, .hero-lightning, .hero-panels { display: none; }

/* ── 16.2 Copy column ───────────────────────────────────────────── */

.hero-inner {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 1560px;
  margin: 0 auto;
  padding: 0 clamp(24px, 3.2vw, 54px);
  display: flex;
  align-items: center;
}
.hero-content {
  max-width: 40rem;
  padding: 0;
  margin: 0;
  text-align: left;
}

/* The eyebrow is plain letter-spaced caps with dot separators, not a
   pill. A bordered badge here competes with the trust strip's glass at
   the other end of the frame; caps do not compete with anything. */
.hero-eyebrow {
  display: flex;
  align-items: center;
  gap: 13px;
  margin: 0 0 22px;
  color: var(--champagne);
  font-size: .705rem;
  font-weight: 600;
  letter-spacing: .215em;
  text-transform: uppercase;
  text-shadow: 0 1px 16px rgba(4,7,15,.9);
}
.hero-eyebrow i {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: currentColor;
  opacity: .75;
}

.hero-heading {
  font-size: clamp(3rem, 5.4vw, 5.15rem);
  line-height: .99;
  letter-spacing: -.024em;
  margin-bottom: 0;
  text-shadow: 0 2px 40px rgba(4,7,15,.8);
}

/* The rule between headline and subhead. Short, champagne, and the only
   horizontal mark in the copy column — it is what stops the four stacked
   text blocks reading as one undifferentiated paragraph. */
.hero-rule {
  display: block;
  width: 58px;
  height: 1px;
  margin: 26px 0 22px;
  background: linear-gradient(90deg, var(--gold), rgba(214,172,99,0));
}

.hero-sub {
  font-size: 1.035rem;
  line-height: 1.66;
  color: var(--text-2);
  margin-bottom: 32px;
  max-width: 34rem;
  text-shadow: 0 1px 20px rgba(4,7,15,.92);
}

.hero-btns { gap: 13px; margin-bottom: 30px; }
.hero-btns .btn-primary { padding: 15px 28px; font-size: .93rem; }
.hero-btns .btn-ghost   { padding: 14px 26px; font-size: .93rem; }

/* Trustline back to ONE row, as in the reference: avatars, the customer
   line, a single star, the score. Section 15 stacked it into two lines,
   which made a four-word claim occupy the height of a paragraph. */
.hero-trustline { align-items: center; gap: 14px; }
.hero-trust-lines {
  display: flex;
  /* Explicit. Section 15 set column on this element and a rule that only
     re-declares `display: flex` inherits it — which is why the line kept
     stacking into two after being rewritten as one. */
  flex-direction: row;
  align-items: center;
  gap: 15px;
  flex-wrap: wrap;
}
.ht-row { display: flex; align-items: center; gap: 7px; }
.ht-star-single { color: var(--gold); line-height: 0; flex-shrink: 0; }
.ht-score { font-size: .82rem; color: var(--text); font-weight: 500; white-space: nowrap; }
.ht-sub   { font-size: .82rem; color: var(--text-2); white-space: nowrap; }
/* Muted and dark. As bright pastels these read as four coloured bubbles
   competing with the champagne; at this weight they read as what they
   are — a placeholder for faces the store does not have. */
.hero-avatar { width: 28px; height: 28px; border-width: 2px; filter: saturate(.62) brightness(.72); }

/* ── 16.3 Place caption, top right ──────────────────────────────── */

.hero-place {
  position: absolute;
  z-index: 2;
  top: 118px;
  right: clamp(24px, 3.2vw, 54px);
  text-align: right;
  pointer-events: none;
  max-width: 15rem;
}
.hp-city {
  margin: 0 0 9px;
  color: var(--text);
  font-size: .935rem;
  font-weight: 500;
  letter-spacing: .34em;
  text-transform: uppercase;
  /* letter-spacing pads the right of the last glyph too, which visually
     un-aligns a right-aligned line from everything under it. */
  margin-right: -.34em;
  text-shadow: 0 1px 3px rgba(4,7,15,.95), 0 2px 20px rgba(4,7,15,.9);
}
.hp-airport {
  margin: 0 -.16em 26px 0;
  color: var(--text-2);
  font-size: .655rem;
  font-weight: 500;
  line-height: 1.85;
  letter-spacing: .16em;
  text-transform: uppercase;
  text-shadow: 0 1px 3px rgba(4,7,15,.95), 0 2px 16px rgba(4,7,15,.9);
}
.hp-route {
  margin: 0 -.2em 0 0;
  color: var(--text);
  text-shadow: 0 1px 3px rgba(4,7,15,.95), 0 2px 16px rgba(4,7,15,.9);
  font-size: .69rem;
  font-weight: 500;
  line-height: 1.8;
  letter-spacing: .2em;
  text-transform: uppercase;
}

/* ── 16.4 The signature ─────────────────────────────────────────── */

/* The airport's motto, written on the apron rather than boxed. Great
   Vibes for the city, caps for the line, a hairline between them. */
.hero-signature {
  position: absolute;
  z-index: 2;
  right: clamp(24px, 3.2vw, 54px);
  top: 56%;
  text-align: right;
  pointer-events: none;
}
.hs-script {
  display: block;
  font-family: 'Great Vibes', 'Instrument Serif', cursive;
  font-size: 2.55rem;
  line-height: 1;
  color: var(--champagne);
  text-shadow: 0 1px 4px rgba(4,7,15,.9), 0 2px 24px rgba(4,7,15,.8);
}
.hs-line {
  display: block;
  margin: 12px -.24em 0 0;
  padding-top: 11px;
  position: relative;
  color: var(--text-2);
  font-size: .64rem;
  font-weight: 500;
  line-height: 1.9;
  letter-spacing: .24em;
  text-transform: uppercase;
  text-shadow: 0 1px 3px rgba(4,7,15,.95), 0 2px 16px rgba(4,7,15,.9);
}
.hs-line::before {
  content: '';
  position: absolute;
  top: 0;
  right: .24em;
  width: 76px;
  height: 1px;
  background: linear-gradient(270deg, var(--line-gold), rgba(214,172,99,0));
}

/* ── 16.5 Runway designator board ───────────────────────────────── */

/* The real sign: retroreflective black panel, numerals in runway
   orange, the direction letter partitioned off by a hairline. It is the
   one object on the frame allowed to be a solid block, because the real
   one is a solid block. */
.hero-rwy {
  position: absolute;
  z-index: 2;
  left: clamp(24px, 3.2vw, 54px);
  bottom: 196px;
  display: flex;
  align-items: stretch;
  height: 46px;
  border-radius: 5px;
  overflow: hidden;
  background: #07090e;
  border: 1px solid rgba(199,206,222,.16);
  box-shadow: 0 10px 30px rgba(2,4,10,.6), inset 0 1px 0 rgba(255,255,255,.06);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
.rwy-num, .rwy-dir {
  display: grid;
  place-items: center;
  min-width: 52px;
  padding: 0 13px;
  font-size: 1.42rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: .02em;
}
.rwy-num { color: #F2A03C; }
.rwy-dir { color: #E8ECF6; border-left: 1px solid rgba(199,206,222,.2); }

/* ── 16.6 Trust strip, lying on the photograph ──────────────────── */

/* Was a band under the hero with a negative top margin pulling it up.
   Now it is inside the frame and positioned against its bottom edge, so
   it sits ON the runway the way the reference does. */
.hero .trust-strip {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: 96px;
  padding: 0 clamp(24px, 3.2vw, 54px);
  margin: 0;
}
.hero .trust-strip-inner {
  max-width: 1560px;
  margin: 0 auto;
  border: 1px solid rgba(199,206,222,.10);
  border-radius: 13px;
  background: rgba(6,10,20,.62);
  -webkit-backdrop-filter: blur(22px) saturate(135%);
          backdrop-filter: blur(22px) saturate(135%);
  box-shadow: 0 18px 46px rgba(2,4,10,.42), inset 0 1px 0 rgba(255,255,255,.045);
}
.hero .trust-cell {
  gap: 15px;
  padding: 19px 30px;
  border-right: 1px solid rgba(199,206,222,.09);
}
/* Circular, unfilled and hairline — the reference's icon treatment. The
   squared gold tiles read as buttons, and nothing here is clickable. */
.hero .trust-cell-icon {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 1px solid rgba(214,172,99,.3);
  background: rgba(214,172,99,.05);
}
.hero .trust-cell-title { font-size: .875rem; margin-bottom: 2px; }
.hero .trust-cell-sub   { font-size: .765rem; }

/* ── 16.7 The foot rule ─────────────────────────────────────────── */

.hero-footbar {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: 18px;
  padding: 0 clamp(24px, 3.2vw, 54px);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
}
.hf-tag, .hf-sim {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 14px;
  color: var(--text-3);
  text-shadow: 0 1px 12px rgba(4,7,15,.9);
  font-size: .625rem;
  font-weight: 600;
  letter-spacing: .21em;
  text-transform: uppercase;
  white-space: nowrap;
}
.hf-sim { justify-content: flex-end; color: var(--text-2); }
.hf-sim svg { color: var(--text-3); flex-shrink: 0; }
/* Each outer label trails (or leads) a rule that runs toward the centre,
   which is what makes the three items read as one ruled line rather
   than three separate captions. */
.hf-tag::after, .hf-sim::before {
  content: '';
  flex: 1;
  min-width: 30px;
  height: 1px;
  background: linear-gradient(90deg, rgba(199,206,222,.22), rgba(199,206,222,0));
}
.hf-sim::before { background: linear-gradient(270deg, rgba(199,206,222,.22), rgba(199,206,222,0)); }

.hf-scroll {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  color: var(--text-2);
  text-shadow: 0 1px 12px rgba(4,7,15,.9);
  transition: color var(--t);
}
.hf-scroll:hover { color: var(--champagne); }
.hf-scroll-label {
  font-size: .625rem;
  font-weight: 600;
  letter-spacing: .21em;
  text-transform: uppercase;
}
.hf-mouse {
  width: 17px;
  height: 26px;
  border-radius: 9px;
  border: 1px solid rgba(199,206,222,.42);
  display: grid;
  justify-items: center;
  padding-top: 5px;
}
.hf-scroll:hover .hf-mouse { border-color: var(--line-gold); }
.hf-mouse i {
  width: 2px;
  height: 5px;
  border-radius: 1px;
  background: currentColor;
  animation: fx-scroll-dot 1.9s var(--ease) infinite;
}
@keyframes fx-scroll-dot {
  0%, 100% { transform: translateY(0);   opacity: 1; }
  55%      { transform: translateY(7px); opacity: .15; }
}

/* ── 16.8 Responsive ────────────────────────────────────────────── */

@media (max-width: 1280px) {
  .hero-heading { font-size: clamp(2.8rem, 5.2vw, 4.3rem); }
  .hero-content { max-width: 33rem; }
  .hero-signature { top: 58%; }
  .hs-script { font-size: 2.15rem; }
  .hero .trust-cell { padding: 18px 22px; }
}

@media (max-width: 1040px) {
  /* The place caption and the signature are the first things to go: they
     are atmosphere, and at this width they start landing on the wing. */
  .hero-place, .hero-signature { display: none; }
  .hero-content { max-width: 30rem; }
  .hero .trust-cell { padding: 16px 18px; gap: 12px; }
  .hero .trust-cell-icon { width: 38px; height: 38px; }
  .hero .trust-cell-sub { font-size: .72rem; }
}

@media (max-width: 900px) {
  /* Below this the strip cannot hold four columns without the labels
     wrapping mid-phrase, so it folds to two rows of two. The frame grows
     to make room rather than the copy shrinking. */
  .hero { padding-bottom: 290px; }
  .hero .trust-strip-inner { grid-template-columns: repeat(2, 1fr); }
  .hero .trust-cell:nth-child(2n) { border-right: none; }
  .hero .trust-cell:nth-child(-n+2) { border-bottom: 1px solid rgba(199,206,222,.09); }
  .hero-rwy { bottom: 290px; }
}

@media (max-width: 860px) {
  /* theme.css turns the hero into a stacked block at this width for the
     old split layout. This hero is a single photograph and stays one:
     the flex frame is restored, the plate keeps its cover fit, and the
     copy simply gets the whole width. */
  .hero {
    display: flex;
    min-height: min(100vh, 760px);
    padding: 96px 0 286px;
  }
  .hero-plate { position: absolute; inset: 0; width: auto; height: auto; }
  .hero-photo {
    /* Portrait-ish viewports need the aircraft pulled toward the centre
       or the cover crop leaves only sky beside the copy. */
    background-position: 64% 44%;
    transform: scale(1.04) scaleX(-1);
  }
  /* With the copy running the full width, a scrim that clears at 58%
     leaves the subhead and the trustline sitting on lit fuselage — the
     brightest thing in the exposure. Two ramps: a vertical one carrying
     the whole frame, and a lighter horizontal one that still favours the
     side the type is on, so the aircraft keeps some contrast of its own
     instead of the frame going uniformly grey. */
  .hero-photo-fade {
    background:
      linear-gradient(180deg,
        rgba(4,7,15,.9) 0%, rgba(4,7,15,.74) 34%, rgba(4,7,15,.46) 62%, rgba(4,7,15,.8) 100%),
      linear-gradient(90deg,
        rgba(4,7,15,.5) 0%, rgba(4,7,15,.22) 52%, transparent 84%);
  }
  /* Back to a row. Section 12 turns .hero-inner into a COLUMN at this
     width, which combined with the base `align-items: center` centred
     the copy on the cross axis — that is where the mysterious 148px
     left offset at 820 came from, not from any margin. The column was
     there to stack the old cut-out aircraft under the copy; this hero
     has one child and nothing to stack. */
  .hero-inner { flex-direction: row; align-items: center; padding: 0 24px; }
  /* Older sheets also centre this block and stack its buttons full-width
     from 860 down. That was written for a hero whose photograph became a
     band ABOVE the copy — centred type made sense under a centred
     picture. This hero keeps the photograph behind the copy at every
     width, so the copy stays left, as on the desktop frame. */
  .hero-content { max-width: 100%; margin: 0; text-align: left; }
  .hero-heading { font-size: clamp(2.6rem, 8.2vw, 3.4rem); }
  .hero-btns { flex-direction: row; align-items: center; }
  .hero-btns .btn-primary,
  .hero-btns .btn-ghost { width: auto; text-align: left; }

  /* The foot rule folds to one line. Stacked into three rows it stood
     107px tall and ran straight up through the trust strip — measured,
     not guessed: at 820 the strip ended at y749 and the footbar started
     at y721. The scroll cue lies down beside the tagline instead, and
     "Microsoft Flight Simulator" is the piece that goes, being the one
     thing the page states again in its own footer. */
  .hero-footbar { grid-template-columns: 1fr auto; gap: 18px; }
  .hf-sim { display: none; }
  .hf-tag::after { display: none; }
  .hf-scroll { flex-direction: row; align-items: center; gap: 10px; }

  /* Two rules already claim the bottom-left; a third object there is a
     pile, not a composition. */
  .hero-rwy { display: none; }
}

@media (max-width: 600px) {
  /* 316 is the trust strip's own height at two rows (208) plus the room
     the foot rule and the gaps need under it. It is the number that
     keeps the copy off the strip — shrink it and they meet. */
  .hero { padding: 88px 0 316px; min-height: 0; }
  .hero-eyebrow { gap: 9px; font-size: .62rem; letter-spacing: .16em; }
  .hero-heading { font-size: clamp(2.3rem, 10vw, 2.9rem); }
  .hero-sub { font-size: .95rem; }
  .hero-sub br { display: none; }
  .hero-btns { flex-direction: column; align-items: stretch; }
  .hero-btns .btn-primary, .hero-btns .btn-ghost { width: 100%; justify-content: center; }
  .hero-trust-lines { gap: 6px 14px; }
  .ht-sub, .ht-score { white-space: normal; }
  .hero .trust-strip { bottom: 76px; }
  .hero .trust-cell { padding: 14px 14px; }
  .hero .trust-cell-icon { width: 34px; height: 34px; }
  .hero .trust-cell-title { font-size: .8rem; }
  .hero .trust-cell-sub { font-size: .68rem; }
  /* At 342px of usable width the tagline and the scroll cue cannot share
     a line without one of them hyphenating. The cue is the one that does
     something, so the tagline goes. */
  .hero-footbar { grid-template-columns: 1fr; justify-items: center; }
  .hf-tag { display: none; }
}

/* ── 16.9 Light build and reduced motion ────────────────────────── */

body.fx-lite .hero .trust-strip-inner {
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
  background: rgba(6,10,20,.9);
}

@media (prefers-reduced-motion: reduce) {
  /* The mirror is layout, not motion — restate the whole transform or
     the still frame renders the aircraft flying backwards. */
  .hero-photo { transform: scale(1.04) scaleX(-1) !important; }
  .hf-mouse i { animation: none !important; }
}
