/* ==========================================================================
   ADITSY — Design System, "Yestalgia" theme
   Sun-bleached, colour-block, sticker-pop retro. Cream canvas, thick ink
   outlines, hard offset shadows, and a warm sunset gradient standing in
   for the old dark-void thrust accent. Same tokens, new mood: 80s poster
   over launch-pad.
   ========================================================================== */

/* Bricolage Grotesque + Space Mono now load via a <link rel="stylesheet">
   (with preconnect) in each page's <head> instead of @import here — an
   @import inside a stylesheet can only be discovered after the whole CSS
   file is fetched and parsed, forcing a serial waterfall instead of a
   parallel fetch. General Sans has no page-level link yet, so it stays
   on @import for now. */
@import url('https://api.fontshare.com/v2/css?f[]=general-sans@400,500,600,700&display=swap');

:root{
  /* surfaces */
  --void:#fff8ea;
  --surface:#ffffff;
  --surface-2:#fff1d6;
  --surface-3:#ffe7bd;
  --line:#181410;
  --line-soft:rgba(24,20,16,0.12);

  /* ink */
  --ink:#181410;
  --ink-dim:#4a4436;
  --muted:#78715c;
  --muted-2:#a89d80;

  /* brand accents */
  --ion:#8c6bff;
  --ion-2:#b7a3ff;
  --ion-soft:rgba(140,107,255,0.14);
  --ember:#ff6b4a;
  --ember-2:#ff9b78;
  --ember-soft:rgba(255,107,74,0.14);
  --mint:#33c98e;
  --yellow:#f3d92e;
  --sky:#4fc3ea;
  --pink:#ff9cc5;
  /* fixed dark ink for text/icons sitting on bright accent chips (yellow,
     sky, pink, mint) — those accents stay bright in both themes, so the
     text on them must stay dark in both themes too, never following --ink. */
  --ink-on-accent:#18140e;

  /* gradients */
  --grad-thrust:linear-gradient(120deg,var(--ember) 0%,var(--pink) 45%,var(--ion) 100%);
  --grad-void:radial-gradient(120% 120% at 50% 0%,#fff1d6 0%,#fff8ea 60%);
  --shadow-pop:5px 5px 0 var(--line);
  --shadow-pop-lg:9px 9px 0 var(--line);

  /* type */
  --f-display:'Bricolage Grotesque','General Sans',sans-serif;
  --f-body:'General Sans',-apple-system,BlinkMacSystemFont,sans-serif;
  --f-mono:'Space Mono',ui-monospace,monospace;

  /* scale */
  --fs-h1:clamp(2.6rem,6.2vw,7.2rem);
  --fs-h2:clamp(2.1rem,4.4vw,4.4rem);
  --fs-h3:clamp(1.5rem,2.6vw,2.4rem);
  --fs-lead:clamp(1.05rem,1.6vw,1.4rem);
  --fs-body:1.0625rem;
  --fs-small:0.875rem;
  --fs-eyebrow:0.8125rem;

  /* spacing */
  --sp-1:0.5rem;
  --sp-2:1rem;
  --sp-3:1.5rem;
  --sp-4:2.5rem;
  --sp-5:4rem;
  --sp-6:6rem;
  --sp-7:9rem;

  --radius-s:10px;
  --radius-m:18px;
  --radius-l:28px;

  --ease-out:cubic-bezier(.16,1,.3,1);
  --ease-inout:cubic-bezier(.65,0,.35,1);
  --ease-bounce:cubic-bezier(.34,1.56,.64,1);
  --dur-s:220ms;
  --dur-m:480ms;
  --dur-l:900ms;

  --container:1320px;
}

/* ---------- dark theme ----------
   Same token names, inverted mood: warm cream flips to a near-black,
   coffee-brown void; the thick ink outlines and offset "sticker" shadows
   flip to a light stroke so cards still read as cut-out and pinned down,
   just under a different light. Accent hues are untouched — they were
   already saturated enough to hold up on a dark ground.
   Explicit choice ([data-theme]) always wins; with no explicit choice,
   the OS preference decides ("System" in the theme switcher). */
:root[data-theme="dark"]{
  --void:#0f0d09;
  --surface:#18140e;
  --surface-2:#1f1a12;
  --surface-3:#272016;
  --line:#f3ecdb;
  --line-soft:rgba(243,236,219,0.14);

  --ink:#f6f1e4;
  --ink-dim:#cabfa4;
  --muted:#d9d0ba;
  --muted-2:#a89d80;

  --ion:#a68bff;
  --ion-2:#c6b6ff;
  --ion-soft:rgba(166,139,255,0.18);
  --ember:#ff8163;
  --ember-2:#ffab8d;
  --ember-soft:rgba(255,129,99,0.18);
  --mint:#4fe0a4;
  --yellow:#f3d92e;
  --sky:#6fd3f2;
  --pink:#ffabd2;

  --grad-void:radial-gradient(120% 120% at 50% 0%,#211b12 0%,#0f0d09 60%);
  --shadow-pop:5px 5px 0 var(--line);
  --shadow-pop-lg:9px 9px 0 var(--line);
}
/* "System" (no explicit choice) follows the OS setting */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]):not([data-theme="dark"]){
    --void:#0f0d09;
    --surface:#18140e;
    --surface-2:#1f1a12;
    --surface-3:#272016;
    --line:#f3ecdb;
    --line-soft:rgba(243,236,219,0.14);

    --ink:#f6f1e4;
    --ink-dim:#cabfa4;
    --muted:#d9d0ba;
    --muted-2:#a89d80;

    --ion:#a68bff;
    --ion-2:#c6b6ff;
    --ion-soft:rgba(166,139,255,0.18);
    --ember:#ff8163;
    --ember-2:#ffab8d;
    --ember-soft:rgba(255,129,99,0.18);
    --mint:#4fe0a4;
    --yellow:#f3d92e;
    --sky:#6fd3f2;
    --pink:#ffabd2;

    --grad-void:radial-gradient(120% 120% at 50% 0%,#211b12 0%,#0f0d09 60%);
    --shadow-pop:5px 5px 0 var(--line);
    --shadow-pop-lg:9px 9px 0 var(--line);
  }
}
/* smooth crossfade when the theme is switched by hand */
body{transition:background var(--dur-m) var(--ease-out), color var(--dur-m) var(--ease-out);}
@media (prefers-reduced-motion:reduce){ body{transition:none;} }

*,*::before,*::after{box-sizing:border-box;}
html{scroll-behavior:auto;}
html,body{height:100%;}
body{
  margin:0;
  background:var(--void);
  color:var(--ink);
  font-family:var(--f-body);
  font-size:var(--fs-body);
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
body.no-scroll{overflow:hidden;}

img,svg,video{display:block;max-width:100%;}
a{color:inherit;text-decoration:none;}
ul{list-style:none;margin:0;padding:0;}
button{font:inherit;color:inherit;background:none;border:none;cursor:pointer;}
input,textarea,select{font:inherit;color:inherit;}

h1,h2,h3,h4{
  font-family:var(--f-display);
  font-weight:700;
  line-height:1.0;
  letter-spacing:-0.005em;
  margin:0;
}
p{margin:0;}

/* focus visibility, always */
:focus-visible{
  outline:2px solid var(--ion-2);
  outline-offset:3px;
  border-radius:4px;
}

/* grain overlay, fixed, whisper level */
.grain{
  position:fixed; inset:0; z-index:2; pointer-events:none;
  opacity:0.05; mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* starfield canvas, fixed behind everything */
#starfield{position:fixed;inset:0;z-index:0;pointer-events:none;}

.container{
  width:100%;
  max-width:var(--container);
  margin:0 auto;
  padding:0 var(--sp-3);
}
@media (max-width:640px){
  .container{padding:0 1.25rem;}
}

section{position:relative;z-index:1;}

/* ---------- eyebrow / labels ---------- */
.eyebrow{
  display:inline-flex; align-items:center; gap:.5rem;
  font-family:var(--f-mono);
  font-size:var(--fs-eyebrow);
  letter-spacing:0.08em;
  text-transform:uppercase;
  color:var(--muted);
}
.eyebrow::before{
  content:'';
  width:6px;height:6px;border-radius:50%;
  background:var(--grad-thrust);
  box-shadow:0 0 12px var(--ion);
}

/* ---------- buttons ---------- */
.btn{
  position:relative;
  display:inline-flex; align-items:center; justify-content:center; gap:.6rem;
  padding:1rem 1.9rem;
  font-family:var(--f-body);
  font-weight:600;
  font-size:0.95rem;
  border-radius:100px;
  cursor:pointer;
  transition:transform var(--dur-s) var(--ease-out), background var(--dur-s) var(--ease-out), color var(--dur-s) var(--ease-out), border-color var(--dur-s) var(--ease-out);
  white-space:nowrap;
}
.btn-primary{
  background:var(--yellow);
  color:var(--ink-on-accent);
  border:2px solid var(--line);
  box-shadow:var(--shadow-pop);
}
.btn-primary:hover{background:var(--grad-thrust);color:#fff;border-color:var(--line);transform:translate(-2px,-2px);box-shadow:7px 7px 0 var(--line);}
.btn-primary:active{transform:translate(1px,1px);box-shadow:2px 2px 0 var(--line);}
.btn-ghost{
  border:2px solid var(--line);
  color:var(--ink);
  background:var(--surface);
  box-shadow:var(--shadow-pop);
}
.btn-ghost:hover{border-color:var(--line);background:var(--sky);color:var(--ink);transform:translate(-2px,-2px);box-shadow:7px 7px 0 var(--line);}
.btn-ghost:active{transform:translate(1px,1px);box-shadow:2px 2px 0 var(--line);}
.btn-sm{padding:.7rem 1.3rem;font-size:.85rem;}
.btn svg{width:16px;height:16px;transition:transform var(--dur-s) var(--ease-out);}
.btn:hover svg{transform:translate(3px,-3px);}

/* magnetic wrapper target */
[data-magnetic]{will-change:transform;}

/* ---------- nav ---------- */
.nav{
  position:fixed; top:0; left:0; right:0; z-index:100;
  padding:1.4rem 0;
  transition:background var(--dur-m) var(--ease-out), padding var(--dur-m) var(--ease-out), border-color var(--dur-m) var(--ease-out);
  border-bottom:2px solid transparent;
  /* header sits inside .page-shell (see that rule further down) and keeps
     a high z-index so it stays above the rest of the page's own content;
     pointer-events stays live only on its actual visible controls so its
     empty box never blocks clicks meant for whatever's behind it. */
  pointer-events:none;
}
.nav > *{pointer-events:auto;}
.nav.is-scrolled{
  background:color-mix(in srgb, var(--void) 90%, transparent);
  backdrop-filter:blur(14px) saturate(140%);
  -webkit-backdrop-filter:blur(14px) saturate(140%);
  padding:1rem 0;
}
.nav-inner{display:flex;align-items:center;justify-content:space-between;gap:2rem;position:relative;z-index:95;pointer-events:none;}
.nav-inner > *{pointer-events:auto;}
.brand{display:flex;align-items:center;gap:.55rem;font-family:var(--f-display);font-size:1.15rem;font-weight:600;letter-spacing:-0.01em;color:inherit;}
.brand .mark{
  display:inline-block;flex:none;width:32px;height:32px;
  background-color:currentColor;
  -webkit-mask-image:url('../img/mark-alpha.png');mask-image:url('../img/mark-alpha.png');
  -webkit-mask-size:contain;mask-size:contain;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center;
  /* same "negative" rim as the cursor mark: currentColor alone can wash
     out over a busy or similarly-toned backdrop (a scrolled, blurred nav,
     a gradient section behind a transparent header), so a thin void-toned
     outline keeps the mark legible no matter what's behind it. */
  filter:
    drop-shadow(1.5px 0 0 var(--void))
    drop-shadow(-1.5px 0 0 var(--void))
    drop-shadow(0 1.5px 0 var(--void))
    drop-shadow(0 -1.5px 0 var(--void));
}
.nav-cta{display:flex;align-items:center;gap:1.1rem;}
/* "Orbit" wordmark badge next to the Aditsy brand mark, nav + footer.
   Small caps chip so the rebrand stays legible at 375px without
   forcing the header to wrap or shrink the primary "Aditsy" mark. */
.brand-badge{
  font-family:var(--f-mono);font-size:.62rem;font-weight:700;letter-spacing:.08em;
  padding:.18rem .42rem;border-radius:100px;border:1.5px solid currentColor;
  line-height:1;text-transform:uppercase;opacity:.82;
}

/* -------- checkbox-driven drawer: opens with zero JS dependency --------
   #nav-toggle-check is the real control; .nav-toggle is its <label>, so
   clicking or pressing Space/Enter on it toggles the drawer natively even
   if every script on the page failed to load. JS only adds polish
   (Escape to close, a ticking clock, focus handling) on top of that. */
.nav-toggle-check{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
}
.nav-toggle{
  display:flex; align-items:center; gap:.6rem;
  border:2px solid var(--line); border-radius:999px;
  padding:.5rem .55rem .5rem 1.05rem;
  background:var(--surface); cursor:pointer;
  box-shadow:3px 3px 0 var(--line);
  transition:transform var(--dur-s) var(--ease-out), box-shadow var(--dur-s) var(--ease-out), background var(--dur-s), color var(--dur-s);
}
.nav-toggle:hover{transform:translate(-2px,-2px);box-shadow:5px 5px 0 var(--line);}
.nav-toggle-check:focus-visible + .nav-toggle{outline:2px solid var(--ion);outline-offset:2px;}
.nav-toggle-label{font-family:var(--f-mono);font-size:.72rem;letter-spacing:.08em;text-transform:uppercase;}
.nav-toggle-label .close-txt{display:none;}
.nav-toggle-icon{position:relative;width:28px;height:28px;flex:none;border-radius:50%;background:var(--ink);display:flex;align-items:center;justify-content:center;}
.nav-toggle-icon i{
  display:block;position:absolute;width:12px;height:1.5px;background:var(--void);
  transition:transform var(--dur-s) var(--ease-out),opacity var(--dur-s);
}
.nav-toggle-icon i:first-child{transform:translateY(-2.5px);}
.nav-toggle-icon i:last-child{transform:translateY(2.5px);}

/* open state driven by :checked (always works) — a JS-set .is-open class
   on .nav is honoured too, so either mechanism opens the same drawer.
   The checkbox now lives at the body level rather than beside .nav-inner
   (see the .page-shell comment above), so :checked's reach into the
   header uses body:has(...) instead of a sibling combinator. */
body:has(.nav-toggle-check:checked) .nav-toggle,
.nav.is-open .nav-toggle{background:var(--ink);color:var(--void);}
body:has(.nav-toggle-check:checked) .nav-toggle .nav-toggle-icon,
.nav.is-open .nav-toggle .nav-toggle-icon{background:var(--void);}
body:has(.nav-toggle-check:checked) .nav-toggle .nav-toggle-icon i,
.nav.is-open .nav-toggle .nav-toggle-icon i{background:var(--ink);}
body:has(.nav-toggle-check:checked) .nav-toggle .nav-toggle-icon i:first-child,
.nav.is-open .nav-toggle .nav-toggle-icon i:first-child{transform:rotate(45deg);}
body:has(.nav-toggle-check:checked) .nav-toggle .nav-toggle-icon i:last-child,
.nav.is-open .nav-toggle .nav-toggle-icon i:last-child{transform:rotate(-45deg) translateY(0);}
body:has(.nav-toggle-check:checked) .nav-toggle-label .open-txt,
.nav.is-open .nav-toggle-label .open-txt{display:none;}
body:has(.nav-toggle-check:checked) .nav-toggle-label .close-txt,
.nav.is-open .nav-toggle-label .close-txt{display:inline;}

/* -------- the nav: a permanent full-screen dark layer sits fixed behind
   the whole site; opening the menu doesn't slide a panel over the page —
   instead the page itself (.page-shell, everything visible: header, main,
   footer) tilts and slides away like a turned book page, pivoting from its
   bottom-left corner, to reveal the dark layer and its nav links behind
   it. Still checkbox-driven with zero JS dependency. -------- */
body:has(.nav-toggle-check:checked){overflow:hidden;}

.page-shell{
  position:relative; z-index:10;
  background:var(--void);
  /* the pivot sits one viewport-height below the shell's own top edge,
     not 100% of the shell's full height — main#main can be many times
     taller than the viewport, and a %-based origin would make the tilt's
     apparent swing balloon on long pages. main.js scrolls to the top
     before opening so this lines up with what's on screen from any
     scroll position. */
  transform-origin:0 100vh;
  transition:transform var(--dur-l) var(--ease-inout), border-radius var(--dur-l) var(--ease-inout), box-shadow var(--dur-l) var(--ease-inout);
  /* no will-change:transform here on purpose — per spec it creates a
     containing block for position:fixed descendants exactly like a real
     transform would, even with none currently applied. main#main (inside
     this shell) holds every GSAP ScrollTrigger pinned section on the page
     (they pin via position:fixed), so a permanent containing block would
     silently detach every one of them from the real viewport during
     normal scrolling. The transform below only turns on while the menu is
     open, when scroll is locked and the shell itself is mostly hidden
     behind the dark nav layer, so it never reaches a moment where it
     could break a pin. */
}
body:has(.nav-toggle-check:checked) .page-shell{
  /* translateX/scale carry the actual displacement (in %, of the shell's
     own width — always ~100vw regardless of page length, so this stays
     consistent on a two-screen page and a twenty-screen one alike);
     rotate is just the tilt on top of that, not what clears the space. */
  transform:translate(-42%, 5vh) rotate(-8deg) scale(0.88);
  border-radius:22px;
  box-shadow:-60px 50px 140px rgba(10,8,5,0.45);
}
@media (prefers-reduced-motion:reduce){
  .page-shell{transition:none;}
  body:has(.nav-toggle-check:checked) .page-shell{transform:none;border-radius:0;box-shadow:none;}
}

/* the dark layer: always present, fixed full-screen, behind .page-shell */
.nav-black{
  position:fixed; inset:0; z-index:5;
  background:var(--ink); color:var(--void);
  display:flex; flex-direction:column;
  padding:1.6rem clamp(1.4rem,4vw,3.4rem) 1.8rem;
  opacity:0; visibility:hidden;
  transition:opacity var(--dur-m) var(--ease-inout), visibility 0s linear var(--dur-m);
}
body:has(.nav-toggle-check:checked) .nav-black{
  opacity:1; visibility:visible;
  transition:opacity var(--dur-m) var(--ease-inout) .1s;
}
/* the dot stays alone on the left as a decorative accent — it's fine if
   the tilted page-shell covers it. Everything a visitor actually needs
   to click (theme switch, Close) lives on the right in .nav-black-bar-right,
   which sits in the black area the page-shell never reaches over, on any
   page length or viewport width. */
.nav-black-bar{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex:none;}
.nav-black-dot{width:9px;height:9px;background:var(--ember-2);flex:none;}
.nav-black-bar-right{display:flex;align-items:center;gap:1.4rem;flex:none;}
.nav-black-bar-right .nav-theme-switch{flex-wrap:nowrap;}
.nav-black-close{
  font-family:var(--f-mono); font-size:.75rem; font-weight:700; letter-spacing:.1em; text-transform:uppercase;
  cursor:pointer; padding:.3rem 0; flex:none;
}
.nav-black-links{flex:1; min-height:0; display:flex; align-items:center; justify-content:flex-end; overflow-y:auto;}
.nav-menu-list{list-style:none;margin:0;padding:0;text-align:right;}
.nav-menu-list a{
  display:inline-flex; align-items:center; justify-content:flex-end; gap:.5em;
  padding:.06em 0; position:relative;
  font-family:var(--f-display); font-weight:800; text-transform:uppercase;
  font-size:clamp(1.5rem,3.6vw,2.5rem); line-height:1.14; letter-spacing:-0.01em;
  color:color-mix(in srgb, var(--void) 40%, transparent);
  transition:color var(--dur-s) var(--ease-out);
}
.nav-menu-list a::before{
  content:''; width:.28em; height:.28em; flex:none; background:var(--ember-2);
  opacity:0; transform:scale(0.4); transition:opacity var(--dur-s), transform var(--dur-s);
}
.nav-menu-list a:hover,.nav-menu-list a:focus-visible,.nav-menu-list a[aria-current="page"]{color:var(--void);}
.nav-menu-list a:hover::before,.nav-menu-list a:focus-visible::before,
.nav-menu-list a[aria-current="page"]::before{opacity:1;transform:scale(1);}
/* staggered entrance once the menu opens */
.nav-menu-list li{opacity:0;transform:translateY(14px);transition:opacity var(--dur-m) var(--ease-out),transform var(--dur-m) var(--ease-out);}
body:has(.nav-toggle-check:checked) .nav-menu-list li{opacity:1;transform:translateY(0);}
body:has(.nav-toggle-check:checked) .nav-menu-list li:nth-child(1){transition-delay:.1s;}
body:has(.nav-toggle-check:checked) .nav-menu-list li:nth-child(2){transition-delay:.14s;}
body:has(.nav-toggle-check:checked) .nav-menu-list li:nth-child(3){transition-delay:.18s;}
body:has(.nav-toggle-check:checked) .nav-menu-list li:nth-child(4){transition-delay:.22s;}
body:has(.nav-toggle-check:checked) .nav-menu-list li:nth-child(5){transition-delay:.26s;}
body:has(.nav-toggle-check:checked) .nav-menu-list li:nth-child(6){transition-delay:.3s;}
body:has(.nav-toggle-check:checked) .nav-menu-list li:nth-child(7){transition-delay:.34s;}

.nav-black-foot{
  flex:none; margin-top:1rem; padding-top:1.1rem;
  border-top:1px solid color-mix(in srgb, var(--void) 16%, transparent);
  display:flex; align-items:flex-end; justify-content:flex-end; gap:1.2rem; flex-wrap:wrap;
}
.nav-theme-switch{display:flex; flex-direction:row; flex-wrap:wrap; align-items:center; gap:1rem;}
.theme-opt{
  display:flex; align-items:center; gap:.5rem;
  font-family:var(--f-mono); font-size:.7rem; letter-spacing:.08em; text-transform:uppercase;
  color:color-mix(in srgb, var(--void) 55%, transparent); cursor:pointer; padding:.15rem 0;
  transition:color var(--dur-s);
}
.theme-opt::before{
  content:''; width:7px; height:7px; border-radius:50%; border:1.5px solid currentColor; flex:none;
  transition:background var(--dur-s), border-color var(--dur-s);
}
.theme-opt:hover{color:var(--void);}
.theme-opt.is-active{color:var(--void); font-weight:700;}
.theme-opt.is-active::before{background:var(--void); border-color:var(--void);}
.nav-black-meta{display:flex; flex-direction:column; align-items:flex-end; gap:.45rem; min-width:0;}
.nav-menu-tag{font-family:var(--f-mono);font-size:.64rem;letter-spacing:.08em;text-transform:uppercase;color:var(--ember-2);display:flex;align-items:center;gap:.5rem;}
.nav-menu-tag::before{content:'';width:6px;height:6px;border-radius:50%;background:var(--ember-2);box-shadow:0 0 0 3px var(--ember-soft);}
.nav-menu-legal{display:flex; flex-direction:row; gap:.9rem;}
.nav-menu-legal a{
  font-family:var(--f-mono); font-size:.66rem; letter-spacing:.06em; text-transform:uppercase;
  color:color-mix(in srgb, var(--void) 55%, transparent); text-decoration:underline; text-underline-offset:3px;
  transition:color var(--dur-s);
}
.nav-menu-legal a:hover{color:var(--void);}

/* rotating/scrolling text hover: a clipped line that rolls up to reveal
   a duplicate underneath — used on the nav's big links and a few
   headline links elsewhere on the site. */
.hover-roll{display:inline-block;overflow:hidden;vertical-align:top;line-height:1.02;height:1.05em;perspective:400px;}
.hover-roll-inner{display:flex;flex-direction:column;transition:transform var(--dur-m) var(--ease-inout);transform-origin:center bottom;}
.hover-roll-line{display:block;line-height:1.05em;}
a:hover .hover-roll-inner,.hover-roll:hover .hover-roll-inner{transform:translateY(-50%) rotateX(4deg);}
@media (prefers-reduced-motion:reduce){
  .hover-roll-inner{transition:none;}
}

@media (max-width:860px){
  .nav-cta .btn-ghost{display:none;}
  .nav-black{padding:1.3rem 1.4rem 1.6rem;}
  .nav-black-bar-right{gap:.85rem;}
  .nav-black-bar-right .nav-theme-switch{gap:.6rem;}
  .nav-menu-list a{font-size:clamp(1.5rem,7vw,2.1rem);}
  .nav-black-foot{gap:.9rem;}
  body:has(.nav-toggle-check:checked) .page-shell{
    transform:translate(-56%, 4vh) rotate(-6deg) scale(0.9);
  }
}
@media (max-height:700px){
  .nav-menu-list a{font-size:clamp(1.25rem,3.6vw,1.8rem);line-height:1.08;}
}
@media (prefers-reduced-motion:reduce){
  .nav-menu-list li{opacity:1;transform:none;transition:none;}
  .nav-black{transition:none;}
}

/* ---------- footer ---------- */
.site-footer{
  position:relative;z-index:1;
  border-top:2px solid var(--line);
  padding:var(--sp-6) 0 var(--sp-3);
  background:var(--surface);
}
.footer-top{
  display:grid;
  grid-template-columns:1.4fr repeat(3,1fr);
  gap:var(--sp-4);
  padding-bottom:var(--sp-5);
  border-bottom:2px solid var(--line);
}
.footer-brand p{color:var(--muted);margin-top:1rem;max-width:32ch;}
.footer-col h4{font-family:var(--f-mono);font-size:.78rem;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);font-weight:500;margin-bottom:1.1rem;}
.footer-col a,.footer-col p{display:block;color:var(--ink-dim);font-size:.92rem;padding:.32rem 0;transition:color var(--dur-s);}
.footer-col a:hover{color:var(--ion-2);}
.footer-bottom{
  display:flex;justify-content:space-between;align-items:center;gap:1rem;
  padding-top:var(--sp-3); color:var(--muted-2); font-size:.82rem;flex-wrap:wrap;
}
.footer-bottom .legal-links{display:flex;gap:1.4rem;}
.footer-bottom a:hover{color:var(--ink-dim);}
.footer-social{display:flex;gap:.9rem;}
.footer-social a{width:38px;height:38px;border:2px solid var(--line);border-radius:50%;display:flex;align-items:center;justify-content:center;transition:border-color var(--dur-s),background var(--dur-s),transform var(--dur-s);box-shadow:3px 3px 0 var(--line);}
.footer-social a:hover{background:var(--yellow);color:var(--ink-on-accent);transform:translate(-2px,-2px);box-shadow:5px 5px 0 var(--line);}
.footer-social svg{width:16px;height:16px;}

@media (max-width:860px){
  .footer-top{grid-template-columns:1fr 1fr;row-gap:var(--sp-4);}
}
@media (max-width:560px){
  .footer-top{grid-template-columns:1fr;}
  .footer-bottom{flex-direction:column;align-items:flex-start;}
}

/* ---------- reveal / motion ---------- */
[data-reveal]{opacity:0;transform:translateY(28px) scale(.97);transition:opacity 800ms var(--ease-bounce), transform 800ms var(--ease-bounce);}
[data-reveal].is-visible{opacity:1;transform:translateY(0) scale(1);}
[data-reveal-scale]{opacity:0;transform:scale(.9) rotate(-1.5deg);transition:opacity 800ms var(--ease-bounce), transform 800ms var(--ease-bounce);}
[data-reveal-scale].is-visible{opacity:1;transform:scale(1) rotate(0);}
[data-stagger] > *{opacity:0;transform:translateY(22px) scale(.96);transition:opacity 650ms var(--ease-bounce), transform 650ms var(--ease-bounce);}
[data-stagger].is-visible > *{opacity:1;transform:translateY(0) scale(1);}
[data-stagger].is-visible > *:nth-child(1){transition-delay:0ms;}
[data-stagger].is-visible > *:nth-child(2){transition-delay:80ms;}
[data-stagger].is-visible > *:nth-child(3){transition-delay:160ms;}
[data-stagger].is-visible > *:nth-child(4){transition-delay:240ms;}
[data-stagger].is-visible > *:nth-child(5){transition-delay:320ms;}
[data-stagger].is-visible > *:nth-child(6){transition-delay:400ms;}

/* ---------- sitewide auto animate-in ----------
   Applied by JS (initAutoReveal) to headings, paragraphs, images, buttons
   etc. across every page so each element animates into place on scroll.
   Different element types get different entrance styles for variety:
   reveal-up (subheadings/labels), reveal-fade (body text), reveal-pop
   (images/buttons — bouncy scale-in), reveal-turn (big titles — rotate +
   scale), reveal-left/reveal-right (slide in from a side, alternated on
   images/cards). The hidden starting state is added by JS, never by
   static HTML — so if scripting is off, nothing is ever added, nothing is
   hidden, and the whole page renders normally. .is-in is the shown state. */
.reveal-up{opacity:0;transform:translateY(26px);transition:opacity 720ms var(--ease-out), transform 720ms var(--ease-out);will-change:opacity,transform;}
.reveal-up.is-in{opacity:1;transform:none;}

.reveal-fade{opacity:0;transition:opacity 820ms var(--ease-out);will-change:opacity;}
.reveal-fade.is-in{opacity:1;}

.reveal-pop{opacity:0;transform:scale(.82);transition:opacity 640ms var(--ease-out), transform 640ms var(--ease-bounce);will-change:opacity,transform;}
.reveal-pop.is-in{opacity:1;transform:scale(1);}

.reveal-turn{opacity:0;transform:rotate(-4deg) scale(.92) translateY(18px);transition:opacity 760ms var(--ease-out), transform 760ms var(--ease-bounce);will-change:opacity,transform;}
.reveal-turn.is-in{opacity:1;transform:rotate(0) scale(1) translateY(0);}

.reveal-left{opacity:0;transform:translateX(-38px);transition:opacity 720ms var(--ease-out), transform 720ms var(--ease-out);will-change:opacity,transform;}
.reveal-left.is-in{opacity:1;transform:none;}

.reveal-right{opacity:0;transform:translateX(38px);transition:opacity 720ms var(--ease-out), transform 720ms var(--ease-out);will-change:opacity,transform;}
.reveal-right.is-in{opacity:1;transform:none;}

/* custom cursor: a spaceship-mark pointer with a hover halo behind it,
   and a canvas comet trail (see effects.js). The soft trailing glow has
   been retired — the mark and ring now carry the whole effect on their
   own, bigger and cleaner without the blurred halo behind them. */
#cursor-trail{position:fixed;inset:0;z-index:9997;pointer-events:none;}
.cursor-glow{display:none;}
.cursor-ring{
  position:fixed;top:0;left:0;z-index:9998;
  width:50px;height:50px;border-radius:50%;
  pointer-events:none;transform:translate(-50%,-50%) scale(0);
  border:1px solid #fff;background:#fff;
  mix-blend-mode:difference;
  opacity:0;
  transition:opacity var(--dur-s) var(--ease-out), transform var(--dur-s) var(--ease-bounce);
  will-change:transform;
}
.cursor-ring.is-active{opacity:1;transform:translate(-50%,-50%) scale(1.1);}
.cursor-mark{
  position:fixed;top:0;left:0;z-index:9999;
  width:52px;height:68px;
  pointer-events:none;transform:translate(-50%,-50%);
  -webkit-mask-image:url('../img/mark-alpha.png');mask-image:url('../img/mark-alpha.png');
  -webkit-mask-size:contain;mask-size:contain;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center;
  background:#fff;
  /* true photographic-negative cursor: mix-blend-mode:difference inverts
     the mark against whatever it sits over, so it self-adjusts on any
     background (light page, dark nav overlay, colored doodle chips)
     without needing the old multi-direction drop-shadow rim hack. */
  mix-blend-mode:difference;
  transition:width var(--dur-s) var(--ease-out),height var(--dur-s) var(--ease-out);
  will-change:transform;
}
.cursor-mark.is-active{width:64px;height:84px;}
@media (hover:none),(pointer:coarse){
  .cursor-glow,.cursor-ring,.cursor-mark,#cursor-trail{display:none;}
}
/* the custom mark replaces the system pointer everywhere a mouse is
   actually driving the page; touch devices keep their native behaviour
   untouched since there's no pointer to draw a custom cursor under. */
@media (hover:hover) and (pointer:fine){
  *{cursor:none !important;}
}

/* ---------- themed scrollbar ---------- */
html{scrollbar-width:thin;scrollbar-color:var(--ink) var(--surface-2);}
::-webkit-scrollbar{width:12px;height:12px;}
::-webkit-scrollbar-track{background:var(--surface-2);}
::-webkit-scrollbar-thumb{
  background-color:var(--ink);
  border-radius:10px;
  border:3px solid var(--surface-2);
}
::-webkit-scrollbar-thumb:hover{background-color:var(--ember);}

/* page transition overlay */
.page-transition{
  position:fixed;inset:0;z-index:10000;
  background:var(--grad-thrust);
  transform:scaleY(0); transform-origin:bottom;
  pointer-events:none;
}
.page-transition.animate-in{animation:wipeIn var(--dur-m) var(--ease-inout) forwards;}
.page-transition.animate-out{animation:wipeOut var(--dur-m) var(--ease-inout) forwards;}
@keyframes wipeIn{from{transform:scaleY(0);transform-origin:bottom;}to{transform:scaleY(1);transform-origin:bottom;}}
@keyframes wipeOut{from{transform:scaleY(1);transform-origin:top;}to{transform:scaleY(0);transform-origin:top;}}

/* loader — a script failure (blocked, offline CDN, ad-blocker) must never
   leave this permanently covering the page: the animation below force-hides
   it after 3.2s even if main.js never runs to add .is-hidden itself. */
.loader{
  position:fixed;inset:0;z-index:10001;background:var(--void);
  display:flex;align-items:center;justify-content:center;flex-direction:column;gap:1.2rem;
  overflow:hidden;
  /* the container's own fade starts a beat after .is-hidden lands, so the
     mark's (now slower, ~1.1s) liftoff plays out clearly against a
     still-solid background before the whole screen dissolves — timed to
     finish close to when the mark itself finishes fading, so the two
     don't visibly race each other. */
  transition:opacity 650ms var(--ease-out) 380ms, visibility 650ms 380ms;
  animation:loader-failsafe 0s linear 3.2s forwards;
  /* purely decorative (logo + progress bar, nothing clickable) — must never
     eat a real click on the nav toggle underneath it while it fades out */
  pointer-events:none;
}
.loader.is-hidden{opacity:0;visibility:hidden;}
@keyframes loader-failsafe{to{opacity:0;visibility:hidden;pointer-events:none;}}
.loader-mark{
  position:relative; /* anchors the ignition-glow pseudo-element below */
  display:block;width:64px;height:64px;flex:none;
  background-color:var(--ink);
  -webkit-mask-image:url('../img/mark-alpha.png');mask-image:url('../img/mark-alpha.png');
  -webkit-mask-size:contain;mask-size:contain;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center;
  filter:drop-shadow(0 10px 20px rgba(24,20,16,0.22));
  animation:float 2.4s ease-in-out infinite;
  /* liftoff: an unhurried, steadily-accelerating launch straight up with
     a bit of zoom — smooth continuous thrust rather than a quick, jerky
     dart. A gentle ease-in curve (no overshoot/negative control points,
     which can read as a jittery little "wind-up" flinch right at the
     start when combined with main.js freezing the mark's mid-bob pose
     just before this fires) so the accelerating feel comes purely from
     the timing curve, not a visual snap. main.js only flips this class
     once the progress bar has actually reached 100%, so the motion
     always reads as "loading finished, launch" rather than firing at an
     arbitrary moment mid-fill. */
  transition:transform 1150ms cubic-bezier(.45,0,.85,1), opacity 750ms ease-out 280ms;
}
/* the ignition flash: a soft sunset-gradient bloom that blooms open right
   as the mark launches, then fades — a one-off "thrust" beat instead of
   the mark just silently zooming away. Sits behind the mark (z-index -1)
   and never appears during the idle bob, only on exit. */
.loader-mark::before{
  content:'';
  position:absolute; inset:-55%;
  border-radius:50%;
  background:var(--grad-thrust);
  opacity:0;
  filter:blur(16px);
  transform:scale(.55);
  transition:opacity 220ms ease-out, transform 220ms ease-out;
  z-index:-1;
}
.loader.is-hidden .loader-mark{
  animation:none;
  transform:translateY(-46vh) scale(2.1);
  opacity:0;
}
.loader.is-hidden .loader-mark::before{
  opacity:.6;
  transform:scale(1.35);
  transition:opacity 260ms ease-out, transform 460ms var(--ease-out);
}
.loader-bar{width:160px;height:2px;background:var(--line);overflow:hidden;border-radius:2px;transition:opacity 200ms ease-out;}
/* base fallback only — main.js drives the real two-phase fill (an eased
   creep toward ~78% while the page is actually loading, then a crisp
   snap to 100% the instant it's ready) by setting transition-duration
   inline per phase, so the bar's completion and the exit animation
   always land in sync instead of firing on unrelated timers. */
.loader-bar span{display:block;height:100%;width:0%;background:var(--grad-thrust);transition:width 900ms var(--ease-inout);}
.loader.is-hidden .loader-bar{opacity:0;}
@media (prefers-reduced-motion:reduce){
  .loader-mark{animation:none;transition:opacity 300ms ease-out;}
  .loader-mark::before{display:none;}
  .loader.is-hidden .loader-mark{transform:none;}
}

/* ---------- typography utilities ---------- */
.text-lead{font-size:var(--fs-lead);color:var(--ink-dim);font-weight:400;line-height:1.55;}
.text-muted{color:var(--muted);}
.text-gradient{
  background:var(--grad-thrust);
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
.mono-tag{
  font-family:var(--f-mono);font-size:.78rem;letter-spacing:.06em;
  color:var(--muted); text-transform:uppercase;
}

/* ---------- section shells ---------- */
.section{padding:var(--sp-7) 0;}
.section-tight{padding:var(--sp-5) 0;}
.section-head{
  display:flex;justify-content:space-between;align-items:flex-end;gap:2rem;
  margin-bottom:var(--sp-5);
}
.section-head h2{max-width:14ch;}
.section-head .text-lead{max-width:36ch;}
@media (max-width:760px){
  .section-head{flex-direction:column;align-items:flex-start;gap:1.2rem;}
  .section{padding:var(--sp-6) 0;}
}

.divider{height:2px;background:var(--line);width:100%;}

/* ---------- cards ---------- */
.card{
  background:var(--surface);
  border:2px solid var(--line);
  border-radius:var(--radius-m);
  padding:var(--sp-3);
  box-shadow:var(--shadow-pop);
  transition:border-color var(--dur-m) var(--ease-out), transform var(--dur-m) var(--ease-out), background var(--dur-m) var(--ease-out), box-shadow var(--dur-m) var(--ease-out);
}
.card:hover{background:var(--surface-2);transform:translate(-3px,-3px);box-shadow:var(--shadow-pop-lg);}

/* ---------- grid utilities ---------- */
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-4);}
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-3);}
.grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-3);}
@media (max-width:900px){
  .grid-2{grid-template-columns:1fr;}
  .grid-3{grid-template-columns:1fr 1fr;}
  .grid-4{grid-template-columns:1fr 1fr;}
}
@media (max-width:560px){
  .grid-3{grid-template-columns:1fr;}
  .grid-4{grid-template-columns:1fr;}
}

/* ---------- back to top ---------- */
.to-top{
  position:fixed; right:1.6rem; bottom:1.6rem; z-index:60;
  width:48px;height:48px;border-radius:50%;
  background:var(--yellow); color:var(--ink-on-accent); border:2px solid var(--line);
  box-shadow:var(--shadow-pop);
  display:flex;align-items:center;justify-content:center;
  opacity:0; pointer-events:none; transform:translateY(10px);
  transition:opacity var(--dur-s), transform var(--dur-s), border-color var(--dur-s), box-shadow var(--dur-s);
}
.to-top.is-visible{opacity:1;pointer-events:auto;transform:translateY(0);}
.to-top:hover{transform:translate(-2px,-2px);box-shadow:var(--shadow-pop-lg);}
.to-top svg{width:16px;height:16px;}

/* ---------- skip link ---------- */
.skip-link{
  position:fixed; top:-100px; left:1rem; z-index:10010;
  background:var(--ink); color:var(--void); padding:.7rem 1.2rem; border-radius:8px;
  transition:top var(--dur-s);
  font-size:.85rem;font-weight:600;
}
.skip-link:focus{top:1rem;}

/* ==========================================================================
   HERO
   ========================================================================== */
.hero{
  min-height:100svh;
  display:flex; flex-direction:column; justify-content:center;
  padding:8.5rem 0 var(--sp-6);
  position:relative;
}
.hero-grid{
  display:grid; grid-template-columns:1.15fr 0.85fr; gap:var(--sp-5); align-items:center;
}
.hero-kicker{margin-bottom:1.6rem;}
.hero h1{margin-bottom:1.7rem;}
.hero h1 .line{display:block;overflow:hidden;}
.hero h1 .line span{display:inline-block;transform:translateY(110%);transition:transform 900ms var(--ease-out);}
.hero.is-ready h1 .line span{transform:translateY(0);}
.hero h1 .line:nth-child(2) span{transition-delay:90ms;}
.hero h1 .line:nth-child(3) span{transition-delay:180ms;}
.hero-lead{max-width:44ch;margin-bottom:2.4rem;}
.hero-actions{display:flex;align-items:center;gap:1.6rem;flex-wrap:wrap;}
.hero-note{font-size:.85rem;color:var(--muted);display:flex;align-items:center;gap:.6rem;}
.hero-note svg{width:16px;height:16px;color:var(--mint);}

/* hero entrance: the h1 lines above already wipe in on load via
   .hero.is-ready — these give the kicker, lead paragraph, buttons and
   visual their own staggered fade/rise/pop so the whole hero animates in
   together, not just the headline. Same load-time gate as the h1 lines
   (never scroll-based, since the hero is always the first thing seen). */
.hero-kicker,.hero-lead,.hero-actions,.hero-note,.hero-visual{opacity:0;transition:opacity 820ms var(--ease-out), transform 820ms var(--ease-out);}
.hero-kicker{transform:translateY(16px);}
.hero-lead{transform:translateY(16px);transition-delay:260ms;}
.hero-actions{transform:scale(.92);transition-timing-function:var(--ease-bounce);transition-delay:360ms;}
.hero-note{transform:translateY(16px);transition-delay:420ms;}
.hero-visual{transform:scale(.9);transition-delay:200ms;}
.hero.is-ready .hero-kicker,
.hero.is-ready .hero-lead,
.hero.is-ready .hero-actions,
.hero.is-ready .hero-note,
.hero.is-ready .hero-visual{opacity:1;transform:none;}

.hero-visual{position:relative;aspect-ratio:1/1.05;display:flex;align-items:center;justify-content:center;}
.hero-orbit{position:absolute;inset:0;border-radius:50%;border:2px solid var(--line);}
.hero-orbit::before,.hero-orbit::after{content:'';position:absolute;inset:12%;border-radius:50%;border:2px solid var(--line);}
.hero-orbit::after{inset:24%;}
.hero-ship{position:relative;width:44%;animation:float 6s ease-in-out infinite;}
.hero-ship-img{
  display:block;width:100%;aspect-ratio:1/1;
  background-color:var(--ink);
  -webkit-mask-image:url('../img/mark-alpha.png');mask-image:url('../img/mark-alpha.png');
  -webkit-mask-size:70%;mask-size:70%;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:center;mask-position:center;
  filter:drop-shadow(0 16px 0 rgba(24,20,16,0.12));
}
@keyframes float{0%,100%{transform:translateY(0) rotate(-2deg);}50%{transform:translateY(-18px) rotate(2deg);}}
.hero-tag{
  position:absolute; padding:.55rem 1rem; border-radius:100px;
  background:var(--surface); border:2px solid var(--line);
  box-shadow:4px 4px 0 var(--line);
  font-family:var(--f-mono); font-size:.72rem; font-weight:700; letter-spacing:.05em; color:var(--ink);
  display:flex;align-items:center;gap:.5rem;
  animation:drift 7s ease-in-out infinite;
}
.hero-tag svg{width:12px;height:12px;color:var(--ember);}
.hero-tag.t1{top:6%;left:0%;animation-delay:0s;}
.hero-tag.t2{bottom:14%;right:0%;animation-delay:1.2s;}
.hero-tag.t3{bottom:2%;left:8%;animation-delay:2.4s;}
@keyframes drift{0%,100%{transform:translateY(0);}50%{transform:translateY(-10px);}}

.scroll-cue{
  position:absolute; left:50%; bottom:1.6rem; transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;gap:.6rem;
  color:var(--muted); font-family:var(--f-mono); font-size:.7rem; letter-spacing:.1em; text-transform:uppercase;
}
.scroll-cue .stick{width:1px;height:34px;background:linear-gradient(var(--ion-2),transparent);position:relative;overflow:hidden;}
.scroll-cue .stick::after{content:'';position:absolute;top:-100%;left:0;width:100%;height:100%;background:var(--ink);animation:scrollcue 2.2s ease-in-out infinite;}
@keyframes scrollcue{0%{top:-100%;}60%{top:100%;}100%{top:100%;}}

@media (max-width:900px){
  .hero-grid{grid-template-columns:1fr;}
  .hero-visual{order:-1;max-width:340px;margin:0 auto 1rem;}
}
@media (max-width:760px){
  /* a full-viewport-height hero reads as dead space on a phone — bring
     the actual content into view sooner, the way an app screen would.
     Top padding stays close to the original so the floating hero-tag
     chips (positioned relative to .hero-visual) still clear the fixed
     header instead of drifting under it. */
  .hero{min-height:auto; padding:7.8rem 0 var(--sp-5);}
}

/* ==========================================================================
   STATS STRIP
   ========================================================================== */
.stats{display:grid;grid-template-columns:repeat(4,1fr);border:2px solid var(--line);border-radius:var(--radius-l);overflow:hidden;box-shadow:var(--shadow-pop-lg);background:var(--surface);}
.stat{padding:var(--sp-4) var(--sp-3);border-left:2px solid var(--line);}
.stat:first-child{border-left:none;}
.stat .num{font-family:var(--f-display);font-size:clamp(2rem,3.4vw,3.2rem);font-weight:700;}
.stat:nth-child(1) .num{color:var(--ember);}
.stat:nth-child(2) .num{color:var(--ion);}
.stat:nth-child(3) .num{color:var(--mint);}
.stat:nth-child(4) .num{color:var(--pink);}
.stat .label{margin-top:.5rem;color:var(--muted);font-size:.88rem;}
@media (max-width:760px){
  .stats{grid-template-columns:1fr 1fr;}
  .stat:nth-child(3){border-left:none;}
  .stat{border-bottom:2px solid var(--line);}
}

/* ==========================================================================
   SERVICES
   ========================================================================== */
.service-list{border-top:2px solid var(--line);}
.service-row{
  display:grid; grid-template-columns:90px 1.4fr 1fr 140px; align-items:center; gap:2rem;
  padding:2.4rem 0; border-bottom:2px solid var(--line);
  transition:padding-left var(--dur-m) var(--ease-out);
  cursor:pointer;
}
.service-row:hover{padding-left:1rem;background:linear-gradient(90deg,var(--yellow) 0%,transparent 70%);}
.service-row .idx{font-family:var(--f-mono);color:var(--muted);font-size:.85rem;}
.service-row h3{font-size:clamp(1.3rem,2.2vw,1.9rem);font-weight:600;}
.service-row p{color:var(--muted);font-size:.95rem;max-width:46ch;}
.service-row .go{
  justify-self:end; width:44px;height:44px;border-radius:50%;border:2px solid var(--line);
  display:flex;align-items:center;justify-content:center;transition:all var(--dur-m) var(--ease-out);
}
.service-row .go svg{width:16px;height:16px;transition:transform var(--dur-m) var(--ease-out);}
.service-row:hover .go{background:var(--grad-thrust);border-color:transparent;}
.service-row:hover .go svg{transform:rotate(45deg);}
@media (max-width:760px){
  .service-row{grid-template-columns:1fr;gap:.8rem;padding:1.8rem 0;}
  .service-row .go{justify-self:start;}
}

.capability-tags{display:flex;flex-wrap:wrap;gap:.7rem;}
.capability-tags span{
  border:2px solid var(--line); border-radius:100px; padding:.55rem 1.1rem;
  font-size:.85rem; color:var(--ink-dim); font-family:var(--f-mono); background:var(--surface);
  transition:border-color var(--dur-s), color var(--dur-s), background var(--dur-s), transform var(--dur-s);
}
.capability-tags span:hover{background:var(--sky);color:var(--ink);transform:translateY(-2px);}
@media (max-width:600px){
  .capability-tags{gap:.5rem;}
  .capability-tags span{padding:.42rem .75rem; font-size:.72rem; line-height:1.4;}
}

/* process */
.process{position:relative;}
.process-step{
  display:grid;grid-template-columns:100px 1fr;gap:2rem;padding:var(--sp-4) 0;
  border-top:2px solid var(--line);
}
.process-step:last-child{border-bottom:2px solid var(--line);}
.process-step .num{font-family:var(--f-display);font-size:2rem;color:var(--muted-2);}
.process-step h3{font-size:1.4rem;font-weight:500;margin-bottom:.6rem;}
.process-step p{color:var(--muted);max-width:56ch;}
@media (max-width:640px){.process-step{grid-template-columns:1fr;gap:.6rem;}}

/* ---------- service scroll: a pinned, numbered walkthrough of the
   service list, one service in view at a time while the section holds
   the viewport, with a progress ring and a live counter next to it.
   Default markup (no JS, or GSAP missing, or prefers-reduced-motion) is
   just a plain stacked list — identical in spirit to .process-step — so
   the content is fully there and readable either way; JS only adds the
   ".is-enhanced" class and does the pinning once it knows GSAP + Lenis +
   motion are all actually available. ---------- */
.service-scroll{position:relative;}
.service-rail,.service-visual{display:none;}
.service-stage{display:block;}
.service-slide{
  position:static; opacity:1;
  padding:var(--sp-4) 0; border-top:2px solid var(--line);
}
.service-slide:last-child{border-bottom:2px solid var(--line);}
.service-slide-tag{display:block;margin-bottom:1rem;}
.service-slide h3{font-size:clamp(1.6rem,3vw,2.4rem);margin-bottom:.9rem;font-weight:600;}
.service-slide p{color:var(--muted);max-width:52ch;margin-bottom:1.3rem;}
.service-slide-cta{margin-top:.4rem;}

.service-scroll.is-enhanced{padding:0;}
.service-scroll.is-enhanced .service-scroll-grid{
  display:grid; grid-template-columns:130px minmax(0,1fr) minmax(0,1fr); gap:var(--sp-4);
  align-items:center; min-height:100vh; padding:var(--sp-6) 0;
}
.service-scroll.is-enhanced .service-rail{
  display:block; position:relative; width:170px; height:360px;
}
.service-scroll.is-enhanced .service-stage{
  position:relative; min-height:320px;
}
.service-scroll.is-enhanced .service-slide{
  position:absolute; inset:0; opacity:0; pointer-events:none;
  padding:0; border:none;
  transition:opacity .55s var(--ease-out), transform .55s var(--ease-out);
  transform:translateY(14px);
}
.service-scroll.is-enhanced .service-slide.is-active{
  opacity:1; pointer-events:auto; transform:translateY(0);
}
.service-scroll.is-enhanced .service-visual{
  display:block; position:relative; aspect-ratio:1/1; border-radius:var(--radius-l);
  overflow:hidden; border:2px solid #0c0906; box-shadow:var(--shadow-pop-lg);
  background:linear-gradient(155deg, #1c1610 0%, #14100c 100%);
}

/* the ring is deliberately oversized and shifted left so only its right
   arc ever shows inside the rail's own clipped bounds — a "half circle"
   grazing the number wheel, same as the reference. A short bright
   segment on it (not the full stroke) rotates continuously as the
   section scrolls, like a compass needle sweeping past each number as it
   becomes current — the literal "ring and numbers rotating" ask. */
.service-rail-clip{
  position:absolute; top:0; left:0; width:170px; height:170px;
  overflow:hidden; pointer-events:none;
}
.service-rail-ring{
  position:absolute; top:50%; left:-260px; width:430px; height:430px;
  margin-top:-215px;
  transform:rotate(0deg);
  will-change:transform;
}
.service-rail-ring svg{display:block;width:100%;height:100%;}
.service-rail-ring .ring-track{stroke:var(--line-soft);}
.service-rail-ring .ring-progress{stroke:var(--mint); stroke-linecap:round;}

.service-rail-window{
  position:absolute; top:190px; left:0; width:170px; height:170px;
  overflow:hidden;
  -webkit-mask-image:linear-gradient(to bottom, transparent 0%, #000 26%, #000 74%, transparent 100%);
  mask-image:linear-gradient(to bottom, transparent 0%, #000 26%, #000 74%, transparent 100%);
}
.service-rail-list{
  list-style:none; margin:0; padding:0;
  position:relative;
  will-change:transform;
}
.service-rail-list li{
  height:64px; line-height:64px;
  font-family:var(--f-display); font-weight:700; color:var(--muted-2);
  font-size:1.15rem; opacity:.4;
  transition:color .3s ease;
  will-change:transform, opacity, font-size;
}
.service-rail-list li.is-active{color:var(--ink);}

.service-visual-panel{
  position:absolute; inset:0; opacity:0;
  transition:opacity .6s var(--ease-out);
}
.service-visual-panel.is-active{opacity:1;}

/* "glow card" panel illustration: fixed dark spotlight card (same in both
   site themes) holding a neon-outline icon with a soft glow, 2-3 orbiting
   satellite chips, a faint scattered-dot backdrop and a corner sparkle.
   Purely decorative (parent has aria-hidden) and never touched by JS —
   .is-active above is still the only thing effects.js toggles. */
.glow-card{
  position:absolute; inset:0;
  background:
    radial-gradient(120% 130% at 28% 18%, rgba(255,255,255,.05), transparent 55%),
    linear-gradient(160deg, #1c1610 0%, #14100c 100%);
}
.glow-card::before{
  content:''; position:absolute; inset:0;
  background-image:radial-gradient(rgba(255,248,234,.16) 1px, transparent 1.7px);
  background-size:28px 28px;
  background-position:8px 8px;
  -webkit-mask-image:radial-gradient(75% 75% at 50% 50%, #000 45%, transparent 92%);
  mask-image:radial-gradient(75% 75% at 50% 50%, #000 45%, transparent 92%);
}
.service-visual-panel[data-panel="0"] .glow-card{--glow:var(--ember);}
.service-visual-panel[data-panel="1"] .glow-card{--glow:var(--ion);}
.service-visual-panel[data-panel="2"] .glow-card{--glow:var(--mint);}
.service-visual-panel[data-panel="3"] .glow-card{--glow:var(--yellow);}
.service-visual-panel[data-panel="4"] .glow-card{--glow:var(--sky);}
.service-visual-panel[data-panel="5"] .glow-card{--glow:var(--pink);}
.service-visual-panel[data-panel="6"] .glow-card{--glow:var(--ion-2);}

.glow-icon{
  position:absolute; left:50%; top:46%; transform:translate(-50%,-50%);
  width:46%; height:46%;
  color:var(--glow); stroke:var(--glow);
}
.glow-chip{
  position:absolute; width:15%; aspect-ratio:1/1;
  display:flex; align-items:center; justify-content:center;
  border-radius:var(--radius-s);
  background:#241c14;
  border:1.5px solid var(--glow);
  box-shadow:2px 2px 0 rgba(0,0,0,.4);
}
.glow-chip svg{
  width:56%; height:56%;
  color:var(--glow); stroke:var(--glow); fill:none;
}
.glow-sparkle{
  position:absolute; top:9%; right:10%;
  width:8%; height:8%;
  color:#fff8ea; opacity:.85;
  animation:doodle-spin 13s linear infinite reverse;
}

@media (max-width:900px){
  .service-scroll.is-enhanced .service-scroll-grid{grid-template-columns:1fr;min-height:auto;padding:var(--sp-5) 0;}
  .service-scroll.is-enhanced .service-rail{display:none;}
  .service-scroll.is-enhanced .service-stage{min-height:280px;}
  .service-scroll.is-enhanced .service-visual{aspect-ratio:16/10;}
  .glow-icon{width:40%;height:40%;}
  .glow-chip{width:17%;}
  .glow-sparkle{width:10%;height:10%;}
}

/* mobile: the pinned/crossfading rail is skipped entirely (see
   effects.js) and mobile gets a plain, simple scroll of text-only
   service cards - title, copy, tags, CTA. The glow-card illustration
   panels stay out of the mobile layout entirely (not just visually
   hidden - .service-visual is display:none below, per the base rule
   near the top of this file) so there's nothing depending on script
   timing that could ever render on top of a card's own text. */
@media (max-width:760px){
  .service-visual,.service-visual-panel{display:none !important;}
}

/* ==========================================================================
   WORK
   ========================================================================== */

/* work stack: a full-bleed, one-project-at-a-time pinned scroll — each
   panel holds the viewport, then the next one slides up and covers it
   while the outgoing panel tilts and shrinks slightly behind it, like a
   physical card being flipped away. Default state is display:none — the
   filterable grid below it is the real, always-readable page; JS swaps
   the two once it knows the pin can actually run (GSAP + motion both
   available), same contract as every other enhanced section on the site. */
.work-stack{display:none;}
.work-stack.is-enhanced{
  display:block; position:relative; margin-bottom:var(--sp-5);
  border-top:2px solid var(--line); border-bottom:2px solid var(--line);
}
.work-panel{
  position:relative; height:100vh; overflow:hidden;
  background:var(--panel-bg); color:#fff8ea;
  padding:clamp(1.6rem,4vw,3.4rem);
  display:flex; flex-direction:column; justify-content:space-between;
  transform-origin:50% 100%;
  will-change:transform;
}
.work-panel + .work-panel{border-top:2px solid var(--line);}
.work-panel-art{position:absolute;inset:0;z-index:0;}
.work-panel-veil{
  position:absolute;inset:0;z-index:0;
  background:linear-gradient(180deg,rgba(24,20,16,.34) 0%,rgba(24,20,16,0) 20%,rgba(24,20,16,0) 50%,rgba(24,20,16,.5) 76%,rgba(24,20,16,.88) 100%);
}
.work-panel-link{position:absolute;inset:0;z-index:1;}
.work-panel-top{
  position:relative; z-index:0;
  display:flex; justify-content:space-between; align-items:flex-start;
  font-family:var(--f-mono);
  text-shadow:0 1px 10px rgba(0,0,0,.4);
}
.work-panel-tag{
  font-size:.8rem; text-transform:uppercase; letter-spacing:.06em; font-weight:700;
  padding:.5rem 1rem; border:2px solid rgba(255,248,234,.55); border-radius:100px;
  background:rgba(24,20,16,.38); backdrop-filter:blur(6px);
}
.work-panel-index{font-family:var(--f-display);font-size:1.6rem;font-weight:700;opacity:.85;}
.work-panel-body{position:relative;z-index:0;max-width:60ch;text-shadow:0 2px 18px rgba(0,0,0,.5);}
.work-panel-body h3{font-size:clamp(2rem,5vw,4.2rem);font-weight:700;margin-bottom:1rem;line-height:1.02;}
.work-panel-body p{font-size:clamp(1rem,1.6vw,1.25rem);color:rgba(255,248,234,.86);margin-bottom:1.4rem;max-width:46ch;}
.work-panel-cta{
  display:inline-flex; align-items:center; gap:.6rem;
  font-family:var(--f-mono); font-size:.85rem; font-weight:700; text-transform:uppercase; letter-spacing:.04em;
  padding:.8rem 1.4rem; border-radius:100px; background:#fff8ea; color:#18140e;
  box-shadow:0 2px 14px rgba(0,0,0,.35);
}
.work-panel-cta svg{width:15px;height:15px;}
@media (max-width:760px){
  .work-panel{height:auto;min-height:100vh;}
  .work-panel-art,.work-panel-veil{position:absolute;inset:0;}
  .work-panel-body h3{font-size:clamp(1.8rem,8vw,2.6rem);}
}

.work-filters{display:flex;gap:.7rem;flex-wrap:wrap;margin-bottom:var(--sp-4);}
.work-filters button{
  border:2px solid var(--line); border-radius:100px; padding:.6rem 1.2rem; font-size:.85rem;
  color:var(--muted); background:var(--surface); transition:all var(--dur-s);
  box-shadow:3px 3px 0 var(--line);
}
.work-filters button:hover{color:var(--ink);transform:translate(-1px,-1px);box-shadow:4px 4px 0 var(--line);}
.work-filters button.is-active{background:var(--ink);color:var(--void);transform:translate(2px,2px);box-shadow:1px 1px 0 var(--line);}

.work-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-3);}
/* Work cards, redesigned: a real project photo up top (a single framed
   shot, not a busy crossfading slideshow) and the title/tag/description
   live on the card's own surface below it, in plain readable text —
   nothing overlaid on the photo except a small tag chip, so there's no
   dark scrim needed to keep text legible over a bright image. */
.work-card{
  display:flex; flex-direction:column;
  border-radius:var(--radius-m); overflow:hidden;
  border:2px solid var(--line); background:var(--surface);
  box-shadow:var(--shadow-pop-lg);
  transition:transform var(--dur-m) var(--ease-out), box-shadow var(--dur-m) var(--ease-out);
}
.work-card:hover{transform:translate(-3px,-3px);}
.work-card-media{
  position:relative; aspect-ratio:16/10; overflow:hidden;
  border-bottom:2px solid var(--line); background:var(--surface-2);
}
.work-card-media img{
  width:100%; height:100%; object-fit:cover; display:block;
  transition:transform 700ms var(--ease-out);
}
.work-card:hover .work-card-media img{transform:scale(1.05);}
.work-card-chip{
  position:absolute; top:.9rem; left:.9rem;
  font-family:var(--f-mono); font-size:.72rem; font-weight:700;
  text-transform:uppercase; letter-spacing:.06em;
  background:var(--surface); color:var(--ink); border:2px solid var(--line);
  border-radius:100px; padding:.35rem .8rem;
}
.work-card-body{
  padding:1.5rem; display:flex; flex-direction:column; gap:.5rem; flex:1;
}
.work-card-body h3{font-size:1.3rem; font-weight:700;}
.work-card-body p{color:var(--muted); font-size:.94rem; flex:1;}
.work-card-cta{
  display:inline-flex; align-items:center; gap:.5rem;
  font-family:var(--f-mono); font-size:.85rem; font-weight:700;
  color:var(--ink); margin-top:.4rem;
}
.work-card-cta svg{width:14px;height:14px; transition:transform var(--dur-s) var(--ease-out);}
.work-card:hover .work-card-cta svg{transform:translate(2px,-2px);}
/* photo slideshow: a stack of real project screenshots crossfaded with a
   slow Ken Burns zoom. No-JS/no-GSAP baseline is plain CSS — only the
   .is-active slide is visible (opacity:1), everything else sits at
   opacity:0, so a visitor with no JS still gets one complete, correct
   photo. initWorkSlideshows() in main.js layers the cycling + zoom on
   top by toggling .is-active on a timer; it runs independently of GSAP
   so it still works if effects.js/GSAP fails to load. Used inside
   .work-card .art, .work-panel (as .work-panel-art) and .cs-cover. */
.work-slideshow{position:relative;width:100%;height:100%;overflow:hidden;}
/* .work-panel-art and .work-slideshow share specificity (0,1,0), and this
   rule sits after .work-panel-art in the cascade — without this override,
   .work-slideshow's position:relative silently wins and the slideshow
   collapses to a content-sized box instead of filling the pinned panel
   edge-to-edge. .work-card .art already wins on its own (a descendant
   selector beats a single class), so it doesn't need this. */
.work-panel-art.work-slideshow{position:absolute;inset:0;width:100%;height:100%;}
.ws-slide{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center top;
  opacity:0;transform:scale(1);
  transition:opacity 1100ms var(--ease-out), transform 4200ms linear;
  will-change:opacity,transform;
}
.ws-slide.is-active{opacity:1;transform:scale(1.08);}
@media (prefers-reduced-motion:reduce){
  .ws-slide{transition:none !important;transform:none !important;}
}

.work-grid{padding-top:1rem;}
@media (max-width:760px){
  .work-grid{grid-template-columns:1fr;}
}

/* case study */
.cs-hero{padding-top:9rem;}
.cs-meta{display:grid;grid-template-columns:repeat(4,1fr);gap:1.6rem;padding:var(--sp-4) 0;border-top:2px solid var(--line);border-bottom:2px solid var(--line);margin:var(--sp-4) 0;}
.cs-meta div span{display:block;font-family:var(--f-mono);font-size:.72rem;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:.4rem;}
.cs-meta div strong{font-weight:500;font-size:1.02rem;}
.cs-cover{position:relative;border-radius:var(--radius-l);overflow:hidden;border:2px solid var(--line);aspect-ratio:16/9;box-shadow:var(--shadow-pop-lg);}
.cs-cover .work-slideshow{position:absolute;inset:0;}

/* parallax-frame: a fixed, clipped window; the layer inside it is
   oversized and drifts on scroll (via data-depth), so cover art reads
   with real depth instead of scrolling flush with the page. */
.parallax-frame{overflow:hidden;position:relative;}
.parallax-layer{position:absolute;left:0;right:0;top:-16%;height:132%;background-size:cover;background-position:center;}
.cs-body{display:grid;grid-template-columns:0.9fr 1.4fr;gap:var(--sp-5);margin-top:var(--sp-6);}
.cs-body .side{position:sticky;top:8rem;align-self:start;}
.cs-body h2,.cs-body h3{margin-bottom:.8rem;font-size:1.5rem;}
.cs-body p + p{margin-top:1.1rem;}
.cs-body p{color:var(--ink-dim);}
.cs-quote{
  margin:var(--sp-5) 0; padding:var(--sp-4); border-left:2px solid var(--ion-2);
  font-family:var(--f-display); font-size:1.5rem; font-weight:500; line-height:1.3;
}
.cs-results{display:grid;grid-template-columns:repeat(3,1fr);gap:1.4rem;margin-top:var(--sp-4);}
.cs-meta.is-compact{grid-template-columns:repeat(2,1fr);max-width:32rem;}
.cs-note{font-style:normal;}
.cs-note strong{display:block;margin-bottom:.3rem;color:var(--ink);}
@media (max-width:900px){.cs-body{grid-template-columns:1fr;}.cs-meta{grid-template-columns:1fr 1fr;}.cs-results{grid-template-columns:1fr;}}

/* cs-gallery: a browsable grid of smaller stills from the project, below
   the main write-up. Static (no slideshow/lightbox behaviour) — just a
   card grid using the same thick-outline / hard-shadow language as
   .work-card, sized down and without the hover text overlay since there's
   no per-image copy to show. */
.cs-gallery-head{margin-top:var(--sp-6);margin-bottom:var(--sp-3);}
.cs-gallery{
  display:grid; grid-template-columns:repeat(4,1fr); gap:var(--sp-3);
  margin-bottom:var(--sp-6);
}
.cs-gallery-item{
  position:relative; display:block; overflow:hidden;
  border:2px solid var(--line); border-radius:var(--radius-m);
  background:var(--surface); box-shadow:var(--shadow-pop);
  aspect-ratio:4/3.1;
  transition:transform var(--dur-m) var(--ease-out), box-shadow var(--dur-m) var(--ease-out);
}
.cs-gallery-item img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center top;
  transition:transform 700ms var(--ease-out);
}
.cs-gallery-item:hover{transform:translate(-3px,-3px);box-shadow:var(--shadow-pop-lg);}
.cs-gallery-item:hover img{transform:scale(1.06);}
@media (max-width:1080px){.cs-gallery{grid-template-columns:repeat(3,1fr);}}
@media (max-width:760px){.cs-gallery{grid-template-columns:repeat(2,1fr);gap:.8rem;}}
@media (max-width:460px){.cs-gallery{grid-template-columns:1fr;}}

/* ==========================================================================
   REVIEWS
   ========================================================================== */
.review-wall{columns:3 320px;column-gap:var(--sp-3);}
.review-card{
  break-inside:avoid; margin-bottom:var(--sp-3);
  border:2px solid var(--line); border-radius:var(--radius-m); padding:var(--sp-3);
  background:var(--surface); box-shadow:var(--shadow-pop);
  transition:transform var(--dur-m) var(--ease-out), box-shadow var(--dur-m) var(--ease-out);
}
.review-card:hover{transform:translate(-3px,-3px);box-shadow:var(--shadow-pop-lg);}
.review-stars{display:flex;gap:.25rem;margin-bottom:1rem;color:var(--ember);}
.review-stars svg{width:15px;height:15px;}
.review-card p{color:var(--ink-dim);font-size:.98rem;}
.review-person{display:flex;align-items:center;gap:.8rem;margin-top:1.3rem;}
.review-avatar{
  width:40px;height:40px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--f-display);font-weight:600;font-size:.9rem;color:#fff;
  background:var(--grad-thrust);
}
.review-person strong{display:block;font-size:.9rem;font-weight:600;}
.review-person span{font-size:.8rem;color:var(--muted);}

/* auto-sliding review marquee: two rows drifting opposite directions,
   each track is its card set duplicated once so translateX(-50%) loops
   seamlessly forever. Pauses on hover/focus so a visitor can actually
   read one without it sliding out from under them, and falls back to a
   plain wrapped row (no motion at all) under reduced-motion. */
.review-marquee{display:flex;flex-direction:column;gap:var(--sp-3);overflow:hidden;}
.review-marquee-track{
  display:flex; gap:var(--sp-3); width:max-content;
  animation:review-marquee-left 42s linear infinite;
}
.review-marquee-track.dir-right{animation-name:review-marquee-right;animation-duration:38s;}
.review-marquee:hover .review-marquee-track,
.review-marquee-track:focus-within{animation-play-state:paused;}
.review-marquee .review-card{
  width:clamp(280px,32vw,380px); flex:none; margin-bottom:0;
}
@keyframes review-marquee-left{from{transform:translateX(0);}to{transform:translateX(-50%);}}
@keyframes review-marquee-right{from{transform:translateX(-50%);}to{transform:translateX(0);}}
@media (prefers-reduced-motion:reduce){
  .review-marquee{overflow:visible;}
  .review-marquee-track{animation:none !important;flex-wrap:wrap;width:auto;transform:none !important;}
  .review-marquee-track .review-card:nth-child(n+5){display:none;}
}
@media (max-width:760px){.review-wall{columns:1;}}

/* ==========================================================================
   BLOG
   ========================================================================== */
.blog-featured{
  display:grid;grid-template-columns:1.1fr 1fr;gap:var(--sp-4);
  border:2px solid var(--line);border-radius:var(--radius-l);overflow:hidden;margin-bottom:var(--sp-5);
  box-shadow:var(--shadow-pop-lg);
}
.blog-featured .art-frame{position:relative;overflow:hidden;min-height:320px;}
.blog-featured .content{padding:var(--sp-4);display:flex;flex-direction:column;justify-content:center;}
.blog-featured h2{margin:1rem 0 1rem;font-size:clamp(1.6rem,2.6vw,2.3rem);}
.blog-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-3);}
.blog-card{border:2px solid var(--line);border-radius:var(--radius-m);overflow:hidden;background:var(--surface);box-shadow:var(--shadow-pop);transition:transform var(--dur-m),box-shadow var(--dur-m);}
.blog-card:hover{transform:translate(-3px,-9px) rotate(-1deg);box-shadow:var(--shadow-pop-lg);}
.blog-card .art{aspect-ratio:16/10;background-size:cover;background-position:center;}
.blog-card .content{padding:1.5rem;}
.blog-card h3{font-size:1.15rem;font-weight:500;margin:.8rem 0 .6rem;line-height:1.3;}
.blog-card .content p{color:var(--muted);font-size:.9rem;}
.post-meta{display:flex;gap:1rem;align-items:center;font-family:var(--f-mono);font-size:.72rem;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;}
@media (max-width:900px){.blog-featured{grid-template-columns:1fr;}.blog-grid{grid-template-columns:1fr 1fr;}}
@media (max-width:600px){.blog-grid{grid-template-columns:1fr;}}

.post-hero{padding-top:9rem;text-align:center;}
.post-hero .container{max-width:820px;}
.post-cover{position:relative;max-width:960px;margin:var(--sp-4) auto 0;border-radius:var(--radius-l);overflow:hidden;border:2px solid var(--line);aspect-ratio:16/8;box-shadow:var(--shadow-pop-lg);}
.post-body{max-width:720px;margin:var(--sp-5) auto 0;}
.post-body h2{font-size:1.7rem;margin:var(--sp-4) 0 1rem;}
.post-body p{color:var(--ink-dim);margin-bottom:1.2rem;}
.post-body ul{margin:1.2rem 0;padding-left:0;}
.post-body li{color:var(--ink-dim);padding-left:1.6rem;position:relative;margin-bottom:.7rem;}
.post-body li::before{content:'';position:absolute;left:0;top:.55rem;width:7px;height:7px;border-radius:50%;background:var(--grad-thrust);}
.post-share{display:flex;align-items:center;justify-content:space-between;padding-top:var(--sp-4);margin-top:var(--sp-4);border-top:2px solid var(--line);max-width:720px;margin-left:auto;margin-right:auto;}

/* ==========================================================================
   CONTACT
   ========================================================================== */
.contact-grid{display:grid;grid-template-columns:1fr 1.1fr;gap:var(--sp-5);}
.contact-info .item{padding:1.6rem 0;border-top:2px solid var(--line);}
.contact-info .item:last-child{border-bottom:2px solid var(--line);}
.contact-info .item span{display:block;font-family:var(--f-mono);font-size:.72rem;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;margin-bottom:.5rem;}
.contact-info .item a,.contact-info .item p{font-size:1.15rem;font-weight:500;}

.field{margin-bottom:1.4rem;}
.field label{display:block;font-size:.85rem;color:var(--muted);margin-bottom:.55rem;font-weight:500;}
.field input,.field textarea,.field select{
  width:100%; background:var(--surface); border:2px solid var(--line); border-radius:var(--radius-s);
  padding:.95rem 1.1rem; color:var(--ink); transition:border-color var(--dur-s), background var(--dur-s);
}
.field input:focus,.field textarea:focus,.field select:focus{border-color:var(--ion-2);background:var(--surface-2);outline:none;}
.field textarea{min-height:130px;resize:vertical;}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:1.2rem;}
.field-error{color:var(--ember-2);font-size:.8rem;margin-top:.5rem;display:none;}
.field.has-error input,.field.has-error textarea{border-color:var(--ember);}
.field.has-error .field-error{display:block;}
.form-note{font-size:.82rem;color:var(--muted);margin-top:1rem;}
.form-success{
  display:none; text-align:center; padding:3.4rem 1rem;
  border:2px solid var(--line); border-radius:var(--radius-m); background:var(--surface);
}
.form-success.is-visible{display:block;}
.form-success svg{width:52px;height:52px;color:var(--mint);margin:0 auto 1.3rem;}
#contact-form.is-hidden{display:none;}
@media (max-width:900px){.contact-grid{grid-template-columns:1fr;}.field-row{grid-template-columns:1fr;}}

/* honeypot — visually hidden without display:none, so bots that skip
   hidden fields still fill it in and out the submission */
.hp-field{
  position:absolute; left:-9999px; top:auto; width:1px; height:1px;
  overflow:hidden;
}
.form-error-general{
  display:none; color:var(--ember); background:var(--ember-soft);
  border:2px solid var(--ember); border-radius:var(--radius-s);
  padding:.8rem 1rem; font-size:.88rem; margin-top:1rem;
}
#contact-form.has-error-general .form-error-general{display:block;}

/* ==========================================================================
   COOKIE CONSENT BANNER
   Deliberately restrained: a slim, low-contrast bar rather than the site's
   thick-border/hard-shadow "sticker" card — this is a compliance notice,
   not a promo, so it should read as quiet and trustworthy at any width.
   ========================================================================== */
.cookie-banner{
  position:fixed; left:1rem; right:1rem; bottom:1rem; z-index:9800;
  max-width:620px; margin:0 auto;
  display:flex; flex-wrap:wrap; align-items:center; gap:.9rem;
  background:var(--surface); border:1px solid var(--line-soft); border-radius:var(--radius-s);
  box-shadow:0 10px 30px rgba(24,20,16,.16);
  padding:.85rem 1.1rem;
  transform:translateY(140%); opacity:0;
  transition:transform var(--dur-m) var(--ease-out), opacity var(--dur-m) var(--ease-out);
}
.cookie-banner.is-visible{transform:translateY(0); opacity:1;}
.cookie-banner p{flex:1 1 260px; font-size:.82rem; line-height:1.5; color:var(--ink-dim); margin:0;}
.cookie-banner .cookie-actions{display:flex; gap:.5rem; flex:0 0 auto;}
.cookie-banner .btn{padding:.5rem 1rem; font-size:.8rem;}
@media (max-width:560px){
  .cookie-banner{
    left:.6rem; right:.6rem; bottom:.6rem;
    padding:.75rem .85rem calc(.75rem + env(safe-area-inset-bottom,0px));
    gap:.55rem;
  }
  .cookie-banner p{font-size:.76rem; line-height:1.42; flex-basis:100%;}
  .cookie-banner .cookie-actions{width:100%;}
  .cookie-banner .cookie-actions .btn{flex:1; padding:.55rem .7rem; font-size:.78rem; min-height:38px;}
}

/* ==========================================================================
   LEGAL / 404
   ========================================================================== */
.legal{padding-top:9rem;}
.legal .container{max-width:800px;}
.legal h2{font-size:1.5rem;margin:var(--sp-4) 0 1rem;}
.legal p,.legal li{color:var(--ink-dim);margin-bottom:1rem;}
.legal ul{padding-left:1.4rem;list-style:disc;}
.legal .updated{color:var(--muted);font-size:.85rem;margin-bottom:var(--sp-4);}

.error-page{
  min-height:100svh; display:flex; flex-direction:column; align-items:center; justify-content:center;
  text-align:center; padding:8rem 1.5rem 4rem;
}
.error-code{
  font-family:var(--f-display); font-weight:700;
  font-size:clamp(6rem,22vw,13rem); line-height:.85;
  background:var(--grad-thrust); -webkit-background-clip:text;background-clip:text;color:transparent;
}
.error-ship{width:120px;margin:1rem auto 2rem;animation:float 5s ease-in-out infinite;}
.error-ship img{width:100%;border-radius:26%;box-shadow:var(--shadow-pop-lg);}
.error-page h1{font-size:clamp(1.6rem,3vw,2.4rem);margin-bottom:1rem;}
.error-page p{color:var(--muted);max-width:44ch;margin-bottom:2.2rem;}

/* ==========================================================================
   ABOUT
   ========================================================================== */
.value-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-3);}
.value-card{background:var(--surface);}
.value-card .num{font-family:var(--f-mono);color:var(--ember);font-weight:700;font-size:.85rem;margin-bottom:1.2rem;display:block;}
.value-card:nth-child(2) .num{color:var(--ion);}
.value-card:nth-child(3) .num{color:var(--mint);}
.value-card:nth-child(4) .num{color:var(--pink);}
.value-card h3{font-size:1.2rem;font-weight:700;margin-bottom:.7rem;}
.value-card p{color:var(--muted);font-size:.92rem;}
@media (max-width:900px){.value-grid{grid-template-columns:1fr 1fr;}}
@media (max-width:560px){.value-grid{grid-template-columns:1fr;}}

/* ==========================================================================
   FAQ LIST — a flat, divided single-column list with a plus/minus toggle
   (used on index.html "Questions" and contact.html "A few things people
   ask"), in place of FAQs boxed up as grid cards.
   ========================================================================== */
.faq-list{display:flex; flex-direction:column; max-width:840px;}
.faq-item{border-top:2px solid var(--line);}
.faq-item:last-child{border-bottom:2px solid var(--line);}
.faq-item summary{
  display:flex; align-items:center; justify-content:space-between; gap:1.5rem;
  min-height:44px; padding:1.5rem 0; cursor:pointer; list-style:none;
  font-family:var(--f-display); font-size:1.12rem; font-weight:700; color:var(--ink);
  transition:color var(--dur-s);
}
.faq-item summary::-webkit-details-marker{display:none;}
.faq-item summary:hover{color:var(--ember);}
.faq-item summary:hover .faq-toggle{border-color:var(--ember);}
.faq-toggle{
  position:relative; flex:none; width:30px; height:30px; border-radius:50%;
  border:2px solid var(--line); color:var(--ink);
  transition:background var(--dur-s), border-color var(--dur-s), color var(--dur-s), transform var(--dur-m) var(--ease-out);
}
.faq-toggle::before,.faq-toggle::after{
  content:''; position:absolute; top:50%; left:50%; background:currentColor;
  transform:translate(-50%,-50%); transition:transform var(--dur-s) var(--ease-out), opacity var(--dur-s);
}
.faq-toggle::before{width:12px;height:2px;}
.faq-toggle::after{width:2px;height:12px;}
.faq-item[open] summary{color:var(--ink);}
.faq-item[open] .faq-toggle{background:var(--ink); color:var(--void); border-color:var(--ink); transform:rotate(135deg);}
.faq-item[open] .faq-toggle::after{opacity:0;}
/* the answer's height is driven by JS (initFaqAccordion) so open/close both
   glide instead of the native instant jump; overflow-hidden clips it while
   it slides, and opacity gives the copy a soft fade on top of the slide.
   Without JS the native <details> still opens/closes, just instantly. */
.faq-answer{padding:0 0 1.7rem; max-width:66ch; overflow:hidden; transition:height var(--dur-m) var(--ease-out), opacity var(--dur-m) var(--ease-out);}
.faq-answer p{color:var(--muted); font-size:.96rem; line-height:1.65; margin:0;}
@media (max-width:480px){
  .faq-item summary{font-size:1rem; padding:1.25rem 0; gap:1rem;}
  .faq-toggle{width:26px;height:26px;}
}

.timeline{position:relative;padding-left:2.4rem;border-left:2px solid var(--line);}
.tl-item{position:relative;padding-bottom:var(--sp-4);}
.tl-item:last-child{padding-bottom:0;}
.tl-item::before{content:'';position:absolute;left:-2.6rem;top:.35rem;width:12px;height:12px;border-radius:50%;background:var(--grad-thrust);border:2px solid var(--line);box-shadow:0 0 0 4px var(--void);}
.tl-item .yr{font-family:var(--f-mono);color:var(--ember);font-weight:700;font-size:.85rem;margin-bottom:.5rem;display:block;}
.tl-item h3{font-size:1.25rem;font-weight:700;margin-bottom:.5rem;}
.tl-item p{color:var(--muted);max-width:56ch;}

.team-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--sp-3);}
.team-card{border-radius:var(--radius-m);overflow:hidden;border:2px solid var(--line);background:var(--surface);box-shadow:var(--shadow-pop);transition:transform var(--dur-m) var(--ease-out),box-shadow var(--dur-m) var(--ease-out);}
.team-card:hover{transform:translate(-3px,-3px);box-shadow:var(--shadow-pop-lg);}
.team-card .photo{aspect-ratio:3/3.6;background-size:cover;background-position:center;position:relative;}
.team-card .photo::after{content:'';position:absolute;inset:0;background:linear-gradient(180deg,transparent 60%,rgba(24,20,16,.35));}
.team-card .info{padding:1.2rem;}
.team-card h3{font-size:1.05rem;font-weight:500;}
.team-card span{color:var(--muted);font-size:.82rem;}
@media (max-width:900px){.team-grid{grid-template-columns:1fr 1fr;}}
@media (max-width:560px){.team-grid{grid-template-columns:1fr 1fr;}}

/* CTA band */
.cta-band{
  position:relative; border-radius:var(--radius-l); overflow:hidden;
  padding:var(--sp-6) var(--sp-4); text-align:center;
  background:var(--surface-2); border:2px solid var(--line);
  box-shadow:var(--shadow-pop-lg);
  isolation:isolate;
}
.cta-band::before{
  content:''; position:absolute; inset:-40%; z-index:-1;
  background:radial-gradient(circle at 50% 40%,var(--ember-soft),transparent 60%);
  animation:pulse 8s ease-in-out infinite;
}
@keyframes pulse{0%,100%{opacity:.6;transform:scale(1);}50%{opacity:1;transform:scale(1.08);}}
.cta-band h2{max-width:20ch;margin:0 auto 1.4rem;}
.cta-band .btn-primary{margin-top:.6rem;}

/* ==========================================================================
   SCROLL SHOWCASE — GSAP-driven effects (see assets/js/effects.js)
   Word-mask text reveal, mountain parallax, horizontal capability strip,
   card stack, orbit badge (spiral rotation), gravity-drop chips, the
   stretching footer curtain, and the cross-section hero handoff.
   ========================================================================== */

/* text reveal: each word rides in its own overflow-hidden mask */
.word-mask{display:inline-block;overflow:hidden;vertical-align:top;padding-bottom:.08em;margin-bottom:-.08em;}
.word-inner{display:inline-block;will-change:transform;}

/* mountain parallax, sits behind the hero content */
.mountains{position:absolute;left:0;right:0;bottom:0;height:60%;z-index:0;overflow:hidden;pointer-events:none;}
.mountains svg{position:absolute;bottom:0;left:50%;width:140%;min-width:1400px;transform:translateX(-50%);}
.mountains .m-back{opacity:.5;}
.mountains .m-mid{opacity:.7;}
.mountains .m-front{opacity:.95;}

/* horizontal capability strip */
.hscroll{overflow:hidden;position:relative;z-index:1;}
.hscroll-track{display:flex;gap:var(--sp-3);width:max-content;padding:0 var(--sp-3);}
.hscroll-card{
  width:min(72vw,340px); flex-shrink:0;
  background:var(--surface); border:2px solid var(--line); border-radius:var(--radius-l);
  padding:var(--sp-4); box-shadow:var(--shadow-pop);
  display:flex; flex-direction:column; gap:1rem;
}
.hscroll-card .n{font-family:var(--f-mono);font-size:.75rem;color:var(--muted);}
.hscroll-card h3{font-size:1.5rem;}
.hscroll-card p{color:var(--muted);font-size:.92rem;}
.hscroll-card .chip{
  align-self:flex-start; font-family:var(--f-mono); font-size:.72rem; text-transform:uppercase;
  padding:.4rem .8rem; border-radius:100px; border:2px solid var(--line); background:var(--yellow);
  color:var(--ink-on-accent);
}
.hscroll-card:nth-child(2) .chip{background:var(--sky);}
.hscroll-card:nth-child(3) .chip{background:var(--pink);}
.hscroll-card:nth-child(4) .chip{background:var(--mint);}
.hscroll-card:nth-child(5) .chip{background:var(--ion-2);}
.hscroll-card:nth-child(6) .chip{background:var(--yellow);}
.hscroll-card:nth-child(7) .chip{background:var(--sky);}
.hscroll-card:nth-child(8) .chip{background:var(--pink);}
/* mobile fallback: wrap the (now 8-card) Orbit Growth Cycle strip into
   a plain stacked column instead of a horizontal scroller, so
   375-428px screens don't have to swipe through eight cards one at a time. */
@media (max-width:640px){
  .hscroll{overflow:visible;}
  .hscroll-track{flex-wrap:wrap;width:auto;padding:0;gap:1rem;}
  .hscroll-card{width:100%;}
}

/* card stack */
.stack-wrap{position:relative;}
.stack-card{
  position:relative;
  background:var(--surface); border:2px solid var(--line); border-radius:var(--radius-l);
  box-shadow:var(--shadow-pop-lg);
  padding:var(--sp-4); margin-bottom:1.4rem;
  transform-origin:top center;
}

/* cross-section hero handoff spacer */
.hero-pin-spacer{position:relative;z-index:1;}

/* ---------- decorative doodles: the hero's mountains/orbit/chips language,
   repeated across every other page and section with different shapes each
   time so the site feels hand-placed rather than templated. Purely
   ornamental (aria-hidden, pointer-events:none) and hidden on small
   screens to keep mobile layouts clean. ---------- */
.has-doodles{position:relative;overflow:hidden;}
.doodle-field{position:absolute;inset:0;z-index:0;pointer-events:none;}
.doodle{position:absolute;display:block;}
.doodle svg{display:block;width:100%;height:100%;}

.doodle-ring{width:40px;height:40px;border:2px solid var(--line);border-radius:50%;animation:doodle-float 6.4s ease-in-out infinite;}
.doodle-ring.is-sm{width:22px;height:22px;}

.doodle-dot{width:11px;height:11px;border-radius:50%;background:var(--mint);animation:doodle-float 5.2s ease-in-out infinite;}
.doodle-dot.is-pink{background:var(--pink);}
.doodle-dot.is-sky{background:var(--sky);}
.doodle-dot.is-yellow{background:var(--yellow);}
.doodle-dot.is-lg{width:16px;height:16px;}

.doodle-plus{width:22px;height:22px;color:var(--sky);animation:doodle-drift 7.6s ease-in-out infinite;}
.doodle-spark{width:26px;height:26px;color:var(--ember);animation:doodle-spin 10s linear infinite;}
.doodle-star{width:20px;height:20px;color:var(--pink);animation:doodle-spin 13s linear infinite reverse;}
.doodle-squiggle{width:60px;height:22px;color:var(--line);animation:doodle-drift 8.4s ease-in-out infinite;}
.doodle-arrow{width:44px;height:44px;color:var(--ink-dim);opacity:.7;animation:doodle-float 6.8s ease-in-out infinite;}
.doodle-zigzag{width:56px;height:20px;color:var(--line);animation:doodle-drift 7.2s ease-in-out infinite;}

@keyframes doodle-spin{from{transform:rotate(0deg);}to{transform:rotate(360deg);}}
@keyframes doodle-float{0%,100%{transform:translateY(0);}50%{transform:translateY(-14px);}}
@keyframes doodle-drift{0%,100%{transform:translateY(0) rotate(0deg);}50%{transform:translateY(-9px) rotate(-7deg);}}

@media (max-width:760px){
  .doodle-field{display:none;}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:0.001ms !important;animation-iteration-count:1 !important;transition-duration:0.001ms !important;scroll-behavior:auto !important;}
  [data-reveal],[data-reveal-scale],[data-stagger] > *,.reveal-up,.reveal-fade,.reveal-pop,.reveal-turn,.reveal-left,.reveal-right,
  .hero h1 .line span,.hero-kicker,.hero-lead,.hero-actions,.hero-note,.hero-visual{opacity:1 !important;transform:none !important;}
  .word-inner{transform:none !important;}
  .faq-answer{transition:none !important;}
  .hscroll-track{flex-wrap:wrap;width:auto;}
}

/* ==========================================================================
   FLOATING WIDGETS: WhatsApp button + Aditsy Assistant chatbot
   Plain HTML/CSS/vanilla-JS, deliberately independent of the GSAP/effects
   progressive-enhancement system — these must work even if that fails.
   ========================================================================== */
.fab-stack{
  position:fixed; right:1.4rem; bottom:1.4rem; z-index:9500;
  display:flex; flex-direction:column; align-items:flex-end; gap:.8rem;
  pointer-events:none;
}
.fab-stack > *{pointer-events:auto;}

.fab-whatsapp{
  display:flex; align-items:center; gap:.6rem;
  width:52px; height:52px; padding:0; border-radius:50%;
  background:var(--grad-thrust); border:2px solid var(--line); color:#fff;
  box-shadow:var(--shadow-pop); cursor:pointer;
  transition:transform var(--dur-s) var(--ease-out), box-shadow var(--dur-s) var(--ease-out), width var(--dur-m) var(--ease-out), border-radius var(--dur-m) var(--ease-out), padding var(--dur-m) var(--ease-out);
  overflow:hidden; white-space:nowrap;
  text-decoration:none;
}
.fab-whatsapp:hover{transform:translate(-2px,-2px); box-shadow:var(--shadow-pop-lg);}
.fab-whatsapp svg{width:26px;height:26px;flex:none;margin:0 13px;}
.fab-whatsapp .fab-label{
  font-family:var(--f-mono); font-size:.82rem; font-weight:700;
  max-width:0; overflow:hidden; opacity:0;
  transition:max-width var(--dur-m) var(--ease-out), opacity var(--dur-s) var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .fab-whatsapp:hover{width:auto; border-radius:100px; padding-right:1.1rem;}
  .fab-whatsapp:hover .fab-label{max-width:140px; opacity:1;}
  .fab-whatsapp:hover svg{margin-left:13px;margin-right:.1rem;}
}

.fab-chat-toggle{
  width:58px; height:58px; border-radius:50%;
  background:var(--ink); color:var(--void); border:2px solid var(--line);
  box-shadow:var(--shadow-pop); cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  transition:transform var(--dur-s) var(--ease-out), box-shadow var(--dur-s) var(--ease-out), background var(--dur-s);
  position:relative;
}
.fab-chat-toggle:hover{transform:translate(-2px,-2px); box-shadow:var(--shadow-pop-lg); background:var(--ember);}
.fab-chat-toggle svg{width:26px;height:26px;}
.fab-chat-toggle .fab-icon-close{display:none;}
.fab-chat-toggle[aria-expanded="true"] .fab-icon-open{display:none;}
.fab-chat-toggle[aria-expanded="true"] .fab-icon-close{display:block;}
.fab-chat-dot{
  position:absolute; top:2px; right:2px; width:12px; height:12px; border-radius:50%;
  background:var(--ember); border:2px solid var(--void);
}

.fab-chat-panel{
  position:fixed; right:1.4rem; bottom:5.6rem; z-index:9600;
  width:min(360px,calc(100vw - 2rem)); max-height:min(560px,calc(100vh - 7.5rem));
  background:var(--surface); border:2px solid var(--line); border-radius:var(--radius-l);
  box-shadow:var(--shadow-pop-lg);
  display:flex; flex-direction:column; overflow:hidden;
  transform:translateY(16px) scale(.97); opacity:0; pointer-events:none;
  transition:transform var(--dur-m) var(--ease-out), opacity var(--dur-s) var(--ease-out);
}
.fab-chat-panel.is-open{transform:translateY(0) scale(1); opacity:1; pointer-events:auto;}

.fab-chat-header{
  display:flex; align-items:center; justify-content:space-between; gap:.6rem;
  padding:1rem 1.2rem; background:var(--ink); color:var(--void); flex:none;
}
.fab-chat-header-info{display:flex; align-items:center; gap:.6rem;}
.fab-chat-header h2{font-size:1rem; font-weight:700; font-family:var(--f-display); margin:0;}
.fab-chat-header p{font-size:.75rem; opacity:.75; margin:0; font-family:var(--f-mono);}
.fab-chat-status{width:9px;height:9px;border-radius:50%;background:#33c98e;flex:none;}
.fab-chat-close{
  background:none; border:none; color:inherit; cursor:pointer;
  width:32px; height:32px; display:flex; align-items:center; justify-content:center;
  border-radius:50%; transition:background var(--dur-s);
}
.fab-chat-close:hover{background:rgba(255,255,255,.15);}
.fab-chat-close svg{width:18px;height:18px;}

.fab-chat-body{
  flex:1 1 auto; overflow-y:auto; padding:1rem 1.1rem;
  display:flex; flex-direction:column; gap:.7rem;
  background:var(--void);
}
.fab-chat-msg{
  max-width:86%; padding:.65rem .9rem; border-radius:var(--radius-m);
  font-size:.88rem; line-height:1.45; border:2px solid var(--line);
}
.fab-chat-msg.is-bot{
  align-self:flex-start; background:var(--surface); border-bottom-left-radius:4px;
}
.fab-chat-msg.is-user{
  align-self:flex-end; background:var(--ember); color:#fff; border-color:var(--ember); border-bottom-right-radius:4px;
}
.fab-chat-chips{display:flex; flex-wrap:wrap; gap:.5rem; margin-top:.2rem;}
.fab-chat-chip{
  font-family:var(--f-mono); font-size:.74rem; text-align:left;
  border:2px solid var(--line); background:var(--surface); border-radius:100px;
  padding:.5rem .9rem; cursor:pointer; transition:all var(--dur-s);
}
.fab-chat-chip:hover{background:var(--yellow); transform:translateY(-1px);}

.fab-chat-form{
  display:flex; gap:.5rem; padding:.8rem; border-top:2px solid var(--line);
  background:var(--surface); flex:none;
}
.fab-chat-input{
  flex:1 1 auto; border:2px solid var(--line); border-radius:100px;
  padding:.7rem 1.1rem; font-size:.88rem; font-family:var(--f-body);
  background:var(--void); color:var(--ink); min-height:44px;
}
.fab-chat-input:focus{outline:2px solid var(--ember); outline-offset:1px;}
.fab-chat-send{
  width:44px; height:44px; border-radius:50%; flex:none;
  background:var(--ink); color:var(--void); border:2px solid var(--line);
  display:flex; align-items:center; justify-content:center; cursor:pointer;
  transition:background var(--dur-s), transform var(--dur-s);
}
.fab-chat-send:hover{background:var(--ember);}
.fab-chat-send svg{width:18px;height:18px;}

@media (max-width:560px){
  /* Smaller footprint + its own contrast dock so the stack reads as a
     floating control rather than merging with whatever card/photo is
     scrolled underneath it (it sits over the bottom-right corner of
     full-width mobile cards, which also carry their own corner button). */
  .fab-stack{
    right:.8rem; bottom:.8rem; gap:.55rem;
    padding:.5rem; border-radius:100px;
    background:color-mix(in srgb, var(--void) 80%, transparent);
    border:1px solid var(--line-soft);
    box-shadow:0 8px 24px rgba(24,20,16,.2);
    backdrop-filter:blur(10px) saturate(140%);
    -webkit-backdrop-filter:blur(10px) saturate(140%);
  }
  .fab-whatsapp{width:44px; height:44px;}
  .fab-whatsapp svg{width:22px; height:22px; margin:0 11px;}
  .fab-chat-toggle{width:46px; height:46px;}
  .fab-chat-toggle svg{width:22px; height:22px;}
  .fab-chat-dot{width:10px; height:10px;}
  .fab-chat-panel{
    right:.5rem; left:.5rem; bottom:.5rem;
    width:auto; max-height:82vh; border-radius:var(--radius-l);
  }
}

/* ==========================================================================
   MOBILE APP SHELL — bottom tab bar (mobile only)
   Gives small screens a native-app-style shell: a fixed bottom bar owning
   the primary destinations + menu, instead of one hamburger tucked in the
   corner. The top header drops to a plain logo strip once this takes over.
   ========================================================================== */
.mobile-tabbar{display:none;}
@media (max-width:760px){
  :root{--tabbar-h:62px;}

  .mobile-tabbar{
    display:flex; position:fixed; left:0; right:0; bottom:0; z-index:9700;
    height:var(--tabbar-h);
    padding-bottom:env(safe-area-inset-bottom,0px);
    background:color-mix(in srgb, var(--surface) 94%, transparent);
    border-top:2px solid var(--line);
    backdrop-filter:blur(16px) saturate(140%);
    -webkit-backdrop-filter:blur(16px) saturate(140%);
    box-shadow:0 -6px 22px rgba(24,20,16,.1);
  }
  .mobile-tab{
    flex:1 1 0; min-width:44px; min-height:44px;
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:.22rem;
    color:var(--ink-dim); text-decoration:none; cursor:pointer; background:none; border:none;
    font-family:var(--f-mono); font-size:.6rem; font-weight:700; letter-spacing:.02em; text-transform:uppercase;
    transition:color var(--dur-s);
    -webkit-tap-highlight-color:transparent;
  }
  .mobile-tab svg{width:21px;height:21px;stroke-width:2px;transition:transform var(--dur-s) var(--ease-out);}
  .mobile-tab.is-active{color:var(--ember);}
  .mobile-tab.is-active svg{transform:translateY(-1px);}
  .mobile-tab:active svg{transform:scale(.86);}
  body:has(.nav-toggle-check:checked) .mobile-tab-menu{color:var(--ember);}

  /* the tab bar now owns primary nav + the contact CTA, so the top
     header can shrink to a plain logo strip */
  .nav-cta{display:none;}

  /* keep every other fixed-position widget clear of the new bar instead
     of letting it bury them */
  .fab-stack{bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom,0px) + .65rem);}
  .to-top{bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom,0px) + .65rem); right:1rem; width:44px; height:44px;}
  .cookie-banner{bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom,0px) + .6rem);}
  .fab-chat-panel{bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom,0px) + 4.3rem);}

  /* room at the very end of the page so the footer never sits under the bar */
  .site-footer{padding-bottom:calc(var(--sp-3) + var(--tabbar-h) + env(safe-area-inset-bottom,0px));}
}
@media (min-width:761px){
  .mobile-tabbar{display:none !important;}
}

