/* ============================================================
   Solution page template — new family (2026-07-29), first page:
   /use-cases/customer-onboarding/. Richer than the use-case
   outcome brief: full story arc with the product template's dark
   aurora hero, proof strip, quantified problem, and flow hovers.
   Motion = data-reveal scroll-ins, count-up stats, hover intents.

   Scope: every rule starts with .p-solution (the shared template
   root — sibling solution routes load this one stylesheet).
   Per-page accents hang off a .p-solution--<slug> modifier.

   Consumes the base.css system primitives directly (kicker,
   section-title, section shell paddings, btn--white/ghost-dark,
   stat-on-dark/stat-grad) — no per-page copies of those.
   ============================================================ */

.p-solution {
  background: var(--color-black);
  color: var(--color-white);
}

/* ---------- shared primitives ---------- */
/* section inner: the template rhythm (matches the product template) */
.p-solution .sol-inner {
  margin-inline: auto;
  max-width: var(--container-large);
  padding: var(--space-section-sm) var(--space-inline);
}
@media (min-width: 768px) { .p-solution .sol-inner { padding-block: var(--space-section); } }
@media (min-width: 1024px) { .p-solution .sol-inner { padding-inline: 24px; } }

/* section intro under the shared .section-title */
.p-solution .sol-intro {
  margin-top: 16px;
  max-width: 680px;
  font-size: var(--fs-body);
  line-height: var(--leading-body);
  color: var(--color-grey-on-white);
}
.p-solution .sol-intro--on-dark { color: rgba(255, 255, 255, 0.7); }

/* flowy gradient hovers — dark + light (the site's signature hover
   intent, mirrored from the product template) */
.p-solution .sol-flow,
.p-solution .sol-flow-light {
  position: relative;
  overflow: hidden;
}
.p-solution .sol-flow > *,
.p-solution .sol-flow-light > * {
  position: relative;
  z-index: 1;
}
.p-solution .sol-flow::before,
.p-solution .sol-flow-light::before {
  content: "";
  position: absolute;
  inset: -45%;
  z-index: 0;
  opacity: 0;
  transition: opacity 0.45s ease;
  will-change: transform, opacity;
}
.p-solution .sol-flow::before {
  background:
    radial-gradient(42% 60% at 18% 30%, color-mix(in oklab, var(--color-blue-500) 60%, transparent), transparent 62%),
    radial-gradient(36% 55% at 78% 18%, color-mix(in oklab, var(--color-blue) 45%, transparent), transparent 60%),
    radial-gradient(52% 72% at 62% 85%, color-mix(in oklab, var(--color-blue-500) 50%, transparent), transparent 65%),
    radial-gradient(28% 42% at 38% 68%, color-mix(in oklab, var(--color-blue-200) 16%, transparent), transparent 60%);
  filter: blur(28px) saturate(130%);
}
.p-solution .sol-flow-light::before {
  background:
    radial-gradient(42% 60% at 18% 30%, color-mix(in oklab, var(--color-blue) 22%, transparent), transparent 62%),
    radial-gradient(36% 55% at 78% 18%, color-mix(in oklab, var(--color-blue-200) 50%, transparent), transparent 60%),
    radial-gradient(52% 72% at 62% 85%, color-mix(in oklab, var(--color-blue-500) 16%, transparent), transparent 65%),
    radial-gradient(28% 42% at 38% 68%, color-mix(in oklab, var(--color-blue-100) 60%, transparent), transparent 60%);
  filter: blur(24px) saturate(120%);
}
.p-solution .sol-flow:hover::before,
.p-solution .sol-flow-light:hover::before {
  opacity: 1;
  animation: sol-flow-drift 7s ease-in-out infinite;
}
@keyframes sol-flow-drift {
  0%, 100% { transform: translate(0%, 0%) rotate(0deg) scale(1); }
  33% { transform: translate(6%, -5%) rotate(7deg) scale(1.1); }
  66% { transform: translate(-5%, 4%) rotate(-5deg) scale(1.05); }
}
@media (prefers-reduced-motion: reduce) {
  .p-solution .sol-flow:hover::before,
  .p-solution .sol-flow-light:hover::before { animation: none; }
}

/* ---------- 1 · hero (dark · split · one full product screen right) ------ */
.p-solution .sol-hero {
  /* the module template's full-screen card hero (Sofia's v4 recipe from
     module.css): the whole hero is ONE rounded aurora card inset by
     --hero-gutter on all four sides; the nav rides inside the card
     (CARD_HERO_ROUTES). The layout inside is untouched — only the
     background became the framed card. */
  --hero-gutter: 12px;
  position: relative;
  display: flex;
  flex-direction: column;
  /* fits the viewport under the announcement strip's seat (--hl-seat,
     highlights-ticker.css); 0px when no strip */
  min-height: calc(100svh - var(--hl-seat, 0px));
  overflow: hidden;
  padding: var(--hero-gutter);
  background: var(--color-background);
}
.p-solution .sol-hero__aurora {
  position: absolute;
  inset: var(--hero-gutter);
  border-radius: 28px;
  /* identical colors to the document-verification module card */
  background:
    radial-gradient(120% 95% at 12% 0%, color-mix(in oklab, var(--color-blue-500) 80%, transparent), transparent 62%),
    radial-gradient(110% 100% at 92% 100%, color-mix(in oklab, var(--color-blue-500) 65%, transparent), transparent 65%),
    color-mix(in oklab, var(--color-black) 86%, var(--color-blue-500));
  /* soft drop retired (Sofia, 2026-08-05: hard shadows only, site rule) */
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--color-white) 14%, transparent);
}
.p-solution .sol-hero__inner {
  position: relative;
  z-index: 1;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 48px;
  margin-inline: auto;
  width: 100%;
  max-width: var(--container-large);
  /* balanced block padding keeps the copy on the viewport's true center */
  padding: 128px 20px 64px;
}
@media (min-width: 1024px) {
  .p-solution .sol-hero__inner {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: 72px;
    align-items: center;
    /* symmetric block padding, scaled to the viewport height so the card
       ALWAYS closes inside the first screen (matching 12px gutter below);
       still symmetric, so the row center = the sticky phone's center */
    padding: clamp(48px, 7svh, 112px) 24px;
  }
}

/* copy — left-aligned; "Onboard" holds still while the word rolls.
   The column stretches to the stage's height: the copy cluster centers in
   the space above the stats, which pin to the bottom (reference layout —
   the block reads higher, the stats close the hero). */
.p-solution .sol-hero__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  align-self: stretch;
}
@media (min-width: 1024px) {
  /* the kicker's margin-top:auto is GONE with the hero stats (Sofia
     2026-08-18: it was one of the twin auto margins that centered the
     cluster against the stats row — alone it pinned the copy to the
     hero's foot). justify-content:center on the column now centers the
     cluster; the optical up-bias below stays. */
  .p-solution .sol-hero__copy { padding-top: 20px; }
}
.p-solution .sol-hero__id {
  display: flex;
  align-items: center;
  gap: 12px;
}
.p-solution .sol-hero__glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-md);
  /* stroke lives on the ::before ring below — a real white->blue gradient
     (the card-stroke rule) instead of a translucent border tinted by the
     fill's glow bleeding under it (background-clip: border-box) */
  border: none;
  background:
    radial-gradient(120% 120% at 20% 0%, color-mix(in oklab, var(--color-blue-500) 55%, transparent), transparent 70%),
    rgba(255, 255, 255, 0.04);
  color: var(--color-white);
}

@property --glyph-ring-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}
.p-solution .sol-hero__glyph::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 0.75px;
  /* white peak orbiting through blue — the registered angle is what
     animates, so the gradient travels smoothly around the hairline */
  /* grey-dominant ring with a passing blue glint: mid-grey base pulled a
     step toward grey-400, blue confined to a third of the orbit */
  --glyph-ring-grey: color-mix(in oklab, var(--color-grey-300) 40%, var(--color-grey-400));
  background: conic-gradient(
    from var(--glyph-ring-angle) at 50% 50%,
    var(--glyph-ring-grey) 0deg,
    var(--glyph-ring-grey) 120deg,
    var(--color-blue-500) 180deg,
    var(--glyph-ring-grey) 240deg,
    var(--glyph-ring-grey) 360deg
  );
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
  animation: glyph-ring-spin 10s linear infinite;
}
@keyframes glyph-ring-spin {
  to { --glyph-ring-angle: 360deg; }
}
@media (prefers-reduced-motion: reduce) {
  .p-solution .sol-hero__glyph::before { animation: none; }
}
.p-solution .sol-hero__glyph .ds-icon {
  width: 20px;
  height: 20px;
}
.p-solution .sol-hero__name {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tight);
  font-size: var(--fs-xl);
  color: var(--color-white);
}
.p-solution .sol-hero__title {
  margin-top: 28px;
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tighter);
  font-size: 10.5vw;
  line-height: 1.04;
  color: var(--color-white);
}
@media (min-width: 640px) { .p-solution .sol-hero__title { font-size: 6.6vw; } }
@media (min-width: 1024px) { .p-solution .sol-hero__title { font-size: clamp(40px, 4.3vw, 62px); } }
/* fixed two-line structure: the rotating word ends line 1, so its width
   never reflows the rest of the title */
.p-solution .sol-hero__title-line { display: block; }
.p-solution .sol-hero__sub {
  margin-top: 20px;
  max-width: 52ch;
  font-size: var(--fs-body);
  line-height: var(--leading-body);
  color: rgba(255, 255, 255, 0.72);
}

/* deepfake-defense: the sub sentence needs a wider seat to hold the 2-line
   cap at 1280 (measured 2026-08-17; the shared 52ch wraps it to 3) */
.p-solution--deepfake-defense .sol-hero__sub { max-width: 62ch; }
.p-solution .sol-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 32px;
}

/* the proof stats live inside the hero, pinned to the column's foot;
   hairline verticals divide them (structural 1px, the proof-strip idiom) */
.p-solution .sol-hero__stats {
  display: flex;
  flex-wrap: wrap;
  gap: 24px 40px;
  margin-top: auto;
  padding-top: 48px;
}
/* the row carries at most two stats (SolutionPage slices) — equal flexible
   columns so long captions wrap inside their stat instead of stacking the
   row (Sofia, 2026-07-31: three wrapped unevenly, "reduce to 2 stats") */
.p-solution .sol-hero__stat {
  /* columns hug their caption so short caps ("countries supported") hold
     ONE line (Sofia, 2026-08-05); 320px still wraps genuinely long ones */
  flex: 0 1 auto;
  min-width: 0;
  max-width: 320px;
}
.p-solution .sol-hero__stat + .sol-hero__stat {
  border-left: 1px solid var(--color-tint-white-10);
  padding-left: 40px;
}
.p-solution .sol-hero__stat-value {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tight);
  font-size: 30px;
  line-height: 1;
  color: var(--color-white);
  font-variant-numeric: tabular-nums;
}
.p-solution .sol-hero__stat-cap {
  margin-top: 8px;
  font-size: var(--fs-sm);
  line-height: var(--leading-snug);
  color: rgba(255, 255, 255, 0.55);
  /* captions wrap inside their stat column — nowrap overflowed the divider
     once longer outcome-brief captions arrived (Sofia, 2026-07-31) */
}

/* rotating qualifier — an inline-grid stack. The browser handles the
   baseline natively (an inline-grid baseline-aligns on its first item),
   the slot is as wide as the widest word by construction, and the words
   crossfade with a micro-drift. No measurement, no clipping, no way to
   misalign. */
.p-solution .sol-hero__swap {
  display: inline-grid;
  white-space: nowrap;
}
/* sequential swap: the leaving word exits fast, the entering one arrives
   after a short beat — the two never overlap into a ghosted jumble */
.p-solution .sol-hero__swap-word {
  grid-area: 1 / 1;
  justify-self: start;
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 0.25s ease,
    transform 0.3s ease;
  pointer-events: none;
}
.p-solution .sol-hero__swap-word.is-active {
  opacity: 0.5;
  transform: none;
  transition:
    opacity 0.45s ease 0.22s,
    transform 0.55s cubic-bezier(0.22, 1, 0.36, 1) 0.22s;
}
.p-solution .sol-hero__swap-word.is-leaving {
  opacity: 0;
  transform: translateY(-8px);
}
@media (prefers-reduced-motion: reduce) {
  .p-solution .sol-hero__swap-word { transition: none; transform: none; }
}
/* narrow screens: one line can't hold the widest word — stay static */
@media (max-width: 639px) {
  .p-solution .sol-hero__swap-word:not(:first-child) { display: none; }
}

/* hero stage: one full phone against a translucent frame + focused glow.
   The frame mirrors the how-it-works landing card (same column, same
   height), so the traveling phone crosses between twin frames. */
.p-solution .sol-hero__stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  /* trimmed (Sofia, 2026-08-05: the phone fan read too big) */
  min-height: min(54svh, 540px);
  /* same construction as the how-it-works landing card (48px of air around
     the in-flow phone), so both frames share the approved proportion */
  padding-block: 48px;
  /* centered on the row (Sofia, 2026-08-06: end-seating sank the fan to
     the card's foot on tall monitors — "the visual still looks very close
     to the bottom"); with the copy cluster's optical lift the two bands
     now share a middle */
  align-self: center;
}
/* the translucent backdrop rectangle retired (Sofia, 2026-08-05: "remove
   the square in the back") — the fan floats free on the aurora; the
   element stays in markup for the traveling-phone dissolve hook */
.p-solution .sol-hero__frame {
  position: absolute;
  inset: 36px 12% 8px;
  z-index: 1;
  border-radius: 24px;
  border: 0;
  background: transparent;
  transition: opacity 0.6s ease;
}
/* the hero frame dissolves while the phone travels to the how section */
.p-solution .sol-flow-wrap.is-hero-left .sol-hero__frame { opacity: 0; }
/* the fan: two dimmed phone silhouettes behind the hero phone (the
   reference stack). They dissolve as soon as the scroll starts, leaving
   the traveling phone alone for the journey. */
.p-solution .sol-hero__ghost {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 1;
  width: clamp(184px, 15vw, 228px);
  aspect-ratio: 24 / 50;
  padding: 8px;
  border-radius: 42px;
  border: 1px solid var(--color-grey-100);
  background: var(--color-white);
  filter: brightness(0.6);
  transition: opacity 0.5s ease, transform 0.65s cubic-bezier(0.22, 1, 0.36, 1);
}
.p-solution .sol-hero__ghost-screen {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  border-radius: 34px;
}
.p-solution .sol-hero__ghost--left {
  transform: translate(calc(-50% - 56%), calc(-50% + 64px)) rotate(-8deg) scale(0.88);
}
.p-solution .sol-hero__ghost--right {
  transform: translate(calc(-50% + 56%), calc(-50% + 64px)) rotate(8deg) scale(0.88);
}
/* scroll begins → the fan folds into the phone and dissolves */
.p-solution .sol-flow-wrap.is-scrolled .sol-hero__ghost { opacity: 0; }
.p-solution .sol-flow-wrap.is-scrolled .sol-hero__ghost--left {
  transform: translate(calc(-50% - 20%), calc(-50% + 20px)) rotate(-2deg) scale(0.84);
}
.p-solution .sol-flow-wrap.is-scrolled .sol-hero__ghost--right {
  transform: translate(calc(-50% + 20%), calc(-50% + 20px)) rotate(2deg) scale(0.84);
}
@media (max-width: 767px) {
  .p-solution .sol-hero__ghost { display: none; }
  /* phones drop the hero visual entirely — the copy and its two stats
     carry the hero; a third stat (some pages render one) hides too
     (Sofia, 2026-08-07 mobile pass) */
  .p-solution .sol-hero__stage { display: none; }
  .p-solution .sol-hero__stat:nth-child(n + 3) { display: none; }
  /* two stats sit SIDE BY SIDE in equal columns, so a long caption wraps to
     a second line inside its own column instead of stacking the row (which
     left the second stat with the horizontal divider's border + indent and
     read broken on deepfake-defense — Nacim, 2026-08-18). The vertical
     hairline divides the pair; the values top-align and captions wrap below. */
  .p-solution .sol-hero__stats {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: start;
    gap: 0;
  }
  .p-solution .sol-hero__stat { max-width: none; }
  .p-solution .sol-hero__stat + .sol-hero__stat { padding-left: 20px; }
}

.p-solution .sol-hero__phone { position: relative; z-index: 2; width: clamp(184px, 15vw, 228px); }
.p-solution .sol-hero__glow {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 580px;
  height: 580px;
  max-width: 140vw;
  transform: translate(-50%, -50%);
  border-radius: 999px;
  background: radial-gradient(closest-side, color-mix(in oklab, var(--color-blue-500) 30%, transparent), transparent 70%);
  animation: sol-glow-drift 30s ease-in-out infinite alternate;
  pointer-events: none;
}
@keyframes sol-glow-drift {
  from { transform: translate(calc(-50% - 20px), -50%); }
  to { transform: translate(calc(-50% + 20px), -50%); }
}
@media (prefers-reduced-motion: reduce) {
  .p-solution .sol-hero__glow { animation: none; }
}


/* shared abstracted bezel: hairline ring, top light, deep seat shadow */
.p-solution .sol-stage__frame {
  padding: 9px;
  border-radius: 42px;
  border: 1px solid var(--color-grey-100);
  background: var(--color-white);
  /* soft drop retired (Sofia, 2026-08-05: hard shadows only, site rule) */
}
.p-solution .sol-stage__screen {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 390 / 844;
  object-fit: cover;
  object-position: top center;
  border-radius: 34px;
}
.p-solution .sol-stage__deck { display: grid; }
.p-solution .sol-stage__deck .sol-stage__screen {
  grid-area: 1 / 1;
  opacity: 0;
  transition: opacity 0.85s ease-in-out;
}
.p-solution .sol-stage__deck .sol-stage__screen.is-active { opacity: 1; }
/* a "rich" screen is a container (base image + overlay) instead of a bare
   <img>, so a step can carry an animated glyph on top of its screen. */
.p-solution .sol-stage__screen--rich { position: relative; overflow: hidden; }
.p-solution .sol-stage__rich-base {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  border-radius: inherit;
}

/* ---------- 2 · how it works (light · pinned steps, traveling phone) ----
   The wrapper .sol-flow-wrap ties the hero and this section together with
   ONE sticky phone (compositor-driven — inherently smooth). Desktop JS
   adds .is-float: the in-line phones hide, this section grows to 380vh and
   pins, and scroll selects the active step (discrete states, eased CSS).
   Fallback: static in-line phones, click + auto-advance steps. */
.p-solution .sol-flow-wrap { position: relative; }
.p-solution .sol-how {
  background: var(--color-white);
  color: var(--color-foreground);
}
/* pin length scales with the walk: 28vh of scroll per step + one viewport
   (was 70vh/step — Sofia, 2026-08-07: "make the scroll much faster and
   smooth"; the walk now clears in less than half the scroll) */
.p-solution .sol-flow-wrap.is-float .sol-how { height: calc(100vh + 28vh * var(--sol-steps, 4)); }
.p-solution .sol-how__pin {
  position: relative;
  display: flex;
  align-items: center;
}
.p-solution .sol-flow-wrap.is-float .sol-how__pin {
  position: sticky;
  top: 0;
  height: 100svh;
}
.p-solution .sol-how__inner {
  display: grid;
  gap: 48px;
  width: 100%;
}
@media (min-width: 1024px) {
  .p-solution .sol-how__inner {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: 72px;
    align-items: center;
  }
}
.p-solution .sol-how__rail { min-width: 0; }
.p-solution .sol-how__steps {
  margin: 40px 0 0;
  padding: 0;
  list-style: none;
}
.p-solution .sol-how__item { border-top: 1px solid var(--color-border-light); }
.p-solution .sol-how__item:last-child { border-bottom: 1px solid var(--color-border-light); }
.p-solution .sol-how__step {
  position: relative;
  display: grid;
  grid-template-columns: 48px 1fr;
  gap: 16px;
  width: 100%;
  padding: 20px 8px;
  border: 0;
  background: none;
  text-align: left;
  font-family: var(--font-sans);
  cursor: pointer;
}
.p-solution .sol-how__num {
  padding-top: 4px;
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tight);
  font-size: var(--fs-body);
  line-height: 1.2;
  /* grey-400: the lightest token that clears WCAG 4.5:1 on white */
  color: var(--color-grey-400);
  font-variant-numeric: tabular-nums;
  transition: color 0.4s ease;
}
.p-solution .sol-how__step.is-active .sol-how__num { color: var(--color-blue); }
.p-solution .sol-how__name {
  display: block;
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tight);
  font-size: var(--fs-3xl);
  line-height: 1.2;
  /* grey-on-white: dimmed but WCAG-compliant on the white section */
  color: var(--color-grey-on-white);
  transition: color 0.4s ease;
}
.p-solution .sol-how__step:hover .sol-how__name { color: var(--color-grey-500); }
.p-solution .sol-how__step.is-active .sol-how__name { color: var(--color-black); }
/* the description expands only on the active step */
.p-solution .sol-how__reveal {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}
.p-solution .sol-how__step.is-active .sol-how__reveal { grid-template-rows: 1fr; }
.p-solution .sol-how__line {
  display: block;
  overflow: hidden;
  min-height: 0;
  max-width: 52ch;
  font-size: var(--fs-sm);
  line-height: var(--leading-body);
  color: var(--color-grey-on-white);
  opacity: 0;
  transition: opacity 0.45s ease 0.1s;
}
.p-solution .sol-how__step.is-active .sol-how__line {
  opacity: 1;
  padding-top: 10px;
}
/* float mode: every description reserves the SAME height, so the rail's
   total height never changes — the title holds still and a collapse+expand
   pair reads as one synchronized, jump-free motion */
.p-solution .sol-flow-wrap.is-float .sol-how__reveal {
  display: block;
  height: 0;
  overflow: hidden;
  transition: height 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}
.p-solution .sol-flow-wrap.is-float .sol-how__step.is-active .sol-how__reveal {
  height: 78px;
}
.p-solution .sol-flow-wrap.is-float .sol-how__line { max-width: 54ch; }

/* the progress-underline "loader" is RETIRED in every mode (Sofia,
   2026-08-07: "do not use a scroll loader… there's no need to have a
   loader") — the scrubbed float bar, the is-done wayfinding bars, and
   the static timed fill are all gone; the lit number + title and the
   expanded body carry the active state. The bar/fill markup stays in
   HowItWorks/pages for now and simply renders nothing. */
.p-solution .sol-how__bar { display: none; }

/* use-case phones pair every step with ITS screen (Sofia, 2026-08-07:
   "otherwise the user can't see the step and the visual") — the shots
   are BUILT BY solution-hero.js, which moves the deck's screens into
   the steps and stamps .is-paired on the section. The shared stage
   hides only then (no-JS keeps today's layout); the open descriptions
   and the retired progress bar apply to every one-column walk. */
.p-solution .sol-how__shot {
  display: flex;
  justify-content: center;
  padding: 8px 0 28px;
}
.p-solution .sol-how__shot-phone { width: min(58vw, 224px); }
/* a paired DASHBOARD step: the desktop console/window scaled to fill the
   column (site.js dashFit sets width + zoom) instead of the phone bezel.
   The moved node is normally an absolute, opacity-0 crossfade layer of the
   shared stage — reset it to a static, visible, self-centering block so it
   sits directly under its step copy at the reference proportion. */
.p-solution .sol-how__shot--dash {
  display: block;
  padding: 8px 0 28px;
}
/* generic — the moved console is the shot's only child, whatever its class
   (.wfs-stage--step, .wfd, .inw, …). The 0,3,0 selector clears any per-deck
   absolute/hidden crossfade state without each page re-declaring it. */
.p-solution .sol-how.is-paired .sol-how__shot--dash > * {
  position: static;
  left: auto;
  top: auto;
  transform: none;
  opacity: 1;
  visibility: visible;
  animation: none;
  margin-inline: auto;
}
.p-solution .sol-how.is-paired .sol-how__stage { display: none; }
@media (max-width: 1023px) {
  .p-solution .sol-how__reveal { grid-template-rows: 1fr; }
  .p-solution .sol-how__line {
    opacity: 1;
    padding-top: 10px;
  }
  .p-solution .sol-how__bar { display: none; }
  .p-solution .sol-how__name { color: var(--color-black); }
  .p-solution .sol-how__num { color: var(--color-blue); }
}

/* the landing frame: soft tinted card the traveling phone settles into */
.p-solution .sol-how__stage {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 80%;
  margin-inline: auto;
  padding: 48px 24px;
  transform: translateY(24px);
  transition: opacity 0.6s ease;
  border-radius: 24px;
  border: 1px solid var(--color-border-light);
  background:
    radial-gradient(120% 100% at 50% 0%, color-mix(in oklab, var(--color-blue-100) 80%, transparent), transparent 70%),
    var(--color-background);
  min-height: min(64svh, 660px);
}
.p-solution .sol-how__phone {
  /* matches the trimmed hero/traveling phones (Sofia, 2026-08-05 ×2);
     soft drop retired (hard shadows only, site rule) */
  width: clamp(184px, 15vw, 228px);
  box-shadow: inset 0 1px 0 rgba(249, 249, 249, 0.08);
}

/* ---------- the traveling phone (desktop + motion only) ----------
   A full-height overlay rail over the wrapper; the inner is sticky for
   100svh, so the phone stays viewport-centered from the hero until the
   how section releases — pure CSS sticky, compositor-smooth. */
.p-solution .sol-phonecol { display: none; }
.p-solution .sol-flow-wrap.is-float .sol-phonecol {
  display: block;
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
}
.p-solution .sol-flow-wrap.is-float .sol-phonecol__inner {
  position: sticky;
  top: 0;
  height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 72px;
  align-items: center;
  margin-inline: auto;
  max-width: var(--container-large);
  padding-inline: 24px;
}
.p-solution .sol-phonecol__slot {
  grid-column: 2;
  display: flex;
  justify-content: center;
  /* optical nudge (Nacim): the phone rides 20px below true center */
  transform: translateY(20px);
}
.p-solution .sol-phonecol__phone {
  /* matches the trimmed hero/how phones (Sofia, 2026-08-05 ×2) */
  width: clamp(184px, 15vw, 228px);
}
/* frame handoff: in float mode the how frame stays hidden until the
   traveling phone touches it — then it emerges and SETTLES into place
   (a soft rise) as the phone lands, mirroring the hero frame's dissolve */
/* frame handoff applies ONLY to solution pages with a traveling phone.
   Standalone HowItWorks has no traveler, so `is-how-near` is never set and
   these rules would pin the stage at opacity:0 forever — exclude standalone
   (mirrors the .sol-phone-inline guard below) and let it use the normal
   [data-reveal] reveal instead. */
.p-solution .sol-flow-wrap.is-float:not([data-sol-standalone]) .sol-how__stage {
  opacity: 0;
  transform: translateY(56px);
  transition: opacity 0.4s ease, transform 0.5s ease;
}
.p-solution .sol-flow-wrap.is-float.is-how-near:not([data-sol-standalone]) .sol-how__stage {
  opacity: 1;
  transform: translateY(24px);
  transition:
    opacity 0.7s ease 0.3s,
    transform 0.85s cubic-bezier(0.22, 1, 0.36, 1) 0.3s;
}

/* float mode hides the in-line phones — the traveling one is THE phone */
/* solution pages hide the inline phones in float (the traveling phone
   covers them); standalone walks have no traveler, so theirs stays */
.p-solution .sol-flow-wrap.is-float:not([data-sol-standalone]) .sol-phone-inline { visibility: hidden; }

/* chapter seams — the home's rounded-curtain motif (x3.css / about.css,
   Sofia 2026-07-31: "apply the rounded corner styles… like the home,
   about"): every change of ground (bright ⇄ dark) opens on rounded top
   corners sliding over the closing chapter; tone-adjacent neighbors
   (how→nothing, threat→caps, deploy→life→social) stay flush. */
.p-solution .sol-threat,
.p-solution .sol-deploy,
.p-solution .sol-req {
  position: relative;
  margin-top: -20px;
  border-top-left-radius: 20px;
  border-top-right-radius: 20px;
}
@media (min-width: 768px) {
  .p-solution .sol-threat,
  .p-solution .sol-deploy,
  .p-solution .sol-req {
    margin-top: -32px;
    border-top-left-radius: 32px;
    border-top-right-radius: 32px;
  }
}
/* Hero → first section: the hero is a self-contained rounded card inset by
   its gutter on all four sides. The seam pattern above pulls neighbors UP over
   the previous section (rounded corners sliding over it) — but the first
   section must NOT slide over the hero, or it eats the card's rounded bottom
   and the two read as one merged block (Nacim, 2026-08-19: "se mezclaron las
   dos secciones … que se vea como card, los mismos espacios en los 4 lados").
   So it clears the hero instead: no negative pull, its own flat top, and a gap
   equal to the hero gutter — the card closes on all four sides with matching
   space, then the next section begins. */
.p-solution .sol-hero + * {
  /* the hero already carries its 12px bottom gutter (padding below the
     aurora), so margin-top:0 leaves exactly that 12px — equal to the other
     three sides — instead of the seam's negative pull */
  margin-top: 0;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

/* the certs band and the FAQ are the unified TrustBand / FaqSection
   components now — their seams ride the components' own --seam modifier
   (components/trust-band.css · components/faq-section.css) */

/* ---------- 2 · problem stats (dark · subtle red wash = danger) ---------- */
.p-solution .sol-threat {
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  background:
    radial-gradient(70% 90% at 84% -12%, color-mix(in oklab, var(--color-red-500) 16%, transparent), transparent 62%),
    radial-gradient(55% 75% at 6% 110%, color-mix(in oklab, var(--color-red-500) 10%, transparent), transparent 64%),
    color-mix(in oklab, var(--color-black) 96%, var(--color-red-500));
  color: var(--color-white);
}
.p-solution .sol-kicker--threat {
  color: color-mix(in oklab, var(--color-red-400) 75%, var(--color-white));
}
/* the shared sol-flow hover glow goes red here — danger, not brand blue */
.p-solution .sol-threat .sol-flow::before {
  background:
    radial-gradient(42% 60% at 18% 30%, color-mix(in oklab, var(--color-red-500) 55%, transparent), transparent 62%),
    radial-gradient(36% 55% at 78% 18%, color-mix(in oklab, var(--color-red-400) 40%, transparent), transparent 60%),
    radial-gradient(52% 72% at 62% 85%, color-mix(in oklab, var(--color-red-500) 45%, transparent), transparent 65%),
    radial-gradient(28% 42% at 38% 68%, color-mix(in oklab, var(--color-red-300) 14%, transparent), transparent 60%);
}
.p-solution .sol-threat__grid {
  display: grid;
  gap: 1px;
  margin-top: 48px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 16px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.12);
}
@media (min-width: 640px) {
  .p-solution .sol-threat__grid { grid-template-columns: 1fr 1fr; }
  .p-solution .sol-threat__grid .sol-threat__cell:last-child:nth-child(odd) { grid-column: 1 / -1; }
}
@media (min-width: 1024px) {
  .p-solution .sol-threat__grid {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
  }
  .p-solution .sol-threat__grid .sol-threat__cell:last-child:nth-child(odd) { grid-column: auto; }
}
.p-solution .sol-threat__cell {
  display: flex;
  flex-direction: column;
  padding: 28px 24px 24px;
  background: color-mix(in oklab, var(--color-black) 94%, var(--color-red-500));
}
.p-solution .sol-threat__cell:hover .sol-threat__cap { color: rgba(255, 255, 255, 0.85); }
.p-solution .sol-threat__cell:hover .sol-threat__src { color: rgba(255, 255, 255, 0.5); }
.p-solution .sol-threat__value {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tighter);
  font-size: 44px;
  line-height: 1;
  color: var(--color-white);
  font-variant-numeric: tabular-nums;
}
@media (min-width: 768px) { .p-solution .sol-threat__value { font-size: 52px; } }
.p-solution .sol-threat__cap {
  margin-top: 12px;
  font-size: var(--fs-sm);
  line-height: var(--leading-snug);
  color: rgba(255, 255, 255, 0.65);
  text-wrap: pretty;
  transition: color 0.3s ease;
}
.p-solution .sol-threat__src {
  margin-top: auto;
  padding-top: 20px;
  font-size: var(--fs-xs);
  letter-spacing: var(--track-wide);
  color: rgba(255, 255, 255, 0.35);
  transition: color 0.3s ease;
}

/* ---------- 4 · the foundation (bright split — the home why-incode
   trionn composition, Sofia 2026-08-05) ----------
   Sticky rail left (kicker · title · intro), the three intelligence
   panels scrolling right of a full-height hairline: canonical aurora
   plates carrying abstract white line scenes (the home wsc vocabulary,
   sol-scoped as ssc-*), name + line + Learn more beneath. The
   orchestration platform closes the feed as a hairline row. The dark
   three-card + merge-connector stack lives in git. */
.p-solution .sol-caps {
  border-top: 1px solid var(--color-border-light);
  background: var(--color-background);
  color: var(--color-foreground);
}
@media (min-width: 1024px) {
  .p-solution .sol-caps__grid {
    display: grid;
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.3fr);
    gap: 64px;
    align-items: start;
  }
  /* the rail pins under the fixed header while the feed scrolls by */
  .p-solution .sol-caps__rail { position: sticky; top: 120px; }
  .p-solution .sol-caps__feed {
    border-left: 1px solid var(--color-border-light);
    padding-left: 64px;
  }
}
.p-solution .sol-caps__title {
  margin-top: 16px;
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tighter);
  font-size: 26px;
  line-height: 1.08;
  color: var(--color-black);
  text-wrap: balance;
}
@media (min-width: 640px) { .p-solution .sol-caps__title { font-size: 34px; } }
@media (min-width: 1280px) { .p-solution .sol-caps__title { font-size: 40px; } }
.p-solution .sol-caps__intro {
  margin-top: 16px;
  max-width: 44ch;
  font-size: var(--fs-body);
  line-height: var(--leading-body);
  color: var(--color-grey-on-white);
}
.p-solution .sol-cap {
  display: block;
  margin-top: 48px;
  color: inherit;
  text-decoration: none;
}
.p-solution .sol-cap:first-child { margin-top: 40px; }
@media (min-width: 1024px) {
  .p-solution .sol-cap { margin-top: 72px; }
  .p-solution .sol-cap:first-child { margin-top: 0; }
}
.p-solution a.sol-cap:focus-visible,
.p-solution .sol-caps__orch:focus-visible {
  outline: 2px solid var(--color-blue);
  outline-offset: 4px;
  border-radius: 8px;
}
/* the aurora media plate: the layer's icon floats centered (the home
   product-card glyph idiom; the abstract line scenes retired same day,
   Sofia 2026-08-05: "icons only") */
.p-solution .sol-cap__glyph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.p-solution .sol-cap__media {
  position: relative;
  /* shorter plate (Sofia, 2026-08-05 ×2: "smaller … vertically"):
     16:10 → 2:1 → 2.4:1 */
  aspect-ratio: 2.4 / 1;
  border-radius: 16px;
  overflow: hidden;
}
.p-solution .sol-cap__glyph-icon {
  /* larger than the home product-card 64px: these plates run much wider */
  width: 96px;
  height: 96px;
  -webkit-mask-size: contain;
  mask-size: contain;
  color: rgba(255, 255, 255, 0.9);
  transition: transform 0.5s var(--ease-out-expo);
}
.p-solution a.sol-cap:hover .sol-cap__glyph-icon { transform: scale(1.08); }
.p-solution .sol-cap__body { margin-top: 24px; }
.p-solution .sol-cap__name {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tighter);
  font-size: var(--fs-2xl);
  line-height: 1.08;
  color: var(--color-black);
}
@media (min-width: 900px) { .p-solution .sol-cap__name { font-size: 28px; } }
.p-solution .sol-cap__line {
  margin-top: 8px;
  max-width: 56ch;
  font-size: var(--fs-body);
  line-height: var(--leading-snug);
  color: var(--color-grey-on-white);
}
.p-solution .sol-cap__learn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 14px;
  font-size: var(--fs-xs);
  letter-spacing: var(--track-wide);
  color: var(--color-grey-on-white);
  transition: color 0.25s ease;
}
.p-solution .sol-cap__learn svg { transition: transform 0.25s ease; }
.p-solution a.sol-cap:hover .sol-cap__learn { color: var(--color-blue); }
.p-solution a.sol-cap:hover .sol-cap__learn svg { transform: translate(2px, -2px); }
/* the rail action: the orchestration row retired (Sofia, 2026-08-05) —
   its label + href live on as the rail's Explore-the-platform link
   (the home rail's See-more idiom) */
.p-solution .sol-caps__more {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 28px;
  padding-block: 6px;
  font-size: var(--fs-sm);
  letter-spacing: var(--track-widest);
  color: var(--color-grey-on-white);
  transition: color 0.2s ease;
}
.p-solution .sol-caps__more-label {
  text-decoration: underline;
  text-underline-offset: 5px;
  text-decoration-color: color-mix(in oklab, currentColor 45%, transparent);
  transition: text-decoration-color 0.2s ease;
}
.p-solution .sol-caps__more:hover { color: var(--color-black); }
.p-solution .sol-caps__more:hover .sol-caps__more-label { text-decoration-color: currentColor; }

/* ---------- 5 · integration paths (bright · SPLIT: copy left, visual right)
   -----------------------------------------------------------------------
   Left column: kicker + a tab switcher + the active mode's tag / title /
   description (real room for copy). Right column: a white→blue rounded panel
   with the phone (cut at the panel's bottom edge) and, for Customization, the
   real Incode Studio controls cut at the panel edges (like the reference).
   Tabs switch the mode; it also auto-advances while in view. */
.p-solution .sol-deploy {
  position: relative;
  background: var(--color-white);
  color: var(--color-foreground);
}
.p-solution .sol-deploy__inner {
  display: grid;
  gap: 40px;
}
@media (min-width: 1024px) {
  .p-solution .sol-deploy__inner {
    grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
    gap: 64px;
    align-items: center;
  }
}

/* --- LEFT: copy ---
   Hierarchy: a top rule line carries the eyebrow (left) + the switcher as
   underline tabs (right); the title + description sit below it. Lighter and
   more editorial than a pill segmented control. */
.p-solution .sol-deploy__copy { min-width: 0; }
.p-solution .sol-deploy__topline {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--color-border-light);
}
.p-solution .sol-deploy__modes {
  display: flex;
  gap: 22px;
}
.p-solution .sol-deploy__mode {
  position: relative;
  padding: 0 0 3px;
  border: 0;
  background: none;
  color: var(--color-grey-400);
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.3s ease;
}
.p-solution .sol-deploy__mode::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -17px;
  height: 2px;
  background: var(--color-blue);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}
.p-solution .sol-deploy__mode:hover { color: var(--color-grey-500); }
.p-solution .sol-deploy__mode.is-active { color: var(--color-black); }
.p-solution .sol-deploy__mode.is-active::after { transform: scaleX(1); }

/* panels stack in one grid cell and crossfade — height = tallest, no jump */
.p-solution .sol-deploy__panels { display: grid; margin-top: 28px; }
.p-solution .sol-deploy__panel {
  grid-area: 1 / 1;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.45s ease, transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}
.p-solution .sol-deploy__panel.is-active { opacity: 1; transform: none; pointer-events: auto; }
.p-solution .sol-deploy__tag {
  display: inline-block;
  padding: 5px 12px;
  border: 1px solid var(--color-blue-200);
  border-radius: 999px;
  background: var(--color-blue-100);
  font-size: var(--fs-xs);
  letter-spacing: var(--track-wide);
  color: var(--color-blue);
}
.p-solution .sol-deploy__title {
  margin-top: 0;
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tight);
  font-size: clamp(28px, 3vw, 40px);
  line-height: 1.1;
  color: var(--color-black);
}
.p-solution .sol-deploy__desc {
  margin-top: 16px;
  max-width: 46ch;
  font-size: var(--fs-xl);
  line-height: var(--leading-body);
  color: var(--color-grey-on-white);
}
.p-solution .sol-deploy__cta { margin-top: 28px; }
/* use-case phones seat the CTA below the visual instead (Sofia,
   2026-08-07 mobile pass): solution-hero.js moves each panel's button
   into a .sol-deploy__mcta slot after the stage; the slots swap with
   the mode switch like panels (they carry data-sol-deploy-panel) */
.p-solution .sol-deploy__mcta { margin-top: 24px; }
.p-solution .sol-deploy__mcta-slot { display: none; }
.p-solution .sol-deploy__mcta-slot.is-active {
  display: flex;
  justify-content: center;
}

/* --- RIGHT: the visual panel ---
   The stage is overflow-VISIBLE so floaters can spill past the panel; the
   inner .sol-deploy__panel is the clip box (rounded, cuts the phone). */
.p-solution .sol-deploy__stage {
  position: relative;
  overflow: visible;
  min-height: min(72svh, 620px);
}
.p-solution .sol-deploy__clip {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 24px;
}
.p-solution .sol-deploy__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  border: 1px solid var(--color-border-light);
  border-radius: 24px;
  background:
    radial-gradient(58% 44% at 50% 116%, color-mix(in oklab, var(--color-blue-500) 24%, transparent), transparent 64%),
    linear-gradient(180deg, var(--color-white) 6%, var(--color-blue-100) 100%);
}
/* the per-mode centerpieces HARD-SWAP (no fade) — one illustration cuts to
   the other instantly (Nacim, 2026-07-30) */
.p-solution .sol-deploy__phone,
.p-solution .sol-deploy__code { display: none; }
.p-solution .sol-deploy__phone.is-active,
.p-solution .sol-deploy__code.is-active { display: block; }

/* Customization: the phone, centered and sized to fit FULLY in the panel so
   the "Take selfie" button shows — that's what the Corner radius control
   references (Nacim, 2026-07-30). Smaller than the cut-off version. */
.p-solution .sol-deploy__phone {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 1;
  /* the stage shrinks with short windows (min(72svh, 620px)) while a
     fixed-width phone kept its height — flush corners on laptop-height
     viewports (Sofia, 2026-08-05). The svh term scales the phone with
     the stage so it always keeps ~48px of air above and below. */
  width: min(clamp(208px, 18vw, 262px), 33svh - 40px);
  transform: translate(-50%, -50%);
  /* soft drop retired (hard shadows only) */
  box-shadow: inset 0 1px 0 rgba(249, 249, 249, 0.08);
}
/* the ONLY edit to the screen: the customer's "Loop" logo sits on a
   white-on-white patch over the baked "incode" wordmark */
.p-solution .sol-deploy__logo-swap {
  position: absolute;
  top: 9.1%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 18px;
  background: var(--color-white);
  border-radius: 8px;
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--color-purple-500);
}

/* Native SDKs: a bespoke drop-in code card, centered in the panel */
.p-solution .sol-deploy__code {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 1;
  width: min(86%, 400px);
  transform: translate(-50%, -50%) scale(0.98);
  border-radius: var(--radius-lg);
  background: var(--color-grey-600);
  /* soft drop retired (hard shadows only) */
  overflow: hidden;
}
.p-solution .sol-deploy__code.is-active { transform: translate(-50%, -50%) scale(1); }
.p-solution .sol-deploy__code-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.p-solution .sol-deploy__code-dots { display: inline-flex; gap: 6px; }
.p-solution .sol-deploy__code-dots i {
  width: 10px;
  height: 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
}
.p-solution .sol-deploy__code-tabs {
  display: inline-flex;
  gap: 6px;
  margin-left: auto;
}
.p-solution .sol-deploy__code-tabs span {
  padding: 4px 12px;
  border-radius: 999px;
  font-size: var(--fs-xs);
  font-weight: 500;
  color: rgba(255, 255, 255, 0.55);
}
.p-solution .sol-deploy__code-tabs span.is-active {
  background: var(--color-blue);
  color: var(--color-white);
}
.p-solution .sol-deploy__code-body {
  padding: 20px 18px 24px;
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.86);
}
.p-solution .sol-deploy__code-ind { padding-left: 20px; }
.p-solution .sol-deploy__code .tok-key { color: var(--color-blue-200); }
.p-solution .sol-deploy__code .tok-type { color: var(--color-white); font-weight: 500; }
.p-solution .sol-deploy__code .tok-fn { color: var(--color-blue-200); }
.p-solution .sol-deploy__code .tok-str { color: var(--color-green-flow); }
.p-solution .sol-deploy__code .tok-punc { color: rgba(255, 255, 255, 0.45); }

/* mode-specific floating elements */
.p-solution .sol-deploy__layer {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}
.p-solution .sol-deploy__float {
  position: absolute;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border: 1px solid var(--color-border-light);
  border-radius: 999px;
  background: var(--color-white);
  /* soft drop retired (hard shadows only) */
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  color: var(--color-grey-500);
  white-space: nowrap;
  opacity: 0;
  transform: translateY(12px) scale(0.96);
  /* NO transition by default → on a mode switch the bubbles cut instantly
     (matching the hard illustration swap). The transition is defined ONLY on
     the shown state below, so it applies on entrance, not on exit. */
}
/* the bubbles rise in — staggered, one after another — once the stage scrolls
   into view (site.js adds .is-revealed). Switching back re-triggers it. */
.p-solution .sol-deploy__stage.is-revealed .sol-deploy__layer.is-active .sol-deploy__float {
  opacity: 1;
  transform: none;
  transition: opacity 0.5s ease, transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.p-solution .sol-deploy__stage.is-revealed .sol-deploy__layer.is-active .sol-deploy__float:nth-child(1) { transition-delay: 0.1s; }
.p-solution .sol-deploy__stage.is-revealed .sol-deploy__layer.is-active .sol-deploy__float:nth-child(2) { transition-delay: 0.24s; }
.p-solution .sol-deploy__stage.is-revealed .sol-deploy__layer.is-active .sol-deploy__float:nth-child(3) { transition-delay: 0.38s; }
.p-solution .sol-deploy__stage.is-revealed .sol-deploy__layer.is-active .sol-deploy__float:nth-child(4) { transition-delay: 0.52s; }

/* studio floats opt OUT of the blanket reveal: they pop on their own
   beats (is-c1/c3/c5), and only while the Customization layer is active —
   switching to the SDK tab removes them with the layer. */
.p-solution .sol-deploy__stage.is-revealed .sol-deploy__layer.is-active .sol-deploy__float--studio {
  opacity: 0;
  transform: translateY(14px) scale(0.86);
  transition: opacity 0.4s ease, transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: 0s;
}
.p-solution .sol-deploy.is-c1 .sol-deploy__stage.is-revealed .sol-deploy__layer.is-active .sol-deploy__float--l,
.p-solution .sol-deploy.is-c3 .sol-deploy__stage.is-revealed .sol-deploy__layer.is-active .sol-deploy__float--tr,
.p-solution .sol-deploy.is-c5 .sol-deploy__stage.is-revealed .sol-deploy__layer.is-active .sol-deploy__float--bl,
.p-solution .sol-deploy.is-c5 .sol-deploy__stage.is-revealed .sol-deploy__layer.is-active .sol-deploy__float--br {
  opacity: 1;
  transform: none;
  transition-delay: 0s;
}
.p-solution .sol-deploy.is-c5 .sol-deploy__stage.is-revealed .sol-deploy__layer.is-active .sol-deploy__float--br { transition-delay: 0.16s; }

/* Incode Studio UI-customization controls (customization state only) — the
   real sdm-opt component, lifted from /platform/ui-customization/
   (ui-customization-studio.css) so the floaters ARE Studio's controls. */
.p-solution .sol-deploy__float--studio {
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border-radius: var(--radius-lg);
}
.p-solution .sol-deploy__ctl-label {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--color-grey-600);
}
.p-solution .sol-deploy .sdm-opts { display: flex; gap: 8px; }
.p-solution .sol-deploy .sdm-opt {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 40px;
  padding: 0 10px;
  border: 1px solid var(--color-grey-100);
  border-radius: var(--radius-lg);
  background: var(--color-white);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  white-space: nowrap;
  color: var(--color-grey-500);
}
.p-solution .sol-deploy .sdm-opt.is-active {
  border-color: var(--color-blue-500);
  box-shadow: 0 0 0 3px var(--color-blue-100);
  color: var(--color-grey-600);
}
/* staged selections: color + logo controls start on the Incode defaults
   and flip on their own beat; font + radius show the brand picks from the
   moment they pop (they never flip) */
.p-solution .sol-deploy .sdm-opt {
  transition: border-color 0.35s ease, box-shadow 0.35s ease, color 0.35s ease;
}
.p-solution .sol-deploy .sol-deploy__float--l .sdm-opt[data-sel="a"],
.p-solution .sol-deploy .sol-deploy__float--tr .sdm-opt[data-sel="a"],
.p-solution .sol-deploy .sol-deploy__float--bl .sdm-opt[data-sel="b"],
.p-solution .sol-deploy .sol-deploy__float--br .sdm-opt[data-sel="b"],
.p-solution .sol-deploy.is-c2 .sol-deploy__float--l .sdm-opt[data-sel="b"],
.p-solution .sol-deploy.is-c4 .sol-deploy__float--tr .sdm-opt[data-sel="b"] {
  border-color: var(--color-blue-500);
  box-shadow: 0 0 0 3px var(--color-blue-100);
  color: var(--color-grey-600);
}
.p-solution .sol-deploy.is-c2 .sol-deploy__float--l .sdm-opt[data-sel="a"],
.p-solution .sol-deploy.is-c4 .sol-deploy__float--tr .sdm-opt[data-sel="a"] {
  border-color: var(--color-grey-100);
  box-shadow: none;
  color: var(--color-grey-500);
}
.p-solution .sol-deploy .sdm-opt svg { display: block; flex-shrink: 0; }
/* color swatch inside an option */
.p-solution .sol-deploy .sdm-opt i {
  width: 18px;
  height: 18px;
  border-radius: 6px;
  border: 1px solid rgba(0, 0, 0, 0.06);
}
.p-solution .sol-deploy__sw--blue { background: var(--color-blue-500); }
.p-solution .sol-deploy__sw--purple { background: var(--color-purple-500); }
.p-solution .sol-deploy__sw--green { background: var(--color-green-500); }
.p-solution .sol-deploy__sw--red { background: var(--color-red-brand); }
.p-solution .sol-deploy__sw--yellow { background: var(--color-yellow-500); }
.p-solution .sol-deploy__sw--teal { background: var(--color-green-flow); }
.p-solution .sol-deploy__sw--deep { background: var(--color-red-600); }
.p-solution .sol-deploy__sw--ink { background: var(--color-grey-500); }
/* corner-radius glyph inside an option (top-left L, radius = the option) */
.p-solution .sol-deploy .sdm-opt b {
  width: 15px;
  height: 15px;
  border: 1.5px solid currentColor;
  border-right: 0;
  border-bottom: 0;
  border-top-left-radius: var(--sdm-glyph, 3px);
}
.p-solution .sol-deploy__glyph--round { --sdm-glyph: 8px; }
.p-solution .sol-deploy__glyph--soft { --sdm-glyph: 5px; }
.p-solution .sol-deploy__glyph--sharp { --sdm-glyph: 2px; }

/* native platform bar (native state only) — one bar, not scattered bubbles */
.p-solution .sol-deploy__float--bar {
  gap: 4px;
  padding: 5px;
}
.p-solution .sol-deploy__bar-seg {
  padding: 7px 16px;
  border-radius: 999px;
  color: var(--color-grey-400);
  font-weight: 500;
  transition: background 0.35s ease, color 0.35s ease;
}
.p-solution .sol-deploy__bar-seg.is-active {
  background: var(--color-blue);
  color: var(--color-white);
}
.p-solution .sol-deploy__float--platforms {
  top: 12%;
  left: 50%;
  transform: translateX(-50%) translateY(10px) scale(0.96);
}
.p-solution .sol-deploy__layer.is-active .sol-deploy__float--platforms {
  transform: translateX(-50%);
}

/* float positions — pulled comfortably INSIDE the panel (Sofia,
   2026-08-05: the floats read tight against the card's corners; give
   the sides real air). Only the customization layer uses these. */
.p-solution .sol-deploy__float--l  { top: 22%; left: 8%; }
.p-solution .sol-deploy__float--tr { top: 14%; right: 8%; }
.p-solution .sol-deploy__float--bl { top: 62%; left: 9%; }
.p-solution .sol-deploy__float--br { top: 64%; right: 8%; }

/* --- mobile (<1024): the split stacks; keep the phone / code card, drop the
   side Studio controls (they'd overflow a full-width panel) --- */
@media (max-width: 1023px) {
  .p-solution .sol-deploy__stage { min-height: min(64svh, 540px); }
  .p-solution .sol-deploy__float--studio { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .p-solution .sol-deploy__float,
  .p-solution .sol-deploy__panel,
  .p-solution .sol-deploy__phone,
  .p-solution .sol-deploy__code { transition: none; }
}

/* ---------- 6 · proof (light · one designed card) ----------
   RETIRED 2026-08-12 (Sofia: unify on the canonical ProofBand —
   components/proof-band.css). SolutionPage.astro now renders <ProofBand>;
   no markup emits these classes. Rules kept for git archaeology only. */
.p-solution .sol-social {
  background: var(--color-white);
  color: var(--color-foreground);
  border-top: 1px solid var(--color-border-light);
}
/* head: title top-left, logo label bottom-aligned over the wall.
   Same column template as the split below so title sits over the stats and
   the label sits over the logo grid. */
.p-solution .sol-social__head {
  display: grid;
  gap: 16px;
  margin-bottom: 40px;
}
@media (min-width: 900px) {
  .p-solution .sol-social__head {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: 72px;
    align-items: end;
  }
}
/* split: billboard ratios left, 3×3 client wall right — tops aligned */
.p-solution .sol-social__split {
  display: grid;
  gap: 48px;
}
@media (min-width: 900px) {
  .p-solution .sol-social__split {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: 72px;
    align-items: start;
  }
}
.p-solution .sol-social__stats {
  display: flex;
  flex-direction: column;
  gap: 32px;
}
.p-solution .sol-social__value {
  display: flex;
  align-items: baseline;
  gap: 14px;
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tighter);
  font-size: 64px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
@media (min-width: 768px) { .p-solution .sol-social__value { font-size: 80px; } }
.p-solution .sol-social__rest {
  font-size: 26px;
  color: var(--color-grey-400);
}
@media (min-width: 768px) { .p-solution .sol-social__rest { font-size: 30px; } }
.p-solution .sol-social__cap {
  margin-top: 10px;
  max-width: 32ch;
  font-size: var(--fs-body);
  line-height: var(--leading-snug);
  color: var(--color-grey-on-white);
}
/* the client wall — a hairline 3×3 matrix, dividers only on the inside */
.p-solution .sol-social__label {
  font-size: var(--fs-sm);
  color: var(--color-grey-on-white);
}
.p-solution .sol-social__logos {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--color-border-light);
  border-radius: 16px;
  overflow: hidden;
  background: var(--color-white);
}
.p-solution .sol-social__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 96px;
  padding: 20px;
  border-top: 1px solid var(--color-border-light);
  border-left: 1px solid var(--color-border-light);
}
.p-solution .sol-social__logo:nth-child(-n + 3) { border-top: none; }
.p-solution .sol-social__logo:nth-child(3n + 1) { border-left: none; }
.p-solution .sol-social__logo img {
  max-width: 100%;
  height: 24px;
  width: auto;
}

/* (7 · certifications moved to the unified TrustBand component —
   components/trust-band.css) */

/* ---------- 8 · beyond onboarding (bright · lifecycle cards) ---------- */
.p-solution .sol-life {
  background: var(--color-white);
  color: var(--color-foreground);
  border-top: 1px solid var(--color-border-light);
}
.p-solution .sol-life__grid {
  display: grid;
  gap: 16px;
  margin-top: 48px;
}
@media (min-width: 768px) { .p-solution .sol-life__grid { grid-template-columns: repeat(3, 1fr); } }
.p-solution .sol-life__card {
  padding: 28px 24px;
  border: 1px solid var(--color-border-light);
  border-radius: 16px;
  background: var(--color-background);
  transition: border-color 0.3s ease;
}
.p-solution .sol-life__card:hover { border-color: var(--color-grey-200); }
.p-solution .sol-life__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border-light);
  background: var(--color-white);
  color: var(--color-blue);
}
.p-solution .sol-life__icon .ds-icon { width: 22px; height: 22px; }
.p-solution .sol-life__name {
  margin-top: 20px;
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tight);
  font-size: var(--fs-2xl);
  line-height: 1.2;
  color: var(--color-black);
}
.p-solution .sol-life__line {
  margin-top: 10px;
  font-size: var(--fs-sm);
  line-height: var(--leading-body);
  color: var(--color-grey-on-white);
}

/* (9 · faq moved to the unified FaqSection component —
   components/faq-section.css) */

/* ═══ Integration choreography (Nacim, 2026-07-30 · v2, cause-and-effect):
   arrive on the blue Incode phone with NO controls. Then, beat by beat:
   c1 the Brand-color bubble pops → c2 the color flips (screen re-themes)
   c3 the Your-logo bubble pops  → c4 the logo flips (Loop patch fades in)
   c5 Font + Corner radius pop (nothing changes — they just arrive).
   Scroll-triggered; resets when the section leaves the viewport. ═══ */
.p-solution .sol-deploy__screens { display: grid; }
.p-solution .sol-deploy__screens .sol-stage__screen { grid-area: 1 / 1; }
.p-solution .sol-deploy__screen-branded {
  opacity: 0;
  transition: opacity 0.6s ease;
}
.p-solution .sol-deploy.is-c2 .sol-deploy__screen-branded { opacity: 1; }
.p-solution .sol-deploy.is-choreo .sol-deploy__logo-swap {
  opacity: 0;
  transition: opacity 0.5s ease;
}
.p-solution .sol-deploy.is-c4 .sol-deploy__logo-swap { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .p-solution .sol-deploy__stage.is-revealed .sol-deploy__layer.is-active .sol-deploy__float--studio {
    transition: none;
  }
  .p-solution .sol-deploy__screen-branded,
  .p-solution .sol-deploy.is-choreo .sol-deploy__logo-swap { transition: none; }
}

/* ═══ Travel feel (Nacim, 2026-07-30): parallax + one-scroll settle ═══ */
/* Parallax planes while the hero exits — scroll-driven CSS animations
   (compositor-only). The copy leaves a touch faster than the scroll, the
   translucent frame and the glow lag behind, and the sticky phone holds
   still: four depth planes. Progressive enhancement: without
   animation-timeline support (or with reduced motion) everything scrolls
   flat, exactly as today. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* Hero-exit "full-screen blue" effect RETIRED (Nacim, 2026-08-19): the
       aurora scaled up on scroll and bled to all four edges, so the hero card
       lost its equal 12px gutters and merged into the problem section. The
       hero now stays a bounded rounded card and simply scrolls away — the
       gutter on all four sides holds, leaving clean space before the next
       section. (The how-section rail still gets its subtle entry lag below.) */
    .p-solution .sol-how { view-timeline-name: --sol-how-enter; }
    .p-solution .sol-how__rail {
      animation: sol-parallax-rail linear both;
      animation-timeline: --sol-how-enter;
      animation-range: entry 0% entry 100%;
    }
  }
}
/* the how rail arrives on its own lagged plane — entry 100% = the top of
   the section reaching the viewport top, i.e. exactly the dock */
@keyframes sol-parallax-rail {
  from { transform: translateY(12svh); }
  to { transform: translateY(0); }
}

/* ============================================================
   proof2 — Variante B (Split editorial), elegida por Nacim 2026-08-01
   Ported pixel-for-pixel from the preview's .pv-b block
   (previews/proof-variants.astro + proof-variants.css). Replaces
   .sol-social in the page arc (same position); sol-certs stays after.
   One headline claim carries the weight on the left ("Verified proof"
   check + stat-grad big number + lead + sub); a tight 3×3 logo grid
   answers on the right; three supporting numbers run as a hairline
   row underneath. The big claim is each page's STRONGEST VERIFIED
   claim from its own fact bank — see .context/website-fanout/PROOF-B-SPEC.md.
   The .sol-social / .sol-certs rules above stay untouched until the
   round-3 swap removes the last consumer.
   ============================================================ */
.p-solution .sol-proof2 {
  background: var(--color-white);
  border-top: 1px solid var(--color-border-light);
}
.p-solution .sol-proof2__split { display: grid; gap: 40px; }
@media (min-width: 900px) {
  .p-solution .sol-proof2__split {
    grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
    gap: 72px;
    align-items: center;
  }
}
.p-solution .sol-proof2__verified {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--fs-sm);
  color: var(--color-blue-500);
}
.p-solution .sol-proof2__big { margin-top: 20px; }
.p-solution .sol-proof2__num {
  display: block;
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tighter);
  font-size: 64px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
@media (min-width: 768px) { .p-solution .sol-proof2__num { font-size: 84px; } }
.p-solution .sol-proof2__lead {
  display: block;
  margin-top: 18px;
  /* two lines max across every page carrying this stat (Sofia,
     2026-08-03) — 38ch lands the longest lead in the fleet on 2 */
  max-width: 38ch;
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.01em;
  font-size: 24px;
  line-height: 1.2;
  color: var(--color-black);
}
@media (min-width: 768px) { .p-solution .sol-proof2__lead { font-size: 28px; } }
.p-solution .sol-proof2__sub {
  margin-top: 18px;
  max-width: 40ch;
  font-size: var(--fs-sm);
  line-height: var(--leading-snug);
  color: var(--color-grey-on-white);
}
/* the tight 3×3 client wall — hairline matrix, dividers only inside */
.p-solution .sol-proof2__logos {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--color-border-light);
  border-radius: 16px;
  overflow: hidden;
  background: var(--color-white);
}
.p-solution .sol-proof2__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 92px;
  padding: 18px;
  border-top: 1px solid var(--color-border-light);
  border-left: 1px solid var(--color-border-light);
}
.p-solution .sol-proof2__logo:nth-child(-n + 3) { border-top: none; }
.p-solution .sol-proof2__logo:nth-child(3n + 1) { border-left: none; }
.p-solution .sol-proof2__logo img { max-width: 100%; height: 22px; width: auto; }

.p-solution .sol-proof2__strip {
  margin-top: 48px;
  padding-top: 32px;
  border-top: 1px solid var(--color-border-light);
  display: grid;
  grid-template-columns: 1fr;
  gap: 28px;
}
@media (min-width: 640px) { .p-solution .sol-proof2__strip { grid-template-columns: repeat(3, 1fr); gap: 0; } }
.p-solution .sol-proof2__cell { padding-right: 32px; }
@media (min-width: 640px) {
  .p-solution .sol-proof2__cell + .sol-proof2__cell { padding-left: 40px; border-left: 1px solid var(--color-border-light); }
}
.p-solution .sol-proof2__cell-value {
  display: block;
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tight);
  font-size: 32px;
  line-height: 1;
  color: var(--color-black);
  font-variant-numeric: tabular-nums;
}
.p-solution .sol-proof2__cell-rest { font-size: 22px; color: var(--color-grey-400); }
.p-solution .sol-proof2__cell-cap {
  display: block;
  margin-top: 10px;
  font-size: var(--fs-sm);
  line-height: var(--leading-snug);
  color: var(--color-grey-on-white);
}


/* ---------- 3b · the stakes, enumerated (outcome-brief risks) — the
   challenge list on the dark threat band; pairs with or replaces the
   quantified stat grid ---------- */
.p-solution .sol-threat__risks {
  list-style: none;
  margin: 48px 0 0;
  padding: 0;
  max-width: 720px;
}
.p-solution .sol-threat__risk {
  display: flex;
  align-items: baseline;
  gap: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  padding: 18px 4px;
}
.p-solution .sol-threat__risk:last-child { border-bottom: 1px solid rgba(255, 255, 255, 0.14); }
.p-solution .sol-threat__risk-num {
  flex-shrink: 0;
  font-size: var(--fs-xs);
  letter-spacing: var(--track-widest);
  color: rgba(255, 255, 255, 0.45);
  font-variant-numeric: tabular-nums;
  transition: color 0.25s ease;
}
.p-solution .sol-threat__risk:hover .sol-threat__risk-num { color: var(--color-blue-200); }
.p-solution .sol-threat__risk-text {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-tight);
  font-size: var(--fs-body);
  line-height: 1.35;
  color: var(--color-white);
}
@media (min-width: 768px) { .p-solution .sol-threat__risk-text { font-size: var(--fs-xl); } }

/* ---------- 7b · compliance coverage (dark band · check chips — the
   outcome brief's requirement list, riding flush into sol-certs) ---------- */
.p-solution .sol-req {
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  background:
    radial-gradient(56% 70% at 88% -14%, color-mix(in oklab, var(--color-x3-blue-deep) 16%, transparent), transparent 66%),
    var(--color-black);
  color: var(--color-white);
}
.p-solution .sol-req__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 40px;
  padding: 0;
  list-style: none;
}
.p-solution .sol-req__chip {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 18px 11px 14px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.04);
  font-size: var(--fs-sm);
  line-height: 1.2;
  color: rgba(255, 255, 255, 0.85);
  transition: border-color 0.25s ease, background-color 0.25s ease;
}
.p-solution .sol-req__chip:hover {
  border-color: rgba(255, 255, 255, 0.35);
  background: rgba(255, 255, 255, 0.08);
}
.p-solution .sol-req__chip svg {
  flex-shrink: 0;
  color: var(--color-blue-200);
}

/* linked lifecycle card (related-brief hubs): the home-card lift + an
   Explore affordance — mirrors uc-prod's interaction */
.p-solution .sol-life__card--link {
  text-decoration: none;
  transition: border-color 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
}
.p-solution .sol-life__card--link:hover {
  border-color: var(--color-grey-300);
  transform: translateY(-3px);
  box-shadow: none;
}
.p-solution .sol-life__more {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 14px;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--color-blue);
}

/* small print under a HowItWorks rail (certs line, qualifiers) —
   components/HowItWorks.astro `note` prop */
.p-solution .sol-how__note {
  margin-top: 20px;
  font-size: var(--fs-xs);
  letter-spacing: var(--track-wide);
  line-height: 1.7;
  color: var(--color-grey-400);
}

/* ---------- four-step phone motion (shared across solution pages) --------
   The Selfie3/IdCapture3/FaceMatch1/Selfie7 components each carry the
   moving layers baked into their SVG (hidden by default). These rules
   reveal the sequences when the deck screen goes .is-active, so any
   solution page that renders these components inherits the motion. */

/* Step 1 "Capture" — the blue gradient scan ring orbits around the face
   while the caption crossfades from "Align your face…" to "Get ready…",
   and finally the ring settles on success green. */
.p-solution .s3-ring-scan { display: none; }
.p-solution svg[data-sol-screen="0"] .s3-ring-scan {
  display: inline;
  transform-box: fill-box;
  transform-origin: center;
  animation: co-ring-scan 2.4s linear infinite;
}
@keyframes co-ring-scan {
  to { transform: rotate(1turn); }
}
.p-solution .s3-caption-ready { display: none; }
.p-solution svg[data-sol-screen="0"].is-active .s3-caption {
  animation: co-cap-out 0.4s ease 1.6s both;
}
.p-solution svg[data-sol-screen="0"].is-active .s3-caption-ready {
  display: inline;
  /* one timeline: in (0.5s) · hold (1.5s) · out (0.5s) = 2.5s from 1.9s */
  animation: co-cap-ready 2.5s ease 1.9s both;
}
.p-solution svg[data-sol-screen="0"].is-active .s3-scan-stop {
  animation: co-scan-success 0.6s ease 3.9s both;
}
@keyframes co-cap-out {
  from { opacity: 1; }
  to { opacity: 0; }
}
@keyframes co-cap-ready {
  0% { opacity: 0; }
  20% { opacity: 1; }     /* 0.5s in */
  80% { opacity: 1; }     /* hold to 2.0s */
  100% { opacity: 0; }    /* 0.5s out */
}
@keyframes co-scan-success {
  to { stop-color: var(--color-green-500); }
}

/* Step 2 "Validate the document" — the license card rides up on
   incode-flow behind the dark scene, lit only inside the capture frame
   (dual-copy light mask). At rest the lit copy exactly covers the dim
   one; on activation both copies translate up together. */
.p-solution .idc-card { filter: brightness(0.2); }
.p-solution svg[data-sol-screen="1"].is-active .idc-card,
.p-solution svg[data-sol-screen="1"].is-active .idc-card-lit {
  animation: co-card-in 1.5s cubic-bezier(0.85, 0, 0.25, 1) 0.25s both;
}
@keyframes co-card-in {
  from { transform: translateY(228px); } /* card top ≈ 15px below the frame's bottom edge */
  to { transform: translateY(0); }
}
.p-solution svg[data-sol-screen="1"].is-active .idc-frame path {
  animation: co-frame-success 0.5s ease 1.75s both;
}
@keyframes co-frame-success {
  to { stroke: var(--color-green-500); }
}

/* Step 3 "Match the person" — the Selfie and ID portraits glide toward
   each other on incode-flow, ending overlapped by ~35px; the tags fade
   out just before they meet. */
.p-solution svg[data-sol-screen="2"].is-active .fm-face-selfie {
  animation: co-fm-selfie-in 1.5s cubic-bezier(0.85, 0, 0.25, 1) 0.3s both;
}
.p-solution svg[data-sol-screen="2"].is-active .fm-face-id {
  animation: co-fm-id-in 1.5s cubic-bezier(0.85, 0, 0.25, 1) 0.3s both;
}
.p-solution svg[data-sol-screen="2"].is-active .fm-tag-selfie,
.p-solution svg[data-sol-screen="2"].is-active .fm-tag-id {
  animation: co-fm-tag-out 0.4s ease 1.2s both;
}
@keyframes co-fm-selfie-in {
  from { transform: translateX(0); }
  to { transform: translateX(25px); }
}
@keyframes co-fm-id-in {
  from { transform: translateX(0); }
  to { transform: translateX(-25px); }
}
@keyframes co-fm-tag-out {
  from { opacity: 1; }
  to { opacity: 0; }
}

/* Step 4 "Decide" — after a 0.5s beat, the green success badge pops in
   with overshoot (incode-settle) and the checkmark draws itself on
   (trim-paths on the stroked centerline twin). */
.p-solution .s7-check-draw { display: none; }
.p-solution svg[data-sol-screen="3"].is-active .s7-badge {
  transform-box: fill-box;
  transform-origin: center;
  animation: co-badge-in 0.6s cubic-bezier(0, 0.75, 0.25, 1) 0.5s both;
}
.p-solution svg[data-sol-screen="3"].is-active .s7-check { opacity: 0; }
.p-solution svg[data-sol-screen="3"].is-active .s7-check-draw {
  display: inline;
  stroke-dasharray: 1;
  animation: co-check-draw 0.3s ease-out 0.8s both;
}
@keyframes co-badge-in {
  0% { transform: scale(0); }
  80% { transform: scale(1.06); }
  100% { transform: scale(1); }
}
@keyframes co-check-draw {
  from { stroke-dashoffset: 1; }
  to { stroke-dashoffset: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .p-solution svg[data-sol-screen="0"] .s3-ring-scan,
  .p-solution svg[data-sol-screen="0"].is-active .s3-caption,
  .p-solution svg[data-sol-screen="0"].is-active .s3-scan-stop,
  .p-solution svg[data-sol-screen="1"].is-active .idc-card,
  .p-solution svg[data-sol-screen="1"].is-active .idc-card-lit,
  .p-solution svg[data-sol-screen="1"].is-active .idc-frame path,
  .p-solution svg[data-sol-screen="2"].is-active .fm-face-selfie,
  .p-solution svg[data-sol-screen="2"].is-active .fm-face-id,
  .p-solution svg[data-sol-screen="2"].is-active .fm-tag-selfie,
  .p-solution svg[data-sol-screen="2"].is-active .fm-tag-id,
  .p-solution svg[data-sol-screen="3"].is-active .s7-badge {
    animation: none;
  }
  /* static state keeps "Align your face…" + the plain blue ring, and
     the filled check instead of the draw-on twin */
  .p-solution svg[data-sol-screen="0"].is-active .s3-caption-ready,
  .p-solution svg[data-sol-screen="3"].is-active .s7-check-draw {
    display: none;
  }
  .p-solution svg[data-sol-screen="3"].is-active .s7-check { opacity: 1; }
}

/* ---------- id-first deck variant (components/HowItWorks.astro `animated`,
   the industry pages) --------
   Those walks read "ID capture → Selfie capture", so the deck leads with
   the document: IdCapture3 rides data-sol-screen="0" and Selfie3 rides
   "1" — the reverse of the index-keyed rules above. These are their
   re-keyed twins, scoped to the .sol-stage__deck--idfirst modifier; the
   rules above stay inert on this deck (each index carries the other
   screen's layer classes) and steps 2/3 (match, decide) keep their
   indices, so they need no twins. */
.p-solution .sol-stage__deck--idfirst svg[data-sol-screen="0"].is-active .idc-card,
.p-solution .sol-stage__deck--idfirst svg[data-sol-screen="0"].is-active .idc-card-lit {
  animation: co-card-in 1.5s cubic-bezier(0.85, 0, 0.25, 1) 0.25s both;
}
.p-solution .sol-stage__deck--idfirst svg[data-sol-screen="0"].is-active .idc-frame path {
  animation: co-frame-success 0.5s ease 1.75s both;
}
.p-solution .sol-stage__deck--idfirst svg[data-sol-screen="1"] .s3-ring-scan {
  display: inline;
  transform-box: fill-box;
  transform-origin: center;
  animation: co-ring-scan 2.4s linear infinite;
}
.p-solution .sol-stage__deck--idfirst svg[data-sol-screen="1"].is-active .s3-caption {
  animation: co-cap-out 0.4s ease 1.6s both;
}
.p-solution .sol-stage__deck--idfirst svg[data-sol-screen="1"].is-active .s3-caption-ready {
  display: inline;
  /* one timeline: in (0.5s) · hold (1.5s) · out (0.5s) = 2.5s from 1.9s */
  animation: co-cap-ready 2.5s ease 1.9s both;
}
.p-solution .sol-stage__deck--idfirst svg[data-sol-screen="1"].is-active .s3-scan-stop {
  animation: co-scan-success 0.6s ease 3.9s both;
}

/* rest screen — visible while the reader approaches the section, before
   the scroll-walk engages: the ID capture LOOPS (card rides in on the
   step-1 curve → frame confirms green → fade → again) so the phone is
   already playing the capture; entering the first step band hands over
   to the one-shot above. The frame's return-to-blue stop rides the
   --idc-frame custom prop the component sets on its root (the traced
   #006AFF has no token). */
.p-solution .sol-stage__deck--idfirst svg[data-sol-screen="rest"].is-active .idc-card,
.p-solution .sol-stage__deck--idfirst svg[data-sol-screen="rest"].is-active .idc-card-lit {
  animation: co-idrest-card 5s linear infinite;
}
.p-solution .sol-stage__deck--idfirst svg[data-sol-screen="rest"].is-active .idc-frame path {
  animation: co-idrest-frame 5s linear infinite;
}
@keyframes co-idrest-card {
  0% { transform: translateY(228px); opacity: 1; }
  6% { transform: translateY(228px); animation-timing-function: cubic-bezier(0.85, 0, 0.25, 1); }
  36% { transform: translateY(0); }
  86% { transform: translateY(0); opacity: 1; }
  94% { transform: translateY(0); opacity: 0; }
  95% { transform: translateY(228px); opacity: 0; }
  100% { transform: translateY(228px); opacity: 1; }
}
@keyframes co-idrest-frame {
  0%, 38% { stroke: var(--idc-frame); }
  46%, 86% { stroke: var(--color-green-500); }
  94%, 100% { stroke: var(--idc-frame); }
}

@media (prefers-reduced-motion: reduce) {
  .p-solution .sol-stage__deck--idfirst svg[data-sol-screen="rest"].is-active .idc-card,
  .p-solution .sol-stage__deck--idfirst svg[data-sol-screen="rest"].is-active .idc-card-lit,
  .p-solution .sol-stage__deck--idfirst svg[data-sol-screen="rest"].is-active .idc-frame path,
  .p-solution .sol-stage__deck--idfirst svg[data-sol-screen="1"] .s3-ring-scan,
  .p-solution .sol-stage__deck--idfirst svg[data-sol-screen="1"].is-active .s3-caption,
  .p-solution .sol-stage__deck--idfirst svg[data-sol-screen="1"].is-active .s3-scan-stop,
  .p-solution .sol-stage__deck--idfirst svg[data-sol-screen="0"].is-active .idc-card,
  .p-solution .sol-stage__deck--idfirst svg[data-sol-screen="0"].is-active .idc-card-lit,
  .p-solution .sol-stage__deck--idfirst svg[data-sol-screen="0"].is-active .idc-frame path {
    animation: none;
  }
  /* static state keeps "Align your face…" + the plain blue ring */
  .p-solution .sol-stage__deck--idfirst svg[data-sol-screen="1"].is-active .s3-caption-ready {
    display: none;
  }
}


/* Optical centering (Sofia, 2026-08-06: the card hero "looks very close
   to the bottom"): the copy cluster was geometrically centered between
   the in-card nav and the stat row, but text reads balanced only when it
   sits a step ABOVE geometric center. The bottom padding biases the flex
   centering up by half its value (~2.5vh). */
@media (min-width: 1024px) {
  .p-solution .sol-hero__copy { padding-bottom: clamp(24px, 5vh, 56px); }
}

/* ---------- shared: the candidate-verification template pieces ----------
   (Sofia 2026-08-18: "apply this template/structure to all use cases") */

/* Fold guard RETIRED (Nacim, 2026-08-19): it added +100px to the hero so the
   dark section's -32px overlap stayed below the fold — but that made the hero
   card taller than the screen and cut off its own bottom ("se corta"). The
   first section now CLEARS the hero (no negative overlap; `.sol-hero + *`
   above), so the hero can be exactly one screen minus the strip and close as
   a card, with the next section resting just past the fold. */

/* story-quote source row — the logo (+ stars when the quote is a G2
   review) under the quote inside the industries ind-story band. G2
   canonical treatment: g2.svg h28 + 5 filled stars + plain attribution. */
.p-solution .cv-story__source {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-top: 32px;
}
.p-solution .cv-story__logo {
  display: block;
  height: var(--logo-h, 28px);
  width: auto;
}
.p-solution .cv-story__stars {
  display: inline-flex;
  gap: 3px;
  color: var(--color-black);
}
.p-solution .cv-story__star {
  display: inline-flex;
  width: 18px;
  height: 18px;
}
.p-solution .cv-story__star svg {
  width: 100%;
  height: 100%;
}
