/* ==========================================================================
   Bilsan Business Solutions — motion.css
   Site-wide motion system. Loaded on every public page after site.css and the
   page styles; driven by motion.js (window.Bilsan.motion).

   Principles: transform / opacity (+ clip-path) only · easings --m-ease and
   --m-ease-io · 300–900 ms · stagger 70 ms · nothing loops aggressively.
   Everything below is off under prefers-reduced-motion and in print.

   Reveal contract
     html.motion-ready          set before first paint by partials/head (JS
                                on, motion allowed). Nothing is hidden without it.
     [data-motion="…"]          opt-in variant: fade-up (default) · fade ·
                                scale · clip · slide-start · slide-end
                                (start/end are logical, mirrored in RTL).
     [data-motion="none"]       opt out (element and its descendants).
     .reveal                    legacy class — same as data-motion="fade-up".
     Automatic targets          children of stagger groups (.grid, .pillars,
                                .metrics, .equation …), section headings,
                                chains, steppers, callouts, notes, tables.
     .is-in                     added once by motion.js when in view;
                                --motion-i (0…8) = stagger index in its batch.

    1. Tokens
    2. Scroll reveal (hidden state → keyframes)
    3. Section headings (rule · lines · lead)
    4. Flow chains & steppers
    5. Ecosystem equation
    6. Page heroes (load entrance + scroll-driven parallax)
    7. Cards, buttons, links (micro-interactions)
    8. Platform cards (home), dropdowns
    9. Header (condense + progress) · back-to-top
   10. Page transitions
   11. Keyframes
   ========================================================================== */

/* ------------------------------------------------------------- 1. Tokens */
:root {
  --m-ease: cubic-bezier(.2, .7, .2, 1);
  --m-ease-io: cubic-bezier(.65, 0, .35, 1);
  --m-dur: .8s;
  --m-stagger: 70ms;
  --m-shift: 22px;
  --m-dir: 1;                 /* 1 = LTR, -1 = RTL (inline direction sign) */
  --m-start: left;            /* inline-start edge, for transform-origin */
  --m-lift: -4px;
}
:root[dir="rtl"] { --m-dir: -1; --m-start: right; }

/* ------------------------------------------ 2. Scroll reveal (screen only) */
@media screen and (prefers-reduced-motion: no-preference) {
  /* Hidden state. Keep in sync with GROUPS / BLOCKS / SKIP in motion.js. */
  .motion-ready .site-main :is(
      .reveal:not(.grid, .pillars, .metrics, .equation, .tr-pipes, .te-layers, .pf-rows, .pf-grid, .tr-legend, .ct-channels, .ct-steps),
      [data-motion]:not([data-motion="none"]),
      :is(.grid, .pillars, .metrics, .equation, .tr-pipes, .te-layers, .pf-rows, .pf-grid, .tr-legend, .ct-channels, .ct-steps) > *,
      .table-wrap, .callout, .note, .pf-sec__head, .pf-flow, .ct-card, .ct-panel, .section-head-row__link
    ):not(.is-in, [data-motion="none"], [data-motion-skip]):not(:is(.page-hero, .home-hero, .hs, [data-motion="none"], [data-motion-skip]) *) {
    opacity: 0;
  }

  .motion-ready [data-m].is-in {
    animation: m-fade-up var(--m-dur) var(--m-ease) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger));
  }
  .motion-ready [data-m="fade"].is-in { animation-name: m-fade; animation-duration: .7s; }
  .motion-ready [data-m="scale"].is-in { animation-name: m-scale; }
  .motion-ready [data-m="clip"].is-in { animation-name: m-clip; animation-duration: .9s; animation-timing-function: var(--m-ease-io); }
  .motion-ready [data-m="slide-start"].is-in { animation-name: m-slide-start; }
  .motion-ready [data-m="slide-end"].is-in { animation-name: m-slide-end; }
}

/* ------------------------------------------------- 3. Section headings */
@media screen and (prefers-reduced-motion: no-preference) {
  .motion-ready .site-main .section-head:not(.is-in, [data-motion="none"], [data-motion-skip]):not(:is(.page-hero, .home-hero, .hs, [data-motion="none"], [data-motion-skip]) *) > * { opacity: 0; }

  .motion-ready .section-head.is-in > * {
    animation: m-fade-up var(--m-dur) var(--m-ease) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + 260ms + var(--m-lines, 1) * 90ms);
  }
  /* eyebrow: text fades while its rule draws from the inline-start edge */
  .motion-ready .section-head.is-in > .kicker {
    animation: m-fade .5s ease backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger));
  }
  .motion-ready .section-head.is-in > .kicker::before {
    transform-origin: var(--m-start) 50%;
    animation: m-draw-x .8s var(--m-ease-io) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + 60ms);
  }
  /* title: split into lines by motion.js, each line rises out of a clip */
  .motion-ready .section-head.is-in > .section-title { animation: none; }
  .motion-ready .section-head.is-in > .section-title.m-whole,
  .motion-ready .section-head.is-in .m-line {
    animation: m-line .9s var(--m-ease) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + 120ms + var(--m-si, 0) * 90ms);
  }
}
.m-line { display: block; }
/* Count-up keeps its final width (set by motion.js) and grows from the inline start. */
:root[dir="rtl"] [data-count] { text-align: right; }

/* ------------------------------------------ 4. Flow chains & steppers */
@media screen and (prefers-reduced-motion: no-preference) {
  .motion-ready .site-main .chain:not(.is-in, [data-motion="none"], [data-motion-skip]):not(:is([data-motion="none"], [data-motion-skip]) *) :is(.chain__step, .chain__arrow) { opacity: 0; }

  .motion-ready .chain.is-in .chain__step {
    position: relative;
    animation: m-step .5s var(--m-ease) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + 80ms + var(--m-si, 0) * var(--m-step, 90ms));
  }
  /* each step "lights up" once in the accent colour as it arrives */
  .motion-ready .chain.is-in .chain__step::after {
    content: "";
    position: absolute;
    inset: -1px;
    border: 1px solid var(--pc);
    border-radius: inherit;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--pc) 16%, transparent);
    opacity: 0;
    pointer-events: none;
    animation: m-lit .9s ease-out;
    animation-delay: inherit;
  }
  /* connector: slides toward the inline end (arrows are mirrored in RTL) */
  .motion-ready .chain.is-in .chain__arrow {
    animation: m-connector .45s var(--m-ease) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + 80ms + (var(--m-si, 0) + .6) * var(--m-step, 90ms));
  }

  /* Opportunity pipelines (traction) and the profile engagement path. */
  .motion-ready .site-main :is(.tr-pipe__steps, .pf-stepper):not(.is-in, [data-motion="none"], [data-motion-skip]):not(:is([data-motion="none"], [data-motion-skip]) *) > li > *,
  .motion-ready .site-main :is(.tr-pipe__steps, .pf-stepper):not(.is-in, [data-motion="none"], [data-motion-skip]):not(:is([data-motion="none"], [data-motion-skip]) *) > li::after { opacity: 0; }

  .motion-ready :is(.tr-pipe__steps, .pf-stepper).is-in > li > :is(.tr-pipe__node, .pf-stepper__marker) {
    animation: m-pop .5s var(--m-ease) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + var(--m-si, 0) * 170ms);
  }
  .motion-ready :is(.tr-pipe__steps, .pf-stepper).is-in > li > :is(.tr-pipe__label, .pf-stepper__label) {
    animation: m-fade-up .6s var(--m-ease) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + var(--m-si, 0) * 170ms + 60ms);
    --m-shift: 8px;
  }
  /* the progress line fills from one node to the next */
  .motion-ready .tr-pipe__steps.is-in > li::after,
  .motion-ready .pf-stepper.is-in > li::after {
    transform-origin: 50% 0;
    animation: m-draw-y .55s var(--m-ease-io) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + var(--m-si, 0) * 170ms + 110ms);
  }
  @media (min-width: 768px) {
    .motion-ready .tr-pipe__steps.is-in > li::after { transform-origin: var(--m-start) 50%; animation-name: m-draw-x; }
  }
  @container (min-width: 480px) {
    .motion-ready .pf-stepper.is-in > li::after { transform-origin: var(--m-start) 50%; animation-name: m-draw-x; }
  }
}

/* ------------------------------------------------ 5. Ecosystem equation */
@media screen and (prefers-reduced-motion: no-preference) {
  .motion-ready .equation > .is-in .equation__op {
    animation: m-op .5s var(--m-ease) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + 180ms);
  }
  .motion-ready .equation__result.is-in .equation__equals {
    animation: m-pop .6s var(--m-ease) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + 220ms);
  }
  /* the result glows once: a soft light sweeps across the red panel */
  .motion-ready .equation__result.is-in::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(100deg, transparent 25%, rgba(255, 255, 255, .24) 50%, transparent 75%);
    opacity: 0;
    pointer-events: none;
    animation: m-sheen 1.6s var(--m-ease-io);
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + 520ms);
  }
}

/* ---------------------------- 6. Page heroes: entrance (CSS only) + parallax */
@media screen and (prefers-reduced-motion: no-preference) {
  .page-hero .breadcrumbs { animation: m-fade .6s ease backwards; }
  :is(.page-hero__content, .pf-hero__main) > * { animation: m-fade-up .8s var(--m-ease) backwards; --m-shift: 14px; }
  :is(.page-hero__content, .pf-hero__main) > :nth-child(2) { animation-delay: 70ms; }
  :is(.page-hero__content, .pf-hero__main) > :nth-child(3) { animation-delay: 140ms; }
  :is(.page-hero__content, .pf-hero__main) > :nth-child(4) { animation-delay: 210ms; }
  :is(.page-hero__content, .pf-hero__main) > :nth-child(n + 5) { animation-delay: 280ms; }
  :is(.page-hero__title, .pf-hero__identity) { animation-name: m-line; }
  .page-hero .kicker::before { transform-origin: var(--m-start) 50%; animation: m-draw-x .9s var(--m-ease-io) 80ms backwards; }
  .page-hero--accent::after { transform-origin: var(--m-start) 50%; animation: m-draw-x 1s var(--m-ease-io) backwards; }
  .pf-glance { animation: m-fade-up .9s var(--m-ease) 240ms backwards; }
}
/* Parallax: the grid decoration / watermark drifts slower than the page. */
@supports (animation-timeline: scroll()) {
  @media screen and (prefers-reduced-motion: no-preference) {
    .page-hero::before,
    .pf-hero__watermark {
      animation: m-parallax linear both;
      animation-timeline: scroll(root block);
      animation-range: 0 75vh;
    }
    .pf-hero__watermark { animation-name: m-parallax-mark; }
  }
}

/* ------------------------------ 7. Cards, buttons, links (interactions) */
:is(.feature, .box--hover, .platform-card, .status-card, .pa-card, .in-card, .pg-cluster, .pf-cluster, .pf-card, .pf-row, .tr-pipe) {
  transition: transform .45s var(--m-ease), box-shadow .45s var(--m-ease), border-color .3s ease, background-color .3s ease;
}
:is(.feature__icon, .platform-card__icon, .status-card__icon, .pa-card__icon, .in-card__icon, .pf-cluster__icon, .mega__icon, .in-plat__icon, .te-plat__icon) {
  transition: translate .45s var(--m-ease), scale .45s var(--m-ease), background-color .2s ease, color .2s ease;
}
.pa-card__mark { transition: rotate .8s var(--m-ease), scale .8s var(--m-ease), opacity .4s ease; }

@media (hover: hover) and (pointer: fine) {
  :is(.feature, .box--hover, .platform-card, .status-card, .pa-card, .in-card, .pg-cluster, .pf-cluster, .pf-card):is(:hover, :has(:focus-visible)) {
    transform: translateY(var(--m-lift));
    border-color: var(--c-line-strong);
    box-shadow: var(--shadow-2);
  }
  /* accent border + soft glow in the card's own platform colour */
  :is(.platform-card, .status-card, .pa-card, .pf-card, .pf-row, .tr-pipe, .in-card, .pf-cluster):is([data-accent], [data-accent] *):is(:hover, :has(:focus-visible)) {
    border-color: color-mix(in srgb, var(--pc) 42%, var(--c-line));
    box-shadow: 0 1px 2px rgba(21, 23, 28, .04), 0 22px 44px -26px color-mix(in srgb, var(--pc) 55%, transparent);
  }
  :is(.feature, .platform-card, .status-card, .pa-card, .in-card, .pf-cluster, .mega__item, .in-plat, .te-plat):hover :is(.feature__icon, .platform-card__icon, .status-card__icon, .pa-card__icon, .in-card__icon, .pf-cluster__icon, .mega__icon, .in-plat__icon, .te-plat__icon) {
    translate: 0 -2px;
    scale: 1.07;
  }
  /* platform cards: a stronger accent glow and the watermark icon turns slightly */
  .pa-card[data-accent]:is(:hover, :has(:focus-visible)) {
    box-shadow: 0 1px 2px rgba(21, 23, 28, .04), 0 28px 56px -30px color-mix(in srgb, var(--pc) 70%, transparent);
  }
  .pa-card:hover .pa-card__mark { rotate: -8deg; scale: 1.08; opacity: .11; }
  /* primary buttons: a light sheen sweeps toward the inline end */
  :where(.btn-primary, .btn-accent):not(.dropdown-toggle) { position: relative; overflow: hidden; isolation: isolate; }
  .btn:is(.btn-primary, .btn-accent):not(.dropdown-toggle)::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(105deg, transparent 30%, rgba(255, 255, 255, .26) 50%, transparent 70%);
    transform: translateX(calc(-110% * var(--m-dir)));
    pointer-events: none;
  }
  .btn:is(.btn-primary, .btn-accent):not(.dropdown-toggle):is(:hover, :focus-visible)::after {
    transform: translateX(calc(110% * var(--m-dir)));
    transition: transform .8s var(--m-ease-io);
  }
}
/* Touch screens: no sticky hover lift after a tap. */
@media (hover: none) {
  :is(.feature, .box--hover, .platform-card, .status-card, .pa-card, .in-card, .pg-cluster, .pf-cluster, .pf-card, .pf-row, .tr-pipe):hover { transform: none; box-shadow: none; }
}
/* Keyboard parity for card-less arrow links. */
.icon-trail { transition: translate .4s var(--m-ease); }
:is(a, button):is(:hover, :focus-visible) > .icon-trail,
:is(.platform-card, .status-card):is(:hover, :has(:focus-visible)) .icon-trail { translate: calc(4px * var(--m-dir)) 0; }

.btn { transition: color .18s ease, background-color .18s ease, border-color .18s ease, box-shadow .18s ease, scale .2s var(--m-ease); }
.btn:active:not(:disabled, .disabled) { scale: .97; }

/* ------------------------------- 8. Platform cards (home), dropdowns */
/* The card itself staggers in as a .grid item; once it is in, its parts follow:
   stat tiles rise, the flow rail draws toward the inline end and each step lights up. */
@media screen and (prefers-reduced-motion: no-preference) {
  .motion-ready .pa-card.is-in :is(.pa-stat, .pa-flow, .pa-audience) {
    animation: m-fade-up .6s var(--m-ease) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + 160ms + var(--pa-si, 0) * 60ms);
    --m-shift: 10px;
  }
  .pa-stat:nth-child(2) { --pa-si: 1; }
  .pa-stat:nth-child(3) { --pa-si: 2; }
  .pa-stat:nth-child(4) { --pa-si: 3; }
  .pa-flow { --pa-si: 4; }
  .pa-audience { --pa-si: 5; }
  .motion-ready .pa-card.is-in .pa-flow__list::after {
    animation: m-draw-x 1.1s var(--m-ease-io) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + 520ms);
  }
  .motion-ready .pa-card.is-in .pa-flow__dot {
    animation: m-pop .5s var(--m-ease) backwards;
    animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + 480ms + var(--i, 0) * 1100ms / var(--n, 4));
  }
  .motion-ready .pa-card.is-in .pa-card__mark { animation: m-mark 1.2s var(--m-ease) backwards; animation-delay: calc(var(--motion-i, 0) * var(--m-stagger) + 120ms); }
  .dropdown-menu.show { animation: m-drop .22s var(--m-ease) backwards; }
  .ct-alert { animation: m-fade-up .6s var(--m-ease) backwards; }
}

/* ------------------------------------ 9. Header (condense, progress), to-top */
/* The bar shrinks while margin-bottom grows by the same amount, so the page
   below never moves (no scroll-anchoring jumps while the header condenses). */
.site-header {
  transition: border-color .35s ease, box-shadow .35s var(--m-ease-io), background-color .35s ease, margin-bottom .35s var(--m-ease-io);
}
.site-header__bar,
.site-logo__img { transition: height .35s var(--m-ease-io); }
.site-header.is-condensed { margin-bottom: calc(var(--header-h) - var(--header-h-condensed)); }

/* Reading progress: brand-red hairline along the top edge of the header. */
.site-header::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 2px;
  background: var(--c-brand-text);
  transform: scaleX(var(--m-progress, 0));
  transform-origin: var(--m-start) 50%;
  pointer-events: none;
}
@supports (animation-timeline: scroll()) {
  .site-header::after { animation: m-progress linear both; animation-timeline: scroll(root block); }
}

.to-top {
  position: fixed;
  z-index: 1025;
  right: max(1rem, calc(env(safe-area-inset-right) + .75rem));
  /* Stacked above the floating contact button (site.css: --float-bottom, --fab-size). */
  bottom: calc(var(--float-bottom, 1rem) + var(--fab-size, 0px) + .75rem);
  margin-bottom: var(--toast-lift, 0px);   /* follows the contact button above an app toast (site.css) */
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border: 1px solid var(--c-line);
  border-radius: 50%;
  background: color-mix(in srgb, var(--c-surface) 90%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  backdrop-filter: saturate(180%) blur(12px);
  box-shadow: var(--shadow-2);
  color: var(--c-ink);
  opacity: 0;
  visibility: hidden;
  transform: translateY(14px) scale(.9);
  transition: opacity .3s ease, transform .45s var(--m-ease), visibility 0s linear .45s, background-color .2s ease, color .2s ease, border-color .2s ease, bottom .3s var(--m-ease);
}
:root[dir="rtl"] .to-top { right: auto; left: max(1rem, calc(env(safe-area-inset-left) + .75rem)); }
.to-top.is-visible { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
.to-top .icon { transition: translate .4s var(--m-ease); }
.to-top:hover, .to-top:focus-visible { border-color: var(--c-ink); background: var(--c-ink); color: var(--c-bg); }
.to-top:is(:hover, :focus-visible) .icon { translate: 0 -2px; }
/* Install hint / standalone tab bar offsets come through --float-bottom (site.css). */
@media print { .to-top, .site-header::after { display: none !important; } }

/* Looping decorations pause while off-screen (motion.js). */
.m-paused, .m-paused * { animation-play-state: paused !important; }

/* ---------------------------------------------------- 10. Page transitions */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  .site-header { view-transition-name: site-header; }
  .tabbar { view-transition-name: site-tabbar; }
  ::view-transition-old(root) { animation: m-vt-out .26s var(--m-ease-io) both; }
  ::view-transition-new(root) { animation: m-vt-in .5s var(--m-ease) both; }
  ::view-transition-group(site-header),
  ::view-transition-group(site-tabbar) { animation-duration: .35s; animation-timing-function: var(--m-ease-io); }
}
/* Browsers without view transitions: a quiet fade-in on load. */
@supports not (view-transition-name: none) {
  @media screen and (prefers-reduced-motion: no-preference) {
    body { animation: m-fade .45s ease backwards; }
  }
}

/* ------------------------------------------------------------ 11. Keyframes */
@keyframes m-fade { from { opacity: 0; } }
@keyframes m-fade-up { from { opacity: 0; translate: 0 var(--m-shift); } }
@keyframes m-scale { from { opacity: 0; scale: .95; } }
@keyframes m-clip {
  from { opacity: 0; clip-path: inset(0 0 100% 0); }
  to { opacity: 1; clip-path: inset(0 0 0 0); }
}
@keyframes m-slide-start { from { opacity: 0; translate: calc(var(--m-dir) * -32px) 0; } }
@keyframes m-slide-end { from { opacity: 0; translate: calc(var(--m-dir) * 32px) 0; } }
@keyframes m-line {
  from { opacity: 0; translate: 0 .55em; clip-path: inset(-.5em -.5em 100% -.5em); }
  to { opacity: 1; translate: 0 0; clip-path: inset(-.5em -.5em -.5em -.5em); }
}
@keyframes m-draw-x { from { scale: 0 1; } }
@keyframes m-draw-y { from { scale: 1 0; } }
@keyframes m-step { from { opacity: 0; scale: .9; } }
@keyframes m-lit { 0% { opacity: 0; } 30% { opacity: 1; } 100% { opacity: 0; } }
@keyframes m-connector { from { opacity: 0; translate: calc(var(--m-dir) * -6px) 0; scale: .5 1; } }
@keyframes m-pop { from { opacity: 0; scale: .6; } }
@keyframes m-op { from { opacity: 0; scale: .4; rotate: -90deg; } }
@keyframes m-sheen {
  0% { opacity: 0; transform: translateX(calc(-100% * var(--m-dir))); }
  30% { opacity: 1; }
  100% { opacity: 0; transform: translateX(calc(100% * var(--m-dir))); }
}
@keyframes m-parallax { to { transform: translate3d(0, 14%, 0); opacity: .35; } }
@keyframes m-parallax-mark { to { transform: translate3d(0, 30%, 0) rotate(-8deg); } }
@keyframes m-mark { from { opacity: 0; scale: .88; rotate: -8deg; } }
@keyframes m-drop { from { opacity: 0; translate: 0 -6px; } }
@keyframes m-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes m-vt-out { to { opacity: 0; transform: translateY(-6px); } }
@keyframes m-vt-in { from { opacity: 0; transform: translateY(10px); } }
