/* ==========================================================================
   Ittihad Society — motion layer  (v1)
   Loaded AFTER site.css. Everything here is additive: remove this file and the
   two tags that load it, and the site is exactly as it was.

   Rules of the house
   - Nothing is ever hidden unless JavaScript is running AND the visitor has not
     asked for reduced motion. motion.js adds `jsm` to <html> only in that case,
     and every "hidden" state below is scoped to `.jsm`.
   - Each piece plays ONCE, when it is first scrolled into view.
   - Movement follows reading direction: content arrives from the right in
     Arabic and from the left in English.
   ========================================================================== */

:root{
  --m-ease:cubic-bezier(.2,.8,.2,1);     /* arrive: fast out, soft landing */
  --m-ease-soft:cubic-bezier(.3,0,.2,1);
  --m-dur:.72s;
}

/* direction sign: +1 in RTL, -1 in LTR — used for "enter from reading side" */
.jsm{--m-dir:1}
.jsm[dir="ltr"]{--m-dir:-1}

/* The site ships a Chrome-only scroll-driven reveal. While the motion layer is
   running it owns these elements instead, so the two never fight over opacity,
   and the reveal works in Firefox and Safari too. */
.jsm .sec-head,.jsm .inst,.jsm .news-card,.jsm .prog,.jsm .stat,.jsm .give-card,
.jsm .ar-doc,.jsm .era,.jsm .contact-card,.jsm .gallery figure,.jsm .howto__step,
.jsm .dept,.jsm .doc{animation:none!important}

/* ---------- the reveal engine ---------- */
.jsm [data-m]{will-change:opacity,transform}
.jsm [data-m]:not(.m-on){opacity:0}
.jsm [data-m].m-on{animation-duration:var(--m-dur);animation-timing-function:var(--m-ease);
  animation-fill-mode:both;animation-delay:calc(var(--d,0)*1ms)}

.jsm [data-m="rise"]:not(.m-on){transform:translateY(26px)}
.jsm [data-m="rise"].m-on{animation-name:m-rise}
@keyframes m-rise{from{opacity:0;transform:translateY(26px)}to{opacity:1;transform:none}}

.jsm [data-m="rise-sm"]:not(.m-on){transform:translateY(14px)}
.jsm [data-m="rise-sm"].m-on{animation-name:m-rise-sm}
@keyframes m-rise-sm{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}

/* cards: a hint of depth, never a full flip */
.jsm [data-m="tilt"]:not(.m-on){transform:perspective(1100px) rotateY(calc(var(--m-dir)*7deg)) translateY(22px)}
.jsm [data-m="tilt"].m-on{animation-name:m-tilt}
@keyframes m-tilt{from{opacity:0;transform:perspective(1100px) rotateY(calc(var(--m-dir)*7deg)) translateY(22px)}
  to{opacity:1;transform:none}}

/* rows that slide in from the reading side */
.jsm [data-m="slide"]:not(.m-on){transform:translateX(calc(var(--m-dir)*34px))}
.jsm [data-m="slide"].m-on{animation-name:m-slide}
@keyframes m-slide{from{opacity:0;transform:translateX(calc(var(--m-dir)*34px))}to{opacity:1;transform:none}}

.jsm [data-m="pop"]:not(.m-on){transform:scale(.82)}
.jsm [data-m="pop"].m-on{animation-name:m-pop;animation-timing-function:cubic-bezier(.2,1.25,.35,1)}
@keyframes m-pop{from{opacity:0;transform:scale(.82)}to{opacity:1;transform:none}}

/* ---------- headline: word by word ---------- */
.m-w{display:inline-block;overflow:hidden;vertical-align:bottom}
.m-w>i{display:inline-block;font-style:normal;will-change:transform}
.jsm .m-split:not(.m-on) .m-w>i{transform:translateY(112%)}
.jsm .m-split.m-on .m-w>i{animation:m-word .78s var(--m-ease) both;animation-delay:calc(var(--d,0)*1ms + var(--i)*62ms)}
@keyframes m-word{from{transform:translateY(112%)}to{transform:translateY(0)}}

/* a tatreez stitch that draws under a section heading */
.m-rule{display:block;height:6px;margin-top:.75rem;width:clamp(72px,18%,132px);
  background:repeating-linear-gradient(90deg,var(--thread) 0 7px,transparent 7px 13px);
  transform-origin:100% 50%;border-radius:2px}
[dir="ltr"] .m-rule{transform-origin:0 50%}
.sec-head--center .m-rule,.sec-head--center .m-rule{margin-inline:auto}
.section--ink .m-rule,.section--olive .m-rule,.page-head .m-rule,.donate-band .m-rule{
  background-image:repeating-linear-gradient(90deg,var(--gold) 0 5px,transparent 5px 10px)}
.jsm .m-rule:not(.m-on){transform:scaleX(0)}
.jsm .m-rule.m-on{animation:m-ruleIn .75s var(--m-ease-soft) both;animation-delay:calc(var(--d,0)*1ms + 170ms)}
@keyframes m-ruleIn{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* ---------- hero ---------- */
.jsm .hero__eyebrow::before{transform-origin:100% 50%}
.jsm[dir="ltr"] .hero__eyebrow::before{transform-origin:0 50%}
.jsm .hero:not(.m-on) .hero__eyebrow::before{transform:scaleX(0)}
.jsm .hero.m-on .hero__eyebrow::before{animation:m-ruleIn .55s var(--m-ease) .18s both}
.jsm .hero:not(.m-on) .hero__eyebrow{opacity:0}
.jsm .hero.m-on .hero__eyebrow{animation:m-rise-sm .6s var(--m-ease) .1s both}
.jsm .hero:not(.m-on) .hero__lead,
.jsm .hero:not(.m-on) .hero__cta{opacity:0;transform:translateY(16px)}
.jsm .hero.m-on .hero__lead{animation:m-rise-sm .7s var(--m-ease) .62s both}
.jsm .hero.m-on .hero__cta{animation:m-rise-sm .7s var(--m-ease) .76s both}

/* the stage: media arrives as a soft unveil, seal lands with a drawn gold ring */
.jsm .hero:not(.m-on) .hero__media{opacity:0;transform:translateY(22px) scale(.985)}
.jsm .hero.m-on .hero__media{animation:m-stage 1.05s var(--m-ease) .3s both}
@keyframes m-stage{from{opacity:0;transform:translateY(22px) scale(.985)}to{opacity:1;transform:none}}
.jsm .hero:not(.m-on) .hero__seal{opacity:0;transform:scale(.72) rotate(-12deg)}
.jsm .hero.m-on .hero__seal{animation:m-seal .85s cubic-bezier(.2,1.1,.3,1) .92s both}
@keyframes m-seal{from{opacity:0;transform:scale(.72) rotate(-12deg)}to{opacity:1;transform:none}}
.m-sealring{position:absolute;inset:-9px;pointer-events:none;overflow:visible}
.m-sealring circle{fill:none;stroke:var(--gold);stroke-width:2.2;stroke-linecap:round;
  stroke-dasharray:1;stroke-dashoffset:1}
.jsm .hero.m-on .m-sealring circle{animation:m-draw 1.35s var(--m-ease-soft) 1.15s both}
@keyframes m-draw{to{stroke-dashoffset:0}}
.jsm .hero:not(.m-on) .hero__scroll{opacity:0;transform:translate(var(--m-sx,-50%),10px)}
.jsm .hero.m-on .hero__scroll{animation:m-scrollin .7s var(--m-ease) 1.25s both}
@keyframes m-scrollin{from{opacity:0;transform:translate(var(--m-sx,-50%),10px)}
  to{opacity:1;transform:translate(var(--m-sx,-50%),0)}}
.jsm .hero.m-on .hero__scroll svg{animation:m-bob 2.4s ease-in-out 2.4s infinite}
@keyframes m-bob{0%,100%{transform:translateY(0)}50%{transform:translateY(4px)}}

/* ---------- stitched dividers ---------- */
.jsm .stitch.m-has{background-image:none}
.m-stitch{display:block;width:100%;height:100%;overflow:visible}
.m-stitch path{fill:none;stroke-width:2.6;stroke-linecap:round;stroke-dasharray:1;stroke-dashoffset:1}
.m-stitch .a{stroke:var(--thread)}
.m-stitch .b{stroke:var(--gold)}
.stitch--gold .m-stitch .a{stroke:var(--gold)}
.stitch--gold .m-stitch .b{stroke:#F0DCA8}
.jsm .stitch.m-on .m-stitch path{animation:m-draw .42s ease both;animation-delay:calc(var(--i)*26ms)}

/* ---------- about: the arch outline draws itself ---------- */
.about__photo{position:relative}
.m-arch{position:absolute;inset:0;pointer-events:none;z-index:2;overflow:visible}
.m-arch path{fill:none;stroke:var(--gold);stroke-width:2.5;stroke-linecap:round;
  stroke-dasharray:1;stroke-dashoffset:1;opacity:.9}
.jsm .about__photo.m-on .m-arch path{animation:m-draw 1.7s var(--m-ease-soft) .35s both}
.jsm .about__photo:not(.m-on) img{opacity:0;transform:scale(1.07)}
.jsm .about__photo.m-on img{animation:m-unveil 1.5s var(--m-ease-soft) both}
@keyframes m-unveil{from{opacity:0;transform:scale(1.07)}to{opacity:1;transform:none}}
.jsm .values .value:not(.m-on){opacity:0;transform:translateY(12px)}
.jsm .values .value.m-on{animation:m-rise-sm .6s var(--m-ease) both;animation-delay:calc(var(--i)*85ms)}

/* ---------- stats: a gold thread draws under each number ---------- */
.stat{position:relative}
.m-underline{display:block;height:3px;width:46px;margin:.55rem auto 0;border-radius:3px;
  background:linear-gradient(90deg,var(--gold),var(--thread));transform-origin:100% 50%}
[dir="ltr"] .m-underline{transform-origin:0 50%}
.jsm .stat:not(.m-on) .m-underline{transform:scaleX(0)}
.jsm .stat.m-on .m-underline{animation:m-ruleIn .8s var(--m-ease-soft) both;animation-delay:calc(var(--d,0)*1ms + 260ms)}

/* ---------- institutions: one sweep of light across each logo ---------- */
.inst{position:relative;overflow:hidden}
.m-shine{position:absolute;top:0;bottom:0;width:42%;z-index:4;pointer-events:none;inset-inline-start:-50%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.72),transparent);opacity:0}
.jsm .inst.m-on .m-shine{animation:m-shine 1.05s var(--m-ease-soft) both;animation-delay:calc(var(--d,0)*1ms + 280ms)}
@keyframes m-shine{0%{inset-inline-start:-50%;opacity:0}12%{opacity:1}88%{opacity:1}100%{inset-inline-start:118%;opacity:0}}

/* the hospital card: sunlight crosses the stone once */
.inst--lead .inst__photo{position:relative;overflow:hidden}
.m-sun{position:absolute;top:-35%;bottom:-35%;width:48%;z-index:3;pointer-events:none;inset-inline-start:-65%;
  background:linear-gradient(105deg,transparent,rgba(255,244,214,.8),transparent);filter:blur(4px);opacity:0}
.jsm .inst--lead.m-on .m-sun{animation:m-sun 1.9s var(--m-ease-soft) .5s both}
@keyframes m-sun{0%{inset-inline-start:-65%;opacity:0}15%{opacity:1}85%{opacity:1}100%{inset-inline-start:132%;opacity:0}}
.jsm .inst--lead:not(.m-on) .lead-facts li{opacity:0;transform:translateY(12px)}
.jsm .inst--lead.m-on .lead-facts li{animation:m-rise-sm .6s var(--m-ease) both;animation-delay:calc(.45s + var(--i)*110ms)}

/* ---------- timeline: the stations land in order ----------
   This design already draws its own connector (.tl__dot::before) and diamond
   (.tl__dot::after), so the motion layer animates THOSE rather than adding a
   second rail. Note the diamond is the ::after — rotating .tl__dot itself
   would swing its connector line into a diagonal. */
.jsm .tl__dot::before{transform-origin:100% 50%}
.jsm[dir="ltr"] .tl__dot::before{transform-origin:0 50%}
.jsm .tl-viewport:not(.m-on) .tl__item:not(.is-clone) .tl__dot::before{transform:scaleX(0)}
.jsm .tl-viewport.m-on .tl__item:not(.is-clone) .tl__dot::before{
  animation:m-ruleIn .7s var(--m-ease-soft) both;animation-delay:calc(.12s + var(--i)*170ms)}
.jsm .tl-viewport:not(.m-on) .tl__item:not(.is-clone) .tl__dot::after{transform:rotate(45deg) scale(0)}
.jsm .tl-viewport.m-on .tl__item:not(.is-clone) .tl__dot::after{
  animation:m-dot .5s cubic-bezier(.2,1.4,.4,1) both;animation-delay:calc(.25s + var(--i)*170ms)}
@keyframes m-dot{from{transform:rotate(45deg) scale(0)}to{transform:rotate(45deg) scale(1)}}
.jsm .tl-viewport:not(.m-on) .tl__item:not(.is-clone) .tl__year,
.jsm .tl-viewport:not(.m-on) .tl__item:not(.is-clone) .tl__text{opacity:0;transform:translateY(10px)}
.jsm .tl-viewport.m-on .tl__item:not(.is-clone) .tl__year{animation:m-rise-sm .55s var(--m-ease) both;animation-delay:calc(.18s + var(--i)*170ms)}
.jsm .tl-viewport.m-on .tl__item:not(.is-clone) .tl__text{animation:m-rise-sm .55s var(--m-ease) both;animation-delay:calc(.3s + var(--i)*170ms)}

/* ---------- programmes: the support chip slides on hover ---------- */
.prog__go{transition:transform .28s var(--m-ease),background-color .25s,color .25s}
.prog:hover .prog__go{transform:translateX(calc(var(--m-dir,1)*-6px))}

/* ---------- transparency seal: circle and tick are drawn ---------- */
.trust__seal{position:relative}
.jsm .trust__seal.m-has{color:transparent}
.m-tick{position:absolute;inset:0;width:100%;height:100%}
.m-tick circle,.m-tick path{fill:none;stroke:var(--gold);stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:1;stroke-dashoffset:1}
.m-tick circle{stroke-width:2.4;opacity:.75}
.m-tick path{stroke-width:5}
.jsm .trust.m-on .m-tick circle{animation:m-draw 1.1s var(--m-ease-soft) .15s both}
.jsm .trust.m-on .m-tick path{animation:m-draw .55s var(--m-ease) .85s both}

/* ---------- centenary medallion: a slow turn of light ---------- */
.seal-figure{position:relative;overflow:hidden}
.m-gleam{position:absolute;top:-40%;bottom:-40%;width:40%;z-index:2;pointer-events:none;inset-inline-start:-55%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.5),transparent);filter:blur(2px);opacity:0}
.jsm .donate-band.m-on .m-gleam{animation:m-sun 2.2s var(--m-ease-soft) .6s both}
.jsm .donate-band:not(.m-on) .seal-figure img{opacity:0;transform:scale(.9)}
.jsm .donate-band.m-on .seal-figure img{animation:m-pop .95s cubic-bezier(.2,1.1,.3,1) .2s both}
@media (prefers-reduced-motion:no-preference){
  .jsm .donate-band.m-on .seal-figure img{animation:m-pop .95s cubic-bezier(.2,1.1,.3,1) .2s both,m-float 7s ease-in-out 1.2s infinite}
  @keyframes m-float{0%,100%{translate:0 0}50%{translate:0 -8px}}
}

/* ---------- quick links: the icon ring fills on hover ---------- */
.quick__ico{position:relative}
.quick__ico::after{content:"";position:absolute;inset:-3px;border-radius:50%;border:2px solid var(--thread);
  opacity:0;transform:scale(.8);transition:opacity .3s,transform .35s var(--m-ease)}
.quick:hover .quick__ico::after{opacity:.55;transform:scale(1)}

/* ---------- reading progress on the header's edge ---------- */
.m-progress{position:absolute;inset-inline:0;bottom:-1px;height:2px;z-index:2;pointer-events:none;
  background:linear-gradient(90deg,var(--thread),var(--gold),var(--olive-600));
  transform:scaleX(var(--m-p,0));transform-origin:100% 50%;transition:transform .12s linear;opacity:.9}
[dir="ltr"] .m-progress{transform-origin:0 50%}

/* ---------- news media: a gentle push in on hover ---------- */
.news-card__media img,.news-card__media video{transition:transform .6s var(--m-ease)}
.news-card:hover .news-card__media img,.news-card:hover .news-card__media video{transform:scale(1.045)}

/* ---------- safety net ----------
   If anything above is ever left mid-flight (a tab restored from the back/forward
   cache, an observer that never fired), this makes the content visible again. */
.jsm .m-done [data-m],.jsm [data-m].m-on{opacity:1}
@media print{.jsm [data-m]{opacity:1!important;transform:none!important}}

/* the scroll hint is centred with a translate, so its reveal must keep that */
.jsm .hero__scroll{--m-sx:-50%}
.jsm[dir="rtl"] .hero__scroll{--m-sx:50%}

/* ---------- a single sheen crosses a primary button on hover ---------- */
.btn-donate,.btn-primary,.btn-gold{position:relative;overflow:hidden;isolation:isolate}
.btn-donate::after,.btn-primary::after,.btn-gold::after{content:"";position:absolute;top:-60%;bottom:-60%;width:38%;
  inset-inline-start:-50%;z-index:-1;pointer-events:none;opacity:0;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.38),transparent)}
.btn-donate:hover::after,.btn-primary:hover::after,.btn-gold:hover::after{animation:m-sheen .72s var(--m-ease-soft)}
@keyframes m-sheen{0%{inset-inline-start:-50%;opacity:0}20%{opacity:1}80%{opacity:1}100%{inset-inline-start:120%;opacity:0}}

/* ---------- quick links lift a little under the pointer ---------- */
.quick{transition:transform .28s var(--m-ease),background-color .22s}
.quick:hover{transform:translateY(-3px)}

/* ---------- institution cards settle, rather than snap, on hover ---------- */
.inst{transition:transform .34s var(--m-ease),box-shadow .34s,border-color .24s}

/* ==========================================================================
   Calm mode — prefers-reduced-motion: reduce
   --------------------------------------------------------------------------
   motion.js adds `jsm-calm` to <html> when the visitor's device asks for
   reduced motion, and skips building the travelling decorations entirely
   (shine, sunlight, gleam, reading bar, word split).

   What is left to do here is take the reveal engine, which is built on
   transforms, and reduce it to opacity alone. The preference is about motion:
   travel, parallax, scaling, rotation. A short fade is not motion, and is the
   accepted substitute — it keeps the page alive rather than switching it off.

   Everything that was drawn stroke by stroke is simply shown already drawn.
   ========================================================================== */

/* ---------- reveals: opacity only, never a transform ---------- */
.jsm-calm [data-m]{
  will-change:opacity;
  transition:opacity .5s linear;
  transition-delay:calc(var(--d,0)*1ms);
}
.jsm-calm [data-m]:not(.m-on){opacity:0;transform:none!important}
.jsm-calm [data-m].m-on{opacity:1;animation:none!important;transform:none!important}

/* ---------- headings: the tatreez rule appears, it does not grow ---------- */
.jsm-calm .m-rule{transition:opacity .5s linear;transition-delay:120ms}
.jsm-calm .m-rule:not(.m-on){opacity:0;transform:none!important}
.jsm-calm .m-rule.m-on{opacity:1;animation:none!important;transform:none!important}

/* a heading is revealed whole in calm mode, so any leftover split is inert */
.jsm-calm .m-split .m-w>i{transform:none!important;animation:none!important}
.jsm-calm .m-w{overflow:visible}

/* ---------- hero ---------- */
.jsm-calm .hero .hero__eyebrow,
.jsm-calm .hero.m-on .hero__eyebrow{opacity:1;animation:none!important;transform:none!important}
.jsm-calm .hero .hero__eyebrow::before,
.jsm-calm .hero.m-on .hero__eyebrow::before{animation:none!important;transform:none!important}

/* ---------- anything drawn with a stroke is shown complete ---------- */
.jsm-calm .stitch .m-stitch path,
.jsm-calm .about__photo .m-arch path,
.jsm-calm .trust .m-tick circle,
.jsm-calm .trust .m-tick path{
  animation:none!important;
  stroke-dashoffset:0!important;
}

/* ---------- static final states for the small decorations ---------- */
.jsm-calm .stat .m-underline,
.jsm-calm .stat.m-on .m-underline{animation:none!important;transform:none!important}

.jsm-calm .tl__dot::before,
.jsm-calm .tl-viewport.m-on .tl__item:not(.is-clone) .tl__dot::before{
  animation:none!important;transform:none!important}
.jsm-calm .tl__dot::after,
.jsm-calm .tl-viewport.m-on .tl__item:not(.is-clone) .tl__dot::after{
  animation:none!important;transform:rotate(45deg)!important}
.jsm-calm .tl-viewport:not(.m-on) .tl__item:not(.is-clone) .tl__year,
.jsm-calm .tl-viewport:not(.m-on) .tl__item:not(.is-clone) .tl__text{opacity:0;transform:none!important}
.jsm-calm .tl-viewport.m-on .tl__item:not(.is-clone) .tl__year,
.jsm-calm .tl-viewport.m-on .tl__item:not(.is-clone) .tl__text{
  opacity:1;animation:none!important;transform:none!important;
  transition:opacity .5s linear;transition-delay:calc(var(--i,0)*60ms)}

.jsm-calm .inst--lead.m-on .lead-facts li{animation:none!important;transform:none!important;opacity:1}

/* the medallion arrives without the pop, and never floats */
.jsm-calm .donate-band .seal-figure img,
.jsm-calm .donate-band.m-on .seal-figure img{
  opacity:1;animation:none!important;transform:none!important;translate:none!important}

/* ---------- travelling highlights are not built in calm mode;
             this is the belt to that braces ---------- */
.jsm-calm .m-shine,
.jsm-calm .m-sun,
.jsm-calm .m-gleam,
.jsm-calm .m-progress{display:none!important}

/* ---------- hover effects that move, reduced to colour alone ---------- */
.jsm-calm .prog:hover .prog__go{transform:none!important}
.jsm-calm .news-card:hover .news-card__media img,
.jsm-calm .news-card:hover .news-card__media video{transform:none!important}
.jsm-calm .quick:hover .quick__ico::after{transform:none!important}
.jsm-calm .btn-donate:hover::after,
.jsm-calm .btn-primary:hover::after,
.jsm-calm .btn-gold:hover::after{animation:none!important;opacity:0!important}
