/* bdils.com motion rules. Owner: Zephyrus. Pairs with motion-tokens.css and motion.js.
   Everything here animates transform / opacity / clip-path only. Layout-affecting properties are never animated.
   Classes are opt-in: markup adds data-m="..." hooks, motion.js adds .is-* states. No JS = content fully visible. */

/* ---- 0. no-JS and pre-init safety: nothing is hidden unless JS has marked the page ready ---- */
html.m-ready [data-m="reveal"]:not(.is-in){opacity:0;transform:translateY(var(--bd-m-reveal-y)) scale(var(--bd-m-reveal-scale))}
html.m-ready [data-m="reveal"].is-in{opacity:1;transform:none;
  transition:opacity var(--bd-m-reveal-dur) var(--bd-m-reveal-ease) var(--m-delay,0ms),transform var(--bd-m-reveal-dur) var(--bd-m-reveal-ease) var(--m-delay,0ms)}
[data-m="reveal"]{will-change:auto}

/* ---- 1. hero entrance ---- */
html.m-ready [data-m="headline"] > *{opacity:0;transform:translateY(var(--bd-m-hero-headline-y))}
html.m-ready [data-m="headline"].is-in > *{opacity:1;transform:none;
  transition:opacity var(--bd-m-hero-headline-dur) var(--bd-m-hero-headline-ease) var(--m-delay,0ms),transform var(--bd-m-hero-headline-dur) var(--bd-m-hero-headline-ease) var(--m-delay,0ms)}
html.m-ready [data-m="nav"]{opacity:0;transform:translateY(var(--bd-m-nav-y))}
html.m-ready [data-m="nav"].is-in{opacity:1;transform:none;transition:opacity var(--bd-m-nav-dur) var(--bd-ease-out) var(--bd-m-nav-delay),transform var(--bd-m-nav-dur) var(--bd-ease-out) var(--bd-m-nav-delay)}
html.m-ready [data-m="cta"] > *{opacity:0;transform:translateY(var(--bd-m-cta-y))}
html.m-ready [data-m="cta"].is-in > *{opacity:1;transform:none;transition:opacity var(--bd-m-cta-dur) var(--bd-ease-out) var(--m-delay,0ms),transform var(--bd-m-cta-dur) var(--bd-ease-out) var(--m-delay,0ms)}
/* pieces are animated by motion.js (WAAPI) so the stagger cap and per-piece rotation can be computed; the CSS only hides them before landing */
html.m-ready [data-m="pieces"]:not(.is-in) > *{opacity:0}

/* ---- 2. scroll: hero exit, CSS scroll-driven where supported ---- */
[data-m="hero"]{position:relative}
[data-m="hero"] .m-scrim{position:absolute;inset:0;background:var(--bd-ink);opacity:0;pointer-events:none}
@supports (animation-timeline:scroll()){
  [data-m="hero"] .m-bench{animation:m-bench-exit linear both;animation-timeline:view();animation-range:exit 0% exit 100%}
  [data-m="hero"] .m-scrim{animation:m-scrim-exit linear both;animation-timeline:view();animation-range:exit 0% exit 100%}
  [data-m="hero"][data-exit-pieces="1"] .m-pieces{animation:m-pieces-freeze linear both;animation-timeline:view();animation-range:exit 0% exit 100%}
}
@keyframes m-bench-exit{to{transform:translateY(calc(var(--bd-m-hero-exit-parallax) * 100vh)) scale(var(--bd-m-hero-exit-scale))}}
@keyframes m-scrim-exit{to{opacity:var(--bd-m-hero-exit-scrim)}}
@keyframes m-pieces-freeze{to{opacity:.55}}
/* JS fallback writes --m-exit (0..1) on [data-m="hero"] when scroll timelines are unsupported */
html.m-no-scroll-timeline [data-m="hero"] .m-bench{transform:translateY(calc(var(--m-exit,0) * var(--bd-m-hero-exit-parallax) * 100vh)) scale(calc(1 - (1 - var(--bd-m-hero-exit-scale)) * var(--m-exit,0)))}
html.m-no-scroll-timeline [data-m="hero"] .m-scrim{opacity:calc(var(--m-exit,0) * var(--bd-m-hero-exit-scrim))}

/* nav morph: fixed nav shrinks; height is on Apollo's .bd-nav.is-scrolled. We only set the timing. */
.bd-nav{transition-duration:var(--bd-m-nav-shrink-dur);transition-timing-function:var(--bd-m-nav-shrink-ease)}
/* scroll progress hairline (optional, v1/v3 only; v2/v4 hide it) */
.m-progress{position:fixed;left:0;top:0;height:2px;width:100%;background:var(--bd-orange);transform:scaleX(var(--m-progress,0));transform-origin:left;z-index:var(--bd-z-nav);pointer-events:none}
@supports (animation-timeline:scroll()){.m-progress{animation:m-progress linear both;animation-timeline:scroll(root)}}
@keyframes m-progress{from{transform:scaleX(0)}to{transform:scaleX(1)}}
[data-theme="skeuomorph"] .m-progress,[data-theme="retro"] .m-progress{display:none}

/* ---- 3. logo wall ---- */
html.m-ready [data-m="logos"] > *{opacity:0;transform:translateY(var(--bd-m-logo-in-y))}
html.m-ready [data-m="logos"].is-in > *{opacity:1;transform:none;transition:opacity var(--bd-m-logo-in-dur) var(--bd-m-logo-in-ease) var(--m-delay,0ms),transform var(--bd-m-logo-in-dur) var(--bd-m-logo-in-ease) var(--m-delay,0ms)}
[data-m="logos"] > *{position:relative;overflow:hidden}
[data-m="logos"] > * > .m-drift{display:block;animation:m-drift var(--bd-m-logo-drift-dur) ease-in-out infinite alternate;animation-delay:var(--m-phase,0ms);
  transition:transform var(--bd-m-logo-hover-dur) var(--bd-m-logo-hover-ease)}
[data-m="logos"] > *:hover > .m-drift,[data-m="logos"] > *:focus-within > .m-drift{animation-play-state:paused;transform:translateY(var(--bd-m-logo-hover-y))}
@keyframes m-drift{from{translate:0 calc(var(--bd-m-logo-drift-amp) * -1)}to{translate:0 var(--bd-m-logo-drift-amp)}}
[data-m="logos"] .m-glint{position:absolute;inset:-20% -40%;pointer-events:none;opacity:0;
  background:linear-gradient(105deg,transparent 42%,rgba(255,255,255,.75) 50%,transparent 58%);transform:translateX(-60%)}
[data-m="logos"] .m-glint.is-on{animation:m-glint var(--bd-m-logo-glint-dur) var(--bd-ease-standard) 1}
@keyframes m-glint{0%{opacity:0;transform:translateX(-60%)}15%{opacity:1}100%{opacity:0;transform:translateX(60%)}}
[data-theme="retro"] [data-m="logos"] .m-glint{background:linear-gradient(90deg,transparent 46%,rgba(255,255,255,.9) 46%,rgba(255,255,255,.9) 54%,transparent 54%)}

/* ---- 4. expertise tiles ---- */
[data-m="tile"]{transition:transform var(--bd-m-tile-hover-dur) var(--bd-m-tile-hover-ease),box-shadow var(--bd-m-tile-hover-dur) var(--bd-m-tile-hover-ease)}
[data-m="tile"]:hover,[data-m="tile"]:focus-within{transform:translateY(var(--bd-m-tile-hover-y))}
[data-m="tile"]:active{transform:translateY(0) scale(var(--bd-m-tile-press-scale));transition-duration:var(--bd-m-tile-press-dur)}

/* ---- 5. carousel (motion.js drives slides with WAAPI) ---- */
[data-m="carousel"] .m-track{position:relative;display:grid}
[data-m="carousel"] .m-track > *{grid-area:1/1}
[data-m="carousel"] .m-track > *:not(.is-active){visibility:hidden;pointer-events:none}
[data-m="carousel"] .m-track > *.is-leaving{visibility:visible}
.bd-dots i{transition:background var(--bd-m-dot-dur),transform var(--bd-m-dot-dur) var(--bd-ease-settle)}
.bd-dots i.on{transform:scale(1.2)}

/* ---- 6. press, card, modal ---- */
[data-m="press"],.bd-btn,.bd-iconbtn{transition:transform var(--bd-m-press-release-dur) var(--bd-m-press-release-ease),box-shadow var(--bd-m-press-release-dur) var(--bd-m-press-release-ease),background var(--bd-dur-fast)}
[data-m="press"]:active,.bd-btn:active,.bd-iconbtn:active,.is-pressed{transform:scale(var(--bd-m-press-scale));transition-duration:var(--bd-m-press-dur);transition-timing-function:var(--bd-m-press-ease)}
.bd-card{transition:transform var(--bd-m-card-hover-dur) var(--bd-m-card-hover-ease),box-shadow var(--bd-m-card-hover-dur) var(--bd-m-card-hover-ease)}
.bd-card:hover,.bd-card:focus-within{transform:translateY(var(--bd-m-card-hover-y))}
/* modal: override Apollo's keyframe animations with token-driven ones; close is run by motion.js (WAAPI) because CSS cannot animate display:none */
.bd-scrim.is-open{animation:m-fade var(--bd-m-scrim-dur) var(--bd-ease-standard) both}
.bd-scrim.is-open .bd-modal{animation:m-modal-in var(--bd-m-modal-in-dur) var(--bd-m-modal-in-ease) both}
@keyframes m-fade{from{opacity:0}}
@keyframes m-modal-in{from{opacity:0;transform:translateY(var(--bd-m-modal-y)) scale(var(--bd-m-modal-scale))}}
.bd-modal.is-shake{animation:m-shake var(--bd-m-shake-dur) var(--bd-m-shake-ease) both}
@keyframes m-shake{0%,100%{transform:translateX(0)}20%,60%{transform:translateX(calc(var(--bd-m-shake-x) * -1))}40%,80%{transform:translateX(var(--bd-m-shake-x))}}
.bd-modal.is-success .bd-modal__success{animation:m-unlock var(--bd-m-unlock-dur) var(--bd-m-unlock-ease) both}
@keyframes m-unlock{from{opacity:0;transform:translateY(var(--bd-m-unlock-y))}}
.bd-modal__lock{transition:transform var(--bd-m-unlock-dur) var(--bd-m-unlock-ease)}
.bd-modal.is-success .bd-modal__lock{transform:rotate(-12deg) translateY(-2px)}
@media (max-width:640px){.bd-scrim.is-open .bd-modal{animation-name:m-sheet-up}}
@keyframes m-sheet-up{from{opacity:0;transform:translateY(40px)}}

/* ---- 7. forms ---- */
.bd-input,.bd-textarea{transition:box-shadow var(--bd-m-focus-dur) var(--bd-ease-standard),border-color var(--bd-m-focus-dur)}
.bd-field .bd-help.is-error{animation:m-error-in var(--bd-m-error-dur) var(--bd-ease-out) both;color:var(--bd-error)}
@keyframes m-error-in{from{opacity:0;transform:translateY(var(--bd-m-error-y))}}
.bd-field.is-error .bd-input{animation:m-shake var(--bd-m-shake-dur) var(--bd-m-shake-ease) both;--bd-m-shake-x:3px}
.bd-btn.is-loading{pointer-events:none}
.bd-btn.is-loading > .m-label{opacity:0;transition:opacity var(--bd-m-submit-dur)}
.m-success{animation:m-unlock var(--bd-m-success-dur) var(--bd-m-success-ease) both}
.bd-tick svg path{stroke-dasharray:30;stroke-dashoffset:30;animation:m-draw var(--bd-m-success-dur) var(--bd-ease-out) 120ms both}
@keyframes m-draw{to{stroke-dashoffset:0}}

/* ---- 8. micro: toggle, tabs, nav link, mute ---- */
[data-m="toggle"] .knob{transition:transform var(--bd-m-toggle-dur) var(--bd-m-toggle-ease)}
[data-m="toggle"][aria-checked="true"] .knob{transform:translateX(var(--m-travel,20px))}
[data-m="tabs"] .m-ink{position:absolute;bottom:0;height:3px;background:var(--bd-orange);border-radius:2px;transform-origin:left;
  transition:translate var(--bd-m-tab-dur) var(--bd-m-tab-ease),width var(--bd-m-tab-dur) var(--bd-m-tab-ease)}
.bd-nav__link::after{transition-duration:var(--bd-m-link-dur)}
.bd-mute{transition:transform var(--bd-m-press-release-dur) var(--bd-m-press-release-ease)}
.bd-mute .bars i{transition:height var(--bd-m-mute-dur)}
.bd-mute[aria-pressed="false"] .bars i{animation:none;height:3px}

/* ---- control bar: bottom centre, hero only. Visibility is driven by motion.js (IntersectionObserver on the hero), never by scroll position maths ---- */
.m-bar{position:fixed;left:50%;bottom:20px;z-index:var(--bd-z-mute);translate:-50% 0;display:flex;gap:4px;padding:6px;border-radius:var(--bd-r-pill);background:var(--bd-plate);border:1px solid var(--bd-line);box-shadow:var(--bd-edge),var(--bd-lift-3);
  transform:translateY(var(--bd-m-bar-y));transition:transform var(--bd-m-bar-out-dur) var(--bd-m-bar-out-ease);will-change:transform}
.m-bar.is-shown{transform:none;transition:transform var(--bd-m-bar-in-dur) var(--bd-m-bar-in-ease)}
.m-bar[hidden]{display:none}
.m-bar > button{position:relative;display:inline-flex;align-items:center;gap:8px;min-height:40px;padding:0 14px;border:0;border-radius:var(--bd-r-pill);background:none;color:var(--bd-ink-2);font:600 13px/1 var(--bd-sans);cursor:pointer;
  transition:transform var(--bd-m-press-release-dur) var(--bd-m-press-release-ease),background var(--bd-dur-fast),color var(--bd-dur-fast);transform:translateY(0)}
.m-bar > button:hover{background:rgba(0,0,0,.06);color:var(--bd-ink)}
.m-bar > button:focus-visible{outline:2px solid var(--bd-orange);outline-offset:2px}
.m-bar > button[aria-pressed="true"]{background:var(--bd-ink);color:var(--bd-paper)}
.m-bar > button[aria-busy="true"]{opacity:.55;pointer-events:none}
.m-bar > button svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
/* return: buttons settle one after another (delay set by motion.js as --m-delay) */
.m-bar:not(.is-shown) > button{transform:translateY(8px);opacity:.0}
.m-bar.is-shown > button{transform:none;opacity:1;transition:transform var(--bd-m-bar-in-dur) var(--bd-m-bar-in-ease) var(--m-delay,0ms),opacity var(--bd-m-bar-in-dur) var(--bd-ease-out) var(--m-delay,0ms),background var(--bd-dur-fast)}
.m-bar .m-tip{position:absolute;left:50%;bottom:calc(100% + 10px);translate:-50% 0;padding:6px 9px;border-radius:var(--bd-r-sm);background:var(--bd-ink);color:var(--bd-paper);font:500 12px/1 var(--bd-sans);white-space:nowrap;opacity:0;transform:translateY(4px);pointer-events:none;transition:opacity var(--bd-dur-fast),transform var(--bd-dur-fast) var(--bd-ease-out)}
.m-bar > button:hover .m-tip,.m-bar > button:focus-visible .m-tip{opacity:1;transform:none}
[data-theme="retro"] .m-bar{border-radius:0;border:3px solid var(--bd-ink);box-shadow:6px 6px 0 #000;background:var(--bd-plate)}
[data-theme="retro"] .m-bar > button{border-radius:0;font-family:var(--bd-mono);text-transform:uppercase}
[data-theme="skeuomorph"] .m-bar{background:linear-gradient(#fbfbfb,#d4d4d4);box-shadow:inset 0 1px 0 #fff,0 4px 8px rgba(0,0,0,.35)}

/* ---- theme switch cover ---- */
.m-theme-cover{position:fixed;inset:0;z-index:999;background:var(--bd-m-theme-cover);opacity:0;pointer-events:none}
.m-theme-cover.is-on{pointer-events:auto}
/* v4: pixel wipe, scanline lines */
[data-theme="retro"] .m-theme-cover{background-image:repeating-linear-gradient(0deg,rgba(255,255,255,.06) 0 2px,transparent 2px 4px);background-color:var(--bd-m-theme-cover)}

/* ---- reduced motion: belt and braces for CSS animations the tokens don't reach ---- */
@media (prefers-reduced-motion:reduce){
  .m-bar,.m-bar > button{transition:none}
  .m-progress,[data-m="logos"] .m-glint{display:none}
  [data-m="logos"] > * > .m-drift{animation:none}
  .bd-mute .bars i{animation:none}
  *{scroll-behavior:auto!important}
}
[data-motion="reduced"] .m-progress,[data-motion="reduced"] [data-m="logos"] .m-glint{display:none}
[data-motion="reduced"] [data-m="logos"] > * > .m-drift{animation:none}
[data-motion="reduced"] .bd-mute .bars i{animation:none}
[data-motion="lite"] [data-m="logos"] > * > .m-drift{animation:none}
[data-motion="lite"] [data-m="logos"] .m-glint{display:none}

/* ---- v4 frame step helpers ---- */
[data-theme="retro"] [data-m="reveal"].is-in,[data-theme="retro"] [data-m="headline"].is-in > *,[data-theme="retro"] [data-m="logos"].is-in > *{transition-timing-function:steps(4,end)}
[data-theme="retro"] *{scroll-behavior:auto}
