/* =====================================================================
   MOTION LAYER v3, "editorial instrument"   (added 2026-09-05)
   Lives in its OWN file so the 16 industry pages (own inline CSS) can load it too.
   Site-wide motion grammar, borrowed from the awwwards editorial school
   (Exo Ape: masked line reveals and clip-path image reveals; Locomotive and
   Studio Freight: rule-draws, numbered rails, mono meta) and translated into
   this design system. Rules of the layer:
     1. Nothing here hides content without JS. Every initial state is scoped
        to a class that site.js adds (.js on <html>, .rv on elements, .w on
        split words, .imgrv on images). No JS, no motion, nothing missing.
     2. Only transform, opacity and clip-path animate. No layout properties.
     3. One easing family: cubic-bezier(.2,.7,.1,1) for entrances (fast out,
        long settle), .55s to 1.1s. Nothing bounces. Nothing floats.
     4. Everything is off under prefers-reduced-motion, in CSS AND in JS.
   ===================================================================== */

/* --- split words (h1, .h2, .standfirst, pull quotes). JS wraps each word
       in <span class="w"><span>word</span></span>; the inner span rises out
       of a clipped box. Small padding keeps descenders and italic overhangs
       from being clipped, the negative margin gives that space back. --- */
.w{display:inline-block;overflow:hidden;vertical-align:bottom;
  padding:0 .06em .12em .03em;margin:0 -.06em -.12em -.03em;}
.w>span{display:inline-block;will-change:transform;
  transition:transform .95s cubic-bezier(.2,.7,.1,1) calc(var(--w,0)*42ms);}
.rv:not(.in) .w>span,.intro:not(.in) .w>span{transform:translateY(112%);}

/* --- intro: the first hero-type section on every page. .js on <html> is
       set by a one-line head script so the section paints nothing until
       site.js has split the headline, then everything rises in order. --- */
/* 2026-09-27: the hero is no longer hidden while motion.js loads. The headline and
   portrait paint at once (they are the Largest Contentful Paint candidates); only the
   secondary pieces below animate. */
.iv{transition:opacity .8s cubic-bezier(.2,.7,.1,1) var(--d,0s),transform .8s cubic-bezier(.2,.7,.1,1) var(--d,0s);}
.intro:not(.in) .iv{opacity:0;transform:translateY(16px);}
/* the portrait: revealed by a clip-path wipe from the bottom, then the red
   register frame slides into place a beat later */
.intro .hero-photo img,.intro .about-photo img{
  transition:clip-path 1.15s cubic-bezier(.65,0,.15,1) .35s,box-shadow .6s cubic-bezier(.2,.7,.1,1) 1.25s;}
.intro:not(.in) .hero-photo img,.intro:not(.in) .about-photo img{
  box-shadow:0 0 0 var(--red) !important;}
/* the highlighted word in the headline gets a red rule drawn under it once
   the words have landed */
.hero h1 .hl{background-image:linear-gradient(var(--red),var(--red));background-repeat:no-repeat;
  background-position:0 92%;background-size:100% .06em;
  transition:background-size .7s cubic-bezier(.2,.7,.1,1) 1.15s;}
.intro:not(.in) .hero h1 .hl,.hero.intro:not(.in) h1 .hl{background-size:0 .06em;}

/* --- section reveal, refined. The section itself only fades (no big
       translate), and its children stagger in behind it. --- */
.reveal{opacity:0;transform:translateY(8px);transition:opacity .6s ease,transform .7s cubic-bezier(.2,.7,.1,1);}
.reveal.in{opacity:1;transform:none;}

/* eyebrow tick draws from the left */
.eyebrow::before{transform-origin:left center;transition:transform .7s cubic-bezier(.2,.7,.1,1) .1s;}
.rv:not(.in) .eyebrow::before,.rv.eyebrow:not(.in)::before{transform:scaleX(0);}

/* --- staggered children. JS sets --i on each child of a .rv container. --- */
.stg>*{transition:opacity .7s cubic-bezier(.2,.7,.1,1) calc(var(--i,0)*70ms),
  transform .8s cubic-bezier(.2,.7,.1,1) calc(var(--i,0)*70ms);}
.stg:not(.in)>*{opacity:0;transform:translateY(18px);}

/* --- image reveal: clip-path wipe from the bottom, per image. --- */
.imgrv{clip-path:inset(0 0 0 0);transition:clip-path 1.05s cubic-bezier(.65,0,.15,1);}
.imgrv:not(.in){clip-path:inset(100% 0 0 0);}

/* --- rules that draw: the stats band, the pull quote and the process rail. --- */
.stats{position:relative;}
.stats::after{content:"";position:absolute;left:0;right:0;bottom:-2px;height:2px;background:var(--red);
  transform-origin:left;transition:transform 1.4s cubic-bezier(.65,0,.15,1) .3s;}
.stats.rv:not(.in)::after{transform:scaleX(0);}
.quote{position:relative;border-top:0;border-bottom:0;}
.quote::before,.quote::after{content:"";position:absolute;left:0;right:0;height:2px;background:var(--ink);
  transform-origin:center;transition:transform 1.1s cubic-bezier(.65,0,.15,1);}
.quote::before{top:0;} .quote::after{bottom:0;transition-delay:.15s;}
.quote.rv:not(.in)::before,.quote.rv:not(.in)::after{transform:scaleX(0);}
.quote .mark{transition:opacity .5s ease .5s,transform .7s cubic-bezier(.2,.7,.1,1) .5s;}
.quote.rv:not(.in) .mark{opacity:0;transform:translateY(-8px);}
.quote cite{transition:opacity .6s ease 1s;}
.quote.rv:not(.in) cite{opacity:0;}

/* --- cards: a red bar scales across the top on hover (the ledger grammar),
       and the read link nudges right. --- */
.card{position:relative;}
.card::before{content:"";position:absolute;top:0;left:0;right:0;height:2px;background:var(--red);
  transform:scaleX(0);transform-origin:left;transition:transform .38s cubic-bezier(.2,.7,.1,1);z-index:1;}
.card:hover::before,.card:focus-visible::before{transform:scaleX(1);}
.card .read,.card .textlink,.card .svc-read{transition:transform .3s cubic-bezier(.2,.7,.1,1),color .15s;display:inline-block;}
.card:hover .read,.card:hover .textlink,.card:hover .svc-read{transform:translateX(4px);}

/* --- masthead: the nav underline wipes in from the left on desktop. Mobile
       keeps its row dividers (border-bottom) exactly as before. --- */
@media(min-width:861px){
  .nav-links a{position:relative;border-bottom:0;padding-bottom:.3rem;}
  .nav-links a::after{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;background:var(--red);
    transform:scaleX(0);transform-origin:left;transition:transform .32s cubic-bezier(.2,.7,.1,1);}
  .nav-links a:hover::after{transform:scaleX(1);}
  .nav-links a.active::after{background:var(--ink);transform:scaleX(1);}
  .nav-links a:hover.active::after{background:var(--red);}
}
.brand-mark{transition:transform .5s cubic-bezier(.2,.7,.1,1);}
.brand:hover .brand-mark{transform:rotate(-8deg);}

/* --- logo tiles: a quiet lift rather than a scale --- */
.logo-tile img{transition:opacity .25s,transform .45s cubic-bezier(.2,.7,.1,1);}
.logo-tile:hover img{transform:translateY(-2px);}

/* --- chips (industries): each chip carries a measured red bar along its
       bottom, proportional to its engagement count (--n, out of 12). It
       grows in on reveal, so the strip reads as an instrument, not tags. --- */
.chip{position:relative;overflow:hidden;}
.chip::after{content:"";position:absolute;left:0;bottom:0;height:3px;background:var(--red);
  width:calc(var(--n,0)/12*100%);transform-origin:left;
  transition:transform .9s cubic-bezier(.2,.7,.1,1) calc(var(--i,0)*45ms + .3s);}
.rv:not(.in) .chip::after{transform:scaleX(0);}
.chip:hover::after{background:var(--paper);}

/* --- process rail (How I work). Each step's top rule draws in sequence,
       its number turns red as the rule arrives, and a red register mark
       travels the full rail from the first step to the last. --- */
.process{position:relative;}
.process .pstep{border-top-color:transparent;}
.process .pstep::after{content:"";position:absolute;top:-2px;left:0;right:0;height:2px;background:var(--ink);
  transform-origin:left;transition:transform .55s cubic-bezier(.65,0,.15,1) calc(var(--i,0)*.3s);}
.process.rv:not(.in) .pstep::after{transform:scaleX(0);}
.process .pstep::before{transition:color .25s ease calc(var(--i,0)*.3s + .45s);}
.process.rv:not(.in) .pstep::before{color:var(--faint);}
.process .pstep h4,.process .pstep p{transition:opacity .6s ease calc(var(--i,0)*.3s + .25s),transform .7s cubic-bezier(.2,.7,.1,1) calc(var(--i,0)*.3s + .25s);}
.process.rv:not(.in) .pstep h4,.process.rv:not(.in) .pstep p{opacity:0;transform:translateY(10px);}
.process .rail-mark{position:absolute;top:-6px;left:0;width:10px;height:10px;background:var(--red);
  transform:translateX(-14px);opacity:0;pointer-events:none;
  transition:left 2s cubic-bezier(.65,0,.15,1),opacity .3s ease;}
.process.in .rail-mark{left:calc(100% - 10px);transform:none;opacity:1;}

/* --- service glyphs: bespoke line drawings that draw themselves in. Every
       path carries pathLength="1" so a single dasharray works for all. --- */
.glyph{width:56px;height:56px;display:block;margin-bottom:.9rem;overflow:visible;}
.glyph *{fill:none;stroke:var(--ink);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:1;stroke-dashoffset:0;
  transition:stroke-dashoffset 1.1s cubic-bezier(.65,0,.15,1) calc(var(--i,0)*.12s + .15s),fill .4s ease calc(var(--i,0)*.12s + 1.1s);}
.glyph .r{stroke:var(--red);}
.glyph .f{fill:var(--red);stroke:var(--red);}
.rv:not(.in) .glyph *{stroke-dashoffset:1;}
.rv:not(.in) .glyph .f{fill:transparent;}
.card:hover .glyph .f{fill:var(--ink);stroke:var(--ink);}
.card:hover .glyph .r{stroke:var(--ink);}

/* --- guides: the five poster cards, in the system (square, ink rule,
       register offset on hover) instead of the rounded shadowed inline
       styles that shipped 2026-08-04. --- */
.guides{display:grid;grid-template-columns:repeat(auto-fit,minmax(158px,1fr));gap:1.2rem;margin-top:1.6rem;}
.guide{display:block;color:inherit;}
.guide img{width:100%;display:block;border:1px solid var(--ink);
  transition:transform .35s cubic-bezier(.2,.7,.1,1),box-shadow .35s cubic-bezier(.2,.7,.1,1);}
.guide:hover img{transform:translate(-3px,-3px);box-shadow:var(--lift) var(--lift) 0 var(--red) !important;}
.guide .gk{display:block;font-family:var(--sans);font-size:.68rem;font-weight:700;letter-spacing:.11em;
  text-transform:uppercase;color:var(--red);margin:.7rem 0 .1rem;}
.guide .gt{display:block;font-family:var(--serif);font-weight:600;font-size:.98rem;color:var(--ink);line-height:1.3;}
.guide .gs{display:block;font-family:var(--serif);font-size:.86rem;color:var(--muted);margin-top:.2rem;line-height:1.4;}

/* --- playbook strip: image drifts under the caption on hover --- */
.strip .sitem{overflow:hidden;}
.strip .sitem img{transition:transform .6s cubic-bezier(.2,.7,.1,1);}
.strip .sitem:hover img{transform:scale(1.035);}
.strip .sitem span{position:relative;}
.strip .sitem span::after{content:"";position:absolute;left:.9rem;bottom:.45rem;width:22px;height:2px;background:var(--red);
  transform:scaleX(0);transform-origin:left;transition:transform .3s cubic-bezier(.2,.7,.1,1);}
.strip .sitem:hover span::after{transform:scaleX(1);}

/* --- FAQ: red left rule on hover, plus on open --- */
.faq details{position:relative;}
.faq details::before{content:"";position:absolute;left:-1rem;top:0;bottom:0;width:2px;background:var(--red);
  transform:scaleY(0);transform-origin:top;transition:transform .3s cubic-bezier(.2,.7,.1,1);}
.faq details:hover::before,.faq details[open]::before{transform:scaleY(1);}

/* --- navy CTA band: the scanlines drift slowly and a red register segment
       sweeps the bottom edge, the way a level indicator does. --- */
.cta-band .dotfield{animation:n9drift 4s linear 1;}
@keyframes n9drift{to{background-position:40px 0;}}
.cta-band::after{content:"";position:absolute;left:0;right:0;bottom:0;height:3px;
  background:linear-gradient(90deg,transparent 0 40%,var(--red) 40% 60%,transparent 60%);
  background-size:250% 100%;animation:n9sweep 2.4s cubic-bezier(.65,0,.35,1) 2 alternate;}
@keyframes n9sweep{from{background-position:100% 0;}to{background-position:0 0;}}

/* --- the watermelon specimen (homepage, the Difference section). A status
       report rendered as the artifact, with the floor truth wiping in under
       the green summary. Plays once on reveal, replays on demand. --- */
.spec{position:relative;background:var(--sheet);border:1px solid var(--ink);
  box-shadow:var(--lift) var(--lift) 0 var(--rule-2) !important;font-family:var(--sans);}
.spec-bar{display:flex;justify-content:space-between;gap:1rem;padding:.55rem .9rem;background:var(--navy);
  color:var(--console-dim);font-family:var(--mono);font-size:.62rem;letter-spacing:.12em;text-transform:uppercase;}
.spec-bar b{color:var(--console);font-weight:500;}
.spec-head{display:flex;justify-content:space-between;align-items:center;gap:1rem;padding:.9rem 1rem .8rem;
  border-bottom:2px solid var(--ink);}
.spec-head .st{font-family:var(--serif);font-weight:600;font-size:1.06rem;color:var(--ink);letter-spacing:-.012em;}
.spec-head .sum{display:inline-flex;align-items:center;gap:.5rem;font-family:var(--mono);font-size:.66rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ink);}
.pip{display:inline-block;width:11px;height:11px;flex:0 0 auto;border-radius:0 !important;}
.pip.go{background:var(--go);} .pip.watch{background:var(--watch);} .pip.stop{background:var(--stop);}
.spec table{width:100%;border-collapse:collapse;font-size:.86rem;}
.spec th{font-family:var(--mono);font-size:.6rem;font-weight:500;letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);text-align:left;padding:.55rem 1rem .5rem;border-bottom:1px solid var(--rule);}
.spec td{padding:.62rem 1rem;border-bottom:1px solid var(--rule);color:var(--ink-2);vertical-align:middle;}
.spec td:first-child{font-family:var(--serif);font-weight:600;color:var(--ink);font-size:.98rem;}
.spec .chipstat{display:inline-flex;align-items:center;gap:.45rem;font-family:var(--mono);font-size:.64rem;
  letter-spacing:.1em;text-transform:uppercase;color:var(--ink);white-space:nowrap;}
.spec .fl{position:relative;}
.spec .fl .chipstat{transition:clip-path .55s cubic-bezier(.65,0,.15,1) calc(1.1s + var(--i,0)*.32s);}
.spec.rv:not(.play) .fl .chipstat{clip-path:inset(0 100% 0 0);}
.spec .fl::before{content:"";position:absolute;left:1rem;right:1rem;top:50%;height:1px;background:var(--rule-2);opacity:0;
  transition:opacity .3s ease calc(1.1s + var(--i,0)*.32s);}
.spec.rv:not(.play) .fl::before{opacity:1;}
.spec-foot{display:flex;justify-content:space-between;align-items:center;gap:1rem;padding:.75rem 1rem;
  font-family:var(--mono);font-size:.64rem;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);}
.spec-foot .line{transition:opacity .5s ease 2.9s;}
.spec.rv:not(.play) .spec-foot .line{opacity:0;}
.spec-foot .line b{color:var(--stop);font-weight:500;}
.spec-foot button{font:inherit;letter-spacing:inherit;text-transform:inherit;color:var(--ink);background:none;
  border:0;border-bottom:1px solid var(--ink);padding:0 0 1px;cursor:pointer;}
.spec-foot button:hover{color:var(--red);border-color:var(--red);}
.spec .stamp{position:absolute;left:34%;top:2.85rem;background:var(--sheet);padding:.3rem .6rem;border:2px solid var(--stop);color:var(--stop);
  font-family:var(--sans);font-weight:700;font-size:.78rem;letter-spacing:.2em;text-transform:uppercase;
  transform:rotate(-9deg) scale(1);opacity:.9;pointer-events:none;
  transition:transform .35s cubic-bezier(.2,.9,.3,1.3) 2.75s,opacity .25s ease 2.75s;}
.spec.rv:not(.play) .stamp{transform:rotate(-9deg) scale(1.5);opacity:0;}
.diff-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(2rem,5vw,4.5rem);align-items:center;}
@media(max-width:900px){.diff-grid{grid-template-columns:1fr;}}

/* --- reduced motion: every initial state above is neutralised here too --- */
@media(prefers-reduced-motion:reduce){
  .w{overflow:visible;}
  .rv:not(.in) .w>span,.intro:not(.in) .w>span{transform:none;}
  .js .intro:not(.in){visibility:visible;}
  .intro:not(.in) .iv{opacity:1;transform:none;}
  .intro:not(.in) .hero-photo img,.intro:not(.in) .about-photo img{clip-path:none;}
  .intro:not(.in) .hero h1 .hl{background-size:100% .06em;}
  .stg:not(.in)>*{opacity:1;transform:none;}
  .imgrv:not(.in){clip-path:none;}
  .rv:not(.in) .eyebrow::before,.stats.rv:not(.in)::after,.quote.rv:not(.in)::before,.quote.rv:not(.in)::after,.process.rv:not(.in) .pstep::after,.rv:not(.in) .chip::after{transform:none;}
  .quote.rv:not(.in) .mark,.quote.rv:not(.in) cite,.process.rv:not(.in) .pstep h4,.process.rv:not(.in) .pstep p{opacity:1;transform:none;}
  .process.rv:not(.in) .pstep::before{color:var(--red);}
  .process .rail-mark{display:none;}
  .rv:not(.in) .glyph *{stroke-dashoffset:0;}
  .rv:not(.in) .glyph .f{fill:var(--red);}
  .cta-band .dotfield,.cta-band::after{animation:none;}
  .spec.rv:not(.play) .fl .chipstat{clip-path:none;} .spec.rv:not(.play) .fl::before{opacity:0;}
  .spec.rv:not(.play) .spec-foot .line{opacity:1;} .spec.rv:not(.play) .stamp{opacity:.9;transform:rotate(-9deg) scale(1);}
}
/* --- logo marquee pause control (WCAG 2.2.2, added 2026-09-27). Hover still
       pauses; the button pauses all three rows for touch and keyboard users. --- */
.marq-ctl{display:flex;justify-content:flex-end;margin-top:1rem;}
.marq-ctl button{font-family:var(--mono);font-size:.64rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ink);
  background:none;border:1px solid var(--ink);padding:.35rem .7rem;cursor:pointer;border-radius:0;}
.marq-ctl button:hover,.marq-ctl button:focus-visible{color:var(--red);border-color:var(--red);}
.marq-ctl+.logo-marquee{margin-top:.5rem;}
.marq-paused .logo-track,.marq-paused .logo-track-reverse{animation-play-state:paused !important;}
@media(max-width:600px){.spec .stamp{left:36%;top:3.35rem;font-size:.56rem;letter-spacing:.14em;padding:.18rem .35rem;}}

/* --- nav between 861 and 1120px: stops Practice Areas and Book a call wrapping to two lines
       (measured on the live site 2026-09-27: links 49px tall, button 68px, at 900px wide). --- */
@media(min-width:861px) and (max-width:1120px){.nav-links{gap:.85rem !important;}.nav-links a{white-space:nowrap;letter-spacing:.06em;}header .btn{white-space:nowrap;padding-left:.9rem;padding-right:.9rem;}}

/* --- print: every animated element prints in its finished state (added 2026-09-27) --- */
@media print{
  .intro .iv,.stg>*,.rv .w>span,.intro .w>span,.quote .mark,.quote cite,.process .pstep h4,.process .pstep p,.spec-foot .line{opacity:1 !important;transform:none !important;}
  .imgrv,.spec .fl .chipstat,.hero-photo img,.about-photo img{clip-path:none !important;}
  .w{overflow:visible !important;}
  .rv .eyebrow::before,.rv.eyebrow::before,.stats::after,.quote::before,.quote::after,.process .pstep::after,.chip::after{transform:none !important;}
  .rv .glyph *{stroke-dashoffset:0 !important;}
  .spec .fl::before{opacity:0 !important;}
  .spec .stamp{opacity:.9 !important;transform:rotate(-9deg) scale(1) !important;}
  .process .rail-mark,.marq-ctl{display:none !important;}
  .logo-track,.logo-track-reverse{animation:none !important;}
}
/* service-page badge: the bespoke glyph sits inside the 44px box, undrawn (the hero is an intro, not a scroll reveal) */
.svc-ic .glyph{width:30px;height:30px;margin:0;}
