/* ==========================================================================
   Atla — DSLR galleries world-map page (galleries-dslr.html)
   --------------------------------------------------------------------------
   EDITORIAL REDESIGN (Option A). Layered on top of assets/css/styles.css
   (loaded FIRST), so all base design tokens (--bg, --ink, --ink-dim,
   --on-color, --hair, --font-mono, --step-*, --dur, --ease, --gutter,
   --container) and the self-hosted @font-face for "Fraunces" / "Inter" are
   already defined there. This file restyles the live page to the approved
   prototype (_studio/preview/photography.html): near-black canvas, warm
   cream ink, a Fraunces display hero with an italic accent, a fine film-grain
   overlay, sprite-icon controls/legend, monochrome->colour map hover, an
   oversized "View" cursor on fine pointers, vibrant earth-tone accents.

   The clickable world map is PRESERVED unchanged in behaviour: countries with
   a gallery light up in their gallery colour (--fill set by the JS via the
   CSSOM) and open the shared lightbox; the accessible fallback list stays.

   Strict-CSP safe: classes / CSS custom properties / SVG presentation
   attributes only. No inline styles, no <style> blocks, no external code.

   Editorial tokens + the .sprite/.icon base rules are (re)declared here with
   identical, fallback-filled values so this page renders correctly regardless
   of styles.css ordering; duplicate @font-face is NOT repeated (styles.css
   owns it and loads first).
   ========================================================================== */

/* ---- Page-scoped editorial tokens (fallback-safe) --------------------- */
.page-galleries--map {
  /* Display + UI families. Fraunces for the editorial serif display (with an
     italic accent); Inter for UI/captions/meta. Both fall back gracefully if
     the woff2 hasn't arrived (font-display: swap handles the FOUT). */
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --font-ui: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* DSLR accent (vivid teal) reused across hero + map + controls. */
  --accent: #a0572c;

  /* Soft hairline variants on the near-black canvas. */
  --line: rgb(255 255 255 / 0.12);
  --line-soft: rgb(255 255 255 / 0.07);
}

/* ---- Page canvas ------------------------------------------------------- */
.page-galleries { background: var(--bg); color: var(--ink); }
/* Inter as the page UI face; the global body font-family stays the system
   sans, so scope the editorial UI font to this page only. */
.page-galleries--map { font-family: var(--font-ui); }

/* ---- Secure inline-sprite + icon system (idempotent) ------------------- */
/* The sprite <symbol> defs are inlined into the page <body> inside .sprite;
   this hides that host. .icon is the generic inline-SVG sizing rule; symbols
   are stroke-based so they inherit currentColor. */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.icon {
  inline-size: 1.2em;
  block-size: 1.2em;
  fill: none;
  stroke: currentColor;
  vertical-align: middle;
  flex: none;
}

/* ---- Film-grain overlay ------------------------------------------------ */
/* A fine fixed grain over the whole page; pointer-transparent, decorative.
   The data-URI SVG noise keeps it CSP-clean (no external fetch). */
.grain {
  position: fixed;
  inset: 0;
  z-index: 80;
  pointer-events: none;
  opacity: 0.04;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---- Oversized "View" cursor (fine pointers only) ---------------------- */
/* On fine-pointer devices, a soft difference-blended dot follows the pointer
   and grows into a labelled "View" puck over a lit country. JS sets its
   position via the CSSOM (--cur-x/--cur-y) and toggles .is-view. */
.gmap-cursor { display: none; }
@media (pointer: fine) {
  .gmap-cursor {
    position: fixed;
    inset-block-start: 0;
    inset-inline-start: 0;
    z-index: 90;
    pointer-events: none;
    display: grid;
    place-items: center;
    inline-size: 12px;
    block-size: 12px;
    border-radius: 999px;
    background: var(--ink);
    mix-blend-mode: difference;
    transform: translate(var(--cur-x, -50px), var(--cur-y, -50px)) translate(-50%, -50%);
    transition: inline-size 0.3s var(--ease), block-size 0.3s var(--ease),
                background-color 0.3s var(--ease);
  }
  .gmap-cursor__label {
    font-family: var(--font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--bg);
    opacity: 0;
    transition: opacity 0.25s var(--ease);
  }
  .gmap-cursor.is-view { inline-size: 74px; block-size: 74px; }
  .gmap-cursor.is-view .gmap-cursor__label { opacity: 1; }

  /* Hide the native cursor over interactive countries so the puck reads as
     the affordance. Only on the canvas itself. */
  .gmap__canvas.is-ready .has-gallery { cursor: none; }
}

/* ---- Hero -------------------------------------------------------------- */
/* The hero keeps the shiny radial .panel treatment from styles.css for the
   vivid teal sheen, but the TITLE switches to the Fraunces editorial display
   with an italic accent (.gmap-hero__title em). */
.gmap-hero { --c: #a0572c; }
.gmap-hero__inner {
  /* Tall enough to feel like a hero, but lets the map sit close beneath. */
  min-block-size: auto;
  padding-block: clamp(8rem, 18vh, 12rem) clamp(2.5rem, 6vh, 4rem);
  gap: clamp(0.9rem, 0.4rem + 1.1vw, 1.6rem);
}
.gmap-hero__cat {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  opacity: 0.85;
}
.gmap-hero__title {
  font-family: var(--font-display);
  font-weight: 300;             /* light optical weight reads as editorial */
  font-optical-sizing: auto;
  font-size: clamp(3rem, 1.4rem + 9vw, 9rem);
  line-height: 0.94;
  letter-spacing: -0.02em;
  max-inline-size: 16ch;
}
.gmap-hero__title em {
  font-style: italic;
  font-weight: 400;
  /* warm accent on the italic word for the editorial "held a little longer" feel */
  color: color-mix(in oklab, var(--on-color) 82%, #fff 18%);
}
@supports not (color: color-mix(in oklab, #000 50%, #fff)) {
  .gmap-hero__title em { color: var(--on-color); }
}
.gmap-hero__desc {
  font-family: var(--font-ui);
  font-size: var(--step-1);
  max-inline-size: 46ch;
  opacity: 0.94;
}
.gmap-hero__back { margin-block-start: clamp(0.5rem, 1.5vw, 1.2rem); }
.gmap-back {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--on-color);
  opacity: 0.92;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.gmap-back:hover,
.gmap-back:focus-visible { opacity: 1; }
.gmap-back .icon { transition: transform var(--dur) var(--ease); }
.gmap-back:hover .icon,
.gmap-back:focus-visible .icon { transform: translateX(-0.3rem); }

/* ---- Map + list section ------------------------------------------------ */
.gmap { background: var(--bg); color: var(--ink); }
.gmap__inner {
  min-block-size: auto;
  padding-block: clamp(2rem, 5vh, 4rem) clamp(5rem, 12vh, 9rem);
  justify-content: flex-start;
  gap: clamp(2rem, 4vw, 3.5rem);
}

/* A small editorial section label above the map. */
.gmap__lead {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.gmap__lead .icon { color: var(--accent); }

/* ---- Map figure -------------------------------------------------------- */
.gmap__figure { margin: 0; }

/* The viewport clips the (zoomable) SVG and hosts the floating controls. */
.gmap__viewport {
  position: relative;
  border-radius: 16px;
  overflow: hidden;
  background:
    radial-gradient(120% 140% at 18% 8%,
      color-mix(in oklab, var(--accent) 30%, #0a0a0b 70%) 0%,
      #14110c 60%,
      #0a0a0b 100%);
  /* fallback for no color-mix() */
  background-color: #14110c;
  border: 1px solid var(--line);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.05);
}

/* The canvas that receives the inlined SVG. aspect-ratio reserves the box
   (zero layout shift) before the SVG arrives. */
.gmap__canvas {
  display: block;
  inline-size: 100%;
  aspect-ratio: 1000 / 500;
}
.gmap__canvas svg {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  /* JS owns gestures on the stage; this stops the browser hijacking drag/zoom. */
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}
/* While dragging, hint the compositor and show a grabbing cursor. */
.gmap__canvas.is-grabbing svg { cursor: grabbing; will-change: transform; }
.gmap__canvas.is-ready svg { cursor: grab; }
.gmap__static { inline-size: 100%; block-size: auto; }

/* ---- SVG map theming (presentation-attr fallbacks live in world.svg) ---- */
/* Ocean + base land. CSS overrides the SVG's presentation attributes. */
.gmap__canvas .map__ocean { fill: #14110c; }
.gmap__canvas .map__land { fill: #2e2820; stroke: #0a0a0b; }
.gmap__canvas .region {
  fill: #2e2820;                 /* "no gallery" land tone */
  stroke: #0a0a0b;
  stroke-width: 1;
  transition: fill var(--dur) var(--ease), filter var(--dur) var(--ease);
}

/* Countries that HAVE a gallery: filled from the per-path --fill custom
   property the JS sets (path.style.setProperty('--fill', gallery.color)). */
.gmap__canvas .region.has-gallery {
  fill: var(--fill, #a0572c);
  cursor: pointer;
}

/* Hover / keyboard focus highlight — never :hover alone (mirrored to focus). */
.gmap__canvas .region.has-gallery:hover,
.gmap__canvas .region.has-gallery:focus-visible {
  filter: brightness(1.18) saturate(1.08);
  stroke: var(--ink);
  stroke-width: 2.25;
  outline: none;                 /* visible ring provided by the stroke below */
}
/* A clear, high-contrast focus ring for keyboard users (the stroke can be lost
   against bright fills, so add a cream halo via drop-shadow on focus). */
.gmap__canvas .region.has-gallery:focus-visible {
  stroke: var(--ink);
  filter: brightness(1.18) saturate(1.08)
          drop-shadow(0 0 0 var(--bg))
          drop-shadow(0 0 3px var(--ink));
}

/* ---- Real political map (Wikimedia BlankMap-World) theming ------------- */
/* world.svg ships with NO presentation attributes (its <style> block is removed
   so the strict CSP allows inlining it), so ALL of its theming lives here.
   Country primary elements carry data-code="ISO" (uppercase); multi-part
   countries are a <g> whose child .landxx paths inherit the lit fill. */

/* Ocean: transparent so the viewport's radial gradient reads as water. */
.gmap__canvas .oceanxx { fill: transparent; stroke: none; }

/* Base land — muted "no gallery" tone with hairline borders. (.antxx = the
   uninhabited territories incl. Antarctica; themed as land for context.) */
.gmap__canvas .landxx,
.gmap__canvas .antxx {
  fill: #2e2820;
  stroke: #0a0a0b;
  stroke-width: 0.6;
  fill-rule: evenodd;
  transition: fill var(--dur) var(--ease), filter var(--dur) var(--ease);
}

/* Decorative overlays the source keeps hidden by default (small-country
   circles, sub-national markers, limited-recognition duplicate layers). The
   stripped <style> set these to opacity:0 — re-hide them so they don't surface
   as black blobs over the map. */
.gmap__canvas .circlexx,
.gmap__canvas .subxx,
.gmap__canvas .noxx,
.gmap__canvas .unxx,
.gmap__canvas .limitxx { opacity: 0; }

/* Lit countries: filled from --fill (JS sets it on the country element via the
   CSSOM; custom properties inherit, so a grouped country's child .landxx paths
   pick it up too). Ordered AFTER the base so equal-specificity ties resolve here. */
.gmap__canvas .has-gallery,
.gmap__canvas .has-gallery .landxx {
  fill: var(--fill, #a0572c);
  cursor: pointer;
}

/* Hover / keyboard-focus highlight (mirrored — never :hover alone). The filter
   brightens the whole country; the stroke is applied to self AND child paths so
   grouped countries get the full outline. */
.gmap__canvas .has-gallery:hover,
.gmap__canvas .has-gallery:focus-visible {
  filter: brightness(1.16) saturate(1.08);
  outline: none;
}
.gmap__canvas .has-gallery:hover,
.gmap__canvas .has-gallery:hover .landxx,
.gmap__canvas .has-gallery:focus-visible,
.gmap__canvas .has-gallery:focus-visible .landxx {
  stroke: var(--ink);
  stroke-width: 1.4;
}
.gmap__canvas .has-gallery:focus-visible {
  filter: brightness(1.16) saturate(1.08) drop-shadow(0 0 2.5px var(--ink));
}

/* ---- Floating zoom / pan controls ------------------------------------- */
.gmap__controls {
  position: absolute;
  inset-block-start: 0.75rem;
  inset-inline-end: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  z-index: 2;
}
.gmap__controls[hidden] { display: none; }
.gmap__btn {
  inline-size: 2.6rem;
  block-size: 2.6rem;
  display: inline-grid;
  place-items: center;
  color: var(--ink);
  background: rgb(10 10 11 / 0.62);
  border: 1px solid var(--line);
  border-radius: 10px;
  cursor: pointer;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              opacity var(--dur) var(--ease);
}
.gmap__btn .icon { inline-size: 1.3rem; block-size: 1.3rem; }
.gmap__btn:hover,
.gmap__btn:focus-visible {
  background: color-mix(in oklab, var(--accent) 55%, #000 45%);
  border-color: rgb(236 229 216 / 0.4);
}
@supports not (color: color-mix(in oklab, #000 50%, #fff)) {
  .gmap__btn:hover,
  .gmap__btn:focus-visible { background: rgb(160 87 44 / 0.55); }
}
.gmap__btn:active { transform: scale(0.94); }
.gmap__btn[disabled] { opacity: 0.34; cursor: default; }

.gmap__hint {
  margin-block-start: 0.85rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--ink-dim);
  max-inline-size: 64ch;
}
.gmap__hint[hidden] { display: none; }
.gmap__hint .icon { color: var(--accent); flex: none; }

/* ---- Fallback list of galleries --------------------------------------- */
.gmap-list { display: block; }
.gmap-list__heading {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.05;
  margin-block-end: clamp(0.75rem, 1.5vw, 1.25rem);
}
.gmap-list__status {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--ink-dim);
}
.gmap-list__status[hidden] { display: none; }
.gmap-list__status .icon { color: var(--accent); }

.gmap-list__items {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(0.6rem, 1.2vw, 1rem);
}
@media (min-width: 700px) {
  .gmap-list__items { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 1280px) {
  .gmap-list__items { grid-template-columns: repeat(3, 1fr); }
}

/* Each list entry is a real <button> (opens the same lightbox the map does). */
.gmap-list__btn {
  --swatch: #a0572c;
  inline-size: 100%;
  display: flex;
  align-items: center;
  gap: 0.9rem;
  text-align: start;
  padding: clamp(0.85rem, 0.6rem + 1vw, 1.2rem) clamp(1rem, 0.7rem + 1vw, 1.3rem);
  border-radius: 12px;
  background: rgb(255 255 255 / 0.03);
  border: 1px solid var(--line-soft);
  color: var(--ink);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.gmap-list__btn:hover,
.gmap-list__btn:focus-visible {
  background: rgb(255 255 255 / 0.06);
  border-color: rgb(236 229 216 / 0.32);
  transform: translateY(-2px);
}
.gmap-list__swatch {
  flex: 0 0 auto;
  inline-size: 1.5rem;
  block-size: 1.5rem;
  border-radius: 6px;
  background: var(--swatch);
  /* glossy chip echoing the hero treatment */
  background-image:
    radial-gradient(120% 120% at 25% 20%,
      color-mix(in oklab, var(--swatch) 65%, #fff 35%) 0%,
      var(--swatch) 70%);
  border: 1px solid rgb(255 255 255 / 0.18);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.25);
}
.gmap-list__text { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.gmap-list__name {
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.15;
}
.gmap-list__meta {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--ink-dim);
  letter-spacing: 0.02em;
}
.gmap-list__meta .icon {
  inline-size: 0.95em;
  block-size: 0.95em;
  color: var(--ink-mute);
}
.gmap-list__count { opacity: 0.85; }

/* Empty / error state row. */
.gmap-list__empty {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--ink-dim);
  padding: 1rem 0;
}

/* ---- Responsive tuning ------------------------------------------------- */
/* mobile (max-width 699.98px): give the map a bit more height proportionally
   so small countries stay tappable, and stack controls comfortably. */
@media (max-width: 699.98px) {
  .gmap__btn { inline-size: 2.9rem; block-size: 2.9rem; } /* larger touch target */
}

/* 4k (min-width 2200px): cap the map width so it doesn't sprawl; container
   already caps at --container, but center the figure tidily. */
@media (min-width: 2200px) {
  .gmap__inner { gap: 4rem; }
}

/* ---- Reduced motion ---------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .gmap__canvas .region,
  .gmap__canvas .landxx,
  .gmap__canvas .antxx,
  .gmap__btn,
  .gmap-list__btn,
  .gmap-back,
  .gmap-back .icon,
  .gmap-cursor { transition: none; }
  .gmap__canvas.is-grabbing svg { will-change: auto; }
}
