@font-face{font-family:'DM Sans';font-style:normal;font-weight:400;font-display:swap;src:url('../assets/fonts/dm-sans-400.woff2') format('woff2');}
@font-face{font-family:'DM Sans';font-style:normal;font-weight:500;font-display:swap;src:url('../assets/fonts/dm-sans-500.woff2') format('woff2');}
@font-face{font-family:'DM Sans';font-style:normal;font-weight:600;font-display:swap;src:url('../assets/fonts/dm-sans-600.woff2') format('woff2');}
@font-face{font-family:'DM Sans';font-style:normal;font-weight:700;font-display:swap;src:url('../assets/fonts/dm-sans-700.woff2') format('woff2');}
@font-face{font-family:'DM Sans';font-style:normal;font-weight:800;font-display:swap;src:url('../assets/fonts/dm-sans-800.woff2') format('woff2');}
:root{
  --purple:#4225A6; --purple-dark:#2E1A7A; --purple-deep:#1a1d23; --purple-night:#111318;
  --magenta:#D51254; --magenta-soft:#F0407E;
  --hl-dark:#C4B5FD;--hl-soft:#DDD6FE; --hl-light:#4225A6;
  --lilac:#F0EEF8; --lilac-2:#EDE9FC; --paper:#FCFBFF;
  --ink:#17123B; --ink-soft:#4A4270;
  --amber:#F4B740; --teal:#12B3A6;
  --hair:rgba(66,37,166,.14);
  --hair-light:rgba(255,255,255,.14);
  --grad-head:linear-gradient(135deg,#4225a6 34%,#6d1f8e 73%,#8b1b7d 93%);
  --shadow:0 24px 60px -28px rgba(21,12,54,.45);
  --shadow-sm:0 10px 30px -18px rgba(21,12,54,.5);
  --ease:cubic-bezier(.22,.61,.36,1);
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{
  font-family:'DM Sans',Arial,sans-serif;
  color:var(--ink);
  background:var(--lilac);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
  line-height:1.5;
}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
.wrap{max-width:1160px;margin:0 auto;padding:0 32px;position:relative}
.eyebrow{
  font-size:12px;font-weight:600;letter-spacing:.22em;text-transform:uppercase;
  display:inline-flex;align-items:center;gap:10px;
}
.eyebrow .sig{width:8px;height:8px;border-radius:50%;background:var(--magenta);flex:none}
h1,h2,h3{letter-spacing:-.03em;line-height:1.04;font-weight:800}
.reveal{opacity:0;transform:translateY(26px);transition:opacity .8s var(--ease),transform .8s var(--ease)}
.reveal.in{opacity:1;transform:none}
.d1{transition-delay:.08s}.d2{transition-delay:.16s}.d3{transition-delay:.24s}.d4{transition-delay:.32s}

/* ---------- Progress runway ----------
   Was a 2px dotted hairline with a magenta dot. Now a runway: asphalt strip,
   dashed centreline, piano-key threshold bars at each end, and an aircraft that
   rides it nose-down in the direction of travel with a magenta trail behind it.

   The old spine used mix-blend-mode:difference so a hairline stayed visible
   over both the dark sections and the lilac ones. That is dropped here. A blend
   group inverts everything inside it, so the aircraft's magenta would shift
   colour section by section, and moving the aircraft out of the group to avoid
   that would need a second fixed element tracking the same geometry. The runway
   carries its own contrast instead: translucent asphalt over a backdrop blur,
   which reads as a dark strip on the lilac grounds and as a slightly deeper,
   glassier strip on the purple ones. It also matches the hero stat panel, which
   is the only other element on the page using that treatment.

   The width went 2px -> 18px, so the left offset comes in from 34px to 28px to
   keep the strip's optical centre roughly where the hairline sat. ---------- */
/* --pass is the aircraft's y offset inside the runway, written every frame by
   frame(). It drives the centreline mask below. Declared here so the value
   inherits down to .rwy and so the mask has something valid to read on the
   first paint, before any scroll has happened. */
#spine{position:fixed;left:28px;top:12vh;bottom:12vh;width:18px;z-index:40;pointer-events:none;--pass:0px}
#spine .rwy{position:absolute;inset:0;border-radius:10px;overflow:hidden;
  background:rgba(10,6,28,.40);
  -webkit-backdrop-filter:blur(7px) saturate(1.25);backdrop-filter:blur(7px) saturate(1.25);
  border:1px solid rgba(255,255,255,.22);
  box-shadow:0 10px 30px -16px rgba(10,6,28,.65),inset 0 1px 0 rgba(255,255,255,.10)}
/* Centreline. Inset top and bottom so it never runs into the threshold bars.

   The dashes clear as the aircraft passes over them. A mask hides everything
   above the aircraft and leaves the runway ahead of it intact, so the strip
   reads as consumed rather than merely progressed against. The 22px subtracted
   from --pass converts the aircraft's runway-relative offset into this
   pseudo-element's own coordinate space, which starts at the same 22px inset --
   change one and change the other. The 16px band gives the dash directly under
   the nose a soft wipe instead of a hard cut; the magenta trail rises into the
   space the dashes vacate.

   Masking rather than repainting the gradient: the background stays a single
   static paint and only the mask position moves, so nothing re-rasterises on
   scroll. -webkit- first for Safari, which still needs the prefix here. */
#spine .rwy::after{content:"";position:absolute;left:50%;top:22px;bottom:22px;width:2px;
  transform:translateX(-50%);
  background:repeating-linear-gradient(180deg,rgba(255,255,255,.66) 0 11px,transparent 11px 24px);
  -webkit-mask-image:linear-gradient(180deg,transparent 0,transparent calc(var(--pass) - 22px),
    #000 calc(var(--pass) - 6px),#000 100%);
  mask-image:linear-gradient(180deg,transparent 0,transparent calc(var(--pass) - 22px),
    #000 calc(var(--pass) - 6px),#000 100%)}
/* Piano-key threshold markings. Four bars, same at both ends. */
#spine .thr{position:absolute;left:4px;right:4px;height:8px;display:flex;gap:2px}
#spine .thr.top{top:6px}
#spine .thr.bot{bottom:6px}
#spine .thr i{flex:1;border-radius:1px;background:rgba(255,255,255,.62)}
/* Distance covered. Sits under the aircraft and grows with it; height is set
   from the same scroll fraction in frame(). */
#spine .trail{position:absolute;left:50%;top:18px;width:3px;height:0;transform:translateX(-50%);
  border-radius:3px;
  background:linear-gradient(180deg,rgba(213,18,84,0) 0%,rgba(213,18,84,.55) 40%,rgba(213,18,84,.95) 100%)}
/* The aircraft. rotate(90deg) points the nose down the runway, which is the
   direction it travels as the page scrolls. */
#spine .plane{position:absolute;left:50%;top:0;width:22px;height:22px;color:var(--magenta);
  transform:translate(-50%,-50%) rotate(90deg);
  filter:drop-shadow(0 0 9px rgba(213,18,84,.75)) drop-shadow(0 1px 2px rgba(10,6,28,.5))}
#spine .plane svg{width:100%;height:100%;display:block}
@media(prefers-reduced-motion:reduce){#spine .plane{transition:none}}
@media(max-width:960px){#spine{display:none}}

/* ---------- Top bar ---------- */
header.bar{position:fixed;top:0;left:0;right:0;z-index:60;
  transition:background .4s var(--ease),box-shadow .4s var(--ease),padding .4s var(--ease);
  padding:20px 0}
header.bar.solid{background:rgba(14,8,36,.82);backdrop-filter:blur(14px);
  box-shadow:0 1px 0 rgba(255,255,255,.08);padding:12px 0}
.bar .wrap{display:flex;align-items:center;justify-content:space-between;gap:20px}
.brandlock{display:flex;align-items:center;gap:14px}
.brandlock img{height:27px}
.brandlock .x{color:rgba(255,255,255,.5);font-weight:600;font-size:13px;letter-spacing:.1em}
.brandlock .eg-logo{height:22px;width:auto}
nav.jump{display:flex;align-items:center;gap:26px}
@media(max-width:1040px){nav.jump{gap:18px}.brandlock{gap:10px}}
nav.jump a{font-size:13px;font-weight:600;color:rgba(255,255,255,.72);letter-spacing:.02em;position:relative;padding:4px 0}
nav.jump a::after{content:"";position:absolute;left:0;bottom:-2px;height:2px;width:0;background:var(--magenta);transition:width .3s var(--ease)}
nav.jump a:hover{color:#fff}nav.jump a:hover::after{width:100%}
.edition{font-size:11px;font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:rgba(255,255,255,.6);
  border:1px solid rgba(255,255,255,.22);border-radius:100px;padding:6px 12px;white-space:nowrap}
/* Raised from 820px: the enlarged lockup needs more room before the nav and
   edition pill can share the row without being squeezed. */
@media(max-width:900px){nav.jump,.edition{display:none}}

/* ---------- Hero ---------- */
/* padding-top is load-bearing: the hero bottom-aligns inside min-height, so
   whenever the content is taller than 82vh (any landscape phone) it overflows
   upward. With no top padding that put the kicker and H1 underneath the fixed
   bar, which sits at z-index 60 against the hero content's z-index 3.
   Reserving the bar's height makes the section grow instead of collide. */
.hero{position:relative;min-height:82vh;display:flex;align-items:flex-end;
  padding:92px 0 6vh;overflow:hidden;background:var(--purple-night)}
.hero .bg{position:absolute;inset:-12% 0;z-index:0;will-change:transform}
/* The hero crops HORIZONTALLY, not vertically, which is worth knowing before
   anyone tries to reframe it. The layer is 124% of the section and the image is
   120% of that, so at 1440x820 the box is 1440x1220 against a 3:2 source: cover
   scales to height and trims ~390px off the width. Changing the Y value does
   nothing; X is the only axis with travel.

   Hence 70% rather than June's centre. July's photo puts the traveller and the
   case in the right third, and centring cut the case in half against the edge
   of the frame. */
.hero .bg img{width:100%;height:120%;object-fit:cover;object-position:70% 50%;filter:saturate(1.02)}
.hero .scrim{position:absolute;inset:0;z-index:1;
  background:linear-gradient(180deg,rgba(14,8,36,.72) 0%,rgba(14,8,36,.38) 30%,rgba(21,12,54,.86) 78%,var(--purple-night) 100%)}
.hero .scrim2{position:absolute;inset:0;z-index:1;mix-blend-mode:multiply;
  background:linear-gradient(120deg,rgba(66,37,166,.75),transparent 60%)}
/* Deliberately NOT position:relative. The stat panel is nested in here now, and
   on desktop it is absolutely positioned against .hero -- giving .wrap a
   position would make it the containing block and shift the panel. z-index
   still applies because .wrap is a flex item of .hero. */
.hero .wrap{position:static;z-index:3;width:100%}
/* On desktop both of these are plain blocks: the panel inside is absolute and
   out of flow, so the headline and paragraph lay out exactly as they always did.
   Neither may ever carry .reveal or any other transform -- a transformed
   ancestor becomes the containing block for the absolutely positioned panel and
   would drag it out of position, then jump it back when the transform clears.
   The reveals belong on the h1 and p themselves. */
.hero-mid{}
.hero-copy{}
.hero .kicker{color:rgba(255,255,255,.86);margin-bottom:20px}
.hero h1{color:#fff;font-size:clamp(40px,6.8vw,88px);max-width:14ch}
.hero h1 .hl{color:#fff;position:relative;display:inline-block;z-index:1}
.hero h1 .hl::after{content:"";position:absolute;left:-.03em;right:-.03em;bottom:.03em;height:.16em;
  background:#D51254;z-index:-1;border-radius:2px}
.hero p.sub{color:rgba(255,255,255,.8);font-size:clamp(15px,1.8vw,19px);max-width:52ch;margin-top:18px;font-weight:400}
.flightstrip{display:inline-flex;align-items:center;gap:0;margin-top:28px;
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.18);border-radius:14px;
  backdrop-filter:blur(8px);overflow:hidden}
.flightstrip .leg{padding:14px 22px;display:flex;flex-direction:column;gap:2px}
.flightstrip .leg .code{font-size:20px;font-weight:800;color:#fff;letter-spacing:.04em}
.flightstrip .leg .lbl{font-size:10px;font-weight:600;letter-spacing:.16em;color:rgba(255,255,255,.6);text-transform:uppercase}
.flightstrip .path{position:relative;width:96px;height:2px;background:rgba(255,255,255,.28);margin:0 4px}
.flightstrip .path .plane-icon{position:absolute;top:50%;left:0;transform:translateY(-50%) rotate(0deg);
  width:16px;height:16px;animation:flyPlane 3.4s var(--ease) infinite}
@keyframes flyPlane{0%{left:-8px;opacity:0}12%{opacity:1}88%{opacity:1}100%{left:calc(100% - 8px);opacity:0}}

/* --fs-px drives both the panel's padding and the rule's negative margin, so
   the rule stays full-bleed at every breakpoint from one value. */
.hero .floatstat{--fs-px:30px;
  position:absolute;right:6%;top:44%;z-index:3;will-change:transform;min-width:296px;
  padding:26px var(--fs-px) 22px;border-radius:22px;
  background:rgba(255,255,255,.08);
  border:1px solid rgba(255,255,255,.18);
  backdrop-filter:blur(18px) saturate(1.4);
  -webkit-backdrop-filter:blur(18px) saturate(1.4);
  box-shadow:0 8px 32px rgba(14,8,36,.28),inset 0 1px 0 rgba(255,255,255,.22)}
.hero .floatstat .n{font-weight:800;letter-spacing:-.04em;line-height:1;font-variant-numeric:tabular-nums}
/* The headline metric is pure white, digits and % alike, so nothing competes
   with it. The two supporting stats sit a step back in a soft lavender --
   number and unit in the same colour, so each reads as one value rather than
   a figure with a differently-coloured sign stuck on. */
.hero .floatstat .fs-lead .n,
.hero .floatstat .fs-lead .n b,
.hero .floatstat .fs-lead .n .u{color:#fff}
.hero .floatstat .fs-cell .n,
.hero .floatstat .fs-cell .n b,
.hero .floatstat .fs-cell .n .u{color:var(--hl-soft)}
.hero .floatstat .l{font-weight:600;text-transform:uppercase;color:rgba(255,255,255,.78)}
.hero .floatstat .fs-lead{text-align:center}
.hero .floatstat .fs-lead .n{font-size:clamp(44px,5.4vw,68px)}
.hero .floatstat .fs-lead .l{font-size:11px;letter-spacing:.18em;margin-top:9px}
.hero .floatstat .fs-rule{height:1px;background:rgba(255,255,255,.16);
  margin:18px calc(var(--fs-px) * -1) 16px}
.hero .floatstat .fs-sub{display:grid;grid-template-columns:1fr 1fr}
/* Desktop keeps the two stats side by side, split by a vertical border, so the
   horizontal divider between them is mobile-only. */
.hero .floatstat .fs-sub .fs-rule{display:none}
.hero .floatstat .fs-cell{text-align:center;padding:0 10px}
/* ~ not +: the divider element now sits between the two cells, so the adjacent
   sibling selector would no longer match. */
.hero .floatstat .fs-cell ~ .fs-cell{border-left:1px solid rgba(255,255,255,.16)}
.hero .floatstat .fs-cell .n{font-size:clamp(19px,1.9vw,25px)}
.hero .floatstat .fs-cell .l{font-size:9px;letter-spacing:.13em;margin-top:7px;color:rgba(255,255,255,.62)}
@media(max-width:1080px){.hero .floatstat{--fs-px:24px;right:4%;top:auto;bottom:20%;
  padding:20px var(--fs-px) 18px;min-width:262px}}

/* Below 820px the panel drops out of its absolute slot and becomes the right
   column of a two-column row. The left column is the headline AND the paragraph
   together, so the panel spans both: its top lines up with the headline, its
   bottom with the last line of the paragraph.

   align-items:stretch does the real work. This row used to be
   align-items:center with the paragraph alone, so a panel taller than the
   paragraph pushed dead space above and below it. Stretching the panel to the
   copy's height removes that gap by construction rather than by tuning margins,
   and "no overlap" stays structural: the copy cannot grow under the panel,
   because the panel owns its own column. */
@media(max-width:820px){
  .hero{flex-direction:column;justify-content:flex-end;align-items:stretch}
  .hero-mid{display:flex;align-items:stretch;gap:14px}
  .hero-copy{flex:1 1 auto;min-width:0}
  .hero p.sub{font-size:13px;line-height:1.5;max-width:none;margin-top:20px}

  /* display:contents dissolves .fs-sub, so all five pieces -- lead, divider,
     stat, divider, stat -- become direct children of one flex column. That is
     what makes space-between able to give every gap the same height. Nesting
     the two stats inside a wrapper meant their spacing was set by the wrapper's
     own rules and could never match the gaps around the first divider.
     Equal-height bands with justify-content:center could not do this either:
     the lead's number is larger, so centring left less room under it than under
     the smaller stats. Spacing the gaps directly, rather than the bands, is
     what makes them even. */
  .hero .floatstat{--fs-px:11px;
    position:static;flex:0 0 auto;width:fit-content;min-width:0;margin:0;
    padding:15px var(--fs-px);border-radius:14px;text-align:center;
    display:flex;flex-direction:column;justify-content:space-between;
    transform:none !important}          /* !important beats the parallax inline transform */
  .hero .floatstat .fs-sub{display:contents}
  .hero .floatstat .fs-sub .fs-rule{display:block}
  .hero .floatstat .fs-rule{margin:0;flex:0 0 auto}
  .hero .floatstat .fs-lead{flex:0 0 auto;text-align:center}
  .hero .floatstat .fs-lead .n{font-size:24px}
  .hero .floatstat .fs-lead .l{font-size:7.5px;letter-spacing:.1em;margin-top:4px}
  .hero .floatstat .fs-cell{flex:0 0 auto;text-align:center;padding:0}
  .hero .floatstat .fs-cell ~ .fs-cell{border-left:none}
  .hero .floatstat .fs-cell .n{font-size:15px}
  .hero .floatstat .fs-cell .l{font-size:7.5px;letter-spacing:.06em;margin-top:3px}
}
/* Landscape phones: 82vh is only ~320px, far less than the hero content needs.
   Drop the min-height entirely and scale the type down so it fits without the
   section ballooning. Keyed on height, so it catches landscape at any width. */
@media(max-height:560px){
  .hero{min-height:auto;padding:88px 0 44px}
  .hero h1{font-size:clamp(28px,4.4vw,42px)}
  .hero p.sub{font-size:14.5px;margin-top:12px;max-width:60ch}
  .hero .kicker{margin-bottom:14px}
  .flightstrip{margin-top:18px}
  .flightstrip .leg{padding:10px 16px}
  .flightstrip .leg .code{font-size:16px}
}

/* Remove default focus/active outline ring on interactive elements */
.note, .cta, .chat-prompt, .gate, .pass, button, a, input {
  outline: none;
  -webkit-tap-highlight-color: transparent;
}
.note:focus, .cta:focus, .chat-prompt:focus, button:focus, a:focus {
  outline: none;
}

/* ---------- Section shells ---------- */
section{position:relative}
/* Section rhythm. All .pad sections share one value so the space above every
   eyebrow stays identical; change it here and the whole page stays even. */
.pad{padding:88px 0}
.sec-head{max-width:640px;margin-bottom:56px}
.sec-head h2{font-size:clamp(30px,4.4vw,52px);margin-top:16px}
.sec-head p{margin-top:18px;font-size:17px;color:var(--ink-soft);font-weight:400}
.dark{background:var(--purple-deep);color:#fff}
.dark .sec-head p{color:rgba(255,255,255,.5)}
.dark .eyebrow{color:rgba(255,255,255,.8)}

/* ---------- Departure board (KPIs) ---------- */
.board{border:1px solid rgba(255,255,255,.12);border-radius:20px;overflow:hidden;background:linear-gradient(180deg,rgba(255,255,255,.05),rgba(255,255,255,.01))}
.board-top{display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:16px 24px;background:rgba(0,0,0,.28);border-bottom:1px solid rgba(255,255,255,.1)}
.board-top .t{font-size:12px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:rgba(255,255,255,.8);display:flex;align-items:center;gap:10px}
.board-top .t .dot{width:8px;height:8px;border-radius:50%;background:var(--amber);box-shadow:0 0 12px var(--amber);animation:blink 2.4s steps(2) infinite}
@keyframes blink{50%{opacity:.3}}
.board-top .now{display:flex;align-items:center;gap:12px;flex-wrap:wrap;justify-content:flex-end;
  font-size:12px;font-weight:600;letter-spacing:.14em;color:rgba(255,255,255,.55);text-transform:uppercase}
/* The reporting period is the one thing a reader checks first, so it gets a
   pill rather than being buried in the same grey run as the scope text. */
.board-top .now .range{color:#fff;font-weight:700;letter-spacing:.1em;white-space:nowrap;
  border:1px solid rgba(255,255,255,.24);background:rgba(255,255,255,.06);border-radius:100px;padding:5px 12px}
.kpis{display:grid;grid-template-columns:repeat(4,1fr)}
.kpi{padding:34px 26px;border-right:1px solid rgba(255,255,255,.1);border-bottom:1px solid rgba(255,255,255,.1);position:relative;overflow:hidden}
.kpi:nth-child(4n){border-right:none}
.kpi::before{content:"";position:absolute;left:0;top:0;bottom:0;width:0;background:rgba(213,18,84,.14);transition:width .5s var(--ease)}
.kpi:hover::before{width:100%}
.kpi .val{font-size:clamp(30px,3.6vw,46px);font-weight:800;letter-spacing:-.03em;font-variant-numeric:tabular-nums;position:relative}
.kpi .val .pre,.kpi .val .suf{color:var(--hl-dark)}
.kpi .lbl{position:relative;margin-top:12px;font-size:12px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.6)}
.kpi .sub{position:relative;margin-top:6px;font-size:13px;color:rgba(255,255,255,.44);font-weight:400}
.kpi.flip .val{animation:flipIn .6s var(--ease) both}
@keyframes flipIn{0%{transform:rotateX(-90deg);opacity:0}100%{transform:none;opacity:1}}

/* ---------- Month-on-month chart ---------- */
.mom{margin-top:22px;border:1px solid rgba(255,255,255,.12);border-radius:20px;overflow:hidden;
  background:linear-gradient(180deg,rgba(255,255,255,.05),rgba(255,255,255,.01))}
.mom-top{display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:16px 24px;background:rgba(0,0,0,.28);border-bottom:1px solid rgba(255,255,255,.1)}
.mom-top .t{font-size:12px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:rgba(255,255,255,.8);display:flex;align-items:center;gap:10px}
.mom-top .t .dot{width:8px;height:8px;border-radius:50%;background:var(--hl-dark);box-shadow:0 0 12px var(--hl-dark);flex:none}
.mom-top .now{font-size:12px;font-weight:600;letter-spacing:.14em;color:rgba(255,255,255,.55);text-transform:uppercase;white-space:nowrap}
.mom-body{padding:26px 24px 22px}
.mom-legend{display:flex;align-items:center;gap:22px;margin-bottom:6px}
.mom-legend .lg{display:inline-flex;align-items:center;gap:8px;font-size:12px;font-weight:600;
  letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.66)}
.mom-legend .lg i{width:16px;height:3px;border-radius:2px;flex:none}
.mom-legend .roas i{background:var(--hl-dark)}
.mom-legend .cpa i{background:var(--magenta-soft)}
.mom-chart svg{width:100%;height:auto;display:block;overflow:visible}
.mom-chart .grid{stroke:rgba(255,255,255,.10);stroke-width:1}
.mom-chart .axis{fill:rgba(255,255,255,.5);font-size:12px;font-weight:500;font-variant-numeric:tabular-nums}
.mom-chart .axis-title{fill:rgba(255,255,255,.42);font-size:11px;font-weight:600;letter-spacing:.16em;text-transform:uppercase}
.mom-chart .ln{fill:none;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round}
.mom-chart .ln.roas{stroke:var(--hl-dark)}
.mom-chart .ln.cpa{stroke:var(--magenta-soft)}
.mom-chart .pt{stroke:var(--purple-deep);stroke-width:2}
.mom-chart .pt.roas{fill:var(--hl-dark)}
.mom-chart .pt.cpa{fill:var(--magenta-soft)}
.mom-chart .dl{font-size:11.5px;font-weight:700;font-variant-numeric:tabular-nums}
.mom-chart .dl.roas{fill:var(--hl-dark)}
.mom-chart .dl.cpa{fill:var(--magenta-soft)}
.mom-chart .jun-band{fill:rgba(255,255,255,.06)}
.mom-chart .jun-rule{stroke:rgba(255,255,255,.28);stroke-width:1;stroke-dasharray:3 4}
.mom-chart .jun-tick{fill:#fff;font-weight:700}
.mom-chart .pill-bg.roas{fill:var(--hl-dark)}
.mom-chart .pill-bg.cpa{fill:var(--magenta-soft)}
.mom-chart .pill-tx{font-size:12px;font-weight:800;fill:var(--purple-deep);font-variant-numeric:tabular-nums}
.mom-chart .halo{fill:none;stroke-width:2}
.mom-chart .halo.roas{stroke:var(--hl-dark);opacity:.45}
.mom-chart .halo.cpa{stroke:var(--magenta-soft);opacity:.45}
.mom-chart .mini-title{fill:rgba(255,255,255,.7);font-size:11px;font-weight:700;letter-spacing:.16em;text-transform:uppercase}
.mom-foot{font-size:13px;color:rgba(255,255,255,.55);font-weight:400;margin-top:18px;max-width:70ch}
.mom-foot b{color:rgba(255,255,255,.92);font-weight:700}
.mom-chart .draw{stroke-dasharray:var(--len);stroke-dashoffset:var(--len);transition:stroke-dashoffset 1.5s var(--ease)}
.mom.in .mom-chart .draw{stroke-dashoffset:0}
.mom-chart .fadein{opacity:0;transition:opacity .6s var(--ease) .9s}
.mom.in .mom-chart .fadein{opacity:1}
@media(prefers-reduced-motion:reduce){
  .mom-chart .draw{stroke-dasharray:none;stroke-dashoffset:0;transition:none}
  .mom-chart .fadein{opacity:1;transition:none}
}

/* ---------- Boarding passes (brands) ---------- */
/* All four passes share one size. The priority pass is marked by colour
   (magenta border, magenta stub) rather than by being larger. */
.passes{display:grid;grid-template-columns:1fr 1fr;gap:20px}
.pass{position:relative;background:var(--paper);border-radius:18px;box-shadow:var(--shadow-sm);
  display:grid;grid-template-columns:1fr 104px;overflow:hidden;transition:transform .45s var(--ease),box-shadow .45s var(--ease);
  border:1px solid var(--hair)}
.pass:hover{transform:translateY(-6px);box-shadow:var(--shadow)}
.pass .main{padding:20px 22px}
.pass .flag{display:inline-flex;align-items:center;gap:7px;font-size:9.5px;font-weight:700;letter-spacing:.15em;
  text-transform:uppercase;color:var(--magenta);margin-bottom:12px}
.pass .flag .sig{width:6px;height:6px;border-radius:50%;background:var(--magenta);animation:pulse 2s infinite}
.pass .flag.alt{color:var(--purple)}
.pass .flag.alt .sig{background:var(--purple);animation:none}
@keyframes pulse{0%,100%{box-shadow:0 0 0 0 rgba(213,18,84,.5)}50%{box-shadow:0 0 0 6px rgba(213,18,84,0)}}
.pass .toprow{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:16px}
.pass .logo{height:21px;display:flex;align-items:center}
.pass .logo img{height:100%;width:auto;object-fit:contain}
.pass .logo img.tall{height:17px}
.pass .fmt{font-size:9px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--purple);
  background:var(--lilac-2);padding:5px 10px;border-radius:100px;white-space:nowrap}
.pass .fields{display:grid;grid-template-columns:repeat(3,auto);gap:16px}
.pass .field .fl{font-size:9px;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-soft)}
.pass .field .fv{font-size:19px;font-weight:800;letter-spacing:-.02em;margin-top:4px;font-variant-numeric:tabular-nums;white-space:nowrap}
.pass .field.roas .fv{color:var(--purple)}
/* flex-wrap is the safety net: "Activated via [DSP]" plus the benchmark chip
   does not fit on one line in every pass at every width, and without wrapping
   the overflow shoves the ticket stub outside the card. */
.pass .dsp{margin-top:16px;display:flex;align-items:center;gap:9px;flex-wrap:wrap;row-gap:10px;
  font-size:11.5px;color:var(--ink-soft);font-weight:500}
.pass .dsp .bm{margin-left:auto}
.pass .dsp .chip{display:inline-flex;align-items:center;height:30px;padding:0 11px;background:#fff;border:1px solid var(--hair);border-radius:7px;flex:none}
.pass .dsp .chip img{height:17px;width:auto}
/* DV360 ships as a two-line stacked lockup, so at a shared cap height it reads
   noticeably smaller than the single-line Trade Desk wordmark next to it. Sizing
   it up on its own keeps the two optically matched rather than mathematically
   equal. Matched by alt text, since that is what the markup carries. */
.pass .dsp .chip img[alt="DV360"]{height:21px}
.pass .stub{position:relative;background:var(--grad-head);color:#fff;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:10px;padding:16px 10px}
.pass .stub::before{content:"";position:absolute;left:-8px;top:0;bottom:0;width:16px;
  background:radial-gradient(circle at 0 50%,transparent 0 7px,var(--paper) 7px) 0 0/16px 22px repeat-y}
.pass .stub .brl{writing-mode:vertical-rl;transform:rotate(180deg);font-size:8px;font-weight:600;letter-spacing:.24em;text-transform:uppercase;color:rgba(255,255,255,.72)}
.pass .stub .barcode{height:52px;width:28px;background:
  repeating-linear-gradient(90deg,#fff 0 2px,transparent 2px 4px,#fff 4px 5px,transparent 5px 9px,#fff 9px 10px,transparent 10px 13px)}
.pass .stub .seat{font-size:16px;font-weight:800;letter-spacing:.02em}
/* The CTV pass spans row 2 rather than leaving a hole beside it. Its three
   fields spread across the extra width instead of clustering at the left edge,
   and the stub widens a step so the ticket stays in proportion. */
.pass.wide{grid-column:1 / -1;grid-template-columns:1fr 132px}
.pass.wide .fields{grid-template-columns:repeat(3,minmax(0,1fr));max-width:640px}
/* Same cap on the DSP row. Without it margin-left:auto throws the benchmark
   chip to the far edge of the card while the figures stop at 640px. */
/* .bm uses margin-left:auto to sit at the far end of the row. On the wide pass
   that flung it to the 640px cap, leaving a gap the eye reads as a mistake.
   Dropping the auto margin lets it sit right after the DSP chip on the row's
   own 9px gap, which is how it already behaves on the two narrow passes where
   the row runs out of width naturally. */
.pass.wide .dsp{max-width:640px}
.pass.wide .dsp .bm{margin-left:0}
.pass.wide .stub .barcode{width:34px}
@media(max-width:900px){.pass.wide{grid-template-columns:1fr 104px}}
@media(max-width:760px){.pass.wide{grid-template-columns:1fr 84px}}

/* priority pass: colour only, same footprint as the rest */
.pass.priority{border:1px solid rgba(213,18,84,.4);box-shadow:0 26px 60px -34px rgba(213,18,84,.5)}
.pass.priority .stub{background:linear-gradient(160deg,var(--magenta),#8b1b7d)}
/* Raised from 760px: two passes side by side leave the DSP row too narrow for
   the benchmark chip once the stub takes its 104px. */
@media(max-width:900px){.passes{grid-template-columns:1fr}}
@media(max-width:760px){
  .pass{grid-template-columns:1fr 84px}
  /* Type comes down a step across the whole pass so the three fields fit on one
     line. "Post-ad Rev" was wrapping to "Post-ad / Rev" on narrower handsets,
     which broke the row into two heights and threw the ticket out of line. */
  .pass .main{padding:16px 16px}
  .pass .fields{gap:10px}
  .pass .field .fl{font-size:8px;letter-spacing:.08em;white-space:nowrap}
  .pass .field .fv{font-size:15px}
  .pass .flag{font-size:8.5px;letter-spacing:.1em;margin-bottom:10px}
  .pass .fmt{font-size:8px;padding:4px 8px}
  .pass .logo{height:18px}
  .pass .logo img.tall{height:15px}
  .pass .dsp{font-size:10.5px;margin-top:13px;gap:7px}
  .pass .dsp .chip{height:26px;padding:0 9px}
  .pass .dsp .chip img{height:14px}
  .pass .dsp .chip img[alt="DV360"]{height:18px}
  /* The benchmark chips leave with the space: on a phone the pass has to carry
     spend, revenue and pROAS legibly first, and the same callouts are still in
     the format table right below. */
  .pass .dsp .bm{display:none}
}

/* ---------- Benchmark callouts ----------
   One chip, used on the boarding passes and in the format table so the two
   never disagree. Purple for above, magenta for below: magenta is the palette's
   attention colour, and a line under its benchmark is exactly the thing a
   reader should not skim past. Greying the misses would have been quieter but
   would also have hidden them. */
.bm{display:inline-flex;align-items:center;gap:5px;padding:4px 9px;border-radius:6px;
  font-size:10px;font-weight:700;letter-spacing:.03em;white-space:nowrap;
  font-variant-numeric:tabular-nums;line-height:1}
.bm .arw{font-size:7px;line-height:1;transform:translateY(.5px)}
.bm.up{background:var(--lilac-2);color:var(--purple)}
.bm.down{background:rgba(213,18,84,.09);color:var(--magenta)}

/* Format Overview table */
.fmt-table-wrap{border-radius:20px;overflow:hidden;background:var(--paper);border:1px solid var(--hair);box-shadow:var(--shadow-sm)}
.fmt-table-head{padding:22px 28px;display:flex;align-items:center;gap:18px;border-bottom:1px solid var(--hair)}
.fmt-table-head .eyebrow{color:var(--purple)}
.fmt-sub{font-size:14px;color:var(--ink-soft);font-weight:400}
.fmt-table-outer{overflow-x:auto}
.fmt-table{width:100%;border-collapse:collapse;font-size:14px}
.fmt-table thead tr{background:linear-gradient(135deg,#4225a6 0%,#2e1a7a 60%,#1f1252 100%)}
.fmt-table th{text-align:left;padding:16px 20px;font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:#fff;border-bottom:none;white-space:nowrap}
.fmt-table th.r,.fmt-table td.r{text-align:right}
.fmt-table th.hl-col{color:#fff}
.fmt-table td{padding:16px 20px;border-bottom:1px solid var(--hair);font-weight:500;vertical-align:middle}
.fmt-table tr:last-child td{border-bottom:none}
.fmt-table tr.hi{background:rgba(66,37,166,.04)}
.fmt-table td.r{font-variant-numeric:tabular-nums;font-weight:700}
.fmt-table td.hl-col{color:var(--purple);font-weight:800;font-size:16px}
.fmt-pill{display:inline-block;padding:5px 12px;border-radius:8px;font-size:12px;font-weight:600;letter-spacing:.04em}
.fmt-pill.disp{background:var(--lilac-2);color:var(--purple)}
.fmt-pill.ctv-pill{background:rgba(244,183,64,.12);color:#b5870a}
/* Video is a new format on this page; its own tint keeps it distinct from the
   purple Display pill without reaching for magenta, which stays rationed. */
.fmt-pill.vid{background:rgba(46,26,122,.10);color:var(--purple-dark)}

/* Format table, now standalone and full width. Taller rows and a larger pROAS
   figure give it presence so it does not read as a stranded strip where the
   two-up pair used to be. */
.fmt-table.fmt-wide th{padding:16px 24px;font-size:11px}
.fmt-table.fmt-wide td{padding:22px 24px;font-size:15px}
.fmt-table.fmt-wide td.hl-col{font-size:22px}
.fmt-table.fmt-wide .fmt-pill{padding:6px 14px;font-size:13px}
/* Center-aligned columns: pROAS + Post-ad Rev (Format table), DSP + Format (Geo).
   .c wins over the .r right-align because it is listed after it here. */
.fmt-table.mini th.c,.fmt-table.mini td.c{text-align:center}
/* Nudge the type down so "Display & Video" and "United Kingdom" stay on one
   line in the narrower side-by-side columns. */
.fmt-table.mini{font-size:12.5px}
.fmt-table.mini th{font-size:9.5px;letter-spacing:.1em;padding:12px 14px;white-space:nowrap}
.fmt-table.mini td{padding:13px 14px;white-space:nowrap}
.fmt-table.mini .fmt-pill{padding:4px 9px;font-size:11px;white-space:nowrap}
.fmt-table.mini .dsp-text{white-space:nowrap}
.fmt-table.mini td.hl-col{font-size:15px}

/* ===== New Activations ===== */
.activations{background:var(--lilac)}
.sec-sub{margin-top:18px;font-size:17px;color:var(--ink-soft);font-weight:400;max-width:640px}
.act-block{margin-top:40px}
.act-block+.act-block{margin-top:56px}
.act-head{display:flex;align-items:center;justify-content:space-between;gap:20px;margin-bottom:20px;flex-wrap:wrap}
.act-title{font-size:22px;font-weight:700;color:var(--ink)}
/* Brand toggle: two logo buttons, the active one lifted onto white. */
.brand-toggle{display:inline-flex;gap:6px;background:var(--lilac-2);border-radius:12px;padding:5px}
.bt-btn{display:inline-flex;align-items:center;justify-content:center;height:40px;min-width:104px;padding:0 20px;
        background:transparent;border:0;border-radius:8px;cursor:pointer;transition:background .18s var(--ease),box-shadow .18s var(--ease)}
.bt-btn img{height:19px;width:auto;opacity:.5;transition:opacity .18s var(--ease)}
.bt-btn:hover img{opacity:.78}
.bt-btn.is-active{background:#fff;box-shadow:var(--shadow-sm)}
.bt-btn.is-active img{opacity:1}
/* Static brandmark for the Other Brand-Specific block (no toggle). */
.act-brandmark{display:inline-flex;align-items:center;height:40px;padding:0 18px;background:#fff;border-radius:10px;box-shadow:var(--shadow-sm)}
.act-brandmark img{height:19px;width:auto}
/* The activations tables carry more columns; let them scroll on narrow screens
   rather than crush the numbers. */
.act-table{font-size:13.5px;min-width:680px}
.act-table th{padding:14px 16px;font-size:10.5px;white-space:nowrap}
.act-table td{padding:15px 16px;white-space:nowrap}
.act-table .fmt-pill{white-space:nowrap}
/* "Reporting awaited" - a quiet neutral pill so an empty metric does not shout. */
.await{display:inline-block;padding:4px 11px;border-radius:8px;font-size:11.5px;font-weight:600;
       letter-spacing:.02em;background:rgba(23,18,59,.06);color:var(--ink-soft);white-space:nowrap}
.brand-cell{min-width:120px}
.tb-logo{height:20px;width:auto;object-fit:contain}
.tb-logo.vrbo-tb{height:16px}
.tb-logo.hotels-tb{height:18px}
.dsp-text{display:inline-block;padding:5px 12px;border-radius:8px;font-size:12px;font-weight:700;letter-spacing:.06em;
  background:var(--lilac-2);color:var(--purple)}

/* ---------- Insights (dot grid) ---------- */
.insights{background:var(--purple-night);color:#fff;position:relative;overflow:hidden}
#dotgrid{position:absolute;inset:0;z-index:0}
.insights .wrap{position:relative;z-index:2}
.insights .sec-head p{color:rgba(255,255,255,.72)}
.notes{display:grid;grid-template-columns:repeat(2,1fr);gap:22px}
.note{position:relative;border:1px solid rgba(255,255,255,.12);border-radius:18px;padding:32px;overflow:hidden;
  background:linear-gradient(180deg,rgba(255,255,255,.045),transparent);transition:transform .4s var(--ease),border-color .4s var(--ease)}
.note::before{content:"";position:absolute;left:0;top:0;bottom:0;width:0;background:var(--purple);transition:width .5s var(--ease);z-index:-1}
.note:hover{transform:translateY(-6px);border-color:rgba(213,18,84,.4)}
.note:hover::before{width:100%}
.note .ic{width:46px;height:46px;border-radius:12px;display:flex;align-items:center;justify-content:center;
  background:rgba(213,18,84,.14);border:1px solid rgba(213,18,84,.3);margin-bottom:20px}
.note .ic svg{width:22px;height:22px;stroke:var(--magenta-soft);fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;transition:stroke .4s}
.note:hover .ic{background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.4)}
.note:hover .ic svg{stroke:#fff}
.note .tag{font-size:11px;font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:rgba(255,255,255,.55)}
.note h3{font-size:21px;font-weight:800;margin:8px 0 12px;letter-spacing:-.01em}
.note p{font-size:15px;color:rgba(255,255,255,.72);font-weight:400}
.pubchips{display:flex;flex-wrap:wrap;gap:10px;margin-top:18px}
.pubchips .pc{height:34px;padding:0 14px;background:#fff;border-radius:8px;display:flex;align-items:center;transition:transform .3s var(--ease)}
.pubchips .pc:hover{transform:translateY(-3px) scale(1.03)}
.pubchips .pc img{height:15px;width:auto;object-fit:contain}
.pubchips .pc img.sm{height:13px}
/* The Weather Channel ships as a square tile rather than a wordmark, so it
   needs height to stay legible where a wordmark only needs cap height. */
.pubchips .pc img.sq{height:22px;border-radius:3px}
@media(max-width:700px){.notes{grid-template-columns:1fr}}

/* ---------- Upsell ---------- */
.upsell{position:relative;overflow:hidden;background:var(--purple-deep);color:#fff}
.upsell .bg{position:absolute;inset:-12% 0;z-index:0;will-change:transform}
/* Showing more of the photo is a proportion problem, not a scale one. The
   section is a wide shallow band, about 2.56:1, and cover always fills the box:
   feed it a 3:2 source and roughly 40% of the image height is discarded no
   matter what object-position says. Neither zoom nor crop position can recover
   it.

   So the source is pre-cropped to 2.07:1 to match this box, and the box is the
   full height of .bg (100%, was 124%). Cover now trims nothing, the whole
   crop is on screen, and the subject renders about 3.8x smaller than she did
   from the original frame. The 12% overscan on .bg still feeds the parallax.

   If the source image is ever swapped, crop it to 2.07:1 or this reverts to
   discarding height. */
.upsell .bg img{width:100%;height:100%;object-fit:cover;object-position:center 50%}
/* The right stop lifts from June's .74 to .46, with an added stop at 70% so the
   falloff is not linear across the whole width. June's photo was a wide beach
   scene that worked as pure texture at any opacity; July's is a legible scene
   worth actually seeing. The 0% and 42% stops are untouched, so the copy column
   keeps exactly the contrast it had. */
.upsell .scrim{position:absolute;inset:0;z-index:1;
  background:linear-gradient(90deg,var(--purple-deep) 0%,rgba(21,12,54,.94) 42%,rgba(21,12,54,.62) 70%,rgba(21,12,54,.46) 100%)}
.upsell .wrap{position:relative;z-index:2;display:grid;grid-template-columns:1.1fr .9fr;gap:60px;align-items:center}
.upsell .flag{color:#D51254;margin-bottom:22px}
.upsell h2{font-size:clamp(34px,5vw,60px);color:#fff}
/* Lavender fill only, no underline. The hero already carries the one underlined
   .hl on the page, and repeating the device here competed with it rather than
   echoing it. This is the same rule June used behind the OmniReach wordmark. */
.upsell h2 .hl{color:var(--hl-dark)}
/* Genre strip. Full width of the wrap, its own row under both columns.
   Deliberately lighter than .omni-feats above it: those are capability claims
   and carry a border, these are inventory labels and sit on a wash, so the two
   rows do not compete when they stack on mobile. */
.genres{grid-column:1 / -1;margin-top:44px;padding-top:26px;
  border-top:1px solid rgba(255,255,255,.12)}
.gen-lbl{font-size:11px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:rgba(255,255,255,.52);margin-bottom:14px}
.gen-chips{display:flex;flex-wrap:wrap;gap:8px}
.gen-chips span{display:inline-flex;align-items:center;height:30px;padding:0 13px;
  border-radius:15px;font-size:13px;font-weight:500;color:rgba(255,255,255,.86);
  background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.10);
  transition:background .3s var(--ease),transform .3s var(--ease)}
.gen-chips span:hover{background:rgba(255,255,255,.13);transform:translateY(-2px)}
@media(max-width:860px){.genres{margin-top:30px;padding-top:22px}
  .gen-chips span{height:28px;padding:0 11px;font-size:12px}}

.omnireach-wordmark{display:inline-flex;align-items:center;vertical-align:-.12em}
.omnireach-inline{height:clamp(30px,4.4vw,52px);width:auto;display:block}
.upsell p.lead{font-size:18px;color:rgba(255,255,255,.82);margin-top:22px;max-width:46ch;font-weight:400}
.omni-feats{display:flex;flex-wrap:wrap;gap:10px;margin-top:26px}
.omni-feats span{font-size:13px;font-weight:500;letter-spacing:.02em;padding:10px 16px;border-radius:10px;
  border:1px solid rgba(255,255,255,.24);background:rgba(255,255,255,.06)}

.nextpass{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.18);border-radius:20px;
  backdrop-filter:blur(10px);overflow:hidden}
.nextpass .np-top{padding:18px 24px;border-bottom:1px dashed rgba(255,255,255,.24);display:flex;justify-content:space-between;align-items:center}
.nextpass .np-top .lbl{font-size:10px;font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:rgba(255,255,255,.6)}
.nextpass .np-top .to{font-size:22px;font-weight:800;color:#fff}
.nextpass .np-body{padding:24px}
.nextpass .np-row{display:flex;justify-content:space-between;padding:10px 0;border-bottom:1px solid rgba(255,255,255,.1);font-size:14px}
.nextpass .np-row:last-of-type{border-bottom:none}
.nextpass .np-row .k{color:rgba(255,255,255,.6)}
.nextpass .np-row .v{font-weight:700}
.cta{margin-top:20px;width:100%;display:inline-flex;align-items:center;justify-content:center;gap:10px;
  padding:16px 22px;border-radius:12px;background:var(--magenta);color:#fff;font-weight:700;font-size:15px;font-family:'DM Sans',Arial,sans-serif;
  letter-spacing:.01em;cursor:pointer;border:none;position:relative;overflow:hidden;transition:transform .3s var(--ease)}
.cta span{position:relative;z-index:2}
.cta::before{content:"";position:absolute;inset:0;background:var(--purple);transform-origin:left center;transform:scaleX(0);
  transition:transform .6s cubic-bezier(.34,1.56,.64,1);z-index:1}
.cta:hover::before{transform:scaleX(1)}
.cta:hover{transform:translateY(-2px);transition:transform .3s cubic-bezier(.34,1.56,.64,1)}
.cta svg{width:18px;height:18px;position:relative;z-index:2;transition:transform .3s var(--ease)}
.cta:hover svg{transform:translateX(4px)}
#dealLibraryCta:hover svg{transform:none}
@media(max-width:860px){.upsell .wrap{grid-template-columns:1fr;gap:34px}
  /* Stacking turns this layer into a tall narrow column, so cover shows only
     about 13% of the photo's width at 390px. Centre lands on the subject's ear
     and reads as an unidentifiable blur; 22% lands on the open sand and sea,
     which works as texture behind the copy. The desktop rule is untouched. */
  .upsell .bg img{object-position:22% 50%}}

/* placeholder note */
.phnote{margin-top:26px;font-size:12px;color:rgba(255,255,255,.5);font-weight:400;
  border-left:2px solid rgba(255,255,255,.3);padding-left:12px;max-width:44ch}

/* ---------- Footer ---------- */
footer{background:var(--purple-night);color:rgba(255,255,255,.7);padding:70px 0 46px;position:relative}
footer .ftop{display:flex;justify-content:space-between;align-items:flex-start;gap:40px;flex-wrap:wrap;
  padding-bottom:38px;border-bottom:1px solid rgba(255,255,255,.1)}
footer .fl img{height:24px;margin-bottom:16px}
footer .fl p{font-size:14px;max-width:40ch;font-weight:400}
footer .fr{display:flex;gap:56px;flex-wrap:wrap}
footer .fcol h4{font-size:11px;font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:rgba(255,255,255,.5);margin-bottom:14px}
footer .fcol a{display:block;font-size:14px;color:rgba(255,255,255,.8);padding:5px 0;transition:color .3s}
footer .fcol a:hover{color:var(--magenta-soft)}
footer .fbot{display:flex;justify-content:space-between;align-items:center;gap:20px;flex-wrap:wrap;padding-top:26px}
footer .fbot p{font-size:12px;color:rgba(255,255,255,.5)}
footer .fbot .conf{display:inline-flex;align-items:center;gap:8px}
footer .fbot .conf .sig{width:7px;height:7px;border-radius:50%;background:var(--magenta)}

@media(prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
  .reveal{opacity:1;transform:none}
  .hero .bg,.band .bg,.upsell .bg,.hero .floatstat{transform:none!important}
}


/* Gated PDF section */
.gated-pdf{background:var(--purple-deep);color:#fff}
.gated-pdf .eyebrow{color:#fff}
.gated-card{display:grid;grid-template-columns:1fr 1fr;gap:52px;align-items:center;
  background:linear-gradient(180deg,rgba(255,255,255,.05),transparent);border:1px solid rgba(255,255,255,.14);
  border-radius:24px;padding:52px}
.gated-left h2{font-size:clamp(28px,4vw,42px);color:#fff;margin-top:16px;letter-spacing:-.02em;line-height:1.1}
.gated-left p{margin-top:18px;color:rgba(255,255,255,.72);font-size:15px;max-width:42ch}
.gated-right{background:var(--paper);border-radius:18px;padding:32px;box-shadow:var(--shadow-sm)}
.gated-form{display:flex;flex-direction:column;gap:16px}
.gf-field{display:flex;flex-direction:column;gap:6px;font-size:12px;font-weight:600;letter-spacing:.04em;
  text-transform:uppercase;color:var(--ink-soft)}
.gf-field input{border:1px solid var(--hair);border-radius:10px;padding:12px 14px;font-size:15px;
  font-family:'DM Sans',Arial,sans-serif;color:var(--ink);outline:none;transition:border-color .2s;font-weight:400}
.gf-field input:focus{border-color:var(--purple)}
.gf-submit{width:100%;justify-content:center;margin-top:4px}
.gf-note{font-size:12px;color:var(--ink-soft);margin-top:2px;font-weight:400}
/* handleGatedSubmit() adds .hidden to the form, but nothing ever acted on it,
   so .gated-form{display:flex} kept the Unlock button on screen and the success
   block rendered directly beneath it -- tick flush against the button. The form
   was always meant to disappear on submit; it just never did. */
.gated-form.hidden{display:none}
.gated-success{text-align:center}
.gated-success.hidden{display:none}
.gs-icon{width:52px;height:52px;border-radius:50%;background:var(--lilac-2);color:var(--purple);
  display:flex;align-items:center;justify-content:center;margin:0 auto 16px}
.gated-success h3{font-size:20px;color:var(--ink);font-weight:800}
.gated-success p{color:var(--ink-soft);font-size:14px;margin-top:8px;font-weight:400;line-height:1.5}
@media(max-width:820px){.gated-card{grid-template-columns:1fr;padding:32px}}


/* ============================================================
   MOBILE OVERRIDES (<=680px)
   Scoped fixes for: logo image distortion, format table,
   boarding passes, the month-on-month chart, and the gated PDF
   form. Upsell Spotlight and Flight Notes are intentionally left
   untouched.
   ============================================================ */
@media(max-width:680px){

  /* The New Activations tables have 8 columns and their min-width:680px pushes
     the data columns off-screen on a phone, leaving only the header visible.
     Below the breakpoint, drop the min-width and switch each row to the same
     stacked-card layout the main table uses, so every value shows with its label. */
  .act-table{ min-width:0; }
  #activations .fmt-table-outer{ overflow-x:visible; }
  .act-table, .act-table thead, .act-table tbody,
  .act-table th, .act-table td, .act-table tr{ display:block; width:100%; }
  .act-table thead{ display:none; }
  .act-table tr{ border-bottom:1px solid var(--hair); padding:14px 18px 16px; }
  .act-table tr:last-child{ border-bottom:none; }
  .act-table tr.hi{ background:rgba(66,37,166,.05); }
  .act-table td{
    display:flex; align-items:center; justify-content:space-between; gap:14px;
    padding:7px 0; border-bottom:none; white-space:normal; text-align:right;
  }
  .act-table td::before{
    content:attr(data-label); font-size:11px; font-weight:600; letter-spacing:.08em;
    text-transform:uppercase; color:var(--ink-soft); flex:none; text-align:left;
  }
  /* Toggle can shrink to fit a narrow header row. */
  .act-head{ gap:14px; }

  /* ---- 0a. Live PMP Performance board. Four KPI columns collapse to a 2x2
     grid; at 4-up each cell is only ~35px of content on a phone, which wraps
     "$18.10M" onto three lines. Border sides are re-dealt for two columns. ---- */
  .board-top{ flex-direction:column; align-items:flex-start; gap:8px; padding:14px 18px; }
  .board-top .t{ font-size:11px; letter-spacing:.16em; }
  /* Stacked, the row is left-aligned, so the pill must be too -- it inherits
     justify-content:flex-end from the desktop layout otherwise and reads as a
     stray indent. */
  .board-top .now{ font-size:11px; letter-spacing:.1em; justify-content:flex-start; gap:10px; }
  .kpis{ grid-template-columns:1fr 1fr; }
  .kpi{ padding:22px 16px; border-right:1px solid rgba(255,255,255,.1); }
  .kpi:nth-child(4n){ border-right:1px solid rgba(255,255,255,.1); }
  .kpi:nth-child(2n){ border-right:none; }
  .kpi:nth-last-child(-n+2){ border-bottom:none; }
  .kpi .val{ font-size:26px; }
  .kpi .lbl{ font-size:10px; letter-spacing:.12em; margin-top:10px; }
  .kpi .sub{ font-size:11.5px; margin-top:5px; }

  /* ---- 0b. Month-on-month chart. The chart itself swaps to a separate
     two-chart render in JS (see the chart block in the script); these are
     only the surrounding shell fixes. The header strip stacks instead of
     letting the date range wrap mid-phrase. ---- */
  .mom-top{ flex-direction:column; align-items:flex-start; gap:6px; padding:14px 18px; }
  .mom-top .t{ font-size:11px; letter-spacing:.16em; }
  .mom-top .now{ font-size:11px; letter-spacing:.1em; }
  .mom-body{ padding:18px 14px 16px; }
  .mom-legend{ gap:16px; margin-bottom:2px; }
  .mom-legend .lg{ font-size:11px; letter-spacing:.1em; }
  .mom-chart svg + svg{ margin-top:14px; }
  .mom-foot{ font-size:12.5px; margin-top:14px; }

  /* Hero kicker is the only June marker on mobile, since the top-bar
     edition pill is hidden below 820px. Keep it from wrapping oddly. */
  .hero .kicker{ font-size:10px; letter-spacing:.16em; margin-bottom:16px; }

  /* Hero type down a step on phones so the block clears the bar comfortably
     and the lines stop crowding each other. The paragraph's size is set once in
     the 820px block, beside the layout that depends on it -- do not re-set it
     here or the two breakpoints disagree. */
  .hero h1{ font-size:34px; }
  .flightstrip{ margin-top:22px; }
  .flightstrip .leg{ padding:11px 16px; }
  .flightstrip .leg .code{ font-size:17px; }
  .flightstrip .leg .lbl{ font-size:9px; }
  .flightstrip .path{ width:64px; }

  /* Header logos are larger now; keep the bar compact on small screens. */
  .brandlock img{ height:23px; }
  .brandlock .eg-logo{ height:19px; }

  /* Section rhythm again, tighter: 88px of dead space at each end of every
     section is a lot of thumb-scrolling on a phone. */
  .pad{ padding:64px 0; }
}

/* Very small phones (320px). Two KPI columns leave ~94px of content each, and
   "$18.10M" at 26px needs 96. Two pixels, but it clips the M. */
@media(max-width:360px){
  .kpi{ padding:20px 12px; }
  .kpi .val{ font-size:22px; }
  .kpi .lbl{ font-size:9px; letter-spacing:.1em; }
  .kpi .sub{ font-size:10.5px; }

  /* ---- 1. Logo/vector safety: never let fixed height + shrinking
     containers squash aspect ratio. max-height (not height) lets the
     browser scale both dimensions together. ---- */
  .tb-logo, .pass .logo img, .pass .logo img.tall,
  footer .fl img, .dsp-badge img {
    height: auto !important;
    width: auto !important;
    max-width: 100% !important;
    object-fit: contain;
  }
  .tb-logo{ max-height:18px; }
  .tb-logo.vrbo-tb{ max-height:14px; }
  .tb-logo.hotels-tb{ max-height:16px; }
  .pass .logo{ height:22px; }
  .pass .logo img{ max-height:22px; }
  .pass .logo img.tall{ max-height:18px; }

  /* ---- 2. Format Overview table -> stacked cards ---- */
  .fmt-table-outer{ overflow-x:visible; }
  .fmt-table, .fmt-table thead, .fmt-table tbody,
  .fmt-table th, .fmt-table td, .fmt-table tr{
    display:block;
    width:100%;
  }
  .fmt-table thead{ display:none; }
  .fmt-table tr{
    border-bottom:1px solid var(--hair);
    padding:14px 18px 16px;
  }
  .fmt-table tr:last-child{ border-bottom:none; }
  .fmt-table tr.hi{ background:rgba(66,37,166,.05); }
  .fmt-table td{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:14px;
    padding:7px 0;
    border-bottom:none;
    white-space:normal;
    text-align:right;
  }
  .fmt-table td.r{ text-align:right; }
  .fmt-table td::before{
    content:attr(data-label);
    font-size:11px;
    font-weight:600;
    letter-spacing:.08em;
    text-transform:uppercase;
    color:var(--ink-soft);
    flex:none;
    text-align:left;
  }
  .fmt-table td.hl-col{ font-size:17px; }
  .fmt-table .brand-cell{ min-width:0; }
  .fmt-table .tb-logo{ margin-left:auto; }
  .fmt-table .dsp-badge, .fmt-table .dsp-text{ margin-left:auto; }
  .fmt-table .fmt-pill{ margin-left:auto; white-space:nowrap; }

  /* ---- 3. Boarding passes: stack main content above a horizontal stub ---- */
  .pass, .pass.priority{
    grid-template-columns:1fr !important;
  }
  .pass .main, .pass.priority .main{
    padding:22px 20px;
  }
  .pass .stub, .pass.priority .stub{
    flex-direction:row;
    justify-content:space-between;
    align-items:center;
    padding:12px 20px;
    gap:12px;
  }
  /* swap the vertical perforation for a horizontal one along the top */
  .pass .stub::before{
    left:0; right:0; top:-8px; bottom:auto; width:auto; height:16px;
    background:radial-gradient(circle at 50% 0,transparent 0 7px,var(--paper) 7px) 0 0/26px 16px repeat-x;
  }
  .pass .stub .brl{
    writing-mode:horizontal-tb;
    transform:none;
    font-size:10px;
  }
  .pass .stub .barcode{
    height:34px; width:70px;
    background:repeating-linear-gradient(90deg,#fff 0 2px,transparent 2px 4px,#fff 4px 5px,transparent 5px 9px,#fff 9px 10px,transparent 10px 13px);
  }
  .pass .stub .seat{ font-size:16px; }

  .pass .fields, .pass.priority .fields{
    grid-template-columns:repeat(3,1fr) !important;
    gap:14px !important;
  }
  .pass .field .fv{ font-size:17px; }
  .pass.priority .field.roas .fv{ font-size:26px; }
  .pass .toprow{ flex-wrap:wrap; row-gap:10px; }
  .pass .logo{ max-width:60%; }
  .pass .fmt{ font-size:9px; padding:5px 9px; }
  .pass .dsp{ flex-wrap:wrap; }

  /* ---- 4. Gated PDF form: fix CSS Grid min-width overflow bug + center ---- */
  .gated-card{
    grid-template-columns:1fr !important;
    padding:24px !important;
    gap:26px !important;
  }
  .gated-left, .gated-right{
    min-width:0;
    width:100%;
  }
  .gated-left{ text-align:center; }
  .gated-left h2{ font-size:clamp(24px,7vw,32px); }
  .gated-left p{ margin-left:auto; margin-right:auto; }
  .gated-right{
    margin:0 auto;
    max-width:100%;
    padding:24px 20px;
  }
  .gf-field input{ width:100%; box-sizing:border-box; }
}

/* Chatbot */
#chatbot-fab{position:fixed;bottom:28px;right:28px;z-index:80;width:56px;height:56px;border-radius:50%;
  background:var(--purple);box-shadow:0 6px 24px rgba(66,37,166,.45);display:flex;align-items:center;justify-content:center;
  cursor:pointer;transition:transform .3s var(--ease),box-shadow .3s var(--ease)}
#chatbot-fab:hover{transform:scale(1.08);box-shadow:0 8px 30px rgba(66,37,166,.6)}
#chatbot-fab svg{width:26px;height:26px}
.chatwin{position:fixed;bottom:96px;right:28px;z-index:90;width:380px;max-height:520px;border-radius:18px;
  background:#fff;box-shadow:0 20px 60px rgba(0,0,0,.22);display:flex;flex-direction:column;overflow:hidden;
  font-family:'DM Sans',Arial,sans-serif;transition:opacity .25s var(--ease),transform .25s var(--ease)}
.chatwin.hidden{opacity:0;pointer-events:none;transform:translateY(16px) scale(.96)}
.chat-head{display:flex;align-items:center;justify-content:space-between;padding:16px 18px;
  background:var(--grad-head);color:#fff;gap:10px}
.chat-head-l{display:flex;align-items:center;gap:12px}
.chat-avatar{width:34px;height:34px;border-radius:50%;background:rgba(255,255,255,.18);display:flex;align-items:center;justify-content:center}
.chat-title{font-size:14px;font-weight:700;letter-spacing:-.01em}
.chat-sub{font-size:11px;color:rgba(255,255,255,.7);font-weight:400}
.chat-close{background:none;border:none;color:rgba(255,255,255,.8);font-size:24px;cursor:pointer;padding:0 4px;line-height:1}
.chat-close:hover{color:#fff}
.chat-body{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px;max-height:340px;min-height:200px}
.chat-msg{padding:12px 16px;border-radius:14px;font-size:14px;line-height:1.5;max-width:90%;font-weight:400;animation:msgIn .3s var(--ease)}
@keyframes msgIn{0%{opacity:0;transform:translateY(8px)}100%{opacity:1;transform:none}}
.chat-msg.bot{background:var(--lilac-2);color:var(--ink);align-self:flex-start;border-bottom-left-radius:4px}
.chat-msg.user{background:var(--purple);color:#fff;align-self:flex-end;border-bottom-right-radius:4px}
.chat-msg.typing{color:var(--ink-soft)}
.chat-msg.typing::after{content:"...";animation:dots 1.2s steps(4) infinite}
@keyframes dots{0%{content:"."}33%{content:".."}66%{content:"..."}100%{content:"."}}
.chat-followup{display:flex;flex-direction:column;gap:10px}
.chat-followup-label{font-size:12px;color:var(--ink-soft);font-weight:600;padding:2px 2px 0}
.chat-prompts{display:flex;flex-direction:column;gap:8px}
.chat-prompt{background:none;border:1px solid var(--hair);border-radius:12px;padding:10px 14px;font-size:13px;
  color:var(--purple);font-weight:500;text-align:left;cursor:pointer;font-family:'DM Sans',Arial,sans-serif;
  transition:background .2s,border-color .2s}
.chat-prompt:hover{background:var(--lilac-2);border-color:var(--purple)}
.chat-input-wrap{display:flex;align-items:center;gap:8px;padding:12px 14px;border-top:1px solid var(--hair)}
.chat-input{flex:1;border:1px solid var(--hair);border-radius:12px;padding:10px 14px;font-size:14px;
  font-family:'DM Sans',Arial,sans-serif;outline:none;transition:border-color .2s}
.chat-input:focus{border-color:var(--purple)}
.chat-send{width:38px;height:38px;border-radius:50%;background:var(--purple);border:none;color:#fff;
  display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .2s}
.chat-send:hover{background:var(--magenta)}
@media(max-width:440px){.chatwin{right:8px;left:8px;width:auto;bottom:88px}}
