/* SIGNL SECTION LIBRARY — the technique layer.
   Mined per quarry/QUARRY-CLINICAL-SPORTS-MEDICINE.md and ported to vanilla CSS.
   Ships to client sites. No framer-motion, no GSAP, no shadcn, no third-party runtime. */

/* ── T1 · MASKED LINE REVEAL ─────────────────────────────────────────────────
   The line sits in a clipping box and slides UP into view. Reads as typeset
   rather than faded-in, which is the 2020 default and now reads as a template.
   The mask edge is hard on purpose — text is UNCOVERED, not dissolved. */
.rv{display:block;overflow:hidden}
.rv>span{display:block;transform:translateY(105%);
  transition:transform .82s cubic-bezier(.16,1,.3,1)}
.is-in .rv>span,.rv.is-in>span{transform:none}
.rv:nth-child(1)>span{transition-delay:0ms}
.rv:nth-child(2)>span{transition-delay:75ms}
.rv:nth-child(3)>span{transition-delay:150ms}
.rv:nth-child(4)>span{transition-delay:225ms}

/* ── T3 · NATIVE SCROLL-DRIVEN ANIMATION ─────────────────────────────────────
   animation-timeline drives this from scroll position with ZERO JavaScript.
   Most of the 21st catalog still ships a library to do exactly this. Smaller
   payload -> better LCP -> better local SEO: the modern technique and the fast
   technique are the same technique.
   ★ Guarded by @supports, and the UN-animated state is the VISIBLE state, so a
   browser without support (or a reduced-motion visitor) sees a complete page. */
@supports (animation-timeline: view()){
  @media (prefers-reduced-motion: no-preference){
    .sd{animation:sd-rise linear both;animation-timeline:view();
        animation-range:entry 8% cover 34%}
    .sd-slow{animation:sd-rise linear both;animation-timeline:view();
        animation-range:entry 2% cover 46%}
  }
}
@keyframes sd-rise{from{opacity:0;transform:translateY(30px)}to{opacity:1;transform:none}}

/* ── T2 · STICKY SCROLL NARRATIVE (the "beats") ──────────────────────────────
   The media pins while it scales and dims; the copy for each beat crossfades
   through it. Turns a LIST into a NARRATIVE — scroll becomes the clock.
   This is the counter-move to the four-card grid every template produces. */
.beats{position:relative}
.beat{min-height:100svh;display:grid;align-content:center;position:relative;z-index:2;
  padding:clamp(2rem,6vw,5rem) 0}
.beats__media{position:sticky;top:0;height:100svh;margin-bottom:-100svh;z-index:1;overflow:hidden}
.beats__media img{width:100%;height:100%;object-fit:cover}
.beats__media::after{content:"";position:absolute;inset:0;
  background:linear-gradient(90deg,rgba(10,14,18,.9) 0%,rgba(10,14,18,.62) 52%,rgba(10,14,18,.35) 100%)}
.beat__card{max-width:34rem;color:#fff}
.beat__n{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-size:var(--step--1);
  letter-spacing:.2em;color:var(--steel-lift);font-weight:500}
.beat__card h3{font-size:var(--step-2);margin:.7rem 0 .9rem;color:#fff;text-transform:uppercase}
.beat__card p{color:rgba(255,255,255,.84);margin:0;font-size:var(--step-0);line-height:1.7}
.beat__card .more{display:inline-block;margin-top:1.3rem;color:#fff;font-weight:600;
  border-bottom:2px solid var(--steel-lift);padding-bottom:2px;text-decoration:none}
@supports (animation-timeline: view()){
  @media (prefers-reduced-motion: no-preference){
    .beat__card{animation:beat-in linear both;animation-timeline:view();
      animation-range:entry 12% cover 32%}
  }
}
@keyframes beat-in{from{opacity:0;transform:translateY(34px)}to{opacity:1;transform:none}}
@media (max-width:760px){
  .beats__media{position:relative;height:44svh;margin-bottom:0}
  .beat{min-height:0;padding:2.4rem 0}
  .beats{background:#0a0e12}
}

/* ── T5 · PROGRESSIVE-BLUR MASK EDGES ────────────────────────────────────────
   A real mask, not an overlay rectangle faked over the background. */
.marquee{overflow:hidden;padding:1.15rem 0;border-block:1px solid var(--line);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 9%,#000 91%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 9%,#000 91%,transparent)}
.marquee__track{display:flex;gap:3rem;width:max-content;
  animation:mq 42s linear infinite;animation-play-state:running}
.marquee:hover .marquee__track{animation-play-state:paused}
.marquee span{white-space:nowrap;font-size:var(--step--1);letter-spacing:.13em;
  text-transform:uppercase;color:var(--graphite);font-weight:600}
@keyframes mq{to{transform:translateX(-50%)}}

@media (prefers-reduced-motion: reduce){
  .rv>span{transform:none!important}
  .marquee__track{animation:none!important}
  .sd,.sd-slow,.beat__card{opacity:1!important;transform:none!important;animation:none!important}
}

/* ── T6 · CONTINUOUS SCROLL-LINKED DEPTH  ★ the fix for "it looks static" ─────
   Founder note: entry reveals fire ONCE and then the page sits still — a
   slideshow, not a living page. The move is animation across the element's WHOLE
   visibility range (cover 0% -> cover 100%) instead of a one-shot entry window,
   with different layers moving at different rates. That rate difference IS depth.
   Still zero JS: animation-timeline does the whole thing. */
@supports (animation-timeline: view()){
  @media (prefers-reduced-motion: no-preference){
    /* media drifts UP slower than the page scrolls — the classic parallax read,
       done natively. Overscaled first so the drift never exposes an edge. */
    .px{animation:px-drift linear both;animation-timeline:view();
        animation-range:cover 0% cover 100%}
    .px img{will-change:transform}
    /* copy drifts the OPPOSITE way, which is what separates the planes */
    .px-copy{animation:px-lift linear both;animation-timeline:view();
        animation-range:cover 0% cover 100%}
    /* the pinned beats media keeps breathing the whole time it is pinned */
    .beats__media img{animation:beat-breathe linear both;animation-timeline:view();
        animation-range:cover 0% cover 100%}
    /* header condenses as you leave the top — the page acknowledges the scroll */
    .hdr{animation:hdr-condense linear both;animation-timeline:scroll();
        animation-range:0 220px}
  }
}
@keyframes px-drift{from{transform:scale(1.12) translateY(-2.2%)}
                    to{transform:scale(1.12) translateY(2.2%)}}
@keyframes px-lift{from{transform:translateY(14px)}to{transform:translateY(-14px)}}
@keyframes beat-breathe{from{transform:scale(1.16)}to{transform:scale(1)}}
@keyframes hdr-condense{to{box-shadow:0 10px 30px -18px rgba(10,14,18,.35)}}

/* Below the width where hero/practitioner stack to one column, the drift's own
   scale(1.12) overflow plus its translate visually overlaps the copy block
   sitting directly above — confirmed via computed transforms, not a screenshot
   artifact: at rest the image's rendered top edge sits ~40px above the CTA
   row's bottom edge. Parallax depth reads best on wide layouts anyway; disable
   it here rather than shrink the type or hand-tune a margin against it. */
@media (max-width:919px){
  .px,.px-copy{animation:none!important;transform:none!important}
}

/* hover with weight rather than a colour swap */
.card,.btn,.hero__img{will-change:transform}
.hero__img img{transition:transform 1.1s cubic-bezier(.2,.7,.3,1)}
.hero__img:hover img{transform:scale(1.03)}

@media (prefers-reduced-motion: reduce){
  .px,.px-copy,.beats__media img,.hdr{animation:none!important;transform:none!important}
}

/* ── REF-01 · KEYWORD CAPSULE IN THE HEADLINE ★★★ ───────────────────────────
   Phenomenon's signature move: one phrase inside the h1 wrapped in a solid pill.
   Makes a headline read as designed rather than set. Uses the brand's own ink so
   it never becomes a second accent colour competing with the CTA. */
h1 .cap,h2 .cap{font-style:normal;background:var(--ink);color:var(--paper);
  border-radius:.44em;padding:.02em .34em .1em;display:inline-block;
  line-height:1.02;box-decoration-break:clone;-webkit-box-decoration-break:clone}
h2 .cap{background:var(--steel)}

/* ── REF-01 · CARDS THAT BREAK THE CONTAINER ★★ ─────────────────────────────
   They overlap the image instead of sitting beside it. Overlap is depth without
   motion — the structural answer to a page that reads flat. */
.hero__img{position:relative;overflow:visible}
.hero__img>img{border-radius:inherit}
.fcard{position:absolute;background:var(--card);border-radius:18px;padding:1rem 1.1rem;
  width:min(15.5rem,62%);border:2px solid var(--ink);z-index:3}
.fcard__k{display:block;font-family:var(--font-mono);font-size:.68rem;letter-spacing:.13em;
  text-transform:uppercase;color:var(--steel);font-weight:500;margin-bottom:.4rem}
.fcard strong{display:block;font-size:.98rem;line-height:1.3;color:var(--ink)}
.fcard p{margin:.4rem 0 0;font-size:.82rem;line-height:1.5;color:var(--ink-soft)}
/* Both anchored to the bottom half, never the top: this hero photo has one
   face upper-left (the practitioner) and one upper-right (the patient, hair
   covering) — top:12% was landing squarely on Dr. Reyna's face. The table,
   torsos and hands in the lower third are the only zone safe across crops. */
.fcard--1{left:-1.75rem;bottom:36%}
.fcard--2{right:-1.75rem;bottom:9%}
@media(max-width:919px){
  .fcard{position:static;width:auto;margin-top:.85rem}
  .hero__img{overflow:visible}
}
