/* Aster / studio edition. Loaded after the original botanical components. */
:root {
  --pad-x: clamp(22px, 5.5vw, 88px);
  --pad-section: clamp(88px, 10vw, 152px);
  --max: 1320px;
}
html { scroll-padding-top: 104px; }
::selection { background: #c4a5e0; color: #221c28; }
a:focus-visible, button:focus-visible, input:focus-visible,
textarea:focus-visible, select:focus-visible {
  outline: 2px solid var(--aster-deep);
  outline-offset: 6px;
}
.eyebrow { font-size: 11px; letter-spacing: .17em; line-height: 1.6; }
.section { scroll-margin-top: 88px; }

/* A visible, quiet navigation with a single project invitation. */
.nav { gap: 30px; padding-top: 22px; padding-bottom: 22px; }
.nav .brand { margin-right: auto; }
.brand-word { font-size: 25px; letter-spacing: -.035em; }
.brand-sub { display: block; font-size: 9px; letter-spacing: .23em; }
.nav-studio-links { display: flex; align-items: center; gap: clamp(24px, 3vw, 44px); }
.nav-studio-links a { font-size: 13px; color: var(--ink-soft); padding: 12px 0; }
.nav-studio-links a:hover { color: var(--aster-deep); }
.nav-project-link {
  display: inline-flex; align-items: center; gap: 26px;
  border: 1px solid var(--line); border-radius: 999px;
  font-size: 13px; padding: 12px 20px; white-space: nowrap;
  transition: background .25s, border-color .25s;
}
.nav-project-link:hover { background: var(--aster-mist); border-color: var(--aster-light); }
.nav.on-dark .nav-project-link:hover { background: #362b3d; }
.nav-toggle { display: none; }
.nav-menu { z-index: 120; }

/* The bloom is the signature; the headline remains the focus. */
.hero {
  min-height: 100vh;
  min-height: 100svh;
  min-height: 100dvh;
  padding-top: clamp(154px, 20vh, 220px);
  padding-bottom: 120px;
  justify-content: center;
}
.hero-grid { width: 100%; }
.hero-eyebrow {
  margin: 0 0 32px; font-family: var(--sans); font-style: normal;
  text-transform: uppercase; font-size: 11px; letter-spacing: .16em;
}
.hero-title {
  font-size: clamp(42px, 5.7vw, 82px); line-height: 1.08;
  letter-spacing: -.055em; max-width: none; margin: 0 0 30px;
}
.hero-title .l > span { opacity: 1; transform: none; filter: none; }
.hero-arrival-ready:not(.loaded) .hero-title .l > span { opacity: 0; transform: translateY(.34em) scale(.985); filter: blur(16px); }
.hero-title .l:nth-child(2) { margin-top: .04em; }
.hero-title em { color: var(--aster-deep); font-weight: 400; }
.hero-lede { max-width: 43ch; font-size: clamp(16px, 1.3vw, 19px); line-height: 1.7; margin-bottom: 32px; }
.hero-actions { gap: 28px; }
.hero-actions .btn { padding: 17px 24px; font-size: 13px; }
.hero-secondary { display: inline-flex; gap: 24px; align-items: center; font-size: 13px; padding: 14px 0; border-bottom: 1px solid var(--line); }
.hero-secondary:hover { color: var(--aster-deep); border-color: var(--aster-deep); }
.hero-flower {
  --fw: clamp(370px, 42vw, 640px);
  right: -9%; top: 48%; width: var(--fw); margin-top: calc(var(--fw) * -.46);
  opacity: .78;
  --flower-fade: radial-gradient(95% 120% at 80% 50%, #000 30%, rgba(0,0,0,.8) 60%, transparent 100%);
}
.hero-flower-halo { opacity: .38; }
/* Original botanical atmosphere, marquee and interactive gallery are retained. */
.work-intro { margin-top: 18px; max-width: 48ch; color: var(--ink-soft); }

/* Capabilities are presented as a considered editorial spread. */
/* Was a flat #eee7f0 block: two hard horizontal edges against cream above and
   below, so it read as a slab dropped into the page rather than part of it. A
   feathered lavender wash instead — transparent at both edges, so the paper
   grain and the neighbouring sections run straight through it. The tint stays
   light (≤ 9% alpha) because body copy sits on it and this palette has little
   contrast to spare under text. */
.expertise {
  background: linear-gradient(180deg,
    rgba(196, 165, 224, 0) 0%,
    rgba(196, 165, 224, 0.09) 24%,
    rgba(196, 165, 224, 0.09) 76%,
    rgba(196, 165, 224, 0) 100%);
}
.process { padding-top: var(--pad-section); }
.tier { border-radius: 8px; }
.tier.featured { box-shadow: none; }
.pricing-footnote { line-height: 1.6; }
.connect-form input, .connect-form textarea, .connect-form select { border-radius: 5px; }
.overlay { visibility: hidden; z-index: 9500; }
.overlay.open { visibility: visible; }

/* Content is readable before enhancement and if an animation library fails. */
.reveal, .reveal-type, .reveal-stagger > * { opacity: 1; transform: none; filter: none; }
.reveals-ready .reveal:not(.in) { opacity: 0; transform: translateY(36px); }
.reveals-ready .reveal-stagger:not(.in) > * { opacity: 0; transform: translateY(28px); }
.reveals-ready .reveal-type:not(.in) { opacity: 0; transform: translateY(.22em) scale(.99); filter: blur(13px); }

/* The complete process stays readable without JS, GSAP, or motion. */
.bloom-zoom:not(.motion-ready) { height: auto; padding: 24px var(--pad-x) 72px; background: none; }
.bloom-zoom:not(.motion-ready) .bloom-zoom-stage { position: static; height: auto; min-height: 0; overflow: visible; display: block; }
.bloom-zoom:not(.motion-ready) .zoom-flower,
.bloom-zoom:not(.motion-ready) .zoom-aura,
.bloom-zoom:not(.motion-ready) .zoom-vignette { display: none; }
.bloom-zoom:not(.motion-ready) .ovule-phases { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); gap: 32px; max-width: 1160px; margin: auto; }
.bloom-zoom:not(.motion-ready) .ovule-reveal { display: block !important; position: static; opacity: 1 !important; transform: none !important; margin: 0; max-width: none; padding: 24px 0 0; border-top: 1px solid var(--line); border-radius: 0; background: none; will-change: auto; }
.bloom-zoom:not(.motion-ready) .ovule-reveal::before { display: none; }
.bloom-zoom:not(.motion-ready) .ovule-title { font-size: 27px; }
.bloom-zoom:not(.motion-ready) .ovule-body { font-size: 15px; text-shadow: none; }
.bloom-zoom:not(.motion-ready) .ovule-label { font-size: 11px; }
@media (max-width: 900px) { .bloom-zoom:not(.motion-ready) .ovule-phases { grid-template-columns: repeat(2,minmax(0,1fr)); } }
@media (max-width: 540px) { .bloom-zoom:not(.motion-ready) .ovule-phases { grid-template-columns: 1fr; } }

@media (max-width: 1050px) {
  .nav { gap: 20px; }
  .nav-studio-links { gap: 24px; }
  .hero { padding-top: clamp(120px, 16svh, 168px); }
  .hero-flower { right: -16%; opacity: .5; }
  .hero-title { font-size: clamp(48px, 6.7vw, 72px); }
}
@media (max-width: 760px) {
  :root { --pad-x: 24px; }
  html { scroll-padding-top: 82px; }
  .nav, .nav.scrolled { padding-top: 15px; padding-bottom: 15px; gap: 16px; }
  .nav-studio-links { display: none; }
  .nav-toggle { display: flex; flex-shrink: 0; }
  .nav-project-link { padding: 10px 16px; font-size: 12px; gap: 14px; }
  .brand { gap: 9px; }
  .brand-word { font-size: 23px; }
  .brand-sub { font-size: 8px; }
  .hero { padding-top: max(112px, 14svh); padding-bottom: calc(104px + env(safe-area-inset-bottom, 0px)); }
  .hero-eyebrow { margin-bottom: 26px; font-size: 10px; letter-spacing: .11em; }
  .hero-title { font-size: clamp(38px, 12vw, 64px); line-height: 1.1; margin-bottom: 26px; letter-spacing: -.052em; }
  .hero-lede { font-size: 16px; max-width: 37ch; line-height: 1.7; }
  .hero-flower { --fw: 480px; right: -235px; top: 43%; opacity: .23; margin-top: -220px; }
  .hero-actions { flex-direction: row; align-items: center; gap: 14px 24px; }
  .hero-actions .btn { width: auto; padding: 16px 21px; }
  .hero-secondary { font-size: 12px; gap: 12px; }
  .philosophy-grid { gap: 32px; }
}
@media (max-width: 380px) {
  :root { --pad-x: 20px; }
  .nav { gap: 12px; }
  .nav .brand-mark { width: 28px; height: 28px; }
  .nav-project-link { padding: 9px 12px; gap: 9px; }
  .brand-word { font-size: 21px; }
  .hero { padding-top: 104px; }
  .hero-title { font-size: clamp(35px, 11.8vw, 44px); }
  .hero-eyebrow { font-size: 9px; }
  .hero-lede { font-size: 15px; }
  .hero-actions { gap: 6px; flex-direction: column; align-items: flex-start; }
  .hero-actions .btn { width: auto; }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .hero-flower, .hero-headline, .shot-stack, .work .case:hover .shot-stack img { transform: none !important; }
  .hero-flower-halo { animation: none; }
  .reveal, .reveal-type, .reveal-stagger > * { opacity: 1 !important; transform: none !important; filter: none !important; }
}

/* Keep the featured offer readable on its dark surface. */
.tier.featured { --ink-soft: #d9d0bd; --ink-mute: #bcb29d; }
.tier.featured li { color: #d9d0bd; }
.tier.featured .ribbon { top: 20px; right: 18px; width: auto; transform: none; padding: 7px 12px; border-radius: 999px; background: #c4a5e0; color: #211b28; font-size: 10px; letter-spacing: .03em; box-shadow: none; }
.aster-static { display: block; width: 48%; height: auto; max-height: 85%; object-fit: contain; margin: 7% auto 0; }
.cyclical-stage:has(canvas) .aster-static { display: none; }

/* Phone layouts follow the visible viewport, including browser chrome changes. */
@media (max-width: 760px) {
  .nav-toggle { min-width: 44px; min-height: 44px; }
  .nav-project-link { min-height: 44px; }
  .nav-menu { max-height: calc(100dvh - 100px); overflow-y: auto; overscroll-behavior: contain; }
  .hero-title { text-wrap: balance; }
  .hero-lede { margin-bottom: 26px; }
  .hero-actions { flex-direction: column; align-items: stretch; gap: 12px; }
  .hero-actions .btn { width: 100%; min-height: 52px; flex: none; }
  .hero-secondary { align-self: flex-start; min-height: 44px; }
  .hero-scroll { bottom: calc(24px + env(safe-area-inset-bottom, 0px)); }
  .hero-flower { --fw: clamp(380px, 112vw, 510px); right: -58%; top: 44%; margin-top: calc(var(--fw) * -.46); }
  .connect-form input, .connect-form select, .connect-form textarea { font-size: 16px; }
  .connect-form input, .connect-form select { min-height: 48px; }
  .connect-form textarea { min-height: 144px; }
  .footer a { display: flex; align-items: center; min-height: 44px; }
}
@media (max-width: 760px) and (max-height: 700px) {
  .hero { padding-top: 100px; padding-bottom: 76px; }
  .hero-eyebrow { margin-bottom: 18px; }
  .hero-title { margin-bottom: 18px; }
  .hero-lede { margin-bottom: 20px; }
  .hero-actions { gap: 8px; }
  .hero-scroll { bottom: 12px; }
}

@media (max-width: 760px) {
  /* Keep pointer lights inside their sections without breaking sticky animation. */
  .on-ink { overflow-x: clip; }
}

/* ========== Expertise ==========
   One sticky heading, three chapters, one vine down the left edge. Kept at the
   end of the sheet so it wins over the phone blocks above. expertise.js sets
   --draw (0..1) on the vine, its branches and each glyph, and --fill (0..1)
   for the washes; both default to 1, so with no JS every stroke is drawn. */
.expertise { position: relative; }
.xp { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 0 clamp(48px, 7vw, 112px); align-items: start; }

.xp-intro { position: sticky; top: 128px; }
.xp-intro h2 {
  font: 400 clamp(38px, 4.1vw, 60px)/1.08 var(--serif);
  letter-spacing: -.035em; margin: 22px 0 26px; text-wrap: balance;
}
.xp-intro h2 em { color: var(--aster-deep); }
.xp-intro > p { font-size: 16px; line-height: 1.75; color: var(--ink-soft); max-width: 36ch; margin: 0 0 34px; }
.xp-links { display: flex; flex-direction: column; align-items: flex-start; gap: 16px; }
.xp-link {
  display: inline-flex; align-items: center; gap: 10px; font-size: 14px; letter-spacing: .01em;
  color: var(--ink); padding-bottom: 5px; border-bottom: 1px solid rgba(94, 61, 138, .35);
  transition: color .3s, border-color .3s, gap .3s;
}
.xp-link:hover, .xp-link:focus-visible { color: var(--aster-deep); border-color: var(--aster-deep); gap: 14px; }
.xp-link--main {
  padding: 15px 24px; border: 0; border-radius: 999px; background: var(--ink); color: var(--cream);
  transition: background .3s, transform .3s, gap .3s;
}
.xp-link--main:hover, .xp-link--main:focus-visible { background: var(--aster-deep); color: var(--cream); transform: translateY(-2px); }

.xp-rows { position: relative; padding-left: 46px; }
.xp-vine { position: absolute; left: 0; top: 0; width: 28px; height: 100%; overflow: visible; pointer-events: none; color: #a58cc6; }
.xp-vine path {
  fill: none; stroke: currentColor; stroke-width: 1.25; stroke-linecap: round;
  stroke-dasharray: 1; stroke-dashoffset: calc(1 - var(--draw, 1));
}
.xp-vine .xp-branch { stroke-width: 1.1; }

.xp-row {
  position: relative; display: grid; grid-template-columns: 104px minmax(0, 1fr); gap: 0 34px;
  padding: 52px 0 60px; border-top: 1px solid rgba(94, 61, 138, .16);
}
.xp-rows > .xp-row:first-of-type { border-top: 0; padding-top: 6px; }
.xp-row::before {
  content: ""; position: absolute; inset: 14px -28px 14px -34px; z-index: -1;
  border-radius: 22px; pointer-events: none;
  background: radial-gradient(300px circle at var(--mx, 30%) var(--my, 30%), rgba(196, 165, 224, .30), rgba(196, 165, 224, 0) 70%);
  opacity: 0; transition: opacity .5s ease;
}
.xp-row:hover::before { opacity: 1; }

.xp-glyph {
  width: 104px; height: 117px; overflow: visible; color: var(--aster-deep);
  transform-origin: 16px 117px; transition: transform .9s cubic-bezier(.2, .7, .2, 1);
}
.xp-glyph .g-line, .xp-glyph .g-fill {
  stroke: currentColor; stroke-width: 1.1; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 1; stroke-dashoffset: calc(1 - var(--draw, 1));
}
.xp-glyph .g-line { fill: none; }
.xp-glyph .g-vein { stroke-width: .8; opacity: .7; }
.xp-glyph .g-fill { fill-opacity: calc(var(--fill, 1) * .5); transition: fill-opacity .6s ease; }
.xp-glyph .g-seed { fill: #c79a6e; }
.xp-glyph .g-leaf, .xp-glyph .g-bud { fill: #9db58c; }
.xp-glyph .g-tip { fill: #b490d8; fill-opacity: calc(var(--fill, 1) * .9); }
.xp-glyph .g-ray { fill: #c4a5e0; }
.xp-glyph .g-ray use { stroke-width: 1; }
.xp-glyph .g-disc { fill: #e3b552; fill-opacity: calc(var(--fill, 1) * .95); }
.xp-row:hover .xp-glyph { animation: xp-sway 3.2s ease-in-out infinite; }
@keyframes xp-sway { 0%, 100% { transform: rotate(0deg); } 30% { transform: rotate(-4deg); } 70% { transform: rotate(3deg); } }

.xp-num { display: block; font: 500 11px/1 var(--sans); letter-spacing: .22em; color: var(--aster-deep); margin-top: 8px; transition: letter-spacing .5s ease; }
.xp-row:hover .xp-num { letter-spacing: .34em; }
.xp-body h3 { font: 400 clamp(40px, 4.4vw, 62px)/1.02 var(--serif); letter-spacing: -.035em; margin: 14px 0 10px; transition: transform .6s cubic-bezier(.2, .7, .2, 1); }
.xp-row:hover .xp-body h3 { transform: translateX(5px); }
.xp-tag { font: italic 400 clamp(19px, 1.7vw, 24px)/1.3 var(--serif); letter-spacing: -.01em; color: var(--aster-deep); margin: 0 0 20px; }
.xp-desc { font-size: 15.5px; line-height: 1.75; color: var(--ink-soft); max-width: 52ch; margin: 0 0 28px; }
.xp-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 13px 30px; max-width: 540px; }
.xp-list li { position: relative; padding-left: 24px; font-size: 14px; line-height: 1.45; color: var(--ink); }
.xp-list li::before {
  content: ""; position: absolute; left: 1px; top: .42em; width: 11px; height: 7px;
  border-radius: 0 100% 0 100%; background: #bba2d9; transform: rotate(-32deg);
}

/* With JS and motion: the chapter's list unfolds item by item when the row
   comes into view. Never applied without the .exp-live class. */
.expertise.exp-live .xp-row .xp-list li { opacity: 0; transform: translateY(10px); transition: opacity .6s ease, transform .6s cubic-bezier(.2, .7, .2, 1); }
.expertise.exp-live .xp-row.xp-in .xp-list li { opacity: 1; transform: none; }
.expertise.exp-live .xp-row.xp-in .xp-list li:nth-child(2) { transition-delay: .08s; }
.expertise.exp-live .xp-row.xp-in .xp-list li:nth-child(3) { transition-delay: .16s; }
.expertise.exp-live .xp-row.xp-in .xp-list li:nth-child(4) { transition-delay: .24s; }

@media (max-width: 1050px) {
  .xp { gap: 0 44px; }
  .xp-row { grid-template-columns: 84px minmax(0, 1fr); gap: 0 24px; }
  .xp-glyph { width: 84px; height: 94px; transform-origin: 13px 94px; }
  .xp-list { grid-template-columns: 1fr; gap: 11px; }
}
@media (max-width: 860px) {
  .xp { grid-template-columns: 1fr; }
  .xp-intro { position: static; margin-bottom: 52px; }
  .xp-intro h2 { font-size: clamp(36px, 9vw, 52px); }
  .xp-rows { padding-left: 0; }
  .xp-vine { display: none; }
  .xp-row { grid-template-columns: 1fr; gap: 0; padding: 40px 0 44px; }
  .xp-rows > .xp-row:first-of-type { border-top: 1px solid rgba(94, 61, 138, .16); padding-top: 40px; }
  .xp-row::before { display: none; }
  .xp-glyph { width: 96px; height: 108px; margin-bottom: 14px; transform-origin: 15px 108px; }
  .xp-num { margin-top: 0; }
  .xp-body h3 { font-size: clamp(38px, 11vw, 52px); }
  .xp-list { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 460px) { .xp-list { grid-template-columns: 1fr; } }
@media (hover: none) { .xp-row::before { display: none; } .xp-row:hover .xp-glyph { animation: none; } }
@media (prefers-reduced-motion: reduce) {
  .xp-row:hover .xp-glyph { animation: none; }
  .xp-row:hover .xp-body h3, .xp-row:hover .xp-num { transform: none; letter-spacing: .22em; }
}

/* ========== Process: from the wall into the flower's night ==========
   The heading sits on the warm, grained candlelit wall; the bloom plays on a
   different, cooler surface. They used to meet at a hard edge with only a few
   RGB points between them, which read as a mismatch rather than a choice.
   Now it is a choice: the stage is a deep violet night, clearly a different
   room from the warm brown above, and the two are joined by a long feather so
   there is no line to see - the wall simply darkens into the night as the
   flower begins. The last stretch warms back toward the next section's
   near-black so the exit is as soft as the entrance.
   Applied in every state (also before JS, and for reduced motion) so the
   section never flashes between two colours. */
.process .bloom-zoom {
  background:
    linear-gradient(180deg, #17150f 0, rgba(23, 21, 15, .85) 70px, rgba(23, 21, 15, 0) clamp(280px, 42vh, 460px)),
    linear-gradient(180deg, #1d1530 0%, #21183a 30%, #1a1229 70%, #130f1b 90%, #100e0a 100%);
}

.process-fade {
  position: relative; z-index: 3; height: 170px; margin-top: -170px; pointer-events: none;
  background: linear-gradient(180deg, rgba(23, 21, 15, 0) 0%, rgba(23, 21, 15, .55) 55%, #17150f 100%);
}

/* ========== Motion system ==========
   One vocabulary instead of a different curve per section.
     --ease-expo   things ARRIVING: fast start, long soft landing
     --ease-out    gentle hovers and fades
     --ease-io     things that travel and stop (progress, wipes)
     --spring      things you TOUCH: a damped spring, ~10% overshoot, settles by
                   the end. Real physics rather than a bezier approximation of
                   it, so a lifted card lands with weight. Browsers without
                   linear() fall back to a bezier with a similar single bounce. */
:root {
  --ease-expo: cubic-bezier(.16, 1, .3, 1);
  --ease-out: cubic-bezier(.22, 1, .36, 1);
  --ease-io: cubic-bezier(.65, 0, .35, 1);
  --spring: cubic-bezier(.34, 1.32, .64, 1);
}
@supports (transition-timing-function: linear(0, 1)) {
  :root {
    --spring: linear(0, 0.035 2.9%, 0.125, 0.247, 0.386, 0.527 14.7%, 0.661, 0.78, 0.881, 0.961 26.5%, 1.022, 1.065, 1.091, 1.104 38.2%, 1.107, 1.101, 1.091, 1.077 50%, 1.062, 1.047, 1.033, 1.021 61.8%, 1.011, 1.002, 0.996, 0.992 73.5%, 0.99, 0.989, 0.989, 0.989 85.3%, 0.991, 0.992, 0.994, 0.995 97.1%, 1);
  }
}

/* ---- Headings: a mask rise instead of a blur --------------------------------
   Each word slides up out of its own clipped line, one after another. The old
   treatment faded the whole heading in through a 13px blur, which is expensive
   to render and smears the type for the whole second it is on screen. This is
   cheaper (transform only) and reads as typography being set, not as a focus
   pull. motion.js adds .rt-split; without it the old reveal still applies. */
.reveal-type.rt-split { opacity: 1; transform: none; filter: none; transition: none; }
.rt-split .rt-w {
  display: inline-block; vertical-align: top; overflow: hidden;
  padding: .16em .12em .22em; margin: -.16em -.12em -.22em;   /* room for ascenders, descenders, italic overhang */
}
.rt-split .rt-i {
  display: inline-block; transform: translate3d(0, 115%, 0);
  transition: transform 1.2s var(--ease-expo);
  transition-delay: calc(var(--rt, 0) * 60ms + 60ms);
}
.rt-split.in .rt-i { transform: none; }

/* ---- Touch feedback: buttons give, then settle -------------------------------
   Hover lifts on the spring; pressing squeezes; release springs back past rest.
   The magnetic pull (motion.js) uses the separate `translate` property so it
   never fights these transforms. */
.btn, .xp-link--main, .nav-project-link, .work-btn {
  translate: var(--mag-x, 0px) var(--mag-y, 0px);
  transition:
    transform .55s var(--spring),
    scale .45s var(--spring),
    background .3s var(--ease-out), color .3s var(--ease-out),
    border-color .3s var(--ease-out), box-shadow .45s var(--ease-out);
}
.btn:active, .xp-link--main:active, .nav-project-link:active, .work-btn:active:not(:disabled) {
  scale: .95; transition-duration: .1s, .1s, .3s, .3s, .3s, .45s;
}
.btn .ar { transition: transform .5s var(--spring); }

/* ---- Cards: lift with weight ------------------------------------------------ */
.case, .tier { transition: transform .7s var(--spring), box-shadow .5s var(--ease-out), border-color .5s var(--ease-out); }

/* ---- Scroll progress: a hairline across the very top --------------------- */
.scroll-progress {
  position: fixed; left: 0; top: 0; right: 0; height: 2px; z-index: 1200; pointer-events: none;
  background: linear-gradient(90deg, #8b5fbf, #c4a5e0 60%, #e3b552);
  transform-origin: 0 50%; transform: scaleX(0); opacity: 0; transition: opacity .4s ease;
}
.scroll-progress.on { opacity: .85; }

@media (prefers-reduced-motion: reduce) {
  .btn, .xp-link--main, .nav-project-link, .work-btn { translate: none; }
  .btn:active, .xp-link--main:active, .nav-project-link:active { scale: 1; }
  .scroll-progress { display: none; }
}
