/* ============================================================
   base.css — near-universal rules extracted from inline <style>
   blocks + curated accessibility overrides.

   Every HTML file still has its original inline <style> block
   as a complete byte-for-byte fallback. This file is loaded
   AFTER the inline <style>, so its rules override on browsers
   that successfully fetch it (equal specificity, later cascade
   origin). If this file ever 404s, the inline fallback kicks
   in and nothing visually breaks (except for the a11y
   overrides at the bottom — those are live-only).

   Do NOT edit by hand. Run:
     python3 scripts/build-base-css.py
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

.nav-hamburger { display: none; }

.nav-hamburger:focus-visible span { background: var(--gold); }

.nav-mobile { display: none; }

.nav-search-icon { position: absolute; left: 0.7rem; top: 50%; transform: translateY(-50%); font-size: 0.75rem; color: rgba(255,255,255,0.3); pointer-events: none; }

.nav-search-input { width: 100%; padding: 0.45rem 0.8rem 0.45rem 2rem; border-radius: 20px; border: 1px solid rgba(255,255,255,0.12); background: rgba(255,255,255,0.06); color: var(--white); font-family: var(--sans); font-size: 0.78rem; outline: none; transition: all 0.2s; }

.nav-search-input::placeholder { color: rgba(255,255,255,0.3); }

.nav-search-input:focus { border-color: var(--gold); background: rgba(255,255,255,0.1); }

.skip-link:focus { top: 0; outline: 2px solid var(--gold); outline-offset: 2px; }

/* Accessibility — skip link and focus-visible affordances */ .skip-link { position: absolute; top: -100px; left: 0; background: var(--ink); color: var(--gold); padding: 0.8rem 1.2rem; z-index: 300; font-size: 0.85rem; font-weight: 500; text-decoration: none; border-radius: 0 0 4px 0; }

/* Search bar in nav */ .nav-search { position: relative; flex: 1; max-width: 260px; margin: 0 1rem; }

:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

@media (max-width: 768px) { .nav-search { display: none; } }

/* ============================================================
   FADE-IN SAFETY NET
   Every page uses `.fade-in { opacity: 0 }` + IntersectionObserver
   to progressively reveal content as it scrolls into view. But if
   ANY JS error happens before the observer runs (CSP block, typo,
   network issue), the observer never runs and every .fade-in
   element stays hidden forever — the entire page appears blank.
   This CSS animation kicks in after 1.5s and reveals the content
   even if no JS executes. The observer's .visible class cancels
   this animation immediately if the JS path works.
   ============================================================ */
.fade-in {
  animation: fade-in-fallback 0.6s ease 1.5s forwards;
}
.fade-in.visible {
  animation: none;
}
@keyframes fade-in-fallback {
  to { opacity: 1; transform: none; }
}

/* ============================================================
   Accessibility / WCAG AA overrides
   These rules are NOT in the extracted near-universal set but
   are curated here to enforce minimum contrast ratios (4.5:1
   for normal text) on top of whatever inline CSS exists.
   ============================================================ */

/* Inline body text links use --gold-dark (4.88:1 on cream)
   instead of --gold (2.01:1 on cream, fails AA). Decorative gold
   is preserved for nav/logo/buttons via the overrides below. */
a { color: var(--gold-dark); }
a:hover { color: var(--gold-dark); text-decoration: underline; }

/* Decorative gold accents — preserve the bright brand color on
   dark backgrounds where contrast is fine (ink header/footer).
   These are the elements you WANT to look gold even though their
   raw color fails AA on cream. */
.nav-logo, .nav-logo:hover,
.nav-mobile a,
.skip-link {
  color: var(--gold);
}
.nav-logo span {
  color: var(--white);
}

/* Nav links on dark bg — increase alpha from 0.7 to 0.85 for
   better contrast (7.0:1 → 10.8:1 on ink). */
.nav-links a {
  color: rgba(255, 255, 255, 0.85);
}
.nav-links a:hover,
.nav-links a[aria-current="page"] {
  color: var(--gold);
}
.nav-back {
  color: rgba(255, 255, 255, 0.75);
}
.nav-back:hover {
  color: var(--gold);
}

/* Footer contrast boost — raise alphas from 0.4/0.25 (failing) to
   0.65/0.65 (passing). Footer links stay muted-white, not gold,
   so they don't fail on #110f0d. */
footer {
  color: rgba(255, 255, 255, 0.65) !important;
}
.footer-links a {
  color: rgba(255, 255, 255, 0.65);
}
.footer-links a:hover {
  color: var(--gold);
}

/* Breadcrumb contrast — current page in --ink for max contrast,
   links in --slate (8.26:1). */
.breadcrumbs a { color: var(--slate); }
.breadcrumbs a:hover { color: var(--gold-dark); }
.breadcrumbs .current { color: var(--ink); }

/* ============================================================
   Map popup styles — shared across homepage + district pages.
   District pages used to open the full Instagram store modal on
   every map-pin click, which blocked the map and felt heavy. We
   now use Leaflet's native bindPopup with a compact dark card
   (same pattern as homepage map) so the popup floats next to the
   pin instead of obscuring the map. "View details" button inside
   still opens the full store modal for users who want the
   Instagram embed + longer description.
   ============================================================ */
.leaflet-popup-content-wrapper {
  background: var(--ink) !important;
  border: 1px solid var(--gold) !important;
  border-radius: 10px !important;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5) !important;
  color: var(--white) !important;
  font-family: var(--sans) !important;
  padding: 0 !important;
}
.leaflet-popup-tip { background: var(--gold) !important; }
.leaflet-popup-close-button {
  color: var(--gold) !important;
  font-size: 18px !important;
  padding: 6px 8px !important;
}
.leaflet-popup-content { margin: 0 !important; }

.map-popup {
  padding: 1rem 1.2rem 1rem;
  min-width: 200px;
  max-width: 260px;
}
.map-popup-tag {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--gold);
  font-weight: 600;
  margin-bottom: 0.3rem;
}
.map-popup-name {
  font-family: var(--serif);
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--white);
  margin-bottom: 0.4rem;
  line-height: 1.2;
}
.map-popup-desc {
  font-size: 0.78rem;
  color: rgba(255, 255, 255, 0.72);
  line-height: 1.5;
  margin-bottom: 0.7rem;
}
.map-popup-meta {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.7rem;
  color: rgba(255, 255, 255, 0.55);
  margin-bottom: 0.8rem;
}
.map-popup-actions {
  display: flex;
  gap: 0.5rem;
}
.map-popup-btn {
  flex: 1;
  font-size: 0.7rem;
  padding: 0.45rem 0.6rem;
  border-radius: 6px;
  font-family: var(--sans);
  cursor: pointer;
  font-weight: 600;
  text-align: center;
  transition: all 0.2s;
  border: none;
  text-decoration: none !important;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.map-popup-btn.primary {
  background: var(--gold);
  color: var(--ink) !important;
}
.map-popup-btn.primary:hover { background: var(--gold-lt, #e8c96b); }
.map-popup-btn.secondary {
  background: rgba(255, 255, 255, 0.08);
  color: rgba(255, 255, 255, 0.9) !important;
  border: 1px solid rgba(255, 255, 255, 0.15);
}
.map-popup-btn.secondary:hover { background: rgba(255, 255, 255, 0.14); }

/* ============================================================
   Hotel carousel — shares all markup + styling with the existing
   .restaurant-carousel. We just need the wrapper margin and the
   blue .rest-btn.book variant for the "Book" affiliate button.
   See scripts/build-hotels.py for the data + injection logic.
   ============================================================ */
.hotel-carousel { margin-bottom: 3rem; overflow: hidden; }
.rest-btn.book {
  background: #1c4a7e;
  color: #fff !important;
  text-decoration: none !important;
}
.rest-btn.book:hover { background: #173e69; }

/* ============================================================
   MICHELIN Key badge — shown on hotel cards for hotels in the
   MICHELIN Key guide. 1-Key = dark pill with gold text. 2-Key
   = inverted (gold pill, dark text) to signal elevated status.
   See CLONING.md "Hotel curation policy" for the rule.
   ============================================================ */
.mkey-badge {
  display: inline-block;
  font-size: 0.55rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.22rem 0.55rem;
  border-radius: 12px;
  background: #1a1a1a;
  color: var(--gold);
  margin-bottom: 0.5rem;
  line-height: 1.2;
}
.mkey-badge.two {
  background: var(--gold);
  color: #1a1a1a;
}
