/* Lodestar Digital feature library (site build).
   Source demos: "Website features" folder. Each block is self-contained and keyed off a data-* hook,
   so a page only gets the effect when it has the markup. Loaded by: index, websites, website-features. */

/* ===== Text-Behind Hero (.hero.hero-tb) =====
   Giant word behind a floating browser frame, real headline in front. JS sets --px/--py (pointer) and --sy (scroll). */
.hero.hero-tb{min-height:auto;display:block;padding-top:140px;padding-bottom:96px}
.hero.hero-tb .wrap{display:block}
.tb__stage{position:relative;display:grid;justify-items:center}
.tb__word{margin:0;font:700 clamp(84px,19vw,262px)/.8 var(--serif);letter-spacing:-.05em;color:var(--bone);opacity:.95;text-align:center;white-space:nowrap;
  user-select:none;pointer-events:none;transform:translate3d(calc(var(--px,0) * -14px),calc(var(--sy,0) * 60px),0);will-change:transform}
.tb__subject{position:relative;z-index:2;width:min(700px,90%);margin:-.16em 0 0;font-size:clamp(84px,19vw,262px);
  transform:translate3d(calc(var(--px,0) * 10px),calc(var(--py,0) * 8px + var(--sy,0) * -30px),0) rotate(-1.5deg);will-change:transform}
.tb__frame{font-size:16px;border-radius:12px;overflow:hidden;background:#0d1714;box-shadow:0 40px 80px -20px rgba(0,0,0,.6),0 0 0 1px rgba(236,229,216,.12)}
.tb__bar{display:flex;align-items:center;gap:6px;padding:9px 12px;background:#14211d}
.tb__bar i{width:9px;height:9px;border-radius:50%;background:#3b4a45}
.tb__bar span{margin-left:10px;flex:1;max-width:280px;height:18px;border-radius:9px;background:#1f2e29;font:500 10px/18px var(--mono);color:#a9bab3;padding:0 10px;overflow:hidden;white-space:nowrap}
.tb__frame img{display:block;width:100%;height:auto;aspect-ratio:16/10;object-fit:cover;object-position:top}
.tb__chip{position:absolute;font:500 12px/1 var(--mono);letter-spacing:.04em;text-transform:uppercase;padding:10px 14px;border-radius:999px;background:var(--ox-deeper);color:var(--bone);
  box-shadow:0 12px 30px -10px rgba(0,0,0,.5),inset 0 0 0 1px rgba(236,229,216,.16);white-space:nowrap;transform:translate3d(calc(var(--px,0) * 22px),calc(var(--py,0) * 18px),0)}
.tb__chip b{color:var(--gold-bright);font-weight:500}
.tb__chip--a{left:-4%;top:22%}.tb__chip--b{right:-5%;top:52%}.tb__chip--c{left:8%;bottom:-18px}
.tb__copy{position:relative;z-index:3;max-width:960px;text-align:center;margin-bottom:clamp(28px,4vw,48px);display:grid;justify-items:center}
.hero.hero-tb h1{font-size:clamp(2.2rem,4.6vw,3.7rem);line-height:1.04;letter-spacing:-.03em;margin:20px 0 18px}
.tb__copy .lead{margin-left:auto;margin-right:auto;max-width:60ch}
.hero.hero-tb .cta-row{justify-content:center;margin-top:28px}
@media (max-width:640px){.tb__subject{margin-top:-.07em}.tb__chip--a{left:-2%;top:-14px}.tb__chip--b{right:-2%;top:auto;bottom:-14px}.tb__chip--c{display:none}}
@media (prefers-reduced-motion:reduce){.tb__word,.tb__chip{transform:none!important}.tb__subject{transform:rotate(-1.5deg)!important}}

/* body{overflow-x:hidden} (site-wide) makes <body> a scroll container, which stops position:sticky. clip hides overflow the same way without that. */
@supports (overflow:clip){body{overflow-x:clip}}

/* ===== Sticky Scroll Steps ([data-ss]), dark skin =====
   Left column (heading + step nav + progress rail) stays pinned; panels scroll past on the right. Stacks under 860px. */
.ss{--ss-panel:var(--ox-soft);--ss-ink:var(--bone);--ss-muted:#c9b8a6;--ss-line:rgba(236,229,216,.16);--ss-accent:var(--gold);--ss-deep:var(--ox-deeper);--ss-top:120px}
.ss__wrap{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:clamp(32px,6vw,90px)}
.ss__aside{position:sticky;top:var(--ss-top);align-self:start;display:grid;gap:26px}
.ss__aside h2{margin:0}
.ss__nav{list-style:none;margin:0;padding:0 0 0 22px;display:grid;gap:4px;position:relative}
.ss__nav::before,.ss__nav::after{content:"";position:absolute;left:0;top:8px;width:2px;border-radius:2px}
.ss__nav::before{bottom:8px;background:var(--ss-line)}
.ss__nav::after{height:calc((100% - 16px) * var(--ss-progress,0));background:var(--ss-accent);transition:height .5s cubic-bezier(.2,.7,.2,1)}
.ss__nav button{all:unset;cursor:pointer;display:flex;gap:14px;align-items:baseline;padding:8px 12px;border-radius:8px;font:600 1.1rem/1.3 var(--serif);color:var(--ss-muted);transition:color .3s,background .3s}
.ss__nav button span{font:500 .75rem/1 var(--mono);letter-spacing:.08em}
.ss__nav button[aria-current="step"]{color:var(--ss-ink);background:var(--ss-panel)}
.ss__nav button[aria-current="step"] span{color:var(--gold-bright)}
.ss__nav button:focus-visible{outline:2px solid var(--ss-accent);outline-offset:2px}
.ss__panels{display:grid;gap:clamp(48px,14vh,150px);padding-block:2vh 10vh}
.ss__panel{display:grid;gap:16px;scroll-margin-top:var(--ss-top)}
.ss__art{aspect-ratio:4/3;border-radius:16px;background:var(--ss-deep);border:1px solid var(--ss-line);overflow:hidden;position:relative;
  box-shadow:0 30px 60px -30px rgba(0,0,0,.6);transition:transform .6s cubic-bezier(.2,.7,.2,1),opacity .6s;opacity:.45;transform:scale(.96)}
.ss__panel.is-active .ss__art{opacity:1;transform:none}
.ss__art svg{display:block;width:100%;height:100%}
.ss__num{font:500 .75rem/1 var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--gold-bright)}
.ss__panel h3{margin:0;font-size:clamp(1.4rem,2.4vw,1.75rem)}
.ss__panel p{margin:0;color:var(--ss-muted);font-size:1.05rem;line-height:1.6;max-width:52ch}
.ss__art .draw{stroke-dasharray:var(--len,1000);stroke-dashoffset:var(--len,1000);transition:stroke-dashoffset 1.6s cubic-bezier(.3,.6,.2,1) .15s}
.ss__panel.is-active .ss__art .draw{stroke-dashoffset:0}
.ss__art .pop{opacity:0;transform-box:fill-box;transform-origin:center;transform:scale(.4);transition:opacity .4s,transform .5s cubic-bezier(.3,1.6,.5,1)}
.ss__panel.is-active .ss__art .pop{opacity:1;transform:none;transition-delay:calc(var(--d,0) * 1ms + 400ms)}
.ss__art .bar{transform-box:fill-box;transform-origin:bottom;transform:scaleY(.08);transition:transform .9s cubic-bezier(.2,.8,.2,1)}
.ss__panel.is-active .ss__art .bar{transform:none;transition-delay:calc(var(--d,0) * 1ms)}
.ss__art .ring{transform-box:fill-box;transform-origin:center;opacity:0}
.ss__panel.is-active .ss__art .ring{animation:ss-ring 2.6s cubic-bezier(.2,.6,.3,1) infinite;animation-delay:calc(var(--d,0) * 1ms)}
@keyframes ss-ring{0%{opacity:.9;transform:scale(.2)}100%{opacity:0;transform:scale(1)}}
@media (max-width:860px){.ss__wrap{grid-template-columns:minmax(0,1fr)}.ss__aside{position:static}.ss__nav{display:none}.ss__art{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  .ss__art,.ss__art *{transition:none!important;animation:none!important}
  .ss__art{opacity:1;transform:none}
  .ss__art .draw{stroke-dashoffset:0}.ss__art .pop{opacity:1;transform:none}.ss__art .bar{transform:none}.ss__art .ring{opacity:.5;transform:none}}

/* ===== Pixel Dissolve (portfolio .pf cards inside [data-pd]) =====
   A canvas over the screenshot starts as a blueprint and builds into the real site on hover/focus (once on scroll for touch). */
[data-pd] .pf .view canvas{position:absolute;inset:0;width:100%;height:100%;display:block;z-index:1;transition:transform .5s var(--ease)}
[data-pd] .pf:hover .view canvas{transform:scale(1.04)}

/* ===== Blueprint Reveal, spotlight mode ([data-br]) =====
   A lens follows the pointer and x-rays the finished site; it sweeps on its own on touch and parks for reduced motion. */
.br{--br-bg:#0B302C;--br-line:rgba(236,229,216,.10);--br-ink:#ECE5D8;--br-accent:#FF7A59;--x:50%;--y:50%;--r:clamp(70px,13vw,130px);
  position:relative;border-radius:14px;overflow:hidden;aspect-ratio:16/10;max-width:100%;background:var(--br-bg);
  box-shadow:0 30px 70px -25px rgba(0,0,0,.55),0 0 0 1px rgba(236,229,216,.1);touch-action:pan-y;user-select:none}
.br__layer{position:absolute;inset:0}
.br__layer img{display:block;width:100%;height:100%;object-fit:cover;object-position:top}
.br__bp{background:var(--br-bg)}
.br__bp img{filter:grayscale(1) invert(1) contrast(1.5) brightness(1.05);mix-blend-mode:screen;opacity:.62}
.br__bp::after{content:"";position:absolute;inset:0;pointer-events:none;background-image:linear-gradient(var(--br-line) 1px,transparent 1px),linear-gradient(90deg,var(--br-line) 1px,transparent 1px);background-size:24px 24px}
.br__bp.is-canvas img{filter:none;mix-blend-mode:normal;opacity:1}
.br__bp.is-canvas::after{display:none}
.br__top{-webkit-mask:radial-gradient(circle var(--r) at var(--x) var(--y),#000 98%,transparent 100%);mask:radial-gradient(circle var(--r) at var(--x) var(--y),#000 98%,transparent 100%)}
.br__ring{position:absolute;z-index:2;left:var(--x);top:var(--y);width:calc(var(--r) * 2);height:calc(var(--r) * 2);transform:translate(-50%,-50%);border-radius:50%;
  box-shadow:0 0 0 2px var(--br-accent),0 0 40px rgba(255,122,89,.35);pointer-events:none}
.br__tag{position:absolute;top:12px;right:12px;z-index:3;font:500 11px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;padding:7px 10px;border-radius:4px;background:rgba(7,36,32,.88);color:var(--br-ink);pointer-events:none}
.br-band{margin:0 auto 48px;max-width:980px;display:grid;gap:14px}
.br-band figcaption{font:500 .78rem/1.5 var(--mono);letter-spacing:.06em;color:#6b5852;text-align:center}
.pad:not(.light) .br-band figcaption{color:#c9b8a6}
