/* FlightProof English homepage — homepage-only Instrument layer.
   Loaded after brand.css; country-guide pages never load this file. */
body.fp-home {
  --fp-home-navy: #1a1a2e;
  --fp-home-amber: #FFE66D;
  --fp-home-paper: #ece8df;
  --fp-home-edge: #d7d2c2;
  --fp-home-dim: #67624f;
  background: var(--fp-home-paper) !important;
  color: var(--fp-home-navy) !important;
  font-family: 'DM Sans', system-ui, sans-serif !important;
}
body.fp-home .wrap {
  width: min(100%, 1220px);
  max-width: 1220px;
  padding-inline: clamp(12px, 2.6vw, 28px);
}
body.fp-home .inst-doc {
  display: flex;
  flex-direction: column;
  max-width: 1180px !important;
  margin: clamp(10px, 2vw, 24px) auto clamp(30px, 5vw, 64px) !important;
  background: rgba(255, 255, 255, .9) !important;
  border: 1px solid var(--fp-home-edge) !important;
  border-radius: 12px !important;
  box-shadow: 0 24px 60px -34px rgba(26, 26, 46, .42) !important;
  overflow: hidden;
}
body.fp-home .inst-strip {
  --i-navy: var(--fp-home-navy);
  --i-amber: var(--fp-home-amber);
  background: rgba(255, 255, 255, .94) !important;
  border-bottom: 1px solid var(--fp-home-edge) !important;
  box-shadow: 0 8px 24px -22px rgba(26, 26, 46, .5);
}

/* Transparent-yellow destination band. */
body.fp-home .inst-band {
  order: 0;
  position: relative;
  /* WHY A MAX-WIDTH. Owner 2026-10-25: "the header is full weight and content
     looks like 80% — match the header with page content so don't make the
     yellow box so wide". The band was a body child with no cap, so it measured
     1423px at a 1440 viewport while every block below it is a centred column:
     the stats strip and the about section sit on 1100px (x=162..1262), the
     guide wall and footer on 1180. The band therefore read as a full-bleed
     header over an 80%-wide page.
     1100 is the column DIRECTLY beneath the hero — the stats strip — so the
     two edges now line up and the alignment is checkable at a glance. Radius
     stays 0: instrument.css calls the flush band part of the locked design, and
     an inset slab with a dashed perforation is still that ticket, not a card. */
  max-width: 1100px;
  margin-inline: auto;
  padding: clamp(22px, 3.2vw, 38px) clamp(18px, 4vw, 46px) clamp(18px, 2.8vw, 30px) !important;
  background: rgba(255, 230, 109, .88) !important;
  color: var(--fp-home-navy) !important;
  border-bottom: 2px dashed var(--fp-home-navy) !important;
  overflow: hidden;
}
body.fp-home .inst-band::before {
  content: "";
  position: absolute;
  width: 360px;
  height: 360px;
  right: -170px;
  top: -220px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .28);
  pointer-events: none;
}
body.fp-home .inst-band .kick {
  color: var(--fp-home-navy) !important;
  font: 800 12px/1.35 var(--i-mono, 'JetBrains Mono', monospace) !important;
  letter-spacing: .04em !important;
  text-transform: none !important;
}
body.fp-home .inst-band h1 {
  position: relative;
  max-width: 31ch !important;
  color: var(--fp-home-navy) !important;
  font: 900 clamp(27px, 4.2vw, 42px)/1.04 Outfit, 'DM Sans', sans-serif !important;
  letter-spacing: -.035em !important;
}
body.fp-home .inst-band p.dek {
  position: relative;
  max-width: 68ch !important;
  color: rgba(26, 26, 46, .78) !important;
  font: 600 15px/1.58 'DM Sans', sans-serif !important;
}
body.fp-home .inst-buy-first {
  position: relative;
  min-height: 48px;
  margin-top: 14px;
  padding: 11px 20px;
  border: 2px solid var(--fp-home-navy) !important;
  border-radius: 12px !important;
  background: var(--fp-home-navy) !important;
  color: var(--fp-home-amber) !important;
  font: 900 17px/1.1 Outfit, 'DM Sans', sans-serif !important;
  box-shadow: 4px 4px 0 rgba(26, 26, 46, .22) !important;
}
body.fp-home .inst-buy-first:hover,
body.fp-home .inst-buy-first:focus-visible {
  transform: translate(-1px, -1px) !important;
  box-shadow: 6px 6px 0 rgba(26, 26, 46, .18) !important;
  outline: 3px solid rgba(26, 26, 46, .25) !important;
  outline-offset: 3px;
}
body.fp-home .inst-readout {
  gap: 8px 12px;
  margin-top: 20px;
}
body.fp-home .inst-readout > span {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  min-height: 34px;
  padding: 7px 10px;
  border: 1px solid rgba(26, 26, 46, .2);
  border-radius: 7px;
  background: rgba(255, 255, 255, .34);
  color: rgba(26, 26, 46, .72) !important;
  font: 700 11px/1.35 'DM Sans', sans-serif !important;
  letter-spacing: 0 !important;
  text-transform: none !important;
}
body.fp-home .inst-readout b {
  color: var(--fp-home-navy) !important;
  font-family: var(--i-mono, 'JetBrains Mono', monospace) !important;
}

/* ---- brand motion: blue flies through the wordmark, distorts, loops ----
   Owner ask 2026-10-25: "animate the colors flying in blue and distorting and
   loop back." Two headers carry the wordmark on homepages — .inst-brand on 28
   homes, header.aph .fp-logo-word on the other 15 — so both are driven by the
   same pair of keyframes. Every 8s a blue light bar travels across (screen
   blend, so only the dark letters pick it up, never the white strip), while
   the letters split into chromatic ghosts and skew for a beat, then settle.
   The bar is clipped to the text box, so nothing leaks over the header. */
@keyframes fp-brand-sweep {
  0%, 40%   { transform: translateX(-160%) skewX(-16deg); opacity: 0; }
  46%       { opacity: .9; }
  62%       { transform: translateX(280%) skewX(-16deg); opacity: .9; }
  68%, 100% { transform: translateX(280%) skewX(-16deg); opacity: 0; }
}
@keyframes fp-brand-glitch {
  /* No transform or filter on this element: either one creates a stacking
   * context, which isolates ::after's screen blend from the header strip and
   * turns the light bar into a pale blue rectangle (seen in the first build).
   * The distortion is carried by the chromatic shadow pair alone. */
  0%, 44%   { text-shadow: none; }
  52%       { text-shadow: -3px 0 rgba(56,168,255,.95), 3px 0 rgba(255,64,140,.55), 0 0 15px rgba(56,168,255,.6); }
  58%       { text-shadow: 3px 0 rgba(56,168,255,.85), -3px 0 rgba(255,64,140,.45), 0 0 12px rgba(56,168,255,.5); }
  64%       { text-shadow: -1.5px 0 rgba(56,168,255,.5), 1.5px 0 rgba(255,64,140,.28), 0 0 6px rgba(56,168,255,.3); }
  70%, 100% { text-shadow: none; }
}
/* The .aph header is light on homepages (the fp-home layer repaints it) but
   its wordmark was still the dark-header white, measured washed out on the
   pale strip. Ink it before animating it, or the blue flies through a logo
   nobody can see. */
body.fp-home header.aph .fp-logo-word { color: var(--fp-home-navy) !important; }
body.fp-home header.aph .fp-logo-word b { color: #8a5a00 !important; }
@media (prefers-reduced-motion: no-preference) {
  body.fp-home .inst-brand,
  body.fp-home header.aph .fp-logo-word {
    position: relative;
    display: inline-block;
    overflow: hidden;
    padding: 0 2px 3px;
    margin: 0 -2px -3px;
    animation: fp-brand-glitch 8s ease-in-out infinite;
  }
  body.fp-home .inst-brand::after,
  body.fp-home header.aph .fp-logo-word::after {
    content: "";
    position: absolute;
    top: -15%;
    bottom: -15%;
    left: 0;
    width: 55%;
    pointer-events: none;
    background: linear-gradient(100deg, rgba(56,168,255,0) 0%, rgba(56,168,255,.55) 34%, #d6ecff 50%, rgba(56,168,255,.55) 66%, rgba(56,168,255,0) 100%);
    mix-blend-mode: screen;
    transform: translateX(-160%) skewX(-16deg);
    animation: fp-brand-sweep 8s cubic-bezier(.45,.05,.55,.95) infinite;
  }
}
@media (prefers-reduced-motion: reduce) {
  body.fp-home .inst-brand,
  body.fp-home header.aph .fp-logo-word { animation: none !important; }
}

/* ---- the border-gate vignette ------------------------------------------
   Owner ask (2026-10-25): a minimal animation of a one-way flyer walking up to
   a BORDER sign reading DENIED, showing the FlightProof ticket, and passing
   through. Drawn inline (scripts/add-border-gate.cjs) so it ships at ~3 KB,
   stays crisp at any width, and carries its sign words in the page's language.
   11s loop: walk 0-30%, blocked 30-55%, ticket 40-45%, barrier lifts 52-64%,
   gate turns green 58-66%, walk through 66-78%, reset 92-100%.
   Decorative: aria-hidden on the wrapper, the hero copy carries the meaning. */
body.fp-home .fp-bgate {
  max-width: 100%;
  margin-top: 22px;
}
body.fp-home .fp-bgate svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}
body.fp-home .fp-bgate .fp-bg-man {
  transform: translate(80px, 170px);
  animation: fp-bg-walk 11s ease-in-out infinite;
}
body.fp-home .fp-bgate .fp-bg-bob {
  animation: fp-bg-bob 1.1s ease-in-out infinite alternate;
}
body.fp-home .fp-bgate .fp-bg-no { animation: fp-bg-no 11s ease-in-out infinite; }
body.fp-home .fp-bgate .fp-bg-yes { animation: fp-bg-yes 11s ease-in-out infinite; }
body.fp-home .fp-bgate .fp-bg-ticket {
  transform-origin: 37px -35px;
  animation: fp-bg-ticket 11s ease-in-out infinite;
}
@keyframes fp-bg-walk {
  0%   { transform: translate(80px, 170px); opacity: 1; }
  30%  { transform: translate(470px, 170px); opacity: 1; }
  55%  { transform: translate(470px, 170px); opacity: 1; }
  78%  { transform: translate(720px, 170px); opacity: 1; }
  90%  { transform: translate(720px, 170px); opacity: 1; }
  93%  { transform: translate(720px, 170px); opacity: 0; }
  94%  { transform: translate(80px, 170px); opacity: 0; }
  100% { transform: translate(80px, 170px); opacity: 1; }
}
@keyframes fp-bg-bob {
  from { transform: translateY(0); }
  to   { transform: translateY(-2.5px); }
}
@keyframes fp-bg-no {
  0%, 24%   { opacity: .22; }
  32%, 50%  { opacity: 1; }
  58%, 100% { opacity: 0; }
}
@keyframes fp-bg-yes {
  0%, 58%   { opacity: 0; }
  66%, 90%  { opacity: 1; }
  97%, 100% { opacity: 0; }
}
@keyframes fp-bg-ticket {
  0%, 40%   { transform: scale(0); opacity: 0; }
  45%       { transform: scale(1.18); opacity: 1; }
  50%, 90%  { transform: scale(1); opacity: 1; }
  100%      { transform: scale(0); opacity: 0; }
}
/* The fare line under the verdict — only on locales that carry one. It is a
   price board, not a second headline: it rolls up 5 units and lands with a
   single 1.09 pop 2% after its verdict appears, then holds still. One beat
   each way, on the same 11s clock as everything else in the scene. */
body.fp-home .fp-bgate .fp-bg-fare {
  transform-box: fill-box;
  transform-origin: center;
  animation: fp-bg-fare-no 11s ease-out infinite;
}
body.fp-home .fp-bgate .fp-bg-fare-yes { animation-name: fp-bg-fare-yes; }
@keyframes fp-bg-fare-no {
  0%, 27%   { transform: translateY(5px) scale(.97); opacity: 0; }
  31%       { transform: translateY(0) scale(1.09); opacity: 1; }
  38%, 54%  { transform: translateY(0) scale(1); opacity: 1; }
  58%, 100% { transform: translateY(0) scale(1); opacity: 0; }
}
@keyframes fp-bg-fare-yes {
  0%, 61%   { transform: translateY(5px) scale(.97); opacity: 0; }
  66%       { transform: translateY(0) scale(1.09); opacity: 1; }
  72%, 90%  { transform: translateY(0) scale(1); opacity: 1; }
  96%, 100% { transform: translateY(0) scale(1); opacity: 0; }
}
/* ── scene 2: the arrival-hall build (only pages that carry a fare line) ──
   The refusal has weight here: he stops, takes a half-step back at 38%, and
   steps up again once the ticket is out. The stride flips only inside the two
   walking windows (0-25%, 65-70% of the 11s clock); the neutral stance holds
   through the wait and the final beat, so a man waiting at a barrier stands
   still instead of frozen mid-lunge. */
body.fp-home .fp-bgate .fp-bg-man2 {
  transform: translate(80px, 170px);
  animation: fp-bg-walk2 11s ease-in-out infinite;
}
@keyframes fp-bg-walk2 {
  0%   { transform: translate(80px, 170px); opacity: 1; }
  30%  { transform: translate(470px, 170px); opacity: 1; }
  34%  { transform: translate(470px, 170px); opacity: 1; }
  38%  { transform: translate(452px, 170px); opacity: 1; }
  52%  { transform: translate(452px, 170px); opacity: 1; }
  60%  { transform: translate(470px, 170px); opacity: 1; }
  78%  { transform: translate(700px, 170px); opacity: 1; }
  90%  { transform: translate(700px, 170px); opacity: 1; }
  93%  { transform: translate(700px, 170px); opacity: 0; }
  94%  { transform: translate(80px, 170px); opacity: 0; }
  100% { transform: translate(80px, 170px); opacity: 1; }
}
body.fp-home .fp-bgate .fp-bg-legs-a { animation: fp-bg-stride-a 11s steps(1, end) infinite; }
body.fp-home .fp-bgate .fp-bg-legs-b { animation: fp-bg-stride-b 11s steps(1, end) infinite; }
@keyframes fp-bg-stride-a {
  0%, 4.9%   { opacity: 1; }
  5%, 9.9%   { opacity: 0; }
  10%, 14.9% { opacity: 1; }
  15%, 19.9% { opacity: 0; }
  20%, 24.9% { opacity: 1; }
  25%, 64.9% { opacity: 0; }
  65%, 69.9% { opacity: 1; }
  70%, 100%  { opacity: 0; }
}
@keyframes fp-bg-stride-b {
  0%, 4.9%   { opacity: 0; }
  5%, 9.9%   { opacity: 1; }
  10%, 14.9% { opacity: 0; }
  15%, 19.9% { opacity: 1; }
  20%, 24.9% { opacity: 0; }
  25%, 64.9% { opacity: 1; }
  65%, 69.9% { opacity: 0; }
  70%, 100%  { opacity: 1; }
}
/* The no-onward-ticket pictogram is what the officer is looking at: solid while
   the plate says DENIED, back to a quiet badge once the ticket is out. */
body.fp-home .fp-bgate .fp-bg-pic { animation: fp-bg-pic 11s ease-in-out infinite; }
@keyframes fp-bg-pic {
  0%, 30%   { opacity: .45; }
  34%, 52%  { opacity: 1; }
  58%, 100% { opacity: .45; }
}
body.fp-home .fp-bgate .fp-bg-ticket2 {
  transform-origin: 24px -34px;
  animation: fp-bg-ticket 11s ease-in-out infinite;
}
/* The officer's question, in a bubble hanging off the booth glass. It leads
   the refusal and holds through it: in at 22%, still legible while the plate
   reaches full DENIED at 32%, and gone at 46% — before the ticket pops in the
   traveller's hand at 45%, which would otherwise land on the words. A whole
   sentence needs the longer hold; the old one-line "Return ticket?" was
   readable at 1.2s, this is not. It grows out of the tail (origin at the right
   edge), so it reads as speech, not a second sign. */
body.fp-home .fp-bgate .fp-bg-ask {
  transform-box: fill-box;
  transform-origin: 100% 50%;
  animation: fp-bg-ask 11s ease-out infinite;
}
@keyframes fp-bg-ask {
  0%, 18%   { opacity: 0; transform: translateY(6px) scale(.96); }
  22%       { opacity: 1; transform: translateY(0) scale(1.03); }
  26%, 42%  { opacity: 1; transform: translateY(0) scale(1); }
  46%, 100% { opacity: 0; transform: translateY(0) scale(1); }
}
/* The fare line, same reason as the plate: at 390px the whole scene renders at
   0.572 scale, so a 16px SVG line lands at 9px. On a phone it gets 19px
   (≈11.4px) and the 88-unit plate has the room below the verdict.
   It was 21px while EN was the only fare locale (14 characters). With all 42
   locales the worst label is Finnish, `SAMANA PÄIVÄNÄ $250+`, which measured
   261 of the 266 units between the text's x=590 and the plate's right edge at
   21px — 5 units of margin, i.e. none once a device falls back to a wider
   sans. 19px leaves 30 units on that label and still lands ≈11.4px on screen. */
@media (max-width: 560px) {
  body.fp-home .fp-bgate .fp-bg-fare { font-size: 19px; }
  /* Same reason as the fare line: 15px lands at 8.6px on a phone. 16px is
     ≈9.2px on screen; the bubble is sized per locale for 16px already (see
     askWidth in scripts/add-border-gate.cjs), so nothing overflows here. */
  body.fp-home .fp-bgate .fp-bg-ask text { font-size: 16px; }
}
/* On a phone the 900-unit scene shrank to 339px wide: a 12px stick figure next
   to an 11px sign, which read as a stray doodle above the order card. Zoom to
   160% and right-align the window instead, so the sign stays at 17px and the
   walker simply enters from the frame edge (the left third is empty anyway).
   overflow:hidden keeps the extra width from becoming page overflow. */
@media (max-width: 560px) {
  body.fp-home .fp-bgate { overflow: hidden; }
  body.fp-home .fp-bgate svg { width: 160%; margin-left: -60%; }
}
/* Standing through the border, sign green, ticket in hand — the end of the
   story is the whole point, so reduced-motion readers get that frame. */
@media (prefers-reduced-motion: reduce) {
  body.fp-home .fp-bgate .fp-bg-man,
  body.fp-home .fp-bgate .fp-bg-bob,
  body.fp-home .fp-bgate .fp-bg-no,
  body.fp-home .fp-bgate .fp-bg-yes,
  body.fp-home .fp-bgate .fp-bg-man2,
  body.fp-home .fp-bgate .fp-bg-legs-a,
  body.fp-home .fp-bgate .fp-bg-legs-b,
  body.fp-home .fp-bgate .fp-bg-pic,
  body.fp-home .fp-bgate .fp-bg-ticket2,
  body.fp-home .fp-bgate .fp-bg-ask,
  body.fp-home .fp-bgate .fp-bg-fare,
  body.fp-home .fp-bgate .fp-bg-ticket { animation: none !important; }
  body.fp-home .fp-bgate .fp-bg-man2 { transform: translate(700px, 170px); }
  body.fp-home .fp-bgate .fp-bg-legs-a { opacity: 1; }
  body.fp-home .fp-bgate .fp-bg-legs-b { opacity: 0; }
  body.fp-home .fp-bgate .fp-bg-pic { opacity: .45; }
  body.fp-home .fp-bgate .fp-bg-ticket2 { transform: scale(1); opacity: 1; }
  body.fp-home .fp-bgate .fp-bg-man { transform: translate(798px, 170px); }
  body.fp-home .fp-bgate .fp-bg-no { opacity: 0; }
  body.fp-home .fp-bgate .fp-bg-yes { opacity: 1; }
  body.fp-home .fp-bgate .fp-bg-ticket { transform: scale(1); opacity: 1; }
}

/* Friendly destination controls. */
body.fp-home .inst-dest {
  position: relative;
  max-width: 720px;
  margin-top: 22px;
}
body.fp-home .inst-dest-ask {
  color: var(--fp-home-navy) !important;
  font-weight: 800 !important;
}
body.fp-home .inst-dest-selwrap {
  border: 1.5px solid var(--fp-home-navy) !important;
  border-radius: 9px !important;
  background: rgba(255, 255, 255, .88) !important;
  box-shadow: 3px 3px 0 rgba(26, 26, 46, .18);
}
body.fp-home .inst-dest-sel {
  min-height: 50px !important;
  color: var(--fp-home-navy) !important;
  background: transparent !important;
}
body.fp-home .inst-dest-sel option {
  background: var(--fp-home-navy) !important;
  color: #fff !important;
}
body.fp-home .inst-dest-chev { color: var(--fp-home-navy) !important; }
body.fp-home .inst-dest-buy {
  min-height: 50px;
  border-radius: 9px !important;
  background: var(--fp-home-navy) !important;
  color: var(--fp-home-amber) !important;
  box-shadow: 3px 3px 0 rgba(26, 26, 46, .25) !important;
}
body.fp-home .inst-dest-warn {
  border-radius: 8px !important;
  border-color: rgba(26, 26, 46, .2) !important;
  background: rgba(255, 255, 255, .78) !important;
}
/* The risk warning was white-on-white: instrument.css paints its text for the
   41-locale dark wall (#fff destination name, rgba(255,255,255,.78) rule,
   pale #ffb3a7 / #f5c877 / #9fd9ba tiers, amber "read the guide" link) and
   fp-home only swapped the CARD to rgba(255,255,255,.78) — so on the gold band
   the name, the tier and the rule all disappeared (owner, 2026-10-25). Re-point
   every text colour at the navy/ink ramp the rest of the band uses, and darken
   the tier accents so they stay legible on the light card. */
body.fp-home .inst-dest-main b { color: var(--fp-home-navy) !important; }
body.fp-home .inst-dest-warn.is-high { border-left-color: #a32a1c !important; }
body.fp-home .inst-dest-warn.is-medium { border-left-color: #8a5a00 !important; }
body.fp-home .inst-dest-warn.is-low { border-left-color: #1f6b45 !important; }
body.fp-home .inst-dest-warn.is-high .inst-dest-tier { color: #a32a1c !important; }
body.fp-home .inst-dest-warn.is-medium .inst-dest-tier { color: #8a5a00 !important; }
body.fp-home .inst-dest-warn.is-low .inst-dest-tier { color: #1f6b45 !important; }
body.fp-home .inst-dest-rule { color: rgba(26, 26, 46, .84) !important; }
body.fp-home .inst-dest-guide {
  color: var(--fp-home-navy) !important;
  text-decoration-color: rgba(26, 26, 46, .45) !important;
}
body.fp-home .inst-dest-guide:hover { color: #0a0a14 !important; }
body.fp-home .inst-dest-answer {
  font: 900 17px/1.25 Outfit, 'DM Sans', sans-serif !important;
  color: var(--fp-home-navy) !important;
}
body.fp-home .inst-dest-mandatory {
  display: block;
  margin-top: 7px;
  padding: 8px 10px;
  border-left: 3px solid var(--fp-home-navy);
  background: rgba(255, 230, 109, .48);
  font: 800 12.5px/1.4 'DM Sans', sans-serif !important;
  color: var(--fp-home-navy) !important;
}

/* Destination desk: one connected instruction strip, not three SaaS cards. */
body.fp-home .fp-need {
  order: 1;
  margin: 0 !important;
  padding: clamp(22px, 3.6vw, 38px) clamp(18px, 3vw, 30px) !important;
  background: rgba(255, 230, 109, .42) !important;
  border: 0 !important;
  border-bottom: 1.5px dashed var(--fp-home-edge) !important;
  border-radius: 0 !important;
  box-shadow: none !important;
}
body.fp-home .fp-need-head {
  max-width: 760px;
  margin-bottom: 18px;
}
body.fp-home .fp-need-kicker {
  color: var(--fp-home-navy) !important;
  font: 800 11px/1.3 var(--i-mono, 'JetBrains Mono', monospace) !important;
  letter-spacing: .1em !important;
}
body.fp-home .fp-need-head h2 {
  color: var(--fp-home-navy) !important;
  font: 900 clamp(22px, 3.2vw, 31px)/1.12 Outfit, 'DM Sans', sans-serif !important;
}
body.fp-home .fp-need-head p:last-child {
  color: rgba(26, 26, 46, .72) !important;
  font-weight: 500 !important;
}
body.fp-home .fp-need-grid {
  display: grid !important;
  grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
  gap: 0 !important;
  margin: 0 !important;
  border-top: 1px solid rgba(26, 26, 46, .22) !important;
  border-bottom: 1px solid rgba(26, 26, 46, .22) !important;
}
body.fp-home .fp-need-step {
  display: grid !important;
  grid-template-columns: 34px minmax(0, 1fr) !important;
  gap: 12px !important;
  padding: 18px 18px 18px 0 !important;
  border: 0 !important;
}
body.fp-home .fp-need-step + .fp-need-step {
  border-left: 1px dashed rgba(26, 26, 46, .25) !important;
  padding-left: 18px !important;
}
body.fp-home .fp-need-n {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0 !important;
  border: 1.5px solid var(--fp-home-navy) !important;
  border-radius: 50% !important;
  background: var(--fp-home-amber) !important;
  color: var(--fp-home-navy) !important;
  font: 800 10px/1 var(--i-mono, 'JetBrains Mono', monospace) !important;
}
body.fp-home .fp-need-step h3 {
  margin: 0 0 5px !important;
  color: var(--fp-home-navy) !important;
  font: 900 15px/1.25 Outfit, 'DM Sans', sans-serif !important;
}
body.fp-home .fp-need-step p {
  color: rgba(26, 26, 46, .7) !important;
  font-weight: 500 !important;
}
body.fp-home .fp-need-step a {
  min-height: 40px !important;
  color: var(--fp-home-navy) !important;
  border-bottom-color: var(--fp-home-navy) !important;
}
body.fp-home .fp-need-dests {
  gap: 7px !important;
  padding-top: 16px !important;
}
body.fp-home .fp-need-dests > span { color: rgba(26, 26, 46, .66) !important; }
body.fp-home .fp-need-dests a {
  min-height: 40px !important;
  border: 1px solid rgba(26, 26, 46, .22) !important;
  border-radius: 7px !important;
  background: rgba(255, 255, 255, .72) !important;
  color: var(--fp-home-navy) !important;
}
body.fp-home .fp-need-dests a:hover,
body.fp-home .fp-need-dests a:focus-visible {
  border-color: var(--fp-home-navy) !important;
  box-shadow: 2px 2px 0 var(--fp-home-amber) !important;
}


/* Guide index comes before the long airport evidence list. */
body.fp-home .inst-guides-sec {
  order: 2;
  margin: 0 !important;
  padding: clamp(26px, 4vw, 42px) clamp(18px, 3vw, 30px) clamp(24px, 4vw, 40px) !important;
  background: rgba(255, 255, 255, .72) !important;
  border-bottom: 1.5px dashed var(--fp-home-edge) !important;
}
body.fp-home .inst-guides-sec .inst-h2--sec {
  color: var(--fp-home-navy) !important;
  font-size: clamp(22px, 3vw, 30px) !important;
}
body.fp-home .inst-guides-sec .inst-dek {
  max-width: 72ch;
  color: var(--fp-home-dim) !important;
}
body.fp-home .inst-guides-sec .inst-region {
  border-color: rgba(26, 26, 46, .18) !important;
  background: rgba(255, 255, 255, .72) !important;
}
body.fp-home .inst-guides-sec .inst-region-h {
  background: rgba(255, 230, 109, .58) !important;
  border-bottom: 1px dashed rgba(26, 26, 46, .22) !important;
}
body.fp-home .inst-guides-sec .inst-region-h b {
  color: var(--fp-home-navy) !important;
  letter-spacing: .08em !important;
}
body.fp-home .inst-guides-sec .inst-region-h span {
  color: rgba(26, 26, 46, .7) !important;
  background: rgba(255, 255, 255, .42) !important;
  border-color: rgba(26, 26, 46, .18) !important;
}
body.fp-home .inst-guides-sec .inst-chips {
  display: grid !important;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)) !important;
  gap: 8px !important;
  background: rgba(255, 255, 255, .44) !important;
}
body.fp-home .inst-guides-sec .inst-chips li { display: block !important; }
body.fp-home .inst-guides-sec .inst-chip {
  display: grid !important;
  gap: 3px !important;
  min-height: 58px !important;
  padding: 9px 11px !important;
  border-color: rgba(26, 26, 46, .18) !important;
  background: rgba(255, 255, 255, .82) !important;
  color: var(--fp-home-navy) !important;
}
body.fp-home .inst-chip-name {
  font: 900 13.5px/1.2 Outfit, 'DM Sans', sans-serif !important;
}
body.fp-home .inst-chip-rule {
  font: 750 10.5px/1.25 'DM Sans', sans-serif !important;
  color: rgba(26, 26, 46, .68) !important;
}
body.fp-home .inst-chip--yes {
  border-inline-start: 4px solid var(--fp-home-navy) !important;
  background: rgba(255, 230, 109, .34) !important;
}
body.fp-home .inst-chip--yes .inst-chip-rule { color: var(--fp-home-navy) !important; }
body.fp-home .inst-chip--check { border-inline-start: 4px solid #d98c00 !important; }
body.fp-home .inst-chip--unknown { border-inline-start: 4px solid #9a9487 !important; }

/* Restore the country-guide perforated split. */
body.fp-home .inst-split {
  order: 3;
  display: grid !important;
  grid-template-columns: minmax(0, 1fr) minmax(340px, 410px) !important;
  align-items: start !important;
  width: 100%;
  background: transparent !important;
}
body.fp-home .inst-main {
  min-width: 0;
  max-width: none !important;
  margin: 0 !important;
  padding: clamp(22px, 3.4vw, 34px) clamp(18px, 3vw, 30px) clamp(26px, 4vw, 38px) !important;
  background: rgba(255, 255, 255, .62) !important;
}
body.fp-home .inst-stub {
  order: 0 !important;
  min-width: 0;
  max-width: none !important;
  margin: 0 !important;
  padding: clamp(20px, 3vw, 28px) clamp(16px, 2.3vw, 22px) clamp(24px, 3.4vw, 30px) !important;
  border-left: 1px dashed var(--fp-home-edge) !important;
  border-top: 0 !important;
  background: #faf8f4 !important;
}
body.fp-home .inst-stub::before {
  display: block !important;
  left: -9px !important;
  background: repeating-linear-gradient(180deg, var(--fp-home-edge) 0 5px, transparent 5px 11px) !important;
}
body.fp-home .inst-stub .inst-h2 {
  color: var(--fp-home-navy) !important;
  font: 900 11px/1.3 var(--i-mono, 'JetBrains Mono', monospace) !important;
  letter-spacing: .12em !important;
}
body.fp-home .inst-stub .fp-ex {
  max-width: none !important;
  margin: 0 !important;
  padding: 0 !important;
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
}
body.fp-home .inst-stub .fp-ex-in {
  min-width: 0 !important;
  min-height: 46px !important;
  border-radius: 7px !important;
  background: #fff !important;
  color: var(--fp-home-navy) !important;
}
body.fp-home .inst-stub .fp-ex-f2wrap { min-width: 0 !important; }
body.fp-home .inst-stub .fp-ex-consent {
  color: var(--fp-home-dim) !important;
  font-size: 11.5px !important;
  line-height: 1.45 !important;
}


body.fp-home .inst-stub #fp-pair {
  margin-top: 18px !important;
  padding-top: 18px !important;
  border-top: 1.5px dashed var(--fp-home-edge) !important;
}
body.fp-home .inst-stub .fp-pair-fact { color: var(--fp-home-dim) !important; }
body.fp-home .inst-stub .fp-code b { color: var(--fp-home-navy) !important; }
body.fp-home .inst-stub .fp-issue {
  border-color: rgba(26, 26, 46, .2) !important;
  background: rgba(255, 230, 109, .24) !important;
  border-radius: 8px !important;
}
body.fp-home .inst-stub .fp-fare { color: var(--fp-home-navy) !important; }
body.fp-home .inst-stub .inst-status { color: var(--fp-home-dim) !important; }

/* Evidence list and sample ticket stay inside the document. */
body.fp-home .inst-main .inst-h2--sec { color: var(--fp-home-navy) !important; }
body.fp-home .inst-main .inst-dek {
  max-width: 72ch;
  color: var(--fp-home-dim) !important;
}
body.fp-home .inst-heat-search {
  min-height: 46px !important;
  border: 1.5px solid rgba(26, 26, 46, .22) !important;
  border-radius: 8px !important;
  background: rgba(255, 255, 255, .9) !important;
  color: var(--fp-home-navy) !important;
}
body.fp-home .inst-tk-sec {
  order: 4;
  max-width: 760px !important;
  margin: 0 auto !important;
  padding: clamp(26px, 4vw, 42px) clamp(18px, 3vw, 30px) !important;
  background: rgba(255, 255, 255, .56) !important;
}
body.fp-home #news-section,
body.fp-home #free-tools {
  background: rgba(255, 255, 255, .72) !important;
  border-color: var(--fp-home-edge) !important;
}

@media (max-width: 960px) {
  body.fp-home .inst-split {
    display: flex !important;
    flex-direction: column !important;
  }
  body.fp-home .inst-main,
  body.fp-home .inst-stub { width: 100%; }
  body.fp-home .inst-stub {
    order: 2 !important;
    border-left: 0 !important;
    border-top: 1.5px dashed var(--fp-home-edge) !important;
  }
  body.fp-home .inst-stub::before { display: none !important; }
}
@media (max-width: 760px) {
  body.fp-home .inst-doc { border-radius: 8px !important; }
  body.fp-home .inst-band {
    padding: 28px 18px 24px !important;
    border-radius: 0 !important;
  }
  body.fp-home .inst-band h1 { max-width: 24ch !important; }
  body.fp-home .inst-band p.dek { font-size: 14px !important; }
  body.fp-home .inst-readout {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
  }
  body.fp-home .inst-readout > span { min-width: 0; }
  body.fp-home .fp-need-grid { grid-template-columns: 1fr !important; }
  body.fp-home .fp-need-step { padding: 16px 0 !important; }
  body.fp-home .fp-need-step + .fp-need-step {
    border-left: 0 !important;
    border-top: 1px dashed rgba(26, 26, 46, .24) !important;
    padding-left: 0 !important;
  }
  body.fp-home .fp-need-dests { align-items: flex-start; }
  body.fp-home .fp-need-dests > span { width: 100%; }
}
@media (max-width: 520px) {
  body.fp-home .wrap { padding-inline: 8px; }
  body.fp-home .inst-doc {
    margin-top: 0 !important;
    border-inline: 0 !important;
  }
  body.fp-home .inst-readout { grid-template-columns: 1fr; }
  body.fp-home .inst-dest-row {
    display: grid !important;
    grid-template-columns: 1fr;
  }
  body.fp-home .inst-dest-buy {
    width: 100%;
    justify-content: center;
  }
  body.fp-home .inst-stub .fp-ex-in { font-size: 13px !important; }
  body.fp-home .inst-main,
  body.fp-home .inst-stub,
  body.fp-home .inst-guides-sec,
  body.fp-home .inst-tk-sec { padding-inline: 14px !important; }
}
@media (prefers-reduced-motion: reduce) {
  body.fp-home * { animation: none !important; transition: none !important; }
}


/* ==========================================================================
   LOCALE HOMES — the legacy shell the English page already dropped.

   The 41 locale homepages still carried the old marketing slab: a second
   purchase widget (.fp-duo) under the country lists, full-bleed service
   sections and a 48px white padding that no longer exists on /.

   The English page hides .welcome-hero with display:none and no longer ships
   .fp-duo at all, so hiding the same block here brings the locale family to
   the same composition instead of two different sites. The country lists,
   the airport evidence, the eSIM row, news and tools are all KEPT.
   ========================================================================== */
body.fp-home:not(.fp-inst) .fp-duo { display: none !important; }
body.fp-home:not(.fp-inst) #services-section {
  background: transparent !important;
  padding: 24px clamp(14px, 3vw, 30px) !important;
  border: 0 !important;
}
body.fp-home:not(.fp-inst) .inst-split {
  background: rgba(255, 255, 255, .74) !important;
  border-top: 1px solid var(--fp-home-edge) !important;
  border-bottom: 1px solid var(--fp-home-edge) !important;
}
body.fp-home:not(.fp-inst) .inst-tk-sec { background: rgba(255, 255, 255, .5) !important; }
body.fp-home:not(.fp-inst) .fpb-stats { background: rgba(255, 255, 255, .74) !important; }

/* ==========================================================================
   THE ORDER CARD — bold, not premium (owner 2026-10-24).

   The stub reads as an order, so it is set like one: a mono kicker with a
   60-second stamp, one hard two-line headline, one sentence, the route, and
   an amber button with a solid navy shadow. No gradients, no soft glow — those
   were what made it read as "premium" instead of decisive.

   Two structural fixes ride along:
   - the inline #fp-home-layout block gave .fp-ex-grid FOUR tracks
     (1fr | 1fr | 44px | 1fr) for a three-column route, so From and To shared
     ~107px each and the To field was clipped by the card edge. Three tracks
     again, with the name spans back under their own fields.
   - #fp-pair printed a second DPS → SIN pair and fare right under the form
     that already holds the route. The ids stay (app-core writes fp-big-from /
     fp-big-to / fp-truth / fp-fare), the duplicate display goes: the truth
     line and the live fare are the only things that still add information.
   ========================================================================== */
body.fp-home .inst-stub .fp-ex-kick {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 12px;
  font: 800 10px/1 var(--i-mono, 'JetBrains Mono', monospace);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--fp-home-dim);
}
body.fp-home .inst-stub .fp-ex-kick b {
  margin-left: auto;
  padding: 4px 7px;
  border-radius: 4px;
  background: var(--fp-home-amber);
  color: var(--fp-home-navy);
  font: 800 10px/1 var(--i-mono, 'JetBrains Mono', monospace);
  letter-spacing: .1em;
}
body.fp-home .inst-stub .fp-ex-title {
  margin: 0 0 10px;
  color: var(--fp-home-navy) !important;
  font: 900 clamp(24px, 2.5vw, 31px)/1.0 Outfit, 'DM Sans', sans-serif !important;
  letter-spacing: -.035em;
  text-transform: none !important;
}
body.fp-home .inst-stub .fp-ex-title em {
  font-style: normal;
  background: var(--fp-home-amber);
  box-shadow: 4px 0 0 var(--fp-home-amber), -4px 0 0 var(--fp-home-amber);
}
body.fp-home .inst-stub .fp-ex-order {
  margin: 0 0 18px;
  max-width: 32ch;
  color: var(--fp-home-dim);
  font: 600 13.5px/1.45 'DM Sans', sans-serif;
}

/* three route tracks, not four */
body.fp-home .inst-stub .fp-ex-grid {
  grid-template-columns: minmax(0, 1fr) 40px minmax(0, 1fr) !important;
  grid-template-rows: auto auto auto !important;
}
body.fp-home .inst-stub .fp-ex-grid > #fp-ex-name-from { grid-area: 3 / 1 !important; }
body.fp-home .inst-stub .fp-ex-grid > #fp-ex-name-to { grid-area: 3 / 3 !important; }
body.fp-home .inst-stub .fp-ex-lab {
  font: 800 10px/1 var(--i-mono, 'JetBrains Mono', monospace);
  letter-spacing: .14em;
  color: var(--fp-home-navy);
  margin-bottom: 5px;
}
body.fp-home .inst-stub .fp-ex-in {
  min-height: 52px !important;
  border: 1.5px solid rgba(26, 26, 46, .3) !important;
  border-radius: 8px !important;
  background: #fff !important;
  color: var(--fp-home-navy) !important;
  font: 800 17px/1.1 var(--i-mono, 'JetBrains Mono', monospace) !important;
}
body.fp-home .inst-stub .fp-ex-in:focus-visible {
  border-color: var(--fp-home-navy) !important;
  box-shadow: 0 0 0 3px rgba(255, 230, 109, .95) !important;
  outline: none !important;
}
body.fp-home .inst-stub .fp-ex-in--human {
  font: 600 15px/1.2 'DM Sans', sans-serif !important;
  letter-spacing: 0 !important;
  text-transform: none !important;
}
body.fp-home .inst-stub .fp-ex-swap {
  /* 44, not 34: this shrank the express card's only icon button to a sub-44
     target (measured 2026-10-29 at 390/768/1280). The base rule in
     instrument.css is 44x46; keep them agreeing. */
  width: 44px;
  height: 44px;
  border: 1.5px solid var(--fp-home-navy) !important;
  border-radius: 50%;
  background: #fff !important;
  color: var(--fp-home-navy) !important;
}

/* the one action */
body.fp-home .inst-stub .fp-ex-submit {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  min-height: 58px;
  margin-top: 14px;
  padding: 14px 18px;
  border: 2px solid var(--fp-home-navy) !important;
  border-radius: 10px;
  background: var(--fp-home-amber) !important;
  color: var(--fp-home-navy) !important;
  font: 900 17px/1 Outfit, 'DM Sans', sans-serif !important;
  letter-spacing: -.01em;
  text-transform: none !important;
  box-shadow: 4px 4px 0 var(--fp-home-navy);
  transition: transform .12s ease, box-shadow .12s ease;
}
body.fp-home .inst-stub .fp-ex-submit:hover,
body.fp-home .inst-stub .fp-ex-submit:focus-visible {
  transform: translate(-1px, -1px);
  box-shadow: 6px 6px 0 var(--fp-home-navy);
  outline: none;
}
body.fp-home .inst-stub .fp-ex-submit:focus-visible { outline: 3px solid rgba(26, 26, 46, .35); outline-offset: 4px; }
body.fp-home .inst-stub .fp-ex-submit .fp-ex-price {
  font: 800 16px/1 var(--i-mono, 'JetBrains Mono', monospace);
  padding-bottom: 2px;
  border-bottom: 2px solid rgba(26, 26, 46, .35);
}

/* the receipt keeps only what the form cannot say */
body.fp-home .inst-stub #fp-pair { margin-top: 10px !important; padding-top: 12px !important; }
/* Only the pages that actually carry the order card (EN, DE today) may drop
   the printed pair: on the other locale homepages #fp-pair's issue button is
   the ONLY buy action, so these rules must not reach them. */
body.fp-home .inst-stub.fp-order #fp-pair .fp-codes,
body.fp-home .inst-stub.fp-order #fp-pair .fp-pair-fact { display: none !important; }
/* The truth line stays — it is the only live feedback the order has (route
   checked, no direct flight, schedule unreachable). 'wait' is also the kind
   app-core uses for "schedule unreachable", so hiding that state would hide a
   message the traveller needs; it is set as a quiet line instead of a box. */
body.fp-home .inst-stub.fp-order #fp-pair .fp-truth {
  margin: 0 0 8px !important;
  padding: 0 !important;
  border: 0 !important;
  background: none !important;
  font: 600 11.5px/1.45 'DM Sans', sans-serif !important;
  color: var(--fp-home-dim) !important;
}
/* the price lives on the button now (paintBuyPrice writes #fp-ex-submit
   .fp-ex-price), so the printed fare and its note would be a second, differently
   formatted figure. The strip keeps the Stripe line and nothing else. */
body.fp-home .inst-stub.fp-order #fp-pair .fp-fare,
body.fp-home .inst-stub.fp-order #fp-pair .fp-fare-note { display: none !important; }
body.fp-home .inst-stub.fp-order #fp-pair .fp-issue-btn { display: none !important; }
body.fp-home .inst-stub.fp-order #fp-pair .fp-issue {
  justify-content: center !important;
  padding: 0 !important;
  border: 0 !important;
  background: transparent !important;
}
body.fp-home .inst-stub .inst-status {
  display: block !important;
  margin-top: 12px !important;
  padding: 0 !important;
  border: 0 !important;
  background: transparent !important;
  color: var(--fp-home-dim) !important;
  font: 700 10.5px/1.3 var(--i-mono, 'JetBrains Mono', monospace) !important;
  letter-spacing: .1em !important;
  text-transform: uppercase !important;
  text-align: center !important;
}
body.fp-home .inst-stub .inst-status::before { display: none !important; }

/* the destination prompt's empty state shipped as a blank white bar: the
   element is [hidden], but .inst-dest-warn sets display, and any author
   display beats the UA [hidden] rule. */
body.fp-home .inst-dest-warn[hidden] { display: none !important; }

/* ---- locale homes: one order card, not a card beside an empty column ----
   .inst-main on the 41 locale pages holds only the map band, which is hidden
   until the popup opens: the split therefore rendered as a 900px white void
   with a 410px stub crushed at its right edge, and the route fields were
   clipped by the card. One column, the card centred and wide enough for the
   route, and the legacy sections below keep their own rhythm. */
body.fp-home:not(.fp-inst) .inst-split {
  display: block !important;
  background: transparent !important;
  border: 0 !important;
}
body.fp-home:not(.fp-inst) .inst-main { display: none !important; }
body.fp-home:not(.fp-inst) .inst-stub {
  max-width: 720px !important;
  margin: clamp(20px, 3.4vw, 38px) auto !important;
  padding: clamp(22px, 3vw, 32px) clamp(18px, 3vw, 30px) clamp(24px, 3.4vw, 34px) !important;
  border: 1.5px solid var(--fp-home-edge) !important;
  border-top: 4px solid var(--fp-home-amber) !important;
  border-radius: 14px !important;
  background: #fff !important;
  box-shadow: 0 26px 50px -38px rgba(26, 26, 46, .5) !important;
}
body.fp-home:not(.fp-inst) .inst-stub::before { display: none !important; }
body.fp-home:not(.fp-inst) .inst-stub .fp-ex-title { font-size: clamp(26px, 3.4vw, 36px) !important; }

@media (max-width: 560px) {
  body.fp-home .inst-stub .fp-ex-submit { font-size: 15.5px !important; }
  body.fp-home .inst-stub .fp-ex-title { font-size: clamp(22px, 6.4vw, 27px) !important; }
  /* The three-track route is a desktop fact. instrument.css stacks From above
     To under 560px (and check-express-layout asserts that phone layout), so the
     desktop track/area override has to stand down here or the two halves stay
     side by side at 149px each. */
  body.fp-home .inst-stub .fp-ex-grid {
    grid-template-columns: minmax(0, 1fr) !important;
    grid-template-rows: none !important;
  }
  /* Every desktop area has to be released, not just the name spans: a single
     explicit track plus a child pinned to column 3 makes the grid create two
     implicit tracks (measured 49px | 34px | 254px, the From field shrunk to a
     sliver). instrument.css's `order` rules then stack the row. */
  body.fp-home .inst-stub .fp-ex-grid > * { grid-area: auto !important; }
  /* id-specific: the two desktop name placements above outrank `> *`, and a
     pinned column 3 is enough to make the grid open two implicit tracks. */
  body.fp-home .inst-stub .fp-ex-grid > #fp-ex-name-from,
  body.fp-home .inst-stub .fp-ex-grid > #fp-ex-name-to { grid-area: auto !important; }
  /* the 960px block sets width:100%, which filled the viewport and defeated the
     side margin; auto width lets the 10px gutter actually show. */
  body.fp-home:not(.fp-inst) .inst-stub { width: auto !important; margin-inline: 10px !important; }
}

/* ==========================================================================
   THE FOOTER — the back face of the pass, on every homepage.

   This block used to live inline in public/index.html scoped to
   `body footer.apf`, i.e. the English page only: the 41 locale homes kept the
   legacy centre-aligned wall of emoji links, so the family ended in two
   different designs. It is ONE layer now, scoped to body.fp-home so it reaches
   every homepage and no other page family (the country guides and the
   checkout do not load this file at all).

   Why the declarations carry !important: they must win over ~34 legacy layers
   plus the per-locale `#fp-footer-inst` block, which sets
   `body:not(.fp-inst) footer{...!important}` on all 41 pages. Higher
   specificity plus a later source position does that without touching those
   legacy blocks.
   ========================================================================== */
body.fp-home footer.apf {
  position: relative;
  overflow: hidden;
  margin-top: 0;
  padding: clamp(36px, 5vw, 64px) 0 28px;
  /* navy field + one amber radial, and a solid colour underneath so a browser
     that drops the gradient still gets the navy and not the paper page */
  background: radial-gradient(900px 320px at 90% -10%, rgba(255, 230, 109, .14), transparent 60%),
    linear-gradient(180deg, #1a1a2e 0%, #12122a 100%) #12122a !important;
  color: #ece8df !important;
  border-radius: 6px 6px 0 0;
  /* the card above ends in paper: a hard amber hairline + inset shadow reads as
     the ticket's torn edge without drawing a border box */
  box-shadow: inset 0 3px 0 #FFE66D, inset 0 24px 40px -30px rgba(255, 230, 109, .35);
  /* the Instrument tokens are scoped to .inst-band/.inst-barcode/.fp-ex, so
     every var() below would silently take its fallback here */
  --i-amber: #FFE66D;
  --i-mono: "JetBrains Mono", ui-monospace, "IBM Plex Mono", Menlo, Consolas, monospace;
}
body.fp-home footer.apf .wrap {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 clamp(16px, 4vw, 32px);
}
body.fp-home footer.apf .fpx-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(20px, 3vw, 40px);
  align-items: start;
  text-align: start;
}
body.fp-home footer.apf .fpx-col {
  display: flex;
  flex-direction: column;
  /* the locale pages' legacy footer centres everything (`footer a`, `.fpx-col`
     inherited align-items:center), which left the column heads floating over
     their own dashed rule and the rows ragged-right. The pass reads left (start). */
  align-items: flex-start;
  gap: 6px;
  min-width: 0;
  background: none;
}
body.fp-home footer.apf .fpx-grid h3 {
  margin: 0 0 8px;
  padding-bottom: 8px;
  border-bottom: 1px dashed rgba(255, 230, 109, .35);
  color: #FFE66D;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 2px;
  text-transform: uppercase;
}
body.fp-home footer.apf .fpx-grid a {
  display: inline-flex;
  align-items: center;
  /* !important because the legacy per-locale mobile block sets
     `footer .fpx-col a{min-height:40px!important}` — without it the 44px touch
     row on phones silently stayed at 40. */
  min-height: 32px !important;
  padding: 3px 0;
  color: #ece8df;
  font-size: 14px;
  line-height: 1.5;
  text-decoration: none;
  overflow-wrap: anywhere;
}
body.fp-home footer.apf .fpx-grid a:hover,
body.fp-home footer.apf .fpx-grid a:focus-visible {
  color: #FFE66D;
}
/* The wordmark: the locales' footer never had a logo before (the legacy wall
   started with a divider), so the mark and its type are declared here rather
   than relying on the header's rules. */
body.fp-home footer.apf .logo {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
}
body.fp-home footer.apf .fp-logo-mark { flex-shrink: 0; }
body.fp-home footer.apf .fp-logo-word {
  color: #ece8df;
  font-family: Outfit, 'DM Sans', sans-serif;
  font-size: 21px;
  letter-spacing: -.015em;
  white-space: nowrap;
}
body.fp-home footer.apf .fp-logo-word b { color: #FFE66D; font-weight: 900; }
body.fp-home footer.apf .fpx-brand .blurb {
  max-width: 44ch;
  margin: 14px 0 12px;
  color: rgba(236, 232, 223, .6);
  font-size: 14px;
  line-height: 1.6;
}
body.fp-home footer.apf .badges {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
body.fp-home footer.apf .badges span {
  padding: 4px 9px;
  border: 1px solid rgba(255, 230, 109, .35);
  border-radius: 999px;
  background: rgba(255, 255, 255, .04);
  color: #FFE66D;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
}
/* The live-counter template holds "{n} tickets sold" in the page's language; it
   is a data source for the counter script, never a badge. The legacy footer
   sets `footer span{display:flex}` on these pages, and an author display beats
   the [hidden] attribute — so it rendered as a second badge reading "{N}". */
body.fp-home footer.apf .fp-sold-tpl { display: none !important; }
body.fp-home footer.apf .f-base {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 16px;
  margin-top: 32px;
  padding-top: 18px;
  border-top: 1px solid #2a2a48;
  color: rgba(236, 232, 223, .55);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: .06em;
  text-transform: uppercase;
}
body.fp-home footer.apf .f-base a { color: rgba(236, 232, 223, .75); }
body.fp-home footer.apf .footer-copy { opacity: 1; text-align: start; }
body.fp-home footer.apf .fpx-build {
  color: rgba(236, 232, 223, .35);
  font-size: 10px;
  letter-spacing: .02em;
  text-transform: none;
}
/* Dark toggle, PWA install and the payment badge are legacy controls with their
   own inline styles. They keep working, but they sit on a dashed rule under the
   links instead of floating between the columns. */
body.fp-home footer.apf .fpx-util {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 28px;
  padding-top: 18px;
  border-top: 1px dashed rgba(255, 230, 109, .25);
}
body.fp-home footer.apf .fpx-util > div { padding: 0 !important; margin: 0 !important; }

/* the perforation: a dashed rule between the columns, the same tear line the
   e-ticket uses, so the footer reads as the back of the pass rather than a
   generic link block. Desktop only — stacked columns need the inset, not a
   divider. */
@media (min-width: 821px) {
  body.fp-home footer.apf .fpx-grid { position: relative; }
  body.fp-home footer.apf .fpx-col {
    position: relative;
    padding-inline-start: clamp(14px, 2vw, 26px);
  }
  body.fp-home footer.apf .fpx-col::before {
    content: "";
    position: absolute;
    inset-block: clamp(2px, 1vw, 8px);
    inset-inline-start: 0;
    width: 1px;
    background: repeating-linear-gradient(180deg, rgba(255, 230, 109, .42) 0 6px, transparent 6px 12px);
  }
}
@media (max-width: 820px) {
  body.fp-home footer.apf .fpx-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  body.fp-home footer.apf .fpx-brand { grid-column: 1 / -1; }
}
@media (max-width: 520px) {
  body.fp-home footer.apf .fpx-grid { grid-template-columns: minmax(0, 1fr); }
  body.fp-home footer.apf .fpx-grid a { min-height: 44px !important; }
  body.fp-home footer.apf .f-base { font-size: 10px; }
}
@media (prefers-reduced-motion: reduce) {
  body.fp-home footer.apf .fpx-grid a { transition: none; }
}
