/*
AI PROJECT NOTE — LECTURA OBLIGATORIA PARA CUALQUIER IA:
Antes de modificar este archivo, toda IA (Claude, ChatGPT u otra) DEBE
leer primero /AI_RULES.md completo. Sin excepcion, sin importar cuan
chico o simple parezca el cambio, y sin esperar a que el usuario lo
pida o lo recuerde — esta nota es la instruccion, no un recordatorio
opcional. Si /AI_RULES.md ya se leyo en esta misma sesion, alcanza con
revisar /AI_SESSION.md en su lugar.

Despues de modificar este archivo, actualizar /AI_SESSION.md con el
cambio hecho y la verificacion realizada.
*/


/* ═══════════════════════════════════════
   VARIABLES DE DISEÑO (DESIGN TOKENS)
   ---------------------------------------
   FUTURO: este bloque completo está pensado
   para conectarse a un panel de administrador
   ("Panel de Estilos") donde el admin pueda
   cambiar estos valores con selectores visuales
   en vez de editar este archivo a mano.
   Cuando se construya ese panel, cada variable
   de acá abajo pasa a ser un control (color
   picker, slider, dropdown de fuente, etc).
   No se necesita tocar el resto del CSS: todo
   el sitio ya "escucha" a estas variables.
═══════════════════════════════════════ */
:root {

  /* ---- FONDOS Y SUPERFICIES ----
     Colores de fondo general (--bg) y de las
     tarjetas/paneles que flotan sobre el fondo
     (--surface, --surface2). */
  --bg:          #f0f4f0;
  --surface:     #ffffff;
  --surface2:    #f7f9f7;

  /* ---- BORDES ----
     Líneas divisorias sutiles entre elementos. */
  --border:      #e2eae2;
  --border2:     #ccdacc;

  /* ---- TEXTO ----
     --text = texto principal (más oscuro/legible)
     --text2 = texto secundario (subtítulos, ayuda)
     --text3 = texto terciario (el más apagado, ej.
     placeholders o notas al pie) */
  --text:        #1a2e1a;
  --text2:       #4a6b4a;
  --text3:       #8aaa8a;

  /* ---- COLOR DE MARCA (ACENTO PRINCIPAL) ----
     --accent = el color "de marca" que se usa en
     botones principales, links activos, elementos
     destacados. Es el color más importante para
     la identidad visual de la app.
     --accent2 = color secundario de acento (para
     contrastar con el principal en detalles puntuales)
     --accent-pale = versión clara del acento, para
     fondos suaves detrás de elementos activos. */
  --accent:      #3a8c4f;
  --accent2:     #f97316;
  --accent-pale: #edf7ef;

  /* ---- PALETA GENERAL DE COLORES ----
     Colores base disponibles para usar en distintos
     elementos de la interfaz (no ligados a una
     categoría de lugar en particular). */
  --green:       #3a8c4f;
  --green-light: #5aaa68;
  --blue:        #3b7dd8;
  --purple:      #7c5aed;
  --teal:        #0d9488;
  --amber:       #e09000;

  /* ---- SOMBRAS ----
     De más sutil (--shadow-xs, para elementos chicos)
     a más marcada (--shadow-lg, para modales/paneles
     grandes que "flotan" sobre el resto). */
  --shadow-xs:   0 1px 4px rgba(0,0,0,.06);
  --shadow-sm:   0 2px 10px rgba(0,0,0,.08);
  --shadow-md:   0 8px 28px rgba(0,0,0,.10);
  --shadow-lg:   0 20px 50px rgba(0,0,0,.14);
  --shadow-panel: 0 12px 30px rgba(0,0,0,.12);

  /* ---- BORDES REDONDEADOS ----
     Qué tan "curvas" son las esquinas de tarjetas y
     botones. --r-sm = esquinas chicas, --r-lg = esquinas
     bien redondeadas (paneles grandes, modales). */
  --r-sm:        12px;
  --r:           16px;
  --r-lg:        20px;
  /* Radio de borde chico, solo para controles interactivos (inputs,
     selects, botones, tabs) — separado de --r (que sigue usándose
     para tarjetas/paneles/modales) para poder achicar el redondeo
     de "los botones" sin afectar el resto del diseño. */
  --r-ctrl:      7px;

  /* ---- TIPOGRAFÍAS ----
     --font-d = fuente de TÍTULOS ("display"): Sora
     --font-b = fuente de TEXTO GENERAL ("body"): Nunito
     --font-m = fuente MONOESPACIADA (para datos tipo
     código o números alineados): JetBrains Mono */
  --font-d:      'Sora', sans-serif;
  --font-b:      'Nunito', sans-serif;
  --font-m:      'JetBrains Mono', monospace;

  /* ---- COLORES POR CATEGORÍA DE LUGAR ----
     Cada categoría de pin tiene su propio color de
     identificación visual en el mapa y en las etiquetas.
     Si se agrega una categoría nueva a futuro, necesita
     su propia variable acá siguiendo el mismo patrón
     "--c-nombrecategoria". */
  --c-food:      #e0603a;   /* Gastronomía */
  --c-culture:   #5a52d8;   /* Cultura */
  --c-music:     #c850a8;   /* Música */
  --c-bar:       #c87020;   /* Bares */
  --c-art:       #0d9488;   /* Arte */
  --c-historic:  #7c4aed;   /* Histórico */
  --c-shop:      #3a8c4f;   /* Comercios */

  /* ---- COMPONENTES RGB DE TOKENS (para rgba() con opacidad) ----
     [PLAN_SISTEMA_SKINS.md] Mismo color que --surface/--text/--accent
     de arriba, pero como "R,G,B" sin el signo #, para poder usarlos
     dentro de rgba(var(--x-rgb), .XX) en vez de escribir el rgba
     entero a mano. Así, cuando un skin cambie --surface/--text/--accent,
     automáticamente seguimos también todos los overlays/sombras/tintes
     translúcidos que dependen de esos colores, sin tener que tocar cada
     rgba() suelto uno por uno. Si se agrega un skin nuevo, estos 3
     deben actualizarse junto con sus --x de arriba (mismo color, otro
     formato) — ver [data-skin="..."] más abajo. */
  --surface-rgb: 255, 255, 255;
  --text-rgb:    26, 46, 26;
  --accent-rgb:  58, 140, 79;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; font-family: var(--font-b); background: var(--bg); color: var(--text); overflow: hidden; }

/* ═══════════════════════════════════════
   MAP
═══════════════════════════════════════ */
#map {
  position: fixed; inset: 0;
  width: 100%; height: 100%;
  z-index: 1;
}
.leaflet-container { font-family: var(--font-b) !important; }
.leaflet-control-zoom {
  border: none !important;
  border-radius: var(--r) !important;
  overflow: hidden;
  box-shadow: var(--shadow-panel) !important;
  margin-top: 70px !important;
  margin-left: 14px !important;
  display: flex !important;
  flex-direction: row !important;
}
.leaflet-control-zoom a {
  background: rgba(var(--surface-rgb), .97) !important;
  backdrop-filter: blur(10px) !important;
  color: var(--text) !important;
  border-right: 1px solid var(--border) !important;
  border-bottom: none !important;
  font-size: 18px !important; font-weight: 400 !important;
  width: 38px !important; height: 38px !important; line-height: 38px !important;
  transition: background .15s, color .15s;
}
.leaflet-control-zoom a:last-child { border-right: none !important; }
.leaflet-control-zoom a:hover { background: var(--accent-pale) !important; color: var(--accent) !important; }
/* [B13, 23/10] Atribución del mapa VISIBLE (la exigen los dueños de cada mapa;
   antes estaba oculta). Chiquita y discreta, arriba a la derecha debajo de la
   barra superior (#topbar: 56 px / 52 px + área segura). Abajo no: ahí va la
   fila de categorías. El texto lo arma js/map-settings.js (+ link "Privacidad"). */
.leaflet-top.leaflet-right { top: calc(56px + env(safe-area-inset-top)); }
@media (max-width: 420px) { .leaflet-top.leaflet-right { top: calc(52px + env(safe-area-inset-top)); } }
.leaflet-control-attribution.leaflet-control {
  margin: 4px 6px 0 0 !important;
  padding: 1px 6px !important;
  font-size: 10px !important;
  line-height: 1.5 !important;
  background: rgba(var(--surface-rgb), .72) !important;
  color: var(--text2) !important;
  border-radius: 6px;
  max-width: calc(100vw - 24px);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.leaflet-control-attribution a { color: var(--text) !important; text-decoration: none; }
.leaflet-control-attribution a:hover { text-decoration: underline; }
/* [I1] + y − solo en compu: en celular y tablet (puntero táctil) se usa el pellizco */
@media (hover: none) and (pointer: coarse) {
  .leaflet-control-zoom { display: none !important; }
}
.leaflet-tooltip {
  background: var(--surface) !important;
  border: 1px solid var(--border) !important;
  color: var(--text) !important;
  font-family: var(--font-b) !important;
  font-size: 11px !important; font-weight: 600 !important;
  border-radius: var(--r-sm) !important;
  padding: 4px 9px !important;
  box-shadow: var(--shadow-sm) !important;
  pointer-events: none;
}
.leaflet-tooltip::before { display: none !important; }

/* ═══════════════════════════════════════
   HEADER — floating search bar style
═══════════════════════════════════════ */
#header {
  position: fixed; top: 0; left: 0; right: 0;
  z-index: 500;
  padding: 0;
  pointer-events: none; /* let map clicks through the transparent area */
  background: none;
  border: none;
  box-shadow: none;
}
/* every direct child of header gets pointer-events back */
#header > * { pointer-events: all; }

/* [I1, 2026-10-22] BARRA SUPERIOR UNIFICADA: una sola barra de punta a punta
   con ☰ (zonas), buscador, banderas, 👤 y ⚙ (solo admin). Los botones y el
   buscador conservan sus ids: ningún .js depende de la posición. Cuando
   aparece ⚙ el buscador se achica solo (flex) y el resto queda a su izquierda. */
#topbar {
  display: flex; align-items: center; gap: 4px;
  width: 100%; height: calc(56px + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) 12px 0;
  box-sizing: border-box;
  background: rgb(var(--surface-rgb));
  border-radius: 0;
  border-bottom: 1px solid var(--border);
  box-shadow: none;
}

/* hamburger / menu button (left) */
#btn-zonas {
  background: transparent;
  border: none;
  border-radius: 12px;
  width: 40px; height: 40px;
  padding: 0;
  font-size: 16px;
  color: var(--text);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all .2s;
  box-shadow: none;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  white-space: nowrap;
  justify-self: start;
  flex-shrink: 0;
  gap: 0;
}
#btn-zonas .zico { display: none; } /* hide old arrow */
#btn-zonas::before { content: '☰'; font-size: 18px; }
#btn-zonas:hover { background: var(--accent); color: white; }
#btn-zonas.open { background: var(--accent); color: white; }

/* Search bar — center, grows to fill */
#search-bar {
  flex: 1;
  display: flex;
  align-items: center;
  min-width: 0;
  background: rgba(var(--text-rgb), .06);
  border-radius: 12px;
  box-shadow: none;
  padding: 0 14px;
  height: 40px;
  gap: 8px;
  overflow: hidden;
}
#search-bar-icon {
  font-size: 15px;
  color: var(--text3);
  flex-shrink: 0;
}
#search-input {
  flex: 1;
  border: none;
  background: transparent;
  outline: none;
  font-family: var(--font-b);
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
  padding: 0;
  min-width: 0;
  text-overflow: ellipsis;
}
#search-input::placeholder { color: var(--text3); }

/* filter/admin button (right) */
#btn-admin {
  height: 40px; width: 40px; padding: 0;
  background: transparent;
  color: var(--text);
  border: none; border-radius: 12px;
  font-size: 17px;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: all .2s;
  -webkit-tap-highlight-color: transparent;
  justify-self: end;
  flex-shrink: 0;
  box-shadow: none;
}
#btn-admin:hover { background: var(--accent); color: white; }
#btn-admin:active { transform: scale(.95); }
#btn-admin.active { background: var(--accent); color: white; }
/* [2026-10-06] Oculta salvo sesión de admin real (js/admin-auth.js) — hace
   falta explícito porque el display:flex de arriba le gana al [hidden] nativo */
#btn-admin[hidden] { display: none; }

/* [Etapa 1, PLAN_USUARIOS_EVENTOS.md] Botón "mi cuenta" del header
   público — mismo lenguaje visual que #btn-admin/#btn-zonas */
#btn-user-account {
  height: 40px; width: 40px; padding: 0;
  background: transparent;
  color: var(--text);
  border: none; border-radius: 12px;
  font-size: 17px;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: all .2s;
  -webkit-tap-highlight-color: transparent;
  flex-shrink: 0;
  box-shadow: none;
}
#btn-user-account:hover { background: var(--accent); color: white; }
#btn-user-account:active { transform: scale(.95); }
#btn-user-account.logged-in { background: var(--accent); color: white; }

/* [Etapa 7, 2026-08-16] Selector de idioma global — vive en el header
   público, no dentro del panel de un lugar puntual, para que el
   visitante elija idioma aunque todavía no haya abierto ningún pin.
   Mismo lenguaje visual que #btn-zonas/#btn-admin (píldora blanca
   flotante). El estado activo (qué botón queda resaltado) lo pinta
   js/lang-switcher.js, no CSS — así se sincroniza solo con
   AppState.getLanguage() sin depender de una clase puesta a mano. */
#lang-switcher {
  height: 40px;
  display: flex;
  align-items: center;
  background: none;
  border-left: 1px solid var(--border);
  border-right: 1px solid var(--border);
  box-shadow: none;
  padding: 0 4px;
  margin: 0 2px;
  gap: 2px;
  flex-shrink: 0;
}
#lang-switcher button {
  border: 2px solid transparent;
  background: transparent;
  padding: 3px;
  border-radius: 10px;
  cursor: pointer;
  line-height: 0;
  transition: background .2s, border-color .2s;
  -webkit-tap-highlight-color: transparent;
}
/* [2026-10-01] Banderas cuadradas en vez de siglas (ES/EN/PT). Inactiva =
   escala de grises + opacidad baja; activa = color completo con aro del
   color de acento. Para ajustar cuánto "se apagan" las inactivas, tocar
   SOLO grayscale/brightness/opacity de la primera regla. */
#lang-switcher button img {
  width: 26px;
  height: 26px;
  border-radius: 6px;
  display: block;
  pointer-events: none;
  filter: grayscale(1) brightness(.85);
  opacity: .6;
  transition: filter .2s, opacity .2s;
}
#lang-switcher button:hover img { filter: grayscale(.4); opacity: .9; }
#lang-switcher button.active { border-color: var(--accent); background: rgba(var(--accent-rgb), .12); }
#lang-switcher button.active img { filter: none; opacity: 1; }
@media (max-width: 420px) {
  /* En pantallas angostas el buscador ya ocupa casi todo — las
     banderas y los botones se achican un poco. */
  #topbar { height: calc(52px + env(safe-area-inset-top)); gap: 2px; padding-left: 6px; padding-right: 6px; }
  #btn-zonas, #btn-user-account, #btn-admin { width: 36px; height: 36px; }
  #search-bar { height: 36px; padding: 0 8px; gap: 6px; }
  #lang-switcher { height: 36px; padding: 0 2px; margin: 0; }
  #lang-switcher button { padding: 2px; }
  #lang-switcher button img { width: 22px; height: 22px; }
}

/* [I1 parte 3, 2026-10-22] Celulares muy chicos (320–340 px) con el ⚙ de admin:
   el buscador quedaba en ~50 px. Se achican un poco más los botones y las
   banderas (las 3 banderas siguen visibles). */
@media (max-width: 340px) {
  #topbar { padding-left: 4px; padding-right: 4px; }
  #btn-zonas, #btn-user-account, #btn-admin { width: 32px; height: 32px; }
  #search-bar { padding: 0 6px; gap: 4px; }
  #lang-switcher button { padding: 1px; border-radius: 8px; }
  #lang-switcher button img { width: 20px; height: 20px; }
}

/* hide old logo */
.logo { display: none !important; }

/* ═══════════════════════════════════════
   SEARCH RESULTS DROPDOWN
═══════════════════════════════════════ */
#search-results {
  position: fixed;
  top: calc(62px + env(safe-area-inset-top));
  left: 12px; right: 12px;
  z-index: 699;
  background: rgba(var(--surface-rgb), 0.98);
  border-radius: 16px;
  box-shadow: 0 8px 30px rgba(0,0,0,.14);
  border: 1px solid rgba(0,0,0,.06);
  overflow: hidden;
  display: none;
  max-height: 280px;
  overflow-y: auto;
}
#search-results.show { display: block; }
.sr-item {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 16px;
  cursor: pointer;
  border-bottom: 1px solid rgba(0,0,0,.05);
  transition: background .15s;
}
.sr-item:last-child { border-bottom: none; }
.sr-item:hover { background: var(--accent-pale); }
.sr-ico {
  width: 36px; height: 36px; border-radius: 10px;
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; flex-shrink: 0;
}
.sr-name { font-size: 13px; font-weight: 700; color: var(--text); }
.sr-cat  { font-size: 11px; color: var(--text3); font-weight: 500; margin-top: 1px; }

/* ═══════════════════════════════════════
   FILTER BAR — horizontal scroll slider, floats over map
═══════════════════════════════════════ */
#filter-bar {
  position: fixed;
  /* [I3 p2] el espacio de abajo se ajusta en Admin → 🎨 Interfaz (--filtros-bottom, js/filtros-estilo.js); 3px = 35 % del de antes */
  bottom: calc(var(--filtros-bottom, 3px) + env(safe-area-inset-bottom));
  left: 0; right: 0;
  z-index: 500;
  background: none;
  border: none;
  box-shadow: none;
  pointer-events: none;
  /* [FIX 2026-09-07] overflow:hidden acá recortaba la parte de
     arriba de cualquier ícono elevado/agrandado (.fbtn.on, hover, y
     sobre todo el salto animado de categoría→subcategorías, cuya
     curva de rebote se pasa un poco del tamaño final antes de
     asentarse). El scroll horizontal ya lo maneja .filter-row con su
     propio overflow-x — este contenedor no necesita recortar nada. */
  overflow: visible;
}
.filter-row {
  position: relative;
  /* [Etapa E, 2026-09-07] los .fbtn pasan a position:absolute (ver
     más abajo) — ya no aportan altura al contenedor por su cuenta,
     por eso ahora hace falta un alto fijo acá. El ancho scrolleable
     lo da un espaciador invisible que arma categories.js
     (_setFilterRowWidth), no estos hijos absolutos. */
  /* [FIX 2026-09-27] "overflow-y: visible" de acá abajo NO se estaba
     respetando de verdad: por spec, cuando overflow-x no es "visible"
     (acá es "auto" por el scroll horizontal), el navegador fuerza
     overflow-y a computar como "auto" también — o sea, este
     contenedor SIEMPRE recortaba verticalmente, aunque dijera
     "visible". Eso cortaba la sombra del círculo (box-shadow, que
     sangra ~11px hacia arriba) incluso en reposo, y de lleno la parte
     de arriba del botón al agrandarse en hover/click (scale+translate
     hacia arriba). No hay forma de tener scroll horizontal real y
     overflow vertical 100% libre a la vez en CSS puro — la solución
     es darle a este contenedor altura de sobra (82px → 110px, +28px)
     para que quepa el peor caso (sombra + hover + estado .on) sin
     tocar nada, y correr el "top" base de .fbtn la misma cantidad
     (4px → 32px) para que el botón en reposo quede exactamente en el
     mismo lugar de siempre — el espacio extra es todo invisible,
     arriba del botón. */
  height: 110px;
  padding: 6px 20px 4px;
  overflow-x: auto;
  /* [FIX 2026-10-01] el "visible" de acá nunca se respetaba (con overflow-x
     auto, el navegador lo computa como auto) y dejaba la fila arrastrable
     también hacia arriba/abajo. Se declara hidden (el recorte vertical ya
     era el comportamiento real), y touch-action: pan-x hace que el dedo
     solo pueda desplazar a los lados; overscroll-behavior evita que el
     gesto "se escape" y mueva la página o el mapa. */
  overflow-y: hidden;
  touch-action: pan-x;
  overscroll-behavior: contain;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  pointer-events: all;
  cursor: grab;
}
.filter-row:active { cursor: grabbing; }
.filter-row::-webkit-scrollbar { display: none; }

/* [ajuste 2026-09-28, mismo día de la Etapa 14] El botón que abre el
   calendario YA NO tiene barra propia — ahora es el botón circular
   que aparece SOBRE "Eventos" al abrir su esquina (misma animación
   que cualquier categoría con subcategorías reales: `.fbtn`/
   `.fbtn-circle`/`.fbtn-sub`, ver css más abajo y
   js/categories.js `_buildCalendarSubBtn`). Los estilos viejos de la
   barra propia (`#eventos-fecha-bar`, `.efb-wrap`, `.efb-btn`,
   `.efb-chip`, `.efb-clear`) se sacan de acá — ya sin uso, el HTML
   que los usaba desapareció de index.html. Queda solo el popover del
   calendario, ahora anclado directo a `#filter-bar` (`position:
   fixed`, así que sigue siendo el contenedor de referencia para
   `position:absolute` acá abajo, sin necesitar el wrapper propio que
   tenía antes). [FIX] `#filter-bar` tiene `pointer-events: none`
   (deja pasar los toques al mapa por fuera de sus botones) — hace
   falta reactivarlo acá a mano, cosa que antes hacía
   `#eventos-fecha-bar { pointer-events: all; }` y que al sacar ese
   div se hubiera perdido en silencio (el popover se hubiera quedado
   ahí sin recibir NINGÚN click). */
.efb-popover {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 700;
  width: min(320px, calc(100vw - 32px));
  background: rgba(var(--surface-rgb), 0.98);
  border: 1px solid rgba(0,0,0,0.06);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-panel), 0 0 0 1px rgba(var(--accent-rgb), .05);
  padding: 14px;
  pointer-events: auto;
}
.efb-popover[hidden] { display: none; }

/* [Etapa 14] Calendario propio — js/calendario-eventos.js.
   Componente compartido: estos estilos no son exclusivos del popover
   del filtro de mapa, la Etapa 15 los reusa igual dentro de otro
   contenedor. */
.cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}
.cal-title {
  font-family: var(--font-b);
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
  text-transform: capitalize;
}
.cal-nav {
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 50%;
  background: var(--surface2);
  color: var(--text);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  -webkit-tap-highlight-color: transparent;
}
.cal-nav:hover { background: var(--border); }
/* [2026-10-01] Cruz de cierre opcional del calendario (solo si quien lo monta pasa `onClose`:
   hoy el popover del filtro del mapa). Es un .btn-x, más chico para que entre en la cabecera. */
.cal-close { width: 30px; height: 30px; margin-left: 6px; font-size: 12px; }
.cal-week {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  margin-bottom: 2px;
}
.cal-wd {
  text-align: center;
  font-family: var(--font-b);
  font-size: 10px;
  font-weight: 700;
  color: var(--text2);
  text-transform: uppercase;
}
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-auto-rows: 36px;
}
.cal-day {
  border: none;
  background: none;
  cursor: pointer;
  font-family: var(--font-b);
  font-size: 13px;
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  -webkit-tap-highlight-color: transparent;
}
.cal-day--blank { cursor: default; }
.cal-num {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .15s, color .15s;
}
.cal-day.is-today .cal-num { box-shadow: inset 0 0 0 1.5px var(--accent); }
.cal-day.in-range { background: rgba(var(--accent-rgb), .14); }
.cal-day.is-start.is-end { border-radius: 15px; }
.cal-day.is-start { border-radius: 15px 0 0 15px; background: rgba(var(--accent-rgb), .14); }
.cal-day.is-end { border-radius: 0 15px 15px 0; background: rgba(var(--accent-rgb), .14); }
.cal-day.is-selected .cal-num { background: var(--accent); color: #fff; }
.cal-hint {
  min-height: 34px;
  padding: 8px 2px 4px;
  font-family: var(--font-b);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.cal-hint-main { font-size: 13px; color: var(--text); text-transform: capitalize; }
.cal-hint-sub { font-size: 11px; color: var(--text2); }
.cal-actions {
  display: flex;
  gap: 8px;
  margin-top: 6px;
}
.cal-btn {
  flex: 1;
  height: 38px;
  border-radius: 12px;
  border: none;
  font-family: var(--font-b);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: opacity .15s;
}
.cal-btn:disabled { opacity: .4; cursor: default; }
.cal-btn--ghost { background: var(--surface2); color: var(--text); }
.cal-btn--ghost:hover:not(:disabled) { background: var(--border); }
.cal-btn--primary { background: var(--accent); color: #fff; }
.cal-btn--primary:hover:not(:disabled) { opacity: .9; }

/* Each category button — column: circle + label.
   [Etapa E, 2026-09-07] position:absolute + variable CSS
   `--current-x` (cada botón la trae seteada inline, ver
   categories.js _setBtnX) en vez de transform inline directo. */
.fbtn {
  position: absolute;
  /* 4px de siempre + 28px del buffer nuevo del .filter-row (ver nota
     arriba) — el botón en reposo cae en el mismo lugar de siempre. */
  top: 32px;
  left: 0;
  width: 70px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  transition: transform .4s cubic-bezier(.65,0,.35,1), opacity .3s ease;
  outline: none;
  transform: translate(var(--current-x, 0px), 0px);
}
/* [2026-09-28] HOVER DESACTIVADO por pedido: los botones redondos de
   categorías ya no se elevan/agrandan al pasar el mouse. Para reactivarlo,
   descomentar este bloque. El resto de efectos (:active, .on, animaciones
   de entrada/salida) siguen funcionando igual.
.filter-row:not(.is-animating) .fbtn:hover {
  transform: translate(var(--current-x, 0px), -3px) scale(1.05);
}
*/
.filter-row:not(.is-animating) .fbtn:active {
  transform: translate(var(--current-x, 0px), 0px) scale(.92);
}
.fbtn.on { transform: translate(var(--current-x, 0px), -5px) scale(1.1); }
.filter-row.is-animating .fbtn { pointer-events: none; }

/* ONE solid circle — flat color, no extra rings */
.fbtn-circle {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 5px 16px rgba(0,0,0,.25);
  transition: box-shadow .2s;
  /* background set inline per category */
}
.fbtn-circle svg {
  width: 22px;
  height: 22px;
  stroke: var(--filtros-icono, white);  /* [I3 p2] color único de los dibujos (Admin → 🎨 Interfaz) */
  stroke-width: 2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* [I3 p2] círculo único: pisa el color propio de cada categoría solo mientras está activo */
[data-filtros-circulo] .fbtn-circle { background: var(--filtros-circulo) !important; }
.fbtn.on .fbtn-circle {
  box-shadow: 0 7px 22px rgba(0,0,0,.35);
}

/* White label */
.fbtn-label {
  font-size: 10px;
  /* [FIX 2026-09-27] pedido: versión bold real del texto. La fuente
     (Nunito) solo traía cargados los pesos 300–700 (ver <link> de
     Google Fonts en index.html), así que 700 era el tope disponible;
     se sumó el peso 800 al <link> para que esto renderice más grueso
     de verdad y no solo "semibold". */
  font-weight: 800;
  color: white;
  font-family: var(--font-b);
  white-space: nowrap;
  /* [FIX 2026-09-27] pedido: outline negro de 2px, no el blur suave
     de antes (costaba leerlo sobre el mapa claro). El truco de 8
     text-shadows a ±2px es el que da un contorno sólido y parejo en
     todos los navegadores; -webkit-text-stroke suma nitidez extra en
     los que lo soportan (no molesta donde no, porque es del mismo
     color que el shadow). */
  /* [FIX 2026-10-01] se quitó -webkit-text-stroke: 2px #000. Ese trazo se
     dibuja CENTRADO sobre el borde de cada letra, o sea 1px hacia adentro
     tapando el relleno blanco, y con letra de 10px la dejaba toda negra.
     El borde negro externo y la sombra los sigue dando el text-shadow de
     abajo, que se pinta DEBAJO del texto: letra blanca arriba, borde y
     sombra negros por debajo. */
  text-shadow:
    -2px -2px 0 #000, 0 -2px 0 #000, 2px -2px 0 #000,
    -2px  0   0 #000,               2px  0   0 #000,
    -2px  2px 0 #000, 0  2px 0 #000, 2px  2px 0 #000;
  letter-spacing: .2px;
}
.fbtn .dot { display: none; }

/* [Etapa E, PLAN_CATEGORIAS_SUBCATEGORIAS.md] Animación categoría↔
   subcategorías — reusa .fbtn/.fbtn-circle/.fbtn-label tal cual, solo
   agrega la caída/subida con fade. Calcada de la referencia final
   que dio Cris (index.html/styles.css/script.js, 2026-09-07):
   `translate(var(--current-x), Ypx)` — el eje X nunca se pierde
   mientras cae o sube, a diferencia del intento anterior (ver
   AI_SESSION.md) que solo animaba Y y por eso el botón "saltaba" a la
   izquierda al caer. */
.fbtn-exit-down {
  transition: transform .3s cubic-bezier(.65,0,.35,1), opacity .28s ease !important;
  transform: translate(var(--current-x, 0px), 46px) scale(.6) !important;
  opacity: 0 !important;
  pointer-events: none;
}
.fbtn-enter-up {
  opacity: 0;
  transform: translate(var(--current-x, 0px), 46px) scale(.6);
}
.fbtn-enter-up.fbtn-entered {
  transition: transform .34s cubic-bezier(.65,0,.35,1), opacity .3s ease;
  opacity: 1;
  transform: translate(var(--current-x, 0px), 0px) scale(1);
}

/* Dropdown overlay */
#zonas-dropdown {
  position: fixed;
  top: calc(62px + env(safe-area-inset-top));
  left: 12px;
  z-index: 699;
  background: rgba(var(--surface-rgb), 0.98);
  border: 1px solid rgba(0,0,0,0.06);
  border-radius: var(--r-lg);
  min-width: 270px;
  max-width: calc(100vw - 28px);
  box-shadow: var(--shadow-panel), 0 0 0 1px rgba(var(--accent-rgb), .05);
  overflow: hidden;
  transform-origin: top left;
  transform: scale(.92) translate3d(0,-8px,0);
  will-change: transform, opacity;
  opacity: 0;
  pointer-events: none;
  transition: transform .22s cubic-bezier(.34,1.56,.64,1), opacity .18s;
  display: flex; flex-direction: column;
  max-height: calc(100dvh - 100px);
}
#zonas-dropdown.open {
  transform: scale(1) translate3d(0,0,0);
  opacity: 1;
  pointer-events: all;
}
#zonas-list-scroll {
  /* ANTES: overflow-y:auto — en la mayoría de los navegadores/SO
     modernos (scrollbars "overlay"), eso hace que la barra sea
     invisible hasta que el usuario ya está scrolleando, así que no
     era obvio que había más zonas abajo. overflow-y:scroll reserva
     el espacio de la barra siempre, y se le da color de pista/thumb
     no transparente para que se vea sin necesidad de interactuar. */
  overflow-y: scroll;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: var(--border2) var(--surface2);
  flex: 1;
  position: relative;
}
#zonas-list-scroll::-webkit-scrollbar {
  width: 6px;
}
#zonas-list-scroll::-webkit-scrollbar-track {
  background: var(--surface2);
}
#zonas-list-scroll::-webkit-scrollbar-thumb {
  background: var(--border2);
  border-radius: 999px;
}
/* Refuerzo visual adicional, independiente de si el navegador del
   usuario decide mostrar la scrollbar nativa o no: un degradado
   suave pegado abajo del contenedor que insinúa "hay más contenido"
   sin necesitar JS. Se apoya en background-attachment:local, que
   hace que el degradado se "esconda" solo automáticamente cuando ya
   se llegó al final del scroll (truco CSS clásico, sin JS). */
#zonas-list-scroll {
  background:
    linear-gradient(var(--surface) 30%, rgba(var(--surface-rgb), 0)),
    linear-gradient(rgba(var(--surface-rgb), 0), var(--surface) 70%) 0 100%,
    radial-gradient(farthest-side at 50% 0, rgba(var(--text-rgb), .10), rgba(var(--text-rgb), 0)),
    radial-gradient(farthest-side at 50% 100%, rgba(var(--text-rgb), .10), rgba(var(--text-rgb), 0)) 0 100%;
  background-repeat: no-repeat;
  background-color: var(--surface);
  background-size: 100% 24px, 100% 24px, 100% 10px, 100% 10px;
  background-attachment: local, local, scroll, scroll;
}
.zd-header {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; /* [2026-10-01] rótulo + cruz */
  padding: 12px 18px 10px;
  font-family: var(--font-m);
  font-size: 9px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text3);
  border-bottom: 1px solid var(--border);
}
.zd-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 11px 16px;
  cursor: pointer;
  border-bottom: 1px solid rgba(0,0,0,.04);
  transition: background .15s;
  -webkit-tap-highlight-color: transparent;
}
.zd-item:last-child { border-bottom: none; }
.zd-item:hover { background: var(--accent-pale); }
.zd-item:hover .zd-name { color: var(--accent); }
.zd-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  transition: color .15s;
  flex: 1;
}
.zd-info-btn {
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 1.5px solid var(--border2);
  background: transparent;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px;
  font-weight: 700;
  color: var(--text3);
  cursor: pointer;
  flex-shrink: 0;
  transition: all .15s;
  -webkit-tap-highlight-color: transparent;
  font-family: var(--font-m);
  margin-left: 10px;
}
.zd-info-btn:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: white;
}

/* Zona info panel */
#zona-panel {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 710;
  background: rgba(var(--surface-rgb), 0.97);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  border-top: 2px solid rgba(var(--accent-rgb), .15);
  padding-bottom: env(safe-area-inset-bottom);
  transform: translateY(100%) translateZ(0);
  transition: transform .4s cubic-bezier(.16,1,.3,1);
  will-change: transform;
  box-shadow: 0 -12px 40px rgba(0,0,0,.12);
  max-height: 55dvh;
  overflow-y: auto;
  scrollbar-width: none;
}
#zona-panel::-webkit-scrollbar { display: none; }
#zona-panel.open { transform: translateY(0) translateZ(0); }

.zp-handle { width: 36px; height: 4px; background: var(--border); border-radius: 2px; margin: 14px auto 0; }

.zp-head {
  padding: 16px 20px 14px;
  border-bottom: 1px solid rgba(0,0,0,.06);
  display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
}
.zp-name {
  font-family: var(--zonas-title-font, var(--font-d));
  font-size: clamp(18px, var(--zonas-title-size, 26px), 40px);
  color: var(--zonas-title-color, inherit);
  font-weight: 800; letter-spacing: -.3px; line-height: 1;
}
.zp-body { padding: 16px 20px 22px; }

.zp-tag-row {
  display: flex; gap: 7px; flex-wrap: wrap; margin-bottom: 14px;
}
.zp-tag {
  background: var(--accent-pale); border: 1px solid rgba(var(--accent-rgb), .2);
  border-radius: 99px; padding: 4px 12px;
  font-size: 11px; font-weight: 600; color: var(--accent);
}
.zp-attr {
  display: flex; gap: 10px; align-items: flex-start;
  margin-bottom: 9px; font-size: 13px;
}
.zp-attr-label {
  font-family: var(--zonas-section-font, inherit);
  font-size: clamp(9px, var(--zonas-section-size, 13px), 20px);
  font-weight: 700; color: var(--zonas-section-color, var(--text)); min-width: 110px; flex-shrink: 0;
}
.zp-attr-val {
  font-family: var(--zonas-body-font, inherit);
  font-size: clamp(11px, var(--zonas-body-size, 13px), 22px);
  color: var(--zonas-body-color, var(--text2)); line-height: 1.5;
}

.zp-go-btn {
  width: 100%; margin-top: 16px;
  background: linear-gradient(135deg, var(--accent), var(--green-light));
  color: white; border: none;
  border-radius: var(--r); padding: 14px;
  font-family: var(--font-b); font-size: 14px; font-weight: 700;
  cursor: pointer; transition: all .2s;
  box-shadow: 0 6px 18px rgba(var(--accent-rgb), .3);
  -webkit-tap-highlight-color: transparent;
}
.zp-go-btn:hover { transform: translateY(-1px); box-shadow: 0 8px 24px rgba(var(--accent-rgb), .38); }

/* Map blur effect when zona panel open */
#map.zona-blur {
  filter: saturate(0.5) brightness(0.85);
  transition: filter .35s;
}
#map { transition: filter .35s; }

/* ═══════════════════════════════════════
   PIN MARKERS
═══════════════════════════════════════ */
.pin-wrap {
  position: relative; cursor: pointer;
  transform-origin: center center;
  /* Only transition transform — GPU composited, no repaint */
  transition: transform .4s cubic-bezier(.34,1.56,.64,1), opacity .25s;
  will-change: transform;
  contain: layout style;
}
.pin-wrap:hover { transform: scale(1.15) translateY(-4px); }
/* Antes: .pin-wrap.dim aplicaba filter:grayscale(80%) + opacity:.35 a
   TODOS los demás pines cuando uno se expandía — eso era el
   "oscurecimiento" del mapa, y al ser un filtro GPU aplicado a varios
   pines a la vez, generaba los tirones de rendimiento. Se neutraliza
   por completo: el mapa mantiene su brillo y color original, sin
   costo extra de composición. La clase `.dim` puede seguir
   agregándose/quitándose desde el JS sin problema — acá ya no hace
   nada visualmente. */
.pin-wrap.dim { /* sin efecto visual: ver nota arriba */ }
/* Expanded: float high above the panel, stays pinned at base */
.pin-wrap.big {
  /* translate3d forces GPU compositing layer */
  transform: scale(3.2) translate3d(0,0,0) !important;
  z-index: 1200 !important;
  opacity: 1 !important;
  /* filter applied dynamically by applyGlobalOutline() — no hardcoded shadow */
  /* [2026-08-31, PLAN_FIX_ZINDEX_PIN_MAXIMIZADO.md Punto 2] Refuerzo
     de contexto de apilamiento propio, para que el pinch-zoom táctil
     nativo del navegador no reordene esto contra las demás
     miniaturas del mapa. Primer paso, sin confirmar todavía en
     dispositivo real — ver plan para el resto del diagnóstico. */
  isolation: isolate;
}

/* Pin genérico (emoji fallback) */
.pin-head {
  width: 40px; height: 40px;
  border-radius: 50% 50% 50% 4px;
  transform: rotate(-45deg);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 3px 10px rgba(0,0,0,.25), inset 0 1px 0 rgba(255,255,255,.3);
  position: relative; overflow: hidden;
}
.pin-head::after {
  content: '';
  position: absolute; inset: 0; border-radius: inherit;
  background: rgba(255,255,255,.18); opacity: 0; transition: opacity .2s;
}
.pin-wrap:hover .pin-head::after { opacity: 1; }
.pin-emoji { transform: rotate(45deg); font-size: 18px; line-height: 1; display: block; }

/* ── PNG custom image pin ── */
.pin-img-wrap {
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  cursor: pointer;
}
.pin-img {
  width: 44px; height: 44px;
  object-fit: contain;
  /* No filter on img — use wrapper shadow instead (GPU composited) */
  display: block;
  transform-origin: center center;
  -webkit-user-drag: none; user-select: none;
  will-change: transform;
}
/* Shadow on wrapper — controlled by globalSettings.shadowOn via applyShadow() */
.pin-img-wrap {
  /* drop-shadow set dynamically by applyShadow() */
  will-change: filter;
}
.pin-img-shadow {
  width: 12px; height: 4px;
  border-radius: 50%;
  background: rgba(0,0,0,.2);
  filter: blur(3px);
  margin-top: -4px;
  transition: transform .25s;
}
.pin-wrap:hover .pin-img-shadow { transform: scaleX(1.4); }
.pin-img-ripple {
  position: absolute;
  bottom: 0; left: 50%;
  transform: translateX(-50%);
  width: 12px; height: 4px;
  border-radius: 50%;
  /* Antes: animation: imgripple 2.8s ease-out infinite; corría SIEMPRE,
     en los 200 pines a la vez, en reposo — eso es lo que tira el
     rendimiento abajo con muchos pines. Ahora queda estática por
     defecto (mismo look que el primer frame de la animación) y solo
     se anima al pasar el mouse o cuando el pin está seleccionado. */
  opacity: .55;
  animation: none !important;
  pointer-events: none;
}
.pin-wrap:hover .pin-img-ripple,
.pin-wrap.big .pin-img-ripple {
  animation: imgripple 2.8s ease-out infinite !important;
}
@keyframes imgripple {
  0%   { transform: translateX(-50%) scale(1); opacity: .55; }
  100% { transform: translateX(-50%) scale(4); opacity: 0; }
}
.pin-wrap.big .pin-img {
  filter: drop-shadow(0 10px 24px rgba(0,0,0,.55)) drop-shadow(0 3px 8px rgba(0,0,0,.4));
}

/* ── image uploader widget ── */
.img-uploader {
  border: 2px dashed var(--border2);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: all .2s;
  position: relative;
  overflow: hidden;
  background: var(--surface2);
}
.img-uploader:hover { border-color: var(--accent); background: var(--accent-pale); }
.img-uploader input[type=file] {
  position: absolute; inset: 0;
  opacity: 0; cursor: pointer; width: 100%; height: 100%; z-index: 1;
}
.img-uploader-inner {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px;
}
.img-preview-box {
  width: 64px; height: 64px; flex-shrink: 0;
  border-radius: var(--r-sm); background: var(--border);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; font-size: 28px;
  border: 1px solid var(--border);
}
.img-preview-box img { width: 100%; height: 100%; object-fit: contain; }
.img-uploader-text { flex: 1; min-width: 0; }
.img-uploader-text strong { display: block; font-size: 13px; font-weight: 600; color: var(--text); margin-bottom: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.img-uploader-text span { font-size: 11px; color: var(--text3); line-height: 1.4; display: block; }
.img-uploader.has-img { border-color: var(--green); border-style: solid; background: #f0fdf4; }
.img-uploader.has-img:hover { border-color: var(--accent); background: var(--accent-pale); }
.img-uploader.has-img .img-uploader-text strong { color: var(--green); }
.img-clear {
  position: absolute; top: 7px; right: 7px; z-index: 2;
  background: white; border: 1px solid var(--border); border-radius: 50%;
  width: 24px; height: 24px; font-size: 11px;
  cursor: pointer; color: var(--text2);
  display: none; align-items: center; justify-content: center;
  box-shadow: var(--shadow-xs);
  -webkit-tap-highlight-color: transparent;
}
.img-uploader.has-img .img-clear { display: flex; }

/* [NUEVO 2026-08-12] Señal visual de nombre de archivo válido/inválido
   antes de subir a Cloudinary — recuadro de 7px, no desplaza el
   layout (usa outline, no border/margin). */
.img-uploader--name-ok   { outline: 7px solid var(--green);   outline-offset: 2px; }
.img-uploader--name-bad  { outline: 7px solid #ef4444;        outline-offset: 2px; }

/* [NUEVO 2026-08-24] Grilla de miniaturas del gestor de imágenes por
   pin (reemplaza el listado vertical de un uploader completo por
   variante). Ancho fijo por celda con auto-fill: en el panel angosto
   del admin arma ~4-5 columnas solo, sin necesitar breakpoints. */
.img-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  gap: 8px;
  margin-bottom: 12px;
}
.img-grid-thumb {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--r-sm);
  border: 2px solid var(--border);
  overflow: hidden;
  cursor: pointer;
  background: var(--surface2);
  transition: border-color .15s, transform .1s;
  -webkit-tap-highlight-color: transparent;
}
.img-grid-thumb:hover { border-color: var(--accent); }
.img-grid-thumb.is-selected { border-color: var(--accent); border-width: 3px; }
.img-grid-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.img-grid-thumb--add {
  display: flex; align-items: center; justify-content: center;
  border-style: dashed;
}
.img-grid-thumb--inactive img { opacity: .4; }
.img-grid-plus { font-size: 22px; color: var(--text3); font-weight: 300; }
.img-grid-badge {
  position: absolute; top: 3px; left: 3px;
  background: rgba(0,0,0,.65); color: #fff;
  font-size: 10px; font-weight: 700; line-height: 1;
  padding: 3px 5px; border-radius: 999px; min-width: 14px; text-align: center;
}
.img-grid-off {
  position: absolute; bottom: 3px; right: 3px;
  background: #ef4444; color: #fff;
  font-size: 9px; font-weight: 700; line-height: 1;
  padding: 2px 4px; border-radius: 4px;
}
.img-grid-thumb--main {
  border-color: #eab308; cursor: default;
}
.img-grid-thumb--main:hover { border-color: #eab308; }
.img-grid-thumb--main .img-grid-badge { background: #eab308; color: #1a1a1a; }
.img-grid-main-tag {
  position: absolute; bottom: 3px; right: 3px;
  color: #eab308; font-size: 12px; text-shadow: 0 1px 2px rgba(0,0,0,.5);
}
.img-order-hint { font-size: 10px; font-weight: 400; color: var(--text3); }

/* Panel de opciones compartido — un solo bloque, muestra los
   controles de la miniatura seleccionada en .img-grid (el resto de
   los .img-slot-detail quedan armados en el DOM pero ocultos). */
.img-slot-panel { position: relative; }
.img-slot-detail { display: none; }
.img-slot-detail.is-selected { display: block; }
.img-slot-order-row .img-order-input { width: 60px; text-align: center; padding: 4px 6px; flex: none; }
/* [B2] Campo "Sufijo" de cada casillero de la grilla de imágenes (js/img-slots.js) */
.img-slot-sufijo-row .img-sufijo-input { width: 120px; padding: 4px 6px; flex: none; text-transform: lowercase; }
.fi.fi--error { border-color: #ef4444; }

/* Geocoder search — see full styles in bottom block */
.geocoder-input { flex: 1; }
.geocoder-result {
  padding: 10px 14px; font-size: 12px; color: var(--text);
  cursor: pointer; border-bottom: 1px solid var(--border);
  transition: background .15s; line-height: 1.4; background: var(--surface);
}
.geocoder-result:last-child { border-bottom: none; }
.geocoder-result:hover { background: var(--accent-pale); color: var(--accent); }
.geocoder-result strong { display: block; font-weight: 700; }
.geocoder-result span { color: var(--text3); font-size: 11px; }
.geocoder-btn.loading { background: var(--text3); cursor: wait; }
.url-fi { flex: 1; font-size: 13px !important; }
.url-load-btn.loading { background: var(--text3); cursor: wait; }

.pin-ripple {
  position: absolute; top: 0; left: 0;
  width: 40px; height: 40px;
  border-radius: 50% 50% 50% 4px;
  transform: rotate(-45deg);
  animation: ripple 2.8s ease-out infinite;
  pointer-events: none;
  will-change: transform, opacity;
}
@keyframes ripple {
  0%   { transform: rotate(-45deg) scale(1); opacity: .5; }
  100% { transform: rotate(-45deg) scale(2.4); opacity: 0; }
}
.pin-lbl {
  display: none; /* nombre solo aparece en el panel de info, no debajo del pin */
}

/* ═══════════════════════════════════════
   POI PANEL (bottom sheet / side panel)
═══════════════════════════════════════ */
#poi-panel {
  position: fixed;
  bottom: -100%; left: 0; right: 0;
  z-index: 600;
  background: rgba(var(--surface-rgb), 0.98);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  border-top: 2.5px solid rgba(var(--accent-rgb), .18);
  bottom: 0;
  transform: translateY(100%) translateZ(0);
  transition: transform .42s cubic-bezier(.16,1,.3,1), max-height .42s cubic-bezier(.16,1,.3,1);
  will-change: transform;
  max-height: 62dvh;
  overflow-y: auto; scrollbar-width: none;
  box-shadow: 0 -14px 40px rgba(0,0,0,.13);
}
#poi-panel::-webkit-scrollbar { display: none; }
#poi-panel.open { transform: translateY(0) translateZ(0); }
/* Segundo estado: pantalla casi completa, para lectura cómoda cuando
   el negocio agregó muchos bloques de texto. El mapa y la miniatura
   quedan centrados detrás, tal como están — el panel simplemente
   sube y los cubre más. */
#poi-panel.expanded { max-height: 94dvh; }
#poi-panel.dragging { transition: none; } /* sin animación mientras se arrastra con el dedo */

.pp-handle { width: 40px; height: 4px; background: var(--border2); border-radius: 2px; margin: 14px auto 0; cursor: grab; touch-action: none; }
.pp-handle:active { cursor: grabbing; }

.pp-head {
  padding: 12px 18px 12px;
  border-bottom: 1px solid rgba(0,0,0,.07);
}
.pp-icon-box {
  display: none;
}
.pp-meta { flex: 1; min-width: 0; width: 100%; }
.pp-cat {
  font-family: var(--font-m); font-size: 9px;
  letter-spacing: 2px; text-transform: uppercase;
  font-weight: 700; margin-bottom: 4px;
}
.pp-name {
  font-family: var(--font-d); font-size: var(--pp-name-size, 26px); font-weight: 800;
  letter-spacing: -.3px; line-height: 1; margin-bottom: 5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pp-desc { font-size: 13px; color: var(--text2); line-height: 1.5; margin-bottom: 3px; font-weight: 400; }
.pp-coords { font-family: var(--font-m); font-size: 9px; color: var(--text3); }

.btn-x {
  background: var(--surface2); border: 1.5px solid var(--border);
  border-radius: 50%; width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; font-size: 13px; color: var(--text2);
  flex-shrink: 0; transition: all .2s;
  -webkit-tap-highlight-color: transparent;
}
.btn-x:hover { background: #fee2e2; color: #dc2626; border-color: #fca5a5; }

/* Style switcher */
.pp-styles {
  padding: 12px 18px;
  border-bottom: 1px solid rgba(0,0,0,.05);
}
.sec-lbl {
  font-family: var(--font-b); font-size: 10px; letter-spacing: 1px;
  text-transform: uppercase; color: var(--text3); margin-bottom: 10px; font-weight: 700;
  display: flex; align-items: center; gap: 8px;
}
.sec-lbl::after { content:''; flex:1; height:1px; background:rgba(0,0,0,.06); }
.style-row { display: flex; gap: 7px; overflow-x: auto; scrollbar-width: none; }
.style-row::-webkit-scrollbar { display: none; }
@keyframes eyeglow {
  0%,100% { 
    filter: drop-shadow(0 0 3px var(--eye-glow-color, #60a5fa)) drop-shadow(0 0 6px var(--eye-glow-color, #60a5fa));
    opacity:.85; 
    transform: scale(1);
  }
  50% { 
    filter: drop-shadow(0 0 8px var(--eye-glow-color, #60a5fa)) drop-shadow(0 0 16px var(--eye-glow-color, #60a5fa)) drop-shadow(0 0 24px var(--eye-glow-color, #60a5fa));
    opacity:1; 
    transform: scale(1.12);
  }
}
/* pp-vis-thumb and sty-btn are defined in the comprehensive style block below */

/* Sections */
.pp-sec { padding: 10px 18px; border-bottom: 1px solid rgba(0,0,0,.05); }
.pp-sec:last-child { border-bottom: none; padding-bottom: calc(22px + env(safe-area-inset-bottom)); }

/* Events */
.ev-scroll { display: flex; gap: 10px; overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
.ev-scroll::-webkit-scrollbar { display: none; }
.ev-card {
  flex-shrink: 0; width: 185px;
  background: linear-gradient(135deg, #f7fcf8, #f0f7f2);
  border: 1px solid rgba(var(--accent-rgb), .15);
  border-radius: var(--r); padding: 12px;
  transition: transform .2s, box-shadow .2s;
}
.ev-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); }
.ev-date { font-family: var(--font-m); font-size: 9px; color: var(--accent); margin-bottom: 4px; letter-spacing: .5px; font-weight: 600; }
.ev-title { font-weight: 700; font-size: 13px; margin-bottom: 3px; line-height: 1.3; color: var(--text); }
.ev-type { font-size: 10px; color: var(--text3); font-weight: 500; }

/* Trivia */
.trivia-box {
  background: linear-gradient(135deg, #edf7ef, #e8f4fd);
  border: 1px solid rgba(var(--accent-rgb), .15); border-radius: var(--r);
  padding: 14px; display: flex; gap: 11px; align-items: flex-start;
}
.trivia-ico { font-size: 20px; flex-shrink: 0; margin-top: 1px; }
.trivia-txt { font-size: 12.5px; color: var(--text2); line-height: 1.5; }
.trivia-txt strong { color: var(--accent); font-weight: 700; }

/* Social */
.soc-row { display: flex; gap: 7px; flex-wrap: wrap; }
.poi-tag {
  display: inline-block;
  background: var(--accent-pale); border: 1px solid rgba(var(--accent-rgb), .15);
  border-radius: 99px; padding: 3px 10px;
  font-size: 10px; font-weight: 600; color: var(--accent);
  margin: 2px 2px 2px 0;
}
.poi-tag-row { margin-bottom: 6px; flex-wrap: wrap; }

.soc-chip {
  background: var(--surface2); border: 1.5px solid var(--border);
  border-radius: 99px; padding: 6px 13px;
  font-size: 11px; font-weight: 600; color: var(--text2);
  text-decoration: none; display: flex; align-items: center; gap: 5px;
  transition: all .18s; box-shadow: var(--shadow-xs);
}
.soc-chip:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-pale); transform: translateY(-1px); }

/* ═══════════════════════════════════════
   ADMIN OVERLAY + PANEL
═══════════════════════════════════════ */
#overlay {
  position: fixed; inset: 0;
  background: rgba(var(--text-rgb), .3);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: 700;
  opacity: 0; pointer-events: none;
  transition: opacity .3s;
}
#overlay.on { opacity: 1; pointer-events: all; }

#admin {
  position: fixed;
  top: 0; right: -440px;
  width: 420px; max-width: 100vw; height: 100dvh;
  z-index: 800;
  background: var(--surface2);
  border-left: 1px solid rgba(0,0,0,.06);
  display: flex; flex-direction: column;
  transition: right .4s cubic-bezier(.16,1,.3,1);
  box-shadow: var(--shadow-lg);
}
#admin.open { right: 0; }

.admin-hd {
  padding: 0 20px;
  height: 60px;
  display: flex; align-items: center; justify-content: space-between;
  border-bottom: 1px solid var(--border);
  background: rgba(var(--surface-rgb), .98);
  flex-shrink: 0;
}
.admin-title {
  font-family: var(--font-d); font-size: 20px; font-weight: 800; letter-spacing: .3px;
  display: flex; align-items: center; gap: 8px; color: var(--text);
}

.admin-tabs {
  display: flex; border-bottom: 1px solid var(--border);
  background: rgba(var(--surface-rgb), .98); flex-shrink: 0;
}
.atab {
  flex: 1; padding: 4px 8px;
  font-size: 11px; font-weight: 700; color: var(--text3);
  cursor: pointer; text-align: center;
  border-bottom: 2.5px solid transparent;
  transition: all .2s; -webkit-tap-highlight-color: transparent;
  font-family: var(--font-b);
}
.atab.on { color: var(--accent); border-bottom-color: var(--accent); }

/* Slider de scroll horizontal para las pestañas del admin — el borde de
   2.5px que marca la pestaña activa no alcanza para agarrar y arrastrar
   cómodo, así que esto agrega una barra bien visible (triple de alta)
   justo debajo, sincronizada con el scroll de .admin-tabs. */
.atabs-slider-track {
  height: 7.5px;
  background: rgba(0,0,0,.06);
  flex-shrink: 0;
  position: relative;
  cursor: pointer;
}
.atabs-slider-thumb {
  position: absolute;
  top: 0; left: 0;
  height: 100%;
  background: var(--accent);
  border-radius: 4px;
  cursor: grab;
  touch-action: none;
}
.atabs-slider-thumb:active { cursor: grabbing; }

/* POI list */
.poi-row {
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r);
  padding: 12px 14px;
  margin-bottom: 9px;
  display: flex; gap: 11px; align-items: center;
  transition: border-color .18s, box-shadow .18s, transform .18s;
  box-shadow: var(--shadow-xs);
}
.poi-row:hover { border-color: var(--accent); box-shadow: 0 4px 16px rgba(var(--accent-rgb), .12); transform: translateY(-1px); }
/* Pin sin ciudad asignada — visible sobre todo con el filtro "Mostrar
   todo" del dropdown Ciudad, donde aparecen pines que el filtro
   geográfico normal nunca deja ver. */
.poi-row.poi-row--sin-ciudad { border-color: #ef4444; border-width: 2px; }
.poi-row-ico {
  width: 42px; height: 42px; border-radius: var(--r);
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; flex-shrink: 0;
  box-shadow: var(--shadow-xs);
}
.poi-row-info { flex: 1; min-width: 0; }
.poi-row-name { font-weight: 700; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.poi-row-cat { font-size: 11px; color: var(--text3); margin-top: 2px; font-weight: 600; }
.poi-row-btns { display: flex; gap: 5px; flex-shrink: 0; }

.ibtn {
  background: var(--surface2); border: 1.5px solid var(--border);
  border-radius: 8px; width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; font-size: 13px; color: var(--text2);
  transition: all .15s; -webkit-tap-highlight-color: transparent;
}
.ibtn:hover { background: var(--accent-pale); color: var(--accent); border-color: var(--accent); }
.ibtn.del:hover { background: #fee2e2; color: #dc2626; border-color: #fca5a5; }

/* Forms */
.fg { margin-bottom: 15px; }
.fl {
  display: block; font-size: 10.5px; font-weight: 700;
  color: var(--text2); margin-bottom: 6px;
  text-transform: uppercase; letter-spacing: .8px;
  font-family: var(--font-b);
}
.fi, .fs, .fta {
  width: 100%;
  background: var(--surface); border: 1.5px solid var(--border);
  border-radius: var(--r-ctrl); padding: 3px 14px;
  font-family: var(--font-b); font-size: 14px; color: var(--text);
  outline: none; transition: border-color .2s, box-shadow .2s;
  -webkit-appearance: none;
  box-shadow: var(--shadow-xs);
}
.fi:focus, .fs:focus, .fta:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .12);
  background: var(--surface);
}
.fta { resize: vertical; min-height: 80px; }

/* Dropdowns de ubicación en la tab "Lugares" (list-filter-country/
   province/city): fondo verde cuando la ciudad elegida ahí coincide
   con la Ubicación Activa de la tab "Ubicaciones", fondo rojo con
   texto blanco cuando el admin la cambió a otra ciudad para previsualizar
   otro lugar — evita confundir "lo que estoy viendo" con "a dónde
   suben las imágenes nuevas ahora mismo". Sin ninguna clase = todavía
   no se eligieron las 3 (estado neutro, ver renderList()). */
.loc-filter-match {
  background: var(--accent) !important; border-color: var(--accent) !important;
  color: #fff !important;
}
.loc-filter-match option { color: var(--text); background: var(--surface); }
.loc-filter-mismatch {
  background: #c0392b !important; border-color: #c0392b !important;
  color: #fff !important;
}
.loc-filter-mismatch option { color: var(--text); background: var(--surface); }

.frow { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
/* Como .frow pero apilada en 1 sola columna — para el filtro de
   ubicación de "Lugares" (país/provincia/ciudad, 1 sobre otro). No
   se reusa .frow para esto porque .frow ya se usa en decenas de
   lugares como grilla de 2 columnas y no hay que tocar esos. */
.frow-col { display: grid; grid-template-columns: 1fr; gap: 8px; }

/* Emoji grid */
.egrid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 7px; margin-top: 8px; }
.eopt {
  aspect-ratio: 1; background: var(--surface);
  border: 1.5px solid var(--border); border-radius: var(--r-ctrl);
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; cursor: pointer;
  transition: all .15s; -webkit-tap-highlight-color: transparent;
  box-shadow: var(--shadow-xs);
}
.eopt:hover { border-color: var(--accent); background: var(--accent-pale); transform: scale(1.07); }
.eopt.sel { border-color: var(--accent); background: var(--accent-pale); outline: 2.5px solid var(--accent); outline-offset: 1px; }

/* Coord pick zone */
.coord-display {
  background: var(--surface); border: 1.5px dashed var(--border2);
  border-radius: var(--r); padding: 11px 14px;
  font-family: var(--font-m); font-size: 11px; color: var(--text3);
  margin-bottom: 8px; transition: all .2s;
}
.coord-display.set { border-color: var(--green); color: var(--green); background: #edf7ef; }

/* Buttons */
.btn-primary {
  width: 100%; background: linear-gradient(135deg, var(--accent), var(--green-light)); border: none;
  border-radius: var(--r-ctrl); padding: 3px 13px;
  font-family: var(--font-b); font-size: 14px; font-weight: 700; color: white;
  cursor: pointer; transition: all .22s; margin-top: 6px;
  box-shadow: 0 6px 18px rgba(var(--accent-rgb), .28);
  -webkit-tap-highlight-color: transparent;
}
.btn-primary:hover { transform: translateY(-1px) scale(1.01); box-shadow: 0 10px 26px rgba(var(--accent-rgb), .35); }
.btn-primary:active { transform: translateY(0) scale(0.99); }
.btn-outline {
  width: 100%; background: transparent;
  border: 1.5px solid var(--border); border-radius: var(--r-ctrl); padding: 3px 12px;
  font-family: var(--font-b); font-size: 14px; font-weight: 600; color: var(--text2);
  cursor: pointer; transition: all .2s; margin-top: 7px;
  -webkit-tap-highlight-color: transparent;
}
.btn-outline:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-pale); }

.btn-map-pick {
  width: 100%; background: var(--surface);
  border: 1.5px dashed var(--border2); border-radius: var(--r-ctrl); padding: 3px 11px;
  font-family: var(--font-b); font-size: 13px; font-weight: 600; color: var(--text2);
  cursor: pointer; transition: all .2s; display: flex; align-items: center;
  justify-content: center; gap: 6px;
  -webkit-tap-highlight-color: transparent;
  box-shadow: var(--shadow-xs);
}
.btn-map-pick:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-pale); }

/* ═══════════════════════════════════════
   PICK BANNER
═══════════════════════════════════════ */
#pick-banner {
  position: fixed; top: 70px; left: 50%;
  transform: translateX(-50%) translateY(-8px);
  z-index: 1000;
  background: linear-gradient(135deg, var(--accent), var(--green-light)); color: white;
  border-radius: 99px; padding: 10px 22px;
  font-size: 13px; font-weight: 700; font-family: var(--font-b);
  box-shadow: 0 8px 24px rgba(var(--accent-rgb), .35);
  white-space: nowrap;
  display: flex; align-items: center; gap: 8px;
  opacity: 0; pointer-events: none;
  transition: opacity .3s, transform .3s;
}
#pick-banner.on { opacity: 1; transform: translateX(-50%) translateY(0); }
#pick-banner-cancel {
  background: rgba(255,255,255,.25); border: none;
  border-radius: 99px; padding: 4px 12px;
  font-size: 12px; font-weight: 700; color: white;
  cursor: pointer; pointer-events: all;
  -webkit-tap-highlight-color: transparent;
}

/* ═══════════════════════════════════════
   CONFIRM MODAL
═══════════════════════════════════════ */
#modal-confirm {
  position: fixed; inset: 0; z-index: 1200;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  opacity: 0; pointer-events: none;
  transition: opacity .2s;
}
#modal-confirm.on { opacity: 1; pointer-events: all; }

/* [2026-10-06] Se eliminó el login de administrador propio (ex #admin-login-*):
   el admin entra por el login público (#user-auth-overlay). */

/* [Etapa 1, PLAN_USUARIOS_EVENTOS.md] LOGIN/REGISTRO PÚBLICO —
   mismo patrón visual que el ex #admin-login-overlay (overlay + caja
   centrada), con tabs y selector de tipo de cuenta agregados. */
#user-auth-overlay {
  position: fixed; inset: 0; z-index: 1300;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  opacity: 0; pointer-events: none;
  transition: opacity .2s;
}
#user-auth-overlay.on { opacity: 1; pointer-events: all; }
#user-auth-overlay::before {
  content: ''; position: absolute; inset: 0;
  background: rgba(0,0,0,.5);
  backdrop-filter: blur(4px);
}
#user-auth-box {
  position: relative; background: rgba(var(--surface-rgb), 0.98);
  border-radius: var(--r-lg); padding: 26px 24px;
  width: 100%; max-width: 340px;
  box-shadow: var(--shadow-panel);
  border: 1px solid rgba(0,0,0,.06);
  display: flex; flex-direction: column; gap: 10px;
}
#user-auth-close {
  position: absolute; top: 10px; right: 10px;
  background: none; border: none; cursor: pointer;
  font-size: 16px; color: var(--text3); padding: 4px;
}
#user-auth-tabs { display: flex; gap: 6px; margin-bottom: 4px; }
.user-auth-tab {
  flex: 1; padding: 9px 6px; border: none; border-radius: var(--r-sm);
  background: rgba(0,0,0,.05); color: var(--text3);
  font-family: var(--font-b); font-size: 13px; font-weight: 700;
  cursor: pointer; transition: all .15s;
}
.user-auth-tab.active { background: var(--accent); color: white; }
.user-auth-pane { display: none; flex-direction: column; gap: 10px; }
.user-auth-pane.on { display: flex; }
.user-auth-pane input[type="text"],
.user-auth-pane input[type="email"],
.user-auth-pane input[type="password"] {
  padding: 12px 14px; border-radius: var(--r-sm);
  border: 1px solid var(--border2); font-size: 14px; font-family: var(--font-b);
  width: 100%; box-sizing: border-box;
}
.user-auth-pane input:focus { outline: none; border-color: var(--accent); }
.user-auth-error { color: #d9432b; font-size: 13px; min-height: 16px; margin: 0; text-align: center; }
.user-auth-divider {
  display: flex; align-items: center; gap: 8px;
  color: var(--text3); font-size: 12px; margin: 2px 0;
}
.user-auth-divider::before, .user-auth-divider::after {
  content: ''; flex: 1; height: 1px; background: var(--border2);
}
.user-auth-google-btn {
  padding: 11px 14px; border-radius: var(--r-sm);
  border: 1px solid var(--border2); background: white;
  font-family: var(--font-b); font-size: 14px; font-weight: 600;
  cursor: pointer; transition: all .15s;
}
.user-auth-google-btn:hover { background: rgba(0,0,0,.03); }
.user-auth-rol-picker { display: flex; flex-direction: column; gap: 8px; }
.user-auth-rol-opt {
  display: grid;
  grid-template-columns: auto 1fr; grid-template-rows: auto auto;
  column-gap: 10px; align-items: center;
  padding: 10px 12px; border-radius: var(--r-sm);
  border: 1px solid var(--border2); cursor: pointer;
  transition: all .15s;
}
.user-auth-rol-opt:has(input:checked) { border-color: var(--accent); background: rgba(var(--accent-rgb), .06); }
.user-auth-rol-opt input[type="radio"] { grid-row: 1 / 3; }
.user-auth-rol-opt span { font-family: var(--font-b); font-size: 14px; font-weight: 700; }
.user-auth-rol-opt small { font-size: 12px; color: var(--text3); }
.user-auth-google-role-intro { font-size: 14px; text-align: center; margin: 0 0 4px; }
.user-auth-cancel-btn {
  background: none; border: none; color: var(--text3);
  font-family: var(--font-b); font-size: 13px; cursor: pointer;
  padding: 4px;
}
/* [2026-10-06] Cambiar contraseña — ver js/user-auth.js, doUserChangePassword */
.user-auth-pass-title {
  font-family: var(--font-d); font-size: 17px; font-weight: 800;
  text-align: center; margin: 0 0 2px;
}
.user-auth-error.ok { color: #1f9d55; }

/* [Etapa 6, PLAN_USUARIOS_EVENTOS.md] Panel de usuario unificado —
   3 solapas (Info/Pines/Eventos), mismo lenguaje visual que ya usaban
   el mini panel de cuenta y el panel del dueño (Etapa 1/2), ahora en
   un solo overlay. Reemplaza a #user-account-overlay/#owner-panel-overlay. */
#user-panel-overlay {
  position: fixed; inset: 0; z-index: 1300;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  opacity: 0; pointer-events: none;
  transition: opacity .2s;
}
#user-panel-overlay.on { opacity: 1; pointer-events: all; }
#user-panel-overlay::before {
  content: ''; position: absolute; inset: 0;
  background: rgba(0,0,0,.5); backdrop-filter: blur(4px);
}
#user-panel-box {
  position: relative; background: rgba(var(--surface-rgb), 0.98);
  border-radius: var(--r-lg); padding: 26px 24px;
  width: 100%; max-width: 420px; max-height: 85vh; overflow-y: auto;
  box-shadow: var(--shadow-panel);
  border: 1px solid rgba(0,0,0,.06);
}
#user-panel-close {
  position: absolute; top: 10px; right: 10px;
  background: none; border: none; cursor: pointer;
  font-size: 16px; color: var(--text3); padding: 4px;
}
#user-panel-tabs { display: flex; gap: 6px; margin: 4px 0 16px; }
.user-panel-tab {
  flex: 1; padding: 9px 6px; border: none; border-radius: var(--r-sm);
  background: rgba(0,0,0,.05); color: var(--text3);
  font-family: var(--font-b); font-size: 13px; font-weight: 700;
  cursor: pointer; transition: all .15s;
}
.user-panel-tab.active { background: var(--accent); color: white; }
.user-panel-pane { display: none; flex-direction: column; gap: 10px; }
.user-panel-pane.on { display: flex; }
#up-pane-info { align-items: center; text-align: center; }
#user-account-name { font-family: var(--font-b); font-weight: 700; font-size: 16px; }
#user-account-role { font-size: 13px; color: var(--text3); margin-bottom: 6px; }

.owner-panel-loading { font-size: 13px; color: var(--text3); text-align: center; margin: 14px 0; }
#owner-panel-empty { font-size: 13px; color: var(--text3); text-align: center; line-height: 1.5; margin: 14px 0; }
#owner-panel-list { display: flex; flex-direction: column; gap: 8px; }
.owner-panel-item {
  display: flex; justify-content: space-between; align-items: center; gap: 8px;
  padding: 12px 14px; border-radius: var(--r-sm);
  border: 1px solid var(--border2); background: white;
  cursor: pointer; text-align: left; transition: all .15s;
  font-family: var(--font-b);
}
.owner-panel-item:hover { border-color: var(--accent); background: rgba(var(--accent-rgb), .05); }
.owner-panel-item-name { font-weight: 700; font-size: 14px; }
.owner-panel-item-cat { font-size: 11px; color: var(--text3); }
#owner-panel-form { display: none; flex-direction: column; }
#owner-panel-form.on { display: flex; }
#owner-edit-name { margin: 0 0 12px; font-size: 16px; }
.owner-panel-back-inline {
  align-self: flex-start;
  background: none; border: none; color: var(--accent);
  font-family: var(--font-b); font-size: 13px; font-weight: 700;
  cursor: pointer; padding: 4px 0; margin-bottom: 4px;
}
.owner-field-row {
  border: 1px solid var(--border2); border-radius: var(--r-sm);
  padding: 10px; margin-bottom: 8px;
  display: flex; flex-direction: column; gap: 6px; position: relative;
}
.owner-field-title, .owner-field-text {
  padding: 8px 10px; border-radius: 8px; border: 1px solid var(--border2);
  font-family: var(--font-b); font-size: 13px; width: 100%; box-sizing: border-box;
}
.owner-field-text { resize: vertical; }
.owner-field-remove {
  position: absolute; top: 6px; right: 6px;
  background: none; border: none; color: var(--text3);
  cursor: pointer; font-size: 13px; padding: 2px 6px;
}
.owner-field-remove:hover { color: #d9432b; }
.owner-panel-add-field-btn {
  background: none; border: 1px dashed var(--border2); border-radius: var(--r-sm);
  padding: 8px; width: 100%; cursor: pointer;
  font-family: var(--font-b); font-size: 13px; color: var(--accent);
  margin-top: 4px;
}
#modal-confirm::before {
  content: ''; position: absolute; inset: 0;
  background: rgba(0,0,0,.4);
  backdrop-filter: blur(4px);
}
.modal-box {
  position: relative; background: rgba(var(--surface-rgb), 0.98);

  border-radius: var(--r-lg); padding: 30px 26px;
  width: 100%; max-width: 330px;
  box-shadow: var(--shadow-panel); text-align: center;
  border: 1px solid rgba(0,0,0,.06);
}
.modal-icon { font-size: 42px; margin-bottom: 14px; }
.modal-box h3 { font-family: var(--font-d); font-size: 24px; margin-bottom: 7px; font-weight: 800; }
.modal-box p { color: var(--text2); font-size: 14px; margin-bottom: 24px; line-height: 1.55; }
.modal-btns { display: flex; gap: 10px; }
.modal-btns button {
  flex: 1; padding: 8px 13px; border-radius: var(--r-ctrl);
  font-size: 14px; font-weight: 700; cursor: pointer; font-family: var(--font-b);
  border: none; transition: all .18s;
}
.btn-cancel-m { background: var(--surface2); color: var(--text2); border: 1.5px solid var(--border) !important; }
.btn-cancel-m:hover { background: var(--border); }
.btn-delete-m { background: #dc2626; color: white; box-shadow: 0 4px 14px rgba(220,38,38,.3); }
.btn-delete-m:hover { background: #b91c1c; transform: translateY(-1px); }

/* ═══════════════════════════════════════
   TOAST
═══════════════════════════════════════ */
#toast {
  position: fixed; bottom: 84px; left: 50%;
  transform: translateX(-50%) translateY(12px);
  z-index: 1500;
  background: rgba(var(--text-rgb), .92); color: white;
  border-radius: 99px; padding: 11px 20px;
  font-size: 13px; font-weight: 600; font-family: var(--font-b);
  box-shadow: 0 8px 24px rgba(0,0,0,.2);
  white-space: nowrap;
  opacity: 0; pointer-events: none;
  transition: all .28s;
  backdrop-filter: blur(8px);
}
#toast.on { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ═══════════════════════════════════════
   RESPONSIVE — DESKTOP SIDE PANEL
═══════════════════════════════════════ */
@media (min-width: 768px) {
  #poi-panel {
    left: 20px; right: auto; bottom: 20px !important;
    width: 390px; border-radius: var(--r-lg);
    border: 1.5px solid rgba(var(--accent-rgb), .15);
    max-height: 74vh;
    transition: transform .42s cubic-bezier(.16,1,.3,1), opacity .3s;
    transform: translateX(-120%) !important;
    box-shadow: var(--shadow-panel);
    background: rgba(var(--surface-rgb), 0.98);
  }
  #poi-panel.open { transform: translateX(0) !important; }
  .pp-handle { display: none; }
}

/* Map cursor when picking */
#map.picking { cursor: crosshair !important; }
#map.picking * { cursor: crosshair !important; }

/* Exportar todo (A4: el Importar viejo se quitó) */
.data-actions {
  display: flex; gap: 8px; margin-bottom: 16px;
}
.btn-export {
  flex: 1; background: linear-gradient(135deg, var(--text), #2d4d2d); color: white; border: none;
  border-radius: var(--r-ctrl); padding: 3px 8px;
  font-family: var(--font-b); font-size: 12px; font-weight: 700;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  gap: 5px; transition: all .2s;
  box-shadow: 0 4px 14px rgba(var(--text-rgb), .2);
  -webkit-tap-highlight-color: transparent;
}
.btn-export:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(var(--text-rgb), .3); }

/* Restaurar desde copia (A5) — panel armado por js/data-io.js */
.btn-restore {
  flex: 1; background: transparent; color: var(--text); border: 1.5px solid var(--text);
  border-radius: var(--r-ctrl); padding: 3px 8px;
  font-family: var(--font-b); font-size: 12px; font-weight: 700; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.restore-panel {
  border: 1px solid rgba(var(--text-rgb), .2); border-radius: 10px; padding: 10px;
  margin: 0 0 14px; font-size: 12px; color: var(--text); word-break: break-word;
  display: flex; flex-direction: column; gap: 6px;
}
.restore-panel[hidden] { display: none; }
.restore-head { display: flex; flex-direction: column; gap: 2px; font-size: 11px; color: var(--text3); position: relative; padding-right: 80px; }
.restore-head > div:first-child { color: var(--text); }
.restore-cancel { position: absolute; top: 0; right: 0; background: none; border: none; color: var(--text3); font-size: 11px; cursor: pointer; }
.restore-sub { font-weight: 700; margin-top: 6px; }
.restore-col { padding: 2px 0; }
.restore-col.off { color: var(--text3); font-size: 11px; }
.restore-col.bad { color: #dc2626; font-size: 11px; }
.restore-check { display: flex; align-items: flex-start; gap: 6px; cursor: pointer; }
.restore-check input { margin-top: 2px; flex: 0 0 auto; }
.restore-del { color: #dc2626; font-size: 11px; margin-top: 4px; }
.restore-link { align-self: flex-start; background: none; border: none; padding: 0; color: var(--text); text-decoration: underline; font-size: 11px; cursor: pointer; }
.restore-diff { border-left: 3px solid rgba(var(--text-rgb), .25); padding: 4px 8px; font-size: 11px; display: flex; flex-direction: column; gap: 2px; }
.restore-red { color: #dc2626; font-weight: 700; }
.restore-warn { background: rgba(220, 38, 38, .08); border: 1px solid rgba(220, 38, 38, .4); color: #b91c1c; border-radius: 8px; padding: 8px; font-size: 11px; display: flex; flex-direction: column; gap: 4px; }
.restore-ok { background: rgba(22, 163, 74, .08); border: 1px solid rgba(22, 163, 74, .4); border-radius: 8px; padding: 8px; font-size: 11px; display: flex; flex-direction: column; gap: 2px; }
.restore-note { font-size: 11px; color: var(--text3); }
.restore-go {
  background: #dc2626; color: #fff; border: none; border-radius: var(--r-ctrl); padding: 6px 8px;
  font-family: var(--font-b); font-size: 12px; font-weight: 700; cursor: pointer;
}
.restore-go:disabled, .restore-panel .btn-export:disabled, .restore-link:disabled { opacity: .45; cursor: not-allowed; }

/* Empty state */
.empty-state {
  padding: 24px 0; text-align: center;
  color: var(--text3); font-size: 13px;
}
.empty-state .big { font-size: 32px; margin-bottom: 8px; }

.color-preset {
  width: 28px; height: 28px; border-radius: 6px;
  cursor: pointer; border: 2px solid transparent;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; transition: all .15s;
  -webkit-tap-highlight-color: transparent;
}
.color-preset:hover { transform: scale(1.15); border-color: var(--text); }
.color-preset.sel { border-color: var(--accent); outline: 2px solid var(--accent); outline-offset: 1px; }

.rm-item {
  background: var(--surface); border: 1.5px solid var(--border);
  border-radius: var(--r); padding: 13px 14px; margin-bottom: 9px;
  position: relative; box-shadow: var(--shadow-xs);
  transition: box-shadow .18s;
}
.rm-item:hover { box-shadow: var(--shadow-sm); }
.rm-item-head {
  display: flex; align-items: center; gap: 7px; margin-bottom: 5px;
}
.rm-badge {
  font-size: 10px; font-weight: 700; padding: 3px 9px;
  border-radius: 99px; white-space: nowrap;
}
.rm-title { font-weight: 700; font-size: 13px; flex: 1; }
.rm-desc  { font-size: 12.5px; color: var(--text2); line-height: 1.55; }
.rm-delete {
  position: absolute; top: 9px; right: 9px;
  background: none; border: none; font-size: 13px;
  color: var(--text3); cursor: pointer; padding: 3px 6px;
  border-radius: 6px;
  -webkit-tap-highlight-color: transparent;
}
.rm-delete:hover { color: var(--danger, #dc2626); background: #fee2e2; }

/* Zonas admin */
.za-row {
  background: var(--surface); border: 1.5px solid var(--border);
  border-radius: var(--r); padding: 10px 12px;
  margin-bottom: 8px;
  display: flex; align-items: center; gap: 9px;
  box-shadow: var(--shadow-xs);
  transition: box-shadow .15s;
}
.za-row:hover { box-shadow: var(--shadow-sm); }
.za-drag { color: var(--text3); cursor: grab; font-size: 16px; flex-shrink:0; touch-action: none; }
.za-drag:active { cursor: grabbing; }
.za-name { flex:1; font-size:13px; font-weight:600; }
.za-toggle {
  width: 38px; height: 22px; border-radius: 99px;
  background: var(--border2); border: none; cursor: pointer;
  position: relative; transition: background .2s; flex-shrink:0;
  -webkit-tap-highlight-color: transparent;
}
.za-toggle::after {
  content:''; position:absolute; top:3px; left:3px;
  width:16px; height:16px; border-radius:50%;
  background:white; box-shadow:0 1px 4px rgba(0,0,0,.2);
  transition: transform .2s;
}
.za-toggle.on { background: var(--green); }
.za-toggle.on::after { transform: translateX(16px); }
.za-edit-btn {
  background: var(--surface2); border: 1.5px solid var(--border);
  border-radius: 8px; width:30px; height:30px;
  display:flex; align-items:center; justify-content:center;
  font-size:13px; cursor:pointer; flex-shrink:0;
  -webkit-tap-highlight-color:transparent; transition: all .15s;
}
.za-edit-btn:hover { background:var(--accent-pale); color:var(--accent); border-color:var(--accent); }

/* Divider with label */
.divider { display: flex; align-items: center; gap: 10px; margin: 18px 0; }
.divider::before, .divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }
.divider span { font-size: 9.5px; color: var(--text3); font-family: var(--font-m); letter-spacing: 1.2px; white-space: nowrap; }

/* ═══════════════════════════════════════
   LEAFLET CONTROL adjustments for taller header
═══════════════════════════════════════ */

/* Tpane background */
.tpane { display: none; padding: 18px 20px; }
.tpane.on { display: block; }
.admin-body { flex: 1; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--border) transparent; background: var(--surface2); position: relative; }

/* === FLECHAS INDICADORAS DE SCROLL — patrón reutilizable en toda la app ===
   Se agregan automáticamente por JS (ver scroll-hints.js) a cualquier
   contenedor marcado con [data-scroll-hint]. Aparecen solo cuando hay
   más contenido oculto en esa dirección, y desaparecen al llegar al final.
   IMPORTANTE: pointer-events queda SIEMPRE en 'none' (nunca reciben
   clicks) — se detectó que, al ser "sticky" en la parte de abajo,
   podían quedar tapando botones reales (ej. "Guardar Lugar") e
   interceptar el toque en vez de dejarlo pasar. Quedan solo como
   indicador visual, sin la comodidad de "tocar para scrollear". */
.scroll-hint-arrow {
  position: sticky; left: 0; right: 0; z-index: 5;
  display: flex; align-items: center; justify-content: center;
  height: 22px; margin: 0 -20px; pointer-events: none;
  opacity: 0; transition: opacity .2s ease;
  background: linear-gradient(var(--dir-from), var(--dir-to));
  font-size: 11px; color: var(--text3);
}
.scroll-hint-arrow.visible { opacity: 1; } /* pointer-events queda siempre en 'none' — ver nota arriba */
.scroll-hint-arrow.top    { top: 0;    --dir-from: rgba(250,252,250,1); --dir-to: rgba(250,252,250,0); }
.scroll-hint-arrow.bottom { bottom: 0; --dir-from: rgba(250,252,250,0); --dir-to: rgba(250,252,250,1); }

/* Variante horizontal — para filas de chips/categorías que se desplazan a los lados */
.scroll-hint-arrow.left, .scroll-hint-arrow.right {
  top: 0; bottom: 0; height: auto; width: 22px; margin: 0;
  background: linear-gradient(to var(--h-dir), var(--dir-from), var(--dir-to));
}
.scroll-hint-arrow.left  { left: 0;  --h-dir: left;  --dir-from: rgba(250,252,250,1); --dir-to: rgba(250,252,250,0); }
.scroll-hint-arrow.right { right: 0; --h-dir: right; --dir-from: rgba(250,252,250,0); --dir-to: rgba(250,252,250,1); }

/* [I3, 23/10] Flechas de la fila de categorías (#filter-row-inner): mínimas y semitransparentes, sin clicks,
   pegadas a los bordes de #filter-bar y centradas en los círculos (59 px = 32 de top del botón + 27 de radio).
   Una sombra suave del borde hacia adentro las hace legibles aunque pasen sobre un círculo. */
.scroll-hint-arrow.scroll-hint-arrow--fila {
  position: absolute; top: 59px; bottom: auto; height: 54px; width: 20px; margin: 0;
  transform: translateY(-50%); z-index: 4;
  color: #fff; font-size: 26px; line-height: 1; opacity: 0;
  text-shadow: 0 0 3px rgba(0,0,0,.95), 0 1px 3px rgba(0,0,0,.8);
}
.scroll-hint-arrow.scroll-hint-arrow--fila.visible { opacity: .85; }
.scroll-hint-arrow.scroll-hint-arrow--fila.left  { left: 0;  right: auto; justify-content: flex-start; padding-left: 3px;  background: linear-gradient(to right, rgba(0,0,0,.32), rgba(0,0,0,0)); }
.scroll-hint-arrow.scroll-hint-arrow--fila.right { right: 0; left: auto;  justify-content: flex-end;   padding-right: 3px; background: linear-gradient(to left,  rgba(0,0,0,.32), rgba(0,0,0,0)); }

/* Style buttons inside panels */
.sty-btn {
  flex-shrink: 0;
  background: var(--surface); border: 1.5px solid var(--border);
  border-radius: var(--r); padding: 8px 13px;
  cursor: pointer; font-size: 11px; font-weight: 700; color: var(--text2);
  font-family: var(--font-b);
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  transition: all .2s; -webkit-tap-highlight-color: transparent;
  box-shadow: var(--shadow-xs);
}
.sty-btn .si { font-size: 22px; }
.sty-btn.on { background: var(--accent-pale); border-color: var(--accent); color: var(--accent); }
.sty-btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }

/* Style row and visual thumbs */
.style-row { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; }
.style-row::-webkit-scrollbar { display: none; }
.pp-vis-thumb {
  width: 46px; height: 46px; border-radius: var(--r);
  object-fit: contain; cursor: pointer;
  border: 2px solid transparent;
  transition: border-color .15s, transform .15s;
  background: var(--surface2);
  box-shadow: var(--shadow-xs);
}
.pp-vis-thumb:hover, .pp-vis-thumb.active { border-color: var(--accent); transform: scale(1.08); }
.pp-vis-thumb-emoji {
  width: 46px; height: 46px; border-radius: var(--r);
  display:flex; align-items:center; justify-content:center;
  font-size: 24px; cursor: pointer;
  border: 2px solid transparent;
  background: var(--surface2);
  transition: border-color .15s, transform .15s;
  box-shadow: var(--shadow-xs);
}
.pp-vis-thumb-emoji:hover, .pp-vis-thumb-emoji.active { border-color: var(--accent); transform: scale(1.08); }

/* Empty state */
.empty-state {
  padding: 28px 0; text-align: center;
  color: var(--text3); font-size: 13px; font-weight: 500;
}
.empty-state .big { font-size: 36px; margin-bottom: 10px; }

/* Cat chips */
.cat-chip {
  border-radius: 99px !important;
  font-weight: 700 !important;
  font-family: var(--font-b) !important;
  transition: all .2s cubic-bezier(.34,1.56,.64,1) !important;
}
.cat-chip:hover { transform: translateY(-1px) scale(1.02) !important; }

/* Geocoder styles */
.geocoder-row { display: flex; gap: 8px; }
.geocoder-input { flex: 1; }
.geocoder-btn {
  background: linear-gradient(135deg, var(--accent), var(--green-light)); color: white; border: none;
  border-radius: var(--r-ctrl); padding: 3px 16px;
  font-family: var(--font-b); font-size: 13px; font-weight: 700;
  cursor: pointer; white-space: nowrap;
  box-shadow: 0 4px 12px rgba(var(--accent-rgb), .25);
  transition: all .2s; -webkit-tap-highlight-color: transparent;
}
.geocoder-btn:hover { transform: translateY(-1px); box-shadow: 0 6px 16px rgba(var(--accent-rgb), .32); }
.geocoder-results {
  margin-top: 6px;
  border-radius: var(--r);
  overflow: hidden;
  border: 1.5px solid var(--border);
  display: none;
  box-shadow: var(--shadow-sm);
}
.geocoder-results.show { display: block; }
.geocoder-item {
  padding: 10px 14px; cursor: pointer; font-size: 13px; font-weight: 500;
  border-bottom: 1px solid var(--border); background: var(--surface);
  transition: background .15s;
}
.geocoder-item:last-child { border-bottom: none; }
.geocoder-item:hover { background: var(--accent-pale); color: var(--accent); }

/* URL input row */
.url-input-row { display: flex; gap: 8px; margin-top: 8px; }
.url-fi { flex: 1; }
.url-load-btn {
  background: var(--surface2); color: var(--text2);
  border: 1.5px solid var(--border); border-radius: var(--r-ctrl);
  padding: 2px 14px; font-family: var(--font-b); font-size: 12px; font-weight: 700;
  cursor: pointer; white-space: nowrap; transition: all .2s;
  -webkit-tap-highlight-color: transparent;
}
.url-load-btn:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-pale); }

/* img uploader */
.img-uploader {
  border: 2px dashed var(--border2); border-radius: var(--r);
  position: relative; overflow: hidden; cursor: pointer;
  transition: border-color .2s, background .2s;
  background: var(--surface);
}
.img-uploader:hover { border-color: var(--accent); background: var(--accent-pale); }
.img-uploader input[type=file] {
  position: absolute; inset: 0;
  opacity: 0; cursor: pointer; width: 100%; height: 100%;
}
.img-uploader-inner {
  display: flex; align-items: center; gap: 13px;
  padding: 13px 15px;
}
.img-preview-box {
  width: 66px; height: 66px; flex-shrink: 0;
  border-radius: var(--r); background: var(--border);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; font-size: 28px;
  border: 1.5px solid var(--border);
}
.img-preview-box img { width: 100%; height: 100%; object-fit: contain; }
.img-uploader-text { flex: 1; }
.img-uploader-text strong { display: block; font-size: 13px; font-weight: 700; color: var(--text); margin-bottom: 2px; }
.img-uploader-text span { font-size: 11px; color: var(--text3); line-height: 1.4; display: block; }
.img-uploader.has-img { border-color: var(--green); border-style: solid; }
.img-uploader.has-img .img-uploader-text strong { color: var(--green); }
.img-clear {
  position: absolute; top: 7px; right: 7px;
  background: rgba(0,0,0,.1); border: none; border-radius: 50%;
  width: 23px; height: 23px; font-size: 11px;
  cursor: pointer; color: var(--text2);
  display: none; align-items: center; justify-content: center;
  z-index: 2; -webkit-tap-highlight-color: transparent;
  transition: background .15s;
}
.img-uploader.has-img .img-clear { display: flex; }
.img-clear:hover { background: rgba(220,38,38,.2); color: #dc2626; }

/* Panel image preview (grande) */
.pp-img-preview {
  width: 100%; max-height: 190px;
  object-fit: contain;
  display: block;
  padding: 14px 18px 0;
  border-radius: var(--r);
}

/* ── MAP PRESET GRID ── */
.mapa-preset-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  margin-bottom: 16px;
}
.mapa-preset-card {
  border: 2px solid var(--border);
  border-radius: var(--r-sm);
  overflow: hidden;
  cursor: pointer;
  transition: border-color .2s, transform .15s;
  background: var(--surface);
}
.mapa-preset-card:hover { border-color: var(--accent); transform: scale(1.02); }
.mapa-preset-card.active { border-color: var(--accent); outline: 2px solid var(--accent); outline-offset: 1px; }
.mapa-preview {
  height: 56px;
  position: relative;
  overflow: hidden;
}
.mapa-preview-lines {
  position: absolute; inset: 0;
  background-image: repeating-linear-gradient(
    0deg, transparent, transparent 8px, rgba(128,128,128,0.4) 8px, rgba(128,128,128,0.4) 9px
  ),
  repeating-linear-gradient(
    90deg, transparent, transparent 14px, rgba(128,128,128,0.4) 14px, rgba(128,128,128,0.4) 15px
  );
}
.mapa-card-name {
  padding: 5px 8px;
  font-size: 11px;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── AUTOFILL FROM OSM ── */
.autofill-btn {
  display: flex; align-items: center; gap: 7px;
  width: 100%;
  background: linear-gradient(135deg, var(--accent-pale), #e8f5e8);
  border: 1.5px solid var(--accent);
  border-radius: var(--r-ctrl);
  padding: 3px 14px;
  font-family: var(--font-b);
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
  transition: all .2s;
  -webkit-tap-highlight-color: transparent;
  margin-bottom: 12px;
}
.autofill-btn:hover {
  background: var(--accent);
  color: white;
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(212,55,15,.25);
}
.autofill-btn:active { transform: translateY(0); }
.autofill-btn.loading {
  background: var(--surface2);
  border-color: var(--border);
  color: var(--text3);
  cursor: wait;
  animation: pulse-border 1.2s ease-in-out infinite;
}
@keyframes pulse-border {
  0%,100% { border-color: var(--border); }
  50%      { border-color: var(--accent); }
}
.autofill-btn .af-icon { font-size: 16px; }

.autofill-result {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  margin-bottom: 10px;
  font-size: 12px;
  color: var(--text2);
  line-height: 1.5;
  display: none;
}
.autofill-result.show { display: block; }
.autofill-result strong { color: var(--text); }

/* Phone + hours fields */
.fi-phone, .fi-hours { width: 100%; }

/* ── CONTACT INFO IN PANEL ── */
.pp-contact {
  display: flex; align-items: center; gap: 6px;
  margin-top: 4px; font-size: 12px; color: var(--text2);
}
.pp-contact-icon { font-size: 13px; flex-shrink: 0; }
.pp-contact-val  { flex: 1; line-height: 1.4; }

/* ═══════════════════════════════════════════
   EVENTOS — tab admin [Etapa 3, PLAN_USUARIOS_EVENTOS.md]
   Reusa el lenguaje visual ya establecido (owner-panel-item,
   geocoder-result, atab) en vez de crear un sistema nuevo.
═══════════════════════════════════════════ */
.evt-camino-toggle { display: flex; gap: 8px; margin-bottom: 14px; }
.evt-camino-btn {
  flex: 1; padding: 10px; border-radius: var(--r-sm);
  border: 1px solid var(--border2); background: white;
  font-family: var(--font-b); font-size: 12px; font-weight: 700;
  color: var(--text3); cursor: pointer; transition: all .15s;
}
.evt-camino-btn.on { border-color: var(--accent); color: var(--accent); background: rgba(var(--accent-rgb), .06); }

/* [Etapa 9 — simplificada] selector de tags de categoría de evento —
   checkboxes con pinta de chip, mismo lenguaje visual que evt-camino-btn. */
.evt-tags-wrap { display: flex; flex-wrap: wrap; gap: 6px; }
.evt-tag-chip {
  display: flex; align-items: center; gap: 5px;
  padding: 6px 10px; border-radius: 999px;
  border: 1px solid var(--border2); background: white;
  font-family: var(--font-b); font-size: 12px; font-weight: 600;
  color: var(--text3); cursor: pointer; transition: all .15s;
}
.evt-tag-chip.on { border-color: var(--accent); color: var(--accent); background: rgba(var(--accent-rgb), .06); }
/* [Etapa 11] foto opcional del evento (form admin `evt-` y de usuario `up-evt-`). */
.evt-img-wrap { display: flex; flex-direction: column; gap: 8px; }
.evt-img-preview {
  width: 100%; max-width: 320px; aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: var(--r-sm); border: 1px solid var(--border2); background: #f3f4f6;
}
.evt-img-preview[hidden], .evt-img-btn[hidden] { display: none; }
.evt-img-actions { display: flex; gap: 8px; align-items: center; }
.evt-img-btn {
  padding: 7px 12px; border-radius: 999px; border: 1px solid var(--border2); background: white;
  font-family: var(--font-b); font-size: 12px; font-weight: 700; color: var(--text3);
  cursor: pointer; transition: all .15s;
}
.evt-img-btn:hover { border-color: var(--accent); color: var(--accent); }
.evt-img-hint { margin-top: 4px; font-family: var(--font-b); font-size: 11px; color: var(--text3); }
.evt-img-error { margin-top: 4px; font-family: var(--font-b); font-size: 12px; color: #b91c1c; }

/* [22/10/2026] Aclaración bajo las fechas del evento ("ocurre desde / hasta"). */
.evt-fechas-row > div { min-width: 0; }
@media (max-width: 480px) { .evt-fechas-row { grid-template-columns: 1fr; } }
.evt-fechas-hint { margin: -2px 0 10px; font-family: var(--font-b); font-size: 11px; color: var(--text3); line-height: 1.35; }

/* [22/10/2026] Bloque "Horarios" por filas (js/eventos-form-shared.js, formularios `evt-` y `up-evt-`).
   Celular primero: el editor es una grilla de 2 columnas (días arriba, horas abajo) y el OK ocupa todo el ancho. */
.hor-wrap { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.hor-list { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.hor-list:empty { display: none; }
.hor-chip {
  display: inline-flex; align-items: center; gap: 2px; max-width: 100%;
  padding: 4px 4px 4px 12px; border-radius: 999px;
  border: 1px solid var(--border2); background: var(--surface2);
  font-family: var(--font-b); font-size: 13px; font-weight: 700; color: var(--text);
}
.hor-chip-txt { overflow-wrap: anywhere; }
.hor-chip-btn, .hor-add {
  min-width: 32px; min-height: 32px; border-radius: 50%; border: 1px solid transparent;
  background: transparent; color: var(--text3); font-size: 14px; line-height: 1; cursor: pointer;
}
.hor-chip-btn:hover, .hor-add:hover { border-color: var(--accent); color: var(--accent); }
.hor-add { border: 1px dashed var(--border2); font-size: 18px; font-weight: 700; }
.hor-editor { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.hor-editor .fi { width: 100%; min-width: 0; min-height: 42px; box-sizing: border-box; }
.hor-ok {
  grid-column: 1 / -1; min-height: 42px; border-radius: var(--r-sm);
  border: 1px solid var(--accent); background: var(--accent); color: #fff;
  font-family: var(--font-b); font-size: 14px; font-weight: 800; cursor: pointer;
}
.hor-err { font-family: var(--font-b); font-size: 12px; color: #b91c1c; }
.hor-err:empty, .hor-warn:empty, .hor-legacy:empty { display: none; }
.hor-warn { font-family: var(--font-b); font-size: 12px; color: #b91c1c; line-height: 1.35; }
.hor-legacy {
  font-family: var(--font-b); font-size: 12px; color: var(--text3); line-height: 1.35;
  padding: 6px 10px; border-radius: var(--r-sm); background: var(--surface2); border: 1px dashed var(--border2);
  overflow-wrap: anywhere;
}
.hor-hint { font-family: var(--font-b); font-size: 11px; color: var(--text3); line-height: 1.35; }
.evt-admin-row {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: var(--r-sm);
  border: 1px solid var(--border2); background: white;
  margin-bottom: 8px; font-family: var(--font-b);
}
.evt-admin-row-main { display: flex; flex-direction: column; gap: 2px; font-size: 12px; }
.evt-admin-row-main strong { font-size: 14px; }
.evt-admin-row-pin, .evt-admin-row-fechas { color: var(--text3); }
.evt-admin-row-estado {
  align-self: flex-start; font-size: 10px; text-transform: uppercase;
  color: var(--accent); font-weight: 700;
}
.evt-admin-row-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.evt-admin-toggle {
  width: 34px; height: 20px; border-radius: 10px; border: none;
  background: #d1d5db; position: relative; cursor: pointer; transition: background .15s;
}
.evt-admin-toggle::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
  border-radius: 50%; background: white; transition: left .15s;
}
.evt-admin-toggle.on { background: #22c55e; }
.evt-admin-toggle.on::after { left: 16px; }
.evt-admin-del {
  background: none; border: none; font-size: 14px; cursor: pointer; opacity: .7;
}
.evt-admin-del:hover { opacity: 1; }
.evt-asignado-click { color: var(--accent); cursor: pointer; font-weight: 700; }
.evt-asignado-click:hover { text-decoration: underline; }

/* [Etapa 4] aviso de pin evento_temporal auto-desactivado (sin
   eventos vigentes) + botón de reactivación manual, dentro de cada
   fila de la lista de eventos. */
.evt-admin-pin-off {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 11px; color: #b45309; margin-top: 2px;
}
.evt-admin-reactivar-pin {
  border: 1px solid #b45309; background: #fffbeb; color: #b45309;
  border-radius: var(--r-sm); font-size: 10px; font-weight: 700;
  padding: 3px 8px; cursor: pointer; font-family: var(--font-b);
}
.evt-admin-reactivar-pin:hover { background: #fef3c7; }

/* [Etapa 6] edición de eventos + contador de cambios + nombre único */
.evt-admin-edit {
  background: none; border: none; font-size: 13px; cursor: pointer; opacity: .75;
}
.evt-admin-edit:hover { opacity: 1; }
.evt-admin-row-cambios { font-size: 10px; color: var(--text3); }
.evt-nombre-ok { color: var(--accent); }
.evt-nombre-dup { color: #ef4444; }

/* ═══════════════════════════════════════════
   SKINS (PLAN_SISTEMA_SKINS.md)
   ---------------------------------------------
   El bloque :root de arriba define los valores de "default" (Warm
   Editorial — el skin que ya existía, sin cambiar nada visualmente).
   Cada skin nuevo solo pisa estas mismas variables + sus versiones
   "-rgb" (deben ir siempre juntas, mismo color en 2 formatos, ver
   comentario junto a --surface-rgb/--text-rgb/--accent-rgb arriba).
   Agregar un skin nuevo = un bloque más acá, nada más — el resto del
   CSS del sitio no se toca. js/skins.js controla el atributo
   data-skin en <html> y qué fuente extra cargar (si el skin la usa).
   ═══════════════════════════════════════════ */

[data-skin="default"] {
  /* Vacío a propósito: son los mismos valores que ya están en :root
     arriba — este bloque existe solo para que el selector exista y
     quede documentado como skin real, no para pisar nada. */
}

[data-skin="neobrutal-night"] {
  /* Traducido 1:1 de "SmartCity — Exploración visual (Neo-Brutalist)"
     (mockup subido) a los nombres de variable que ya usa el proyecto —
     no se copian las clases sueltas del mockup (.phone/.sheet/.tab-btn),
     esas eran solo para mostrar la idea. */
  --bg:          #0a0a0c;
  --surface:     #18181b;
  --surface2:    #121216;
  --border:      #27272a;
  --border2:     #3f3f46;
  --text:        #f4f1ea;
  --text2:       #a1a1aa;
  --text3:       #71717a;
  --accent:      #facc15;
  --accent2:     #facc15;
  --accent-pale: #27271a;

  --surface-rgb: 24, 24, 27;
  --text-rgb:    244, 241, 234;
  --accent-rgb:  250, 204, 21;

  --font-d:      'Space Grotesk', sans-serif;
  --font-b:      'Plus Jakarta Sans', sans-serif;
}

/* Forma característica del Neo-Brutalist para la fila principal de
   pestañas del admin (LUGARES/ZONAS/UBICACIONES/etc) — traducida 1:1
   de .tabs/.tab-btn del mockup: caja con borde de 2px, esquinas
   superiores redondeadas, sin borde abajo, y la fila entera apoyada
   sobre una línea de acento gruesa. Implementada completa a pedido
   explícito de Cris (2026-08-31): este skin se hace fiel al mockup
   en TODO, sin mezclar con el rediseño minimalista del skin default
   (que sigue intacto — cambiar de skin alterna entre los dos). */
[data-skin="neobrutal-night"] .admin-tabs {
  border-bottom: 3px solid var(--accent);
  gap: 3px;
  padding: 0 4px;
}
[data-skin="neobrutal-night"] .atab {
  border: 2px solid var(--border2);
  border-bottom: none;
  border-radius: 8px 8px 0 0;
  padding: 6px 8px;
}
[data-skin="neobrutal-night"] .atab.on {
  background: var(--accent);
  color: #000;
  border-color: var(--accent);
}

/* [I4c, 23/10, pedido de Cris] Calendario y reloj de los campos de fecha y hora
   (eventos: "El evento ocurre desde/hasta" y horas de "Horarios"). En el celular se
   tocan para abrir el selector, pero el ícono salía casi del mismo color que el fondo.
   Ahora se dibuja con el color de la LETRA (--text) y un poco más grande, en todos
   los skins. En Firefox no se puede cambiar el ícono: ahí solo se pide el esquema
   claro/oscuro correcto (color-scheme) y el alto de dedo. */
.fi[type="datetime-local"], .fi[type="date"], .fi[type="time"] {
  min-height: 42px;
  box-sizing: border-box;
  color-scheme: light;
}
[data-skin="neobrutal-night"] .fi[type="datetime-local"],
[data-skin="neobrutal-night"] .fi[type="date"],
[data-skin="neobrutal-night"] .fi[type="time"] { color-scheme: dark; }
.fi[type="datetime-local"]::-webkit-calendar-picker-indicator,
.fi[type="date"]::-webkit-calendar-picker-indicator,
.fi[type="time"]::-webkit-calendar-picker-indicator {
  opacity: 1;
  width: 26px; height: 26px;
  margin-left: 6px;
  cursor: pointer;
  background-color: var(--text);
  background-image: none;
  -webkit-mask: var(--ico-fecha) center / contain no-repeat;
          mask: var(--ico-fecha) center / contain no-repeat;
}
.fi[type="time"]::-webkit-calendar-picker-indicator {
  -webkit-mask: var(--ico-reloj) center / contain no-repeat;
          mask: var(--ico-reloj) center / contain no-repeat;
}
:root {
  --ico-fecha: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2'/%3E%3Cpath d='M16 2v4M8 2v4M3 10h18'/%3E%3C/svg%3E");
  --ico-reloj: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 6v6l4 2'/%3E%3C/svg%3E");
}

/* [I6, 23/10] "¿Dónde está Jerónimo?" (js/jeronimo.js): brillo del pin y cartel corto al
   llegar con el ojito a la imagen con sufijo `jeronimo`. Dura GLOW_MS/CARTEL_MS de js/jeronimo.js. */
.pin-wrap .pin-img.pin-img--jeronimo { animation: jeronimo-brillo 2.6s ease-in-out 1; }
@keyframes jeronimo-brillo {
  0%, 100% { filter: drop-shadow(0 0 0 rgba(250, 204, 21, 0)); }
  20%, 60% { filter: drop-shadow(0 0 10px #facc15) drop-shadow(0 0 26px rgba(250, 204, 21, .9)); }
  40%      { filter: drop-shadow(0 0 4px #facc15) drop-shadow(0 0 12px rgba(250, 204, 21, .5)); }
}
#jeronimo-cartel {
  position: fixed; left: 0; top: 0;
  transform: translateY(8px) scale(.96);
  z-index: 1600;
  max-width: calc(100vw - 24px);
  display: flex; align-items: center; gap: 10px;
  background: var(--surface); color: var(--text);
  border: 2px solid var(--accent); border-radius: 16px; padding: 12px 18px;
  font-size: 15px; font-weight: 700; font-family: var(--font-b); line-height: 1.25;
  box-shadow: 0 8px 24px rgba(0,0,0,.28);
  opacity: 0; pointer-events: none;
  transition: opacity .25s, transform .25s;
}
#jeronimo-cartel svg { flex: none; width: 22px; height: 22px; fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
#jeronimo-cartel.on { opacity: 1; transform: translateY(0) scale(1); }
@media (prefers-reduced-motion: reduce) {
  .pin-wrap .pin-img.pin-img--jeronimo { animation: none; filter: drop-shadow(0 0 10px #facc15) drop-shadow(0 0 22px rgba(250, 204, 21, .8)); }
  #jeronimo-cartel { transition: none; }
}
