/* =============================================================
   XPixel - section composition
   Page-specific layout. Reusable widgets live in components.css.
   Desktop breakpoint is 64em; tablet 48em; large desktop 90em.
   ============================================================= */

/* ---- Skip link ------------------------------------------------------- */
.skip-link {
  position: absolute;
  top: -100%;
  left: var(--space-200);
  z-index: 200;
  background: var(--accent);
  color: var(--accent-ink);
  padding: var(--space-75) var(--space-200);
  border-radius: var(--radius-sm);
  font-weight: var(--weight-semibold);
}
.skip-link:focus { top: var(--space-200); }

.nav-logo { font-weight: var(--weight-semibold); font-size: var(--fs-body); color: var(--fg); display: inline-flex; align-items: center; gap: var(--space-75); }

/* ---- Hero - BYQ layout: mono eyebrow, 96px headline on an 80px line,
   20px lead at 64% ink, one lime CTA. Plain page tone behind it. ---- */
.hero {
  position: relative;
  padding-block: calc(var(--nav-inset) + var(--nav-pill) + var(--space-800)) var(--space-800);
  text-align: center;
}
.hero-inner { max-width: 72rem; margin-inline: auto; }
.hero-copy { display: grid; justify-items: center; gap: var(--space-400); }
/* BYQ's "WEBFLOW AWARDS FINALIST" eyebrow: Geist Mono 12px, 0.75px tracked, flanked by marks */
.hero-audience {
  display: inline-flex; align-items: center; gap: var(--space-100);
  font-family: var(--font-mono); font-size: var(--fs-label); font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--fg-2); text-wrap: balance;
}
.hero-audience::before, .hero-audience::after { content: "✦"; flex: none; font-size: 0.875rem; color: var(--faint); letter-spacing: 0; }
.hero h1 {
  font-size: var(--fs-display);
  line-height: var(--lh-display);
  letter-spacing: var(--tracking-display);
  font-weight: var(--weight-medium);
  display: grid;
  gap: 0;
  width: 100%;
  margin-block: var(--space-100) 0;
}
.hero-line { display: block; }
/* The rotating phrase is masked; its own taller line keeps descenders clear. */
.hero .rotator { margin-block-start: 0; height: 1.12em; line-height: 1.12; }
.hero .lead { max-width: 40rem; margin-inline: auto; color: var(--muted); font-size: var(--fs-lead); line-height: 1.4; }
.hero-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-100); }
@media (max-width: 47.99em) {
  .hero-audience::before, .hero-audience::after { display: none; }
}
/* Phones: the headline runs at 48px+, wider than "Connected commerce" can
   sit on one line. Every rotating phrase is two words, so each one stacks
   word-over-word (min-content) in a fixed two-line mask: the box never
   changes height between phrases, so nothing below it jumps. The static
   lines wrap naturally and get a slightly looser leading so descenders
   ("acquisition") clear the line below. */
@media (max-width: 47.99em) {
  .hero h1 { line-height: 0.94; }
  .hero .rotator { height: 2.04em; line-height: 0.98; justify-content: stretch; padding-block-end: 0.06em; }
  .hero .rotator-item { white-space: normal; width: min-content; justify-self: center; align-self: center; text-align: center; }
}
/* Very small phones (≤ 383px, e.g. 320px SE-class): "acquisition" is the
   widest word and needs ~5.6em; scale with the viewport so it always fits. */
@media (max-width: 23.99em) {
  .hero h1 { font-size: min(3.5rem, 15.8vw); }
}
@media (max-width: 39.99em) {
  /* One matched, full-width pair of actions - easier to hit, and the two
     buttons read as a deliberate set rather than two different widths. */
  .hero-actions { flex-direction: column; align-items: stretch; width: 100%; max-width: 22rem; }
  .hero-actions .btn { width: 100%; }
}
@media (min-width: 64em) {
  .hero { padding-block: calc(var(--nav-inset) + var(--nav-pill) + 9rem) var(--space-900); }
}

/* ---- Showcase wall - see .mosaic in components.css -------------------------
   One caption for the whole wall, set on the dissolving edge and aligned
   to the content grid, replaces a "Placeholder" chip on every tile. */
.showcase { position: relative; }
.showcase-caption {
  position: absolute;
  left: 0; right: 0; bottom: var(--space-300);
  z-index: 4;
  pointer-events: none;
}
.showcase-caption p {
  display: inline-flex; align-items: center; gap: var(--space-75);
  font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: var(--tracking-mono);
  color: var(--muted);
}
.showcase-caption p::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--alert); flex: none; }


/* ---- Capabilities - BYQ "One platform" row: three image cards, then a
   hairline-topped strip with a line of copy and the lime CTA. ---------- */
.cap-cards { row-gap: var(--space-600); }
/* Phones: the three cards become a swipe carousel - same edge-bleed track
   as the rails (full viewport width, first card on the content edge) with
   the dots below. Desktop keeps the three-up grid untouched. */
@media (max-width: 47.99em) {
  .cap-cards {
    display: flex; gap: var(--space-300);
    overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain;
    margin-inline: calc(-1 * var(--container-pad));
    padding-inline: var(--container-pad); scroll-padding-inline: var(--container-pad);
    padding-block: var(--space-100);
    scrollbar-width: none; -webkit-tap-highlight-color: transparent;
  }
  .cap-cards::-webkit-scrollbar { display: none; }
  .cap-cards.is-dragging, .cap-cards.is-driving { scroll-snap-type: none; scroll-behavior: auto; }
  .cap-cards > .media-card { flex: 0 0 min(86vw, 22rem); scroll-snap-align: start; }
  .cap-cards:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
  .cap-section .rail-dots { padding-block-start: var(--space-200); }
}
.cap-foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-300);
  margin-block-start: var(--space-800); padding-block-start: var(--space-500);
  border-block-start: 1px solid var(--line);
}
.cap-foot p { font-size: var(--fs-lead); line-height: var(--lh-snug); color: var(--fg-2); display: grid; }
.cap-foot p span { color: var(--muted); font-size: var(--fs-body); }

/* ---- Tagline reveal ------------------------------------------------------------
   The tagline opens the warm band it shares with the toolkit: one
   statement, then the platforms it rests on. No bottom padding of its
   own, so the two read as one movement rather than a strip and a block. */
.tagline-section { padding-block: var(--section-y-loose) var(--space-400); }
.tagline-section .tagline { max-width: 20ch; }
.reveal-word { transition: color var(--duration-reveal) var(--ease); }

/* ---- Toolkit - the platforms already in play -----------------------------------
   Platform marks around a crossfading headline. On desktop the stage pins and
   main.js draws the marks in from a loose scatter onto one shared orbit as you
   scroll ("12+ platforms, one connected system"), then turns the orbit slowly;
   a hairline ring fades in beneath to tie them together. The headline swaps
   line by line over the same scroll. Phones and tablets get a flat wrapped
   grid; reduced motion gets the finished orbit, static. */
.toolkit { position: relative; }
.toolkit-section { overflow: clip; }   /* marks never widen the page or spill over the neighbouring sections; clip (not hidden) keeps sticky working */
.toolkit-orbit { display: none; }
.toolkit-copy { position: relative; z-index: 300; display: grid; gap: var(--space-200); justify-items: center; text-align: center; max-width: 50rem; margin-inline: auto; }   /* wide enough for the longest line to stay on two lines */
.toolkit-stack { position: relative; display: grid; }
.toolkit-line {
  grid-area: 1 / 1;
  text-wrap: balance;
  font-size: var(--fs-tagline);
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-hero);
  font-weight: var(--weight-medium);
  color: var(--fg);
  opacity: 0;
  transform: translateY(0.35em);
  filter: blur(6px);
  transition: opacity 350ms var(--ease), transform 350ms var(--ease), filter 350ms var(--ease);
}
.toolkit-line.is-on { opacity: 1; transform: none; filter: none; }
/* a line that has been passed exits upward, so the swap reads in the scroll direction */
.toolkit-line.is-on ~ .toolkit-line { transform: translateY(0.35em); }
.toolkit-line:has(~ .toolkit-line.is-on) { transform: translateY(-0.35em); }
.toolkit-icon { --size: 84px; }
.toolkit-icon-badge {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: var(--shadow-1);
  color: var(--fg);
}
.toolkit-icon-badge svg { width: 42%; height: 42%; }
/* One brand colour per mark - the one deliberate exception to the page's
   single neutral palette, since these badges represent other companies'
   own identities rather than XPixel's UI. Values are literal, not design
   tokens: they belong to this component only, not the shared palette. */
.toolkit-icon-badge--linkedin { background: #0A66C2; color: #FFFFFF; }
.toolkit-icon-badge--instagram { background: radial-gradient(circle at 30% 107%, #FDF497 0%, #FDF497 5%, #FD5949 45%, #D6249F 60%, #285AEB 90%); color: #FFFFFF; }
.toolkit-icon-badge--instagram svg { width: 40%; height: 40%; }
.toolkit-icon-badge--tiktok { background: #000000; color: #FFFFFF; }
.toolkit-icon-badge--tiktok svg { width: 40%; height: 40%; }
.toolkit-icon-badge--stripe { background: #635BFF; color: #FFFFFF; }
.toolkit-icon-badge--stripe svg { width: 38%; height: 38%; }
.toolkit-icon-badge--pinterest { background: #BD081C; color: #FFFFFF; }
.toolkit-icon-badge--pinterest svg { width: 44%; height: 44%; }
.toolkit-icon-badge--klaviyo { background: #FF4B32; color: #FFFFFF; }
.toolkit-icon-badge--klaviyo svg { width: 40%; height: 40%; }
.toolkit-icon-badge--mailchimp { background: #FFE01B; color: #241C15; }
.toolkit-icon-badge--mailchimp svg { width: 48%; height: 48%; }
.toolkit-icon-badge--meta { background: #0866FF; color: #FFFFFF; }
.toolkit-icon-badge--meta svg { width: 46%; height: 46%; }
.toolkit-icon-badge--googleads { background: #4285F4; color: #FFFFFF; }
.toolkit-icon-badge--webflow { background: #146EF5; color: #FFFFFF; }
.toolkit-icon-badge--webflow svg { width: 44%; height: 44%; }
.toolkit-icon-badge--shopify { background: #95BF47; color: #FFFFFF; }
.toolkit-icon-badge--facebook { background: #1877F2; color: #FFFFFF; }
.toolkit-icon-badge--facebook svg { width: 38%; height: 38%; }
.js .toolkit-icon-badge {
  opacity: 0;
  transform: scale(0.55);
  transition: opacity var(--duration-slow) var(--ease) calc(var(--i, 0) * 45ms),
              transform var(--duration-slow) var(--ease-heavy) calc(var(--i, 0) * 45ms),
              box-shadow var(--duration-fast) var(--ease);
}
.js .toolkit-icons.is-visible .toolkit-icon-badge { opacity: 1; transform: scale(1); }
.js .toolkit-icons.is-settled .toolkit-icon-badge { transition-delay: 0s; }
.js .toolkit-icons.is-visible .toolkit-icon-badge { animation: toolkit-float 7s var(--ease) infinite; animation-delay: calc(var(--i, 0) * -0.6s); }
@keyframes toolkit-float { 0%, 100% { translate: 0 0; } 50% { translate: 0 -10px; } }
@keyframes toolkit-float-sm { 0%, 100% { translate: 0 3px; } 50% { translate: 0 -3px; } }

@media (max-width: 63.99em) {
  .toolkit { display: flex; flex-direction: column; align-items: center; gap: var(--space-500); padding-block: var(--space-500) var(--section-y-tight); }
  .toolkit-icons { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-200); max-width: 26rem; }
  .toolkit-icon { width: 56px; height: 56px; }
}
@media (max-width: 26.24em) {
  /* Phones under ~420px: shrink the circles and the gap between them
     together, rather than letting the row wrap raggedly or overflow. */
  .toolkit-icons { gap: var(--space-100); max-width: 20rem; }
  .toolkit-icon { width: 44px; height: 44px; }
}
/* Desktop: BYQ pinned stage. The section is tall; the stage sticks to the
   viewport while main.js turns scroll progress into the headline swap and
   the outward, diagonal drift of the marks (--ox/--oy). overflow-x: clip on
   the section (not hidden) keeps sticky working. */
@media (min-width: 64em) {
  .toolkit-section { height: 220vh; padding-block: 0; }
  .toolkit { position: sticky; top: 0; height: 100vh; min-height: 36rem; display: grid; place-items: center; }
  .toolkit-icons { position: absolute; inset: 0; pointer-events: none; }
  /* The shared orbit: a hairline ellipse sized and faded in by main.js. */
  .toolkit-orbit {
    display: block;
    position: absolute; left: 50%; top: 50%;
    border-radius: 50%;
    border: 1px solid var(--line-strong);
    opacity: 0;
    transform: translate(-50%, -50%) scale(var(--orbit-s, 1.08));
    pointer-events: none;
  }
  /* A gentle idle bob so the stage is never frozen between scrolls. It
     animates `translate`, independent of the wrapper's scroll-driven
     transform and the badge's own scale. */
  .js .toolkit-icons.is-visible .toolkit-icon-badge { animation: toolkit-float-sm 6s ease-in-out infinite; animation-delay: calc(var(--i, 0) * -0.5s); }
  .toolkit-icon {
    position: absolute;
    left: 50%;
    top: 50%;
    width: var(--size);
    height: var(--size);
    pointer-events: auto;
    transform: translate(-50%, -50%) translate3d(var(--ox, 0px), var(--oy, 0px), 0);
    will-change: transform;
  }
  .toolkit-icon:hover .toolkit-icon-badge { box-shadow: var(--shadow-2); transform: scale(1.08); }
}
@media (min-width: 64em) and (prefers-reduced-motion: reduce) {
  .toolkit-section { height: auto; padding-block: var(--section-y); }
  .toolkit { position: relative; height: auto; min-height: 40rem; }
}

/* ---- Edge-to-edge services rail ------------------------------------------------ */
.rail-section { overflow: hidden; }
.rail-head { display: flex; align-items: end; justify-content: space-between; gap: var(--space-400); flex-wrap: wrap; margin-block-end: var(--space-400); }
.rail-head h2 { margin-block-start: var(--space-200); max-width: 18ch; }
.rail-head .sec-sub { margin-block-start: var(--space-200); }
.rail-controls {
  display: flex; align-items: center; gap: var(--space-200);
  width: 100%;
}
/* Phones: no arrows or counter - the card peeking in at the edge plus the
   dots below the track say "swipe", and a thumb needs no buttons. From
   tablet up the compact counter + arrows sit beside the heading. */
.rail-progress { flex: none; width: 96px; }
.rail-controls .icon-btn { flex: none; }
@media (max-width: 47.99em) {
  .rail-controls { display: none; }
  .rail-head { margin-block-end: var(--space-300); }
}
.rail-dots { display: none; }
@media (max-width: 47.99em) {
  .rail-dots { display: flex; justify-content: center; flex-wrap: wrap; padding-block-start: var(--space-100); padding-inline: var(--container-pad); }
}
.rail-dot {
  display: inline-grid; place-items: center;
  width: 28px; height: 28px; padding: 0; border: 0; border-radius: 50%;
  background: transparent; cursor: pointer; touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
.rail-dot::before {
  content: ""; display: block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--line-strong);
  transition: width var(--duration) var(--ease), background-color var(--duration) var(--ease);
}
.rail-dot.is-active::before { width: 24px; border-radius: var(--radius-full); background: var(--fg); }
.rail-dot:focus-visible { outline-offset: 0; border-radius: 50%; }
.rail-count { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--muted); min-width: 4.5ch; }
.rail-controls .icon-btn { border-color: transparent; }
.rail-controls .icon-btn:hover { border-color: var(--line-strong); background: var(--surface-2); }
.rail {
  position: relative;
}
.rail-track {
  display: flex;
  gap: var(--space-300);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  /* The track runs the full viewport width, but its first card must sit
     exactly where .container's content starts (the same maths as the
     container: centred, capped at --container, with a gutter). The same
     inset on the right means the last card ends on the container's right
     edge, so the track can never scroll into empty space. Percentages
     here resolve against the track's own (full-bleed) width. */
  --rail-inset: max(var(--container-pad), calc((100% - var(--container)) / 2 + var(--container-pad)));
  padding-inline: var(--rail-inset);
  padding-block: var(--space-200);
  scroll-padding-inline: var(--rail-inset);
  scrollbar-width: none;
}
.rail-track::-webkit-scrollbar { display: none; }
.rail-track { -webkit-tap-highlight-color: transparent; }
/* Snap is switched off while the script is moving the track (.is-driving)
   or the mouse is dragging it, and comes back the moment either ends. */
.rail-track.is-dragging, .rail-track.is-driving { scroll-snap-type: none; scroll-behavior: auto; }
.rail-track.is-dragging { cursor: grabbing; user-select: none; -webkit-user-select: none; }
.rail-track.is-dragging * { pointer-events: none; }
.rail-track img { -webkit-user-drag: none; user-select: none; -webkit-user-select: none; }
.rail-track [aria-roledescription="slide"]:not(.is-current) { cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .rail-track { cursor: grab; } }
.rail-track:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; border-radius: var(--radius-lg); }
.svc {
  flex: 0 0 min(86vw, 22rem);
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  border-radius: var(--radius-card);
  background: var(--glass-fill);
  backdrop-filter: blur(var(--glass-blur));
  border: 1px solid var(--glass-border);
  box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-card);
  overflow: hidden;
  position: relative;
  transition: border-color var(--duration) var(--ease), box-shadow var(--duration) var(--ease);
}
@supports not (backdrop-filter: blur(1px)) {
  .svc { background: var(--surface); border-color: var(--line); box-shadow: var(--shadow-card); }
}
.svc.is-current { --settle: 1; }
.svc:hover, .svc:focus-within { --lift: -2px; border-color: var(--line-strong); box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-card-hover); }
.svc-visual { position: relative; flex: none; aspect-ratio: 4 / 3; max-height: 22rem; background: var(--surface-2); border-block-end: 1px solid var(--line); overflow: hidden; transition: opacity var(--duration-slow) var(--ease); }
.svc:not(.is-current):not(:hover):not(:focus-within) .svc-visual { opacity: 0.72; }
.svc-visual > * { height: 100%; transition: transform var(--duration-media) var(--ease); }
.svc:hover .svc-visual > * { transform: scale(1.04); }
.svc-visual--photo img { width: 100%; height: 100%; object-fit: cover; display: block; filter: var(--photo-grade); }
.svc-body { flex: 1; padding: var(--space-300); display: flex; flex-direction: column; gap: var(--space-75); min-height: 9.5rem; }
.svc-body h3 { font-size: var(--fs-h3); }
.svc-body p { color: var(--muted); font-size: var(--fs-sm); line-height: var(--lh-snug); max-width: 30ch; }
.svc-body .btn { justify-self: start; margin-block-start: auto; }
.svc-more {
  position: absolute; inset: 0; z-index: 2;
  background: var(--surface);
  padding: var(--space-300);
  display: flex; flex-direction: column; gap: var(--space-200);
  transform: translateY(100%);
  visibility: hidden;
  transition: transform var(--duration-slow) var(--ease);
}
.svc.is-open .svc-more { transform: none; visibility: visible; transition: transform var(--duration-slow) var(--ease-heavy); }
.svc-more-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-200); }
.svc-more h4 { font-size: var(--fs-h3); }
.svc-more ul { display: grid; gap: var(--space-100); }
.svc-more li { position: relative; padding-inline-start: var(--space-300); color: var(--fg-2); font-size: var(--fs-sm); }
.svc-more li::before { content: ""; position: absolute; left: 0; top: 0.55em; width: 14px; height: 2px; background: var(--accent); }
.svc-more .svc-foot { margin-block-start: auto; font-size: var(--fs-xs); color: var(--muted); font-family: var(--font-mono); }

/* Pause non-essential motion inside the rail on hover or focus */
.rail:hover .svc *, .rail:focus-within .svc * { animation-play-state: paused; }

/* ---- Success stories - a second rail, text-only cards ------------------ */
.story {
  flex: 0 0 min(86vw, 22rem);
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  gap: var(--space-200);
  padding: var(--space-300);
  border-radius: var(--radius-card);
  background: var(--glass-fill);
  backdrop-filter: blur(var(--glass-blur));
  border: 1px solid var(--glass-border);
  box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-card);
  transition: border-color var(--duration) var(--ease), box-shadow var(--duration) var(--ease);
}
@supports not (backdrop-filter: blur(1px)) {
  .story { background: var(--surface); border-color: var(--line); box-shadow: var(--shadow-card); }
}
/* The selected story is lifted (solid surface, deeper shadow); the others
   sit flat. Text stays at full contrast on every card - on a wide screen
   all five are readable at once, and touch has no hover to un-dim them. */
.story { transition: border-color var(--duration) var(--ease), box-shadow var(--duration) var(--ease), background-color var(--duration) var(--ease), transform var(--duration) var(--ease); }
.story:not(.is-current) { background: color-mix(in srgb, var(--glass-fill) 45%, transparent); box-shadow: none; }
.story.is-current { background: var(--surface); border-color: var(--line-strong); box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-2); transform: translateY(-2px); }
.story:hover, .story:focus-within { border-color: var(--line-strong); box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-card-hover); }
.story h3 { font-size: var(--fs-h3); line-height: var(--lh-heading); margin-block-start: var(--space-50); }
.story-block { display: grid; gap: 0.3em; }
.story-block p { margin: 0; font-size: var(--fs-sm); line-height: var(--lh-snug); color: var(--fg-2); }


/* ---- Engagement model ------------------------------------------------------------- */
.eng { display: grid; grid-template-columns: 1fr; gap: var(--space-300); margin-block-start: var(--space-500); align-items: stretch; }
.eng-stage { display: flex; flex-direction: column; gap: var(--space-200); padding: var(--space-400); background: var(--glass-fill); backdrop-filter: blur(var(--glass-blur)); border: 1px solid var(--glass-border); border-radius: var(--radius-card); box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-card); position: relative; }
.eng-stage--core { border-color: var(--accent-deep); box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-card), 0 0 0 3px var(--accent-soft); }
@supports not (backdrop-filter: blur(1px)) {
  .eng-stage { background: var(--surface); border-color: var(--line); box-shadow: var(--shadow-card); }
}
.eng-step { display: flex; align-items: center; gap: var(--space-100); }
.eng-num { width: var(--space-400); height: var(--space-400); border-radius: 50%; display: grid; place-items: center; font-family: var(--font-mono); font-size: var(--fs-sm); background: var(--fg); color: var(--bg); }
.eng-stage h3 { font-size: var(--fs-h3); }
.eng-stage > p { color: var(--muted); line-height: var(--lh-snug); max-width: 34ch; }
.eng-price { display: flex; align-items: baseline; gap: var(--space-100); margin-block-start: var(--space-100); }
.eng-price strong { font-family: var(--font-body); font-weight: var(--weight-medium); font-size: var(--fs-h3); color: var(--fg); }
.eng-price span { font-size: var(--fs-sm); color: var(--muted); }
.eng-stage .acc { margin-block-start: auto; border-block-start-color: var(--line); }
.eng-stage .acc-item { border-block-end: none; }
.eng-stage .acc-item summary { padding-block: var(--space-200) var(--space-100); font-size: var(--fs-sm); }
.eng-stage .acc-body > * { font-size: var(--fs-sm); padding-block-end: var(--space-100); }

/* Engagement connector - a genuine flow indicator, not a stray arrow.
   A traveling pulse (same technique as the journey diagram) plus an
   explicit legend of the five stages beneath explain why "Build" and
   "Manage" are one system rather than two unrelated offers. */
.eng-link { display: flex; align-items: center; justify-content: center; gap: var(--space-75); }
.eng-flow { overflow: visible; }
.eng-flow-base { fill: none; stroke: var(--line-strong); stroke-width: 2; vector-effect: non-scaling-stroke; }
.eng-flow-pulse { fill: none; stroke: var(--accent-deep); stroke-width: 3; stroke-linecap: round; vector-effect: non-scaling-stroke; stroke-dasharray: 18 100; stroke-dashoffset: 118; opacity: 0; }
.eng.is-visible .eng-flow-pulse { animation: eng-flow-run 3.6s var(--ease) infinite; animation-delay: 0.5s; }
@keyframes eng-flow-run { 0%, 6% { opacity: 0; stroke-dashoffset: 118; } 12% { opacity: 1; } 46% { opacity: 1; stroke-dashoffset: -18; } 52%, 100% { opacity: 0; stroke-dashoffset: -18; } }
.eng-flow--v { display: none; }
.eng-flow--h { flex: 1; height: 2px; max-width: 64px; }
.eng-flow-caption { margin-block-start: var(--space-400); text-align: center; font-size: var(--fs-sm); color: var(--muted); }
.eng-flow-steps { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-75); margin-block-start: var(--space-100); }
.eng-flow-steps .chip { font-family: var(--font-mono); font-weight: var(--weight-regular); }

/* Risk reversal, visible - not buried in the accordion below. The one
   claim most likely to overcome price hesitation gets a line of its own,
   not a click to reveal. */
.eng-guarantee {
  display: flex; align-items: flex-start; gap: var(--space-200);
  margin-block-start: var(--space-400);
  padding: var(--space-300);
  border-radius: var(--radius-card);
  background: var(--accent-soft);
}
.eng-guarantee .ico { flex: none; width: 20px; height: 20px; margin-block-start: 0.15em; color: var(--accent-text); }
.eng-guarantee p { font-size: var(--fs-sm); line-height: var(--lh-snug); color: var(--fg-2); }
.eng-guarantee p strong { color: var(--fg); font-weight: var(--weight-semibold); }


@media (min-width: 64em) {
  .eng { grid-template-columns: 1fr auto 1fr; gap: var(--space-300); }
  .eng-link { flex-direction: column; width: 96px; }
  .eng-flow--h { display: none; }
  .eng-flow--v { display: block; width: 2px; height: 48px; }
}
@media (max-width: 63.99em) {
  .eng-link { padding-block: var(--space-100); }
}

/* ---- Process timeline -------------------------------------------------------------- */
.proc { position: relative; margin-block-start: var(--space-600); --p: 0; }
.proc-flow { position: relative; }   /* the line is positioned against the steps only, so it ends at the last step instead of running on through the fit panel */
.proc-line { position: absolute; left: 0; right: 0; top: 7px; height: 2px; background: var(--line-strong); }
.proc-line i { position: absolute; inset: 0; background: var(--accent); transform-origin: left; transform: scaleX(var(--p)); }
.proc-steps { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-300); }
.proc-step { position: relative; padding-block-start: var(--space-400); display: grid; gap: var(--space-100); align-content: start; }
.proc-step::before { content: ""; position: absolute; top: 0; left: 0; width: 16px; height: 16px; border-radius: 50%; background: var(--bg); border: 2px solid var(--line-strong); transition: border-color var(--duration) var(--ease), background-color var(--duration) var(--ease), box-shadow var(--duration) var(--ease); }
.proc-step.is-on::before { border-color: var(--accent); background: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.proc-step h3 { font-size: var(--fs-h3); }
.proc-step p { color: var(--muted); font-size: var(--fs-sm); line-height: var(--lh-snug); max-width: 26ch; }
/* Commercial terms under each step: mono metadata, not a pill, so the
   only pills in this section are none and the timeline stays quiet. */
.proc-step .proc-terms { justify-self: start; margin-block-start: var(--space-50); color: var(--fg-2); }
.proc-step .proc-terms--free { color: var(--accent-text); }

/* Qualification panel - a recessed outer tray holding a glass inner
   card (the same nested-shell logic as a machined hardware enclosure:
   a visible seam, then a distinct surface inside it), so the panel
   reads as one deliberate object instead of a bordered rectangle. */
.proc-fit {
  margin-block-start: var(--space-600);   /* 48px on phones, 80px from tablet up: the panel is a new idea, not a footnote to the steps */
}
@media (min-width: 48em) {
  .proc-fit { margin-block-start: var(--space-800); }
}   /* no outer frame: the card inside is the only surface */
.proc-fit-inner {
  /* Layout only: no surface, stroke or padding of its own, so the heading
     and the two columns sit directly on the page and line up with the
     steps above. */
  display: grid;
  gap: var(--space-300);
}
.proc-fit-head { display: grid; gap: var(--space-100); }
.proc-fit-head .label { font-size: var(--fs-sm); }
.proc-fit-head p { color: var(--muted); font-size: var(--fs-body); line-height: var(--lh-snug); max-width: 48ch; }

/* Two weighted surfaces instead of a checklist plus a disconnected
   warning sentence - "who this is for" and "who it isn't" each get
   their own tinted panel, so a visitor self-qualifies either way in
   one glance instead of reading a list, then hunting for the
   exclusion in smaller print underneath. Lime for the fit the system
   is built for; amber (the existing "gap/disconnected" signal) for
   the one it isn't - no new colours introduced. Hovering a line item
   nudges it with the same spring used for the button-in-button hover
   elsewhere, so the panel doesn't feel inert. */
.proc-fit-cols { display: grid; gap: var(--space-200); }
.proc-fit-col {
  display: grid;
  align-content: start;
  gap: var(--space-200);
  padding: var(--space-300);
  border-radius: calc(var(--radius-card) - var(--space-75));
}
.proc-fit-col--yes { background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent-deep), 0 8px 24px -18px var(--accent-glow); }
.proc-fit-col--no { background: var(--surface); box-shadow: inset 0 0 0 1px var(--line); }
.proc-fit-col-label { display: inline-flex; align-items: center; gap: var(--space-100); font-size: var(--fs-body); font-weight: var(--weight-semibold); }
.proc-fit-col--yes .proc-fit-col-label { color: var(--accent-text); }
.proc-fit-col--no .proc-fit-col-label { color: var(--alert); }
.proc-fit-col ul { display: grid; gap: var(--space-50); }
.proc-fit-col li {
  display: flex; align-items: flex-start; gap: var(--space-75);
  font-size: var(--fs-sm);
  padding: var(--space-75);
  margin-inline: calc(var(--space-75) * -1);
  border-radius: var(--radius-sm);
  transition: background-color var(--duration-fast) var(--ease), transform var(--duration-fast) var(--ease-spring);
}
.proc-fit-col li svg { width: 16px; height: 16px; flex: none; margin-block-start: 0.2em; stroke-width: 2.5; }
.proc-fit-col--yes li { color: var(--fg-2); }
.proc-fit-col--yes li svg { color: var(--accent-text); }
.proc-fit-col--yes li:hover { background: color-mix(in srgb, var(--accent) 18%, transparent); transform: translateX(2px); }
.proc-fit-col--no li { color: var(--muted); }
.proc-fit-col--no li svg { color: var(--alert); }
.proc-fit-col--no li:hover { background: var(--hover-fill); transform: translateX(2px); }
@media (min-width: 48em) {
  .proc-fit-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 63.99em) {
  .proc-line { left: 7px; right: auto; top: 0; bottom: 0; width: 2px; height: auto; }
  .proc-line i { transform-origin: top; transform: scaleY(var(--p)); }
  .proc-steps { grid-template-columns: 1fr; gap: var(--space-500); }
  .proc-step { padding-block-start: 0; padding-inline-start: var(--space-500); }
  .proc-step p { max-width: none; }
}

/* ---- Build stack - the platforms a client already runs --------------------
   Client-recognisable brands (Instagram, TikTok, Meta Ads, Shopify,
   Mailchimp), not XPixel's own internal tooling - chosen so a prospect
   can scan this row and immediately see their own stack reflected back.
   No .label eyebrow here on purpose - the page already carries eyebrows
   on most sections above it. */
/* BYQ "Trusted by agencies" row: centred mono tag, then a single line of
   monochrome wordmarks at reduced strength that come to full colour on hover. */
.stack-strip-section { padding-block: var(--space-700) var(--space-800); border-block-start: 0; }
.stack-strip-head { text-align: center; margin-block-end: var(--space-600); }
.stack-strip-head h2.label { font-size: 0.6875rem; letter-spacing: var(--tracking-label); line-height: 1.3; }
.stack-strip { display: flex; flex-wrap: wrap; justify-content: space-around; align-items: center; gap: var(--space-500) var(--space-700); list-style: none; }
.stack-strip-item { display: flex; align-items: center; gap: var(--space-100); transition: transform var(--duration) var(--ease); }
.stack-strip-item:hover { transform: translateY(-2px); }
/* Real brand wordmarks in their own colours: never dimmed or greyed. Each
   is sized to a common optical height, not a common width. */
.stack-strip-logo { display: block; height: 2.25rem; width: auto; max-width: none; }
.stack-strip-logo--meta { height: 2rem; }
.stack-strip-logo--tiktok { height: 2.125rem; }
.stack-strip-logo--shopify { height: 2.375rem; }
.stack-strip-badge {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: var(--radius-md);
  flex: none;
}
.stack-strip-badge svg { width: 44%; height: 44%; }
.stack-strip-badge--mailchimp { background: #FFE01B; color: #241C15; width: 2.25rem; height: 2.25rem; }   /* Freddie in Mailchimp's own yellow, beside its script wordmark */
.stack-strip-badge--mailchimp svg { width: 74%; height: 74%; }   /* Freddie fills the badge; the generic 44% glyph size left him tiny */
@media (max-width: 47.99em) {
  .stack-strip { gap: var(--space-400) var(--space-500); }
  .stack-strip-logo { height: 1.75rem; }
  .stack-strip-logo--meta { height: 1.5rem; }
  .stack-strip-logo--tiktok { height: 1.625rem; }
  .stack-strip-logo--shopify { height: 1.875rem; }
  .stack-strip-badge--mailchimp { width: 1.75rem; height: 1.75rem; }
}

/* ---- Ending - CTA + FAQ -------------------------------------------------------------------
   The close is the one place the page changes register: the section and
   the footer beneath it sit on the ink scope (tokens.css), so the final
   call to action is the darkest thing on the page after nine light
   sections. Nothing here is restyled for dark; the components read the
   remapped tokens. */
.ending { padding-block: var(--section-y-loose) var(--section-y); }
.ending .grid { align-items: start; }
/* Closing panel: an abstract photograph shown at full strength, the pitch
   set on it in white, and the enquiry form on a solid white sheet inset
   from the panel edge (sheet radius = panel radius − inset, so the two
   curves stay concentric). The sheet carries the form so field contrast
   never depends on the picture behind it. */
.cta-panel {
  position: relative;
  padding: var(--space-300) var(--space-200) var(--space-200);
  border-radius: var(--radius-xl);
  display: grid;
  gap: var(--space-400);
  overflow: hidden;
  isolation: isolate;
  background: #0a1040;
  color: #fff;
  scroll-margin-block-start: calc(var(--nav-inset) + var(--nav-pill) + var(--space-300));
}
.cta-bg {
  position: absolute; inset: 0 0 auto 0; z-index: 0;
  height: min(100%, 30rem);
  -webkit-mask-image: linear-gradient(180deg, #000 60%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 60%, transparent 100%);
}
.cta-bg img { width: 100%; height: 100%; object-fit: cover; object-position: 40% 40%; }
.cta-bg::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(5, 8, 36, 0.62) 0%, rgba(5, 8, 36, 0.28) 55%, rgba(5, 8, 36, 0) 100%); }
.cta-panel > :not(.cta-bg) { position: relative; z-index: 1; }
.cta-head { display: grid; gap: var(--space-200); padding-inline: var(--space-100); padding-block-start: var(--space-100); min-width: 0; }
.cta-panel .label { justify-self: start; background: rgba(255, 255, 255, 0.14); border: 1px solid rgba(255, 255, 255, 0.28); color: #fff; }
.cta-panel h2 { max-width: 16ch; color: #fff; }
.cta-panel .h-muted { color: rgba(255, 255, 255, 0.66); }
.cta-panel p { color: rgba(255, 255, 255, 0.86); max-width: 36ch; font-size: var(--fs-lead); line-height: var(--lh-snug); }
.cta-sheet {
  display: grid;
  gap: var(--space-300);
  padding: var(--space-300) var(--space-200);
  border-radius: calc(var(--radius-xl) - var(--space-100));
  background: var(--surface);
  color: var(--fg);
  box-shadow: 0 24px 48px -24px rgba(3, 6, 30, 0.6);
}
.cta-sheet p { color: var(--fg-2); max-width: none; }
/* Every box in the sheet may shrink below its content's natural width (grid and
   flex items default to min-width: auto, which is what pushed a nowrap select
   past the edge); long text then wraps, or truncates with an ellipsis where
   it is a single-line value. */
.cta-sheet, .fit-form, .fit-form-row, .fit-form-actions { min-width: 0; }
.cta-meta { display: flex; flex-wrap: wrap; gap: var(--space-100) var(--space-300); font-size: var(--fs-sm) !important; color: var(--fg-2); padding-block-start: var(--space-200); border-block-start: 1px solid var(--line); }
.cta-meta span { display: inline-flex; align-items: center; gap: var(--space-50); }
.cta-meta a { color: var(--fg); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line-strong); transition: text-decoration-color var(--duration-fast) var(--ease); }
.cta-meta a:hover { text-decoration-color: var(--fg); }

/* The fit-call enquiry form: real fields instead of a bare mailto link, so
   the enquiry arrives pre-qualified (what they need, what they can spend)
   the same way the Process section already screens for fit. */
.fit-form { display: grid; gap: var(--space-200); }
.fit-form-row { display: grid; gap: var(--space-200); grid-template-columns: 1fr; }
.fit-field { display: grid; gap: var(--space-75); align-content: start; min-width: 0; }
.fit-field label { font-size: var(--fs-sm); font-weight: var(--weight-medium); color: var(--fg); }
.fit-field-optional { font-weight: var(--weight-regular); color: var(--muted); }
.fit-field-textarea { height: auto; min-height: 6.5rem; padding-block: var(--space-100); resize: vertical; line-height: var(--lh-snug); }
/* two classes deep so they win over `.cta-panel p` (intro-sized, white) */
.cta-sheet .fit-error { margin: 0; font-size: var(--fs-xs); line-height: var(--lh-snug); color: var(--alert); max-width: none; overflow-wrap: anywhere; }
.fit-form-actions { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-200); justify-self: start; }
.fit-form-actions .btn-primary { min-height: var(--tap-target); padding-inline: var(--space-300); }
.cta-sheet .fit-form-status { font-size: var(--fs-sm); line-height: var(--lh-snug); color: var(--fg-2); overflow-wrap: anywhere; }
.cta-sheet .fit-form-status[data-state="error"] { color: var(--alert); }
@media (min-width: 48em) {
  .fit-form-row { grid-template-columns: 1fr 1fr; }
  .cta-panel { padding: var(--space-400) var(--space-300) var(--space-300); }
  .cta-head { padding-inline: var(--space-200); }
  .cta-sheet { padding: var(--space-400) var(--space-300); }
}

/* ---- FAQ - stacked cards, each a tray with a raised core -------------------------
   Every question is its own object: a tinted tray (the <details>) holding a
   white core (its ::before), so the nested-bezel construction needs no extra
   markup and <summary> stays the first child of <details>. Closed cards are
   quiet; hovering lifts the core, and an open card takes the page's single
   accent: lime ring on the tray, lime button on the toggle. The hairline
   list style is kept for the same component inside the Engagement cards. */
.faq-head { display: grid; gap: var(--space-100); justify-items: start; }
.faq h2 { font-size: clamp(1.75rem, 1.3rem + 1.3vw, 2.5rem); font-weight: var(--weight-semibold); letter-spacing: var(--tracking-hero); line-height: 1.05; margin-block-start: var(--space-100); }
.faq-sub { color: var(--muted); font-size: var(--fs-body); }
.faq .acc { display: grid; gap: var(--space-100); border: 0; margin-block-start: var(--space-400); }
.faq .acc-item {
  --shell: 6px;
  position: relative;
  padding: var(--shell);
  border: 0;
  border-radius: calc(var(--radius-card) + var(--shell));
  background: var(--line-soft);
  box-shadow: inset 0 0 0 1px var(--line);
  transition: background-color var(--duration) var(--ease), box-shadow var(--duration) var(--ease);
}
.faq .acc-item::before {
  content: "";
  position: absolute; inset: var(--shell);
  border-radius: var(--radius-card);
  background: var(--surface);
  box-shadow: inset 0 1px 0 var(--glass-edge), var(--shadow-1);
  transition: box-shadow var(--duration) var(--ease), transform var(--duration) var(--ease-heavy);
}
.faq .acc-item > * { position: relative; }
.faq .acc-item:hover::before { box-shadow: inset 0 1px 0 var(--glass-edge), 0 10px 24px -14px rgba(7, 7, 8, 0.22); transform: translateY(-1px); }
.faq .acc-item[open] { background: var(--accent-soft); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent-deep) 55%, transparent); }
.faq .acc-item summary {
  padding: var(--space-200) var(--space-200) var(--space-200) var(--space-300);
  min-height: 4rem;
  font-size: var(--fs-lead);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-tight);
  line-height: var(--lh-snug);
  border-radius: var(--radius-card);
}
.faq .acc-item summary:hover { color: var(--fg); }
.faq .acc-item summary:focus-visible { outline-offset: 2px; border-radius: var(--radius-card); }
/* the toggle is a small button sitting inside the row: + turns to × and fills lime */
.faq .acc-icon {
  width: 36px; height: 36px;
  border-radius: 50%;
  border: 0;
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--line);
  color: var(--fg-2);
  transition: transform var(--duration) var(--ease-spring), background-color var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}
.faq .acc-icon svg { width: 14px; height: 14px; stroke-width: 2; }
.faq .acc-item summary:hover .acc-icon { background: var(--hover-fill); transform: scale(1.06); }
.faq .acc-item[open] .acc-icon { transform: rotate(45deg); background: var(--accent); box-shadow: none; color: var(--accent-ink); }
.faq .acc-item[open] summary:hover .acc-icon { transform: rotate(45deg) scale(1.06); background: var(--accent); }
.faq .acc-body > * { padding: 0 var(--space-500) var(--space-300) var(--space-300); color: var(--fg-2); font-size: var(--fs-body); line-height: 1.55; max-width: 38rem; }
.faq-more {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--space-200);
  margin-block-start: var(--space-300); padding: var(--space-200) var(--space-300);
  border-radius: var(--radius-card);
  border: 1px dashed var(--line-strong);
}
.faq-more p { font-size: var(--fs-sm); color: var(--muted); }
.faq-more strong { color: var(--fg); font-weight: var(--weight-semibold); }
@media (max-width: 47.99em) {
  .faq .acc-item summary { padding: var(--space-100) var(--space-100) var(--space-100) var(--space-200); font-size: var(--fs-body); font-weight: var(--weight-medium); min-height: 3.5rem; }
  .faq .acc-body > * { padding: 0 var(--space-200) var(--space-200) var(--space-200); }
  .faq-more { padding: var(--space-200); }
}
@media (min-width: 64em) { .cta-panel { position: sticky; top: calc(var(--nav-inset) + var(--nav-pill) + var(--space-300)); } }

/* ---- Footer - continues the ink scope of the ending -------------------------------------
   Left: brand, one line on what XPixel does, and the newsletter as a single
   pill (field and submit share one rounded shell, the submit carries its
   own arrow disc). Right: two link columns. Below: an oversized, fading
   wordmark as the page's last image, then the legal row with a back-to-top
   link. Tokens come from the ink scope, so nothing here is dark-specific. */
.footer { position: relative; overflow: hidden; border-block-start: 1px solid var(--line-strong); padding-block: var(--space-700) var(--space-400); }
.footer-grid { display: grid; gap: var(--space-600); }
.footer-brand { min-width: 0; }
.footer-brand .nav-logo { min-height: 44px; }
.footer-tagline { margin-block-start: var(--space-300); color: var(--muted); font-size: var(--fs-body); line-height: 1.55; max-width: 36ch; text-wrap: pretty; }
/* newsletter: one pill, the field and the button inside it */
.footer-signup {
  display: flex; align-items: center; gap: var(--space-100);
  margin-block-start: var(--space-400); max-width: 28rem;
  padding: 4px 4px 4px var(--space-200);
  border-radius: var(--radius-lg);   /* 12px; the button inside is 8px = 12 - the 4px inset, so the curves stay concentric */
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--line-strong), inset 0 1px 0 var(--glass-edge);
  transition: box-shadow var(--duration-fast) var(--ease);
}
.footer-signup:focus-within { box-shadow: inset 0 0 0 1px var(--accent), 0 0 0 4px var(--accent-soft); }
.footer-signup .field {
  flex: 1 1 auto; min-width: 0; height: 44px; padding-inline: 0; border: 0; border-radius: 0;
  background: transparent; box-shadow: none; color: var(--fg);
}
.footer-signup .field:focus-visible { box-shadow: none; outline: none; }   /* the pill's own focus ring replaces the field's */
.footer-signup-btn {
  flex: none; display: inline-flex; align-items: center; gap: var(--space-100);
  min-height: 44px; padding: 0 6px 0 var(--space-200);
  border: 0; border-radius: var(--radius-md);   /* same 8px as every other button */
  background: var(--accent); color: var(--accent-ink);
  font: inherit; font-weight: var(--weight-semibold); font-size: var(--fs-sm); cursor: pointer;
  touch-action: manipulation;
  transition: background-color var(--duration-fast) var(--ease), transform var(--duration-press) var(--ease);
}
.footer-signup-btn:hover { background: var(--accent-deep); }
.footer-signup-btn:active { transform: scale(0.97); }
.footer-signup-ico {
  display: inline-grid; place-items: center; width: 32px; height: 32px; border-radius: var(--radius-sm);
  background: rgba(7, 7, 8, 0.12);
  transition: transform var(--duration) var(--ease-spring);
}
.footer-signup-ico .ico { width: 16px; height: 16px; stroke-width: 2; }
.footer-signup-btn:hover .footer-signup-ico { transform: translate(2px, -1px) scale(1.06); }
.footer-signup-note { margin-block-start: var(--space-100); padding-inline: var(--space-200); font-size: var(--fs-xs); line-height: 1.5; color: var(--muted); max-width: 30rem; }
.footer-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-400) var(--space-300); align-content: start; }
.footer-col { min-width: 0; }
.footer-col .label { display: block; margin-block-end: var(--space-200); color: var(--muted); }
.footer-col .footer-links { flex-direction: column; align-items: flex-start; gap: 0; }
.footer-links { display: flex; flex-wrap: wrap; gap: 0 var(--space-300); list-style: none; }
.footer-links a {
  display: inline-flex; align-items: center; gap: var(--space-75);
  min-height: 44px; font-size: var(--fs-body); color: var(--fg-2);
  overflow-wrap: anywhere;
  transition: color var(--duration-fast) var(--ease), transform var(--duration) var(--ease-heavy);
}
.footer-links a:hover { color: var(--accent); transform: translateX(3px); }
.footer-mark {
  margin-block: var(--space-700) 0;
  font-family: var(--font-display); font-weight: var(--weight-semibold);
  font-size: clamp(4.5rem, 22vw, 20rem); line-height: 0.8; letter-spacing: -0.05em; text-align: center;
  color: transparent;
  background: linear-gradient(180deg, rgba(241, 241, 241, 0.22) 0%, rgba(241, 241, 241, 0.04) 70%, transparent 100%);
  -webkit-background-clip: text; background-clip: text;
  user-select: none; -webkit-user-select: none; pointer-events: none;
  padding-block-end: 0.12em;
}
.footer-bottom {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--space-100) var(--space-300);
  margin-block-start: var(--space-200); padding-block-start: var(--space-200); border-block-start: 1px solid var(--line);
}
.footer-bottom p { font-size: var(--fs-xs); line-height: 1.5; color: var(--muted); max-width: 52ch; }
.footer-legal { gap: 0 var(--space-300); }
.footer-legal a { font-size: var(--fs-sm); color: var(--muted); }
.footer-to-top { color: var(--fg) !important; font-weight: var(--weight-medium); }
.footer-to-top .footer-signup-ico { width: 32px; height: 32px; background: var(--surface-3); transform: rotate(-90deg); }
.footer-to-top:hover { transform: none; }
.footer-to-top:hover .footer-signup-ico { background: var(--accent); color: var(--accent-ink); transform: rotate(-90deg) translateX(2px); }
@media (min-width: 48em) {
  .footer-grid { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: var(--space-700); align-items: start; }
}
@media (min-width: 64em) {
  .footer { padding-block-start: var(--space-800); }
}
@media (max-width: 26.24em) {
  .footer-signup-btn { padding-inline-start: var(--space-100); }
}

/* Secondary pages (privacy, terms, 404, style guide) sit under the fixed nav */
.page-main { padding-block-start: calc(var(--nav-inset) + var(--nav-pill) + var(--space-600)); padding-block-end: var(--section-y); }

/* Privacy/terms body copy: h2 here is a reading sub-heading, not a page
   title, so it's sized well below the global h2 (reserved for section
   headers elsewhere on the site). */
.legal-page h2 { font-size: var(--fs-h3); letter-spacing: var(--tracking-tight); line-height: var(--lh-heading); margin-block-start: var(--space-500); margin-block-end: var(--space-150); }
.legal-page ul { list-style: disc; padding-inline-start: 1.25em; display: grid; gap: var(--space-150); margin-block-start: var(--space-150); }
.legal-page ul li::marker { color: var(--muted); }
.legal-page p + p { margin-block-start: var(--space-150); }
.legal-page a { color: var(--fg); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line-strong); }
.legal-page a:hover { text-decoration-color: var(--fg); }

/* ---- Scroll reveal ------------------------------------------------------------------- */
.js .reveal { opacity: 0; transform: translateY(20px); transition: opacity var(--duration-reveal) var(--ease), transform var(--duration-reveal) var(--ease); }
.js .reveal.is-visible { opacity: 1; transform: none; }
.js .reveal-stagger > * { opacity: 0; transform: translateY(16px); transition: opacity var(--duration-reveal) var(--ease), transform var(--duration-reveal) var(--ease); }
.js .reveal-stagger.is-visible > * { opacity: 1; transform: none; }
.js .reveal-stagger.is-visible > :nth-child(2) { transition-delay: 80ms; }
.js .reveal-stagger.is-visible > :nth-child(3) { transition-delay: 160ms; }
.js .reveal-stagger.is-visible > :nth-child(4) { transition-delay: 240ms; }
.js .reveal-stagger.is-visible > :nth-child(5) { transition-delay: 320ms; }
.js .reveal-stagger.is-visible > :nth-child(6) { transition-delay: 400ms; }
.js .reveal-stagger.is-visible > :nth-child(7) { transition-delay: 480ms; }
.js .reveal-stagger.is-visible > :nth-child(8) { transition-delay: 560ms; }
/* Masked reveal: content wipes in from the bottom; mask on the child, never the observed element */
.js .reveal-mask > * { clip-path: inset(0 0 100% 0); transition: clip-path 1s var(--ease-heavy); }
.js .reveal-mask.is-visible > * { clip-path: inset(0 0 0 0); }
/* Settle reveal: sharpen and scale to 1 (images, proof tiles) */
.js .reveal-settle > * { opacity: 0; transform: scale(0.97); filter: blur(6px); transition: opacity var(--duration-reveal) var(--ease), transform var(--duration-reveal) var(--ease-heavy), filter var(--duration-reveal) var(--ease); }
.js .reveal-settle.is-visible > * { opacity: 1; transform: none; filter: none; }
.js .reveal-settle.is-visible > :nth-child(2) { transition-delay: 90ms; }
.js .reveal-settle.is-visible > :nth-child(3) { transition-delay: 180ms; }
.js .reveal-settle.is-visible > :nth-child(4) { transition-delay: 270ms; }
.js .reveal-settle.is-visible > :nth-child(5) { transition-delay: 360ms; }
.js .reveal-settle.is-visible > :nth-child(6) { transition-delay: 450ms; }

/* ---- Reduced motion: complete static page, every end state defined ---------------- */
@media (prefers-reduced-motion: reduce) {
  .js .reveal, .js .reveal-stagger > *, .js .reveal-mask > *, .js .reveal-settle > *, .js .mosaic-tile { opacity: 1; transform: none; clip-path: none; filter: none; transition: none; }
  .rotator-item { animation: none; }
  .rotator-item:not(.is-active) { opacity: 0; }
  .mosaic-col { transform: none; }
  .mosaic-tile:hover > .ui-scope, .mosaic-tile:hover > .photo img, .mosaic-tile:hover > .photo video { transform: none; }
  .eng-flow-pulse { animation: none; opacity: 0; }
  .feat-caret { animation: none; }
  .feat-ai-link::after { animation: none; left: 50%; opacity: 1; }
  .feat-build-block { animation: none; opacity: 1; transform: none; }
  .feat-ad-dot { animation: none; opacity: 1; transform: none; }
  .feat-ad-chart-bar { animation: none; transform: scaleY(1); opacity: 1; }
  .proc { --p: 1; }
  .rail-track { scroll-behavior: auto; }
  .toolkit-icon-badge { animation: none; transform: none; transition: none; }
  .toolkit-line { transition: none; }
}
