/* ===== CGS v3 motion layer (experimental) =====
   Everything here is opt-in: it only applies when the visitor has no reduced-motion
   preference, and the hero demo only runs once motion.js adds .is-live to the stage.
   Without JS or with reduced motion, the page looks exactly like the approved v2 design. */

@media (prefers-reduced-motion: no-preference) {

  /* ---------- Scroll reveals ---------- */
  .js .reveal {
    transform: translateY(22px);
    transition: opacity .9s cubic-bezier(.16, 1, .3, 1), transform .9s cubic-bezier(.16, 1, .3, 1);
    transition-delay: var(--rd, 0ms);
  }
  .js .reveal.is-visible { transform: none; }

  /* Section headings: the block stays put, its lines arrive one after another. */
  .js .section-head.reveal, .js .xb-head.reveal { opacity: 1; transform: none; }
  .js .section-head.reveal > *, .js .xb-head.reveal > * > *, .js .xb-head.reveal > p {
    opacity: 0; translate: 0 16px;
    transition: opacity .8s cubic-bezier(.16, 1, .3, 1), translate .9s cubic-bezier(.16, 1, .3, 1);
  }
  .js .section-head.reveal.is-visible > *, .js .xb-head.reveal.is-visible > * > *, .js .xb-head.reveal.is-visible > p { opacity: 1; translate: 0 0; }
  .js .section-head.reveal > :nth-child(2), .js .xb-head.reveal > * > :nth-child(2) { transition-delay: .08s; }
  .js .section-head.reveal > :nth-child(3), .js .xb-head.reveal > p { transition-delay: .16s; }
  .js .section-head.reveal > :nth-child(4) { transition-delay: .24s; }

  /* ---------- Hero copy: one staggered entrance on load ---------- */
  .js .xa-copy.reveal { opacity: 1; transform: none; }
  /* kicker and headline are readable from the first frame and simply settle into place;
     the supporting text, buttons and facts follow shortly after */
  .js .xa-copy > * { animation: xaRise 1s cubic-bezier(.16, 1, .3, 1) both; }
  .js .xa-copy > :nth-child(-n+2) { animation: xaSettle .7s cubic-bezier(.16, 1, .3, 1) both; }
  .js .xa-copy > :nth-child(3) { animation-delay: .2s; }
  .js .xa-copy > :nth-child(4) { animation-delay: .3s; }
  .js .xa-copy > :nth-child(5) { animation-delay: .4s; }

  /* ---------- Hero product demo ----------
     One 9s loop shared by every part; each part is offset with animation-delay, so the
     sequence stays in step on every repeat: ad tapped -> page loads -> form filled ->
     request sent -> inquiry recorded. Each part waits in its "before" state until its
     turn, then holds its finished state for most of the loop. */
  .xa-stage.is-live { --loop: 9s; --start: 1.3s; }

  /* entrances (once) */
  .xa-stage.is-live .xa-ad { --rot: -3deg; --fy: -6px; animation: xaIn 1.1s cubic-bezier(.16, 1, .3, 1) .35s both, xaAdLift var(--loop) ease-in-out calc(var(--start) + .6s) infinite backwards, xaFloat 6.5s ease-in-out 1.5s infinite alternate; }
  .xa-stage.is-live .xa-phone { --rot: 3deg; --fy: -8px; animation: xaIn 1.1s cubic-bezier(.16, 1, .3, 1) .55s both, xaPulse var(--loop) ease-out calc(var(--start) + 2.2s) infinite backwards, xaFloat 7.5s ease-in-out 1.7s infinite alternate; }
  .xa-stage.is-live .xa-lead { --rot: -1.5deg; --fy: -5px; animation: xaFade 1.1s cubic-bezier(.16, 1, .3, 1) .75s both, xaLift var(--loop) cubic-bezier(.16, 1, .3, 1) calc(var(--start) + 6.1s) infinite backwards, xaFloat 7s ease-in-out 1.9s infinite alternate; }
  .xa-stage.is-live .xa-path { animation: xaFadeOnly 1.2s ease .95s both; }

  /* 01 the ad: the button is tapped and stays active until the page starts loading */
  .xa-stage.is-live .xa-ad .adbtn { position: relative; animation: xaAdBtn var(--loop) ease calc(var(--start) + .6s) infinite backwards; }
  .xa-stage.is-live .xa-ad .adbtn::after, .xa-stage.is-live .xa-phone .btn-m::after {
    content: ''; position: absolute; inset: -2px; border-radius: 999px; border: 2px solid var(--sage); opacity: 0; pointer-events: none;
    animation: xaRipple var(--loop) cubic-bezier(.16, 1, .3, 1) calc(var(--start) + .65s) infinite backwards;
  }
  .xa-stage.is-live .xa-phone .btn-m { position: relative; }
  .xa-stage.is-live .xa-phone .btn-m::after { animation-delay: calc(var(--start) + 4.65s); }

  /* 02 the page: loads, form is filled, request is sent */
  .xa-stage.is-live .scr > .bar, .xa-stage.is-live .scr > .h, .xa-stage.is-live .scr > .p { animation: xaSkel var(--loop) cubic-bezier(.16, 1, .3, 1) infinite backwards; }
  .xa-stage.is-live .scr > .bar { animation-delay: calc(var(--start) + 2.4s); }
  .xa-stage.is-live .scr > .h { animation-delay: calc(var(--start) + 2.55s); }
  .xa-stage.is-live .scr > .h.s { animation-delay: calc(var(--start) + 2.7s); }
  .xa-stage.is-live .scr > .p { animation-delay: calc(var(--start) + 2.85s); }
  .xa-stage.is-live .scr > .p + .p { animation-delay: calc(var(--start) + 3s); }
  .xa-stage.is-live .xa-phone .f { position: relative; }
  .xa-stage.is-live .xa-phone .f::after {
    content: ''; position: absolute; left: 9px; top: 50%; height: 6px; margin-top: -3px; border-radius: 3px; background: var(--sage); width: 0;
    animation: xaType var(--loop) steps(7, end) calc(var(--start) + 3.4s) infinite backwards;
  }
  .xa-stage.is-live .xa-phone .f + .f::after { animation-delay: calc(var(--start) + 3.9s); }
  .xa-stage.is-live .xa-phone .btn-m { animation: xaPress var(--loop) ease calc(var(--start) + 4.6s) infinite backwards; }

  /* 03 the inquiry: lifts, check pops, details are recorded line by line */
  .xa-stage.is-live .xa-lead::after {
    content: ''; position: absolute; inset: 0; border-radius: inherit; box-shadow: 0 0 0 2px var(--sage), 0 0 34px rgba(185, 194, 181, .55); opacity: 0; pointer-events: none;
    animation: xaGlow var(--loop) ease-out calc(var(--start) + 6.1s) infinite backwards;
  }
  .xa-stage.is-live .xa-lead .ok { animation: xaCheck var(--loop) cubic-bezier(.34, 1.56, .64, 1) calc(var(--start) + 6.2s) infinite backwards; }
  .xa-stage.is-live .xa-lead .ls { animation: xaLine var(--loop) ease calc(var(--start) + 6.45s) infinite backwards; }
  .xa-stage.is-live .xa-lead .ls + .ls { animation-delay: calc(var(--start) + 6.7s); }

  /* paused while the hero is off screen or the tab is hidden */
  .xa-stage.is-paused, .xa-stage.is-paused *, .xa-stage.is-paused *::after { animation-play-state: paused !important; }
}

@keyframes xaRise { from { opacity: 0; translate: 0 18px; } to { opacity: 1; translate: 0 0; } }
@keyframes xaSettle { from { opacity: .7; translate: 0 8px; } to { opacity: 1; translate: 0 0; } }
@keyframes xaIn { from { opacity: 0; translate: 0 28px; } to { opacity: 1; translate: 0 0; } }
@keyframes xaFade { from { opacity: 0; scale: .96; } to { opacity: 1; scale: 1; } }
@keyframes xaFadeOnly { from { opacity: 0; } to { opacity: 1; } }
/* gentle float after the entrance; keeps each card's own tilt */
@keyframes xaFloat { from { transform: rotate(var(--rot)) translateY(0); } to { transform: rotate(var(--rot)) translateY(var(--fy)); } }

@keyframes xaAdLift { 0%, 100% { scale: 1; } 4%, 20% { scale: 1.025; } 28% { scale: 1; } }
@keyframes xaAdBtn {
  0% { background: rgba(243, 238, 227, 0); color: var(--ink); border-color: var(--rule); scale: 1; }
  3% { background: var(--ink); color: var(--paper); border-color: var(--ink); scale: .92; }
  6%, 20% { background: var(--ink); color: var(--paper); border-color: var(--ink); scale: 1; }
  26%, 100% { background: rgba(243, 238, 227, 0); color: var(--ink); border-color: var(--rule); scale: 1; }
}
@keyframes xaRipple { 0% { opacity: 0; scale: 1; } 1% { opacity: .9; scale: 1; } 10% { opacity: 0; scale: 1.5 1.9; } 100% { opacity: 0; scale: 1.5 1.9; } }
@keyframes xaGlow { 0% { opacity: 0; } 5% { opacity: 1; } 22% { opacity: 0; } 100% { opacity: 0; } }
@keyframes xaPulse { 0%, 100% { scale: 1; } 4% { scale: 1.025; } 10% { scale: 1; } }
@keyframes xaSkel {
  0% { opacity: .15; translate: -8px 0; }
  5% { opacity: 1; translate: 0 0; }
  92% { opacity: 1; translate: 0 0; }
  97%, 100% { opacity: .15; translate: -8px 0; }
}
@keyframes xaType { 0% { width: 0; } 6% { width: 58%; } 90% { width: 58%; } 95%, 100% { width: 0; } }
@keyframes xaPress {
  0%, 100% { scale: 1; background: var(--ink); }
  3% { scale: .93; background: var(--accent-hover); }
  7% { scale: 1; background: var(--ink); }
}
@keyframes xaLift { 0%, 100% { translate: 0 0; } 5%, 14% { translate: 0 -10px; } 22% { translate: 0 0; } }
@keyframes xaCheck {
  0% { scale: .6; opacity: .3; }
  5% { scale: 1.2; opacity: 1; }
  9%, 88% { scale: 1; opacity: 1; }
  94%, 100% { scale: .6; opacity: .3; }
}
@keyframes xaLine {
  0% { opacity: .25; translate: -6px 0; }
  5%, 86% { opacity: 1; translate: 0 0; }
  92%, 100% { opacity: .25; translate: -6px 0; }
}

/* ===== Stage 2: service card hovers =====
   Pointer devices only (no sticky hover on phones). Keyboard focus inside a card gets the
   same treatment. Colour/shadow feedback stays for reduced-motion visitors; movement does not. */
#services .xb-card .n, #services .xb-card .ill { transition: color .4s ease, background-color .5s ease; }

@media (hover: hover) and (pointer: fine) {
  #services .xb-card:hover, #services .xb-card:focus-within {
    box-shadow: 0 26px 52px rgba(0, 0, 0, .34), 0 0 0 1px rgba(185, 194, 181, .6);
  }
  #services .xb-card:hover .n, #services .xb-card:focus-within .n { color: var(--ink); }
  #services .xb-card:hover .ill, #services .xb-card:focus-within .ill { background-color: var(--paper); }
}

@media (prefers-reduced-motion: no-preference) {
  /* keep the scroll-reveal entrance and add the hover properties to the same transition */
  .js #services .xb-card.reveal {
    transition: opacity .9s cubic-bezier(.16, 1, .3, 1), transform .9s cubic-bezier(.16, 1, .3, 1),
                translate .55s cubic-bezier(.16, 1, .3, 1), box-shadow .55s ease, scale .2s ease;
    transition-delay: var(--rd, 0ms);
  }
  #services .xb-card .link-arrow::after { display: inline-block; transition: translate .35s cubic-bezier(.16, 1, .3, 1); }
  #services .ill-search .r, #services .ill-social .post, #services .ill-web .win, #services .ill-track .node {
    transition: translate .55s cubic-bezier(.16, 1, .3, 1), rotate .55s cubic-bezier(.16, 1, .3, 1), box-shadow .55s ease, opacity .4s ease, scale .45s cubic-bezier(.34, 1.56, .64, 1);
  }
  #services .ill-social .img { background-size: 170% 170%; background-position: 0% 0%; transition: background-position 1.2s cubic-bezier(.16, 1, .3, 1); }
  #services .ill-web .hb { transition: width .6s cubic-bezier(.16, 1, .3, 1); }
  #services .ill-web .row .frm { transition: background-color .45s ease; }
  #services .ill-track .ln { transition: width .5s cubic-bezier(.16, 1, .3, 1); }

  @media (hover: hover) and (pointer: fine) {
    #services .xb-card:hover, #services .xb-card:focus-within { translate: 0 -8px; }
    #services .xb-card:hover .link-arrow::after, #services .xb-card:focus-within .link-arrow::after { translate: 4px 0; }

    /* 01 search: the sponsored result rises above the organic one */
    #services .xb-card:hover .ill-search .r:not(.o), #services .xb-card:focus-within .ill-search .r:not(.o) { translate: 0 -3px; box-shadow: 0 10px 20px rgba(31, 58, 46, .16); }
    #services .xb-card:hover .ill-search .r.o, #services .xb-card:focus-within .ill-search .r.o { opacity: .35; }
    /* 02 social: the post tips forward, its image drifts */
    #services .xb-card:hover .ill-social .post, #services .xb-card:focus-within .ill-social .post { translate: 0 -4px; rotate: -3deg; box-shadow: 0 12px 24px rgba(31, 58, 46, .16); }
    #services .xb-card:hover .ill-social .img, #services .xb-card:focus-within .ill-social .img { background-position: 100% 100%; }
    /* 03 web: the page lifts, the headline grows, the form field is highlighted */
    #services .xb-card:hover .ill-web .win, #services .xb-card:focus-within .ill-web .win { translate: 0 -4px; box-shadow: 0 12px 24px rgba(31, 58, 46, .16); }
    #services .xb-card:hover .ill-web .hb, #services .xb-card:focus-within .ill-web .hb { width: 78%; }
    #services .xb-card:hover .ill-web .row .frm, #services .xb-card:focus-within .ill-web .row .frm { background-color: var(--sage); }
    /* 04 tracking: the path stretches out and the inquiry is confirmed */
    #services .xb-card:hover .ill-track .ln, #services .xb-card:focus-within .ill-track .ln { width: 20px; }
    #services .xb-card:hover .ill-track .node.on, #services .xb-card:focus-within .ill-track .node.on { scale: 1.08; box-shadow: 0 0 0 4px rgba(185, 194, 181, .65); }
  }

  /* phones and tablets: a light press instead of hover */
  @media (hover: none) {
    #services .xb-card:active { scale: .985; }
  }
}

/* ===== Stage 3: How We Work timeline, drawn as the visitor scrolls =====
   motion.js sets --tl-p (0 to 1) on the timeline and .is-reached on each step the line has
   passed: its dot fills and its number deepens to forest. All step text stays readable throughout.
   Scrolling back up reverses it. Without JS or with reduced motion the timeline is
   the approved static version. */
@media (prefers-reduced-motion: no-preference) {
  .timeline.is-live::before { opacity: .3; }
  .timeline.is-live::after {
    content: ''; position: absolute; left: 0; right: 0; top: 17px; height: 2px;
    background: linear-gradient(90deg, var(--ink) 0%, var(--ink) 75%, var(--sage) 100%);
    transform-origin: left center; transform: scaleX(var(--tl-p, 0)); transition: transform .12s linear;
  }
  /* steps stay fully readable; progress is shown by the line, the dots and the number colour */
  .js .timeline.is-live li.reveal { opacity: 1; transform: none; }
  /* inactive numbers: a mix of Moss Grey and Forest (#45574C, 6.4:1 on the section background) */
  .timeline.is-live .tl-num { color: #45574C; transition: color .3s ease; }
  .timeline.is-live li.is-reached .tl-num { color: var(--ink); }
  .timeline.is-live li .tl-node { background: var(--paper-alt); scale: .8; transition: background-color .25s ease, scale .4s cubic-bezier(.34, 1.56, .64, 1); }
  .timeline.is-live li.is-reached .tl-node { background: var(--ink); scale: 1; animation: tlPing .9s ease-out; }

  @media (max-width: 900px) {
    .timeline.is-live::after {
      left: 7px; right: auto; top: 8px; bottom: 8px; width: 2px; height: auto;
      background: linear-gradient(180deg, var(--ink) 0%, var(--ink) 80%, var(--sage) 100%);
      transform-origin: center top; transform: scaleY(var(--tl-p, 0));
    }
  }
}
@keyframes tlPing { from { box-shadow: 0 0 0 0 rgba(31, 58, 46, .35); } to { box-shadow: 0 0 0 12px rgba(31, 58, 46, 0); } }

/* ===== Hero polish: CTA hovers =====
   Content never fades or drifts on the way out: once something has appeared it stays fully
   visible until it scrolls off screen (owner decision, October 18, 2026). */

/* Primary CTA: lifts slightly, its halo widens. Secondary link: underline sweeps to cream.
   Colour changes apply to everyone; movement only without a reduced-motion preference. */
.xa-hero .xa-cta { transition: background-color .35s ease, box-shadow .45s ease, translate .45s cubic-bezier(.16, 1, .3, 1), scale .2s ease; }
.xa-hero .xa-link {
  background: linear-gradient(var(--paper), var(--paper)) no-repeat left bottom / 0% 1px;
  background-origin: border-box;
  transition: background-size .5s cubic-bezier(.16, 1, .3, 1), color .3s ease;
}
.xa-hero .xa-cta:hover, .xa-hero .xa-cta:focus-visible { background: #fff; box-shadow: 0 0 0 8px rgba(243, 238, 227, .16), 0 14px 30px rgba(0, 0, 0, .28); }
.xa-hero .xa-link:hover, .xa-hero .xa-link:focus-visible { background-size: 100% 1px; }
.xa-hero .xa-cta:focus-visible .arr, .xa-hero .xa-link:focus-visible .arr { transform: translateX(3px); }

@media (prefers-reduced-motion: no-preference) {
  .xa-hero .arr { transition: transform .35s cubic-bezier(.16, 1, .3, 1); }
  @media (hover: hover) and (pointer: fine) {
    .xa-hero .xa-cta:hover { translate: 0 -2px; }
    .xa-hero .xa-cta:hover .arr, .xa-hero .xa-link:hover .arr { transform: translateX(4px); }
  }
  .xa-hero .xa-cta:active { translate: 0 0; scale: .98; }

  /* the service strip settles in last */
  .js .xa-band { animation: xaFadeOnly 1s ease 1s both; }
}

/* ===== Services: each illustration builds once as its card arrives =====
   Runs a single time when the card is revealed (.is-visible). Animations only fill
   backwards, so once they finish the approved hover effects take over unchanged. */
@media (prefers-reduced-motion: no-preference) {
  .js #services .xb-card.reveal.is-visible .ill > * { animation: svBuild .7s cubic-bezier(.16, 1, .3, 1) .3s backwards; }
  .js #services .xb-card.reveal.is-visible .ill > :nth-child(2) { animation-delay: .42s; }
  .js #services .xb-card.reveal.is-visible .ill > :nth-child(3) { animation-delay: .54s; }
  .js #services .xb-card.reveal.is-visible .ill > :nth-child(4) { animation-delay: .66s; }
  .js #services .xb-card.reveal.is-visible .ill > :nth-child(5) { animation-delay: .78s; }
  /* 01 search: the sponsored result settles in with its outline */
  .js #services .xb-card.reveal.is-visible .ill-search .r:not(.o) { animation-name: svBuild, svOutline; animation-duration: .7s, 1.1s; }
  /* 03 web: the page headline draws across */
  .js #services .xb-card.reveal.is-visible .ill-web .hb { animation: svGrow .8s cubic-bezier(.16, 1, .3, 1) .55s backwards; }
  /* 04 tracking: each connector draws, then the inquiry is confirmed */
  .js #services .xb-card.reveal.is-visible .ill-track .ln { animation: svLine .45s ease-out .5s backwards; }
  .js #services .xb-card.reveal.is-visible .ill-track .ln ~ .ln { animation-delay: .74s; }
  .js #services .xb-card.reveal.is-visible .ill-track .node.on { animation: svPop .6s cubic-bezier(.34, 1.56, .64, 1) .95s backwards; }
}
@keyframes svBuild { from { opacity: 0; translate: 0 10px; } }
@keyframes svOutline { from { box-shadow: 0 0 0 4px rgba(185, 194, 181, .7); } to { box-shadow: 0 0 0 0 rgba(185, 194, 181, 0); } }
@keyframes svGrow { from { width: 0; } }
@keyframes svLine { from { width: 0; } }
@keyframes svPop { from { opacity: 0; scale: .6; } }
