/* ============================================================
   JOSEQUAL — Motion & depth layer  (loads AFTER styles.css)
   Senior-grade, restrained motion: a living WebGL gradient hero,
   3D perspective scroll-entrances, depth-tilt cards, magnetic
   buttons, an infinite logo marquee. Fully reversible —
   delete motion.css + motion.js + hero3d.js and their tags.
   ============================================================ */

:root {
  --ease-spring: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-soft:   cubic-bezier(0.33, 1, 0.68, 1);
}

/* ============================================================
   1 · 3D PERSPECTIVE SCROLL-ENTRANCES (the "alive" feel)
   Redefine the base reveal so everything rises in with depth.
   Higher/equal specificity + later load beats styles.css.
   ============================================================ */
.reveal {
  opacity: 0;
  transform: perspective(1400px) translateY(46px) rotateX(9deg);
  transform-origin: 50% 100%;
  transition: opacity .9s var(--ease-spring), transform 1s var(--ease-spring);
  will-change: opacity, transform;
}
.reveal.in {
  opacity: 1;
  transform: perspective(1400px) translateY(0) rotateX(0deg);
}

/* ============================================================
   3 · SCROLL PROGRESS BAR (subtle, professional)
   ============================================================ */
.scroll-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px;
  z-index: 300; transform-origin: 0 50%; transform: scaleX(0);
  background: linear-gradient(90deg, var(--blue), var(--blue-bright) 55%, #8f6bff);
  box-shadow: 0 0 12px var(--blue-glow); pointer-events: none;
}

/* ============================================================
   4 · LOGO MARQUEE (infinite, edge-faded)
   ============================================================ */
.logos .row.is-marquee {
  display:block; grid-template-columns:none; overflow:hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee-viewport { display:flex; width:max-content; }
.marquee-track {
  display:flex; align-items:center; gap: clamp(34px, 5vw, 72px);
  padding-inline-end: clamp(34px, 5vw, 72px);
  animation: marquee 38s linear infinite;
}
.logos .row.is-marquee:hover .marquee-track { animation-play-state: paused; }
.marquee-track .client-logo {
  flex: none;
  width: auto;
  max-width: clamp(96px, 12vw, 150px);
  height: clamp(32px, 4vw, 40px);
  object-fit: contain;
  object-position: center;
  background: transparent;
  opacity: 0.88;
  transition: opacity .35s ease, transform .35s var(--ease-spring);
}
.logos.theme-light .marquee-track .client-logo {
  mix-blend-mode: multiply;
}
.marquee-track .client-logo:hover {
  opacity: 1;
  transform: translateY(-2px);
}
@keyframes marquee { to { transform: translateX(-50%); } }

/* ============================================================
   5 · SERVICE CARDS — 3D tilt + glare + depth pop
   ============================================================ */
.svc[data-tilt] { transform-style: preserve-3d; }
/* Beat styles.css `.reveal.in { transform:none }` AND my own base
   reveal: tilt transform must win once the card is in view. */
.svc.reveal.in[data-tilt],
.svc[data-tilt]:hover {
  opacity: 1;
  transform: perspective(1000px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg)) translateY(var(--ty,0)) translateZ(0);
  transition: transform .25s var(--ease-soft), border-color .4s, box-shadow .5s;
}
.svc[data-tilt]:hover { --ty: -8px; }
.svc .ico, .svc h3, .svc .desc, .svc .num, .svc .link { transform: translateZ(30px); }
.svc .ico { transition: transform .4s var(--ease-spring), background .3s; }
.svc[data-tilt]:hover .ico { transform: translateZ(48px) scale(1.06); }
.svc__glare {
  position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  background: radial-gradient(240px circle at var(--mx,50%) var(--my,50%), rgba(255,255,255,.16), transparent 60%);
  opacity:0; transition: opacity .4s; z-index:3;
}
.svc[data-tilt]:hover .svc__glare { opacity:1; }

/* ============================================================
   6 · WORK CARDS — image zoom + light sweep
   ============================================================ */
.work image-slot, .work .shot { transition: transform .7s var(--ease-spring); }
.work:hover .shot { transform: scale(1.06); }
.work::after {
  content:""; position:absolute; inset:0; z-index:2; pointer-events:none;
  background: linear-gradient(115deg, transparent 30%, rgba(255,255,255,.14) 50%, transparent 70%);
  transform: translateX(-120%); transition: transform .8s var(--ease-soft);
}
.work:hover::after { transform: translateX(120%); }

/* ============================================================
   7 · MAGNETIC BUTTONS + light sweep
   ============================================================ */
.btn { position: relative; overflow: hidden; will-change: transform; }
.btn-primary::after {
  content:""; position:absolute; top:0; left:-75%; width:50%; height:100%;
  background: linear-gradient(115deg, transparent, rgba(255,255,255,.35), transparent);
  transform: skewX(-18deg); transition: left .6s var(--ease-soft); pointer-events:none;
}
.btn-primary:hover::after { left: 130%; }

/* ============================================================
   8 · PROCESS — step circles light up
   ============================================================ */
.proc .pn { display:inline-flex; align-items:center; justify-content:center;
  width:34px; height:34px; border-radius:50%;
  border:1px solid rgba(90,141,255,.4); transition: background .4s, color .4s, transform .4s; }
.proc:hover .pn { background: var(--blue); color:#fff; transform: scale(1.08); }

/* ============================================================
   9 · HERO POLISH — cinematic motion over the photo
   ============================================================ */
/* The two ambient glows (g1, g2) are relocated by motion.js INTO .heroC —
   .heroC is a z-index:2 stacking context (it has class .hero-variant), so the
   photo + text live above .hero-bg. Placed after the photo but before the text,
   the cards layer correctly: above the photo, behind the headline.
   g1 = ui-dashboard, g2 = work-store. */
.hero-shot {
  position: absolute;
  z-index: 1;                 /* photo is z0 inside .heroC; headline text is z1 (later in DOM) so it stays on top */
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
  filter: none;
  opacity: 1;
  border-radius: 16px;
  border: 1px solid rgba(150, 180, 255, 0.18);
  box-shadow: 0 30px 60px -28px rgba(0, 0, 0, 0.7); /* clean drop shadow, no glow halo */
  overflow: hidden;
  pointer-events: none;
  will-change: transform;
}
/* g1 sits where the original glow g1 was — top-right corner */
.hero-shot.g1 {
  width: clamp(280px, 31vw, 460px); height: auto; aspect-ratio: 16 / 10;
  top: 4%; right: 0; left: auto; bottom: auto;
  background-image: url("assets/ui-dashboard.png");
  animation: heroFloatA 13s var(--ease-soft) infinite alternate;
}
/* g2 sits where the original glow g2 was — bottom-left corner */
.hero-shot.g2 {
  width: clamp(210px, 24vw, 350px); height: auto; aspect-ratio: 16 / 11;
  bottom: 4%; left: 0; right: auto; top: auto;
  background-image: url("assets/work-store.png");
  animation: heroFloatB 16s var(--ease-soft) infinite alternate;
}
/* On narrow screens the headline reflows tall; shrink/tuck the cards. */
@media (max-width: 980px) {
  .hero-shot.g1 { width: 220px; top: 1%; right: 0; }
  .hero-shot.g2 { width: 184px; bottom: 2%; left: 0; }
}
@media (max-width: 640px) {
  .hero-shot { display: none; }
}
@keyframes heroFloatA { from { transform: translate(0,0) rotate(0deg); } to { transform: translate(-22px, 26px) rotate(-1.2deg); } }
@keyframes heroFloatB { from { transform: translate(0,0) rotate(0deg); } to { transform: translate(26px, -22px) rotate(1.4deg); } }

/* Kinetic headline — words rise out of a mask, staggered */
.heroC h1.reveal { opacity: 1; transform: none; } /* words carry the motion */
.h-word { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: .12em; margin-bottom: -.12em; font-size: 0.93em; }
.h-word-in {
  display: inline-block;
  transform: translateY(110%) rotate(3deg); opacity: 0;
  transition: transform .95s var(--ease-spring), opacity .95s var(--ease-spring);
}
.heroC h1.in .h-word-in { transform: translateY(0) rotate(0); opacity: 1; }

/* Idle shimmer/glow on the hero's primary CTA */
.heroC .hero-actions .btn-primary { animation: ctaGlow 3.6s ease-in-out infinite; }
.heroC .hero-actions .btn-primary:hover { animation: none; }
@keyframes ctaGlow {
  0%, 100% { box-shadow: 0 10px 30px -10px var(--blue-glow), inset 0 1px 0 rgba(255,255,255,.25); }
  50%      { box-shadow: 0 16px 44px -8px var(--blue-glow), 0 0 0 4px rgba(47,107,255,.12), inset 0 1px 0 rgba(255,255,255,.3); }
}

/* ============================================================
   9b · HERO — Atmospheric background & elevated typography
   ============================================================ */

/* Multi-layer atmospheric background: electric-blue bloom on the left
   (where the headline lives), a violet mist upper-right, a deep indigo
   pool at the base. Replaces the flat navy-950 with something that
   feels lit from within. */
.hero {
  /* Full-viewport height — content centered vertically so the entire
     hero fills the screen on first load across all device sizes.
     100svh = Small Viewport Height (accounts for mobile browser chrome). */
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: center;
  /* Reduce padding-top to just clear the fixed nav (~80px) instead of
     the default clamp(140px,18vh,220px) — flexbox handles centering. */
  padding-top: clamp(88px, 11vh, 120px);
  padding-bottom: clamp(44px, 6vh, 80px);
  background:
    radial-gradient(ellipse 75% 55% at 10% 58%, rgba(28, 60, 215, 0.36) 0%, transparent 62%),
    radial-gradient(ellipse 52% 46% at 90% 6%,  rgba(96, 28, 220, 0.22) 0%, transparent 56%),
    radial-gradient(ellipse 58% 42% at 55% 102%, rgba(8, 18, 88, 0.60) 0%, transparent 54%),
    linear-gradient(152deg, #060f2c 0%, #06071e 48%, #040516 100%);
}

/* Animated WAVE gradient — a slow, flowing band of brand color that drifts
   across the dark base. Two oversized linear gradients animate their
   background-position at different speeds, so the colors never repeat and
   read like a gentle wave. Sits above the dark base, behind the grid/glows
   and the headline. Brand palette only: #5ba6ff → #9168ff → #c47cff.
   Tune intensity with --wave-opacity and speed with the animation times. */
.hero { --wave-opacity: .32; }
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: var(--wave-opacity);
  mix-blend-mode: screen;          /* lets the wave glow over the navy base */
  background:
    linear-gradient(120deg,
      transparent 0%,
      rgba(91, 166, 255, 0.55) 22%,
      rgba(145, 104, 255, 0.45) 44%,
      transparent 64%),
    linear-gradient(300deg,
      transparent 12%,
      rgba(196, 124, 255, 0.40) 40%,
      rgba(91, 166, 255, 0.35) 66%,
      transparent 88%);
  background-size: 300% 300%, 280% 280%;
  background-position: 0% 50%, 100% 50%;
  filter: blur(44px);
  animation: heroWaveA 24s ease-in-out infinite alternate,
             heroWaveB 32s ease-in-out infinite alternate;
}
@keyframes heroWaveA { to { background-position: 100% 50%, 100% 50%; } }
@keyframes heroWaveB { to { background-position: 0% 50%, 0% 50%; } }

/* ---- Cinematic hero overlay: vignette + top scrim (z1, under text) ---- */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;                 /* above wave/bg (z0), below .heroC content (z2) */
  pointer-events: none;
  background:
    /* soft dark scrim at the top so nav links stay legible over the wave */
    linear-gradient(180deg, rgba(2, 4, 16, 0.55) 0%, transparent 16%),
    /* cinematic vignette — darkens the outer edges, focuses the centre */
    radial-gradient(ellipse 96% 78% at 50% 42%, transparent 56%, rgba(2, 4, 16, 0.62) 100%);
}

/* ---- Film grain texture across the whole hero (subtle, blended) ---- */
.hero-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.07;
  mix-blend-mode: soft-light;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 140px 140px;
}

/* Wrap must be full-width when .hero is a flex container.
   Hero gets a slightly WIDER frame than the rest of the site so the big
   headline + stat rail breathe. Everything inside (pill, headline, row,
   actions, stats) shares this same frame, so it all stays left-aligned to
   one edge and the stat rail sits flush to the right edge. */
.hero > .wrap { width: 100%; max-width: 1480px; }

/* Lower hero block: action buttons on the left, horizontal stats pushed to
   the right side of the frame. */
.heroC .row {
  display: flex;
  grid-template-columns: none;
  justify-content: space-between;
  align-items: center;
  gap: 40px;
  flex-wrap: wrap;
}

/* Stat rail — horizontal, right-aligned, with subtle dividers between items */
.heroC .stat-rail {
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: flex-start;
  gap: clamp(26px, 5vw, 64px);
  border-left: none;
  padding-left: 0;
  text-align: left;
}
.heroC .stat-rail > * {
  position: relative;
  padding-left: clamp(26px, 5vw, 64px);
}
.heroC .stat-rail > *:first-child { padding-left: 0; }
.heroC .stat-rail > *:not(:first-child)::before {
  content: "";
  position: absolute;
  left: 0; top: 4px; bottom: 4px;
  width: 1px;
  background: var(--line-2);
}

/* Softer headline — slightly smaller than the base clamp so the hero
   feels calmer and more refined (was clamp(46px, 9.5vw, 138px)). */
.heroC h1 { font-size: clamp(42px, 8vw, 116px); }

/* "digital" — electric-blue → indigo → violet gradient text */
.heroC h1 .accent {
  background: linear-gradient(128deg, #5ba6ff 0%, #9168ff 52%, #c47cff 100%);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  display: inline-block; /* required for background-clip in all browsers */
}

/* "that" — gradient fill so it pops above the image card behind it;
   creates typographic bookends with .accent ("digital … that") */
.heroC h1 .hl {
  background: linear-gradient(128deg, #5ba6ff 0%, #9168ff 52%, #c47cff 100%);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  display: inline-block;
}

/* "experiences" — brighter, more vivid blue-white outline stroke */
.heroC h1 .out {
  -webkit-text-stroke: 1.8px rgba(95, 148, 255, 0.82);
}

/* Eyebrow — lavender-blue instead of muted grey-dim */
.heroC .eyebrow {
  color: #8eabff;
}

/* Stat counter numbers — electric-blue → violet gradient */
.heroC .stat-rail .m-num span {
  background: linear-gradient(135deg, #66aaff 0%, #a270ff 100%);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
  display: inline-block;
}

/* ============================================================
   10 · HERO EXTRAS — word rotator · status pill · cursor
   spotlight · scroll cue. All brand-colored, all reversible.
   ============================================================ */

/* --- Word rotator: Matrix-style decode/scramble (JS-driven) ---
   The last headline word's letters flicker through random glyphs in
   electric blue, then lock in left-to-right as the gradient word.
   An invisible sizer reserves the width of the longest word so the
   surrounding text never shifts. */
.rotator {
  position: relative;
  display: inline-block;
  vertical-align: bottom;
  white-space: nowrap;
}
.rot-size { visibility: hidden; }          /* reserves width, no shift */
.rot-out {
  position: absolute;
  left: 0; top: 0;
  white-space: nowrap;
  /* settled letters carry the brand gradient */
  background: linear-gradient(128deg, #5ba6ff 0%, #9168ff 52%, #c47cff 100%);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}
/* scrambling characters: solid electric blue with a faint glow */
.rot-glitch {
  -webkit-text-fill-color: #7db4ff;
  color: #7db4ff;
  opacity: .9;
  text-shadow: 0 0 12px rgba(91, 166, 255, 0.55);
}
/* screen-reader-only word */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --- Live "now booking" status pill --- */
.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 22px;
  padding: 8px 16px;
  border-radius: 999px;
  font: 600 13.5px/1 var(--display, "Space Grotesk");
  letter-spacing: .01em;
  color: #cfe0ff;
  text-decoration: none;
  background: rgba(20, 30, 70, 0.55);
  border: 1px solid rgba(140, 170, 255, 0.28);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: border-color .35s, transform .35s var(--ease-spring), background .35s;
}
.status-pill strong { color: #fff; font-weight: 700; }
.status-pill:hover {
  transform: translateY(-2px);
  border-color: rgba(140, 170, 255, 0.55);
  background: rgba(28, 42, 96, 0.7);
}
.status-pill .dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: #38e08a; flex: none;
  box-shadow: 0 0 0 0 rgba(56, 224, 138, 0.6);
  animation: pillPulse 2.4s ease-out infinite;
}
@keyframes pillPulse {
  0%   { box-shadow: 0 0 0 0 rgba(56, 224, 138, 0.55); }
  70%  { box-shadow: 0 0 0 8px rgba(56, 224, 138, 0); }
  100% { box-shadow: 0 0 0 0 rgba(56, 224, 138, 0); }
}

/* --- Scroll-to-explore cue --- */
.scroll-cue {
  position: absolute;
  left: 50%; bottom: clamp(18px, 3vh, 34px);
  transform: translateX(-50%);
  z-index: 4;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: #8eabff;
  font: 600 11px/1 var(--display, "Space Grotesk");
  letter-spacing: .22em;
  text-transform: uppercase;
  opacity: .82;
  transition: opacity .5s ease, transform .5s var(--ease-spring);
}
.scroll-cue:hover { opacity: 1; }
.scroll-cue.is-hidden { opacity: 0; transform: translateX(-50%) translateY(14px); pointer-events: none; }
.sc-mouse {
  width: 22px; height: 34px; border-radius: 12px;
  border: 1.5px solid rgba(140, 170, 255, 0.55);
  display: flex; justify-content: center; padding-top: 6px;
}
.sc-wheel {
  width: 3px; height: 7px; border-radius: 2px;
  background: #8eabff;
  animation: scWheel 1.8s ease-in-out infinite;
}
@keyframes scWheel {
  0%   { transform: translateY(0); opacity: 1; }
  70%  { transform: translateY(9px); opacity: 0; }
  100% { transform: translateY(0); opacity: 0; }
}
@media (max-width: 640px) { .scroll-cue .sc-label { display: none; } }

/* ============================================================
   11 · TESTIMONIALS — elevated
   ============================================================ */
.tst { position: relative; overflow: hidden; }

/* Featured card: richer gradient + decorative depth */
.tst-main {
  padding: clamp(36px, 4vw, 54px) !important;
  background: linear-gradient(155deg, #1b3bb0 0%, #0e1f63 48%, #0a163f 100%) !important;
  border-color: rgba(120, 150, 255, 0.45) !important;
  box-shadow: 0 40px 80px -40px rgba(12, 28, 90, 0.65);
}
/* glow orb top-right */
.tst-main::before {
  content: ""; position: absolute; z-index: 0;
  width: 360px; height: 360px; top: -140px; right: -120px;
  background: radial-gradient(circle, rgba(120, 160, 255, 0.45), transparent 60%);
  filter: blur(20px); pointer-events: none;
}
/* faint grid texture */
.tst-main::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(rgba(255,255,255,0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.05) 1px, transparent 1px);
  background-size: 42px 42px;
  mask-image: radial-gradient(ellipse 80% 70% at 70% 30%, #000, transparent 75%);
}
.tst-main > * { position: relative; z-index: 1; }

.tst-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; }
.tst-main .quote-mark {
  font-size: 130px;
  background: linear-gradient(135deg, #7db4ff, #b18bff);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  opacity: .8;
}
.tst-main blockquote { margin-top: 6px; }

/* highlighted metric inside the quote */
.hl-metric {
  color: #fff; font-weight: 700;
  background: linear-gradient(120deg, #7db4ff, #b18bff);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  white-space: nowrap;
}

/* big gold rating in the featured card */
.stars-lg svg { width: 19px; height: 19px; }
.stars-lg { filter: drop-shadow(0 2px 6px rgba(255, 194, 75, 0.4)); }

/* Small cards: gradient top accent on hover + crisper depth */
.tst-card { position: relative; overflow: hidden; }
.tst-card::before {
  content: ""; position: absolute; left: 0; top: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, var(--blue), #9168ff);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .45s var(--ease-spring);
}
.tst-card:hover::before { transform: scaleX(1); }
.tst-card:hover { transform: translateY(-6px); }
.theme-light .tst-card:hover, .theme-tint .tst-card:hover {
  border-color: rgba(47, 107, 255, 0.4);
}
.tst-card p { font-style: italic; }

/* Avatars: gradient ring + lift */
.author .av {
  box-shadow: 0 0 0 2px rgba(255,255,255,0.12), 0 6px 16px -6px rgba(0,0,0,0.5);
}
.tst-main .author .av {
  background: linear-gradient(135deg, #7db4ff, #6d3bff);
  box-shadow: 0 0 0 2px rgba(255,255,255,0.25);
}

/* ============================================================
   REDUCED MOTION — keep it accessible
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .marquee-track,
  .hero-shot,
  .hero::before,
  .status-pill .dot,
  .sc-wheel,
  .heroC .hero-actions .btn-primary { animation: none !important; }
  .h-word-in { transform: none !important; opacity: 1 !important; }
  .rot-glitch { text-shadow: none !important; }
  .scroll-progress, .scroll-cue { display: none; }
  .reveal { transform: none !important; }
}
/* Frozen-timeline safety (some preview iframes pause rAF) */
.anim-frozen .marquee-track,
.anim-frozen .hero-shot,
.anim-frozen .hero::before,
.anim-frozen .heroC .hero-actions .btn-primary { animation: none !important; }
.anim-frozen .h-word-in { transform: none !important; opacity: 1 !important; }
.anim-frozen .reveal { opacity:1 !important; transform:none !important; transition:none !important; }
