/* =============================================================================
 * TownBus — Sunrise Indigo design system (Blade-only build, no Tailwind)
 * Hand-rolled CSS with CSS custom properties so the same tokens
 * are reused across every component. Drop in /resources/views/layouts/app.blade.php
 * via <link rel="stylesheet" href="{{ asset('css/townbus.css') }}">.
 * ========================================================================== */

:root {
  /* =========================================================================
   * Linear / Stripe-style tinted palette.
   *
   * Design philosophy: full-saturation colours appear ONLY as borders, text,
   * and 4-12% tinted backgrounds. Solid saturated fills are reserved for
   * one button class (.btn--cta) and emphasised pills.
   *
   * Every brand colour ships in 5 stops:
   *   -bg     12% tint   — soft button / pill background
   *   -bg-mid  6% tint   — even quieter, used for cards / hover states
   *   (base)            — borders + body text accent
   *   -dim              — hover / pressed state for the base
   *   -text             — high-contrast label sits inside the tint chip
   *                       Each -text passes WCAG AA on its -bg pair.
   * ========================================================================= */

  /* Brand (community green) */
  --color-primary:        #51BB86;
  --color-primary-dim:    #3FA672;
  --color-primary-light:  #6FD39A;
  --color-primary-bg:     rgba(81, 187, 134, 0.12);
  --color-primary-bg-mid: rgba(81, 187, 134, 0.06);
  --color-primary-text:   #2A8A5E;
  --color-primary-soft:   #E6F5EE;   /* legacy alias — solid version of -bg */
  --color-primary-deep:   #2A8A5E;   /* legacy alias */

  /* Accent — orange. Used as the ONE saturated CTA fill (.btn--cta). */
  --color-accent:         #F97E2F;
  --color-accent-dim:     #E36617;
  --color-accent-bg:      rgba(249, 126, 47, 0.12);
  --color-accent-text:    #B14F12;
  --color-accent-soft:    #FEEDDF;
  --color-orange:         #F97E2F;

  /* Info — blue. Used for state pills + info-tinted buttons. */
  --color-info:           #2CB7F9;
  --color-info-dim:       #1F94D1;
  --color-info-bg:        rgba(44, 183, 249, 0.12);
  --color-info-text:      #0F6E9D;
  --color-info-soft:      #DEF1FE;

  /* Violet — restored as a proper purple. Used for "category" / topic
     badges where green/blue would conflict semantically. */
  --color-violet:         #8B5CF6;
  --color-violet-dim:     #7C3AED;
  --color-violet-bg:      rgba(139, 92, 246, 0.12);
  --color-violet-text:    #5B21B6;
  --color-violet-soft:    #EDE5FF;

  /* Semantic — split from primary so "verified" reads as a distinct
     success state, not just more brand colour. */
  --color-success:        #16A34A;   /* darker / more saturated than primary */
  --color-success-bg:     rgba(22, 163, 74, 0.10);
  --color-success-text:   #15803D;
  --color-warning:        #F59E0B;
  --color-warning-bg:     rgba(245, 158, 11, 0.12);
  --color-warning-text:   #92400E;
  --color-error:          #E74C3C;
  --color-error-bg:       rgba(231, 76, 60, 0.10);
  --color-error-text:     #B91C1C;
  --color-danger:         #E74C3C;   /* alias used in some Blade files */

  /* Neutrals — text-low bumped from #A2C5B9 (failed AA) to #6B8A7E (passes). */
  --color-background:     #FDFDFD;
  --color-surface:        #FFFFFF;
  --color-surface-alt:    #F7FAF8;   /* very faint cool-tinted card bg */
  --color-text-high:      #0F172A;
  --color-text-mid:       #475569;
  --color-text-low:       #6B8A7E;   /* WCAG AA on white */
  --color-border:         #E6EDE8;
  --color-border-strong:  #CAD9D0;

  /* Shadows — Stripe/Linear lean tiny and tight, NOT brand-coloured. */
  --shadow-sm:  0 1px 2px rgba(15, 23, 42, 0.04);
  --shadow-md:  0 1px 3px rgba(15, 23, 42, 0.05), 0 4px 12px rgba(15, 23, 42, 0.04);
  --shadow-lg:  0 4px 12px rgba(15, 23, 42, 0.06), 0 16px 32px rgba(15, 23, 42, 0.06);
  --shadow-cta: 0 1px 2px rgba(249, 126, 47, 0.20), 0 4px 12px rgba(249, 126, 47, 0.15);

  /* Operator colours — saturated for badge text, with matching -bg tints. */
  --color-op-mtc:         #51BB86;
  --color-op-tnstc:       #2CB7F9;
  --color-op-metro:       #8B5CF6;   /* back to violet — distinctive */
  --color-op-local-train: #F59E0B;

  /* Border radius — Stripe rounds buttons softly (10px), pills round fully. */
  --radius-sm: 0.5rem;
  --radius:    0.75rem;
  --radius-lg: 1rem;
}

/* ---- Base ---------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  background: var(--color-background);
  color: var(--color-text-high);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Defensive: stop any wide child (header cluster, overflowing card,
     misaligned absolute element) from breaking out and forcing a side
     scroll on phones. Real fixes live in component CSS below. */
  overflow-x: hidden;
}
html { overflow-x: hidden; }
a { color: var(--color-primary); text-decoration: none; }
a:hover { color: var(--color-primary-dim); }
img { max-width: 100%; height: auto; display: block; }
::selection { background: var(--color-primary-soft); color: var(--color-primary-deep); }

h1, h2, h3, h4 { margin: 0 0 0.5rem; color: var(--color-text-high); line-height: 1.2; }
h1 { font-size: clamp(2.25rem, 4.5vw, 3.25rem); font-weight: 800; letter-spacing: -0.02em; }
h2 { font-size: clamp(1.75rem, 3vw, 2.25rem); font-weight: 700; }
h3 { font-size: 1.25rem; font-weight: 700; }
p  { margin: 0 0 1rem; color: var(--color-text-mid); }

/* ---- Layout containers --------------------------------------------------- */

.container { max-width: 72rem; margin: 0 auto; padding: 0 1.5rem; }
.container-sm { max-width: 48rem; margin: 0 auto; padding: 0 1.5rem; }

.stack > * + * { margin-top: 1rem; }
.hstack { display: flex; gap: 0.75rem; align-items: center; }
.spacer { flex: 1; }

/* ---- Header / nav -------------------------------------------------------- */

.site-header {
  position: sticky; top: 0; z-index: 30;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--color-border);
}
.site-header__inner {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1rem 1.5rem;
  max-width: 72rem; margin: 0 auto;
}
.brand { display: inline-flex; align-items: center; gap: 0.5rem; font-weight: 800; color: var(--color-primary-deep); font-size: 1.125rem; letter-spacing: -0.01em; }
.brand__mark {
  display: inline-flex; align-items: center; justify-content: center;
  height: 2.25rem; width: 2.25rem; border-radius: 0.75rem;
  background: var(--color-primary);
  color: white;
}
.nav { display: none; gap: 1.5rem; }
.nav a { color: var(--color-text-mid); font-weight: 500; font-size: 0.9rem; }
.nav a:hover, .nav a.active { color: var(--color-primary); }
@media (min-width: 768px) { .nav { display: flex; } }

/* ---- Hamburger button (mobile-only trigger for the drawer) -------------- */
.hamburger {
  display: none;          /* shown on mobile via media query below */
  width: 2.25rem; height: 2.25rem;
  border: 0; background: transparent;
  cursor: pointer; padding: 0;
  border-radius: 0.5rem;
  flex-direction: column; justify-content: center; align-items: center;
  gap: 0.25rem;
}
.hamburger:hover { background: var(--color-primary-soft); }
.hamburger > span {
  display: block;
  width: 1.25rem; height: 2px; border-radius: 1px;
  background: var(--color-text-high);
  transition: transform 160ms ease, opacity 160ms ease;
}
.hamburger[aria-expanded="true"] > span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.hamburger[aria-expanded="true"] > span:nth-child(2) { opacity: 0; }
.hamburger[aria-expanded="true"] > span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* ---- Slide-out drawer (mobile nav) -------------------------------------- */
.drawer {
  position: fixed; inset: 0; z-index: 60;
}
.drawer[hidden] { display: none; }
.drawer__scrim {
  position: absolute; inset: 0;
  background: rgba(15, 23, 42, 0.45);
  opacity: 0; transition: opacity 200ms ease;
}
.drawer__panel {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(86vw, 22rem);
  background: var(--color-surface);
  box-shadow: -16px 0 32px rgba(15, 23, 42, 0.12);
  transform: translateX(100%);
  transition: transform 200ms ease;
  display: flex; flex-direction: column;
  overflow-y: auto;
}
.drawer--open .drawer__scrim { opacity: 1; }
.drawer--open .drawer__panel { transform: translateX(0); }
.drawer__header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--color-border);
}
.drawer__close {
  border: 0; background: transparent;
  font-size: 1.75rem; line-height: 1;
  width: 2.25rem; height: 2.25rem;
  border-radius: 0.5rem;
  cursor: pointer; color: var(--color-text-mid);
}
.drawer__close:hover { background: var(--color-primary-soft); color: var(--color-primary); }
.drawer__nav { display: flex; flex-direction: column; padding: 0.5rem 0.75rem 1.25rem; }
.drawer__nav-link {
  padding: 0.85rem 1rem;
  border-radius: 0.625rem;
  color: var(--color-text-high);
  font-weight: 600; font-size: 1rem;
  text-decoration: none;
  transition: background 120ms ease;
}
.drawer__nav-link:hover,
.drawer__nav-link.active { background: var(--color-primary-soft); color: var(--color-primary-deep); }
.drawer__nav-link--sub { font-size: 0.85rem; color: var(--color-text-mid); font-weight: 500; padding: 0.6rem 1rem; }
.drawer__divider { height: 1px; background: var(--color-border); margin: 0.5rem 0.5rem; }

/* ---- Mobile header layout -----------------------------------------------
   Goals (per the design pinned on the request):
   - Single top row: brand · spacer · profile · Get-the-app · lang · ham
   - Profile button: icon only (name text hidden)
   - Get-the-app button: icon only (label hidden)
   - Hamburger replaces the wide desktop nav and opens the drawer above
   - Near-you pill hidden (sticky banner + home section cover it)
   ------------------------------------------------------------------------ */
@media (max-width: 767px) {
  .site-header__inner {
    padding: 0.6rem 0.85rem;
    gap: 0.4rem;
    flex-wrap: nowrap;     /* must stay one row */
  }
  .site-header__inner > .hstack.site-header__actions {
    gap: 0.3rem;
    flex-wrap: nowrap;
    justify-content: flex-end;
    min-width: 0;
  }
  .brand { font-size: 1rem; gap: 0.4rem; }
  .brand > img { width: 30px !important; height: 30px !important; }
  .brand > span { white-space: nowrap; }

  /* Hide elements that don't fit the single-row mobile design. */
  #tb-near-pill { display: none !important; }

  /* Hamburger shown only on mobile. */
  .hamburger { display: inline-flex; }

  /* Compact buttons. */
  .site-header .btn {
    padding: 0.4rem 0.65rem !important;
    font-size: 0.78rem !important;
  }
  .site-header [data-locale] {
    padding: 0.3rem 0.5rem !important;
    font-size: 0.72rem !important;
  }

  /* Profile button: hide the name on mobile, keep the icon + caret. */
  .profile-menu__name { display: none; }
  .profile-menu__trigger {
    padding: 0.4rem 0.55rem !important;
    font-size: 0.95rem !important;
  }
  .profile-menu__panel {
    right: 0.5rem;
    max-width: calc(100vw - 1rem);
  }

  /* Get-the-app: icon-only on mobile to save the most horizontal space. */
  .site-header__cta-label { display: none; }
  .site-header__cta { padding: 0.4rem 0.65rem !important; font-size: 0.95rem !important; }

  /* Sign-in button stays text but tighter padding. */
  .site-header__signin { font-size: 0.78rem !important; padding: 0.4rem 0.6rem !important; }
}

/* ---- Buttons ------------------------------------------------------------- *
 *
 * Linear / Stripe-style tinted buttons. No saturated fills — colour appears
 * as tinted background + saturated text + 1px saturated border. The single
 * exception is `.btn--cta` (orange solid fill) which is used at most
 * once per screen for the strongest conversion action.
 *
 *   .btn--primary    — tinted-green default for most "do the thing" actions
 *   .btn--cta        — solid-orange high-conversion action (Sign up, Track now)
 *   .btn--secondary  — soft neutral, used as the quieter sibling
 *   .btn--ghost      — borderless, used in dense card UIs
 * ------------------------------------------------------------------------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.4rem;
  padding: 0.55rem 1rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  font-weight: 600; font-size: 0.9rem;
  line-height: 1.2;
  cursor: pointer; text-decoration: none;
  transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease, box-shadow 120ms ease;
}
.btn:hover { text-decoration: none; }
.btn:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Primary — green tinted bg, green border, green text. */
.btn--primary {
  background: var(--color-primary-bg);
  border-color: rgba(81, 187, 134, 0.40);
  color: var(--color-primary-text);
}
.btn--primary:hover {
  background: rgba(81, 187, 134, 0.18);
  border-color: var(--color-primary);
  color: var(--color-primary-text);
}

/* CTA — the ONE saturated-fill button. Use sparingly: 1 per screen. */
.btn--cta {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: white;
  box-shadow: var(--shadow-cta);
}
.btn--cta:hover {
  background: var(--color-accent-dim);
  border-color: var(--color-accent-dim);
  color: white;
}

/* Secondary — neutral, no brand colour. Used as the quieter sibling. */
.btn--secondary {
  background: var(--color-surface);
  border-color: var(--color-border-strong);
  color: var(--color-text-high);
}
.btn--secondary:hover {
  background: var(--color-surface-alt);
  border-color: var(--color-text-low);
}

/* Ghost — borderless. */
.btn--ghost {
  background: transparent;
  border-color: transparent;
  color: var(--color-text-mid);
}
.btn--ghost:hover {
  background: var(--color-primary-bg-mid);
  color: var(--color-primary-text);
}

.btn--sm  { padding: 0.35rem 0.7rem; font-size: 0.8rem; }
.btn--lg  { padding: 0.75rem 1.4rem; font-size: 1rem; }
.btn--block { width: 100%; }

/* ---- Cards ---------------------------------------------------------------- *
 * Stripe/Linear cards are FLAT — tiny tinted border + minimal shadow.
 * Hover doesn't lift cards anymore (felt twitchy on dense grids); instead
 * the border picks up some brand colour to signal interactivity.
 * ------------------------------------------------------------------------- */

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 1.5rem;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
a.card:hover,
.card[role="button"]:hover { border-color: rgba(81, 187, 134, 0.40); box-shadow: var(--shadow-md); }
.card--flat   { box-shadow: none; }
.card--elevated { box-shadow: var(--shadow-md); border-radius: var(--radius-lg); }

/* ---- Pills / badges ------------------------------------------------------ *
 * Tinted-bg + saturated-text. Same pattern as buttons. Sentence case, not
 * UPPERCASE — Linear / Stripe favour readability over Bauhaus drama.
 * ------------------------------------------------------------------------- */

.pill {
  display: inline-flex; align-items: center; gap: 0.3rem;
  padding: 0.2rem 0.6rem; border-radius: 9999px;
  font-size: 0.75rem; font-weight: 600;
  letter-spacing: 0;          /* drop the uppercase tracking */
  text-transform: none;
  background: var(--color-surface-alt);
  color: var(--color-text-mid);
  border: 1px solid var(--color-border);
}
.pill--primary  { background: var(--color-primary-bg); color: var(--color-primary-text); border-color: transparent; }
.pill--success  { background: var(--color-success-bg); color: var(--color-success-text); border-color: transparent; }
.pill--warning  { background: var(--color-warning-bg); color: var(--color-warning-text); border-color: transparent; }
.pill--accent   { background: var(--color-accent-bg);  color: var(--color-accent-text);  border-color: transparent; }
.pill--violet   { background: var(--color-violet-bg);  color: var(--color-violet-text);  border-color: transparent; }
.pill--info     { background: var(--color-info-bg);    color: var(--color-info-text);    border-color: transparent; }

.dot { display: inline-block; height: 0.4rem; width: 0.4rem; border-radius: 9999px; background: var(--color-success); }
.dot--pulse { animation: pulse 2s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }

/* ---- Icons --------------------------------------------------------------- *
 * The <x-icon> component outputs an SVG with the .icon class. Default
 * vertical-align so icons sit on the baseline next to text without
 * needing a wrapper in every call site.
 * ------------------------------------------------------------------------- */
.icon { display: inline-block; vertical-align: -0.18em; flex: none; }

/* FAQ accordion — chevron flips when <details> is opened. */
.faq-item[open] .faq-item__chevron {
  transform: rotate(180deg);
  color: var(--color-primary);
}
.faq-item summary::-webkit-details-marker { display: none; }   /* hide native triangle on Chrome / Safari */
.faq-item summary { list-style: none; }                          /* and on Firefox */

/* ---- Route map ---------------------------------------------------------- *
 * Container styling for <x-ui.route-map>. Leaflet adds its own classes to
 * the canvas; everything here is the FRAME around it.
 * ------------------------------------------------------------------------- */
.route-map {
  display: block;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--color-border);
  background: var(--color-surface-alt);
}
.route-map__canvas {
  width: 100%;
  height: var(--route-map-h, 360px);
  background: #DDE9E2;             /* loading colour while tiles fetch */
}
.route-map__attribution {
  padding: 0.4rem 0.75rem;
  font-size: 0.7rem;
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
}
/* Leaflet tooltip — re-skin to match the rest of the design system. */
.leaflet-tooltip {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  color: var(--color-text-high);
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 500;
  border-radius: 0.5rem;
  box-shadow: var(--shadow-sm);
  padding: 0.25rem 0.5rem;
}
.route-map__pin { background: none; border: 0; }

/* ---- Live tracking marker + pill ----------------------------------------
 * Live bus markers are a pulsing orange dot floating above the static stop
 * dots. The pill in the top-left of the map shows the live tracking count
 * so users know the map updates itself.
 * ------------------------------------------------------------------------ */
.route-map { position: relative; }   /* anchor the absolutely-positioned pill */

.route-map__live {
  position: absolute;
  top: 0.75rem; left: 0.75rem;
  z-index: 500;                       /* above Leaflet's own controls */
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.3rem 0.65rem;
  border-radius: 9999px;
  background: var(--color-surface);
  border: 1px solid var(--color-accent);
  color: var(--color-accent-text);
  font-size: 0.75rem; font-weight: 600;
  box-shadow: var(--shadow-sm);
}
.route-map__live .dot { background: var(--color-accent); }
.route-map__live--stale {
  opacity: 0.6;
  border-color: var(--color-border);
  color: var(--color-text-mid);
}
.route-map__live--stale .dot { background: var(--color-text-low); animation: none; }

/* Bus marker — Leaflet wraps the SVG in a div; kill the default
   white background/border so just the SVG shows through. */
.route-map__bus { background: none; border: 0; }
.route-map__bus svg { animation: route-map-bus-pulse 1.6s ease-in-out infinite; }
@keyframes route-map-bus-pulse {
  0%, 100% { transform: scale(1);    opacity: 1;   }
  50%      { transform: scale(1.15); opacity: 0.85; }
}

/* ---- Directory "Show more" expander ----------------------------------- *
 * Native <details> styled as a quiet button. The chevron rotates when open
 * via the .faq-item__chevron rules higher up (we reuse the rotation pattern
 * but rebuild the summary look here so the spacing reads as button, not
 * accordion header).
 * ------------------------------------------------------------------------ */
.directory-more summary {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.55rem 1rem;
  border-radius: var(--radius);
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface);
  color: var(--color-text-mid);
  font-weight: 600; font-size: 0.85rem;
  cursor: pointer;
  list-style: none;
  transition: border-color 120ms ease, color 120ms ease, background 120ms ease;
}
.directory-more summary::-webkit-details-marker { display: none; }
.directory-more summary:hover {
  background: var(--color-primary-bg-mid);
  border-color: rgba(81, 187, 134, 0.40);
  color: var(--color-primary-text);
}
.directory-more[open] summary { color: var(--color-primary-text); border-color: rgba(81, 187, 134, 0.40); }
.directory-more[open] summary .icon { transform: rotate(180deg); transition: transform 200ms ease; }

/* Empty-state panel — shown when a route has no coordinates to render
   the map. Frame matches the regular map so the layout doesn't jump. */
.route-map--empty {
  display: flex;
  align-items: center; justify-content: center;
  min-height: 200px;
  padding: 1.5rem;
  text-align: center;
  background: var(--color-surface-alt);
}
.route-map__empty { max-width: 28rem; }
.route-map__empty-icon  { font-size: 2rem; line-height: 1; margin-bottom: 0.5rem; opacity: 0.8; }
.route-map__empty-title { font-size: 1rem; font-weight: 600; margin: 0 0 0.5rem; }
.route-map__empty-body  { font-size: 0.85rem; color: var(--color-text-mid); margin: 0 0 0.5rem; line-height: 1.5; }
.route-map__empty-hint  { font-size: 0.75rem; margin: 0; }

/* Reliability legend — one-line strip explaining polyline / dot tints. */
.route-map__reliability {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.4rem 0.75rem;
  font-size: 0.75rem;
  background: var(--color-surface-alt);
  border-top: 1px solid var(--color-border);
}
.route-map__reliability-swatch {
  width: 0.6rem; height: 0.6rem; border-radius: 9999px; flex: none;
}
.route-map__reliability-swatch--good  { background: var(--color-success); }
.route-map__reliability-swatch--mixed { background: var(--color-warning); }
.route-map__reliability-swatch--bad   { background: var(--color-error); }

/* ---- Hero / mesh background --------------------------------------------- */

.hero {
  position: relative; overflow: hidden;
  /* Subtle radial accents in the new brand palette — green / blue / violet.
     Each one is much fainter than before so the hero whitespace dominates. */
  background:
    radial-gradient(at 18% 12%, rgba(81, 187, 134, 0.10) 0px, transparent 55%),
    radial-gradient(at 82% 12%, rgba(44, 183, 249, 0.08) 0px, transparent 55%),
    radial-gradient(at 50% 96%, rgba(139, 92, 246, 0.06) 0px, transparent 60%),
    var(--color-background);
}
.hero__inner {
  display: grid; gap: 3rem; align-items: center;
  padding: 5rem 1.5rem;
  max-width: 72rem; margin: 0 auto;
}
@media (min-width: 768px) {
  .hero__inner { grid-template-columns: 1fr 1fr; padding-block: 7rem; }
}
.hero h1 { margin-top: 1.25rem; }
.hero__accent {
  /* Tighter gradient: green → blue. The previous green→green sweep was
     visually flat. Brand-on-brand gradients only work when the two stops
     are far apart in hue. */
  background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-info) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.hero__cta { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 2rem; }
.hero__sub { margin-top: 1rem; color: var(--color-text-low); font-size: 0.875rem; }

/* ---- Hero side card (preview of a live route) --------------------------- */

.preview-card { position: relative; }
.preview-card .card { padding: 1.5rem 1.75rem; }
.preview-card__live { font-size: 0.75rem; color: var(--color-text-mid); display: inline-flex; align-items: center; gap: 0.4rem; }
.preview-card__route-no { font-size: 3rem; font-weight: 800; color: var(--color-primary); line-height: 1; }
.preview-card__stops { margin-top: 1.5rem; display: flex; flex-direction: column; gap: 0.7rem; }
.preview-card__stop { display: flex; align-items: center; gap: 0.75rem; }
.preview-card__stop-dot {
  height: 0.75rem; width: 0.75rem; border-radius: 9999px;
  border: 2px solid var(--color-primary); background: white;
}
.preview-card__stop-dot--active { background: var(--color-primary); }
.preview-card__eta { font-size: 0.75rem; color: var(--color-text-mid); font-variant-numeric: tabular-nums; }
.preview-card__credits {
  margin-top: 1.5rem;
  display: flex; align-items: center; justify-content: space-between;
  background: var(--color-primary-soft); border-radius: 0.5rem; padding: 0.75rem;
  font-size: 0.75rem;
}

/* ---- Stats / features / sections ---------------------------------------- */

.section { padding: 5rem 0; }
.section--soft { background: var(--color-primary-soft); }
.section--bordered { border-block: 1px solid var(--color-border); background: var(--color-surface); }
.section__title { text-align: center; }
.section__lead { text-align: center; color: var(--color-text-mid); max-width: 36rem; margin: 0.75rem auto 3rem; }

.stat-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; padding: 3rem 0; max-width: 72rem; margin: 0 auto; padding-inline: 1.5rem; }
@media (min-width: 768px) { .stat-grid { grid-template-columns: repeat(4, 1fr); gap: 2rem; } }
.stat__value { font-size: 2.25rem; font-weight: 800; color: var(--color-primary); }
.stat__label { color: var(--color-text-mid); font-size: 0.875rem; }

.feature-grid { display: grid; gap: 1rem; }
@media (min-width: 640px) { .feature-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 960px) { .feature-grid { grid-template-columns: repeat(3, 1fr); } }
.feature__icon {
  display: inline-flex; align-items: center; justify-content: center;
  height: 2.5rem; width: 2.5rem; border-radius: 0.75rem;
  background: var(--color-primary-soft); color: var(--color-primary);
  margin-bottom: 1rem;
}
.feature h3 { margin-bottom: 0.5rem; }

/* ---- Forms --------------------------------------------------------------- */

.form-group { margin-bottom: 1rem; }
.form-group label { display: block; font-size: 0.8rem; font-weight: 600; color: var(--color-text-mid); margin-bottom: 0.35rem; }
.input, .select, .textarea {
  display: block; width: 100%;
  padding: 0.65rem 0.85rem;
  border-radius: 0.625rem;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface);
  font-size: 0.95rem;
  font-family: inherit;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.input:focus, .select:focus, .textarea:focus {
  outline: 0;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.16);
}
.textarea { min-height: 6rem; resize: vertical; }
.helper { color: var(--color-text-low); font-size: 0.8rem; margin-top: 0.25rem; }
.error { color: var(--color-error); font-size: 0.85rem; margin-top: 0.25rem; }

.checkbox { display: inline-flex; align-items: center; gap: 0.5rem; color: var(--color-text-mid); font-size: 0.875rem; }

/* Search form (two-row grid with auto submit) */
.search-form { display: grid; gap: 0.75rem; padding: 1.5rem; }
.search-form__row {
  display: grid; gap: 0.75rem; align-items: end;
  grid-template-columns: 1fr;
}
@media (min-width: 768px) {
  .search-form__row--primary { grid-template-columns: 1fr 1fr auto; }
  .search-form__row--filters { grid-template-columns: 1fr 1fr 1fr auto; }
}

/* ---- Route results grid -------------------------------------------------- */

.route-grid { display: grid; gap: 1rem; }
@media (min-width: 640px) { .route-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .route-grid { grid-template-columns: repeat(3, 1fr); } }

.route-card { display: block; }
.route-card__head { display: flex; align-items: center; gap: 0.75rem; }
.route-card__no {
  display: inline-flex; align-items: center; justify-content: center;
  height: 3rem; width: 3rem; border-radius: 0.625rem;
  background: var(--color-primary-soft); color: var(--color-primary);
  font-weight: 800; font-size: 0.85rem;
}
.route-card__title { font-weight: 600; }
.route-card__ta { font-size: 0.75rem; color: var(--color-text-low); }
.route-card__journey { margin-top: 0.75rem; font-size: 0.9rem; }
.route-card__journey .arrow { color: var(--color-text-low); margin: 0 0.4rem; }
.route-card__meta { margin-top: 0.75rem; display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }
.route-card__duration {
  margin-left: auto;
  color: var(--color-primary);
  font-weight: 700; font-size: 0.85rem;
  display: inline-flex; align-items: center; gap: 0.25rem;
}
.route-card__foot { margin-top: 0.5rem; font-size: 0.75rem; color: var(--color-text-low); }

/* ---- Profile menu (header dropdown) -------------------------------------- */

.profile-menu { position: relative; }
.profile-menu__trigger { display: inline-flex; align-items: center; gap: 0.15rem; }
.profile-menu__panel {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  min-width: 14rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 0.875rem;
  box-shadow: var(--shadow-lg);
  padding: 0.4rem;
  z-index: 50;
  animation: profile-menu-in 120ms ease-out;
}
.profile-menu__panel[hidden] { display: none; }
@keyframes profile-menu-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.profile-menu__header {
  padding: 0.6rem 0.75rem 0.5rem;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 0.25rem;
}
.profile-menu__item {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.55rem 0.75rem;
  border-radius: 0.5rem;
  color: var(--color-text-high);
  font-size: 0.9rem;
  text-decoration: none;
  transition: background 100ms ease;
}
.profile-menu__item:hover {
  background: var(--color-primary-soft);
  color: var(--color-primary-deep);
}
.profile-menu__item--danger:hover {
  background: var(--color-accent-soft);
  color: var(--color-accent-dim);
}
.profile-menu__divider {
  height: 1px;
  background: var(--color-border);
  margin: 0.35rem 0.25rem;
}

/* ---- Footer -------------------------------------------------------------- */

.site-footer { border-top: 1px solid var(--color-border); background: var(--color-surface); margin-top: 4rem; }
.site-footer__inner { max-width: 72rem; margin: 0 auto; padding: 2.5rem 1.5rem; display: grid; gap: 2rem; }
@media (min-width: 768px) { .site-footer__inner { grid-template-columns: 2fr 1fr 1fr 1fr; } }
.site-footer h4 { font-size: 0.85rem; color: var(--color-text-high); margin-bottom: 0.75rem; }
.site-footer ul { list-style: none; padding: 0; margin: 0; }
.site-footer ul li { margin-bottom: 0.5rem; font-size: 0.875rem; }
.site-footer ul a { color: var(--color-text-mid); }
.site-footer ul a:hover { color: var(--color-primary); }
.site-footer__base {
  border-top: 1px solid var(--color-border);
  padding: 1.25rem; text-align: center;
  font-size: 0.75rem; color: var(--color-text-low);
}

/* =============================================================================
 * Tamil overrides — applied when the document is html[lang="ta"].
 * Tamil characters are taller than Latin (vertical strokes + diacritics) and
 * Tamil words run 20–40% longer than English equivalents. Without these
 * tweaks the hero h1 overflows, nav items wrap awkwardly, and headlines
 * lose their visual rhythm. None of this affects the English layout.
 * ========================================================================= */

html[lang="ta"] body {
  /* Noto Sans Tamil first so all-Tamil text uses one consistent font; falls
   * back to Inter for occasional Latin words mixed into Tamil pages. */
  font-family: 'Noto Sans Tamil', 'Inter', system-ui, sans-serif;
  line-height: 1.7;            /* Tamil needs more breathing room vertically. */
}

/* Headings: drop the negative letter-spacing (Tamil doesn't tolerate it),
 * grow line-height so diacritics don't clip, scale font-size down ~10–15%
 * since each glyph already feels heavier. */
html[lang="ta"] h1 {
  font-size: clamp(1.9rem, 4vw, 2.75rem);
  line-height: 1.35;
  letter-spacing: 0;
  font-weight: 700;   /* 700 reads "extra-bold" in Tamil; back off from 800. */
}
html[lang="ta"] h2 {
  font-size: clamp(1.5rem, 2.75vw, 2rem);
  line-height: 1.4;
  letter-spacing: 0;
  font-weight: 600;
}
html[lang="ta"] h3 { font-size: 1.15rem; line-height: 1.45; font-weight: 600; }
html[lang="ta"] h4 { font-size: 0.95rem; }

/* Buttons: keep a single line where possible, but allow word-wrap inside the
 * coral CTA — "உங்கள் பேருந்தைக் கண்டுபிடிக்க" needs the room. */
html[lang="ta"] .btn {
  white-space: normal;
  line-height: 1.3;
  font-weight: 600;
}

/* Nav: more inter-item space + allow wrap so "எப்படி செயல்படுகிறது" doesn't
 * crowd "கேள்வி பதில்". Falls back gracefully on narrow viewports. */
html[lang="ta"] .nav {
  gap: 1.5rem;
  flex-wrap: wrap;
}

/* Pills/badges: drop the uppercase + letter-spacing — Tamil has no case. */
html[lang="ta"] .pill {
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.78rem;
  padding: 0.25rem 0.7rem;
}

/* Hero accent gradient line — slightly looser leading so the second line
 * doesn't crowd the first. */
html[lang="ta"] .hero h1 br + .hero__accent {
  display: inline-block;
  margin-top: 0.25rem;
}

/* Form labels read more clearly with a touch more weight in Tamil. */
html[lang="ta"] .form-group label {
  font-weight: 600;
}

/* Card titles use h3, already adjusted above. Card descriptions get a
 * tighter line-height so cards don't grow vertically. */
html[lang="ta"] .card p {
  line-height: 1.6;
  font-size: 0.95rem;
}

/* Footer columns: more breathing room since column widths are fixed by grid
 * but Tamil link text needs room not to wrap mid-word. */
html[lang="ta"] .site-footer__inner ul li {
  margin-bottom: 0.7rem;
  line-height: 1.5;
}

/* Stats numbers stay Latin-only (numerals look the same) — but the labels
 * are Tamil, so reduce the label size slightly and use Tamil font. */
html[lang="ta"] .stat__label {
  font-size: 0.8rem;
  font-family: 'Noto Sans Tamil', 'Inter', system-ui, sans-serif;
}

/* The TownBus brand mark never translates — force Inter so the wordmark
 * always reads the same regardless of locale. */
.brand span:last-child {
  font-family: 'Inter', system-ui, sans-serif;
}

/* ---- Utility helpers ----------------------------------------------------- */

.text-center { text-align: center; }
.text-mid    { color: var(--color-text-mid); }
.text-low    { color: var(--color-text-low); }
.text-primary { color: var(--color-primary); }
.text-accent { color: var(--color-accent); }
.muted-line  { height: 1px; background: linear-gradient(90deg, transparent, var(--color-border-strong), transparent); margin: 2rem 0; }
.mt-2 { margin-top: 0.5rem; } .mt-4 { margin-top: 1rem; } .mt-6 { margin-top: 1.5rem; } .mt-8 { margin-top: 2rem; }
.mb-2 { margin-bottom: 0.5rem; } .mb-4 { margin-bottom: 1rem; }
.flex-wrap { flex-wrap: wrap; }
.gap-2 { gap: 0.5rem; } .gap-4 { gap: 1rem; }

/* ============================================================
 * Business directory (/business) — discovery hub.
 * Mobile-first: hero stacks, category rail scrolls horizontally,
 * business grid is 1-up → 2-up → 3-up. Skeletons reserve layout
 * during the lazy near-you fetch so CLS stays at 0.
 * ============================================================ */
.visually-hidden {
    position: absolute; width: 1px; height: 1px; padding: 0;
    margin: -1px; overflow: hidden; clip: rect(0,0,0,0);
    white-space: nowrap; border: 0;
}

.biz-page { padding-bottom: 3rem; }

/* Hero — soft tinted block, sticky search not used here to keep
   FCP clean. The search input sits inside a flex pill with the
   submit button on the right; collapses to stacked on narrow. */
.biz-hero {
    background:
        radial-gradient(ellipse 80% 60% at 20% 0%, var(--color-primary-bg) 0%, transparent 70%),
        radial-gradient(ellipse 60% 50% at 100% 0%, var(--color-info-bg) 0%, transparent 70%),
        var(--color-background);
    padding-block: 2rem 2.5rem;
    border-bottom: 1px solid var(--color-border);
}
.biz-hero__inner { display: flex; flex-direction: column; gap: 1.25rem; }
.biz-hero__intro { max-width: 38rem; }
.biz-hero__title { font-size: 1.75rem; margin-top: 0.5rem; letter-spacing: -0.01em; }
.biz-hero__sub   { color: var(--color-text-mid); margin: 0.5rem 0 0; font-size: 0.95rem; }
@media (min-width: 640px) {
    .biz-hero__title { font-size: 2.25rem; }
}

.biz-hero__search {
    display: flex; align-items: center; gap: 0.5rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border-strong);
    border-radius: 9999px;
    padding: 0.35rem 0.4rem 0.35rem 1rem;
    box-shadow: var(--shadow-sm);
    max-width: 36rem;
}
.biz-hero__search:focus-within {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--color-primary-bg);
}
.biz-hero__search-icon { color: var(--color-text-low); display: inline-flex; }
.biz-hero__search input[type="search"] {
    flex: 1; border: 0; outline: 0; background: transparent;
    font-size: 0.95rem; min-width: 0; padding: 0.5rem 0;
    color: var(--color-text-high);
}
.biz-hero__search input::-webkit-search-cancel-button { -webkit-appearance: none; }

.biz-hero__quick { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.biz-hero__quick .btn { gap: 0.4rem; }

/* Section scaffolding — every directory section uses the same head row */
.biz-section { padding-block: 1.75rem; }
.biz-section--soft     { background: var(--color-surface-alt); }
.biz-section--bordered { border-block: 1px solid var(--color-border); background: var(--color-surface); }
.biz-section__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; margin-bottom: 1rem;
}
.biz-section__head h2 { font-size: 1.15rem; margin: 0; }
.biz-section__head h2 strong { color: var(--color-primary-text); font-weight: 700; }
.biz-section__more {
    color: var(--color-primary-text); font-weight: 600; font-size: 0.85rem;
    display: inline-flex; align-items: center; gap: 0.25rem; white-space: nowrap;
}
.biz-section__more:hover { color: var(--color-primary); }

/* Category rail — horizontal scroll on mobile (snap), wrap on wider. */
.cat-rail {
    display: flex; gap: 0.75rem;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 0.5rem;
    margin: 0 -1rem; padding-inline: 1rem;
    scrollbar-width: thin;
}
.cat-rail > * { scroll-snap-align: start; flex: 0 0 auto; }
.cat-rail::-webkit-scrollbar { height: 4px; }
.cat-rail::-webkit-scrollbar-thumb { background: var(--color-border-strong); border-radius: 9999px; }

.cat-grid {
    display: grid; gap: 0.75rem;
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 640px)  { .cat-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 960px)  { .cat-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.cat-chip {
    display: flex; align-items: center; gap: 0.6rem;
    padding: 0.6rem 0.85rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    color: var(--color-text-high);
    min-width: 9rem;
    transition: border-color 120ms, box-shadow 120ms, transform 120ms;
}
.cat-chip:hover {
    border-color: var(--color-primary);
    box-shadow: var(--shadow-md);
    color: var(--color-text-high);
    transform: translateY(-1px);
}
.cat-chip__icon {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    width: 2.25rem; height: 2.25rem; border-radius: 9999px;
    background: var(--color-primary-bg);
    color: var(--color-primary-text);
    flex: 0 0 auto;
    font-size: 0.8rem; font-weight: 700; letter-spacing: 0.02em;
}
/* Initials sit beneath; the glyph (if rendered) covers them. When the
   icon name isn't registered, <x-ui.icon> renders nothing and the
   initials remain visible — so every chip always has a visual identity. */
.cat-chip__initials {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    color: var(--color-primary-text);
}
.cat-chip__glyph {
    position: relative; z-index: 1;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--color-primary-bg);
    width: 100%; height: 100%; border-radius: inherit;
}
.cat-chip__label { display: flex; flex-direction: column; min-width: 0; }
.cat-chip__name  { font-weight: 600; font-size: 0.9rem; line-height: 1.1; }
.cat-chip__count { font-size: 0.75rem; color: var(--color-text-low); margin-top: 0.15rem; }

/* Business grid + card — image header, title, meta, action row. */
.biz-grid {
    display: grid; gap: 1rem;
    grid-template-columns: 1fr;
}
@media (min-width: 600px)  { .biz-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 960px)  { .biz-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1280px) { .biz-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.biz-card {
    display: flex; flex-direction: column;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    transition: border-color 120ms, box-shadow 120ms, transform 120ms;
}
.biz-card:hover {
    border-color: var(--color-primary);
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
}
.biz-card__media {
    position: relative; display: block;
    aspect-ratio: 16 / 10;
    background: var(--color-surface-alt);
    overflow: hidden;
}
.biz-card__media img {
    width: 100%; height: 100%; object-fit: cover; display: block;
    transition: transform 250ms;
}
.biz-card:hover .biz-card__media img { transform: scale(1.03); }
.biz-card__media-fallback {
    display: flex; align-items: center; justify-content: center;
    width: 100%; height: 100%;
    color: var(--color-primary);
    background: linear-gradient(135deg, var(--color-primary-bg) 0%, var(--color-info-bg) 100%);
}
.biz-card__badge {
    position: absolute; top: 0.5rem; left: 0.5rem;
    display: inline-flex; align-items: center; gap: 0.25rem;
    background: rgba(255,255,255,0.92);
    color: var(--color-success-text);
    font-size: 0.7rem; font-weight: 600;
    padding: 0.2rem 0.5rem; border-radius: 9999px;
    backdrop-filter: blur(4px);
}
.biz-card__body { padding: 0.75rem 0.9rem 0.9rem; display: flex; flex-direction: column; gap: 0.4rem; }
.biz-card__title {
    font-weight: 700; font-size: 0.95rem; line-height: 1.25;
    color: var(--color-text-high);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
}
.biz-card__title:hover { color: var(--color-primary-text); }
.biz-card__meta {
    display: inline-flex; align-items: center; gap: 0.3rem; flex-wrap: wrap;
    font-size: 0.8rem; color: var(--color-text-mid);
}
.biz-card__dot   { color: var(--color-text-low); }
.biz-card__place { color: var(--color-text-low); }
.biz-card__actions {
    display: flex; gap: 0.4rem; flex-wrap: wrap;
    margin-top: 0.4rem; padding-top: 0.5rem;
    border-top: 1px dashed var(--color-border);
}
.biz-card__action {
    display: inline-flex; align-items: center; gap: 0.3rem;
    padding: 0.3rem 0.55rem;
    border-radius: 9999px;
    font-size: 0.75rem; font-weight: 600;
    background: var(--color-primary-bg-mid);
    color: var(--color-primary-text);
    border: 1px solid transparent;
}
.biz-card__action:hover {
    background: var(--color-primary-bg);
    color: var(--color-primary-text);
}
.biz-card__action--wa {
    background: rgba(37, 211, 102, 0.12);
    color: #128C7E;
}
.biz-card__action--wa:hover { background: rgba(37, 211, 102, 0.20); color: #075E54; }

/* Skeleton — reserves layout while the near-you JSON resolves */
.biz-card--skeleton { pointer-events: none; }
.biz-card__media--skeleton {
    background: linear-gradient(90deg, var(--color-surface-alt) 0%, var(--color-border) 50%, var(--color-surface-alt) 100%);
    background-size: 200% 100%;
    animation: biz-shimmer 1.4s ease-in-out infinite;
}
.skeleton-line {
    height: 0.7rem; border-radius: 4px; width: 70%;
    background: linear-gradient(90deg, var(--color-surface-alt) 0%, var(--color-border) 50%, var(--color-surface-alt) 100%);
    background-size: 200% 100%;
    animation: biz-shimmer 1.4s ease-in-out infinite;
}
.skeleton-line--lg { height: 0.9rem; width: 90%; margin-bottom: 0.4rem; }
@keyframes biz-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* Reduced motion — kill the shimmer animation. */
@media (prefers-reduced-motion: reduce) {
    .biz-card__media--skeleton,
    .skeleton-line { animation: none; }
    .biz-card:hover { transform: none; }
    .biz-card:hover .biz-card__media img { transform: none; }
}

/* ============================================================
 * Horizontal scroll rails (.biz-rail / .review-rail).
 * Mobile: each card is ~78% of viewport, snap-aligned to the
 * left edge — feels like Swiggy / Netflix discovery.
 * Desktop: 4 cards fit comfortably, rail bleeds 1rem each side
 * to keep edge cards from butting against the container.
 * ============================================================ */
.biz-rail,
.review-rail {
    display: flex; gap: 0.85rem;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    padding: 0.25rem 1rem 0.75rem;
    margin: 0 -1rem;
    scrollbar-width: thin;
}
.biz-rail > *,
.review-rail > * { scroll-snap-align: start; flex: 0 0 auto; }

/* Card sizing inside a rail — slightly tighter than the standalone grid */
.biz-rail .biz-card     { width: 78vw; max-width: 18rem; }
.review-rail .review-card { width: 80vw; max-width: 20rem; }
@media (min-width: 600px) {
    .biz-rail .biz-card     { width: 17rem; }
    .review-rail .review-card { width: 19rem; }
}

.biz-rail::-webkit-scrollbar,
.review-rail::-webkit-scrollbar { height: 4px; }
.biz-rail::-webkit-scrollbar-thumb,
.review-rail::-webkit-scrollbar-thumb { background: var(--color-border-strong); border-radius: 9999px; }

/* Variant pills on the card media — bottom-left so they don't clash
   with the verified badge (top-left). */
.biz-card__pill {
    position: absolute; bottom: 0.5rem; left: 0.5rem;
    display: inline-flex; align-items: center; gap: 0.25rem;
    padding: 0.2rem 0.55rem;
    border-radius: 9999px;
    font-size: 0.7rem; font-weight: 600;
    background: rgba(15, 23, 42, 0.7);
    color: white;
    backdrop-filter: blur(6px);
}
.biz-card__pill--trending { background: rgba(249, 126, 47, 0.92); }
.biz-card__pill--verified { background: rgba(22, 163, 74, 0.92); }
.biz-card__pill--time     { background: rgba(44, 183, 249, 0.92); }

/* Section-head icon alignment (h2 with an inline icon before the text) */
.biz-section__head h2 {
    display: inline-flex; align-items: center; gap: 0.4rem;
}
.biz-section__head h2 .icon { color: var(--color-primary); }
.biz-section__sub {
    font-size: 0.9rem; color: var(--color-text-mid); font-weight: 600;
    margin: 0.5rem 0 0.75rem; text-transform: uppercase; letter-spacing: 0.05em;
}

/* Review card — sits inside .review-rail */
.review-card {
    display: flex; flex-direction: column; gap: 0.6rem;
    padding: 0.9rem 1rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}
.review-card__head { display: flex; align-items: center; gap: 0.6rem; }
.review-card__avatar {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2rem; height: 2rem; border-radius: 9999px;
    background: var(--color-primary-bg); color: var(--color-primary-text);
    font-weight: 700; font-size: 0.85rem; flex: 0 0 auto;
}
.review-card__who { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.review-card__name { font-weight: 600; font-size: 0.85rem; color: var(--color-text-high); }
.review-card__when { font-size: 0.7rem; color: var(--color-text-low); }
.review-card__stars { display: inline-flex; gap: 0.05rem; font-size: 0.85rem; line-height: 1; color: var(--color-border-strong); }
.review-card__star.is-on { color: var(--color-accent); }
.review-card__body {
    font-size: 0.85rem; color: var(--color-text-mid); margin: 0;
    line-height: 1.45;
    display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;
    overflow: hidden;
}
.review-card__listing {
    display: inline-flex; align-items: center; gap: 0.3rem;
    font-size: 0.75rem; font-weight: 600;
    color: var(--color-primary-text);
    padding: 0.3rem 0.5rem; border-radius: 9999px;
    background: var(--color-primary-bg-mid);
    align-self: flex-start;
}
.review-card__listing:hover { background: var(--color-primary-bg); color: var(--color-primary-text); }

/* Animated placeholder — typing cursor. The JS swaps the text;
   CSS just paints the blinking | when the input is unfocused. */
.biz-hero__search input[type="search"]::placeholder { transition: opacity 200ms; }

/* ============================================================
 * Progressive render — below-the-fold sections.
 * `content-visibility: auto` tells the browser it can skip layout
 * and paint for offscreen sections, hydrating them only when they
 * approach the viewport. Big LCP/TBT win on long pages.
 * `contain-intrinsic-size` keeps scrollbar geometry stable so the
 * page height isn't jumping as sections hydrate.
 * ============================================================ */
.biz-section--defer {
    content-visibility: auto;
    contain-intrinsic-size: 1px 480px;
}

/* ============================================================
 * District discovery rail — visual cards (not text-only).
 * Each card has a gradient cover with the district initial and a
 * count badge bottom-right; the body below carries name + count.
 * 6-colour palette cycled by district id for visual variety
 * without an admin uploading covers.
 * ============================================================ */
.district-rail {
    display: flex; gap: 0.85rem;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    padding: 0.25rem 1rem 0.75rem;
    margin: 0 -1rem;
    scrollbar-width: thin;
}
.district-rail::-webkit-scrollbar { height: 4px; }
.district-rail::-webkit-scrollbar-thumb { background: var(--color-border-strong); border-radius: 9999px; }
/* Wrap variant — used inside the collapsed "Show all" drawer where
   horizontal scroll inside a scrollable area is awkward. */
.district-rail--wrap {
    flex-wrap: wrap; overflow: visible; scroll-snap-type: none;
    margin: 0; padding: 0;
}

.district-card {
    flex: 0 0 auto;
    width: 9.5rem;
    scroll-snap-align: start;
    display: flex; flex-direction: column;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    color: var(--color-text-high);
    transition: border-color 120ms, box-shadow 120ms, transform 120ms;
}
.district-rail--wrap .district-card { width: 9.5rem; }
.district-card:hover {
    border-color: var(--color-primary);
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
    color: var(--color-text-high);
}
.district-card__cover {
    position: relative;
    aspect-ratio: 1 / 1;
    display: flex; align-items: center; justify-content: center;
    color: rgba(255, 255, 255, 0.95);
    font-weight: 800;
    overflow: hidden;
}
.district-card__cover::before {
    content: '';
    position: absolute; inset: 0;
    background-image: radial-gradient(circle at 30% 20%, rgba(255,255,255,0.25) 0%, transparent 60%);
    pointer-events: none;
}
.district-card__initial {
    font-size: 2.5rem; line-height: 1;
    letter-spacing: -0.02em;
    text-shadow: 0 2px 8px rgba(0,0,0,0.15);
}
.district-card__count-badge {
    position: absolute; bottom: 0.4rem; right: 0.4rem;
    min-width: 1.4rem; height: 1.4rem; padding: 0 0.4rem;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.95);
    color: var(--color-text-high);
    font-size: 0.7rem; font-weight: 700;
    box-shadow: 0 1px 3px rgba(0,0,0,0.12);
}
.district-card__body { padding: 0.55rem 0.7rem 0.7rem; }
.district-card__name {
    font-weight: 700; font-size: 0.85rem; line-height: 1.2;
    color: var(--color-text-high);
    display: flex; align-items: center; gap: 0.25rem;
}
.district-card__home { color: var(--color-accent); font-size: 1rem; line-height: 0; }
.district-card__ta  { font-family: 'Noto Sans Tamil', sans-serif; font-size: 0.7rem; color: var(--color-text-low); margin-top: 0.1rem; }
.district-card__count { font-size: 0.7rem; color: var(--color-text-low); margin-top: 0.25rem; }

/* 6-colour gradient palette — deterministic from district id.
   All chosen for AAA contrast against the white initial. */
.district-card--p0 .district-card__cover { background: linear-gradient(135deg, #51BB86 0%, #2A8A5E 100%); }
.district-card--p1 .district-card__cover { background: linear-gradient(135deg, #F97E2F 0%, #B14F12 100%); }
.district-card--p2 .district-card__cover { background: linear-gradient(135deg, #2CB7F9 0%, #0F6E9D 100%); }
.district-card--p3 .district-card__cover { background: linear-gradient(135deg, #8B5CF6 0%, #5B21B6 100%); }
.district-card--p4 .district-card__cover { background: linear-gradient(135deg, #F59E0B 0%, #92400E 100%); }
.district-card--p5 .district-card__cover { background: linear-gradient(135deg, #EC4899 0%, #9D174D 100%); }

@media (prefers-reduced-motion: reduce) {
    .district-card:hover { transform: none; }
}

/* ============================================================
 * Event discovery cards (/events).
 * Same overall shape as .biz-card but the cover gets a corner
 * date pill (big day-of-month) and a category chip — same
 * visual treatment as BookMyShow / Eventbrite.
 * Re-uses .biz-rail and .biz-section--defer.
 * ============================================================ */
.event-card {
    flex: 0 0 auto;
    width: 78vw; max-width: 18rem;
    display: flex; flex-direction: column;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    transition: border-color 120ms, box-shadow 120ms, transform 120ms;
}
@media (min-width: 600px) { .event-card { width: 17rem; } }

.event-card:hover {
    border-color: var(--color-violet);
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
}
.event-card__media {
    position: relative; display: block;
    aspect-ratio: 16 / 10;
    background: var(--color-surface-alt);
    overflow: hidden;
}
.event-card__media img {
    width: 100%; height: 100%; object-fit: cover; display: block;
    transition: transform 250ms;
}
.event-card:hover .event-card__media img { transform: scale(1.03); }
.event-card__media-fallback {
    display: flex; align-items: center; justify-content: center;
    width: 100%; height: 100%;
    color: var(--color-violet);
    background: linear-gradient(135deg, var(--color-violet-bg) 0%, var(--color-primary-bg) 100%);
}
/* Calendar-style date pill — top-left. Two-row stacked layout
   (month abbrev over big day-of-month) mimics a tear-off calendar. */
.event-card__date {
    position: absolute; top: 0.55rem; left: 0.55rem;
    display: flex; flex-direction: column; align-items: center;
    min-width: 2.6rem;
    padding: 0.15rem 0.45rem 0.3rem;
    border-radius: 0.55rem;
    background: rgba(255, 255, 255, 0.96);
    color: var(--color-text-high);
    box-shadow: 0 2px 8px rgba(15, 23, 42, 0.12);
    line-height: 1;
    backdrop-filter: blur(4px);
}
.event-card__date-month {
    font-size: 0.6rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.08em; color: var(--color-accent-text);
}
.event-card__date-day {
    font-size: 1.35rem; font-weight: 800; margin-top: 0.05rem;
    letter-spacing: -0.02em;
}
/* Category pill — top-right. Uses the standard .pill colour scheme
   passed in by the partial (.pill--violet, etc.) */
.event-card__cat {
    position: absolute; top: 0.55rem; right: 0.55rem;
    backdrop-filter: blur(4px);
}

.event-card__body { padding: 0.75rem 0.9rem 0.9rem; display: flex; flex-direction: column; gap: 0.5rem; }
.event-card__title {
    font-weight: 700; font-size: 0.95rem; line-height: 1.25;
    color: var(--color-text-high);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
}
.event-card__title:hover { color: var(--color-violet-text); }
.event-card__meta {
    display: inline-flex; align-items: center; gap: 0.3rem; flex-wrap: wrap;
    font-size: 0.78rem; color: var(--color-text-mid);
}
.event-card__when,
.event-card__where { display: inline-flex; align-items: center; gap: 0.25rem; }
.event-card__when  { color: var(--color-violet-text); font-weight: 600; }
.event-card__dot   { color: var(--color-text-low); }

.event-card__actions {
    display: flex; gap: 0.4rem; flex-wrap: wrap;
    margin-top: 0.4rem; padding-top: 0.5rem;
    border-top: 1px dashed var(--color-border);
}
.event-card__action {
    display: inline-flex; align-items: center; gap: 0.3rem;
    padding: 0.3rem 0.55rem;
    border-radius: 9999px;
    font-size: 0.75rem; font-weight: 600;
    background: var(--color-violet-bg);
    color: var(--color-violet-text);
    border: 1px solid transparent;
    cursor: pointer;
}
.event-card__action:hover {
    background: var(--color-violet-bg);
    color: var(--color-violet-text);
    filter: brightness(0.95);
}
.event-card__action--share {
    background: var(--color-primary-bg);
    color: var(--color-primary-text);
}

.event-card--skeleton { pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
    .event-card:hover { transform: none; }
    .event-card:hover .event-card__media img { transform: none; }
}

/* Free / paid + verified overlays on the event card cover.
   Positions chosen so nothing overlaps: date top-left, category
   top-right, price bottom-left, verified bottom-right. */
.event-card__price {
    position: absolute; bottom: 0.5rem; left: 0.5rem;
    padding: 0.2rem 0.55rem;
    border-radius: 9999px;
    font-size: 0.7rem; font-weight: 700; letter-spacing: 0.02em;
    backdrop-filter: blur(4px);
}
.event-card__price--free { background: rgba(22, 163, 74, 0.92); color: white; }
.event-card__price--paid { background: rgba(15, 23, 42, 0.78); color: white; }
.event-card__verified {
    position: absolute; bottom: 0.5rem; right: 0.5rem;
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.5rem; height: 1.5rem; border-radius: 9999px;
    background: rgba(255, 255, 255, 0.95);
    color: var(--color-success-text);
    box-shadow: 0 1px 3px rgba(0,0,0,0.15);
}
.event-card__distance {
    display: inline-flex; align-items: center;
    color: var(--color-text-low);
    font-size: 0.75rem; font-weight: 500;
}

/* ============================================================
 * Top contributors strip — small horizontal rail of cards
 * showing who has submitted the most events. Lightweight; no
 * avatars yet (we don't store one), uses initial in a coloured
 * circle like the review-card avatar.
 * ============================================================ */
.contributor-rail {
    display: flex; gap: 0.6rem;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    padding: 0.25rem 1rem 0.75rem;
    margin: 0 -1rem;
    scrollbar-width: thin;
}
.contributor-rail::-webkit-scrollbar { height: 4px; }
.contributor-rail::-webkit-scrollbar-thumb { background: var(--color-border-strong); border-radius: 9999px; }

.contributor {
    flex: 0 0 auto;
    scroll-snap-align: start;
    display: flex; align-items: center; gap: 0.5rem;
    padding: 0.5rem 0.85rem 0.5rem 0.5rem;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 9999px;
    box-shadow: var(--shadow-sm);
}
.contributor__avatar {
    display: inline-flex; align-items: center; justify-content: center;
    width: 2rem; height: 2rem; border-radius: 9999px;
    background: var(--color-primary-bg);
    color: var(--color-primary-text);
    font-weight: 700; font-size: 0.85rem;
}
.contributor__name  { font-weight: 600; font-size: 0.85rem; color: var(--color-text-high); }
.contributor__count { font-size: 0.7rem; color: var(--color-text-low); display: block; }
.contributor--first .contributor__avatar { background: var(--color-accent-bg); color: var(--color-accent-text); }
.contributor--first::before {
    content: '🥇'; margin-right: 0.1rem;
}

/* ============================================================
 * Event map view (/events/map) — Leaflet container + filter bar.
 * Map fills the viewport below the filter row so the page feels
 * like a discovery surface, not a marketing page.
 * ============================================================ */
.event-map-page {
    display: flex; flex-direction: column;
    height: calc(100vh - 4rem);   /* leave room for the site header */
    min-height: 28rem;
}
.event-map-filters {
    display: flex; gap: 0.5rem;
    overflow-x: auto; overflow-y: hidden;
    padding: 0.6rem 1rem;
    background: var(--color-surface);
    border-bottom: 1px solid var(--color-border);
    scrollbar-width: none;
}
.event-map-filters::-webkit-scrollbar { display: none; }
.event-map-filters .pill {
    cursor: pointer; user-select: none;
    transition: background 120ms, border-color 120ms;
}
.event-map-filters .pill.is-active {
    background: var(--color-primary);
    color: white;
    border-color: var(--color-primary);
}
.event-map { flex: 1; width: 100%; background: var(--color-surface-alt); }
.event-map .leaflet-popup-content { font-family: inherit; font-size: 0.85rem; min-width: 14rem; }
.event-map-popup__title { font-weight: 700; margin: 0 0 0.25rem; }
.event-map-popup__meta  { font-size: 0.75rem; color: var(--color-text-mid); margin: 0 0 0.4rem; }
.event-map-popup__cta   { display: inline-flex; align-items: center; gap: 0.25rem; font-size: 0.8rem; font-weight: 600; color: var(--color-primary-text); }
