/* ==================================================================
   Localink – Design System (based on Vercel site)
   ================================================================== */

/* 'General Sans' isn't a Google Fonts family (it's from Fontshare) --
   this @import was silently 400ing on every single page, so the whole
   site has actually been rendering in the browser's fallback system font
   the entire time. Plus Jakarta Sans is the closest real match to the
   original's humanist, rounded-terminal character; Archivo gives
   headlines their own sturdier, more structural presence -- fitting a
   directory of verified tradespeople -- instead of reusing the body font
   at a heavier weight. */
@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,300..800;1,300..800&family=Archivo:ital,wght@0,500..800;1,500..800&display=swap');

:root {
  /* ----- Brand colours (from the LocalLink logo: navy blue + green, gold accent) ----- */
  --navy: #063577;
  --navy-light: #0a4a9e;
  --navy-dark: #042352;
  --orange: #3f9c17;
  --orange-light: #6dc94a;
  --orange-dark: #2f7a12;
  --gold: #fdb902;
  --gold-dark: #e0a200;

  /* ----- Base colours (light mode default) ----- */
  --background: #f8f8f9;
  --background-secondary: #ffffff;
  --background-tertiary: #f0f0f2;
  --foreground: #0f1729;
  --foreground-secondary: #374151;
  --foreground-muted: #6b7280;
  --border: #e5e7eb;
  --border-hover: #d1d5db;
  --card-bg: #ffffff;
  --card-shadow: 0 1px 3px rgba(6, 53, 119, 0.08), 0 4px 12px rgba(6, 53, 119, 0.04);
  --card-shadow-hover: 0 4px 12px rgba(6, 53, 119, 0.12), 0 8px 24px rgba(6, 53, 119, 0.08);
  --glass-bg: rgba(255, 255, 255, 0.72);
  --glass-border: rgba(255, 255, 255, 0.18);
  --input-bg: #ffffff;
  --input-border: #d1d5db;
  --overlay: rgba(15, 23, 41, 0.5);
  --success: #10b981;
  --success-bg: #ecfdf5;
  --warning: #f59e0b;
  --warning-bg: #fffbeb;
  --error: #ef4444;
  --error-bg: #fef2f2;
  --info: #3b82f6;
  --info-bg: #eff6ff;
  --star-filled: #fbbf24;
  --star-empty: #d1d5db;

  /* ----- Fonts ----- */
  --font-body: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-display: 'Archivo', system-ui, sans-serif;

  /* ----- Radius hierarchy: one size for everything read as the generic
     "SaaS card" look. Chips/buttons stay tight and precise; cards get a
     touch more room; the hero and other large feature surfaces get the
     most, so scale signals importance instead of every corner looking
     the same. ----- */
  --radius-sm: 0.5rem;
  --radius: 0.75rem;
  --radius-lg: 1.5rem;
}

/* ----- DARK MODE OVERRIDES ----- */
.dark {
  --background: #0f1729;
  --background-secondary: #1a2332;
  --background-tertiary: #1f2a3a;
  --foreground: #f8fafc;
  --foreground-secondary: #cbd5e1;
  --foreground-muted: #94a3b8;
  --border: #2d3b4f;
  --border-hover: #3a4a5f;
  --card-bg: #1a2332;
  --card-shadow: 0 1px 3px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.2);
  --card-shadow-hover: 0 4px 12px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.3);
  --glass-bg: rgba(26, 35, 50, 0.85);
  --glass-border: rgba(255, 255, 255, 0.06);
  --input-bg: #1a2332;
  --input-border: #2d3b4f;
}

/* ----- Base Styles ----- */
* {
  border-color: var(--border);
}

html {
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color-scheme: light dark;
}

body {
  background: var(--background);
  color: var(--foreground);
  font-family: var(--font-body);
  line-height: 1.6;
  overflow-x: hidden;
  transition: background 0.3s, color 0.3s;
}

/* ----- Scrollbar ----- */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
::-webkit-scrollbar-thumb {
  background: var(--foreground-muted);
  border-radius: 999px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::selection {
  background: var(--orange);
  color: #fff;
}

/* ----- Typography ----- */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
}

/* ----- Cards & Containers ----- */
.bg-\[var\(--card-bg\)\] {
  background-color: var(--card-bg);
}
.text-\[var\(--foreground\)\] {
  color: var(--foreground);
}
.text-\[var\(--foreground-muted\)\] {
  color: var(--foreground-muted);
}
.text-\[var\(--orange\)\] {
  color: var(--orange);
}
.bg-\[var\(--orange\)\] {
  background-color: var(--orange);
}
.border-\[var\(--border\)\] {
  border-color: var(--border);
}

/* ----- Buttons (reuse existing classes) ----- */
.btn-primary {
  background-color: var(--orange);
  color: #fff;
  padding: 0.75rem 1.5rem;
  border-radius: var(--radius);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: -0.025em;
  transition: all 0.2s ease;
  box-shadow: 0 4px 0 var(--orange-dark);
  display: inline-block;
  text-align: center;
  border: none;
  cursor: pointer;
}
.btn-primary:hover {
  background-color: var(--orange-dark);
  transform: translateY(-2px);
  box-shadow: 0 2px 0 var(--orange-dark);
}
.btn-primary:active {
  transform: translateY(2px);
  box-shadow: 0 0px 0 var(--orange-dark);
}
.btn-primary:focus-visible, .btn-secondary:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
.btn-primary:disabled, .btn-secondary:disabled {
  cursor: not-allowed;
  transform: none !important;
  filter: grayscale(0.3);
}

.btn-secondary {
  background-color: var(--card-bg);
  border: 2px solid var(--border);
  color: var(--foreground);
  padding: 0.75rem 1.5rem;
  border-radius: var(--radius);
  font-weight: 700;
  text-transform: uppercase;
  transition: all 0.2s ease;
  box-shadow: 0 4px 0 var(--foreground-muted);
  display: inline-block;
  text-align: center;
  cursor: pointer;
}
.btn-secondary:hover {
  transform: translateY(-2px);
  box-shadow: 0 2px 0 var(--foreground-muted);
  border-color: var(--orange);
}
.btn-secondary:active {
  transform: translateY(2px);
  box-shadow: 0 0px 0 var(--foreground-muted);
}

/* ----- Responsive tweaks ----- */
@media (max-width: 640px) {
  .bold-search {
    flex-direction: column;
    align-items: stretch;
    border-radius: 1.5rem;
  }
  .btn-primary, .btn-secondary {
    padding: 0.6rem 1.2rem;
    font-size: 0.9rem;
  }
}
/* ----- Navbar scroll effect ----- */
header {
  transition: background-color 0.3s ease, box-shadow 0.3s ease, backdrop-filter 0.3s ease;
}

header.scrolled {
  background-color: var(--glass-bg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  border-bottom: 1px solid var(--glass-border);
}

.dark header.scrolled {
  background-color: var(--glass-bg);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}

/* Also ensure the navbar stays above content */
header {
  z-index: 50;
}
/* ----- Services dropdown arrow rotation ----- */
#servicesDropdownArrow {
  transition: transform 0.2s ease;
}
#servicesDropdownArrow.rotate-180 {
  transform: rotate(180deg);
}

/* Dropdown menu smooth appearance */
#servicesDropdownMenu {
  transition: opacity 0.2s ease, transform 0.2s ease;
  opacity: 1;
  transform: translateY(0);
}
#servicesDropdownMenu.hidden {
  display: none;
}
/* ========== TOAST NOTIFICATIONS ========== */
.toast-container {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 380px;
  width: 100%;
}

.toast {
  padding: 16px 20px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 500;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
  animation: slideInRight 0.4s ease forwards;
  display: flex;
  align-items: center;
  gap: 12px;
  backdrop-filter: blur(10px);
  border: 1px solid var(--border);
}

.toast-success {
  background: var(--success-bg);
  color: var(--success);
  border-color: var(--success);
}

.toast-error {
  background: var(--error-bg);
  color: var(--error);
  border-color: var(--error);
}

.toast-warning {
  background: var(--warning-bg);
  color: var(--warning);
  border-color: var(--warning);
}

.toast-info {
  background: var(--info-bg);
  color: var(--info);
  border-color: var(--info);
}

.dark .toast-success {
  background: rgba(16, 185, 129, 0.15);
  color: #34d399;
  border-color: rgba(16, 185, 129, 0.3);
}

.dark .toast-error {
  background: rgba(239, 68, 68, 0.15);
  color: #f87171;
  border-color: rgba(239, 68, 68, 0.3);
}

.dark .toast-warning {
  background: rgba(245, 158, 11, 0.15);
  color: #fbbf24;
  border-color: rgba(245, 158, 11, 0.3);
}

.dark .toast-info {
  background: rgba(59, 130, 246, 0.15);
  color: #60a5fa;
  border-color: rgba(59, 130, 246, 0.3);
}

.toast-icon {
  font-size: 20px;
  flex-shrink: 0;
}

.toast-close {
  background: none;
  border: none;
  color: currentColor;
  opacity: 0.6;
  cursor: pointer;
  font-size: 18px;
  margin-left: auto;
  padding: 0 4px;
  transition: opacity 0.2s;
}

.toast-close:hover {
  opacity: 1;
}

@keyframes slideInRight {
  from {
    transform: translateX(120%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

.toast.hiding {
  animation: slideOutRight 0.3s ease forwards;
}

@keyframes slideOutRight {
  to {
    transform: translateX(120%);
    opacity: 0;
  }
}
/* ========== LOADING STATES ========== */
.loading-spinner {
  display: inline-block;
  width: 32px;
  height: 32px;
  border: 3px solid var(--border);
  border-top-color: var(--orange);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
  gap: 16px;
  min-height: 200px;
}

.loading-container p {
  color: var(--foreground-muted);
  font-size: 14px;
}

/* Skeleton loading */
.skeleton {
  background: var(--background-tertiary);
  border-radius: 8px;
  animation: pulse 1.5s ease-in-out infinite;
}

.skeleton-text {
  height: 14px;
  width: 100%;
  margin-bottom: 8px;
}

.skeleton-text.w-75 { width: 75%; }
.skeleton-text.w-50 { width: 50%; }
.skeleton-text.w-25 { width: 25%; }

.skeleton-card {
  padding: 20px;
  background: var(--card-bg);
  border-radius: 16px;
  border: 1px solid var(--border);
}

.skeleton-image {
  height: 160px;
  width: 100%;
  border-radius: 12px;
  margin-bottom: 12px;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}
/* Booking filter buttons */
.booking-filter {
  transition: all 0.2s ease;
  cursor: pointer;
}

.booking-filter.active {
  background-color: var(--orange) !important;
  color: white !important;
  border-color: var(--orange) !important;
}

.booking-filter:hover:not(.active) {
  background-color: var(--background-tertiary);
}

/* ========== GENERAL VISUAL POLISH ========== */
/* Smooth lift-on-hover for cards site-wide (opt-in via class, applied where cards are rendered) */
.rounded-3xl, .rounded-2xl {
  transition: box-shadow 0.25s ease, transform 0.25s ease;
}

/* Focus rings for accessibility on interactive elements that don't already define one */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Links inside body copy get a subtle animated underline instead of an abrupt color snap */
.prose a, main a:not(.btn-primary):not(.btn-secondary) {
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color 0.2s ease;
}

/* Consistent badge sizing across the site (verified, featured, availability, etc.) */
.badge-verified, .badge-premium {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.75rem;
  font-weight: 700;
  padding: 0.25rem 0.65rem;
  border-radius: 999px;
}
.badge-verified {
  background: var(--info-bg);
  color: var(--info);
}
.dark .badge-verified {
  background: rgba(59, 130, 246, 0.15);
  color: #60a5fa;
}
.badge-premium {
  background: linear-gradient(135deg, var(--gold), var(--gold-dark));
  color: #1a1200;
}

/* Smoother section dividers */
hr {
  border-color: var(--border);
  opacity: 0.7;
}

/* ========== NAVIGATION POLISH ========== */
/* Mobile menu slides + fades in smoothly instead of popping open */
#mobileMenu:not(.hidden) {
  animation: mobileMenuSlideDown 0.25s ease-out;
}
@keyframes mobileMenuSlideDown {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Animated underline accent on desktop nav links */
.nav-link::after {
  content: '';
  position: absolute;
  left: 1rem;
  right: 1rem;
  bottom: 0.3rem;
  height: 2px;
  border-radius: 999px;
  background: var(--orange);
  transform: scaleX(0);
  transition: transform 0.2s ease;
}
.nav-link:hover::after,
.nav-link.active::after {
  transform: scaleX(1);
}
.nav-link.active {
  color: var(--foreground) !important;
  background: var(--background-tertiary);
}

/* Bigger, touch-friendly tap feedback for icon buttons in the header */
header button:active, header a[aria-label]:active {
  transform: scale(0.92);
}

/* ========== SCROLL REVEAL (one consistent system, not per-card fades) ==========
   Applied to whole sections via [data-reveal] (see script.js), not to every
   card inside them -- a page scrolling through a dozen identical card
   fade-ins is the single most common "AI-generated" tell. Respects
   prefers-reduced-motion. */
[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.6s ease-out, transform 0.6s ease-out;
}
[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ========== HERO ENTRANCE ==========
   One orchestrated sequence on first load: eyebrow-free headline, then
   subtext, then the search bar, each stepping in slightly after the last.
   This replaces scattered hover/fade effects with a single deliberate
   moment, per the restraint principle -- nothing else on the page moves
   on its own. */
.hero-stagger > * {
  opacity: 0;
  transform: translateY(14px);
  animation: heroStaggerIn 0.7s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.hero-stagger > *:nth-child(1) { animation-delay: 0.05s; }
.hero-stagger > *:nth-child(2) { animation-delay: 0.17s; }
.hero-stagger > *:nth-child(3) { animation-delay: 0.29s; }
.hero-stagger > *:nth-child(4) { animation-delay: 0.41s; }
@keyframes heroStaggerIn {
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-stagger > * {
    opacity: 1;
    transform: none;
    animation: none;
  }
}
/* ========== GLASS THEME (homepage: <body class="glassy">) ==========
   Frosted surfaces only read as glass when there is colour behind them,
   so the page gets a soft, fixed wash of the brand navy/green/gold for the
   translucent cards, stats panel, menus and header to blur. Scoped to
   .glassy so dashboard/admin pages keep their solid, dense surfaces. */
body.glassy::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(40rem 30rem at 8% 18%, rgba(63, 156, 23, 0.16), transparent 70%),
    radial-gradient(36rem 28rem at 92% 40%, rgba(6, 53, 119, 0.16), transparent 70%),
    radial-gradient(32rem 26rem at 30% 92%, rgba(253, 185, 2, 0.14), transparent 70%),
    var(--background);
}
.dark body.glassy::before {
  background:
    radial-gradient(40rem 30rem at 8% 18%, rgba(63, 156, 23, 0.14), transparent 70%),
    radial-gradient(36rem 28rem at 92% 40%, rgba(10, 74, 158, 0.28), transparent 70%),
    radial-gradient(32rem 26rem at 30% 92%, rgba(253, 185, 2, 0.08), transparent 70%),
    var(--background);
}

/* Let the wash show through the plain page sections */
body.glassy main > section.bg-\[var\(--background\)\] {
  background-color: transparent;
}

/* Frosted cards, stats panel and pill buttons */
body.glassy .bg-\[var\(--card-bg\)\],
body.glassy .glass-panel {
  background-color: rgba(255, 255, 255, 0.55);
  backdrop-filter: blur(18px) saturate(160%);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  border-color: rgba(255, 255, 255, 0.7);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8), 0 8px 32px -12px rgba(6, 53, 119, 0.18);
}
body.glassy .glass-panel {
  border: 1px solid rgba(255, 255, 255, 0.7);
}
.dark body.glassy .bg-\[var\(--card-bg\)\],
.dark body.glassy .glass-panel {
  background-color: rgba(26, 35, 50, 0.55);
  border-color: rgba(255, 255, 255, 0.08);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 8px 32px -12px rgba(0, 0, 0, 0.5);
}

/* Hero: brighter, blurred orbs give the search card something to frost */
body.glassy .hero-orbs {
  opacity: 0.55;
  filter: blur(70px);
}
body.glassy #heroSearchForm {
  background-color: rgba(255, 255, 255, 0.78);
  border: 1px solid rgba(255, 255, 255, 0.5);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 20px 50px -12px rgba(0, 0, 0, 0.35);
}
.dark body.glassy #heroSearchForm {
  background-color: rgba(26, 35, 50, 0.6);
  border-color: rgba(255, 255, 255, 0.12);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 20px 50px -12px rgba(0, 0, 0, 0.5);
}

/* Header and dropdowns */
body.glassy header.scrolled {
  background-color: rgba(255, 255, 255, 0.6);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border-bottom: 1px solid rgba(255, 255, 255, 0.6);
}
.dark body.glassy header.scrolled {
  background-color: rgba(15, 23, 41, 0.6);
  border-bottom-color: rgba(255, 255, 255, 0.06);
}
body.glassy #servicesDropdownMenu,
body.glassy #userDropdownMenu,
body.glassy #mobileMenu {
  background-color: rgba(255, 255, 255, 0.75);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
}
.dark body.glassy #servicesDropdownMenu,
.dark body.glassy #userDropdownMenu,
.dark body.glassy #mobileMenu {
  background-color: rgba(26, 35, 50, 0.75);
}

/* Browsers without backdrop-filter: fall back to near-solid surfaces so
   text never sits on a see-through card. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  body.glassy .bg-\[var\(--card-bg\)\],
  body.glassy .glass-panel,
  body.glassy #heroSearchForm { background-color: var(--card-bg); }
}

/* ========== INTERACTIVE FX (fx.js) ==========
   Decorative only; fx.js adds these classes when the browser supports the
   effect and the visitor hasn't asked for reduced motion. */
#heroShader {
  opacity: 0;
  transition: opacity 1.2s ease;
}
.shader-on #heroShader { opacity: 1; }
/* The shader supplies the colour field, so the static orbs (the no-WebGL
   fallback) step back. */
.shader-on .hero-orbs { opacity: 0 !important; }

.fx-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  z-index: 60;
  pointer-events: none;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--orange), var(--gold));
}

.fx-spot {
  background-image: radial-gradient(420px circle at var(--mx, 50%) var(--my, 50%), rgba(255, 255, 255, 0.08), transparent 45%);
}
.fx-tilt {
  transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform;
}
.fx-tilt.is-tilting { transition: transform 0.12s ease-out; }
.fx-magnetic { transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1); }
