/* Snackpass marketplace redesign — shared chrome for the four staging pages
   (/home-v3, /creators-v2, /brands-v2, /commerce).

   These pages are the inverse of the rest of snackpass.co: one fixed blue
   gradient runs behind all of them, so every surface is glass or a floating
   white card and type is white by default. That system is identical on all
   four, which is why it lives here instead of being copied into each page's
   <style> block. Each page keeps only its own sections locally.

   This file is NOT part of brand.css and is loaded only by the redesign
   pages — nothing on the live marketing site is affected by editing it.
   Tokens and the .btn / .eyebrow families still come from brand.css. */

.spr {
  /* The handoff specifies this gradient as final intent. Its three stops are
     not in tokens/colors.css — they sit between --sp-blue and --sp-sky. Named
     once here rather than repeated; if this background graduates to the whole
     site, these belong in the token file. */
  --spr-page: linear-gradient(160deg, #0a5fa0 0%, #0088e8 45%, #19aeff 100%);
  /* The same stops as the page, at pill scale: --gradient-product runs bright
     blue into sky, which reads much lighter than the background it sits on. */
  --spr-cta: linear-gradient(135deg, #0d6cb4 0%, #0099ff 100%);
  --spr-glass: rgba(255,255,255,.12);
  --spr-glass-line: rgba(255,255,255,.3);
  --spr-card-shadow: 0 24px 64px rgba(10,37,64,.25);
  /* Surface theme. The default is the gradient: white type on glass. A
     .spr-light wrapper flips these for sections that sit on white, so every
     shared component below reads from the variables instead of hardcoding a
     colour for one surface. */
  --spr-ink: #fff;
  --spr-ink-soft: rgba(255,255,255,.85);
  --spr-ink-mute: rgba(255,255,255,.7);
  --spr-eyebrow: #fff;
  --spr-accent: var(--sp-navy);
  position: relative;
  text-transform: none;          /* overrides the brand lowercase default */
  font-family: var(--font-text);
  color: #fff;
}
/* Painted on the root as well, so the first frame is blue rather than a white
   flash before the fixed layer composites. */
html, body { background: #0088e8; }
.spr h1, .spr h2, .spr h3 { font-family: var(--font-display); font-weight: 800; color: var(--spr-ink); text-transform: none; }

/* ---- light surface ----
   Wraps the sections that sit on white once the gradient has faded out. Only
   the variables change; the components themselves are the same rules. */
.spr-light {
  --spr-ink: var(--sp-navy);
  --spr-ink-soft: var(--sp-slate);
  --spr-ink-mute: var(--sp-slate);
  /* Eyebrows run at 13px, where --sp-blue is 3.0:1 on white. This scope is
     the redesign only; brand.css stays as it is for the live pages. */
  /* Brand blue, at your call: --sp-blue-800 cleared AA at this size but read
     closer to navy than to Snackpass. #0099FF is 3.0:1 on white against the
     4.5:1 small-text bar, so eyebrows on light surfaces are a known exception
     — sizing them to 19px bold would make 3:1 the applicable bar and clear it. */
  --spr-eyebrow: var(--sp-blue);
  --spr-accent: var(--sp-blue);
  --spr-glass: #fff;
  --spr-glass-line: var(--sp-line);
  --spr-card-shadow: 0 18px 48px rgba(10,37,64,.10);
  color: var(--sp-navy);
}
/* A white pill on a white page is invisible, so the CTA buttons become the
   product-gradient primary instead — no markup change needed. */
.spr-light .btn-white { background: var(--spr-cta); color: #fff; box-shadow: 0 10px 28px rgba(10,95,160,.34); }
.spr-light .btn-white:hover { filter: brightness(1.04); transform: translateY(-2px); }
/* Glass has nothing to refract on white; these become plain white cards. */
.spr-light .spr-glass, .spr-light .cre-benefit, .spr-light .brd-trait, .spr-light .com-app-card {
  backdrop-filter: none; -webkit-backdrop-filter: none;
  box-shadow: 0 14px 40px rgba(10,37,64,.08);
}
/* A floating white card needs a hairline once the page behind it is also
   white — the deep shadow alone stops reading as an edge. */
.spr-light .spr-card-white { border: 1px solid var(--sp-line); box-shadow: 0 18px 48px rgba(10,37,64,.10); }
/* Translucent-white icon tiles become a light blue fill. */
.spr-light .brd-trait-ico, .spr-light .com-app-ico {
  background: var(--sp-blue-050); border-color: var(--sp-blue-100); color: var(--sp-blue);
}

/* ---- fade page ----
   Creators and Brands lead with the gradient and then resolve onto white. The
   background stops being fixed (so it scrolls away with the hero), is capped
   at the hero's height, and is masked so it dissolves rather than ending on a
   hard edge. --spr-fade-h is set per page to match its hero. */
.spr-fade { background: #fff; }
.spr-fade .spr-bg {
  position: absolute; top: 0; bottom: auto; height: var(--spr-fade-h, 1100px);
  -webkit-mask-image: linear-gradient(180deg, #000 var(--spr-fade-solid, 58%), transparent 100%);
  mask-image: linear-gradient(180deg, #000 var(--spr-fade-solid, 58%), transparent 100%);
}
/* Content links take the surface's colour, but buttons must keep their own —
   without the :not() this beats .btn-white and its label goes white-on-white. */
.spr a:not(.btn) { color: inherit; }
/* nowrap keeps eyebrows from breaking awkwardly where there is room. On a
   phone there isn't: "loved by thousands of brands and creators" measures
   452px of letter-spaced caps in a 390px frame and ran off both edges. */
.spr .eyebrow { white-space: nowrap; }
@media (max-width: 620px) {
  .spr .eyebrow { white-space: normal; text-wrap: balance; }
}
.spr-eyebrow-light { color: var(--spr-eyebrow); }

/* ---- buttons ---- */
.spr .btn-sm { font-size: 13.5px; padding: 8px 16px; }
/* Press feedback: brand.css's .btn has hover but no :active. 140ms because a
   press has to answer immediately — the 200ms hover spring is too slow here. */
.spr .btn { transition: transform 140ms var(--ease-out), box-shadow var(--dur-base) var(--ease-out), filter var(--dur-base) var(--ease-out); }
.spr .btn:active { transform: translateY(-1px) scale(.97); }
/* On the gradient the ghost button is an outline, not brand.css's white pill. */
.spr-btn-ghost-dark { background: transparent; color: #fff; border: 1.5px solid rgba(255,255,255,.55); box-shadow: none; }
.spr-btn-ghost-dark:hover { border-color: #fff; background: rgba(255,255,255,.12); }

/* ---- the page background ----
   One fixed gradient with blurred light shapes over it. Each shape drifts on
   its own long loop and its wrapper is translated by scroll position, so the
   light moves at a different rate from the content. Only the wrappers are
   scripted; the blur never re-renders because the blurred child is not what
   moves. The fourth shape is Home's alone (data-bgr also spins it). */
.spr-bg { position: fixed; inset: 0; z-index: 0; overflow: hidden; background: var(--spr-page); pointer-events: none; }
.spr-bg > div { position: absolute; inset: 0; will-change: transform; }
.spr-bg span { position: absolute; display: block; border-radius: 50%; }
.spr-glow-1 { top: 16%; left: 22%; width: 92vw; height: 56vw; background: radial-gradient(closest-side, rgba(255,255,255,.45), rgba(255,255,255,0) 70%); filter: blur(60px); animation: sprDrift1 18s ease-in-out infinite alternate; }
.spr-glow-2 { top: -18%; right: -12%; width: 72vw; height: 48vw; background: radial-gradient(closest-side, rgba(47,195,255,.75), transparent 70%); filter: blur(50px); animation: sprDrift2 22s ease-in-out infinite alternate; }
.spr-glow-3 { bottom: -22%; left: -14%; width: 78vw; height: 52vw; background: radial-gradient(closest-side, rgba(8,64,120,.65), transparent 70%); filter: blur(70px); animation: sprDrift3 26s ease-in-out infinite alternate; }
.spr-glow-4 { top: 48%; left: 6%; width: 85vw; height: 16vw; border-radius: 50%; background: linear-gradient(90deg, transparent, rgba(255,255,255,.35), transparent); filter: blur(44px); transform: rotate(-22deg); animation: sprDrift3 20s ease-in-out infinite alternate; }
@keyframes sprDrift1 { from { transform: rotate(-20deg) translate3d(0,0,0) scale(1); } to { transform: rotate(-10deg) translate3d(7vw,-5vh,0) scale(1.08); } }
@keyframes sprDrift2 { from { transform: translate3d(0,0,0) scale(1); } to { transform: translate3d(-6vw,7vh,0) scale(1.18); } }
@keyframes sprDrift3 { from { transform: translate3d(0,0,0) rotate(0deg); } to { transform: translate3d(6vw,-6vh,0) rotate(8deg); } }
/* Content rides above the background. The nav is deliberately excluded: it
   carries its own position: sticky, and a `position: relative` here would
   quietly un-stick it. */
.spr > div:not(.spr-bg), .spr > section, .spr > header, .spr > footer { position: relative; z-index: 1; }

/* ---- floating glass nav ---- */
.spr-nav { position: sticky; top: 16px; z-index: 50; padding: 0 24px; }
.spr-nav-inner {
  /* The right padding was sized around a CTA pill. With sign in as the last
     item the text would otherwise sit hard against the edge. */
  max-width: 920px; margin: 0 auto; padding: 8px 16px 8px 24px;
  display: flex; align-items: center; gap: 24px;
  background: rgba(255,255,255,.14);
  backdrop-filter: blur(24px) saturate(1.6); -webkit-backdrop-filter: blur(24px) saturate(1.6);
  border: 1px solid rgba(255,255,255,.35); border-radius: var(--radius-pill);
  box-shadow: 0 8px 32px rgba(10,37,64,.18), inset 0 1px 0 rgba(255,255,255,.45);
}
/* Padding rather than height: the lockup keeps its size, the link gets a
   thumb-sized target around it. */
.spr-nav-logo { display: flex; align-items: center; padding: 11px 6px; margin: -11px -6px; }
/* One lockup, inverted to white — no second asset to keep in sync. */
/* width: auto matters: the img carries width/height attributes, so a CSS
   height override on its own leaves the attribute width in place and squashes
   the lockup — which is what happened at the mobile breakpoint. */
.spr-nav-logo img { height: 24px; width: auto; display: block; filter: brightness(0) invert(1); }
.spr-nav-links { display: flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 600; }
/* Sign in and the CTA are one group. As separate children of a
   space-between row they were pushed apart, which read as two unrelated
   controls rather than the account corner of the bar. */
/* The sections sit next to the logo; sign in is pushed to the far edge on its
   own, so the bar reads as "where to go" on the left, "who you are" on the
   right. margin-left rather than space-between, which would have spread the
   three sections across the middle. */
.spr-nav-end { display: flex; align-items: center; gap: 4px; flex: none; margin-left: auto; }
.spr-nav-links a { color: #fff; padding: 8px 14px; border-radius: var(--radius-pill); transition: background var(--dur-base) var(--ease-out); }
.spr-nav-links a:hover { background: rgba(255,255,255,.18); }
.spr-nav-links a[aria-current="page"] { background: rgba(255,255,255,.22); }

/* Over the white half the glass pill and its white type disappear, so the nav
   swaps to a light treatment. Driven by an observer watching a sliver of
   viewport at the nav's own height, so it stays correct however the sections
   above it reflow. */
.spr-nav-inner { transition: background .4s var(--ease-out), border-color .4s var(--ease-out), box-shadow .4s var(--ease-out); }
.spr-nav-logo img { transition: filter .4s var(--ease-out); }
.spr-nav.is-light .spr-nav-inner {
  background: rgba(255,255,255,.82);
  border-color: var(--sp-line);
  box-shadow: 0 8px 32px rgba(10,37,64,.10), inset 0 1px 0 #fff;
}
.spr-nav.is-light .spr-nav-logo img { filter: none; }
.spr-nav.is-light .spr-nav-links a { color: var(--sp-navy); }
.spr-nav.is-light .spr-nav-links a:hover { background: var(--sp-mist); color: var(--sp-blue); }
.spr-nav.is-light .spr-nav-links a[aria-current="page"] { background: var(--sp-mist); color: var(--sp-blue); }
.spr-nav.is-light .btn-white { background: var(--spr-cta); color: #fff; box-shadow: 0 6px 18px rgba(10,95,160,.3); }

/* ---- sign in ----
   Built on <details> rather than a scripted popover: it opens, closes and
   takes the keyboard on its own with the script blocked, which matters for a
   menu whose whole job is getting someone to their dashboard. The script only
   adds the two conveniences the element does not have, closing on Escape and
   on a click elsewhere.
   The panel is white on both surfaces. It sits over the page rather than in
   the nav's glass, so inheriting the nav's white type would leave it invisible
   against its own background. */
.spr-signin { position: relative; flex: none; }
.spr-nd { position: relative; flex: none; }
/* Sign in is the only control in the bar that isn't a place on the site, so it
   wears a bubble to read as its own thing next to the three section labels.
   The ring is an inset shadow rather than a border: a real border would add
   2px of height and stand the summary proud of the links beside it. */
.spr-signin > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 14px; font-weight: 600; color: #fff;
  padding: 8px 13px 8px 15px; border-radius: var(--radius-pill);
  background: rgba(255,255,255,.16);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.30), inset 0 1px 0 rgba(255,255,255,.22);
  transition: background var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.spr-signin > summary::-webkit-details-marker { display: none; }
.spr-signin > summary::marker { content: ""; }
.spr-signin > summary::after, .spr-nd-link::after {
  content: ""; width: 14px; height: 14px; flex: none;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center/contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center/contain no-repeat;
  transition: transform var(--dur-base) var(--ease-out);
}
.spr-signin[open] > summary::after { transform: rotate(180deg); }
.spr-signin > summary:hover, .spr-signin[open] > summary {
  background: rgba(255,255,255,.28);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.44), inset 0 1px 0 rgba(255,255,255,.30);
}
/* The label is a destination, not just a toggle: clicking "for brands" goes to
   the brands page. The panel opens on hover and on keyboard focus, so it needs
   no script and nothing swallows the click. Below 900px the burger carries all
   of this, and on a touch screen without hover the tap follows the link, which
   is the page the menu was pointing at anyway. */
.spr .spr-nd-link { display: inline-flex; align-items: center; gap: 5px; color: #fff; padding: 8px 14px; border-radius: var(--radius-pill); transition: background var(--dur-base) var(--ease-out); }
.spr-nd:hover .spr-nd-link, .spr-nd:focus-within .spr-nd-link { background: rgba(255,255,255,.18); }
.spr-nd-menu { opacity: 0; visibility: hidden; transform: translateY(-4px); transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out), visibility var(--dur-base); }
.spr-nd:hover .spr-nd-menu, .spr-nd:focus-within .spr-nd-menu { opacity: 1; visibility: visible; transform: translateY(0); }
.spr-nd:hover .spr-nd-link::after, .spr-nd:focus-within .spr-nd-link::after { transform: rotate(180deg); }
.spr-signin-menu, .spr-nd-menu {
  position: absolute; top: calc(100% + 12px); z-index: 60;
  min-width: 264px; padding: 8px;
  background: #fff; border: 1px solid var(--sp-line); border-radius: 18px;
  box-shadow: 0 22px 54px rgba(10,37,64,.22);
}
.spr-signin-menu { right: 0; }
.spr-nd-menu { left: 0; min-width: 286px; }
.spr .spr-signin-menu a, .spr .spr-nd-menu a { display: block; padding: 10px 12px; border-radius: 12px; color: var(--sp-navy); font-size: 14.5px; font-weight: 700; }
.spr-signin-menu a span, .spr-nd-menu a span { display: block; margin-top: 2px; font-size: 12.5px; font-weight: 400; color: var(--sp-slate); }
.spr .spr-signin-menu a:hover, .spr .spr-nd-menu a:hover { background: var(--sp-mist); color: var(--sp-blue); }
.spr-nav.is-light .spr-signin > summary, .spr-nav.is-light .spr-nd-link { color: var(--sp-navy); }
/* Over the white half the translucent bubble has nothing to sit on, so it
   becomes a solid one with a hairline ring. */
.spr-nav.is-light .spr-signin > summary {
  background: #fff;
  box-shadow: inset 0 0 0 1px var(--sp-line), 0 1px 2px rgba(10,37,64,.06);
}
.spr-nav.is-light .spr-signin > summary:hover, .spr-nav.is-light .spr-signin[open] > summary {
  background: var(--sp-mist); color: var(--sp-blue);
  box-shadow: inset 0 0 0 1px var(--sp-blue-100), 0 1px 2px rgba(10,37,64,.06);
}
.spr-nav.is-light .spr-nd:hover .spr-nd-link, .spr-nav.is-light .spr-nd:focus-within .spr-nd-link { background: var(--sp-mist); color: var(--sp-blue); }
@media (max-width: 620px) {
  /* The links collapse at this width; sign in stays, since it is the only way
     back into an account from a phone.
     The panel anchors to the viewport rather than to the summary here. Hung
     off the summary's right edge it reaches 240px leftward, which runs past
     the left edge of a 360px screen and clips the card. */
  .spr-signin > summary { padding: 8px 8px 8px 10px; font-size: 13.5px; }
  .spr-signin-menu, .spr-nd-menu { position: fixed; top: 74px; left: 12px; right: 12px; min-width: 0; }
}

/* ---- the menu, below desktop ----
   The page links collapse under 900px and, until this, collapsed into nothing.
   Same <details> mechanism as sign in: open, close and keyboard with no
   script. It carries the page links and both dashboards, so nothing in the bar
   is unreachable from a phone. */
.spr-burger { position: relative; display: none; flex: none; }
.spr-burger > summary {
  list-style: none; cursor: pointer;
  width: 40px; height: 40px; border-radius: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  transition: background var(--dur-base) var(--ease-out);
}
.spr-burger > summary::-webkit-details-marker { display: none; }
.spr-burger > summary::marker { content: ""; }
.spr-burger > summary span { display: block; width: 16px; height: 2px; border-radius: 2px; background: #fff; transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out); }
.spr-burger[open] > summary { background: rgba(255,255,255,.18); }
.spr-burger[open] > summary span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.spr-burger[open] > summary span:nth-child(2) { opacity: 0; }
.spr-burger[open] > summary span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
.spr-burger-menu {
  position: fixed; top: 74px; left: 12px; right: 12px; z-index: 60;
  padding: 8px; background: #fff; border: 1px solid var(--sp-line);
  border-radius: 18px; box-shadow: 0 22px 54px rgba(10,37,64,.22);
}
.spr .spr-burger-menu a { display: block; padding: 11px 12px; border-radius: 12px; color: var(--sp-navy); font-size: 15px; font-weight: 700; }
.spr .spr-burger-menu a:hover { background: var(--sp-mist); color: var(--sp-blue); }
.spr-burger-menu a span { display: block; margin-top: 2px; font-size: 12.5px; font-weight: 400; color: var(--sp-slate); }
.spr-burger-sep { height: 1px; margin: 6px 10px; background: var(--sp-line); }
.spr-burger-label { display: block; padding: 8px 12px 2px; font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--sp-slate); }
.spr-nav.is-light .spr-burger > summary span { background: var(--sp-navy); }
.spr-nav.is-light .spr-burger[open] > summary { background: var(--sp-mist); }
@media (max-width: 900px) {
  /* Tablet down: the links and the sign-in menu fold into the one button. */
  .spr-nav-links { display: none; }
  .spr-signin { display: none; }
  .spr-burger { display: block; }
}

/* ---- skip link ----
   Off-screen until it takes focus, then it lands as a real control in the top
   left. The nav is sticky at 16px, so this sits above it. */
.spr-skip {
  position: fixed; top: 10px; left: 10px; z-index: 100;
  transform: translateY(-150%); opacity: 0;
  background: #fff; color: var(--sp-navy); font-size: 14px; font-weight: 700;
  padding: 11px 18px; border-radius: var(--radius-pill);
  box-shadow: 0 10px 30px rgba(10,37,64,.22);
  transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}
.spr .spr-skip:focus-visible { transform: translateY(0); opacity: 1; outline: none; box-shadow: 0 10px 30px rgba(10,37,64,.22), var(--focus-ring); }
@media (prefers-reduced-motion: reduce) { .spr-skip { transition: opacity var(--dur-base) ease; } }

/* ---- shared page furniture ---- */
.spr-hero { padding: 176px 32px 88px; margin-top: -72px; position: relative; }
.spr-hero-inner { max-width: 1180px; margin: 0 auto; display: flex; flex-direction: column; gap: 30px; align-items: center; text-align: center; }
.spr-h1 { font-size: clamp(52px, 7.6vw, 110px); letter-spacing: -0.035em; line-height: 0.97; margin: 0; max-width: 15ch; text-wrap: balance; }
.spr-sub { font-size: 20px; line-height: 1.55; color: rgba(255,255,255,.92); max-width: 50ch; margin: 0; text-wrap: pretty; }
.spr-cta-row { display: flex; gap: 14px; flex-wrap: wrap; justify-content: center; }

/* Section statement — the big word-reveal line each page opens its body with. */
.spr-statement { padding: 40px 32px 0; text-align: center; overflow: hidden; }
.spr-statement h2 { font-size: clamp(40px, 5.8vw, 92px); letter-spacing: -0.032em; line-height: 1.04; margin: 0 auto; max-width: 100%; }

/* Glass and white card primitives. */
.spr-glass {
  background: var(--spr-glass);
  backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px);
  border: 1px solid var(--spr-glass-line); border-radius: 28px;
}
.spr-card-white { background: #fff; border-radius: 28px; box-shadow: var(--spr-card-shadow); color: var(--sp-navy); }
.spr-card-white h3, .spr-card-white h2 { color: var(--sp-navy); }
.spr-lift { transition: transform var(--dur-base) var(--ease-out); }

/* Two-column "text beside a floating mock" row, used by Brands and Commerce. */
.spr-feature { padding: 56px 32px; }
.spr-feature-grid { max-width: 1180px; margin: 0 auto; display: grid; grid-template-columns: 1fr 1fr; gap: 64px; align-items: center; }
.spr-feature-copy { display: flex; flex-direction: column; gap: 20px; align-items: flex-start; }
.spr-feature-copy h2 { font-size: clamp(30px, 3.6vw, 48px); letter-spacing: -0.028em; line-height: 1.02; margin: 0; }
.spr-feature-copy p { margin: 0; color: var(--spr-ink-soft); font-size: 17px; line-height: 1.6; max-width: 46ch; }
.spr-ticks { display: flex; flex-direction: column; gap: 12px; font-size: 16px; font-weight: 600; color: var(--spr-ink); }

/* Closing CTA. */
.spr-close { padding: 24px 24px 120px; text-align: center; }
.spr-close-inner { max-width: 960px; margin: 0 auto; display: flex; flex-direction: column; align-items: center; gap: 24px; }
.spr-close h2 { font-size: clamp(40px, 5.6vw, 80px); letter-spacing: -0.03em; line-height: 0.98; margin: 0; text-wrap: balance; }
.spr-close p { margin: 0; color: var(--spr-ink-soft); font-size: 19px; max-width: 48ch; }

/* ---- footer ----
   White variant. On Home / Commerce / Apply it lands against the gradient and
   reads as its own block; on Creators and Brands the page above it is already
   white, so it carries a top hairline to separate rather than floating. */
/* On the pages that keep the gradient all the way down (home, commerce), the
   white footer used to meet it on a hard horizontal line. This band sits just
   above the footer and dissolves whatever is behind it into white. On the fade
   pages the area above is already white, so it costs nothing and shows
   nothing. */
.spr-footer { position: relative; }
.spr-footer::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 200px;
  background: linear-gradient(180deg, rgba(255,255,255,0), #fff);
  pointer-events: none;
}
.spr-footer { background: #fff; color: var(--sp-navy); border-top: 1px solid var(--sp-line); padding: 72px 32px 40px; }
.spr-footer-inner { max-width: 1180px; margin: 0 auto; display: flex; flex-direction: column; gap: 48px; }
.spr-footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 40px; }
.spr-footer-brand { display: flex; flex-direction: column; gap: 14px; align-items: flex-start; }
.spr-footer-brand img { height: 26px; width: auto; }
.spr-footer-brand p { margin: 0; color: var(--sp-slate); font-size: 14px; line-height: 1.6; }
.spr-footer-col { display: flex; flex-direction: column; gap: 10px; font-size: 14px; }
.spr-footer-col span { font-weight: 700; font-size: 12px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--sp-slate); }
.spr-footer-col a { color: var(--sp-navy); font-weight: 500; }
.spr-footer-col a:hover { color: var(--sp-blue); }
.spr-footer-bottom { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; border-top: 1px solid var(--sp-line); padding-top: 24px; font-size: 13px; color: var(--sp-slate); }

/* ---- the reel feed ----
   Four columns of 9:16 tiles, each crawling opposite its neighbours and offset
   by a different top margin so the grid never reads as rows. Every column's
   list is duplicated and translated by exactly half its height plus half a
   gap, which is what makes the loop seamless. Shared by Home and Apply. */
.spr-feed {
  padding: 24px 24px 0; overflow: hidden; height: 1280px;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 10%, #000 86%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 10%, #000 86%, transparent);
}
.spr-feed-grid { max-width: 1180px; margin: 0 auto; display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: 22px; align-items: start; }
.spr-feed-col { will-change: transform; }
.spr-feed-col:nth-child(1) { margin-top: 0; --spr-crawl: sprFeedUp 55s linear infinite; }
.spr-feed-col:nth-child(2) { margin-top: 64px; --spr-crawl: sprFeedDown 70s linear infinite; }
.spr-feed-col:nth-child(3) { margin-top: 28px; --spr-crawl: sprFeedUp 62s linear infinite; }
.spr-feed-col:nth-child(4) { margin-top: 88px; --spr-crawl: sprFeedDown 80s linear infinite; }
/* Held in a variable rather than set on `.spr-feed-col:nth-child(n) .spr-feed-track`
   directly: that selector out-specifies any later plain `.spr-feed-track` rule,
   so the reduced-motion override below would silently lose. */
.spr-feed-track { display: flex; flex-direction: column; gap: 22px; animation: var(--spr-crawl); }
@keyframes sprFeedUp { from { transform: translateY(0); } to { transform: translateY(calc(-50% - 11px)); } }
@keyframes sprFeedDown { from { transform: translateY(calc(-50% - 11px)); } to { transform: translateY(0); } }
.spr-tile {
  position: relative; width: 100%; aspect-ratio: 9/16; border-radius: 22px; overflow: hidden;
  background: var(--sp-navy); box-shadow: var(--shadow-md);
  transition: transform .35s var(--ease-out);
}
.spr-tile video, .spr-tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.spr-tile::after { content: ""; position: absolute; inset: 0; background: linear-gradient(transparent 55%, rgba(0,0,0,.45)); pointer-events: none; }
.spr-tile-views {
  position: absolute; bottom: 12px; left: 12px; z-index: 2; background: rgba(10,37,64,.5);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  color: #fff; font-size: 13px; font-weight: 600; padding: 5px 12px; border-radius: var(--radius-pill); white-space: nowrap;
}

/* ---- brand wall ----
   One row of customer names crawling sideways. Names rather than logo files:
   the artwork we have is each brand's own Snackpass avatar — app-style square
   icons, opaque JPEGs on white and coloured grounds — and this treatment sets
   the marks in white on the gradient, which needs clean transparent artwork
   that most of them aren't. Set in type, every brand reads at the same
   weight, and the twelve with no usable logo are in the wall too.
   Each brand is its own span so swapping one for an <img> later is a
   per-brand edit, not a rebuild.
   The list is duplicated and shifted by half the track plus half a gap — a
   plain -50% lands mid-gap and the row jumps.
   The crawl is held in a custom property set on the ROW, so `animation` is
   declared exactly once, at .spr-marks-track's own specificity. Declaring it
   as `.spr-marks-row-a .spr-marks-track` instead would out-specify the
   reduced-motion rule below and keep the row moving for anyone who asked the
   OS for less motion. */
.spr-marks { display: flex; flex-direction: column; width: 100%; }
.spr-marks-row {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}
.spr-marks-track {
  display: flex; width: max-content; align-items: center; gap: 52px;
  animation: var(--spr-marks-crawl);
}
.spr-marks-row-a { --spr-marks-crawl: sprMarksA 96s linear infinite; }
@keyframes sprMarksA { from { transform: translateX(0); } to { transform: translateX(calc(-50% - 26px)); } }
.spr-mark {
  flex: none; white-space: nowrap;
  font-family: var(--font-display); font-weight: 800; font-size: 22px;
  letter-spacing: -0.015em; color: var(--spr-ink); opacity: .72;
}
@media (max-width: 620px) {
  .spr-marks-track { gap: 34px; }
  @keyframes sprMarksA { from { transform: translateX(0); } to { transform: translateX(calc(-50% - 17px)); } }
  .spr-mark { font-size: 18px; }
}
@media (prefers-reduced-motion: reduce) {
  .spr-marks-track { animation: none; }
}

/* ---- airy pages (/brands-v2 and /creators-v2) ----
   The same components, dialled back and given room: type steps down about a
   notch and the space BETWEEN sections roughly doubles, so each one arrives on
   its own instead of running into the next. Scoped to a wrapper class because
   /home-v3 and /commerce were composed at the tighter rhythm and still read
   correctly there.
   The mobile values are repeated here rather than inherited: the base phone
   rules are single-class, so these two-class rules would out-specify them at
   every width and leave the phone with desktop padding. */
.spr-airy .spr-h1 { font-size: clamp(44px, 6.4vw, 92px); }
.spr-airy .spr-sub { font-size: 18.5px; }
.spr-airy .spr-hero { padding: 176px 32px 128px; }
.spr-airy .spr-statement { padding: 128px 32px 0; }
.spr-airy .spr-statement h2 { font-size: clamp(34px, 4.9vw, 78px); }
.spr-airy .spr-feature { padding: 104px 32px; }
.spr-airy .spr-feature-grid { gap: 76px; }
.spr-airy .spr-feature-copy h2 { font-size: clamp(27px, 3.1vw, 41px); }
.spr-airy .spr-feature-copy p { font-size: 16px; }
.spr-airy .spr-close { padding: 104px 24px 148px; }
.spr-airy .spr-close h2 { font-size: clamp(34px, 4.8vw, 68px); }
.spr-airy .spr-close p { font-size: 17.5px; }
@media (max-width: 900px) {
  .spr-airy .spr-hero { padding: 132px 22px 76px; }
  .spr-airy .spr-sub { font-size: 17px; }
  .spr-airy .spr-statement { padding: 64px 22px 0; }
  .spr-airy .spr-feature { padding: 68px 22px; }
  .spr-airy .spr-feature-grid { gap: 34px; }
  .spr-airy .spr-close { padding: 56px 18px 104px; }
}

/* ---- reveals ---- */
[data-reveal] { opacity: 0; transform: translateY(36px); transition: opacity .55s var(--ease-out), transform .55s var(--ease-out); }
[data-reveal].is-in { opacity: 1; transform: translateY(0); }
/* The mask each word rises out of. Padded on all four sides with the padding
   pulled back off by negative margins: layout is unchanged, but the glyphs get
   room instead of being sheared off. The top padding matters most — these
   headlines run at line-height 0.97–1.04, tighter than the font's own line
   box, so the content box is the one edge with no headroom of its own. */
.spr-wline { display: inline-block; overflow: hidden; vertical-align: bottom; padding: .14em .09em .08em; margin: -.14em -.09em -.08em; }
.spr-w { display: inline-block; transform: translateY(115%); transition: transform .55s var(--ease-out); }
.spr-w-em { /* accent word: colour only, see .spr-w-navy */ }
/* No italics anywhere in the redesign. <em> is kept in the markup where the
   copy means emphasis, but it is set upright — the accent colour and the
   travelling highlight carry emphasis instead of a slant. */
.spr h1 em, .spr h2 em, .spr h3 em, .spr blockquote em, .spr p em { font-style: normal; }
.spr-w-navy { color: var(--spr-accent); }
[data-reveal].is-in .spr-w { transform: translateY(0); }
/* A headline whose words rise out of their own masks shouldn't also fade and
   lift as a block — the two together read as a soft blur instead of type
   scrolling into place. The words carry the entrance; the block sits still. */
[data-reveal]:has(.spr-w) { opacity: 1; transform: none; }

/* ---- hover ----
   Only where there is a real pointer: on touch these fire on tap and leave a
   card stuck in its hover state. */
@media (hover: hover) and (pointer: fine) {
  .spr-lift:hover { transform: translateY(-4px); }
}

/* ---- responsive ----
   The handoff is a set of desktop artboards, so everything below is new work. */
@media (max-width: 1080px) {
  .spr-feature-grid { gap: 40px; }
}
@media (max-width: 900px) {
  .spr-nav { top: 10px; padding: 0 14px; }
  .spr-nav-inner { padding: 8px 8px 8px 16px; gap: 12px; }
  .spr-nav-links { gap: 0; font-size: 13px; }
  .spr-nav-links a { padding: 8px 9px; }
  .spr-hero { padding: 132px 22px 64px; }
  .spr-sub { font-size: 18px; }
  .spr-statement { padding: 24px 22px 0; }
  .spr-feature { padding: 44px 22px; }
  /* Stack the feature rows, and always put the copy above its mock — otherwise
     the alternating layout leaves some mocks orphaned above their heading. */
  .spr-feature-grid { grid-template-columns: 1fr; gap: 32px; }
  .spr-feature-copy { order: -1; }
  .spr-close { padding: 16px 18px 88px; }
  .spr-footer { padding: 56px 22px 32px; }
  .spr-footer-grid { grid-template-columns: 1fr 1fr; gap: 32px; }
  .spr-footer-brand { grid-column: 1 / -1; }
}
@media (max-width: 780px) {
  /* Four columns of 9:16 on a phone is a strip of thumbnails — two reads as a
     feed, which is the point of the section. */
  .spr-feed { height: 760px; padding: 16px 16px 0; }
  .spr-feed-grid { grid-template-columns: repeat(2, minmax(0,1fr)); gap: 14px; }
  .spr-feed-track { gap: 14px; }
  @keyframes sprFeedUp { from { transform: translateY(0); } to { transform: translateY(calc(-50% - 7px)); } }
  @keyframes sprFeedDown { from { transform: translateY(calc(-50% - 7px)); } to { transform: translateY(0); } }
  .spr-feed-col:nth-child(3), .spr-feed-col:nth-child(4) { display: none; }
}
@media (max-width: 620px) {
  .spr-nav-logo img { height: 20px; }
  /* btn-lg is sized for a wide hero. Stacked edge to edge on a phone the pair
     reads oversized, so they step down and sit at their content width rather
     than stretching — still comfortably over the 44px tap target. */
  .spr-cta-row { width: 100%; flex-direction: column; align-items: center; gap: 10px; }
  .spr-cta-row .btn { justify-content: center; font-size: 15.5px; padding: 13px 26px; }
}
/* Reduced motion means gentler, not none: nothing travels and the light holds
   still, but content still fades in, because a crossfade aids comprehension
   and causes no vestibular trouble. */
@media (prefers-reduced-motion: reduce) {
  .spr-bg span { animation: none; }
  .spr-feed-track { animation: none; }
  /* A still feed still needs to be a feed, not a six-thousand-pixel poster
     wall: shorten it and show three tiles a column. The staggered column
     offsets and the fade mask stay — both are static layout, not motion. */
  .spr-feed { height: 900px; }
  .spr-tile:nth-child(n+4) { display: none; }
  [data-reveal] { transform: none; transition: opacity .45s ease; }
  [data-reveal].is-in { transform: none; }
  .spr-w { transform: none; transition: none; }
}

/* ---- Split hero: copy on the left, two crawling reel columns on the right.
   Shared by Creators and Brands; page-specific type sizing stays on the page.
   ---- */
.spr-hsplit { max-width: 1180px; margin: 0 auto; display: grid; grid-template-columns: 1.12fr .88fr; gap: 48px; align-items: center; }
.spr-hsplit-copy { display: flex; flex-direction: column; gap: 30px; align-items: flex-start; text-align: left; }

/* Two columns of reels beside the copy, crawling against each other. Each
   column's list is duplicated and shifted by half its height plus half a gap —
   a plain -50% lands mid-gap and the tiles visibly jump. */
/* min-width: 0 so the media column can't be stretched by its own contents.
   The mobile reel row is width: max-content, and a grid item's default
   min-width: auto let that widen the whole column to the length of the row. */
.spr-hsplit-media { position: relative; min-width: 0; }
.spr-reels {
  display: grid; grid-template-columns: 1fr 1fr; gap: 16px; height: 604px; overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 13%, #000 87%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 13%, #000 87%, transparent);
}
/* The crawl is held in a variable rather than set on
   `.spr-reelcol-up .spr-reeltrack` directly: that selector out-specifies any
   later plain `.spr-reeltrack` rule, so the reduced-motion override below
   would silently lose and the columns would keep moving. */
.spr-reeltrack { display: flex; flex-direction: column; gap: 16px; animation: var(--spr-crawl); }
.spr-reelcol-up { --spr-crawl: sprReelUp 46s linear infinite; }
.spr-reelcol-down { --spr-crawl: sprReelDown 52s linear infinite; margin-top: -58px; }
@keyframes sprReelUp { from { transform: translateY(0); } to { transform: translateY(calc(-50% - 8px)); } }
@keyframes sprReelDown { from { transform: translateY(calc(-50% - 8px)); } to { transform: translateY(0); } }
.spr-reels .spr-tile { border-radius: 20px; }

/* The collab invite, landing over the reels. It rides the shared reveal, so
   its entrance is a slide-and-fade on first sight and a plain fade for anyone
   who asked for less motion. */
.spr-push {
  position: absolute; left: -34px; top: 52%; z-index: 3; width: min(400px, 92%);
  display: flex; align-items: center; gap: 11px;
  background: rgba(255,255,255,.94);
  backdrop-filter: blur(20px) saturate(1.4); -webkit-backdrop-filter: blur(20px) saturate(1.4);
  border-radius: 18px; padding: 12px 14px;
  box-shadow: 0 18px 44px rgba(10,37,64,.3);
  color: var(--sp-navy);
}
/* The source icon is 122x120, not square. Cropping the odd 2px with
   object-fit keeps the tile square without stretching the mark. */
.spr-push-app { border-radius: 9px; flex: none; object-fit: cover; }
.spr-push-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.spr-push-meta { display: flex; justify-content: space-between; gap: 10px; font-size: 11px; font-weight: 600; letter-spacing: .06em; color: var(--sp-slate); text-transform: uppercase; }
.spr-push-title { font-size: 14.5px; font-weight: 700; line-height: 1.3; }
.spr-push-sub { font-size: 13.5px; color: var(--sp-slate); line-height: 1.35; }

@media (max-width: 980px) {
  .spr-hsplit { grid-template-columns: 1fr; gap: 40px; }
  .spr-reels { height: 420px; }
  .spr-reelcol-down { margin-top: -40px; }
  /* Full width of the media column here; at 92% the handle in the title
     tipped onto a second line. */
  .spr-push { left: 0; top: auto; bottom: -18px; width: 100%; }
}
/* One row on a phone. Two crawling columns eat most of the screen and leave
   the tiles too small to read, so the down column is dropped and the up
   column's list — already duplicated for a seamless loop — runs sideways
   instead. --spr-crawl is set on the track itself here: a declaration on the
   element beats the value it would otherwise inherit from the column. */
/* The clamp floor is a desktop floor. On a phone the statement has the whole
   width and should carry the screen, so it scales with the viewport instead
   of sitting at a fixed minimum. */
@media (max-width: 620px) {
  .spr-statement h2 { font-size: clamp(38px, 11.5vw, 56px); }
  .spr-airy .spr-statement h2 { font-size: clamp(36px, 10.8vw, 52px); }
}
@media (max-width: 620px) {
  .spr-reels {
    display: block; height: auto; gap: 0;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  }
  .spr-reelcol-down { display: none; }
  .spr-reelcol-up { overflow: hidden; }
  .spr-reeltrack { flex-direction: row; width: max-content; gap: 10px; --spr-crawl: sprReelRow 30s linear infinite; }
  .spr-reels .spr-tile { width: 126px; flex: none; border-radius: 16px; }
  /* Sized down to sit over a single row without covering it. */
  .spr-push { gap: 9px; padding: 9px 11px; border-radius: 14px; bottom: -14px; }
  .spr-push-app { width: 30px; height: 30px; }
  .spr-push-meta { font-size: 10px; }
  .spr-push-title { font-size: 13px; }
  .spr-push-sub { font-size: 12px; }
}
@keyframes sprReelRow { from { transform: translateX(0); } to { transform: translateX(calc(-50% - 5px)); } }
@media (prefers-reduced-motion: reduce) {
  .spr-reeltrack { animation: none; }
}
