/* ============================================================
   PERFECTO CLINIC — motion system, v5
   Rules this file obeys, without exception:
   1. Nothing content-bearing ever has opacity below 1 at rest.
      Every animation here either moves a decorative layer, or
      transforms an element that is already fully visible.
   2. The page is complete and readable with JavaScript disabled
      and with animations switched off.
   3. prefers-reduced-motion and the accessibility widget's
      stop-animations flag (html.a11y-nomotion) both halt everything.
   ============================================================ */

/* ---------- the keyframe library ---------- */

/* A gold hairline drawing itself in. Decorative divider only. */
@keyframes pf-rule{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* Slow drift on a photograph. Never on text. */
@keyframes pf-ken{from{transform:scale(1) translate3d(0,0,0)}to{transform:scale(1.07) translate3d(0,-1.2%,0)}}

/* Continuous rail for the press strip. Duplicated content, so it loops seamlessly. */
@keyframes pf-marquee{from{transform:translate3d(0,0,0)}to{transform:translate3d(50%,0,0)}}

/* A metallic sweep. Runs on a ::after layer, never on the text itself. */
@keyframes pf-sheen{from{transform:translate3d(-140%,0,0) skewX(-14deg)}to{transform:translate3d(240%,0,0) skewX(-14deg)}}

/* Entrance: movement only. Opacity stays at 1 throughout. */
@keyframes pf-rise{from{transform:translate3d(0,22px,0)}to{transform:translate3d(0,0,0)}}
@keyframes pf-slide-start{from{transform:translate3d(-26px,0,0)}to{transform:translate3d(0,0,0)}}

/* A number counting into place: it scales up from 0.94, never from invisible. */
@keyframes pf-figure{from{transform:scale(.94)}to{transform:scale(1)}}

/* Live indicator beside the Google rating. */
@keyframes pf-beacon{0%,100%{transform:scale(1);box-shadow:0 0 0 0 rgba(194,161,107,.5)}
  70%{transform:scale(1.04);box-shadow:0 0 0 10px rgba(194,161,107,0)}}

/* Carousel affordance: the first nudge that tells you the rail moves. */
@keyframes pf-nudge{0%,100%{transform:translate3d(0,0,0)}40%{transform:translate3d(-9px,0,0)}}

/* ---------- application ---------- */

/* Entrance. Base state is visible, on purpose and permanently. */
html.js .reveal{opacity:1}
html.js .reveal.in{animation:pf-rise var(--slow) var(--ease) both}
html.js .reveal.in.from-start{animation-name:pf-slide-start}
/* Stagger inside a group, capped so nothing waits long enough to look broken. */
html.js .stagger.in>*{animation:pf-rise var(--mid) var(--ease) both}
html.js .stagger.in>*:nth-child(2){animation-delay:70ms}
html.js .stagger.in>*:nth-child(3){animation-delay:140ms}
html.js .stagger.in>*:nth-child(4){animation-delay:210ms}
html.js .stagger.in>*:nth-child(n+5){animation-delay:280ms}

/* Photographs that drift. Opt in with .m-ken on the figure. */
.m-ken{overflow:hidden}
.m-ken>img{will-change:transform}
html.js .m-ken.in>img{animation:pf-ken 14s var(--ease) both alternate infinite}

/* The gold hairline. It is a real divider, so it is visible at rest
   and only replays the draw when it scrolls into view. */
.m-rule{display:block;height:1px;background:var(--gold);transform-origin:right center;border:0;margin:0}
html.js .m-rule.in{animation:pf-rule var(--slow) var(--ease) both}

/* Verified figures. Already legible; the animation only settles them. */
html.js .m-figure.in{animation:pf-figure var(--mid) var(--ease) both}

/* The beacon next to the live Google rating. */
.m-beacon{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--gold);margin-inline-end:.5rem;vertical-align:middle}
html.js .m-beacon{animation:pf-beacon 2.6s var(--ease) infinite}

/* Sheen on the primary action, on hover and focus only, never idling. */
.btn-primary{position:relative;overflow:hidden;isolation:isolate}
.btn-primary::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(100deg,transparent 0%,rgba(255,255,255,.28) 50%,transparent 100%);
  transform:translate3d(-140%,0,0) skewX(-14deg);
}
html.js .btn-primary:hover::after,html.js .btn-primary:focus-visible::after{animation:pf-sheen 820ms var(--ease) 1}

/* Press strip marquee. The track holds its logos twice so the loop is seamless. */
.m-marquee{overflow:hidden;position:relative}
.m-marquee .m-track{display:flex;gap:clamp(38px,5vw,86px);width:max-content;align-items:center}
html.js .m-marquee .m-track{animation:pf-marquee 42s linear infinite}
.m-marquee:hover .m-track,.m-marquee:focus-within .m-track{animation-play-state:paused}
/* Without JS the logos are simply a scrollable row. */
html:not(.js) .m-marquee{overflow-x:auto}

/* Carousel first-run affordance. Fires once, when the rail enters view. */
html.js .reel.nudge>.slide:first-child{animation:pf-nudge 1100ms var(--ease) 1}

/* ---------- the two global off switches ---------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important;
  }
  .reveal,.stagger>*,.m-ken>img,.m-rule,.m-figure{transform:none!important;opacity:1!important}
  .m-marquee{overflow-x:auto}
  .m-marquee .m-track{animation:none!important}
}
html.a11y-nomotion *,html.a11y-nomotion *::before,html.a11y-nomotion *::after{
  animation:none!important;transition:none!important;scroll-behavior:auto!important;
}
html.a11y-nomotion .reveal,html.a11y-nomotion .stagger>*,
html.a11y-nomotion .m-ken>img,html.a11y-nomotion .m-rule,html.a11y-nomotion .m-figure{
  transform:none!important;opacity:1!important;
}
html.a11y-nomotion .m-marquee{overflow-x:auto}

/* ---------- carousel chrome, v5 ---------- */
/* The rail itself is a native horizontal scroller. With JS off it keeps working:
   you scroll it with a finger, a trackpad, or the keyboard after tabbing to it. */
.reel{scroll-behavior:smooth}
.reel:focus-visible{outline:2px solid var(--focus);outline-offset:6px}
html:not(.js) .reel-ctl{display:none}      /* buttons that cannot work are not shown */
html:not(.js) .reel-hint{display:block}
.reel-hint{display:none;font-size:.82rem;color:var(--on-dark-3);margin:.6rem 0 0}
.band-paper .reel-hint{color:var(--on-paper-3)}

/* Disabled nav at the ends, so the control tells the truth about the rail. */
.reel-nav[aria-disabled="true"]{opacity:.42;cursor:default}
.reel-nav[aria-disabled="true"]:hover{border-color:var(--hair-dark);color:var(--on-dark-2)}

/* Progress hairline under the rail: a real position readout, not decoration. */
.reel-bar{position:relative;height:2px;background:var(--hair-dark);margin-top:clamp(14px,1.6vw,22px)}
.reel-bar span{position:absolute;inset-block:0;inset-inline-start:0;width:18%;background:var(--gold);
  transition:width var(--fast) var(--ease),inset-inline-start var(--fast) var(--ease)}
html:not(.js) .reel-bar{display:none}
.band-paper .reel-bar{background:var(--hair-paper)}
.band-paper .reel-nav,.band-paper .reel-play{border-color:var(--hair-paper);color:var(--on-paper-2)}
.band-paper .reel-nav:hover,.band-paper .reel-play:hover{border-color:var(--gold-deep);color:var(--gold-deep)}
.band-paper .reel-count{color:var(--on-paper-3)}
.band-paper .reel-count .num{color:var(--gold-deep)}
