/* Section-specific utilities not in the compiled Tailwind extract */

.border-white\/8 {
  border-color: rgb(255 255 255 / 0.08);
}

.bg-cyan-500\/8 {
  background-color: rgb(6 182 212 / 0.08);
}

.bg-emerald-500\/12 {
  background-color: rgb(16 185 129 / 0.12);
}

.bg-gold-500\/8 {
  background-color: rgb(232 160 21 / 0.08);
}

.bg-emerald-500\/8 {
  background-color: rgb(16 185 129 / 0.08);
}

.max-h-\[32rem\] {
  max-height: 32rem;
}

/* Revolving marquee, used by the trust-logo strip and the reviews carousel.
   Two identical tracks are placed back to back so the loop is seamless; the
   parent uses a mask so logos/cards fade in and out at the edges. */
.marquee-viewport {
  position: relative;
  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-track {
  display: flex;
  width: max-content;
  animation: marquee-scroll var(--marquee-duration, 32s) linear infinite;
}
.marquee-track.marquee-reverse {
  animation-direction: reverse;
}
.marquee-viewport:hover .marquee-track {
  animation-play-state: paused;
}
@keyframes marquee-scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}
@media (prefers-reduced-motion: reduce) {
  .marquee-track {
    animation: none;
  }
}

/* Contact details start as placeholders pointing at the contact form and
   swap in the real mailto/tel/whatsapp values once contact-reveal.js
   confirms the visitor isn't a flagged bot. */
.pk-contact-pending {
  opacity: 0.85;
}

/* ------------------------------------------------------------------
   MOBILE NAV — backdrop + slide panel.

   --pk-header-h is set/updated by nav.js (ResizeObserver on
   #site-header) instead of a hardcoded top offset, so the panel
   always starts exactly where the header currently ends, including
   when the header shrinks its own padding on scroll. Falls back to
   88px (the header's un-scrolled height) if JS hasn't run yet, so
   there's no flash-of-wrong-position before the observer's first
   callback fires.

   Height uses 100dvh (dynamic viewport height), not 100vh, so
   mobile browser chrome (URL bar collapsing/expanding on scroll)
   can't leave the panel taller than the visible viewport or clipped
   under it. A plain 100vh line is declared first as a fallback for
   browsers/in-app webviews that don't support dvh at all - without
   it, height/max-height fall back to unset, the panel grows to fit
   every link, and with body scroll locked while open there's no way
   to reach whatever runs past the bottom of the screen. This, plus
   the backdrop previously using inset:0 and covering the header
   itself (darkening it and stealing the close-tap from the toggle
   button), is what "shows outside view" was actually caused by,
   combined with the stale top offset mentioned above.

   Only transform/opacity are animated (both GPU-composited) instead
   of height/max-height, so open/close stays smooth even on low-end
   devices; visibility/pointer-events are toggled in the same
   transition so the closed panel is fully inert, not just invisible.
   ------------------------------------------------------------------ */

:root {
  --pk-header-h: 88px;
}

.mobile-nav-backdrop {
  position: fixed;
  top: var(--pk-header-h);
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 54;
  background: rgba(11, 11, 15, 0.6);
  opacity: 0;
  visibility: hidden;
  transition: opacity 200ms ease;
}

.mobile-nav-backdrop[data-state="open"] {
  opacity: 1;
  visibility: visible;
}

.mobile-nav-panel {
  position: fixed;
  top: var(--pk-header-h);
  left: 0;
  right: 0;
  /* vh first as a fallback for browsers/in-app webviews that don't
     support dvh, so height never falls back to "unset" and lets
     content run past the bottom of the screen with no way to reach
     it (scroll is locked on body while the panel is open). Browsers
     that understand dvh use the second, more accurate declaration. */
  height: calc(100vh - var(--pk-header-h));
  height: calc(100dvh - var(--pk-header-h));
  z-index: 55;
  overflow-y: auto;
  overscroll-behavior: contain;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-0.5rem);
  transition: opacity 220ms ease, transform 220ms cubic-bezier(0.16, 1, 0.3, 1), visibility 220ms;
}

.mobile-nav-panel[data-state="open"] {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.mobile-nav-panel-inner {
  max-height: calc(100vh - var(--pk-header-h) - 1.5rem);
  max-height: calc(100dvh - var(--pk-header-h) - 1.5rem);
  overflow-y: auto;
}

@media (min-width: 1024px) {
  .mobile-nav-backdrop,
  .mobile-nav-panel {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .mobile-nav-backdrop,
  .mobile-nav-panel,
  .nav-toggle-icon-top,
  .nav-toggle-icon-mid,
  .nav-toggle-icon-bottom {
    transition: none !important;
  }
}

/* Hamburger -> X morph. Lines animate via SVG-space transforms;
   transform-origin: center keeps the rotation pivoting on each
   line's own middle rather than the icon's corner. */
.nav-toggle-icon-top,
.nav-toggle-icon-mid,
.nav-toggle-icon-bottom {
  transform-origin: center;
  transition: transform 200ms ease, opacity 200ms ease;
}

#nav-toggle[aria-expanded="true"] .nav-toggle-icon-top {
  transform: translateY(6px) rotate(45deg);
}

#nav-toggle[aria-expanded="true"] .nav-toggle-icon-mid {
  opacity: 0;
}

#nav-toggle[aria-expanded="true"] .nav-toggle-icon-bottom {
  transform: translateY(-6px) rotate(-45deg);
}