/* ==========================================================================
   Spark — homepage  (index.html)
   Layout recreated from PSD/spark web HOME.psd (1366 x 5315).
   Loaded after css/tokens.css and css/base.css.

   Coordinates in comments are the comp's absolute pixel positions, so any value
   here can be traced back to a layer in reference/spark-web-home-layers.json.
   "comp" always means the PSD; "ink" means the first painted pixel, not a box
   edge.

   Two deliberate deviations, both recorded in README.md:

   1. The comp's left edges run anywhere from 27 to 106. Everything here is
      normalised to the one value that recurs, 68, and the overhangs that
      survive are the ones that carry artwork.
   2. Three of the nine bands are sized by aspect-ratio with their contents in
      cqw. Those are the bands whose content has to stay registered to a
      flattened backdrop: the manifesto's bordered card, and the two carousels
      whose cards are a composed arrangement rather than a grid. Everything else
      reflows normally. 1cqw = 13.66px at the comp's width.
   ========================================================================== */

/* --- Shared home-page pieces --------------------------------------------- */

/* Caps display. The comp's BebasNeueBold has no lowercase, so the source text
   is written in sentence case and capitalised here — same rendered result. */
.caps {
  font-family: var(--font-caps);
  font-weight: 400;
  text-transform: uppercase;
  color: var(--text);
}

.caps__accent, .accent { color: var(--orange); }

/* .dash — the 1px orange fade every rule in this comp is made of — moved to
   base.css when the footer became a three-page component. */

.eyebrow {
  font-size: var(--fs-eyebrow);
  line-height: 1;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text);
}

/* Both carousels head their band with the same link + arrow. */
.view-all {
  display: inline-flex;
  align-items: center;
  font-size: var(--fs-view-all);
  line-height: 1;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--text);
}

/* 403x63 r7. Three instances share this geometry: two in the hero, one closing
   the page. The comp gives them a 3px #FEA868 stroke in lighten mode over an
   orange outer glow; box-shadow stands in for the glow. */
.pill {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 403px;
  height: 63px;
  border: 2px solid var(--pill-edge-ghost);
  border-radius: var(--r-pill);
  box-shadow: 0 0 18px rgb(244 105 2 / 0.34);
  font-size: var(--fs-pill);
  font-weight: 600;
  line-height: 1;
  color: var(--text);
}

.pill--filled {
  border-color: var(--pill-edge);
  background: rgb(0 0 0 / 0.81);
  box-shadow: 0 0 18px rgb(244 105 2 / 0.45), inset 0 0 60px rgb(244 105 2 / 0.16);
}

/* The comp centres both labels on x=688 — 4px right of the pill's own centre —
   and then places the chevrons independently, *outside* the label rather than
   beside it. So they are pinned to the comp's own x rather than laid out in
   the flex row. */
.pill { padding-left: 9px; }

.pill__chevrons {
  position: absolute;
  top: 50%;
  display: inline-flex;
  transform: translateY(-50%);
  left: 326px;                    /* comp 808, pill starts 482 */
}

/* The comp put these at 49 (comp 531), which cleared "Own the Best Opportunity"
   by a single pixel. The label is now "Your Sponsorship Opportunity" — 43px
   wider, so it centres 21px further left and ran straight under the chevrons.
   Moved to 20, which leaves the same ~9px gap to the label that the forward
   chevrons on the second pill already have. */
.pill__chevrons--back { left: 20px; }

/* --- Chevron sizing ------------------------------------------------------ */

/* The comp sets these as type with a non-uniform transform — scaleX 0.60 /
   scaleY 1.11, a 1.85x vertical stretch no font-size can express — so they are
   drawn. Shape comes from .chevron in base.css. */
.pill .chevron { width: 14px; height: 25px; }
.chevron--back { transform: scaleX(-1); }

/* ==========================================================================
   Header — comp logo 61,32..221,83 · lockup 1132,34..1308,56
   The band above the hero photo is 202px of flat black.

   The comp's own cluster — "Log In", a gradient "Sign Up" pill and a language
   globe — was replaced on instruction with the site's three destinations, at
   the create-event page's scale rather than the comp's ~10px, and the button
   for the current page filled orange. The buttons themselves are shared: see
   the header section in base.css. The lockup no longer ends on the comp's
   x=1308, because three full-length labels are much wider than "Log In", so
   the group is anchored to its right edge and grows leftward.
   ========================================================================== */

/* The bar itself is shared — see the header section in base.css. All this page
   adds is what sits under it.

   The comp puts 202px of flat black above the hero photo, with the logo in the
   top 83px of it. Sticky, that would be a 202px bar following you down a
   5300px page, so the bar is only the part that carries content and the
   remaining 107px is given back as padding on <main>. Same 202px before the
   hero photo as the comp draws, but the thing that sticks is 95px. */
.page-home main { padding-top: 107px; }

/* Anchor targets have to clear the stuck header, not just the viewport edge. */
.page-home [id] { scroll-margin-top: 111px; }

/* ==========================================================================
   Hero — comp band 202..754 (552 tall)
   ========================================================================== */

.hero {
  position: relative;
  height: 552px;
  overflow: hidden;
}

.hero__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero__inner {
  position: relative;
  height: 100%;
  text-align: center;
}

/* Comp cap tops 293 and 397, so the pitch is 104. The second line carries a
   drop shadow, a white outer glow and a bevel; the first two are worth
   approximating, the bevel is not. */
.hero__title {
  padding-top: 76px;              /* cap top y=293 */
  font-family: var(--font-caps);
  font-weight: 400;
  font-size: var(--fs-hero);
  line-height: var(--lh-hero);
  text-transform: uppercase;
}

.hero__title .caps__accent {
  text-shadow: 0 2px 13px rgb(0 0 0 / 0.67), 0 0 2px rgb(255 255 255 / 0.4);
}

/* Comp pills at y=514 and y=598, so 21px apart. */
.hero__actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 21px;
  margin-top: 28px;              /* comp pill A top y=514 */
}

/* ==========================================================================
   Manifesto — comp band 760..1546 (786 tall)

   Sized by aspect-ratio with its copy in cqw, because the backdrop bakes in the
   653x653 bordered card the copy has to sit inside. 1cqw = 13.66px.
   ========================================================================== */

.manifesto {
  position: relative;
  margin-top: 6px;                /* comp band starts 760, the hero ends 754 */
  aspect-ratio: 1366 / 786;
  container-type: inline-size;
  overflow: hidden;
}

.manifesto__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.manifesto__copy {
  position: absolute;
  left: 8.638cqw;                 /* 118px */
  top: 12.006cqw;                 /* 924px, cap top 932 */
  width: 37.482cqw;               /* 512px — 'SHIFT CULTURE' needs 493 and
                                     wrapped at the PSD box's own 492 */
}

.manifesto__title {
  font-size: 8.126cqw;            /* 111px */
  line-height: 7.833cqw;          /* 107px, measured cap-top to cap-top */
}

/* Comp dash tops 1143 / 1283 / 1374; paragraph ink tops 1164 / 1312 / 1393. */
.manifesto__dash {
  width: 5.929cqw;                /* 81px */
  margin-top: 1.757cqw;           /* 24px */
}

.manifesto__text {
  margin-top: 1.098cqw;           /* 15px */
  width: 35.578cqw;               /* 486px, which reproduces the comp's own
                                     5/2/2 line breaks; its 478px box gives 5/3/2 */
  font-size: 1.391cqw;            /* 19px */
  line-height: 1.684cqw;          /* 23px, rendered pitch */
  color: var(--text);
}

.manifesto__text + .manifesto__dash { margin-top: 0.732cqw; }  /* 10px */

/* ==========================================================================
   Carousels — sponsorship opportunities and partner stories

   The comp draws both at rest: cards at several sizes with deliberate overlaps,
   over a backdrop. Sized by aspect-ratio with contents in cqw so the
   arrangement holds together at any width.

   Neither is at rest any more. The opportunities row is four equal cards that
   grow under the pointer, and the story rail scrolls forever — see the two
   sections below and spark.js.
   ========================================================================== */

.carousel {
  position: relative;
  container-type: inline-size;
  overflow: hidden;
}

/* 21px gap: the manifesto band ends at 1546, this one starts at 1567. */
.carousel--opps    { margin-top: 21px; aspect-ratio: 1366 / 769; }  /* comp 1567..2336 */
.carousel--stories { aspect-ratio: 1366 / 491; }                    /* comp 2336..2827 */

.carousel__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.carousel__title {
  position: absolute;
  left: 4.978cqw;                 /* 68px */
  font-size: 3.682cqw;            /* 50.3px */
  line-height: 1;
}

.carousel--opps    .carousel__title { top: 1.794cqw; }  /* cap top y=1596 */
.carousel--stories .carousel__title { top: 2.343cqw; }  /* cap top y=2373 */

.carousel__view-all {
  position: absolute;
  font-size: 1.098cqw;            /* 15px */
}

.carousel--opps    .carousel__view-all { left: 77.306cqw; top: 4.100cqw; }  /* 1056, y=1625 */
.carousel--stories .carousel__view-all { left: 77.306cqw; top: 4.173cqw; }  /* 1056, y=2396 */

.view-all__arrow {
  width: 3.075cqw;                /* 42px */
  height: 1.464cqw;               /* 20px */
  margin-left: 0.879cqw;          /* 12px */
  color: var(--orange);
}

/* The comp stacks two rules here: an orange vector dash at 71,1669 and a
   rasterised, white-tinted copy of it 18px to the right, tapered at both ends
   like a lens flare. One of them is leftover, but both are what renders. */
.carousel__dash {
  position: absolute;
  left: 5.198cqw;                 /* 71px */
  top: 7.467cqw;                  /* y=1669 */
  width: 5.929cqw;                /* 81px */
  height: 1px;
  background-image: linear-gradient(90deg, rgb(244 105 2 / 0.25), transparent);
}

.carousel__dash--streak {
  left: 6.515cqw;                 /* 89px */
  top: 7.394cqw;                  /* y=1668 */
  width: 5.271cqw;                /* 72px */
  height: 2px;
  background-image: linear-gradient(90deg,
    transparent, rgb(255 246 238 / 0.95) 45%, rgb(255 246 238 / 0.95) 62%, transparent);
  filter: blur(0.5px);
}

/* The opportunities row has no prev/next discs: there are four cards and they
   all fit. The comp drew a pair here at 23,1987 (38x36) and 1295,1944 (36x36) —
   two different sizes, 43px out of level, and the left one tucked under card 1
   so 10px of a control sat behind artwork. The story rail below does need a
   pair, and .rail-nav is what they should have been. */

/* --- Sponsorship cards --------------------------------------------------- */

/* Each card sets --k to one comp pixel, so every value below is literally the
   number measured in the PSD.

   The comp draws the second card larger (327x453 against 291x397) and lifted
   26px, which is the carousel's resting centre position. On instruction that
   emphasis is now a *hover* state rather than a fixed one: all four cards are
   the same size, on one line, and whichever the pointer is on grows. So the
   size is still the comp's — 1.124x, card 2's own ratio — it has just moved
   from one permanent card to whichever card is being looked at.

   Only the two outer edges are the comp's now: the row still runs 51..1286,
   and the 5.198cqw the shrunk card gave back is split evenly across the three
   gaps, at 1.733cqw (23.7px) each. Tops are averaged from the three cards that
   already agreed to within 4px. */
.opp {
  position: absolute;
  top: 14cqw;
  width: 21.303cqw;               /* 291px */
  aspect-ratio: 291 / 397;
  --k: 0.0725cqw;                 /* one comp pixel */
  border: calc(2 * var(--k)) solid var(--orange);
  border-radius: calc(19 * var(--k));
  background: var(--bg);
  box-shadow: 0 0 calc(22 * var(--k)) rgb(244 105 2 / 0.28);
  overflow: hidden;
}

.opp--1 { left:  3.733cqw; }      /* comp x51 */
.opp--2 { left: 26.769cqw; }
.opp--3 { left: 49.804cqw; }
.opp--4 { left: 72.840cqw; }      /* comp x995, and its right edge is the comp's */

.opp__link { display: block; height: 100%; }

/* The top 77.5% of the comp's own card — everything above its baked copy. The
   card is black beneath, so a gradient over the poster's foot hides the seam. */
.opp__poster {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 77.5%;
  object-fit: fill;
}

.opp__link::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 66%, #000 78%);
}

/* Anchored to the card's foot: the comp's pill sits 16px above the bottom edge
   whatever the card's size. */
.opp__foot {
  position: absolute;
  z-index: 1;                     /* over the fade */
  left: 0;
  right: 0;
  bottom: calc(16 * var(--k));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(7 * var(--k));
}

/* The comp sets this as orange 8.66px text ending in a ">", which reads as a
   link and is not one — it is the card's status. Drawn as a pill instead, in
   two variants, and taken up to 11px on the way: 8.66px was flagged in the
   README as below any reasonable minimum, and this element is being redrawn
   anyway, so there is nothing left to be faithful to. */
.status {
  display: inline-flex;
  align-items: center;
  padding: calc(6 * var(--k)) calc(14 * var(--k));
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: calc(11 * var(--k));
  font-weight: 600;
  line-height: 1;
  letter-spacing: calc(0.06 * 11 * var(--k));     /* PSD tracking 60 */
  text-transform: uppercase;
}

.status--open {
  color: var(--status-open);
  background: rgb(244 105 2 / 0.12);
}

.status--closed {
  color: var(--status-closed);
  background: rgb(138 138 138 / 0.12);
}

/* Comp 238x49 r11 with a 0.5px white stroke, which antialiases to ~42% white. */
.opp__meta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(21 * var(--k));
  width: calc(238 * var(--k));
  height: calc(49 * var(--k));
  border: 1px solid var(--meta-edge);
  border-radius: calc(11 * var(--k));
  font-size: calc(11.35 * var(--k));
  line-height: 1;
  color: var(--text);
}

.opp__when, .opp__where {
  display: inline-flex;
  align-items: center;
  gap: calc(14 * var(--k));
}

.opp__sep {
  width: 1px;
  height: calc(28 * var(--k));
  background: var(--meta-edge);
}

.opp__meta .icon--calendar-2 { width: calc(17 * var(--k)); height: calc(17 * var(--k)); }
.opp__meta .icon--location   { width: calc(14 * var(--k)); height: calc(20 * var(--k)); }

/* --- Partner-story rail --------------------------------------------------

   The comp draws five cards at five sizes, fanned by overlap, with the middle
   one largest and on top (67,2478 281x281 · 233,2470 298x297 · 527,2464
   312x309 · 816,2470 299x297 · 1019,2478 281x281, band top 2336).

   On instruction that becomes a rail you can scroll forever in either
   direction, so the sizes have to be uniform — "the middle card" is now
   whichever card the rail is showing, not a fixed one. The emphasis it used to
   carry is applied by spark.js to whatever reaches the middle, at 1.11x, which
   is the comp's own 312/281.

   The card is the comp's base 281x281 with its own --k, so every offset inside
   it is still literally the number measured in the PSD.

   overflow-y has to be hidden rather than visible: a scroll container clips
   both axes whatever you write, so the block padding is what gives the middle
   card room to grow into. */
.stories {
  position: absolute;
  left: 0;
  right: 0;
  top: 8.4cqw;
  padding-block: 1.7cqw;          /* headroom for the 1.11x centre card */
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain; /* don't hand a horizontal fling to the page */
  /* `scroll-behavior: smooth` is set on <html> for anchor links and inherits
     into every scroll container, including this one. Left inherited, the loop's
     wrap would *animate* — the rail would visibly slide a whole period
     backwards instead of the jump being invisible. */
  scroll-behavior: auto;
  scrollbar-width: none;
  cursor: grab;
  /* spark.js gives the middle cards a z-index of up to 100 so they overlap
     their neighbours in the right order. Without a stacking context here those
     numbers would compete with everything else on the page — in particular the
     nav buttons below, which sit over the rail and would lose. Contained, the
     whole rail is one layer and the buttons only have to beat it. */
  isolation: isolate;
}

.stories::-webkit-scrollbar { display: none; }

.stories.is-dragging { cursor: grabbing; }

/* --- Rail navigation ------------------------------------------------------

   Vertically centred on the rail: it starts at 8.4cqw, adds 1.7cqw of padding,
   then half a card — 8.4 + 1.7 + 20.571/2 = 20.386cqw.

   The rail is full-bleed, so there is no margin to put these in and they sit
   over the outermost cards whatever we do. The failure mode to avoid is the
   comp's, where the left disc was *under* card 1 and came out clipped: hence
   the z-index, the opaque-enough fill and the ring. */
.rail-nav {
  position: absolute;
  z-index: 2;                     /* over the rail's own contained stack */
  top: 20.386cqw;
  display: none;                  /* → grid, once spark.js has bound them */
  place-items: center;
  width: 3.221cqw;                /* 44px */
  height: 3.221cqw;
  padding: 0;
  transform: translateY(-50%);
  border: 1px solid var(--orange);
  border-radius: 50%;
  background: rgb(0 0 0 / 0.62);
  color: var(--text);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
}

.stories[data-loop-ready] ~ .rail-nav { display: grid; }

.rail-nav--prev { left:  1.610cqw; }   /* 22px */
.rail-nav--next { right: 1.610cqw; }

.rail-nav .chevron {
  width: 0.732cqw;                /* 10px */
  height: 1.318cqw;               /* 18px */
}

.rail-nav:hover,
.rail-nav:focus-visible {
  background: var(--orange);
  color: var(--bg);
}

.stories__track {
  display: flex;
  gap: 1.17cqw;                   /* 16px */
  width: max-content;
}

/* The card art carries the poster and the soft black panel the copy sits on —
   baking that panel is exact where a CSS gradient would only approximate it. */
.story {
  flex: none;
  position: relative;
  width: 20.571cqw;               /* comp 281px */
  aspect-ratio: 281 / 281;
  --k: 0.0547cqw;                 /* one comp pixel */
  border: calc(2 * var(--k)) solid var(--orange);
  border-radius: calc(19 * var(--k));
  background: var(--bg);
  overflow: hidden;
}

.story__link { display: block; height: 100%; }

/* The art is the top 58% of the comp's own card — everything above its baked
   copy. The rest of the card is the black the copy sits on, so a gradient over
   the art's foot hides the seam. */
.story__art {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 58%;
  object-fit: fill;
}

.story__link::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 48%, #000 60%);
}

/* Comp offsets are from the editable card's own 376x371 box: title ink at
   19,231, the dash at 19,286, the description at 21,302. */
.story__body {
  position: absolute;
  z-index: 1;                     /* over the fade */
  left: calc(20 * var(--k));
  top: calc(231 * var(--k));
  right: calc(16 * var(--k));
}

.story__title {
  display: block;
  font-size: calc(29.6 * var(--k));
  line-height: calc(27 * var(--k));
}

/* The comp gives each card one title line. Marketing's copy is two — the event
   on the first, what Spark actually did on the second — so this is a line the
   comp has no counterpart for and its size is chosen rather than measured.

   It is not set at the title's size: "OFFICIAL TICKETING PARTNER" is 26
   characters and at 29.6k it wraps to two lines on a 340k card, which would
   make the role louder than the act. At 13k it fits one line with room to
   spare, and orange makes it read as a label rather than a second heading. */
.story__role {
  display: block;
  margin-top: calc(4 * var(--k));
  font-size: calc(13 * var(--k));
  line-height: 1;
  letter-spacing: 0.06em;
  color: var(--orange);
}

.story__dash {
  width: calc(59 * var(--k));
  margin-top: calc(9 * var(--k));
}

.story__text {
  display: block;
  margin-top: calc(9 * var(--k));
  font-size: calc(14.29 * var(--k));
  line-height: 1.2;
  color: var(--text);
}

/* ==========================================================================
   Why brands trust Spark — comp band 2827..3645 (818 tall)
   The one light band. Its backdrop is the white plate with the crowd photo
   washing out into it; everything on top is CSS.
   ========================================================================== */

.trust {
  position: relative;
  height: 818px;
  overflow: hidden;
  color: var(--ink);
  text-align: center;
}

.trust__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.trust__inner { position: relative; }

/* Comp ink 2868, i.e. 41px into the band. */
.trust__eyebrow {
  padding-top: 37px;              /* ink y=2868 */
  font-size: var(--fs-trust-eyebrow);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink);
}

.trust__eyebrow-dash {
  width: 81px;
  margin: 17px auto 0;            /* dash at y=2900 */
}

/* --- The two headline numbers — comp 50M+ at 292,2956 and 150K at 811 ----- */

.headline-stats {
  display: flex;
  justify-content: center;
  gap: 227px;                     /* comp centres them on 424 and 928 */
  margin-top: 50px;               /* cap top y=2956 */
}

.headline-stats__value {
  font-size: var(--fs-stat-big);
  line-height: 0.72;              /* comp digit height 113 on a 157.7px face */
  color: var(--orange);
  /* The comp gives all five numerals a white outer glow and a soft shadow. */
  text-shadow: 0 2px 3px rgb(0 0 0 / 0.2), 0 0 27px rgb(255 255 255 / 0.9);
}

.headline-stats__label {
  margin-top: 27px;               /* ink y=3097 */
  font-size: var(--fs-stat-label);
  font-weight: 700;
  line-height: 1;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
}

.headline-stats__dash {
  width: 63px;
  margin: 13px auto 0;            /* dash at y=3125 */
  --dash-alpha: 0.26;
}

/* --- The two white panels — comp 89..1278, so 21px inside the column ----- */

.panel {
  width: 1189px;
  max-width: 100%;
  margin-inline: auto;
  border-radius: var(--r-panel);
  background: var(--paper);
  box-shadow: 0 2px 24px rgb(0 0 0 / 0.32);
}

/* Comp panel 3167..3300. Column boundaries come from its two 1px dividers at
   x=460 and x=900, which is what makes the three columns uneven. */
.panel--stats {
  display: grid;
  grid-template-columns: 371fr 440fr 378fr;
  margin-top: 38px;               /* panel top y=3167 */
  height: 133px;
}

.panel-stat { position: relative; }

.panel-stat + .panel-stat::before {
  content: "";
  position: absolute;
  left: 0;
  top: 24px;                      /* comp 3191, panel top 3167 */
  width: 1px;
  height: 81px;
  background: linear-gradient(180deg, #F2F2F2, transparent);
}

.panel-stat__value {
  margin-top: 20px;               /* cap top y=3187 */
  font-size: var(--fs-stat-small);
  line-height: 0.726;             /* comp digit height 61 */
  color: var(--orange);
  text-shadow: 0 2px 3px rgb(0 0 0 / 0.2), 0 0 27px rgb(255 255 255 / 0.9);
}

.panel-stat__label {
  margin-top: 15px;               /* ink y=3263 */
  font-size: var(--fs-stat-label-sm);
  font-weight: 700;
  line-height: 1;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
}

.panel-stat__dash {
  width: 35px;
  margin: 7px auto 0;             /* dash at y=3276 */
  --dash-alpha: 0.26;
}

/* Comp panel 3314..3614. The comp masks one flat 1152x221 wall into it; this is
   now nineteen supplied files in three groups, so the panel's height is
   released and it grows with its rows instead. */
.panel--logos {
  margin-top: 14px;               /* panel top y=3314 */
  padding: 34px 26px 30px;
}

.logos {
  display: flex;
  align-items: stretch;
}

/* Weighted by artwork rather than by headcount: four wide promoter marks need
   more room than four narrow ones would, and equal thirds leave the middle
   group half empty while the outer two run to an extra row.
   The promoters' share is then rounded *up* past its proportional 228px to
   275, which is what Ravel and Rajawali need to sit on one line. Proportional
   widths alone gave that group 1/2/1 — two orphan rows out of three — because
   flex-wrap packs greedily and a group of four wide marks packs worst. At
   these weights every row in every group holds at least two. */
.logos__group { min-width: 0; padding: 0 20px; }

.logos__group--brands    { flex: 15 1 0; }   /* 3/2/2 */
.logos__group--promoters { flex: 10 1 0; }   /* 2/2   */
.logos__group--artists   { flex: 12 1 0; }   /* 3/3/2 */

/* The divider is the group's own left edge, so it cannot drift out of register
   with what it divides — same reasoning as the objective columns on
   create-event. */
.logos__group + .logos__group { border-left: 1px solid var(--logo-rule); }

.logos__set {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 26px 28px;
  height: 100%;
}

.logos__item { display: flex; }

/* Only ever shrinks. These are 1x files between 63 and 185 CSS px wide, and
   `max-*` cannot scale a mark up past its natural size, so nothing is ever
   rendered soft. The caps catch the three widest wordmarks and the two square
   lockups; everything else draws at the size it was exported. */
.logos__mark {
  width: auto;
  height: auto;
  max-width: 132px;
  max-height: 52px;
  object-fit: contain;
}

/* The wall fits at this width, so its wrapper does nothing and the caption
   below would be noise. Both come back in the phone block at the end. */
.trust__logo-hint { display: none; }

/* ==========================================================================
   Our capabilities — comp band 3756..4472
   ========================================================================== */

.caps-section {
  position: relative;
  padding-top: 105px;             /* cap top y=3756, band starts 3645 */
  padding-bottom: 131px;          /* rules end 4472, the CTA panel opens 4603 */
  text-align: center;
}

.caps-section__title {
  padding-left: 41px;             /* comp centres it on 703, not 683 */
  font-size: var(--fs-caps-h2);
  line-height: 1;
  color: var(--orange);
  text-shadow: 0 2px 3px rgb(0 0 0 / 0.2), 0 0 27px rgb(255 255 255 / 0.35);
}

.caps-section__dash {
  width: 81px;
  margin: 16px auto 0;            /* dash at y=3826 */
}

.capability-grid {
  display: grid;
  grid-template-columns: 307fr 304fr 304fr 315fr;   /* rules at 375/679/983 */
  margin-top: 90px;               /* column box y=3932 */
}

/* The comp's three column rules sit at x=375 / 679 / 983, which on a 1230px
   column at x=68 is within 8px of the quarter points. They hold a flat #282828
   for the top half and then fade out. */
.capability + .capability::before {
  content: "";
  position: absolute;
  top: -20px;                     /* comp 3912, column box starts 3932 */
  left: -0.5px;
  width: 1px;
  height: 560px;                  /* comp 3912..4472 */
  background: linear-gradient(180deg,
    transparent 0, var(--caps-rule) 6%, var(--caps-rule) 53%, transparent 100%);
}

/* The comp bottom-aligns all four icons on y=4137 but top-aligns all four
   titles on 4178 and all four bodies on 4294 — and the titles run to one line
   or two. No single flow can hold both edges, so the column is a fixed 540px
   box (3932..4472, the height of its divider rule) and the three pieces are
   pinned inside it. */
.capability {
  position: relative;
  height: 540px;
}

.capability__icon {
  position: absolute;
  left: 50%;
  bottom: 335px;                  /* comp icon feet y=4137 */
  transform: translateX(-50%);
}

.capability:nth-child(1) .capability__icon { width: 200px; height: 200px; }
.capability:nth-child(2) .capability__icon { width: 151px; height: 175px; }
.capability:nth-child(3) .capability__icon { width: 214px; height: 206px; }
.capability:nth-child(4) .capability__icon { width: 219px; height: 207px; }

/* The dash is a child of the title so it follows the last line: one line in
   columns 1 and 4, two in columns 2 and 3. */
.capability__title {
  position: absolute;
  left: 0;
  right: 0;
  top: 235px;                     /* cap top y=4178 */
  font-size: var(--fs-caps-title);
  line-height: var(--lh-caps-title);
}

.capability__dash {
  width: 57px;
  margin: 13px auto 0;
  --dash-alpha: 0.44;
}

/* The comp's four text boxes are different widths, and those widths are what
   set its line breaks. */
.capability__text {
  position: absolute;
  left: 50%;
  top: 358px;                     /* ink y=4294 */
  transform: translateX(-50%);
  font-size: var(--fs-caps-body);
  line-height: var(--lh-caps-body);
  color: var(--text);
}

.capability:nth-child(1) .capability__text { width: 262px; }  /* PSD box 251 wraps to 4 lines */
.capability:nth-child(2) .capability__text { width: 272px; }
.capability:nth-child(3) .capability__text { width: 274px; }
.capability:nth-child(4) .capability__text { width: 265px; }

/* ==========================================================================
   Closing CTA — comp panel 27..1351 x 4603..4977 (1324x374 r30)
   ========================================================================== */

.closing {
  padding: 0 15px 19px 27px;      /* comp panel 27..1351; card opens 4996 */
}

.closing__panel {
  position: relative;
  width: 100%;
  max-width: 1324px;
  height: 374px;
  padding-right: 24px;            /* comp centres the copy on 677, not 689 */
  border: 1px solid var(--orange);
  border-radius: var(--r-cta);
  overflow: hidden;
  text-align: center;
}

.closing__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.closing__eyebrow {
  position: relative;
  padding-top: 31px;              /* ink y=4637, panel top 4603 */
}

.closing__eyebrow-dash {
  width: 81px;
  margin: 14px auto 0;            /* dash at y=4662 */
}

.closing__title { position: relative; margin-top: 19px; }

/* Two lines, two different faces: BebasNeuePro-Regular then GeneralSans-Bold. */
.closing__title-line1 {
  display: block;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-cta-line1);
  line-height: 1;
  color: var(--text);
}

.closing__title-line2 {
  display: block;
  margin-top: 8px;
  font-weight: 700;
  font-size: var(--fs-cta-line2);
  line-height: 1;
  color: var(--orange);
  text-shadow: 0 2px 4px rgb(0 0 0 / 0.5);
}

/* Comp: right-aligned copy, a 1px vertical rule at x=723, then the pill. */
.closing__foot {
  position: relative;
  display: flex;
  align-items: center;
  padding-left: 289px;            /* comp lede starts 316, panel 27 */
  margin-top: 19px;               /* pill top y=4876 */
}

.closing__lede {
  width: 379px;                   /* comp 316..695, right-aligned */
  font-size: var(--fs-footer-link);
  line-height: 24px;
  text-align: right;
  color: var(--text);
}

.closing__sep {
  flex: none;
  margin: 0 26px 0 28px;          /* comp rule at 723, pill at 758 */
  width: 1px;
  height: 81px;
  background: linear-gradient(180deg, rgb(244 105 2 / 0.07), rgb(244 105 2 / 0.54));
}

.closing__pill {
  font-size: var(--fs-eyebrow);
  font-weight: 400;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.closing__arrow { width: 42px; height: 20px; color: var(--text); }

/* ==========================================================================
   Site footer — comp 4996..5295, then 20px of black tail

   Moved to base.css in full, including its hover, its narrow-desktop reflow
   and its phone layout. Only this comp draws a footer, but all three pages now
   close with it, and a component that ships on every page cannot live in one
   page's stylesheet — that is exactly how the phone header's hide rule ended
   up hiding nothing on two of three pages.
   ========================================================================== */

/* ==========================================================================
   Phase 2 — hover, focus and motion

   Nothing below this line comes from the comp; a comp is a single resting
   state and draws no hover, no focus ring and no transition. Every value here
   was chosen rather than measured, and each is listed as such in README.md.

   The two constraints: none of it may change how the page looks at rest, and
   none of it may be load-bearing.
   ========================================================================== */

/* --- Gold on hover -------------------------------------------------------
   Every call to action goes gold on hover. Each rule pairs :hover with
   :focus-visible, so a keyboard gets the same signal a mouse does. */

/* The footer's own share of this — its links, its phone number and its social
   tiles — went to base.css with the component. */
.view-all {
  transition: color var(--dur) var(--ease);
}

.view-all:hover,
.view-all:focus-visible {
  color: var(--gold);
}

/* Arrows and bullets are drawn in currentColor but pinned to orange by their
   own rules, so inheriting the gold is not enough — it has to be said again. */
.view-all:hover .view-all__arrow,
.view-all:focus-visible .view-all__arrow,
.closing__pill:hover .closing__arrow,
.closing__pill:focus-visible .closing__arrow {
  color: var(--gold);
}

/* Hero and closing pills. The comp already gives them an orange outer glow, so
   hover recolours the glow it has rather than adding a second effect. Their
   chevrons need no rule of their own — those are currentColor and unpinned. */
.pill {
  transition:
    color var(--dur) var(--ease),
    border-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}

.pill:hover,
.pill:focus-visible {
  color: var(--gold);
  border-color: var(--gold);
  box-shadow: 0 0 22px var(--gold-dim);
}

.pill--filled:hover,
.pill--filled:focus-visible {
  box-shadow: 0 0 22px var(--gold-dim), inset 0 0 60px rgb(240 180 41 / 0.14);
}

/* --- Capability icons shake on hover -------------------------------------
   Top goes left, centre, right, centre, repeating until the hover ends. The
   pivot is the icon's base, which is what makes it the *top* that swings —
   about the centre it would read as spinning.

   The swing was 45 degrees, which was the brief and was too much: at that
   angle a 70px glyph sweeps most of its own column and reads as a malfunction
   rather than a nudge. Taken to 10 on instruction.

   `rotate` rather than `transform`, because .capability__icon already spends
   its transform on the translateX(-50%) that centres it in the column, and the
   independent rotate property composes with that instead of replacing it.
   transform-origin governs both, and a translate does not care where the
   origin is, so nothing else moves. */
@keyframes capability-shake {
   0%  { rotate:   0deg; }
  25%  { rotate: -10deg; }
  50%  { rotate:   0deg; }
  75%  { rotate:  10deg; }
 100%  { rotate:   0deg; }
}

.capability__icon {
  transform-origin: 50% 100%;
}

.capability:hover .capability__icon,
.capability:focus-within .capability__icon {
  animation: capability-shake 0.9s ease-in-out infinite;
}

/* --- Opportunity cards follow the pointer --------------------------------
   The perspective goes on the band, not on the <ul>. The band is already the
   containing block for these absolutely positioned cards, so putting it here
   changes no geometry; putting it on the <ul> would move every card, because
   `perspective` establishes a containing block of its own and that <ul> is a
   zero-height static box.

   --tilt is set by js/spark.js and is 0deg at rest, which is how the comp
   draws them. With JavaScript off, or under prefers-reduced-motion, it is
   never set at all and the fallback in the shorthand keeps them square. */
.carousel--opps { perspective: 1400px; }

/* Two transforms on one card, composed rather than fighting: the tilt follows
   the pointer across the whole band, the scale answers the pointer being on
   this particular card. Both ride the same transition. */
.opp {
  transform: rotateY(var(--tilt, 0deg)) scale(var(--pop, 1));
  transition: transform 160ms ease-out;
  will-change: transform;
}

/* 1.124 is not a taste decision — it is 327/291, the ratio the comp used to
   make its centre card the featured one. :focus-within so the card a keyboard
   has landed on grows too; spark.js squares that card up at the same moment.
   The gaps are 23.7px and the card grows 18px each side, so nothing collides,
   but the z-index makes that true regardless of what the gaps become later. */
.opp:hover,
.opp:focus-within {
  --pop: 1.124;
  z-index: 1;
}

/* --- Partner-story rail: cards face the middle ---------------------------
   --face and --pop are set per card by spark.js, from how far that card sits
   from the middle of the rail. Both fall back to the identity, so with no
   script this is a plain horizontal scroller of five flat cards.

   perspective() lives inside each card's own transform rather than on the
   track. On the track the vanishing point would be the centre of a rail
   several thousand pixels wide, so a card's angle would depend on where it
   happened to fall in the clone sequence. Per card, each turns about its own
   axis, which is the whole point.

   900px is short on purpose: at 1500px a 16-degree turn foreshortens a 281px
   card by about 4%, which is not a fan, it is a rounding error. */
.story {
  transform: perspective(900px) rotateY(var(--face, 0deg)) scale(var(--pop, 1));
  transition: transform 90ms linear;
}

/* Motion is decoration. The reveal is handled in base.css; these are the
   page's own moving parts. */
/* Scroll-linked rotation is exactly the kind of motion this asks to be spared,
   so the rail stays a rail and the cards stay flat — spark.js checks the same
   query and never sets --face. */
@media (prefers-reduced-motion: reduce) {
  .opp,
  .story { transition: none; }

  .view-all,
  .pill { transition: none; }

  .capability:hover .capability__icon,
  .capability:focus-within .capability__icon { animation: none; }
}

/* ==========================================================================
   Narrower desktops. The comp only exists at 1366, so below that the column
   shrinks on its 68px gutters and the fixed-height bands are released. The
   three cqw bands need nothing — they scale themselves.
   Mobile is deliberately out of scope until the mobile comps land.
   ========================================================================== */

@media (max-width: 1365px) {
  .trust { height: auto; padding-bottom: 60px; }
  .trust__bg { object-position: center top; }

  .closing__panel { height: auto; padding-bottom: 40px; }
}

@media (max-width: 1200px) {
  .page-home { --gutter: 40px; }

  .panel--stats { height: auto; padding-bottom: 24px; }
  .panel--logos { padding: 28px 12px; }
  .logos__group { padding: 0 18px; }
  .logos__set { gap: 22px 22px; }

  /* Below the comp's width the capability columns stop being wide enough to
     hold the comp's line breaks, so they are released from the fixed 540px box
     and simply flow. Pinning them would only push copy out of its column. */
  .capability-grid { gap: 0 12px; }

  .capability {
    display: flex;
    flex-direction: column;
    align-items: center;
    height: auto;
  }

  .capability__icon,
  .capability__title,
  .capability__text {
    position: static;
    transform: none;
  }

  .capability__icon { order: -1; }
  .capability__title { margin-top: 28px; }
  .capability:nth-child(1) .capability__text,
  .capability:nth-child(2) .capability__text,
  .capability:nth-child(3) .capability__text,
  .capability:nth-child(4) .capability__text { width: auto; max-width: 274px; }
  .capability__text { margin-top: 22px; }
  .capability + .capability::before { top: 0; height: 100%; }
}

/* ==========================================================================
   Phones and tablets — 390px design, from `Spark Home Mobile.dc.html`

   Not a second page: the same markup, re-laid-out. Every number below is the
   design's own at its 390px canvas, and the two card types keep their `--k`
   scale so everything *inside* a card stays in the comp's proportions — the
   card just gets a new width and --k is restated in px, because a cqw unit on
   a 390px container is meaningless.

   The breakpoint is 1023, not 767, and that is deliberate. The desktop layout
   is fluid down to about 1024 and no further — below it the header's three
   pills and the story rail push the document to a horizontal scroll. Ending
   the phone layout at 767 would have left 768..1023 as the one width the site
   is broken at, so the two layouts meet exactly where the desktop one stops
   working. The design is drawn at 390 and simply gets wider from there: the
   rails show more cards, the bands keep their 20px inset.
   Only the homepage carries the drawer markup, so the header rules here are
   scoped to .page-home; when the other two mobile designs land they move to
   base.css.
   ========================================================================== */

@media (max-width: 1023px) {

  /* The shared column goes. Every band below sets its own 16 or 20px inset,
     which is how the design works — there is no single content column on a
     phone, and leaving .shell in place would add its gutter *on top of* each
     band's padding and inset everything twice. */
  .page-home .shell {
    width: 100%;
    max-width: none;
    margin-inline: 0;
  }

  /* --- Header --------------------------------------------------------- */

  /* The bar, the toggle and the drawer are shared, and live in base.css. Only
     this page's own consequence of them stays here: the hero starts directly
     under the bar, because the comp's 202px of black above it is a desktop
     composition and not a mobile one. */
  .page-home main { padding-top: 0; }

  /* --- Hero ------------------------------------------------------------- */

  .hero { height: 556px; }
  .hero__bg { object-position: 52% 40%; }

  /* The comp's own black-to-transparent-to-black wash, which the desktop band
     gets from the photograph itself. At this crop it needs help. */
  .hero__inner::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgb(0 0 0 / 0.55) 0%, rgb(0 0 0 / 0.1) 32%,
                                        rgb(0 0 0 / 0.72) 78%, #000 100%);
  }

  .hero__inner {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 0 20px 40px;
  }

  /* The design sets 48px flat. At 390 that puts "WE CONNECT BRANDS TO IT" at
     386px inside a 350px box, so it wraps to a third line and the two-line
     lockup the comp draws falls apart. Measured, not guessed: the widest line
     needs 8.05 characters-worth per 10px of type, so the size has to track the
     viewport until there is room for the full 48. 10.9vw is 42.5px at 390,
     which puts that line at 342 — inside the box with 8px to spare — and the
     min() hands back to a flat 48px by 441px wide. */
  .hero__title {
    position: relative;
    padding-top: 0;
    font-size: min(48px, 10.9vw);
    line-height: 0.917;             /* the design's 44/48 */
    letter-spacing: 0.005em;
    text-wrap: balance;
  }

  .hero__actions {
    position: relative;
    align-items: stretch;
    gap: 12px;
    margin-top: 30px;
  }

  /* .pill is a fixed 403x63 — the comp's own box, and 13px wider than the
     viewport. Both hero pills and the closing one become full-width buttons. */
  .pill {
    width: auto;
    height: 54px;
    padding-left: 0;
    font-size: 15px;
  }

  /* The comp pins the chevrons to absolute x positions inside that 403px box.
     With the box gone they anchor to the button's own edges. */
  .pill__chevrons { left: auto; right: 18px; }
  .pill__chevrons--back { left: 18px; right: auto; }
  .pill .chevron { width: 8px; height: 15px; }

  /* --- Manifesto -------------------------------------------------------- */

  /* The desktop band is one baked image with the card drawn into it. Here the
     photograph is a 236px strip and the card is real CSS over it, because at
     390px the baked card would be 45px tall and its copy unreadable. */
  .manifesto {
    aspect-ratio: auto;
    margin-top: 0;
    padding-top: 236px;            /* the strip the photo below fills */
    padding-bottom: 44px;
    container-type: normal;
  }

  /* "EXPERIENCE / SHIFT CULTURE" is *baked into this photograph* — the comp
     flattened the card's headline into the backdrop, and the desktop layout
     lays the live copy exactly on top of it, which is why it is invisible
     there. A 236px strip of the same image at this width shows the baked
     headline above the card that repeats it.
     The design's own 74% object-position does not help: at 390x236 the image
     covers at scale 0.30, so only 20px of the 1366 is ever cropped and the
     whole left half — headline included — stays on screen.
     So the photo is widened to 216% and anchored right, which crops at 0.616
     and starts the visible window at source x734: past the baked card, into
     the crowd. It is absolute, hence the padding-top above. */
  .manifesto__bg {
    left: auto;
    right: 0;
    bottom: auto;
    top: 0;
    width: 216%;
    /* base.css caps every img at max-width:100%, which silently clamps the
       216% straight back to the viewport and undoes the whole crop. */
    max-width: none;
    height: 236px;
    object-position: 100% 42%;
  }

  .manifesto::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 236px;
    background: linear-gradient(180deg, rgb(0 0 0 / 0.15), rgb(0 0 0 / 0.92));
  }

  .manifesto__copy {
    position: relative;
    left: auto;
    top: auto;
    width: auto;
    margin: -56px 20px 0;
    padding: 26px 22px 28px;
    border: 1px solid rgb(244 105 2 / 0.55);
    border-radius: 14px;
    background: rgb(0 0 0 / 0.82);
    backdrop-filter: blur(3px);
    box-shadow: 0 0 34px rgb(244 105 2 / 0.16);
  }

  .manifesto__title { font-size: 44px; line-height: 41px; }

  .manifesto__dash { width: 81px; height: 1px; margin-top: 20px; }
  .manifesto__text + .manifesto__dash { margin-top: 18px; }

  /* width, not just the type: the desktop rule sets 35.578cqw, and once
     container-type goes to normal a cqw falls back to the *viewport*, not to
     the card. That silently became 139px inside a 306px card — a column two
     words wide with half the card empty beside it. */
  .manifesto__text {
    width: auto;
    margin-top: 12px;
    font-size: 14px;
    line-height: 20px;
  }

  /* --- Both carousels --------------------------------------------------- */

  .carousel {
    aspect-ratio: auto;
    height: auto;
    padding: 34px 0 40px;
    container-type: normal;        /* no cqw survives below */
  }

  .carousel--opps { margin-top: 0; perspective: none; }

  .carousel__bg { opacity: 0.9; }

  .carousel::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, #000 0%, rgb(0 0 0 / 0.3) 28%,
                                        rgb(0 0 0 / 0.38) 71%, #000 100%);
  }

  /* Both of these are placed by two-class rules above — .carousel--opps
     .carousel__title and its --stories twin — so a single-class override here
     loses on specificity and the element keeps a cqw offset that no longer
     means anything. Matching the specificity is the whole point of the doubled
     selectors below. */
  .carousel--opps .carousel__title,
  .carousel--stories .carousel__title {
    position: relative;
    z-index: 1;
    left: auto;
    top: auto;
    padding: 0 20px;
    font-size: 30px;
  }

  /* One dash under the heading, not the comp's doubled vector-plus-streak: at
     this size the 18px offset between them reads as a mistake. */
  .carousel__dash {
    position: relative;
    z-index: 1;
    left: auto;
    top: auto;
    width: 81px;
    margin: 10px 0 0 20px;
  }

  .carousel__dash--streak { display: none; }

  .carousel--opps .carousel__view-all,
  .carousel--stories .carousel__view-all {
    position: relative;
    z-index: 1;
    left: auto;
    top: auto;
    /* Block-level rather than inline-flex: as an inline box it picks up a
       20px indent from the band's text flow and lands at 40, not 20. */
    display: flex;
    width: fit-content;
    align-items: center;
    margin: 22px 0 0 20px;
    font-size: 12px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
  }

  .view-all__arrow { width: 30px; height: 12px; margin-left: 10px; }

  /* --- Opportunity rail ------------------------------------------------- */

  .opps {
    position: relative;
    z-index: 1;
    display: flex;
    gap: 14px;
    margin-top: 20px;
    padding: 0 20px 4px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }

  .opps::-webkit-scrollbar { display: none; }

  .opp {
    position: relative;
    flex: none;
    left: auto;
    top: auto;
    scroll-snap-align: center;
    width: 230px;
    /* 230 / 291, so every calc() inside the card still reads as comp pixels. */
    --k: 0.79px;
    border-radius: calc(24 * var(--k));
  }

  /* Hover growth is a pointer affordance; on a touch rail it would fire on tap
     and shift the card the finger is on. */
  .opp:hover, .opp:focus-within { --pop: 1; }

  /* --- Story rail ------------------------------------------------------- */

  .stories {
    position: relative;
    left: auto;
    right: auto;
    top: auto;
    margin-top: 20px;
    padding: 0 20px 4px;
    scroll-snap-type: x mandatory;
    cursor: auto;
    isolation: auto;
  }

  .stories__track { gap: 14px; }

  /* The desktop card is a fixed square with its copy absolutely placed. Those
     offsets are struck from the editable card's own 376px box, not from the
     281px it renders at, so --k is width/376 and not width/281 — the ratio the
     line below used to carry. At 0.89 the title landed 206px down a 250px card
     and a two-line one fell straight out of the bottom.
     Correcting --k to 250/376 fits, but it also takes the description to
     9.5px, which is not a size to read on a phone. So the card stops being a
     fixed square here: the art is a strip, the copy flows beneath it at sizes
     chosen for this width, and the flex row stretches every card to the
     tallest so the row still reads as a row. --k stays correct for the border
     and the corner, which are still comp measurements. */
  .story {
    scroll-snap-align: center;
    width: 250px;
    height: auto;
    aspect-ratio: auto;
    --k: 0.665px;                  /* 250 / 376 */
    border-width: 2px;
    border-radius: 13px;
    transform: none;               /* the loop is stood down; nothing turns */
  }

  .story__link { display: flex; flex-direction: column; }

  .story__art {
    position: relative;
    height: 145px;
    flex: none;
    object-fit: cover;             /* desktop fills a known box; this one crops */
  }

  /* Desktop fades the whole card because the copy sits *over* the art. Here it
     sits under it, so the fade has only the art's own foot to soften. */
  .story__link::after {
    inset: 105px 0 auto;
    height: 40px;
    background: linear-gradient(180deg, transparent, #000);
  }

  .story__body {
    position: relative;
    left: auto;
    top: auto;
    right: auto;
    padding: 12px 16px 16px;
  }

  .story__title { font-size: 21px; line-height: 20px; }
  /* Same proportion to the title as on desktop. The card is content-height
     here, so the extra line grows it rather than needing room made for it. */
  .story__role { margin-top: 4px; font-size: 10px; }
  .story__dash { width: 52px; margin-top: 10px; }
  .story__text { margin-top: 10px; font-size: 12px; line-height: 16px; }

  /* Chevrons are a pointer affordance standing in for a rail you cannot drag.
     A touch rail can be swiped, so they are only clutter here — and they are
     absolutely placed against a rail that no longer has the height to hold
     them, which is what left them floating beside the heading.
     Matching the loop-ready selector on purpose: that rule is three classes
     wide and would otherwise win from outside this media block, which is
     exactly what happens when a desktop window is narrowed rather than
     loaded at this width. */
  .rail-nav,
  .stories[data-loop-ready] ~ .rail-nav { display: none; }

  /* --- Why brands trust Spark ------------------------------------------- */

  .trust {
    height: auto;
    padding: 36px 0 40px;
  }

  .trust::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgb(255 255 255 / 0.55),
                                        rgb(255 255 255 / 0.92) 40%, #fff 100%);
  }

  .trust__inner { z-index: 1; padding: 0 20px; }

  .trust__eyebrow { padding-top: 0; font-size: 15px; }
  .trust__eyebrow-dash { width: 63px; margin-top: 13px; }

  .headline-stats { gap: 16px; margin-top: 30px; }
  .headline-stats__item { flex: 1; }
  .headline-stats__value { font-size: 60px; line-height: 0.78; }
  .headline-stats__label { margin-top: 12px; font-size: 11px; line-height: 1.2; }
  .headline-stats__dash { width: 44px; margin-top: 9px; }

  .panel { width: auto; }

  .panel--stats {
    grid-template-columns: repeat(3, 1fr);
    height: auto;
    margin-top: 26px;
    padding: 18px 4px 16px;
  }

  .panel-stat { padding: 0 6px; }
  .panel-stat__value { font-size: 34px; line-height: 0.75; }
  .panel-stat__label { margin-top: 9px; font-size: 8.5px; line-height: 1.25; }
  .panel-stat__dash { display: none; }

  /* The comp's fading gradient divider is 1px of nothing at this height; a
     flat hairline is what actually reads. */
  .panel-stat + .panel-stat::before {
    top: 0;
    height: 100%;
    background: #EFEFEF;
  }

  /* The logo wall is 1152px of artwork. Scaled to 350 the marks are illegible,
     so it keeps a readable size and scrolls — the design says so in words, and
     the caption below is the affordance. */
  /* .trust__inner already pads 20; the design's own 20px margin would double
     it, so the panel only needs the top gap. */
  .panel--logos {
    margin: 14px 0 0;
    padding: 22px 16px 18px;
  }

  /* Three columns cannot survive 350px — the widest group would be one mark
     per row and eight rows deep. So the grouping turns: the groups stack, and
     the rule that divided them turns with them. The wall no longer scrolls,
     which is why the caption below dropped the word "swipe". */
  .logos {
    display: block;
    overflow: visible;
    padding: 0;
  }

  .logos__group { padding: 18px 0; }

  .logos__group + .logos__group {
    border-left: 0;
    border-top: 1px solid var(--logo-rule);
  }

  .logos__group:first-child { padding-top: 0; }
  .logos__group:last-child { padding-bottom: 0; }

  .logos__set { gap: 18px 20px; height: auto; }

  /* Four marks, and three of them fit on one line only because The I Group is
     a square lockup and lands 38px wide — which strands MEG alone underneath.
     Halved slots force the even 2/2 the other two groups fall into on their
     own. */
  .logos__group--promoters .logos__item {
    width: calc(50% - 10px);
    justify-content: center;
  }

  /* Smaller caps than desktop: at 350px the three widest wordmarks would
     otherwise take a whole row each. */
  .logos__mark { max-width: 104px; max-height: 38px; }

  .trust__logo-hint {
    display: block;
    margin-top: 16px;
    font-size: 9.5px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--logo-hint);
  }

  /* --- Our capabilities ------------------------------------------------- */

  .caps-section { padding: 48px 0 46px; }

  .caps-section__title { padding-left: 0; font-size: 42px; }
  .caps-section__dash { width: 81px; margin-top: 14px; }

  .capability-grid {
    display: flex;
    gap: 1px;
    margin-top: 0;
    padding: 34px 20px 0;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }

  .capability-grid::-webkit-scrollbar { display: none; }

  .capability {
    flex: none;
    scroll-snap-align: center;
    width: 250px;
    height: auto;
    padding: 0 18px;
    border-right: 1px solid var(--caps-rule);
  }

  .capability:last-child { border-right: 0; }

  /* The desktop divider is a fading gradient pinned to the column box; the
     border above replaces it. */
  .capability + .capability::before { display: none; }

  /* All four icons to one size — the comp's four different ones are a
     desktop composition and at 96px the differences read as a mistake. */
  .capability:nth-child(1) .capability__icon,
  .capability:nth-child(2) .capability__icon,
  .capability:nth-child(3) .capability__icon,
  .capability:nth-child(4) .capability__icon { width: 96px; height: 96px; }

  .capability__title { margin-top: 22px; font-size: 22px; line-height: 24px; }
  .capability__dash { width: 57px; margin-top: 11px; }

  .capability:nth-child(1) .capability__text,
  .capability:nth-child(2) .capability__text,
  .capability:nth-child(3) .capability__text,
  .capability:nth-child(4) .capability__text {
    width: auto;
    max-width: none;
    margin-top: 14px;
    font-size: 12.5px;
    line-height: 17px;
  }

  /* --- Closing CTA ------------------------------------------------------ */

  .closing { padding: 0 16px 34px; }

  .closing__panel {
    height: auto;
    padding: 30px 22px 28px;
    border-radius: 22px;
    text-align: center;
  }

  .closing__bg { object-position: 50% 46%; }

  .closing__panel::after {
    content: "";
    position: absolute;
    inset: 0;
    background: rgb(0 0 0 / 0.42);
  }

  .closing__eyebrow,
  .closing__title,
  .closing__foot { position: relative; z-index: 1; }

  .closing__eyebrow { left: auto; top: auto; font-size: 11px; }
  .closing__eyebrow-dash { width: 81px; margin: 13px auto 0; }

  .closing__title { left: auto; top: auto; margin-top: 18px; }
  .closing__title-line1 { font-size: 30px; line-height: 1.05; }
  .closing__title-line2 { margin-top: 6px; font-size: 31px; line-height: 1.05; }

  /* The desktop foot is one row with the lede right-aligned against a 289px
     indent — the comp's own composition. Here it stacks. */
  .closing__foot {
    left: auto;
    top: auto;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    padding-left: 0;
    margin-top: 0;
  }

  .closing__lede {
    width: auto;
    margin-top: 18px;
    font-size: 13.5px;
    line-height: 19px;
    text-align: center;
  }

  /* The desktop separator is a vertical rule between the lede and the pill,
     which only makes sense when they sit side by side. */
  .closing__sep { display: none; }

  .closing__pill {
    justify-content: center;
    gap: 12px;                     /* the desktop arrow is pinned, not spaced */
    height: 52px;
    margin-top: 20px;
    font-size: 12px;
    letter-spacing: 0.2em;
  }

  .closing__arrow { width: 30px; height: 13px; }
}
