/* OpenMobility OS — custom component styles
   Only add things here that Tailwind utility classes cannot express.
   Keep this file small. */

/* Hide Alpine-controlled elements (e.g. the mobile menu) until Alpine
   initializes, so they don't flash on first paint. */
[x-cloak] { display: none !important; }

/* Typographic polish for Inter (with the system-ui fallback). */
body {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: "cv11", "ss01";
  letter-spacing: -0.011em;
}

/* Brand-colored focus ring for keyboard users — cohesion + accessibility.
   Skips elements that manage their own focus styling. */
:focus-visible {
  outline: 2px solid #059669;
  outline-offset: 2px;
  border-radius: 4px;
}

/* Subtle emerald gradient mesh for the landing hero. Awkward to express as
   inline Tailwind utilities, and city-agnostic (pure decoration). */
.hero-gradient {
  background:
    radial-gradient(60rem 30rem at 0% -10%, rgba(16, 185, 129, 0.10), transparent 60%),
    radial-gradient(50rem 25rem at 100% 0%, rgba(5, 150, 105, 0.08), transparent 55%),
    linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
}

/* Animated underline-grow for top-nav links. */
.nav-link {
  position: relative;
  padding-bottom: 2px;
  transition: color 0.15s ease;
}
.nav-link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 100%;
  background: #059669;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.18s ease;
}
.nav-link:hover::after,
.nav-link[aria-current="page"]::after {
  transform: scaleX(1);
}

/* Reusable hover-lift for interactive cards (shadow + slight rise). */
.card-lift {
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}
.card-lift:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 28px -12px rgba(15, 23, 42, 0.18);
}

/* MapLibre popup override */
.maplibregl-popup-content {
  border-radius: 8px;
  font-size: 0.75rem;
  line-height: 1.5;
  max-width: 240px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.12);
}

/* Prose code blocks inside measure descriptions.
   Scoped to .measure-description so it does not override explicitly
   dark-styled terminal blocks on the About page or methodology pages. */
.measure-description.prose pre,
.measure-description .prose pre {
  background: #f1f5f9;
  color: #1e293b;
  border-radius: 6px;
  padding: 0.75rem 1rem;
  font-size: 0.8rem;
  overflow-x: auto;
}

/* Map fullscreen — "map-is-fullscreen" is set by the map page in both the
   native Fullscreen API path and the fixed-position fallback; the fallback
   additionally gets "map-fullscreen-fallback" to fill the viewport itself.
   The shell keeps its flex column (map frame + legend), the frame grows to
   take all remaining height, and the map fills the frame. */
#map-shell.map-is-fullscreen {
  background: #f8fafc;
  padding: 0.75rem;
}
#map-shell.map-is-fullscreen .map-frame {
  flex: 1 1 auto;
  min-height: 0;
}
#map-shell.map-is-fullscreen #map {
  height: 100% !important;
}
#map-shell.map-fullscreen-fallback {
  position: fixed;
  inset: 0;
  z-index: 50; /* above the sticky header (z-40) */
}
html.dark #map-shell.map-is-fullscreen {
  background: #0f172a;
}

/* HTMX loading indicator */
.htmx-indicator {
  display: none;
}
.htmx-request .htmx-indicator {
  display: inline;
}

/* Score bars (in case JS is not available, bars render via inline style anyway) */
.score-bar {
  height: 6px;
  border-radius: 9999px;
  background: #e2e8f0;
  overflow: hidden;
}
.score-bar-fill {
  height: 100%;
  border-radius: 9999px;
  transition: width 0.4s ease;
}

/* ==========================================================================
   Dark mode
   --------------------------------------------------------------------------
   The app styles its ~26 templates with Tailwind utility classes directly
   (no build step). Rather than edit every template, we remap the light
   utility classes the app actually uses to dark equivalents under `html.dark`.
   `!important` makes these win over Tailwind's runtime-injected utilities
   regardless of stylesheet insertion order. Only LIGHT surfaces/text are
   remapped — already-dark utilities (slate-700/800/900 backgrounds, white /
   slate-100 text) are intentionally left alone, as are the meaningful map
   colour scales (layer palette, score/severity gradients).
   ========================================================================== */

html.dark { color-scheme: dark; }

/* Structural chrome (targeted by element to also catch opacity-modified
   utilities like bg-white/85 on the sticky header). */
html.dark body { background-color: #0b1120; color: #e2e8f0; }
html.dark header { background-color: rgba(15, 23, 42, 0.8) !important; border-color: #1e293b !important; }
html.dark footer { background-color: #0f172a !important; border-color: #1e293b !important; }

/* Surfaces */
html.dark .bg-white { background-color: #1e293b !important; }
html.dark .bg-slate-50 { background-color: #0f172a !important; }
html.dark .bg-slate-100 { background-color: #334155 !important; }
html.dark .bg-slate-200 { background-color: #475569 !important; }
html.dark .hover\:bg-white:hover { background-color: #1e293b !important; }
html.dark .hover\:bg-slate-50:hover { background-color: #243244 !important; }
html.dark .hover\:bg-slate-100:hover { background-color: #334155 !important; }
html.dark .hover\:bg-slate-200:hover { background-color: #475569 !important; }

/* Text — remap the dark-on-light scale to a light-on-dark scale */
html.dark .text-slate-950,
html.dark .text-slate-900,
html.dark .text-slate-800 { color: #f1f5f9 !important; }
html.dark .text-slate-700 { color: #e2e8f0 !important; }
html.dark .text-slate-600 { color: #cbd5e1 !important; }
html.dark .text-slate-500 { color: #94a3b8 !important; }
html.dark .text-slate-400 { color: #64748b !important; }
html.dark .hover\:text-slate-950:hover,
html.dark .hover\:text-slate-900:hover,
html.dark .hover\:text-slate-800:hover,
html.dark .hover\:text-slate-700:hover { color: #f8fafc !important; }

/* Borders — default Tailwind border colour + the explicit slate borders */
html.dark *,
html.dark ::before,
html.dark ::after { border-color: #334155; }
html.dark .border-slate-200,
html.dark .border-slate-300 { border-color: #334155 !important; }
html.dark .border-slate-400 { border-color: #475569 !important; }
html.dark .divide-y > :not([hidden]) ~ :not([hidden]) { border-color: #334155 !important; }
html.dark .hover\:border-slate-400:hover { border-color: #64748b !important; }

/* Form controls */
html.dark select,
html.dark input,
html.dark textarea { background-color: #1e293b !important; color: #e2e8f0 !important; border-color: #334155 !important; }
html.dark input::placeholder,
html.dark textarea::placeholder { color: #64748b !important; }

/* Semantic panels & badges — tone the light *-50/*-100 fills down to
   translucent washes and lift the text so they stay legible (not glaring)
   on a dark surface. Status meaning is preserved by hue. */
html.dark .bg-emerald-50,
html.dark .bg-emerald-100,
html.dark .bg-green-100 { background-color: rgba(16, 185, 129, 0.16) !important; }
html.dark .bg-amber-50,
html.dark .bg-amber-100 { background-color: rgba(245, 158, 11, 0.16) !important; }
html.dark .bg-orange-100 { background-color: rgba(249, 115, 22, 0.16) !important; }
html.dark .bg-red-50,
html.dark .bg-red-100 { background-color: rgba(239, 68, 68, 0.16) !important; }
html.dark .bg-blue-50,
html.dark .bg-blue-100 { background-color: rgba(59, 130, 246, 0.16) !important; }
html.dark .bg-brand-50 { background-color: rgba(16, 185, 129, 0.14) !important; }

html.dark .text-emerald-900,
html.dark .text-emerald-800,
html.dark .text-emerald-700,
html.dark .text-green-800 { color: #6ee7b7 !important; }
html.dark .text-amber-900,
html.dark .text-amber-800,
html.dark .text-amber-700,
html.dark .text-amber-600 { color: #fcd34d !important; }
html.dark .text-orange-800 { color: #fdba74 !important; }
html.dark .text-red-900,
html.dark .text-red-800,
html.dark .text-red-700 { color: #fca5a5 !important; }
html.dark .text-blue-900,
html.dark .text-blue-800,
html.dark .text-blue-700 { color: #93c5fd !important; }
html.dark .text-brand-700 { color: #34d399 !important; }

html.dark .border-emerald-200,
html.dark .border-emerald-300 { border-color: rgba(16, 185, 129, 0.4) !important; }
html.dark .border-amber-200,
html.dark .border-amber-300 { border-color: rgba(245, 158, 11, 0.4) !important; }
html.dark .border-red-200 { border-color: rgba(239, 68, 68, 0.4) !important; }
html.dark .border-blue-200 { border-color: rgba(59, 130, 246, 0.4) !important; }
html.dark .border-brand-200,
html.dark .border-brand-300 { border-color: rgba(16, 185, 129, 0.4) !important; }

/* Landing hero gradient reads dark too. */
html.dark .hero-gradient {
  background:
    radial-gradient(60rem 30rem at 0% -10%, rgba(16, 185, 129, 0.14), transparent 60%),
    radial-gradient(50rem 25rem at 100% 0%, rgba(5, 150, 105, 0.10), transparent 55%),
    linear-gradient(180deg, #0b1120 0%, #0f172a 100%);
}

/* MapLibre chrome: popups, controls, attribution, scale. */
html.dark .maplibregl-popup-content {
  background: #1e293b;
  color: #e2e8f0;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45);
}
html.dark .maplibregl-popup-anchor-top .maplibregl-popup-tip { border-bottom-color: #1e293b; }
html.dark .maplibregl-popup-anchor-bottom .maplibregl-popup-tip { border-top-color: #1e293b; }
html.dark .maplibregl-popup-anchor-left .maplibregl-popup-tip { border-right-color: #1e293b; }
html.dark .maplibregl-popup-anchor-right .maplibregl-popup-tip { border-left-color: #1e293b; }
html.dark .maplibregl-popup-close-button { color: #94a3b8; }
html.dark .maplibregl-ctrl-group {
  background: #1e293b;
  box-shadow: 0 0 0 1px rgba(148, 163, 184, 0.25);
}
html.dark .maplibregl-ctrl-group button + button { border-top-color: #334155; }
html.dark .maplibregl-ctrl-group button .maplibregl-ctrl-icon { filter: invert(1) hue-rotate(180deg); }
html.dark .maplibregl-ctrl-scale {
  background: rgba(30, 41, 59, 0.7);
  color: #e2e8f0;
  border-color: #475569;
}
html.dark .maplibregl-ctrl-attrib {
  background: rgba(15, 23, 42, 0.75) !important;
  color: #94a3b8;
}
html.dark .maplibregl-ctrl-attrib a { color: #cbd5e1; }

/* Theme-toggle pill: show the icon/label that matches the current mode.
   Moon + "Dark" in light mode (click → dark); Sun + "Light" in dark mode. */
.theme-icon-sun,
.theme-label-light { display: none; }
html.dark .theme-icon-sun,
html.dark .theme-label-light { display: inline; }
html.dark .theme-icon-moon,
html.dark .theme-label-dark { display: none; }
