@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Space+Grotesk:wght@500;600&family=Poppins:wght@300&display=swap');

* { margin: 0; padding: 0; box-sizing: border-box; }
/* Several purely-decorative elements (glow blobs, ambient card glows, light
   beams) deliberately bleed past their own container's edges for a soft,
   full-bleed look — .about-visual-glow's -40px inset is one example. That's
   fine until a narrow/single-column mobile layout puts the container close
   enough to the viewport edge that the bleed pushes past it, which was
   producing an unwanted horizontal scrollbar. Clipping it here catches any
   such element site-wide instead of chasing each one's exact inset value. */
body { background: #000000; overflow-x: hidden; }
/* 100dvh (with 100vh as a fallback for browsers that don't support it) —
   plain 100vh on mobile Safari/Chrome measures against the viewport with the
   address bar collapsed, which is taller than what's actually visible while
   it's still expanded. Since the hero is scroll-locked here (can't scroll to
   trigger the bar collapsing), that gap cuts content off at the bottom on a
   real phone — 100dvh tracks the actually-visible height instead. */
body.scroll-locked { overflow: hidden; height: 100vh; height: 100dvh; }

/* Hide the native scrollbar once the hero unlocks into the normal scrollable
   page — the section-dots and scroll-hint already communicate scroll
   position, and a stock OS scrollbar clashes with the custom glass/dark
   aesthetic. Scrolling itself still works; only the visible track/thumb UI
   is suppressed. */
html {
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* legacy Edge/IE */
  overflow-x: hidden; /* see the overflow-x note on body above — position:fixed
    decorative elements anchor to the viewport/html's initial containing
    block, not body, so body's own overflow-x:hidden alone didn't clip them */
}
html::-webkit-scrollbar {
  display: none; /* Chrome, Safari, Chromium Edge */
}

/* Hero — locked single-viewport carousel. Its children (canvas, hero text,
   dots, scroll hint) are positioned relative to THIS wrapper rather than the
   viewport, so once unlocked it behaves like any other normal-flow section
   and scrolls away naturally instead of staying pinned on screen. */
.hero-viewport {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100dvh; /* see body.scroll-locked comment above */
  overflow: hidden;
}

#three-canvas {
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* Soft angled light beams behind the 3D laptop — two wide, gently rotated
   bands of gradual gradient (never a hard edge), sitting behind the canvas
   (z-index:1) so the laptop reads as lit by them rather than floating in
   front of a plain gradient. No blur() filter — see the vignette/blob note
   further down on why a stacked blur reads as a muddy haze instead of a
   clean falloff. */
.hero-light-beams {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.hero-light-beam {
  position: absolute;
  top: -40%;
  left: -30%;
  width: 160%;
  height: 220%;
  transform-origin: center;
}
.hero-light-beam-1 {
  background: linear-gradient(
    100deg,
    transparent 40%,
    rgba(255, 255, 255, 0.025) 47%,
    rgba(255, 255, 255, 0.045) 50%,
    rgba(255, 255, 255, 0.025) 53%,
    transparent 60%
  );
  transform: rotate(-10deg);
  animation: beamDrift1 20s ease-in-out infinite;
}
.hero-light-beam-2 {
  background: linear-gradient(
    100deg,
    transparent 58%,
    rgba(199, 201, 204, 0.02) 65%,
    rgba(199, 201, 204, 0.035) 68%,
    rgba(199, 201, 204, 0.02) 71%,
    transparent 78%
  );
  transform: rotate(-10deg);
  animation: beamDrift2 26s ease-in-out infinite;
}
@keyframes beamDrift1 {
  0%, 100% { transform: rotate(-10deg) translateX(0); }
  50% { transform: rotate(-8deg) translateX(50px); }
}
@keyframes beamDrift2 {
  0%, 100% { transform: rotate(-10deg) translateX(0); }
  50% { transform: rotate(-12deg) translateX(-40px); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-light-beam {
    animation: none !important;
  }
}

/* Ambient glow wrapping the 3D laptop's silhouette (right-of-center on
   desktop, matching getRestingLaptopOffset() in laptop.js) — grounds it in
   the scene instead of floating in front of a flat background. Sized wide
   and tall rather than pooled tight underneath: the laptop fills the frame
   almost to the bottom edge, so there's no visible "floor" for a contact
   shadow/reflection to land on — the visible black space is beside and
   around it, which is what this actually needs to reach. Approximate rather
   than JS-tracked: it's a big soft shape, so it reads fine even as the
   laptop shifts slightly across viewport sizes and hero-carousel states. */
.hero-ground-glow {
  position: absolute;
  left: 68%;
  top: 48%;
  width: 1100px;
  max-width: 85vw;
  height: 800px;
  transform: translate(-50%, -50%);
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(
    ellipse 55% 60% at 50% 50%,
    rgba(255, 255, 255, 0.06) 0%,
    rgba(199, 201, 204, 0.035) 32%,
    rgba(154, 156, 160, 0.015) 58%,
    transparent 80%
  );
}
@media (max-width: 880px) {
  .hero-ground-glow {
    left: 50%;
    top: 45%;
    width: 700px;
    height: 600px;
  }
}

/* Glass header */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 950;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 48px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.015));
  backdrop-filter: blur(22px) saturate(140%);
  -webkit-backdrop-filter: blur(22px) saturate(140%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    inset 0 -1px 0 rgba(255, 255, 255, 0.04),
    0 8px 32px rgba(0, 0, 0, 0.35);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  opacity: 0;
  transform: translateY(-16px);
  pointer-events: none;
  transition: opacity 0.8s cubic-bezier(0.22, 1, 0.36, 1), transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}
/* Was a fixed 1.2s CSS animation, timed independently of the loader — it
   finished while the loader (a real ~4.3s minimum) was still showing. The
   loader's opaque background used to mask that; now that it's transparent,
   the header needs to actually wait for loader-hidden instead. */
.site-header.header-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.site-logo {
  height: 70px;
  width: auto;
  filter: drop-shadow(0 1px 8px rgba(255, 255, 255, 0.18));
  transition: filter 0.3s ease;
}
.site-logo:hover {
  filter: drop-shadow(0 1px 14px rgba(255, 255, 255, 0.3));
}
.site-nav {
  display: flex;
  align-items: center;
  gap: 36px;
}
.nav-link {
  position: relative;
  padding: 6px 0;
  color: rgba(230, 231, 234, 0.55);
  font-family: 'Inter', Arial, sans-serif;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  transition: color 0.3s ease;
}
.nav-link::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: linear-gradient(90deg, #ffffff, rgba(255, 255, 255, 0.2));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}
.nav-link:hover {
  color: #ffffff;
}
.nav-link:hover::after {
  transform: scaleX(1);
}
.nav-link.active {
  color: #ffffff;
  text-shadow: 0 0 12px rgba(255, 255, 255, 0.35);
}
.nav-link.active::after {
  transform: scaleX(1);
}

.enquire-btn {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #0a0a0a;
  padding: 11px 26px;
  border: none;
  border-radius: 999px;
  cursor: pointer;
  background: linear-gradient(135deg, #ffffff, #c7c9cc 55%, #9a9ca0);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    0 4px 18px rgba(255, 255, 255, 0.12),
    0 2px 8px rgba(0, 0, 0, 0.3);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.enquire-btn:hover {
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    0 6px 22px rgba(255, 255, 255, 0.22),
    0 3px 10px rgba(0, 0, 0, 0.35);
}
.enquire-btn:active {
  transform: translateY(0);
}

/* Mobile hamburger toggle (hidden on desktop, shown via the media query below) */
.menu-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 36px;
  height: 36px;
  border: none;
  background: transparent;
  cursor: pointer;
  padding: 0;
}
.menu-toggle span {
  display: block;
  width: 100%;
  height: 2px;
  background: #ffffff;
  border-radius: 2px;
  transition: transform 0.25s ease, opacity 0.25s ease;
}
.menu-toggle.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-toggle.open span:nth-child(2) { opacity: 0; }
.menu-toggle.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Mobile nav dropdown panel — always laid out (position:fixed takes it out of
   flow, so this costs nothing) and gated by visibility/opacity/transform
   instead of display:none, because display can't be part of a transition:
   toggling display:none -> flex on open would skip the enter animation, and
   flex -> none on close would cut the exit animation off instantly. The
   visibility delay is flipped per state so it appears instantly on open but
   only truly hides once the close transition has finished playing. */
.mobile-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 940;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 110px 28px 28px;
  background: rgba(8, 8, 9, 0.92);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  transform: translateY(-100%);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.35s ease, visibility 0s linear 0.35s;
}
.mobile-nav.mobile-nav-open {
  transform: translateY(0);
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.35s ease, visibility 0s linear 0s;
}
.mobile-nav-link {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: rgba(230, 231, 234, 0.7);
  text-decoration: none;
  padding: 14px 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.mobile-nav-link.active {
  color: #ffffff;
}
.mobile-nav-enquire {
  margin-top: 18px;
  align-self: flex-start;
}

/* Background vignette (matches loader.html) — deep black with only a faint
   silver hint near the top-left, not a visible gray glow. */
.vignette-bg {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background: radial-gradient(
    ellipse 120% 80% at 30% 20%,
    rgba(120, 122, 128, 0.05) 0%,
    rgba(70, 72, 78, 0.02) 20%,
    #030303 45%,
    #000000 75%
  );
}

/* Film-grain texture over the vignette (matches loader.html) */
.grain-overlay {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: 0.5;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

/* Site-wide 3D grid canvas — fixed full-page, sits behind every section as
   the page scrolls (see initBgGridScene() in laptop.js for the three.js
   side). Transparent clear color, so it only ever adds faint grid lines on
   top of the page's own black background, never blocks it. */
#bg-grid-canvas {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* Slow-drifting silver glow blobs — only ever animate `transform` (cheap,
   compositor-only). The softness comes from gradual multi-stop gradients,
   not a blur() filter: stacking a heavy blur on top of an already-soft
   radial-gradient double-softened the edges into a muddy haze rather than a
   clean, smooth falloff. */
.bg-blobs {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
}
.bg-blob {
  position: absolute;
  border-radius: 50%;
  will-change: transform;
}
.bg-blob-1 {
  width: 700px;
  height: 700px;
  top: -180px;
  left: 2%;
  background: radial-gradient(
    circle,
    rgba(255, 255, 255, 0.05) 0%,
    rgba(199, 201, 204, 0.03) 30%,
    rgba(154, 156, 160, 0.012) 55%,
    transparent 75%
  );
  animation: blobDrift1 26s ease-in-out infinite;
}
.bg-blob-2 {
  width: 780px;
  height: 780px;
  bottom: -240px;
  right: 0%;
  background: radial-gradient(
    circle,
    rgba(199, 201, 204, 0.04) 0%,
    rgba(154, 156, 160, 0.02) 32%,
    rgba(120, 122, 128, 0.008) 58%,
    transparent 78%
  );
  animation: blobDrift2 32s ease-in-out infinite;
}
.bg-blob-3 {
  width: 560px;
  height: 560px;
  top: 36%;
  left: 40%;
  background: radial-gradient(
    circle,
    rgba(255, 255, 255, 0.03) 0%,
    rgba(199, 201, 204, 0.018) 35%,
    rgba(154, 156, 160, 0.007) 60%,
    transparent 78%
  );
  animation: blobDrift3 22s ease-in-out infinite;
}
@keyframes blobDrift1 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(70px, 90px) scale(1.15); }
}
@keyframes blobDrift2 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(-80px, -60px) scale(1.1); }
}
@keyframes blobDrift3 {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(-60px, 50px) scale(1.2); }
}

/* Soft glow that follows the cursor. Positioned via translate3d (compositor-
   only) rather than animating the gradient itself, so it stays cheap even
   moving every mousemove frame. */
.cursor-spotlight {
  position: fixed;
  top: 0;
  left: 0;
  width: 640px;
  height: 640px;
  margin: -320px 0 0 -320px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.07), transparent 70%);
  pointer-events: none;
  z-index: 0;
  opacity: 0;
  transform: translate3d(-9999px, -9999px, 0);
  transition: opacity 0.6s ease;
  will-change: transform;
}
.cursor-spotlight.active {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .bg-blob {
    animation: none !important;
  }
  .cursor-spotlight {
    transition: none !important;
    opacity: 0 !important;
  }
}

@media (max-width: 880px) {
  /* Blobs stay (cheap, no interaction needed); the cursor spotlight is
     desktop-only since touch devices have no persistent pointer to follow. */
  .cursor-spotlight {
    display: none;
  }
}

/* ============================================
   ✏️ EDIT THIS — appears on the laptop screen
   ============================================ */
#screen-content {
  width: 1280px;
  height: 800px;
  position: fixed;
  top: -9999px; /* hidden from page */
  left: 0;
  background: #0a0a0a;
  color: white;
  font-family: 'Inter', Arial, sans-serif;
  overflow: hidden;
}

/* Mini website mockup — shared by #screen-content (baked onto the 3D screen)
   and #screen-flyin (the 2D HTML version that animates in over it) */
.mock-site {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  text-align: center;
  padding: 40px;
}
.mock-logo {
  height: 64px;
  width: auto;
}
.mock-headline {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 44px;
  font-weight: 600;
  color: #ffffff;
  max-width: 820px;
}
.mock-tagline {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 18px;
  font-weight: 300;
  color: rgba(255, 255, 255, 0.55);
  max-width: 560px;
}
.mock-ctas {
  display: flex;
  gap: 16px;
  margin-top: 8px;
}
.mock-cta-primary,
.mock-cta-secondary {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 15px;
  font-weight: 500;
  padding: 13px 30px;
  border-radius: 999px;
  display: inline-block;
}
.mock-cta-primary {
  background: linear-gradient(135deg, #ffffff, #c7c9cc);
  color: #0a0a0a;
}
.mock-cta-secondary {
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: #ffffff;
}

/* Full site layout (#screen-content only) — header, hero, features.
   #screen-flyin keeps the simpler centered .mock-site teaser as-is. */
#screen-content .mock-site {
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: 0;
  padding: 0;
  text-align: left;
  background:
    radial-gradient(circle at 12% 8%, rgba(255, 255, 255, 0.07), transparent 40%),
    radial-gradient(circle at 88% 85%, rgba(255, 255, 255, 0.05), transparent 45%),
    #060607;
}
.mock-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 26px 56px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.mock-header .mock-logo {
  height: 32px;
}
.mock-nav {
  display: flex;
  gap: 8px;
}
.mock-nav span {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 0.04em;
  padding: 8px 16px;
  border-radius: 999px;
  color: rgba(255, 255, 255, 0.65);
}
.mock-nav span:first-child {
  background: rgba(255, 255, 255, 0.08);
  color: #ffffff;
}
.mock-nav-cta {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12px;
  font-weight: 600;
  padding: 10px 24px;
  border-radius: 999px;
  background: linear-gradient(135deg, #ffffff, #c7c9cc);
  color: #0a0a0a;
}
.mock-hero {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 20px;
  padding: 0 60px;
  overflow: hidden;
}
.mock-glow {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}
.mock-glow-1 {
  width: 480px;
  height: 480px;
  top: -180px;
  left: 50%;
  margin-left: -240px;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.1), transparent 70%);
}
.mock-glow-2 {
  width: 360px;
  height: 360px;
  bottom: -200px;
  right: 6%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.06), transparent 70%);
}
.mock-hero > *:not(.mock-glow) {
  position: relative;
  z-index: 1;
}
.mock-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.75);
  padding: 7px 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  position: relative;
  z-index: 1;
}
.mock-badge-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #ffffff;
  display: inline-block;
}
.mock-accent {
  color: #ffffff;
  position: relative;
}
.mock-features {
  display: flex;
  gap: 28px;
  padding: 40px 56px 50px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.mock-feature {
  flex: 1;
  text-align: left;
  padding: 22px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.mock-feature-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.04));
  border: 1px solid rgba(255, 255, 255, 0.15);
  font-family: 'Space Grotesk', sans-serif;
  font-size: 12px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.75);
}
.mock-feature h3 {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 18px;
  font-weight: 600;
  color: #ffffff;
  margin: 14px 0 6px;
}
.mock-feature p {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 13px;
  font-weight: 300;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.5);
}

/* Software development mockup — code editor */
#screen-content .mock-site.mock-ide {
  flex-direction: row;
}
.mock-ide-sidebar {
  width: 210px;
  background: rgba(255, 255, 255, 0.03);
  border-right: 1px solid rgba(255, 255, 255, 0.08);
  padding: 24px 18px;
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.mock-ide-files {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.mock-ide-files span {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12.5px;
  color: rgba(255, 255, 255, 0.55);
  padding: 8px 10px;
  border-radius: 8px;
}
.mock-ide-files span.active {
  background: rgba(255, 255, 255, 0.08);
  color: #ffffff;
}
.mock-ide-dot {
  width: 8px;
  height: 8px;
  border-radius: 3px;
  display: inline-block;
  flex-shrink: 0;
}
.mock-ide-dot-tsx { background: #82aaff; }
.mock-ide-dot-json { background: #f0c882; }
.mock-ide-dot-css { background: #8fe3b0; }
.mock-ide-dot-md { background: rgba(255, 255, 255, 0.35); }
.mock-ide-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.mock-ide-tabs {
  display: flex;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.mock-ide-tabs span {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.45);
  padding: 14px 22px;
  border-right: 1px solid rgba(255, 255, 255, 0.06);
}
.mock-ide-tabs span.active {
  color: #ffffff;
  background: rgba(255, 255, 255, 0.03);
  box-shadow: inset 0 -2px 0 #ffffff;
}
.mock-ide-code {
  flex: 1;
  padding: 22px 26px;
  font-family: 'Courier New', Consolas, monospace;
  font-size: 13px;
  line-height: 1.85;
  overflow: hidden;
}
.mock-ide-line {
  white-space: pre;
  color: rgba(255, 255, 255, 0.75);
}
.mock-ide-ln {
  display: inline-block;
  width: 26px;
  color: rgba(255, 255, 255, 0.2);
}
.mock-ide-kw { color: #c792ea; }
.mock-ide-fn { color: #82aaff; }
.mock-ide-str { color: #8fe3b0; }
.mock-ide-cm { color: rgba(255, 255, 255, 0.35); font-style: italic; }
.mock-ide-num { color: #f0c882; }
.mock-ide-terminal {
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(0, 0, 0, 0.25);
  padding: 14px 26px;
  font-family: 'Courier New', Consolas, monospace;
  font-size: 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.mock-ide-terminal-line {
  color: rgba(255, 255, 255, 0.55);
}
.mock-ide-ok {
  color: #8fe3b0;
}

/* Mobile app mockup — phone frame centered on the laptop screen */
#screen-content .mock-site.mock-mobile {
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
}
.mock-mobile-phone {
  position: relative;
  z-index: 1;
  width: 300px;
  height: 620px;
  background: #0a0a0b;
  border: 6px solid #1c1c1e;
  border-radius: 42px;
  padding: 18px 16px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.05);
}
.mock-mobile-notch {
  position: absolute;
  top: 6px;
  left: 50%;
  transform: translateX(-50%);
  width: 90px;
  height: 22px;
  background: #1c1c1e;
  border-radius: 0 0 14px 14px;
}
.mock-mobile-topbar {
  display: flex;
  justify-content: space-between;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 10px;
  color: rgba(255, 255, 255, 0.6);
  padding-top: 6px;
}
.mock-mobile-greeting {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 17px;
  font-weight: 600;
  color: #ffffff;
}
.mock-mobile-hero-card {
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.03));
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 16px;
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.mock-mobile-hero-card span {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 11px;
  color: rgba(255, 255, 255, 0.55);
}
.mock-mobile-hero-card strong {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 24px;
  color: #ffffff;
}
.mock-mobile-cards-row {
  display: flex;
  gap: 10px;
}
.mock-mobile-mini-card {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  padding: 12px 6px;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 10.5px;
  color: rgba(255, 255, 255, 0.7);
}
.mock-mobile-mini-icon {
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  font-size: 13px;
  color: #ffffff;
}
.mock-mobile-list-title {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 11.5px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.6);
  margin-top: 2px;
}
.mock-mobile-list-item {
  display: flex;
  align-items: center;
  gap: 10px;
}
.mock-mobile-list-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: linear-gradient(135deg, #ffffff, #9a9ca0);
  flex-shrink: 0;
}
.mock-mobile-list-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  font-family: 'Inter', Arial, sans-serif;
}
.mock-mobile-list-text strong {
  font-size: 12px;
  color: #ffffff;
}
.mock-mobile-list-text span {
  font-size: 10px;
  color: rgba(255, 255, 255, 0.4);
}
.mock-mobile-list-item em {
  font-style: normal;
  font-size: 12px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.75);
}
.mock-mobile-navbar {
  margin-top: auto;
  display: flex;
  justify-content: center;
  gap: 14px;
  padding-top: 10px;
  font-size: 8px;
  color: rgba(255, 255, 255, 0.25);
}
.mock-mobile-navbar .active {
  color: #ffffff;
}

/* Digital marketing mockup — reuses the .mock-app-* dashboard shell (see ERP
   below) but swaps the bar chart for a line chart. */
.mock-app-linechart {
  flex: 1;
  width: 100%;
}

/* ERP dashboard mockup */
#screen-content .mock-site.mock-app {
  flex-direction: row;
}
.mock-app-sidebar {
  width: 210px;
  background: rgba(255, 255, 255, 0.03);
  border-right: 1px solid rgba(255, 255, 255, 0.08);
  padding: 24px 18px;
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.mock-app-logo {
  height: 24px;
}
.mock-app-nav {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.mock-app-nav span {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.55);
  padding: 9px 12px;
  border-radius: 10px;
}
.mock-app-nav span.active {
  background: rgba(255, 255, 255, 0.08);
  color: #ffffff;
}
.mock-app-nav-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.6;
  display: inline-block;
}
.mock-app-main {
  flex: 1;
  min-width: 0;
  padding: 26px 32px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.mock-app-topbar {
  display: flex;
  align-items: center;
  gap: 18px;
}
.mock-app-topbar h2 {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 19px;
  font-weight: 600;
  color: #ffffff;
  white-space: nowrap;
}
.mock-app-search {
  flex: 1;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 10px;
  padding: 10px 16px;
}
.mock-app-profile {
  display: flex;
  align-items: center;
  gap: 10px;
}
.mock-app-profile-text {
  display: flex;
  flex-direction: column;
  white-space: nowrap;
}
.mock-app-profile-text strong {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12.5px;
  font-weight: 600;
  color: #ffffff;
}
.mock-app-profile-text span {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 11px;
  color: rgba(255, 255, 255, 0.45);
}
.mock-app-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: linear-gradient(135deg, #ffffff, #9a9ca0);
  flex-shrink: 0;
}
.mock-app-cards {
  display: flex;
  gap: 14px;
}
.mock-app-card {
  flex: 1;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 14px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.mock-app-card span {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 11.5px;
  color: rgba(255, 255, 255, 0.5);
}
.mock-app-card strong {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 19px;
  color: #ffffff;
}
.mock-app-up,
.mock-app-down {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 11px;
  font-style: normal;
  font-weight: 500;
}
.mock-app-up { color: #8fe3b0; }
.mock-app-down { color: #f0a3a3; }
.mock-app-row {
  flex: 1;
  display: flex;
  gap: 16px;
  min-height: 0;
}
.mock-app-panel-title {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12.5px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.7);
  margin-bottom: 14px;
}
.mock-app-chart {
  flex: 1;
  display: flex;
  flex-direction: column;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 14px;
  padding: 20px;
}
.mock-app-bars {
  flex: 1;
  display: flex;
  align-items: flex-end;
  gap: 14px;
}
.mock-app-bar {
  flex: 1;
  background: linear-gradient(180deg, #ffffff, #9a9ca0);
  border-radius: 6px 6px 0 0;
  opacity: 0.85;
}
.mock-app-table {
  flex: 1;
  display: flex;
  flex-direction: column;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 14px;
  padding: 20px;
}
.mock-app-row-item {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12px;
}
.mock-app-row-item:first-of-type {
  border-top: none;
}
.mock-app-row-item span:first-child {
  color: rgba(255, 255, 255, 0.4);
  width: 50px;
}
.mock-app-row-item span:nth-child(2) {
  flex: 1;
  color: rgba(255, 255, 255, 0.8);
}
.mock-app-row-item strong {
  color: #ffffff;
  font-weight: 500;
}
.mock-app-pill {
  font-style: normal;
  font-size: 10.5px;
  font-weight: 500;
  padding: 4px 10px;
  border-radius: 999px;
}
.mock-app-pill-paid {
  background: rgba(143, 227, 176, 0.15);
  color: #8fe3b0;
}
.mock-app-pill-pending {
  background: rgba(240, 200, 130, 0.15);
  color: #f0c882;
}

/* E-commerce storefront mockup */
.mock-shop-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 36px 56px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.mock-shop-banner-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}
.mock-shop-banner h2 {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 30px;
  font-weight: 600;
  color: #ffffff;
}
.mock-shop-banner p {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.55);
}
.mock-shop-banner-visual {
  width: 150px;
  height: 110px;
  border-radius: 16px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.03));
  border: 1px solid rgba(255, 255, 255, 0.1);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.mock-shop-discount {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 24px;
  font-weight: 600;
  color: #ffffff;
}
.mock-shop-filters {
  display: flex;
  gap: 10px;
  padding: 18px 56px;
}
.mock-shop-filters span {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.55);
  padding: 7px 16px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.1);
}
.mock-shop-filters span.active {
  background: #ffffff;
  color: #0a0a0a;
  border-color: transparent;
}
.mock-shop-grid {
  flex: 1;
  display: flex;
  gap: 20px;
  padding: 8px 56px 24px;
}
.mock-shop-card {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.mock-shop-thumb {
  position: relative;
  width: 100%;
  height: 100px;
  border-radius: 12px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.03));
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.mock-shop-sale {
  position: absolute;
  top: 8px;
  left: 8px;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 9.5px;
  font-weight: 600;
  color: #0a0a0a;
  background: #ffffff;
  padding: 3px 8px;
  border-radius: 999px;
}
.mock-shop-rating {
  font-size: 10px;
  color: #f0c882;
  letter-spacing: 1px;
}
.mock-shop-name {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12.5px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.85);
}
.mock-shop-price {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.mock-shop-price strong {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 14px;
  color: #ffffff;
}
.mock-shop-price del {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 11px;
  color: rgba(255, 255, 255, 0.35);
}
.mock-shop-add {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 11px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.7);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  padding: 7px 0;
  text-align: center;
  margin-top: 4px;
}
.mock-shop-trust {
  display: flex;
  justify-content: center;
  gap: 32px;
  padding: 16px 56px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.mock-shop-trust span {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 11px;
  color: rgba(255, 255, 255, 0.45);
}

/* Mobile Apps section visual — positioned via JS (left/top in px) to land
   exactly on the 3D laptop's resting screen position, see
   updateMobileMockPosition() / getLaptopScreenCenterPx() in laptop.js. The
   top/left below are just a fallback until that first runs. */
.mobile-mock-visual {
  position: absolute;
  top: 50%;
  left: 50%;
  /* Width alone (32vw/460px) ignored viewport HEIGHT entirely — on a common
     1366x768 laptop screen the unscaled image (aspect-ratio 1024:1536) comes
     out taller than the space between the header and the viewport bottom,
     so no amount of repositioning could keep it fully on-screen. The third
     min() term derives a max width from the available height instead: 176px
     reserved is the same header(~110px) + top(32px) + bottom(24px) margins
     updateMobileMockPosition() clamps against in laptop.js, plus ~10px of
     slack — tight enough to stay as large as possible, not so tight it
     shrinks on viewports that never needed it. /1.5 for the portrait
     aspect ratio. */
  width: min(32vw, 460px, calc((100vh - 176px) / 1.5));
  width: min(32vw, 460px, calc((100dvh - 176px) / 1.5));
  height: auto;
  aspect-ratio: 1024 / 1536; /* mobile-mock-1.png's natural size — lets the
    browser compute box height from width alone, without waiting on image
    decode, so offsetHeight is reliable the instant it's read in JS */
  transform: translate(-50%, -50%) scale(0.92);
  z-index: 15;
  pointer-events: none;
  opacity: 0;
  filter: drop-shadow(0 40px 70px rgba(0, 0, 0, 0.6));
  transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.22, 1, 0.36, 1), left 0.3s ease, top 0.3s ease;
}
.mobile-mock-visual.mobile-mock-visible {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

/* Headline / tagline / CTAs on the left, revealed once the laptop moves right */
#hero-content {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 6%;
  max-width: 480px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start; /* column flex defaults to stretch, which was forcing the inline-flex badge to full column width */
  /* Centers within the space below the fixed header instead of across the
     full viewport — a pure top:50%/translateY(-50%) center let a tall
     headline+tagline combo creep up underneath (sometimes touching) the
     header on shorter viewports, since centering math doesn't know the
     header exists. Padding reserves that clearance regardless of how tall
     the content gets. */
  padding: 150px 0 40px;
  box-sizing: border-box;
  --hero-exit-shift: -26px;
  z-index: 40;
  pointer-events: none;
  transition: opacity 0.4s ease, transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}
#hero-content.hero-visible {
  pointer-events: auto;
}
#hero-content.hero-fade-out {
  opacity: 0;
  /* Exits in the direction of travel (set via JS per-transition) so the
     change reads as a scroll rather than a plain crossfade. */
  transform: translateY(var(--hero-exit-shift));
}
.hero-glow {
  position: absolute;
  top: -120px;
  left: -120px;
  width: 420px;
  height: 420px;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.08), transparent 70%);
  pointer-events: none;
  z-index: -1;
}
#hero-content > *:not(.hero-glow) {
  opacity: 0;
  transform: translateY(20px);
  filter: blur(8px);
}
#hero-content.hero-visible > *:not(.hero-glow) {
  animation: wordReveal 0.9s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
#hero-content.hero-visible .hero-badge { animation-delay: 0.05s; }
#hero-content.hero-visible .hero-headline { animation-delay: 0.2s; }
#hero-content.hero-visible .hero-tagline { animation-delay: 0.4s; }
#hero-content.hero-visible .hero-ctas { animation-delay: 0.55s; }
#hero-content.hero-visible .hero-stats { animation-delay: 0.7s; }

.hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.75);
  padding: 6px 12px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  margin-bottom: 22px;
  white-space: nowrap;
}
.hero-badge span:last-child {
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.hero-badge-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #ffffff;
  flex-shrink: 0;
  display: inline-block;
}
.hero-headline {
  font-family: 'Space Grotesk', sans-serif;
  font-size: clamp(2rem, 4.5vw, 3.2rem);
  font-weight: 600;
  line-height: 1.15;
  color: #ffffff;
  margin-bottom: 18px;
}
.hero-accent {
  background: linear-gradient(90deg, #888, #fff, #888);
  background-size: 200% auto;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: shine 6s linear infinite;
}
.hero-tagline {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 16px;
  font-weight: 300;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.6);
  margin-bottom: 28px;
}
.hero-ctas {
  display: flex;
  gap: 14px;
  margin-bottom: 40px;
}
.hero-cta-primary,
.hero-cta-secondary {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 14px;
  font-weight: 500;
  padding: 13px 28px;
  border-radius: 999px;
  cursor: pointer;
  border: none;
  transition: transform 0.25s ease, box-shadow 0.25s ease, background 0.25s ease;
}
.hero-cta-primary {
  background: linear-gradient(135deg, #ffffff, #c7c9cc 55%, #9a9ca0);
  color: #0a0a0a;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), 0 4px 18px rgba(255, 255, 255, 0.12);
}
.hero-cta-primary:hover {
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7), 0 8px 26px rgba(255, 255, 255, 0.2);
}
.hero-cta-secondary {
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: #ffffff;
}
.hero-cta-secondary:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.5);
}
.hero-stats {
  display: flex;
  gap: 36px;
  padding-top: 28px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.hero-stat {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.hero-stat strong {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 22px;
  font-weight: 600;
  color: #ffffff;
}
.hero-stat span {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
}

/* Section progress dots — right edge, one per SECTIONS entry (built by
   buildSectionDots() in laptop.js). Click to jump straight to a section. */
.section-dots {
  position: absolute;
  right: 28px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 45;
  display: flex;
  flex-direction: column;
  gap: 14px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.6s ease;
}
.section-dots.section-dots-visible {
  opacity: 1;
  pointer-events: auto;
}
.section-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: none;
  padding: 0;
  background: rgba(255, 255, 255, 0.25);
  cursor: pointer;
  transition: background 0.3s ease, transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
.section-dot:hover {
  background: rgba(255, 255, 255, 0.55);
}
.section-dot.active {
  background: #ffffff;
  transform: scale(1.4);
}
@media (max-width: 880px) {
  .section-dots {
    right: auto;
    left: 50%;
    top: auto;
    bottom: 3%;
    transform: translateX(-50%);
    flex-direction: row;
  }
  .section-dot.active {
    transform: scale(1.3);
  }
}

/* Scroll hint — shown only on the first section to teach the scroll-to-
   navigate interaction, then fades out for good once the user moves on. */
.scroll-hint {
  position: absolute;
  right: 1.5%;
  top: 64%;
  z-index: 40;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.6s ease;
}
.scroll-hint.scroll-hint-visible {
  opacity: 1;
}
.scroll-hint-mouse {
  width: 22px;
  height: 36px;
  border: 1.5px solid rgba(255, 255, 255, 0.4);
  border-radius: 12px;
  display: flex;
  justify-content: center;
  padding-top: 6px;
  box-sizing: border-box;
}
.scroll-hint-wheel {
  width: 3px;
  height: 7px;
  border-radius: 2px;
  background: #ffffff;
  animation: scrollHintWheel 1.6s ease infinite;
}
@keyframes scrollHintWheel {
  0% { opacity: 1; transform: translateY(0); }
  70% { opacity: 0; transform: translateY(10px); }
  100% { opacity: 0; transform: translateY(10px); }
}
.scroll-hint-label {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}
@media (max-width: 880px) {
  .scroll-hint {
    left: 50%;
    right: auto;
    top: auto;
    bottom: 20%;
    transform: translateX(-50%);
  }
}

/* Loading screen (loader.html splash) — transparent so the page's own
   vignette/grid/particles (rendering underneath since z-index:0) show
   through, matching the rest of the site instead of a flat black duplicate. */
#loader-overlay {
  position: fixed;
  inset: 0;
  isolation: isolate;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  transition: opacity 0.6s ease;
}
#loader-overlay.loader-hidden {
  opacity: 0;
  pointer-events: none;
}
.loader-container {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.5rem;
  z-index: 10;
  padding: 2rem;
  width: 100%;
  max-width: 1200px;
}

.logo-svg {
  width: 100%;
  max-width: 320px;
  height: auto;
  overflow: visible;
  opacity: 0;
  transform: translateY(20px) scale(0.95);
  animation: logoEnter 1.4s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
@keyframes logoEnter {
  to { opacity: 1; transform: translateY(0) scale(1); }
}

.path {
  fill: none;
  stroke: url(#liquidSilver);
  stroke-width: 11;
  stroke-linecap: round;
  filter: url(#silverGlow);
  stroke-dasharray: 250;
  stroke-dashoffset: 250;
  opacity: 0;
}
#g1-top { animation: drawPath 1.5s cubic-bezier(0.16, 1, 0.3, 1) 0.25s forwards; }
#g1-bar { stroke-dasharray: 80; stroke-dashoffset: 80; animation: drawPath 0.85s ease-out 1s forwards; }
#g2-top { animation: drawPath 1.5s cubic-bezier(0.16, 1, 0.3, 1) 0.6s forwards; }
#g2-bar { stroke-dasharray: 80; stroke-dashoffset: 80; animation: drawPath 0.85s ease-out 1.3s forwards; }
@keyframes drawPath {
  to { stroke-dashoffset: 0; opacity: 1; }
}

.text-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  width: 100%;
}
.word-wrapper {
  overflow: hidden;
  margin-bottom: 0.25rem;
}
.word {
  display: block;
  opacity: 0;
  transform: translateY(30px);
  filter: blur(10px);
}
.brand-name {
  font-family: 'Space Grotesk', sans-serif;
  font-size: clamp(2rem, 8vw, 4rem);
  font-weight: 600;
  letter-spacing: -0.01em;
  background: linear-gradient(90deg, #888, #fff, #888);
  background-size: 200% auto;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: wordReveal 0.85s cubic-bezier(0.22, 1, 0.36, 1) 1.9s forwards,
             shine 6s linear infinite;
}
.sub-name {
  /* Matches the "TECHNOLOGIES" subtitle baked into assets/images/logo.png,
     which is set in a thin geometric sans (round O, near-spurless G) —
     nothing like Inter's grotesque letterforms, which is what this
     inherited by default before. */
  font-family: 'Poppins', sans-serif;
  font-size: clamp(0.7rem, 2vw, 0.95rem);
  font-weight: 300;
  color: rgba(255, 255, 255, 0.5);
  letter-spacing: 0.7em;
  text-transform: uppercase;
  margin-top: 0.5rem;
  margin-left: 0.7em;
  animation: wordReveal 1s cubic-bezier(0.22, 1, 0.36, 1) 2.2s forwards;
}
@media (max-width: 480px) {
  .sub-name { letter-spacing: 0.3em; }
  .loader-container { gap: 1.5rem; }
}
@keyframes wordReveal {
  to { opacity: 1; transform: translateY(0); filter: blur(0); }
}
@keyframes shine {
  to { background-position: 200% center; }
}

.accent-line {
  width: 100px;
  height: 1px;
  background: radial-gradient(circle, rgba(255,255,255,0.4), transparent);
  margin-top: 2.5rem;
  opacity: 0;
  transform: scaleX(0);
  animation: lineFill 1.3s ease-out 2.7s forwards;
}
@keyframes lineFill {
  to { opacity: 1; transform: scaleX(1); }
}

/* ============================================
   RESPONSIVE
   ============================================ */
@media (max-width: 880px) {
  .site-header {
    padding: 14px 20px;
  }
  .site-logo {
    height: 58px;
  }
  .mobile-mock-visual {
    /* The 32vw desktop sizing (tuned against a much wider viewport) reads as
       tiny on a phone, where 32vw is only ~125px — bump it to fill a real
       share of the screen instead. Third min() term is the same
       height-aware shrink as the desktop rule, tuned for this breakpoint's
       shorter header (86px vs 110px) — keeps a landscape phone from hitting
       the same bottom cutoff. */
    width: min(58vw, 320px, calc((100vh - 150px) / 1.5));
    width: min(58vw, 320px, calc((100dvh - 150px) / 1.5));
  }
  .site-nav,
  .site-header .enquire-btn {
    /* Scoped to the header specifically — .mobile-nav-enquire shares the
       .enquire-btn class for its styling but lives in the mobile nav panel,
       not the header, and must stay visible there. */
    display: none;
  }
  .menu-toggle {
    display: flex;
  }

  /* The 3D laptop rests roughly in the viewport's upper half on narrow
     screens (see isNarrowViewport() in laptop.js, which recenters and pulls
     the camera back for portrait aspect ratios). Anchoring the text block by
     `top` instead of `bottom` gives it a fixed, laptop-clear starting line
     regardless of how tall its own content gets — the old bottom-anchored
     layout let the block grow upward into the laptop whenever any line
     wrapped, which is exactly what was happening. */
  #hero-content {
    left: 6%;
    right: 6%;
    top: 60%;
    bottom: auto;
    max-width: none;
    padding: 0;
    transform: none;
  }
  #hero-content.hero-fade-out {
    opacity: 0;
    transform: translateY(var(--hero-exit-shift));
  }
  .hero-glow {
    top: -80px;
    left: -80px;
    width: 280px;
    height: 280px;
  }
  .hero-badge {
    margin-bottom: 8px;
  }
  .hero-headline {
    /* Sized against the longest of the six rotating headlines (two lines,
       e.g. "Native-Grade Apps For iOS & Android"), not just the shortest —
       the block has to fit above the fold on every hero section, not only
       the first one. */
    font-size: clamp(1.35rem, 6.4vw, 1.9rem);
    line-height: 1.15;
    margin-bottom: 6px;
  }
  .hero-tagline {
    font-size: 12.5px;
    line-height: 1.4;
    max-width: 420px;
    margin-bottom: 10px;
  }
  .hero-ctas {
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 10px;
  }
  .hero-stats {
    flex-wrap: wrap;
    gap: 16px;
    padding-top: 10px;
  }
  .hero-stat strong {
    font-size: 17px;
  }
  .hero-stat span {
    font-size: 11px;
  }

  /* A mouse-and-scroll-wheel icon doesn't read as an affordance on a
     touchscreen, and it had nowhere collision-free to sit once the text
     block was compacted to fit above the fold — the section dots at the
     bottom already communicate "there's more, tap to jump" on mobile. */
  .scroll-hint {
    display: none;
  }

  .loader-container {
    padding: 1rem;
  }
}

@media (max-width: 480px) {
  .site-header {
    padding: 12px 16px;
  }
  .site-logo {
    height: 48px;
  }
  .mobile-nav {
    padding: 90px 20px 24px;
  }
  #hero-content {
    top: 58%;
  }
  .hero-badge {
    font-size: 11px;
  }
  .hero-headline {
    font-size: clamp(1.3rem, 7.5vw, 1.8rem);
  }
  .hero-cta-primary,
  .hero-cta-secondary {
    font-size: 13px;
    padding: 11px 22px;
  }
  .hero-stat strong {
    font-size: 18px;
  }
}

/* Short-viewport phones (e.g. 800px-tall Android devices, vs. 844+ on most
   iPhones) — gated on height, not width, since this is purely about
   vertical room between the laptop and the section dots. Without this the
   two longer of the six rotating headlines (2 lines each) push the stats
   row far enough down to sit under the dots on shorter screens. */
@media (max-width: 880px) and (max-height: 820px) {
  #hero-content {
    top: 56%;
  }
  .hero-badge {
    margin-bottom: 6px;
  }
  .hero-headline {
    line-height: 1.08;
    margin-bottom: 4px;
  }
  .hero-tagline {
    margin-bottom: 6px;
  }
  .hero-ctas {
    margin-bottom: 6px;
  }
  .hero-stats {
    padding-top: 6px;
    gap: 12px;
  }
  .hero-stat strong {
    font-size: 15px;
  }
}

/* ============================================
   PAGE CONTENT — everything below the hero (About onward). Normal document
   flow; the hero unlocks into this via heroLocked in laptop.js.
   ============================================ */

/* Scroll reveal — each element opts into a distinct 3D choreography via
   data-reveal ("rise" | "depth" | "flip-left" | "flip-right" | "flip-up" |
   "pop" | "grow-x"), toggled to .in-view by initScrollReveal() in laptop.js.
   The .page-section ancestor in every selector is load-bearing: it bumps
   specificity above component rules like .service-card's own transition
   (see the .service-card rule below), so this system always owns transform
   during the entrance instead of losing the cascade to a same-specificity,
   later-declared rule. */
.page-section .reveal {
  opacity: 0;
  will-change: transform, opacity;
  transition: opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.85s cubic-bezier(0.34, 1.56, 0.64, 1);
  transition-delay: calc(var(--reveal-index, 0) * 0.1s);
}
.page-section .reveal.in-view {
  opacity: 1;
}

/* rise (default) — lifts up out of the floor with real depth, not just a nudge */
.page-section .reveal,
.page-section .reveal[data-reveal='rise'] {
  transform: perspective(1400px) translateY(64px) rotateX(20deg) scale(0.94);
}
.page-section .reveal.in-view,
.page-section .reveal[data-reveal='rise'].in-view {
  transform: perspective(1400px) translateY(0) rotateX(0deg) scale(1);
}

/* depth — materializes toward the camera out of soft focus; reserved for
   section headers and other single "big moment" elements per section */
.page-section .reveal[data-reveal='depth'] {
  transform: perspective(1200px) translateZ(-260px) scale(0.82);
  filter: blur(9px);
  transition: opacity 0.9s cubic-bezier(0.16, 1, 0.3, 1),
    transform 1.05s cubic-bezier(0.16, 1, 0.3, 1),
    filter 1.05s cubic-bezier(0.16, 1, 0.3, 1);
}
.page-section .reveal[data-reveal='depth'].in-view {
  transform: perspective(1200px) translateZ(0) scale(1);
  filter: blur(0);
}

/* flip-left / flip-right — door-hinge swing on the Y axis, for elements that
   sit in a left or right column (about-visual, contact panels) */
.page-section .reveal[data-reveal='flip-left'] {
  transform-origin: left center;
  transform: perspective(1800px) rotateY(-98deg) translateX(-30px);
}
.page-section .reveal[data-reveal='flip-left'].in-view {
  transform: perspective(1800px) rotateY(0deg) translateX(0);
}
.page-section .reveal[data-reveal='flip-right'] {
  transform-origin: right center;
  transform: perspective(1800px) rotateY(98deg) translateX(30px);
}
.page-section .reveal[data-reveal='flip-right'].in-view {
  transform: perspective(1800px) rotateY(0deg) translateX(0);
}

/* flip-up — flap hinge from the bottom edge; used for grid cards so they
   snap open like a panel instead of just sliding up */
.page-section .reveal[data-reveal='flip-up'] {
  transform-origin: bottom center;
  transform: perspective(1600px) rotateX(-82deg) translateY(24px);
}
.page-section .reveal[data-reveal='flip-up'].in-view {
  transform: perspective(1600px) rotateX(0deg) translateY(0);
}

/* pop — springy scale+rotate settle for small chips, badges and numbers */
.page-section .reveal[data-reveal='pop'] {
  transform: scale(0.4) rotate(-12deg);
}
.page-section .reveal[data-reveal='pop'].in-view {
  transform: scale(1) rotate(0deg);
}

/* grow-x — a connector line traces itself in from the left, no fade needed */
.page-section .reveal[data-reveal='grow-x'] {
  opacity: 1;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.6s cubic-bezier(0.65, 0, 0.35, 1);
  transition-delay: calc(var(--reveal-index, 0) * 0.1s + 0.15s);
}
.page-section .reveal[data-reveal='grow-x'].in-view {
  transform: scaleX(1);
}

/* Post-settle interaction handoff — once the entrance transition has
   finished, laptop.js swaps in a fast transition so pointer-tilt (see
   initCardTilt()) feels responsive instead of dragging through the same
   0.85s spring used for the reveal itself. */
.page-section .reveal.tilt-ready {
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Ambient background orbs — decorative depth layers behind section content,
   drifted by initParallax() in laptop.js via data-parallax on scroll. */
.ambient-orb {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  z-index: -1;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.07), transparent 70%);
}

/* Scroll-linked parallax — initParallax() in laptop.js writes --parallax-y
   on elements as they drift near the viewport. Driven through a custom
   property (not a direct transform overwrite) so it composes safely with
   any base transform an element already needs, e.g. .cta-banner-glow's
   own translateX(-50%) centering below. */
[data-parallax] {
  transform: translate3d(0, var(--parallax-y, 0px), 0);
}
.cta-banner-glow[data-parallax] {
  transform: translateX(-50%) translateY(var(--parallax-y, 0px));
}
/* Insets stay positive and the size is capped to a share of the viewport
   width, so the blurred orb can never push the section past the viewport
   edge on narrow screens — see the footer min-width grid overflow bug fixed
   earlier in this file for why that matters here. */
#process .ambient-orb {
  width: min(420px, 60vw);
  height: min(420px, 60vw);
  top: 0;
  right: 20px;
}
#testimonials .ambient-orb {
  width: min(460px, 60vw);
  height: min(460px, 60vw);
  bottom: 20px;
  left: 20px;
}
#contact .ambient-orb {
  width: min(400px, 60vw);
  height: min(400px, 60vw);
  top: 40px;
  right: 20px;
}
@media (max-width: 880px) {
  .ambient-orb {
    opacity: 0.5;
  }
}

@media (prefers-reduced-motion: reduce) {
  .page-section .reveal {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
  }
  .ambient-orb {
    display: none;
  }
}

/* Shared primitives reused by every section below */
.page-section {
  position: relative;
  z-index: 1;
  padding: 130px 48px;
  max-width: 1280px;
  margin: 0 auto;
}
.section-header {
  max-width: 640px;
  margin-bottom: 60px;
}
.section-header.center {
  max-width: 700px;
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}
.section-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.75);
  padding: 7px 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  margin-bottom: 22px;
}
.section-badge-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #ffffff;
  display: inline-block;
}
.section-heading {
  font-family: 'Space Grotesk', sans-serif;
  font-size: clamp(1.9rem, 3.6vw, 2.8rem);
  font-weight: 600;
  line-height: 1.2;
  color: #ffffff;
  margin-bottom: 18px;
}
.text-accent {
  background: linear-gradient(90deg, #888, #fff, #888);
  background-size: 200% auto;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: shine 6s linear infinite;
}
.section-sub {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 16px;
  font-weight: 300;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.6);
}
@media (max-width: 880px) {
  .page-section {
    padding: 90px 24px;
  }
  .section-header {
    margin-bottom: 44px;
  }
}

/* ---------- About ---------- */
.about-grid {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 72px;
  align-items: center;
}
.about-stats {
  display: grid;
  grid-template-columns: repeat(4, auto);
  gap: 28px;
  margin-top: 40px;
}
.about-stat {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.about-stat strong {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 26px;
  font-weight: 600;
  color: #ffffff;
}
.about-stat span {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
}
.about-visual {
  position: relative;
}
.about-visual-glow {
  position: absolute;
  inset: -40px;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.08), transparent 70%);
  pointer-events: none;
  z-index: -1;
}
.about-visual-card {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 20px;
  overflow: hidden;
  aspect-ratio: 1 / 1; /* matches about.png's native 1024x1024 */
}
.about-visual-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
@media (max-width: 880px) {
  .about-grid {
    grid-template-columns: 1fr;
    gap: 48px;
  }
  .about-stats {
    grid-template-columns: repeat(2, auto);
    gap: 24px 32px;
  }
}

/* ---------- Services ---------- */
.services-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.service-card {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 18px;
  padding: 30px 26px;
  transition: border-color 0.4s ease, background 0.4s ease;
}
.service-card:hover {
  border-color: rgba(255, 255, 255, 0.2);
  background: rgba(255, 255, 255, 0.05);
}
.service-icon {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.03));
  border: 1px solid rgba(255, 255, 255, 0.14);
  margin-bottom: 20px;
}
.service-icon svg {
  width: 20px;
  height: 20px;
  stroke: #ffffff;
  fill: none;
  stroke-width: 1.6;
}
.service-card h3 {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 18px;
  font-weight: 600;
  color: #ffffff;
  margin-bottom: 10px;
}
.service-card p {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 14px;
  font-weight: 300;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.55);
}
@media (max-width: 880px) {
  .services-grid {
    grid-template-columns: 1fr;
  }
}
@media (min-width: 881px) and (max-width: 1100px) {
  .services-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ---------- Process ---------- */
.process-steps {
  display: flex;
  align-items: flex-start;
  gap: 0;
}
.process-step {
  flex: 1;
  min-width: 0;
}
.process-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.18);
  font-family: 'Space Grotesk', sans-serif;
  font-size: 15px;
  font-weight: 600;
  color: #ffffff;
  margin-bottom: 20px;
}
.process-step h3 {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 18px;
  font-weight: 600;
  color: #ffffff;
  margin-bottom: 10px;
}
.process-step p {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 14px;
  font-weight: 300;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.55);
  max-width: 240px;
}
.process-connector {
  flex-shrink: 0;
  width: 60px;
  height: 1px;
  margin-top: 23px;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.05));
}
@media (max-width: 880px) {
  .process-steps {
    flex-direction: column;
    gap: 36px;
  }
  .process-connector {
    display: none;
  }
  .process-step p {
    max-width: none;
  }
}

/* ---------- Testimonials ---------- */
.testimonials-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.testimonial-card {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 18px;
  padding: 32px 28px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.testimonial-stars {
  color: #f0c882;
  font-size: 13px;
  letter-spacing: 2px;
}
.testimonial-quote {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 14.5px;
  font-weight: 300;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.75);
  flex: 1;
}
.testimonial-author {
  display: flex;
  align-items: center;
  gap: 12px;
}
.testimonial-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: linear-gradient(135deg, #ffffff, #9a9ca0);
  flex-shrink: 0;
}
.testimonial-author-text {
  display: flex;
  flex-direction: column;
}
.testimonial-author-text strong {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 13.5px;
  font-weight: 600;
  color: #ffffff;
}
.testimonial-author-text span {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.45);
}
@media (max-width: 880px) {
  .testimonials-grid {
    grid-template-columns: 1fr;
  }
}
@media (min-width: 881px) and (max-width: 1100px) {
  .testimonials-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ---------- Case Studies (Recent Work) ---------- */
.case-studies-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px;
}
.case-study-card {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 18px;
  padding: 32px 28px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.case-study-tag {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 15px;
  font-weight: 600;
  color: #ffffff;
}
.case-study-block {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 14px;
  font-weight: 300;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.6);
}
.case-study-block strong {
  font-weight: 600;
  color: rgba(255, 255, 255, 0.85);
}
.case-study-result {
  color: rgba(255, 255, 255, 0.75);
}
@media (max-width: 880px) {
  .case-studies-grid {
    grid-template-columns: 1fr;
  }
}

/* ---------- Industries: 3D cylindrical carousel ----------
   8 cards sit on the surface of an invisible cylinder (rotateY + translateZ,
   45deg apart) inside a perspective stage. Drag or the arrow buttons rotate
   the cylinder; JS (initIndustriesCarousel in laptop.js) dims/brightens each
   card by how far it's turned from front-facing. Below 880px this whole
   carousel is hidden in favor of .industries-scroller, a flat swipeable
   strip — a drag-cylinder is a poor fit for a narrow touch viewport. */
.industries-carousel {
  --industry-card-w: 260px;
  --industry-card-h: 350px;
  --industry-radius: 400px; /* translateZ distance; 314px would be edge-to-edge with no gap */
  position: relative;
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.carousel-stage {
  width: 100%;
  max-width: 620px;
  height: 460px;
  perspective: 1500px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.carousel-cylinder {
  position: relative;
  width: var(--industry-card-w);
  height: var(--industry-card-h);
  transform-style: preserve-3d;
  transform: rotateY(var(--cylinder-rotation, 0deg));
  transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
  cursor: grab;
  touch-action: pan-y;
}
.carousel-cylinder.dragging {
  transition: none;
  cursor: grabbing;
}
.carousel-cylinder:focus-visible {
  outline: none;
  filter: drop-shadow(0 0 0 1px rgba(255, 255, 255, 0.35));
}
.industry-card {
  position: absolute;
  inset: 0;
  width: var(--industry-card-w);
  height: var(--industry-card-h);
  transform: rotateY(calc(var(--i) * 45deg)) translateZ(var(--industry-radius));
  transition: opacity 0.5s ease, filter 0.5s ease;
  /* Without this, a card rotated past 90deg shows its mirrored backface —
     reads as garbled, overlapping text bleeding into the cards in front.
     The opacity falloff in initIndustriesCarousel() already fades a card
     near-invisible well before it reaches this cutoff. */
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
/* Shared full-bleed photo treatment: the image fills the whole card, and the
   heading/tagline sit on a gradient scrim pinned to the bottom. */
.industry-card,
.industry-card-flat {
  display: flex;
  align-items: flex-end;
  background-color: rgba(255, 255, 255, 0.04);
  background-size: cover;
  background-position: center;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 20px;
  overflow: hidden;
  user-select: none;
}
.industry-card-overlay {
  width: 100%;
  padding: 60px 20px 20px;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.35) 35%, rgba(0, 0, 0, 0.88) 100%);
}
.industry-card-overlay h3 {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 16px;
  font-weight: 600;
  color: #ffffff;
  margin-bottom: 6px;
}
.industry-card-overlay p {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12.5px;
  font-weight: 300;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.7);
}
/* The card size/radius above are fixed px values, so the carousel's total
   visible width doesn't shrink with the viewport on its own — below ~1250px
   there isn't enough room left for the arrows to clear the cards at full
   size. Scale the whole cylinder down so it fits with clearance to spare. */
@media (min-width: 881px) and (max-width: 1250px) {
  .industries-carousel {
    --industry-card-w: 200px;
    --industry-card-h: 270px;
    --industry-radius: 300px;
  }
  .carousel-stage {
    max-width: 480px;
    height: 380px;
  }
  .industry-card .industry-card-overlay {
    padding: 40px 16px 16px;
  }
}
.carousel-nav-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  flex-shrink: 0;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.14);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.3s ease, border-color 0.3s ease, transform 0.2s ease;
}
.carousel-nav-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.28);
  transform: translateY(-50%) scale(1.06);
}
.carousel-nav-prev { left: 0; }
.carousel-nav-next { right: 0; }
.carousel-nav-btn svg {
  width: 18px;
  height: 18px;
  stroke: #ffffff;
  fill: none;
  stroke-width: 1.8;
}

/* Flat swipeable fallback (touch/narrow viewports only) */
.industries-scroller {
  display: none;
  gap: 16px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding: 4px 4px 12px;
  -webkit-overflow-scrolling: touch;
}
.industries-scroller::-webkit-scrollbar {
  display: none;
}
.industry-card-flat {
  scroll-snap-align: start;
  flex: 0 0 78%;
  height: 380px;
  border-radius: 18px;
}
@media (max-width: 880px) {
  .industries-carousel {
    display: none;
  }
  .industries-scroller {
    display: flex;
  }
}
@media (max-width: 480px) {
  .industry-card-flat {
    flex-basis: 88%;
  }
}

/* ---------- FAQ ---------- */
.faq-list {
  max-width: 820px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.faq-item {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 14px;
  padding: 6px 26px;
  transition: border-color 0.3s ease, background 0.3s ease;
}
.faq-item:hover {
  border-color: rgba(255, 255, 255, 0.16);
}
.faq-item summary {
  list-style: none;
  padding: 20px 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.faq-item summary::-webkit-details-marker {
  display: none;
}
.faq-item summary::after {
  content: '+';
  flex-shrink: 0;
  font-family: 'Space Grotesk', sans-serif;
  font-size: 20px;
  font-weight: 400;
  color: rgba(255, 255, 255, 0.5);
  transition: transform 0.3s ease;
}
.faq-item[open] summary::after {
  transform: rotate(45deg);
}
.faq-item summary h3 {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 16px;
  font-weight: 600;
  color: #ffffff;
}
.faq-item p {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 14.5px;
  font-weight: 300;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.6);
  padding-bottom: 22px;
  margin: 0;
}
@media (max-width: 880px) {
  .faq-item summary h3 {
    font-size: 15px;
  }
}

/* ---------- CTA banner ---------- */
.cta-banner {
  position: relative;
  overflow: hidden;
  text-align: center;
  padding: 90px 48px;
  border-radius: 28px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.015));
  border: 1px solid rgba(255, 255, 255, 0.1);
}
.cta-banner-glow {
  position: absolute;
  top: -50%;
  left: 50%;
  transform: translateX(-50%);
  width: 700px;
  height: 500px;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.1), transparent 70%);
  pointer-events: none;
}
.cta-banner-heading {
  position: relative;
  font-family: 'Space Grotesk', sans-serif;
  font-size: clamp(1.8rem, 4vw, 2.6rem);
  font-weight: 600;
  color: #ffffff;
  max-width: 620px;
  margin: 0 auto 16px;
}
.cta-banner-sub {
  position: relative;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 15px;
  font-weight: 300;
  color: rgba(255, 255, 255, 0.6);
  max-width: 480px;
  margin: 0 auto 36px;
}
.cta-banner-ctas {
  position: relative;
  display: flex;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
}
@media (max-width: 880px) {
  .cta-banner {
    padding: 60px 28px;
    border-radius: 20px;
  }
}

/* ---------- Clientele marquee ---------- */
.marquee {
  position: relative;
  width: 100%;
  padding: 28px 0;
  background: #ffffff;
  border-radius: 16px;
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee-track {
  display: flex;
  align-items: center;
  gap: 64px;
  width: max-content;
  animation: marqueeScroll 32s linear infinite;
}
.marquee:hover .marquee-track {
  animation-play-state: paused;
}
@keyframes marqueeScroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
.marquee-logo {
  height: 30px;
  width: auto;
  flex-shrink: 0;
  object-fit: contain;
  /* Keep each logo's real colors — just dim it slightly at rest so the row
     stays quiet, then bring it to full color/opacity on hover. */
  opacity: 0.65;
  transition: opacity 0.3s ease;
}
.marquee-logo:hover {
  opacity: 1;
}
/* Carlay's mark is a white-on-transparent wordmark — invisible on the white
   strip above unless flipped dark. The other two logos are already dark and
   read fine as-is. */
.marquee-logo-invert {
  filter: invert(1);
}
@media (prefers-reduced-motion: reduce) {
  .marquee-track {
    animation: none;
  }
}

/* ---------- Contact ---------- */
.contact-grid {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: 64px;
}
.contact-info-list {
  display: flex;
  flex-direction: column;
  gap: 22px;
  margin-top: 36px;
}
.contact-local-note {
  margin-top: 28px;
  padding-top: 24px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 13.5px;
}
.contact-info-item {
  display: flex;
  align-items: flex-start;
  gap: 14px;
}
.contact-info-icon {
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.contact-info-icon svg {
  width: 16px;
  height: 16px;
  stroke: #ffffff;
  fill: none;
  stroke-width: 1.6;
}
.contact-info-text strong {
  display: block;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 13.5px;
  font-weight: 600;
  color: #ffffff;
  margin-bottom: 2px;
}
.contact-info-text span {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.55);
}
.contact-form-card {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 22px;
  padding: 40px;
  min-width: 0; /* grid/flex items default to min-width:auto, which refuses
    to shrink below content's intrinsic size — without this the <select>
    below (sized to its longest option text) was forcing this whole card,
    and the page along with it, wider than the viewport at ~1280-1366px. */
}
.contact-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}
.contact-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 20px;
  min-width: 0;
}
.contact-field label {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12.5px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.6);
}
.contact-field input,
.contact-field select,
.contact-field textarea {
  width: 100%;
  min-width: 0;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 14px;
  color: #ffffff;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  padding: 13px 16px;
  outline: none;
  transition: border-color 0.25s ease, background 0.25s ease;
}
.contact-field select option {
  background: #0a0a0a;
  color: #ffffff;
}
.contact-field input:focus,
.contact-field select:focus,
.contact-field textarea:focus {
  border-color: rgba(255, 255, 255, 0.4);
  background: rgba(255, 255, 255, 0.07);
}
.contact-field textarea {
  resize: vertical;
  min-height: 110px;
  font-family: 'Inter', Arial, sans-serif;
}
.contact-field.has-error input,
.contact-field.has-error select,
.contact-field.has-error textarea {
  border-color: rgba(240, 130, 130, 0.6);
}
.contact-field-error {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 11.5px;
  color: #f0a3a3;
  min-height: 14px;
}
.contact-submit {
  width: 100%;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 15px;
  font-weight: 500;
  padding: 15px 28px;
  border-radius: 999px;
  border: none;
  cursor: pointer;
  background: linear-gradient(135deg, #ffffff, #c7c9cc 55%, #9a9ca0);
  color: #0a0a0a;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), 0 4px 18px rgba(255, 255, 255, 0.12);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.contact-submit:hover {
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7), 0 8px 26px rgba(255, 255, 255, 0.2);
}
.contact-submit:disabled {
  opacity: 0.6;
  cursor: default;
  transform: none;
}
.contact-success {
  display: none;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
  padding: 50px 20px;
}
.contact-form-card.submitted .contact-form {
  display: none;
}
.contact-form-card.submitted .contact-success {
  display: flex;
}
.contact-success-icon {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(143, 227, 176, 0.12);
  border: 1px solid rgba(143, 227, 176, 0.35);
}
.contact-success-icon svg {
  width: 24px;
  height: 24px;
  stroke: #8fe3b0;
  fill: none;
  stroke-width: 2;
}
.contact-success h3 {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 20px;
  color: #ffffff;
}
.contact-success p {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.55);
  max-width: 320px;
}
@media (max-width: 880px) {
  .contact-grid {
    grid-template-columns: 1fr;
    gap: 40px;
  }
  .contact-form-row {
    grid-template-columns: 1fr;
    gap: 0;
  }
  .contact-form-card {
    padding: 28px;
  }
}

/* ---------- Footer ---------- */
.site-footer {
  position: relative;
  z-index: 1;
  padding: 80px 48px 32px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.footer-grid {
  max-width: 1280px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1.2fr;
  gap: 48px;
  padding-bottom: 56px;
}
.footer-grid > * {
  /* Grid items default to min-width:auto, which refuses to shrink below an
     unbreakable word's width (e.g. "Development") — that forces the whole
     grid (and page) wider than the viewport on narrow screens. */
  min-width: 0;
}
.footer-brand-logo {
  height: 34px;
  margin-bottom: 18px;
}
.footer-brand p {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 13.5px;
  font-weight: 300;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.5);
  max-width: 280px;
  margin-bottom: 22px;
}
.footer-socials {
  display: flex;
  gap: 10px;
}
.footer-social-link {
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.1);
  transition: background 0.25s ease, border-color 0.25s ease, transform 0.25s ease;
}
.footer-social-link:hover {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.25);
  transform: translateY(-2px);
}
.footer-social-link svg {
  width: 15px;
  height: 15px;
  stroke: #ffffff;
  fill: none;
  stroke-width: 1.7;
}
.footer-col-title {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.4);
  margin-bottom: 22px;
}
.footer-links {
  display: flex;
  flex-direction: column;
  gap: 13px;
}
.footer-links a {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.65);
  text-decoration: none;
  transition: color 0.25s ease;
  width: fit-content;
}
.footer-links a:hover {
  color: #ffffff;
}
.footer-newsletter p {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 13.5px;
  font-weight: 300;
  color: rgba(255, 255, 255, 0.5);
  margin-bottom: 16px;
}
.footer-newsletter-form {
  display: flex;
  gap: 8px;
}
.footer-newsletter-form input {
  flex: 1;
  min-width: 0;
  font-family: 'Inter', Arial, sans-serif;
  font-size: 13px;
  color: #ffffff;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 999px;
  padding: 11px 18px;
  outline: none;
}
.footer-newsletter-form button {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  cursor: pointer;
  background: linear-gradient(135deg, #ffffff, #c7c9cc);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.25s ease;
}
.footer-newsletter-form button:hover {
  transform: translateY(-2px);
}
.footer-newsletter-form button svg {
  width: 16px;
  height: 16px;
  stroke: #0a0a0a;
  fill: none;
  stroke-width: 2;
}
.footer-bottom {
  max-width: 1280px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 28px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  flex-wrap: wrap;
  gap: 16px;
}
.footer-bottom p {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12.5px;
  color: rgba(255, 255, 255, 0.4);
}
.footer-bottom-links {
  display: flex;
  gap: 24px;
}
.footer-bottom-links a {
  font-family: 'Inter', Arial, sans-serif;
  font-size: 12.5px;
  color: rgba(255, 255, 255, 0.4);
  text-decoration: none;
  transition: color 0.25s ease;
}
.footer-bottom-links a:hover {
  color: rgba(255, 255, 255, 0.8);
}
@media (max-width: 880px) {
  .site-footer {
    padding: 56px 24px 24px;
  }
  .footer-grid {
    grid-template-columns: 1fr 1fr;
    gap: 36px;
    padding-bottom: 36px;
  }
  .footer-brand {
    grid-column: 1 / -1;
  }
  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
  }
}
