/* =============================================================
   PALARY — SECTIONS
   Per-section layout + background. Redesign pass: surfaces are lighter —
   Features (§3) + Integration (§4) are white; the forest #2E4B47 anchor
   now lives ONLY on Stats+Testimonial (§6), the single dark "depth cue".
   Quiet #FFFFFF ↔ #F5F4F2 alternation carries rhythm; the grid + whitespace
   divide, colour divides once.
   ============================================================= */

/* Background utilities mapped to the section table */
.bg-dark   { background: var(--color-bg-primary);        color: var(--color-text-primary); }
.bg-brand  { background: var(--color-bg-brand);           color: var(--color-text-on-forest); }
.bg-forest { background: var(--color-bg-forest-surface);  color: var(--color-text-on-forest); }
.bg-light  { background: var(--color-bg-light);           color: var(--color-text-inverse-primary); }
.bg-white  { background: var(--color-bg-light-pure);      color: var(--color-text-inverse-primary); }
.bg-accent { background: var(--color-bg-accent);          color: var(--color-text-on-accent); }

/* The visible column grid + scroll guide were removed (the 5-col wallpaper read
   as decorative, not structural — it couldn't align both the 5-card hero and the
   3-card content rows; 5 vs 3 share no interior lines). A new structural concept
   is being designed. The hero fan (cards → logo) stays. */
.section { position: relative; isolation: isolate; }

/* Shared section header: eyebrow + headline + optional support */
.section-head { max-width: 760px; display: flex; flex-direction: column; gap: var(--gap-20); }
.section-head .eyebrow { color: var(--color-text-inverse-secondary); }
.bg-dark .section-head .eyebrow,
.bg-forest .section-head .eyebrow { color: var(--color-text-muted-on-forest); }
.bg-brand .section-head .eyebrow  { color: var(--color-text-on-dark-muted); }

/* Eyebrow pill — background adapts to section context */
.bg-dark .eyebrow    { background: var(--eyebrow-bg-dark); }
.bg-forest .eyebrow  { background: var(--eyebrow-bg-forest); }
/* Integration (.bg-brand) has a strong dark container — no pill needed there */
.bg-brand .eyebrow   { background: none; padding: 0; border-radius: 0; }
.section-head__support { color: var(--color-text-inverse-secondary); }
.bg-dark .section-head__support   { color: var(--color-text-secondary); }
.bg-forest .section-head__support { color: var(--color-text-muted-on-forest); }
.bg-brand .section-head__support  { color: var(--color-text-on-dark-muted); }

.bg-dark .tag,
.bg-forest .tag  { background: var(--tag-bg-on-dark);   color: var(--tag-text-on-dark); }
.bg-brand .tag   { background: var(--tag-bg-on-brand);  color: var(--tag-text-on-brand); }
.bg-accent .tag  { background: var(--tag-bg-on-accent); color: var(--tag-text-on-accent); }

/* ====================== 1+2. HERO + LOGO WALL ======================
   Dark bg continues through hero into logo wall (§ table 1→2).
   Hero: centered copy, then the animated Hero Stack visual below. */
.hero {
  position: relative;                  /* stacking context for .hero__bg */
  background: var(--color-bg-primary); /* fallback under the animated layer */
  color: var(--color-text-primary);
  padding-top: var(--gap-64);
  /* Dark breathing room below the Palary mark before the white logo wall begins
     (Figma node 823:7094: ~67px below the logo). Keeps the logo from kissing the
     dark→white seam. */
  padding-bottom: var(--gap-64);
  overflow: hidden;
}
/* Hero content sits above the animated backdrop. Strands (.herofan) at z1 sit UNDER
   the grain (z2); the copy stays at z3 above the grain so the headline reads crisp. */
.hero > .herofan { position: relative; z-index: 1; }
.hero > .container { position: relative; z-index: 3; }
.hero__copy {
  max-width: 1000px; margin-inline: auto; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: var(--gap-24);
}
/* Centered layout — override base align-self: flex-start back to center */
.hero__copy .eyebrow { color: var(--lime-100); opacity: 0.75; align-self: center; background: var(--eyebrow-bg-dark); }
.hero__subline { color: var(--color-text-secondary); max-width: 60ch; }

/* ---- Animated gradient backdrop (recolored from the Figma note) ----
   Technique: dark linear base + large blurred radial "blobs" at
   mix-blend-mode:hard-light, each slowly drifting. Mirrors the React
   BackgroundGradientAnimation, but authored in static CSS. All tunable
   values are scoped vars here so this block is the single source of truth.
   Palette traces to the Figma note (sage/charcoal/beige), NOT the bright
   purple/cyan demo. */
.hero__bg {
  --blob-blur: 90px;           /* Figma note: blur(125.9px), eased for the web + amplified motion */
  --blob-blend: hard-light;    /* Figma note: mix-blend-mode */
  --blob-tilt: 24deg;          /* Figma note: rotate(24deg) */
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  /* Base wash — Figma note: linear-gradient(148deg, …) */
  background: linear-gradient(148deg,
    #30302F 0%, #4E4E4E 19%, #30302F 42%,
    #353E3C 61%, #0A0A0A 77%, #383838 100%);
}
/* Dark veil over the blobs (Figma note: rgba(0,0,0,0.39)). Sits above the
   blobs but below hero content, so it deepens the glow without dimming copy. */
.hero__bg::after {
  content: "";
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, 0.30);  /* Figma note: 0.39 — lifted so color movement reads */
}
/* Silk-screen grain — a real PNG noise texture (not feTurbulence; the brief wants
   print-feel clumping). Sits ABOVE the strands (z-index 2), below the copy (z-index 3),
   so the strands read as printed ink under the grain. mix-blend overlay on the dark. */
.hero__grain {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  opacity: var(--grain-opacity); mix-blend-mode: overlay;
  background-image: url("../assets/noise.png");
  background-repeat: repeat; background-size: 256px 256px;
}
/* Vignette — pull the edges down so the centre opening reads as lit. */
.hero__vignette {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(ellipse 80% 70% at 50% 46%,
              transparent 40%, rgba(0,0,0,0.28) 100%);
}
.hero__blob {
  position: absolute;
  border-radius: 9999px;
  filter: blur(var(--blob-blur));
  mix-blend-mode: var(--blob-blend);
  transform-origin: center;
  will-change: transform;
}
/* Blob A — large sage glow.  Figma: #1C1C1C → #63908A */
.hero__blob--a {
  width: 117%; height: 91%; left: 35%; top: 23%;
  background: radial-gradient(ellipse 53% 25% at 28% -5%, #1C1C1C 0%, #63908A 100%);
  opacity: 1;
  animation: heroBlobDrift 20s ease-in-out infinite;
}
/* Blob B — bright mint core.  Figma: #B0D3BE → #4D7D77 (forest-500) */
.hero__blob--b {
  width: 117%; height: 57%; left: 50%; top: 15%;
  background: radial-gradient(ellipse 28% 30% at 24% 27%, #B0D3BE 0%, #4D7D77 100%);
  opacity: 0.95;
  animation: heroBlobOrbit 26s linear infinite;
}
/* Blob C — beige → steel, translucent.  Figma: rgba(211,204,176,.68) → rgba(77,110,125,.68) */
.hero__blob--c {
  width: 117%; height: 67%; left: 40%; top: -32%;
  background: radial-gradient(ellipse 49% 76% at -13% 36%,
    rgba(211, 204, 176, 0.78) 0%, rgba(77, 110, 125, 0.78) 100%);
  opacity: 0.9;
  animation: heroBlobSway 24s ease-in-out infinite;
}

/* Drift choreography. rotate(var(--blob-tilt)) is held constant in every
   keyframe so the 24° Figma tilt is preserved while the blob translates.
   Travel + scale are amplified so the motion reads under heavy blur. */
@keyframes heroBlobDrift {        /* vertical breathing + pulse */
  0%, 100% { transform: rotate(var(--blob-tilt)) translate(0, -22%) scale(1); }
  50%      { transform: rotate(var(--blob-tilt)) translate(0,  22%) scale(1.15); }
}
@keyframes heroBlobOrbit {        /* full rotation + lateral swing */
  0%   { transform: rotate(var(--blob-tilt))                         translateX(-18%); }
  50%  { transform: rotate(calc(var(--blob-tilt) + 180deg)) translateX( 18%); }
  100% { transform: rotate(calc(var(--blob-tilt) + 360deg)) translateX(-18%); }
}
@keyframes heroBlobSway {         /* lateral drift, rock + pulse */
  0%, 100% { transform: rotate(var(--blob-tilt))                        translate(-20%, -6%) scale(1); }
  50%      { transform: rotate(calc(var(--blob-tilt) + 14deg)) translate( 20%,  8%) scale(1.12); }
}

/* Honor the site-wide motion contract: freeze the blobs, keep the palette. */
@media (prefers-reduced-motion: reduce) {
  .hero__blob { animation: none; }
}
@media (prefers-reduced-motion: reduce) {
  /* Static, legible strands — rendered at rest (the entrance never runs), no bulbs. */
  .herofan__lines .strand-sliver { visibility: visible; }
  #bulb-layer { display: none; }
}

/* ---- Hero card-fan ----
   5 source cards in a row converge (via SVG strands built in motion.js) into the
   Palary mark, which hands off into the page column grid below. Cards are equal
   width (flex: 1) + equal height (align-items: stretch); rd-16 + lime-100 text per
   Figma. <1024 the row becomes a static vertical stack (no marquee). */
/* Fluid width capped on ultrawide — tracks .container exactly (same 88% /
   var(--container) model) so the fan and all page content share one edge.
   Cards (flex:1) + the stage widen with it; strands re-measure. */
.herofan { width: calc(100% - 2 * var(--side-padding)); max-width: var(--container); margin: var(--gap-48) auto 0; }
.herofan__cards {
  display: flex; gap: var(--gap-16); align-items: stretch; justify-content: center;
  list-style: none; margin: 0; padding: 0;
}
/* Desktop: the marquee wrapper is layout-transparent, so the cards behave as a
   direct flex row exactly as before. The clones motion.js appends for the mobile
   loop stay hidden until the <1024 marquee takes over. */
.herofan__marquee { display: contents; }
.agentcard[data-clone] { display: none; }
.agentcard {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; gap: var(--pd-8);
  padding: var(--pd-20) var(--pd-16);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(241, 255, 203, 0.22);   /* #F1FFCB at low alpha */
  border-radius: var(--rd-16);
  box-shadow: 0 18px 40px -16px rgba(10, 39, 32, 0.45);
  text-align: center; backdrop-filter: blur(3px);
  transition: border-color .3s ease, box-shadow .3s ease, transform .3s ease;
}
.agentcard__label {
  font-family: var(--font-body); font-weight: 600; font-size: 14px; line-height: 1.3;
  text-transform: uppercase; letter-spacing: var(--tracking-label); color: var(--lime-100);
}
.agentcard__sub {
  font-weight: 500; font-size: 13px; line-height: 1.35;
  color: var(--lime-100); opacity: 0.7;
}

.herofan__converge {
  position: relative;
  height: 380px;                       /* converge-space above + diverge-space below the waist */
  margin-top: var(--gap-16);
}
.herofan__lines {
  position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible;
  /* Edge fades: strands + bulbs dissolve IN at the card bottoms (top ~14%) and OUT at
     the section seam (bottom 20%), so neither end hard-cuts. Logo/nebula are in
     .herofan__hub (outside the SVG), so they stay crisp. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 14%, #000 80%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0, #000 14%, #000 80%, transparent 100%);
}
/* Filled-sliver strands (Figma 861-246): two stacked gradient fills — a teal wash
   UNDER the signal gradient. The sliver tapers to a near-point at the logo. The halo
   layer (Phase 2) duplicates these under a blur; the centerline track is invisible
   and only carries the bulbs' MotionPath (Phase 3). */
.herofan__lines .strand-sliver         { stroke: none; }
.herofan__lines .strand-sliver--teal   { fill: url(#strandTeal);   opacity: 0.55; }
.herofan__lines .strand-sliver--signal { fill: url(#strandSignal); opacity: 0.9; }
/* Halo: the same sliver, signal-gradient fill, blurred + boosted = the soft halation.
   Opacity 0.95 (was 0.7, +~36%) pairs with the wider blur for the riso bleed. */
.herofan__lines .strand-sliver--halo   { fill: url(#strandSignal); opacity: 0.95; filter: url(#strandHalo); }
.herofan__lines .strand-track          { fill: none; stroke: none; }
/* Bulbs — travelling light (Phase 3). Radial 6-stop teardrop + soft blur; the <g> is
   moved along a .strand-track by GSAP MotionPath. */
.herofan__lines .bulb__halo { fill: url(#bulbGrad); filter: url(#bulbHalo); opacity: 0.5; }
.herofan__lines .bulb__core { fill: url(#bulbGrad); filter: url(#bulbBlur); }
/* The hub = the convergence point. Lifted to 50% (~84px up from the old 72% on the 380px
   stage) so the converge compresses into the upper half and the diverge fan gets the whole
   lower half to spread wider. waistY is read live from the logo rect (motion.js), so this
   CSS move re-converges the strands automatically. */
.herofan__hub {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 84px; height: 84px;
}
.herofan__logo { position: absolute; inset: 0; width: 100%; height: 100%; }
.herofan__nebula {
  position: absolute; left: 50%; top: 50%;
  width: 210px; height: 210px; transform: translate(-50%, -50%);
  border-radius: 9999px; pointer-events: none; z-index: -1;
  /* Smaller, dimmer, much softer — a gentle bloom hugging the mark, not a disc. */
  background: radial-gradient(circle, color-mix(in srgb, var(--hub-glow) 34%, transparent) 0%,
                                       transparent 60%);
  filter: blur(20px);
}
/* <1024: the card row becomes a full-bleed horizontal marquee (40s, slow +
   readable). The strands decouple from the cards — they fan from FIXED anchors
   on the converge stage (built in motion.js) while the cards scroll above them.
   The stage narrows to the page content box so those anchors sit at 0/33.3/66.7/
   100% — the same x-positions as the section grid lines below (4-line tablet
   grid). Reduced-motion → static, manually-swipeable strip. */
@media (max-width: 1023px) {
  .herofan { max-width: none; margin-top: var(--gap-32); }

  /* marquee viewport: full-bleed, clipped, edges faded to hide the loop seam */
  .herofan__marquee {
    display: block;
    width: 100vw; margin-left: calc(50% - 50vw);
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 12%, #000 88%, transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 12%, #000 88%, transparent 100%);
  }
  /* the animated track: two identical card sets, shifted by exactly one set */
  .herofan__cards {
    flex-direction: row; flex-wrap: nowrap; justify-content: flex-start;
    width: max-content; gap: 0; padding-block: var(--gap-16);
    animation: herofan-marquee 40s linear infinite;
  }
  .herofan__cards:hover { animation-play-state: paused; }   /* 768–1023 pointer band */
  .agentcard[data-clone] { display: flex; }
  .agentcard { flex: 0 0 auto; width: 232px; margin-right: var(--gap-16); }

  /* converge stage = page content box, centered → anchors align to the grid.
     Taller than before so the lifted logo (waist) + the divergence fit. */
  .herofan__converge {
    width: 100%;
    max-width: calc(var(--container) - 2 * var(--side-padding));
    margin-inline: auto; height: 300px;
  }
}

/* Constant linear motion (emil: marquees use linear easing, CSS keyframes keep
   it off the main thread). One set width = 50% of the duplicated track. */
@keyframes herofan-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Reduced motion: stop the scroll; let the strip be swiped by hand. The fan
   itself renders static (the draw-in only runs under no-preference). */
@media (prefers-reduced-motion: reduce) {
  .herofan__cards { animation: none; }
}
@media (prefers-reduced-motion: reduce) and (max-width: 1023px) {
  .herofan__marquee { overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/* Logo wall — white surface (the page's light body begins here). The hero fan
   converges into the logo just above; this section opens the light body.
   bg comes from the `bg-white section` classes in the markup. */
.logowall {
  /* Equal top/bottom — the partner strip is a transition band: enough air to
     breathe, but tighter than a full section so it doesn't float. */
  padding-block: var(--gap-64);
}
.logowall__label {
  text-align: center; color: var(--color-text-inverse-secondary);
  margin-bottom: var(--gap-32);
  /* Logowall eyebrow is centered text, not a pill — undo eyebrow base pill styles */
  display: block;
  width: auto;
  background: none;
  padding: 0;
  border-radius: 0;
}
.logowall__row {
  display: flex; align-items: center; justify-content: center;
  gap: var(--gap-64); flex-wrap: wrap;
}
.logowall__item {
  display: inline-flex; align-items: center;
  transition: opacity var(--dur-default) var(--ease-out);
}
/* Uniform monochrome-dark treatment: collapses a dark, a black and a multicolor
   logo into one tasteful partner wall on the white bg (§3.3 restraint). Darkens
   toward full ink on hover. */
.logowall__item img {
  height: 32px; width: auto;
  filter: brightness(0);
  opacity: 0.5;
  transition: opacity var(--dur-default) var(--ease-out);
}
.logowall__item:hover img { opacity: 0.85; }

/* ====================== 3. FEATURES ======================
   White bg, 3 numbered cards (01/02/03). 3-up floats across the 5-col grid (Figma). */
.features__grid {
  margin-top: var(--gap-64);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap-16);
}

/* ====================== 4. INTEGRATION ======================
   White bg (redesign pass). Text left, product visual right.
   Lattice: 50/50 — taglines span-10 / visual span-10. */
.integration__layout {
  margin-top: var(--gap-64);
  align-items: center;
  column-gap: var(--gap-48);
}
.integration__taglines { display: flex; flex-direction: column; gap: var(--gap-32); grid-column: span 10; }
.integration__tagline { display: flex; flex-direction: column; gap: var(--gap-12); }
.integration__tagline .tag { width: max-content; }
.integration__tagline p { color: var(--color-text-on-forest); }
.integration__visual {
  grid-column: span 10;
  overflow: visible;
}
.integration__visual img {
  width: 100%; height: auto; display: block;
}

/* ====================== 5. DREI PLATTFORMEN ======================
   Light bg, 3 customer cards (text-only secondary). 3-up floats across the grid. */
.platforms__grid {
  margin-top: var(--gap-64);
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gutter);
}
/* Card labels are already inside a bordered card — no pill needed */
.platform-card__label { color: var(--color-text-inverse-secondary); background: none; padding: 0; border-radius: 0; }
.platform-card__name { font-family: var(--font-display); margin-top: calc(var(--gap-20) * -1 + var(--gap-12)); }
.platform-card__desc { color: var(--color-text-inverse-secondary); }

/* ====================== 6. STATS + TESTIMONIAL ======================
   Forest bg. Desktop: headline (left) + stats cluster (right) share one band,
   divider underneath, then a centered quote. Stacks below tablet. */
.ref__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--gap-48);
  padding-bottom: var(--gap-48);
  border-bottom: var(--bd-1) solid rgba(241,241,241,0.12);
}
.ref__head .section-head { margin: 0; }
/* Stats sit as a right-aligned inline cluster (not a full-width grid). */
.stats__row {
  display: flex; gap: var(--gap-48); flex-shrink: 0;
}
.stat__value { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-h1);
               line-height: 1; letter-spacing: -0.02em; color: var(--lime-400);
               white-space: nowrap; }
.stat__num { display: inline-block; font-variant-numeric: tabular-nums; }
.stat__value .unit { color: var(--lime-400); }
.stat__label { color: var(--color-text-muted-on-forest); margin-top: var(--gap-12); }
/* Centered quote block below the divider. */
.testimonial {
  margin: var(--gap-64) auto 0; max-width: 760px; text-align: center;
}
.testimonial__quote {
  font-family: var(--font-display); font-weight: 600;
  font-size: var(--fs-h3); line-height: var(--lh-h3); letter-spacing: var(--ls-h3);
}
.testimonial__by { margin-top: var(--gap-24); color: var(--color-text-muted-on-forest); }

/* ====================== 7. STADT UND GEMEINDE ======================
   Light bg, text-led, two-column title/body. */
/* Lattice: title col-10 / body col-10 — even 50/50 split. Grid from .grid;
   section rule only carries top alignment. (.container + .grid on one element.) */
.kommunen__layout {
  align-items: start;
}
.kommunen__body { display: flex; flex-direction: column; gap: var(--gap-24); color: var(--color-text-inverse-secondary); }
.kommunen__subline { color: var(--color-text-inverse-primary); font-weight: 600; }

/* ====================== 8. FINAL CTA ======================
   Lime bleed card (rd-16, NOT 14 — §3.1). Centered. Single CTA.
   Preceding section (Kommunen, light) — bleed card sits inside a
   dark wrapper so the lime hit lands with maximum contrast (§4.3). */
.final-cta-wrap { background: var(--color-bg-light-pure); }
/* Tighten the white space framing the floating card — override the global
   section padding (128px) down to a snug 3rem (48px) just for this section. */
.final-cta-wrap .section { padding-block: 3rem; }
/* Let the lime card break out of the page-wide .container (90% / 1600) to sit
   near full-bleed — a slim 24px frame on every breakpoint so the CTA reads big. */
.final-cta-wrap .container {
  width: auto;
  max-width: none;
  margin-inline: var(--pd-24);
}
.final-cta {
  background: radial-gradient(135% 130% at 50% 0%,
    var(--lime-300) 0%, var(--lime-400) 48%, var(--lime-500) 100%);
  color: var(--color-text-on-accent);
  border-radius: var(--rd-16);
  padding: var(--pd-80) var(--pd-40);
  display: flex; flex-direction: column; align-items: center;
  gap: var(--gap-48);
  text-align: center;
  box-shadow: var(--shadow-lg);
}
.final-cta .eyebrow { color: var(--color-text-on-accent); opacity: 0.7; background: var(--eyebrow-bg-accent); align-self: center; }
.final-cta__copy {
  display: flex; flex-direction: column; align-items: center; gap: var(--gap-16);
  max-width: 52ch;
}
.final-cta__subline { max-width: 40ch; }
.final-cta__person {
  display: flex; flex-direction: column; align-items: center; gap: var(--gap-20);
  width: 180px;
}
.final-cta__person .contact-card__avatar {
  width: 180px;
  height: 180px;
}
.final-cta__person .btn {
  width: 100%;
  justify-content: center;
}

/* ====================== 9. FAQ ======================
   Header (headline + lead + CTA) left-aligned above full-width accordion.
   Flat hairline list — no outer border, no card container. */

.faq__header {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: var(--gap-24);
  max-width: 560px;
  margin-bottom: var(--gap-64);
}
@media (max-width: 1023px) {
  .faq__header { margin-bottom: var(--gap-48); }
}
.faq__lead {
  color: var(--color-text-inverse-secondary);
  max-width: 44ch;
}

.faq__list {
  border-top: var(--bd-1) solid var(--charcoal-100);
  overflow: hidden;                /* required: GSAP height tween on .faq__a */
}
.faq__item { border-bottom: var(--bd-1) solid var(--charcoal-100); }

.faq__q {
  list-style: none;
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--gap-24);
  padding: var(--pd-24) 0;
  cursor: pointer;
  font-family: var(--font-body); font-weight: 600;
  font-size: var(--fs-xl); line-height: var(--lh-xl); letter-spacing: var(--ls-xl);
  color: var(--color-text-inverse-primary);
  transition: color var(--dur-default) var(--ease-out);
}
.faq__q::-webkit-details-marker { display: none; }
.faq__item[open] .faq__q { color: var(--charcoal-900); }
.faq__q:focus-visible { outline: 2px solid var(--forest-500); outline-offset: -2px; }

/* Plus/minus icon — vertical line collapses to zero on open.
   margin-top aligns icon to first text line when question wraps. */
.faq__icon { flex: 0 0 20px; color: var(--charcoal-400); margin-top: 0.15em; }
.faq__icon-v {
  transform-origin: 12px 12px;
  transition: transform var(--dur-default) var(--ease-out);
}
.faq__item[open] .faq__icon-v { transform: scaleY(0); }
.faq__item[open] .faq__icon { color: var(--charcoal-600); }

/* Answer panel — overflow:hidden lets motion.js tween height 0↔natural */
.faq__a { overflow: hidden; }
.faq__a p {
  margin: 0;
  padding: 0 0 var(--pd-28);
  color: var(--color-text-inverse-secondary);
  max-width: 72ch;
}

@media (max-width: 480px) {
  .faq__header { margin-bottom: var(--gap-40); }
  .faq__q { padding: var(--pd-20) 0; gap: var(--gap-16); }
  .faq__a p { padding: 0 0 var(--pd-20); }
}

/* ====================== RESPONSIVE ====================== */
@media (max-width: 1023px) {
  .features__grid,
  .platforms__grid { grid-template-columns: repeat(2, 1fr); row-gap: var(--gap-32); }
  /* Stats break out of the head row and stack under the headline:
     label → headline → number → number → number. */
  .ref__head { flex-direction: column; align-items: flex-start; gap: var(--gap-40); }
  .stats__row { flex-direction: column; gap: var(--gap-32); }
  .testimonial { text-align: left; margin-inline: 0; }
  .final-cta { padding: var(--pd-100) var(--pd-40); }
  /* When the integration columns stack, collapse to one track (so the 20-col
     grid's fixed column-gaps don't force a min-width / overflow) and give the
     image clear air below the text. */
  .integration__layout { grid-template-columns: 1fr; column-gap: 0; row-gap: var(--gap-48); }
}
/* Phones (incl. large phones up to the tablet breakpoint): stack the card grids
   into a single column so image + text cards never get squished side-by-side. */
@media (max-width: 767px) {
  .features__grid,
  .platforms__grid { grid-template-columns: 1fr; row-gap: var(--gap-40); }
}
@media (max-width: 480px) {
  .features__grid,
  .platforms__grid { grid-template-columns: 1fr; row-gap: var(--gap-40); }
  .logowall__row { gap: var(--gap-32); flex-direction: column; }
  .final-cta { padding: var(--pd-80) var(--pd-20); border-radius: var(--rd-12); }
  .testimonial__quote { font-size: var(--fs-h4); line-height: var(--lh-h4); }
  /* Compact the single nav CTA so it never crowds the wordmark on 375px */
  .nav__inner .btn { height: 44px; padding-inline: var(--pd-16); }
}
