/* ==========================================================================
   Michela Mancino · Motion
   One material, carried through the page: the line.
   Display type is written in with a soft left-to-right wipe, hairlines are
   drawn like ink, the orbit draws itself around what matters.
   The hero is the one authored sequence; every section after it gets a
   single, quieter gesture tied to what it says.

   Values written by motion.js:
     --p       0..1 scroll progress on [data-scroll] elements
     --drift   px, scroll parallax on [data-depth] hazes
     --mx/--my -1..1 eased pointer position over the hero (desktop pointers)
     --k       order among siblings that arrive together (stagger)
     --n       index of a split word or digit
   Hidden start states exist only under html.motion, which motion.js sets
   once the observers that release them are running.
   ========================================================================== */

@property --sweep {
  syntax: "<angle>";
  inherits: false;
  initial-value: 360deg;
}

:root {
  --ease-ink: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-wipe: 1.4s;
  --dur-ink: 1.3s;
  --stagger: 110ms;
}

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

  /* ======================= 1 · hero: the load sequence =======================
     CSS only, so it plays even before motion.js: nav, portrait opening,
     haze blooming, the name written, the orbit drawn, then the intro. */

  .top__in > * { animation: fade 1s ease 0.1s both; }
  .top__in > .nav { animation-delay: 0.3s; }

  .portrait { animation: unveil 1.4s var(--ease-out) 0.1s both; }
  .portrait img { animation: settle 2.4s var(--ease-out) 0.1s backwards; }
  .hero .haze--warm { animation: bloom 2.4s var(--ease-out) 0.15s both; }
  .hero .haze--shade { animation: fade 2.4s ease 0.3s both; }

  .name__word,
  .motion .reveal {
    -webkit-mask-image: var(--mask-wipe);
    mask-image: var(--mask-wipe);
    -webkit-mask-size: 260% 100%;
    mask-size: 260% 100%;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
  }
  .name__word { animation: wipe 1.5s var(--ease-wipe) both; }
  .name__word--first { animation-delay: 0.45s; }
  .name__word--last { animation-delay: 1.05s; }

  .orbit ellipse, .orbit path { stroke-dasharray: 1; animation: draw 1.8s var(--ease-out) 0.8s both; }

  .intro > * { animation: lift 1s var(--ease-out) both; }
  .intro > :nth-child(1) { animation-delay: 1.2s; }
  .intro > :nth-child(2) { animation-delay: 1.3s; }
  .intro > :nth-child(3) { animation-delay: 1.4s; }
  .intro > :nth-child(4) { animation-delay: 1.5s; }
  .intro > :nth-child(5) { animation-delay: 1.6s; }

  .badge { animation: fade 1.2s ease 1.6s both; }
  .badge__ring { animation: spin-in 2s var(--ease-out) 1.5s backwards; }

  /* the call to action answers once, after the name has settled */
  .intro .pill .ico { animation: ring 1s ease-in-out 2.6s; }

  /* ======================= 2 · hero: depth and departure =======================
     Pointer: layers shift by depth, the photo counter-moves inside its capsule.
     Scroll: the name parts around the portrait as the page leaves it. */

  .name__word--first { translate: calc(var(--mx, 0) * 14px - var(--p, 0) * 6cqw) calc(var(--my, 0) * 9px); }
  .name__word--last { translate: calc(var(--mx, 0) * 14px + var(--p, 0) * 6cqw) calc(var(--my, 0) * 9px); }
  .portrait {
    translate: calc(var(--mx, 0) * 5px) calc(var(--my, 0) * 3px);
    scale: calc(1 - var(--p, 0) * 0.06);
  }
  .portrait img {
    translate: calc(var(--mx, 0) * -4px) calc(var(--my, 0) * -3px);
    scale: calc(1.04 + var(--p, 0) * 0.14);
  }
  .orbit {
    translate: calc(var(--mx, 0) * 9px) calc(var(--my, 0) * 6px);
    rotate: calc(8deg + var(--p, 0) * 7deg);
  }
  .hero .haze { translate: calc(var(--mx, 0) * -20px) calc(var(--drift, 0px) + var(--my, 0) * -14px); }

  /* while the pointer rests on the portrait the capsule turns onto the orbit's axis,
     like a body inside its ring (motion.js sets .is-turned) */
  .portrait { transition: rotate 0.9s var(--ease-out); }
  .portrait.is-turned { rotate: calc(8deg + var(--p, 0) * 7deg); }
  .motion .hero :is(.name__word, .portrait, .orbit) { will-change: translate; }
  .motion .haze.is-live { will-change: translate; }

  /* ======================= 3 · the written line =======================
     Serif display type wipes in left to right as it enters. */

  .motion [data-reveal] { --d: calc(var(--k, 0) * var(--stagger)); }

  .motion .reveal {
    -webkit-mask-position: 100% 0;
    mask-position: 100% 0;
    transition:
      -webkit-mask-position var(--dur-wipe) var(--ease-wipe) calc(var(--d, 0ms) + var(--wd, 0ms)),
      mask-position var(--dur-wipe) var(--ease-wipe) calc(var(--d, 0ms) + var(--wd, 0ms));
  }
  .motion .is-in.reveal, .motion .is-in .reveal { -webkit-mask-position: 0 0; mask-position: 0 0; }
  /* once written, the mask goes so descenders and overhangs are never cropped */
  .motion .reveal.is-written { -webkit-mask-image: none; mask-image: none; }

  .motion .cred__v { --wd: 100ms; }
  .motion .step__n { --wd: 250ms; }

  /* ======================= 4 · the drawn line =======================
     Hairlines arrive like ink, from the left; separators fall from the top. */

  .motion :is(.svc, .entry, .belief, .door, .crow, .skills li, .topic, .step, .creds__list, .assure, .crows) { position: relative; }
  .motion :is(.svc, .entry, .belief, .door, .crow, .skills li) { border-bottom-color: transparent; }
  .motion :is(.topic, .step, .crows) { border-top-color: transparent; }
  .motion :is(.creds__list, .assure) { border-block-color: transparent; }

  .motion :is(.svc, .entry, .belief, .door, .crow, .skills li, .creds__list, .assure)::after,
  .motion :is(.topic, .step, .creds__list, .assure, .crows)::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 1px;
    background: var(--ink, var(--rule));
    scale: 0 1;
    transform-origin: 0 50%;
    pointer-events: none;
    transition: scale var(--dur-ink) var(--ease-ink) var(--d, 0ms);
  }
  .motion :is(.svc, .entry, .belief, .door, .crow, .skills li, .creds__list, .assure)::after { bottom: -1px; }
  .motion :is(.topic, .step, .creds__list, .assure, .crows)::before { top: -1px; }
  .motion :is(.creds__list, .assure)::after { transition-delay: calc(var(--d, 0ms) + 300ms); }
  .motion .is-in:is(.svc, .entry, .belief, .door, .crow, .skills li, .creds__list, .assure)::after,
  .motion .is-in:is(.topic, .step, .creds__list, .assure, .crows)::before { scale: 1 1; }

  .motion .contact { --ink: var(--on-dark-rule); }

  @media (min-width: 861px) {
    .motion :is(.cred + .cred, .assure__item + .assure__item) { position: relative; border-left-color: transparent; }
    .motion :is(.cred + .cred, .assure__item + .assure__item)::before {
      content: "";
      position: absolute;
      left: -1px;
      top: 0;
      bottom: 0;
      width: 1px;
      background: var(--rule-soft);
      scale: 1 0;
      transform-origin: 50% 0;
      transition: scale 1s var(--ease-ink) calc(var(--d, 0ms) + 350ms);
    }
    .motion .is-in:is(.cred, .assure__item)::before { scale: 1 1; }
  }

  /* ======================= 5 · the quiet layer =======================
     Reading text settles in after its heading or line, never before. */

  .motion :is(
    .cred__k, .approach__text > p:not(.lead), .svc__body, .vision__cite, .vision__text > *,
    .belief__text, .door__text, .about__body > *, .pagehead__lede > *, .area__intro, .part__lead,
    .topic > p, .step > :is(h3, p), .assure dt, .assure dd, .close__actions,
    .entry > *, .contact__lede, .crow > :not(.crow__tel)
  ) {
    opacity: 0;
    translate: 0 0.75rem;
    transition:
      opacity 0.9s ease calc(var(--d, 0ms) + var(--fd, 0ms)),
      translate 1.1s var(--ease-out) calc(var(--d, 0ms) + var(--fd, 0ms));
  }
  .motion .is-in :is(
    .cred__k, .approach__text > p:not(.lead), .svc__body, .vision__cite, .vision__text > *,
    .belief__text, .door__text, .about__body > *, .pagehead__lede > *, .area__intro, .part__lead,
    .topic > p, .step > :is(h3, p), .assure dt, .assure dd,
    .entry > *, .crow > :not(.crow__tel)
  ),
  .motion :is(.vision__text, .about__body, .pagehead__lede, .close__actions, .contact__lede).is-in > *,
  .motion :is(.close__actions, .contact__lede).is-in { opacity: 1; translate: none; }

  .motion .cred__k { --fd: 300ms; }
  .motion .approach__text > p:not(.lead) { --fd: 900ms; }
  .motion .svc__body { --fd: 300ms; }
  .motion .vision__cite { --fd: 700ms; }
  .motion :is(.vision__text, .about__body, .pagehead__lede) > :nth-child(2) { --fd: 150ms; }
  .motion :is(.about__body, .pagehead__lede) > :nth-child(3) { --fd: 300ms; }
  .motion :is(.belief__text, .door__text, .area__intro, .part__lead) { --fd: 300ms; }
  .motion .topic > p { --fd: 250ms; }
  .motion .step > h3 { --fd: 500ms; }
  .motion .step > p { --fd: 600ms; }
  .motion .assure dd { --fd: 450ms; }
  .motion .close__actions { --fd: 400ms; }
  .motion .entry > :nth-child(2) { --fd: 120ms; }
  .motion .entry > :nth-child(3) { --fd: 240ms; }
  .motion .crow > :nth-child(2) { --fd: 120ms; }

  /* hazes: warm light arrives with its section */
  .motion .haze[data-reveal] {
    opacity: 0;
    scale: 0.8;
    transition: opacity 2s ease, scale 2.8s var(--ease-out);
  }
  .motion .haze.is-in { opacity: 1; scale: 1; }

  /* ======================= 6 · one gesture per section ======================= */

  /* profilo: the lead comes into focus a word at a time, the way a profile does */
  .motion .split-w {
    display: inline-block;
    opacity: 0;
    filter: blur(6px);
    translate: 0 0.25em;
    transition:
      opacity 0.8s ease,
      filter 1.1s var(--ease-out),
      translate 1.1s var(--ease-out);
    transition-delay: calc(var(--d, 0ms) + 250ms + var(--n, 0) * 26ms);
  }
  .motion .is-in .split-w { opacity: 1; filter: none; translate: none; }

  /* visione: the quote fades up, then the orbit is drawn round "visto da te" */
  .motion .vision__quote {
    opacity: 0;
    translate: 0 1rem;
    transition: opacity 1.2s ease, translate 1.4s var(--ease-out);
  }
  .motion .vision__fig.is-in .vision__quote { opacity: 1; translate: none; }
  .motion .ring-word__orbit :is(ellipse, path) {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    transition: stroke-dashoffset 1.8s var(--ease-out) 900ms;
  }
  .motion .vision__fig.is-in .ring-word__orbit :is(ellipse, path) { stroke-dashoffset: 0; }

  /* the examples arrive like cards set down one after another */
  .cases__list { --stagger: 140ms; }
  .motion .case {
    opacity: 0;
    translate: 0 1rem;
    transition: opacity 0.9s ease var(--d, 0ms), translate 1.1s var(--ease-out) var(--d, 0ms);
  }
  .motion .case.is-in { opacity: 1; translate: none; }

  /* capsule photos open the way the hero portrait does. The image is clipped, not
     the figure: a clipped target would hide itself from the observer that releases it */
  .motion :is(.about__photo, .pagehead__photo, .direct__photo) { background: transparent; }
  .motion :is(.about__photo, .pagehead__photo, .direct__photo) img {
    clip-path: inset(46% 0 46% 0 round 999px);
    transition: clip-path 1.4s var(--ease-out) var(--d, 0ms);
  }
  .motion .is-in:is(.about__photo, .pagehead__photo) img,
  .motion .direct.is-in .direct__photo img { clip-path: inset(0 0 0 0 round 999px); }

  /* come si inizia: three steps drawn as one path, line then number then words */
  .steps { --stagger: 380ms; }
  .assure { --stagger: 180ms; }
  .motion .assure__ico { position: relative; box-shadow: none; }
  .motion .assure__ico::before {
    --sweep: 0deg;
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    box-shadow: inset 0 0 0 1px var(--taupe);
    -webkit-mask-image: conic-gradient(#000 var(--sweep), transparent 0);
    mask-image: conic-gradient(#000 var(--sweep), transparent 0);
    transition: --sweep 1.3s var(--ease-ink) calc(var(--d, 0ms) + 100ms);
  }
  .motion .is-in .assure__ico::before { --sweep: 360deg; }
  .motion .assure__ico .ico {
    opacity: 0;
    scale: 0.6;
    transition:
      opacity 0.6s ease calc(var(--d, 0ms) + 700ms),
      scale 0.9s var(--ease-out) calc(var(--d, 0ms) + 700ms);
  }
  .motion .is-in .assure__ico .ico { opacity: 1; scale: 1; }
  .motion .call.is-in .pill .ico { animation: ring 1s ease-in-out calc(var(--d, 0ms) + 1.2s); }

  /* contatti: the capsule opens into the closing field, the orbit returns,
     and the number is dialled in, one digit at a time */
  .motion .contact[data-scroll] {
    --open: calc(1 - var(--p, 1));
    clip-path: inset(0 calc(var(--open) * 6vw) 0 round calc(var(--open) * 44vw) calc(var(--open) * 44vw) 0 0);
  }
  .motion .contact__orbit ellipse {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    transition: stroke-dashoffset 2.6s var(--ease-out) 0.2s;
  }
  .motion .contact__orbit.is-in ellipse { stroke-dashoffset: 0; }
  .contact__orbit { rotate: calc(-9deg + (var(--p, 0.5) - 0.5) * 14deg); }
  .motion .crow__tel { overflow: clip; }
  .motion .split-c {
    display: inline-block;
    translate: 0 108%;
    transition: translate 1s var(--ease-out) calc(var(--d, 0ms) + 200ms + var(--n, 0) * 55ms);
  }
  .motion .is-in .split-c { translate: none; }

  /* ======================= 7 · feedback ======================= */

  .nav--menu[open] ul { transform-origin: 100% 0; animation: menu-in 0.4s var(--ease-out); }
  .nav--menu[open] li { animation: lift 0.5s var(--ease-out) backwards; animation-delay: calc(80ms + var(--n, 0) * 35ms); }

  /* focus rings settle onto their target instead of popping */
  :where(a, summary):not(.badge, .brand):focus-visible { animation: focus-in 0.3s var(--ease-out); }
}

/* ======================= reduced motion: stillness, not absence =======================
   Nothing travels. The hero fades in as one, the dock fades instead of
   sliding, hover nudges are dropped; colour and opacity feedback stay. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .stage { animation: fade 0.6s ease both; }
  .pill .ico, .textlink--arrow .ico, .badge__arrow { transition: none; }
  .pill:hover .ico, .textlink--arrow:hover .ico, .badge:hover .badge__arrow { rotate: none; translate: none; }  .pill:active { scale: none; }
  .dock { translate: none; opacity: 0; transition: opacity 0.3s ease, visibility 0s linear 0.3s; }
  .dock.is-on { opacity: 1; transition: opacity 0.3s ease; }
  .crow__tel, .foot__col a { transition-duration: 0.01ms; }
}

@keyframes wipe {
  from { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  to { -webkit-mask-position: 0 0; mask-position: 0 0; }
}
@keyframes unveil {
  from { clip-path: inset(46% 0 46% 0 round 999px); }
  to { clip-path: inset(0 0 0 0 round 999px); }
}
@keyframes settle { from { scale: 1.22; } }
@keyframes draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes bloom { from { opacity: 0; scale: 0.72; } }
@keyframes fade { from { opacity: 0; } }
@keyframes lift { from { opacity: 0; translate: 0 14px; } }
@keyframes spin-in { from { rotate: -140deg; } }
@keyframes ring {
  0%, 100% { rotate: 0deg; }
  12% { rotate: -16deg; }
  26% { rotate: 12deg; }
  40% { rotate: -9deg; }
  54% { rotate: 5deg; }
  68% { rotate: -2deg; }
}
@keyframes menu-in { from { opacity: 0; scale: 0.94; translate: 0 -6px; } }
@keyframes focus-in { from { outline-offset: 10px; outline-color: transparent; } }
