/* ============================================================
   Século — Engine (motor de búsqueda): HOJA DE ESTILOS
   ------------------------------------------------------------
   Extraído de public/index.html el 17-ago-2026.
   Rediseño de marca (tinta + terracota) el 19-ago-2026.

   POR QUÉ ESTÁ SEPARADO: el look&feel eran 326 líneas dentro de un
   index.html de 7.272, junto a 6.441 líneas de lógica (geocodificación,
   tiers, llamadas a la API). Rediseñar obligaba a editar el mismo fichero
   que el motor, y cualquier propuesta llegaba con 7.000 líneas de ruido
   alrededor — que es donde se cuelan los errores.

   LENGUAJE DE DISEÑO: dibujado, no encajonado. La estructura sale de
   filetes de 1px, del espacio y de un único fondo cálido — nunca de
   fondos alternos, esquinas redondeadas ni sombras. Ni blanco puro ni
   negro puro. Esquinas rectas. El color está racionado: un fondo cálido,
   tinta marrón para el texto, gris-azul para toda la estructura y el
   texto secundario, y terracota SÓLO para marcar una sección o el estado
   vivo de un control.

   REGLA DE CONTRASTE INNEGOCIABLE: la terracota es un color OSCURO.
   Texto oscuro sobre terracota da 2.1:1 — ilegible. Todo relleno
   terracota lleva texto claro (--brand-light). Sobre superficies de
   tinta, la terracota es --color-accent-on-dark, nunca --color-accent.
   ============================================================ */

/* ── TOKENS ──────────────────────────────────────────────────── */
:root{
  /* Marca */
  --brand-light:#F6F5F0;--brand-terracotta:#91301D;--brand-dark:#3E3A37;--brand-grey:#43515C;
  /* Superficies — sin blanco puro en ningún sitio */
  --color-bg:#F6F5F0;--color-raised:#F1EFE8;--color-sunken:#EBE8E0;
  /* Tinta */
  --color-primary:#3E3A37;--color-mid:#43515C;
  --color-faint:rgba(67,81,92,0.72);--color-placeholder:rgba(67,81,92,0.55);
  /* ACENTO = TINTA. La terracota se retiró del acento: en una herramienta de
     análisis el rojo se lee como alarma, no como "seleccionado". Queda
     reservada a --color-error, que es el único sitio donde ese significado
     es el correcto. */
  --color-accent:#3E3A37;--color-accent-dark:#2C2926;--color-accent-deep:#1F1D1B;
  /* Filetes — todos de 1px, nunca 2px */
  --rule:rgba(67,81,92,0.18);--rule-strong:rgba(67,81,92,0.34);--rule-faint:rgba(67,81,92,0.10);
  /* Sobre oscuro — el acento es tinta, así que sobre tinta sube a un tono claro */
  --color-on-dark:#F0EEE8;--color-accent-on-dark:#D8D2CA;--rule-on-dark:rgba(240,238,232,0.20);
  --on-dark-78:rgba(240,238,232,0.78);--on-dark-68:rgba(240,238,232,0.68);
  --on-dark-55:rgba(240,238,232,0.55);--on-dark-25:rgba(240,238,232,0.25);
  /* Semánticos */
  --color-success:#3F6B52;--color-warning:#9A6B1F;--color-error:#91301D;
  --tint-success:rgba(63,107,82,0.12);--tint-success-rule:rgba(63,107,82,0.30);
  --tint-warning:rgba(154,107,31,0.12);--tint-warning-rule:rgba(154,107,31,0.30);
  --tint-error:rgba(145,48,29,0.10);--tint-error-rule:rgba(145,48,29,0.28);
  --tint-accent:rgba(62,58,55,0.08);--tint-accent-rule:rgba(62,58,55,0.26);
  /* Tipografía */
  --font-display:'Zalando Sans Expanded','Bai Jamjuree',sans-serif;
  --font-body:'Bai Jamjuree',sans-serif;
  /* IBM Plex Mono en lugar de DM Mono: DM Mono no trae cero barrado ni
     ningún cero alternativo (no tiene la característica OpenType 'zero'),
     así que su 0 se confunde con una O. Plex sí la trae y se activa abajo. */
  --font-mono:'IBM Plex Mono','DM Mono',monospace;
  /* Azul acero para lo SELECCIONADO en el mapa: rompe la uniformidad gris
     sin salirse del gris-azul de marca (--brand-grey #43515C). */
  --map-select:#5A7D94;--map-select-soft:rgba(90,125,148,0.18);
  --app-t-xs:0.625rem;--app-t-sm:0.6875rem;--app-t-base:0.75rem;--app-t-md:0.8125rem;
  --app-t-lg:0.875rem;--app-t-xl:1.0625rem;--app-t-2xl:1.375rem;
  /* Espacio y controles */
  --app-space-1:2px;--app-space-2:4px;--app-space-3:6px;--app-space-4:8px;
  --app-space-5:12px;--app-space-6:14px;--app-space-7:16px;--app-space-8:20px;--app-space-9:24px;
  --ctrl-xs:22px;--ctrl-sm:28px;--ctrl-md:32px;--ctrl-lg:36px;
  /* Ancho del panel lateral en UN solo sitio: la pestaña se coloca contra
     este borde, así que si el número se duplica acaban separándose. */
  --sidebar-w:255px;
  /* Plegado deja un riel visible, igual que #gisPanelRight.collapsed deja
     10px asomando con su translateX(210px). Es lo que hace que la pestaña
     se lea pegada a un panel y no suelta sobre el mapa. */
  --sidebar-rail:10px;
  /* Forma y movimiento */
  --radius:0;
  --ease-out:cubic-bezier(0.22,0.61,0.36,1);
  --transition:0.18s cubic-bezier(0.22,0.61,0.36,1);
  /* Alias heredados — mantener hasta que no quede ninguna referencia --ux-* */
  --ux-primary:var(--color-primary);--ux-accent:var(--color-accent);
  --ux-bg:var(--color-bg);--ux-surface:var(--color-raised);--ux-border:var(--rule);
  --ux-mid:var(--color-mid);--ux-divider:var(--rule);--ux-white:var(--color-raised);
  --text-1:var(--color-primary);--text-2:var(--color-mid);--text-3:var(--color-faint);
  --gray-100:var(--color-raised);--gray-200:var(--rule);--gray-300:var(--rule-strong);
  --gray-500:var(--color-faint);--gray-700:var(--color-mid);--gray-900:var(--color-primary);
  --success:var(--color-success);--error:var(--color-error);--warning:var(--color-warning);
  --ux-font-display:var(--font-display);--ux-font-body:var(--font-body);--ux-font-mono:var(--font-mono)
}

*{box-sizing:border-box;margin:0;padding:0}
/* Cero barrado en toda la interfaz. Sólo afecta a la mono: Bai Jamjuree no
   implementa la característica 'zero', así que en el texto corrido no hace
   nada. Evita leer "0 propriedades" como "O propriedades". */
html{font-variant-numeric:slashed-zero;font-feature-settings:'zero' 1}
body{background:var(--color-bg);color:var(--color-primary);font-family:var(--font-body),'Segoe UI',system-ui,sans-serif;font-weight:400;font-size:var(--app-t-base);display:flex;flex-direction:column;height:100vh;height:100dvh;overflow:hidden}

/* ── PRIMITIVAS COMPARTIDAS ──────────────────────────────────
   .app-btn es la base; las clases históricas (.btn-sm, .sort-btn…) la
   comparten por selector agrupado en vez de renombrarse, porque el motor
   las referencia por nombre al alternar estados. */
.app-btn,
.btn-sm,.sort-btn,.type-btn,.dedup-toggle,.card-btn,.card-save-btn,.card-iso-btn,
.sel-btn,.sel-iso-btn,.sel-modal-btn,.agent-btn,.lang-btn,.gis-btn-link,.agent-zone-select-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--app-space-3);
  position:relative;overflow:hidden;isolation:isolate;
  height:var(--ctrl-sm);padding:0 11px;
  background:transparent;
  border:1px solid var(--rule-strong);border-radius:var(--radius);
  color:var(--color-mid);
  font-family:var(--font-body);font-size:var(--app-t-md);font-weight:500;
  letter-spacing:0.04em;line-height:1;cursor:pointer;text-decoration:none;white-space:nowrap;
  transition:color 0.2s var(--ease-out),border-color 0.2s var(--ease-out),background-color 0.2s var(--ease-out)
}
/* El gesto de marca: el relleno sube desde abajo, no aparece de golpe.
   LAS TRES LISTAS SIGUIENTES DEBEN SER IDÉNTICAS. Si un selector aparece en
   :hover (que pone el texto claro) pero falta en ::after (que pone el fondo
   oscuro), ese botón se queda con texto claro sobre fondo claro y el rótulo
   desaparece al pasar el ratón. Al añadir un botón, añádelo a las tres. */
.app-btn::after,
.btn-sm::after,.sort-btn::after,.type-btn::after,.dedup-toggle::after,.card-btn::after,
.card-save-btn::after,.card-iso-btn::after,.sel-btn::after,.sel-iso-btn::after,.sel-modal-btn::after,
.agent-btn::after,.lang-btn::after,.gis-btn-link::after,.agent-zone-select-btn::after{
  content:'';position:absolute;inset:0;z-index:-1;
  background:var(--color-accent);
  transform:scaleY(0);transform-origin:bottom;
  transition:transform 0.2s var(--ease-out)
}
.app-btn:hover,
.btn-sm:hover,.sort-btn:hover,.type-btn:hover,.dedup-toggle:hover,.card-btn:hover,
.card-save-btn:hover,.card-iso-btn:hover,.sel-btn:hover,.sel-iso-btn:hover,.sel-modal-btn:hover,
.agent-btn:hover,.lang-btn:hover,.gis-btn-link:hover,.agent-zone-select-btn:hover{
  border-color:var(--color-accent);color:var(--brand-light)
}
.app-btn:hover::after,
.btn-sm:hover::after,.sort-btn:hover::after,.type-btn:hover::after,.dedup-toggle:hover::after,
.card-btn:hover::after,.card-save-btn:hover::after,.card-iso-btn:hover::after,
.sel-btn:hover::after,.sel-iso-btn:hover::after,.sel-modal-btn:hover::after,.agent-btn:hover::after,
.lang-btn:hover::after,.gis-btn-link:hover::after,.agent-zone-select-btn:hover::after{transform:scaleY(1)}
/* Red de seguridad: si un botón lleva color de texto en línea (los hay en
   index.html), el :hover del atributo style ganaría y dejaría texto oscuro
   sobre el relleno. Esto lo fuerza a claro mientras el relleno está subido. */
.app-btn:hover *,.btn-sm:hover *,.sort-btn:hover *,.type-btn:hover *,.dedup-toggle:hover *,
.card-btn:hover *,.card-save-btn:hover *,.card-iso-btn:hover *,.sel-btn:hover *,
.sel-iso-btn:hover *,.sel-modal-btn:hover *,.agent-btn:hover *,.lang-btn:hover *,
.gis-btn-link:hover *,.agent-zone-select-btn:hover *{color:inherit;fill:none;stroke:currentColor}
/* Deshabilitado: ni relleno ni cambio de texto */
.app-btn:disabled,.btn-sm:disabled,.sort-btn:disabled,.type-btn:disabled,.card-btn:disabled,
.card-save-btn:disabled,.card-iso-btn:disabled,.sel-btn:disabled,.agent-btn:disabled{
  opacity:0.5;cursor:not-allowed;color:var(--color-placeholder);border-color:var(--rule)
}
.app-btn:disabled::after,.btn-sm:disabled::after,.sort-btn:disabled::after,.type-btn:disabled::after,
.card-btn:disabled::after,.card-save-btn:disabled::after,.card-iso-btn:disabled::after,
.sel-btn:disabled::after,.agent-btn:disabled::after{display:none}
/* Activo/seleccionado — un estado RELLENO, no un estado hover */
.app-btn.active,
.btn-sm.active,.sort-btn.active,.type-btn.active,.dedup-toggle.active,
.agent-btn.selected,.lang-btn.active,.card-iso-btn.active,.sel-btn.active{
  background:var(--color-accent);border-color:var(--color-accent);
  color:var(--brand-light);font-weight:600
}
/* Variante de aviso del conmutador de duplicados. Lleva su propio :hover
   porque una clase de estado gana en especificidad al :hover genérico y,
   sin esto, el ámbar se quedaría sobre el relleno de tinta. */
.dedup-toggle.has-dupes{color:var(--color-warning);border-color:var(--tint-warning-rule);background:var(--tint-warning)}
.dedup-toggle.has-dupes:hover{color:var(--brand-light);border-color:var(--color-accent);background:transparent}
/* Primario — el botón Buscar. TINTA, no terracota. */
.app-btn--primary,.search-btn,#agentSendBtn,#ux-nav-upgrade,.sel-btn-primary{
  display:inline-flex;align-items:center;justify-content:center;
  position:relative;overflow:hidden;isolation:isolate;
  height:var(--ctrl-lg);padding:0 var(--app-space-7);
  background:var(--color-primary);border:1px solid var(--color-primary);border-radius:var(--radius);
  color:var(--color-on-dark);
  font-family:var(--font-body);font-size:var(--app-t-md);font-weight:600;
  letter-spacing:0.1em;text-transform:uppercase;line-height:1;cursor:pointer;text-decoration:none;
  transition:color 0.2s var(--ease-out),border-color 0.2s var(--ease-out),background-color 0.2s var(--ease-out)
}
/* El primario ya es tinta, así que su relleno de hover sube al gris-azul de
   marca: si usara el acento (también tinta) el hover sería invisible. */
.app-btn--primary::after,.search-btn::after,#agentSendBtn::after,#ux-nav-upgrade::after,.sel-btn-primary::after{
  content:'';position:absolute;inset:0;z-index:-1;background:var(--brand-grey);
  transform:scaleY(0);transform-origin:bottom;transition:transform 0.2s var(--ease-out)
}
.app-btn--primary:hover,.search-btn:hover,#agentSendBtn:hover,#ux-nav-upgrade:hover,.sel-btn-primary:hover{
  border-color:var(--brand-grey);color:var(--brand-light)
}
.app-btn--primary:hover::after,.search-btn:hover::after,#agentSendBtn:hover::after,
#ux-nav-upgrade:hover::after,.sel-btn-primary:hover::after{transform:scaleY(1)}
.app-btn--primary:disabled,.search-btn:disabled,#agentSendBtn:disabled{
  background:var(--color-sunken);border-color:var(--rule);color:var(--color-placeholder);cursor:not-allowed
}
.app-btn--primary:disabled::after,.search-btn:disabled::after,#agentSendBtn:disabled::after{display:none}
/* Fantasma — sólo icono, barras de herramientas, toggles de panel */
.app-btn--ghost{border-color:transparent;background:transparent}
.app-btn--ghost:hover{border-color:var(--rule-strong)}
/* Foco visible y homogéneo en todo control interactivo */
.app-btn:focus-visible,button:focus-visible,a:focus-visible,input:focus-visible,
select:focus-visible,textarea:focus-visible{outline:2px solid var(--color-accent);outline-offset:1px}

/* Cintillo: el filete terracota corto que marca sección sin gastar color */
.app-eyebrow{
  display:inline-flex;align-items:center;gap:var(--app-space-4);
  font-family:var(--font-body);font-size:var(--app-t-sm);font-weight:500;
  letter-spacing:0.12em;text-transform:uppercase;color:var(--color-mid)
}
.app-eyebrow::before{content:'';width:16px;height:1px;background:var(--color-accent);flex-shrink:0}

/* Mensajes en línea — rectos, filete, tinte al 10–12% */
.app-message{padding:var(--app-space-4) var(--app-space-5);border-radius:var(--radius);font-size:var(--app-t-base);border:1px solid;line-height:1.5}
.app-message--success{background:var(--tint-success);border-color:var(--tint-success-rule);color:var(--color-success)}
.app-message--warning{background:var(--tint-warning);border-color:var(--tint-warning-rule);color:var(--color-warning)}
.app-message--error{background:var(--tint-error);border-color:var(--tint-error-rule);color:var(--color-error)}

/* Iconos de línea: 1px, currentColor, rejilla de 16px. Heredan el color
   del control, así que se vuelven terracota en activo como todo lo demás. */
.app-icon{width:16px;height:16px;flex-shrink:0;stroke:currentColor;stroke-width:1;fill:none;stroke-linecap:square;stroke-linejoin:miter;display:block}
.app-icon--sm{width:13px;height:13px}
/* Parche mientras queden emoji semánticos (POI, capas GIS) sin sustituir */
.emoji{filter:saturate(0.55);font-style:normal}

/* ── CABECERA ────────────────────────────────────────────────── */
header{background:var(--color-raised);border-bottom:1px solid var(--rule);padding:var(--app-space-3) var(--app-space-6);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;z-index:100;gap:var(--app-space-5)}
.header-brand{display:flex;align-items:center;gap:var(--app-space-4);flex-shrink:0}
.header-brand img,.header-brand svg{display:block;flex-shrink:0}
.brand-wordmark{font-family:var(--font-display);font-size:var(--app-t-md);color:var(--color-primary);letter-spacing:0.06em;font-weight:500;line-height:1.14;white-space:nowrap}
.brand-version{font-family:var(--font-mono);font-size:var(--app-t-xs);color:var(--color-faint);letter-spacing:0.04em}
/* display:contents — el envoltorio no pinta nada en escritorio: .header-actions
   y .header-right siguen siendo hijos flex directos de <header>, así que la
   maquetación de escritorio es exactamente la de antes. En móvil este mismo
   elemento se convierte en el panel deslizante. */
.nav-drawer{display:contents}
.nav-drawer-head,.nav-menu-btn,.nav-scrim,.sheet-head,.toggle-label{display:none}
/* view-toggle + header-actions forman el grupo central: los márgenes
   automáticos lo centran igual que cuando eran un solo contenedor. */
.view-toggle{display:flex;gap:var(--app-space-3);align-items:center;flex-shrink:0;margin-left:auto}
.header-actions{display:flex;gap:var(--app-space-3);align-items:center;flex-shrink:0;margin-right:auto}
.header-right{display:flex;align-items:center;gap:var(--app-space-3);flex-shrink:0}
header .view-toggle .btn-sm{height:var(--ctrl-md)}
/* Equilibrio visual: TODO control de la cabecera mide lo mismo */
header .btn-sm,header .lang-btn,#ux-nav-upgrade,.header-right .ux-nav-link{height:var(--ctrl-md)}
#ux-nav-upgrade{font-size:var(--app-t-sm);padding:0 var(--app-space-5);letter-spacing:0.08em}
.ux-nav-link{display:inline-flex;align-items:center;padding:0 var(--app-space-3);font-family:var(--font-body);font-size:var(--app-t-base);font-weight:500;letter-spacing:0.04em;color:var(--color-mid);text-decoration:none;border:1px solid transparent;transition:color 0.18s var(--ease-out),border-color 0.18s var(--ease-out)}
.ux-nav-link:hover{color:var(--color-accent)}
.ux-nav-link--boxed{border-color:var(--rule-strong)}
.ux-nav-link--boxed:hover{border-color:var(--color-accent);color:var(--color-accent)}
.lang-selector{display:flex;align-items:center;gap:0;margin-right:var(--app-space-3)}
.lang-btn{padding:0 var(--app-space-4);font-size:var(--app-t-sm);letter-spacing:0.06em}
/* Selector de idioma como control segmentado: un solo filete entre botones */
.lang-selector .lang-btn+.lang-btn{border-left:none}

.sort-bar{display:flex;gap:var(--app-space-3)}
.sort-btn{font-size:var(--app-t-base);letter-spacing:0.06em;padding:0 var(--app-space-4)}

/* z-index:0 crea aquí un contexto de apilamiento, y eso es lo importante:
   Leaflet reparte z-index altos a sus propios elementos (panes 400, controles
   1000) y, sin contexto, esos números competían en la raíz contra el z-index
   100 de <header> — por eso el mapa y la barra GIS se pintaban ENCIMA del
   menú. Encerrados aquí, .main entero queda por debajo de la cabecera.
   Cualquier capa que deba tapar la cabecera va fuera de .main. */
.main{display:flex;flex:1;overflow:hidden;min-height:0;position:relative;z-index:0}

/* ── BARRA LATERAL ───────────────────────────────────────────── */
/* Filete fuerte a la derecha, igual que el del panel GIS: la lengüeta se
   apoya en él y la costura entre panel y pestaña queda continua. */
.sidebar{width:var(--sidebar-w);background:var(--color-sunken);border-right:1px solid var(--rule-strong);padding:0;overflow-y:hidden;flex-shrink:0;display:flex;flex-direction:column;transition:width 0.25s var(--ease-out),padding 0.25s var(--ease-out),border-color 0.25s var(--ease-out);position:relative}
.sidebar-scroll{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:var(--app-space-5);padding:var(--app-space-6) var(--app-space-6) var(--app-space-4);scrollbar-width:thin;scrollbar-color:var(--rule-strong) var(--color-sunken)}
.sidebar-footer{padding:var(--app-space-5) var(--app-space-6) var(--app-space-6);flex-shrink:0;border-top:1px solid var(--rule)}
/* Riel en vez de width:0 — mantiene el canto contra el que se apoya la pestaña */
.sidebar.collapsed{width:var(--sidebar-rail)!important;overflow:hidden!important;min-width:0}
/* El riel debe ser SÓLO fondo y filete. Sin esto, los 10px visibles recortan
   los controles y se ve el borde izquierdo de cada etiqueta e input. */
.sidebar.collapsed>*{visibility:hidden}
.sidebar.collapsed .sidebar-scroll,.sidebar.collapsed .sidebar-footer{padding:0!important;overflow:hidden!important}
.sidebar-scroll::-webkit-scrollbar{width:4px}
.sidebar-scroll::-webkit-scrollbar-track{background:var(--color-sunken)}
.sidebar-scroll::-webkit-scrollbar-thumb{background:var(--rule-strong);border-radius:var(--radius)}
.sidebar .btn-sm{border-color:var(--rule-strong);color:var(--color-mid)}
.sidebar .btn-sm:hover{color:var(--brand-light);border-color:var(--color-accent)}
/* ── PESTAÑAS DE PANEL (izquierda y derecha) ──────────────────
   Las dos son el mismo objeto: una lengüeta pegada al canto del panel que
   abren, sin filete en el lado que toca el panel para que se lea como una
   prolongación de él y no como algo flotando encima del mapa.
   La flecha SIEMPRE está — sólo gira. Nunca se escribe con textContent
   (eso borraría el SVG); el estado se marca con una clase. */
#sidebarToggleBtn,.gis-panel-toggle{
  position:absolute;top:50%;transform:translateY(-50%);
  width:22px;height:44px;padding:0;
  display:flex;align-items:center;justify-content:center;
  background:var(--color-sunken);
  border:1px solid var(--rule-strong);border-radius:var(--radius);
  color:var(--color-mid);cursor:pointer;
  transition:left 0.25s var(--ease-out),right 0.25s var(--ease-out),color 0.18s var(--ease-out),background-color 0.18s var(--ease-out),border-color 0.18s var(--ease-out)
}
/* Igual que la pestaña GIS: la posición la decide el SELECTOR DE HERMANO
   según el estado del panel, no un style.left escrito desde JS. Y se monta
   1px sobre el filete del panel para que la costura sea continua y la
   lengüeta se lea como parte del panel, no como algo suelto encima. */
#sidebarToggleBtn{border-left:none;z-index:1010;margin-left:-1px}
#sidebarPanel+#sidebarToggleBtn{left:var(--sidebar-w)}
#sidebarPanel.collapsed+#sidebarToggleBtn{left:var(--sidebar-rail)}
#sidebarToggleBtn:hover,.gis-panel-toggle:hover{background:var(--color-accent);border-color:var(--color-accent);color:var(--brand-light)}
#sidebarToggleBtn .app-icon,.gis-panel-toggle .app-icon{width:13px;height:13px;transition:transform 0.25s var(--ease-out)}
/* Plegado: la flecha apunta al lado por el que se abrirá */
#sidebarToggleBtn.is-collapsed .app-icon{transform:rotate(180deg)}
.gis-panel-toggle.is-open .app-icon{transform:rotate(180deg)}
#layerLoadingBar{display:none;position:fixed;top:0;left:0;right:0;height:2px;z-index:5000;background:linear-gradient(90deg,transparent,var(--color-accent),transparent);background-size:200% 100%;animation:loadSlide 1.2s linear infinite}
@keyframes loadSlide{0%{background-position:200% 0}100%{background-position:-200% 0}}

/* ── FORMULARIOS ─────────────────────────────────────────────── */
/* Los grupos se separan con filete, no sólo con hueco: es el gesto
   arquitectónico del site aplicado a un panel de control. */
.filter-group{display:flex;flex-direction:column;gap:var(--app-space-3);border-bottom:1px solid var(--rule-faint);padding-bottom:var(--app-space-5)}
.filter-group:last-child{border-bottom:none;padding-bottom:0}
.filter-label{font-family:var(--font-body);font-size:var(--app-t-sm);font-weight:500;letter-spacing:0.12em;text-transform:uppercase;color:var(--color-mid)}
.filter-select,.filter-input{width:100%;height:var(--ctrl-md);padding:0 9px;background:var(--color-raised);border:1px solid var(--rule-strong);border-radius:var(--radius);color:var(--color-primary);font-family:var(--font-body);font-size:var(--app-t-base);transition:border-color 0.2s var(--ease-out)}
.filter-input[type=number]{font-family:var(--font-mono);font-variant-numeric:slashed-zero tabular-nums}
.filter-select{appearance:none;cursor:pointer;padding-right:26px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%233E3A37'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 9px center}
.filter-input:hover,.filter-select:hover{border-color:rgba(67,81,92,0.5)}
.filter-select:focus,.filter-input:focus{outline:2px solid var(--color-accent);outline-offset:1px;border-color:var(--color-accent)}
.filter-input::placeholder{color:var(--color-placeholder)}
.range-row{display:flex;gap:var(--app-space-3);align-items:center}
.range-sep{color:var(--color-faint);font-size:var(--app-t-base);flex-shrink:0}
.range-row .filter-input{width:50%}
input[type=checkbox],input[type=radio]{accent-color:var(--color-accent);cursor:pointer}
input[type=range]{flex:1;accent-color:var(--color-accent);height:3px;cursor:pointer}

.type-grid{display:flex;flex-wrap:wrap;gap:var(--app-space-2)}
.type-btn{height:var(--ctrl-sm);padding:0 var(--app-space-4);font-size:var(--app-t-base)}

.portais-header,.weights-header{display:flex;justify-content:space-between;align-items:center;cursor:pointer;padding:var(--app-space-2) 0}
.portais-header:hover .filter-label,.weights-header:hover .filter-label{color:var(--color-accent)}
/* Cuadratín dibujado: dos filetes de 1px, no un glifo tipográfico */
.portais-chevron{width:16px;height:16px;flex-shrink:0;position:relative;color:var(--color-faint)}
.portais-chevron::before{content:'';position:absolute;left:5px;top:50%;width:5px;height:5px;border-right:1px solid currentColor;border-bottom:1px solid currentColor;transform:translateY(-50%) rotate(-45deg);transition:transform 0.2s var(--ease-out)}
.portais-chevron.open::before{transform:translateY(-50%) rotate(45deg)}
.portais-header:hover .portais-chevron,.weights-header:hover .portais-chevron{color:var(--color-accent)}
/* Los grupos de variables GIS también son plegables: mismo cuadratín */
.gis-var-group-title{display:flex;align-items:center;gap:var(--app-space-3)}
.gis-var-group-title::before{content:'';width:5px;height:5px;flex-shrink:0;border-right:1px solid currentColor;border-bottom:1px solid currentColor;transform:rotate(-45deg)}
.portais-mini-dot{width:5px;height:5px;border-radius:50%;background:var(--rule-strong);flex-shrink:0}
.portais-body{display:none;flex-direction:column;gap:var(--app-space-2);margin-top:var(--app-space-2)}
.portais-body.open{display:flex}
.portal-row{display:flex;align-items:center;gap:var(--app-space-3);padding:var(--app-space-2) var(--app-space-1);font-size:var(--app-t-base);color:var(--color-mid);line-height:1.3}
.portal-row input[type=checkbox]{width:13px;height:13px;flex-shrink:0}
.portal-row label{flex:1;cursor:pointer;display:flex;align-items:center;gap:var(--app-space-3)}
.portal-rpp{width:46px;height:var(--ctrl-xs);background:var(--color-raised);border:1px solid var(--rule-strong);color:var(--color-mid);padding:0 var(--app-space-2);border-radius:var(--radius);font-family:var(--font-mono);font-size:var(--app-t-sm);text-align:center;font-variant-numeric:slashed-zero tabular-nums}
.portal-rpp:focus{outline:2px solid var(--color-accent);outline-offset:1px;border-color:var(--color-accent)}
.portal-status-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0;background:var(--rule-strong)}
.portal-status-dot.ok{background:var(--color-success)}
.portal-status-dot.warn{background:var(--color-warning)}
.portal-status-dot.err{background:var(--color-error)}
.portal-status-dot.busy{background:var(--color-accent);animation:pulse 1s infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.4}}

.tier-badge{font-family:var(--font-body);font-size:var(--app-t-xs);font-weight:600;padding:1px var(--app-space-2);border-radius:var(--radius);border:1px solid;flex-shrink:0;line-height:1.4}
.tier-a{background:var(--tint-success);color:var(--color-success);border-color:var(--tint-success-rule)}
.tier-b{background:var(--tint-warning);color:var(--color-warning);border-color:var(--tint-warning-rule)}
.sr-auto-badge{font-size:var(--app-t-xs);font-weight:600;padding:1px var(--app-space-2);border-radius:var(--radius);background:var(--tint-accent);color:var(--color-accent);border:1px solid var(--tint-accent-rule);flex-shrink:0;margin-left:auto;line-height:1.4}

.weights-body{display:none;flex-direction:column;gap:var(--app-space-3);margin-top:var(--app-space-2)}
.weights-body.open{display:flex}
.weight-row{display:flex;align-items:center;gap:var(--app-space-3)}
.weight-label{font-size:var(--app-t-sm);color:var(--color-mid);flex:1}
.weight-val{font-family:var(--font-mono);font-size:var(--app-t-sm);color:var(--color-accent);width:14px;text-align:center;flex-shrink:0;font-variant-numeric:slashed-zero tabular-nums}

.search-btn{width:100%;margin-top:var(--app-space-2)}

/* ── RESULTADOS ──────────────────────────────────────────────── */
.content{flex:1;display:flex;flex-direction:column;overflow:hidden;min-height:0}
.results-header{padding:var(--app-space-4) var(--app-space-6);border-bottom:1px solid var(--rule);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;gap:var(--app-space-4);background:var(--color-raised)}
.results-count{font-size:var(--app-t-lg);color:var(--color-mid);white-space:nowrap}
.results-count strong{font-family:var(--font-mono);font-weight:600;color:var(--color-accent);font-variant-numeric:slashed-zero tabular-nums}
.results-count em{color:var(--color-faint);font-style:normal;font-size:var(--app-t-sm);margin-left:var(--app-space-3)}
.dedup-toggle{font-size:var(--app-t-base);padding:0 var(--app-space-4)}
.view-area{flex:1;overflow:hidden;position:relative;min-height:0}
.grid-view{padding:var(--app-space-5) var(--app-space-5);display:grid;grid-template-columns:repeat(4,1fr);grid-auto-rows:min-content;gap:var(--app-space-4);overflow-y:auto;height:100%;align-content:start;align-items:start;min-height:0;scrollbar-width:thin;scrollbar-color:var(--rule-strong) var(--color-bg)}
.grid-view::-webkit-scrollbar{width:4px}
.grid-view::-webkit-scrollbar-track{background:var(--color-bg)}
.grid-view::-webkit-scrollbar-thumb{background:var(--rule-strong);border-radius:var(--radius)}
.map-view{width:100%;height:100%;display:none;position:relative}

/* ── TARJETAS ────────────────────────────────────────────────── */
.card{background:var(--color-raised);border:1px solid var(--rule);border-radius:var(--radius);overflow:hidden;display:flex;flex-direction:column;transition:border-color 0.18s var(--ease-out);position:relative;align-self:start}
.card:hover{border-color:var(--color-accent)}
.card.card-selected{border-color:var(--color-accent);background:var(--tint-accent);box-shadow:inset 0 0 0 1px var(--color-accent)}
.card.card-dupe{opacity:0.55;border-style:dashed}
.card-img-wrap{position:relative;height:110px;overflow:hidden;background:var(--color-sunken);flex-shrink:0;cursor:pointer}
.card-img-wrap img{width:100%;height:100%;object-fit:cover;display:block;transition:transform 0.2s var(--ease-out)}
.card-img-wrap:hover img{transform:scale(1.03)}
.card-img-placeholder{display:flex;align-items:center;justify-content:center;width:100%;height:100%;color:var(--rule-strong);position:relative}
/* Marca de imagen ausente: dos filetes de 1px cruzados, no un emoji */
.card-img-placeholder::before,.card-img-placeholder::after{content:'';position:absolute;left:50%;top:50%;background:var(--rule-strong)}
.card-img-placeholder::before{width:22px;height:1px;transform:translate(-50%,-50%)}
.card-img-placeholder::after{width:1px;height:22px;transform:translate(-50%,-50%)}
.card-portal-badge{position:absolute;bottom:var(--app-space-2);left:var(--app-space-2);font-family:var(--font-body);font-size:var(--app-t-xs);font-weight:600;letter-spacing:0.08em;padding:2px var(--app-space-3);border-radius:var(--radius);text-transform:uppercase;line-height:1.4;backdrop-filter:blur(4px)}
.card-score-badge{position:absolute;top:var(--app-space-2);right:var(--app-space-2);font-family:var(--font-mono);font-size:var(--app-t-xs);font-weight:600;padding:2px var(--app-space-3);border-radius:var(--radius);background:var(--color-accent);color:var(--brand-light);line-height:1.4;font-variant-numeric:slashed-zero tabular-nums}
.card-score-badge.mid{background:var(--color-warning);color:var(--brand-light)}
.card-score-badge.low{background:var(--rule-strong);color:var(--color-primary)}
.card-select-btn{position:absolute;top:var(--app-space-2);left:var(--app-space-2);background:rgba(241,239,232,0.92);border:1px solid var(--rule-strong);color:var(--color-mid);font-size:var(--app-t-base);padding:2px var(--app-space-3);border-radius:var(--radius);cursor:pointer;line-height:1.4;backdrop-filter:blur(3px);transition:color 0.18s var(--ease-out),border-color 0.18s var(--ease-out),background-color 0.18s var(--ease-out);z-index:2}
.card-select-btn::before{content:'☆';font-size:1.05em;line-height:1}
.card-select-btn.active::before{content:'★'}
.card-select-btn:hover{border-color:var(--color-accent);color:var(--color-accent)}
.card-select-btn.active{background:var(--color-accent);border-color:var(--color-accent);color:var(--brand-light);font-weight:600}
.card-multi-badge{position:absolute;bottom:var(--app-space-2);right:var(--app-space-2);font-family:var(--font-mono);font-size:var(--app-t-xs);background:var(--color-accent);color:var(--brand-light);padding:1px var(--app-space-2);border-radius:var(--radius);font-weight:600;line-height:1.4}
.card-body{padding:var(--app-space-3) var(--app-space-4) 5px;display:flex;flex-direction:column;gap:var(--app-space-2);flex:1;overflow:hidden}
/* El precio pasa de oro a tinta: un número rojo junto a una divisa se lee
   como saldo negativo o error, no como precio. */
.card-price{font-family:var(--font-mono);font-size:var(--app-t-lg);font-weight:600;color:var(--color-primary);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:slashed-zero tabular-nums}
.card-title{font-size:var(--app-t-base);color:var(--color-primary);overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;line-height:1.3}
.card-specs{display:flex;gap:var(--app-space-2);flex-wrap:wrap}
.spec-chip{font-family:var(--font-mono);font-size:var(--app-t-xs);color:var(--color-mid);background:var(--color-sunken);border:1px solid var(--rule);border-radius:var(--radius);padding:1px 5px;white-space:nowrap;line-height:1.5}
.spec-chip.hl{color:var(--color-primary);border-color:var(--rule-strong)}
.card-location{font-size:var(--app-t-sm);color:var(--color-faint);display:flex;align-items:center;gap:var(--app-space-2);margin-top:auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.geo-dot{width:4px;height:4px;border-radius:50%;flex-shrink:0}
.geo-exact{background:var(--color-accent)}
.geo-approx{background:var(--rule-strong)}
.card-actions{display:flex;gap:var(--app-space-2);padding:0 var(--app-space-4) var(--app-space-3);flex-shrink:0}
.card-btn{flex:1;font-size:var(--app-t-base);padding:0 var(--app-space-3)}
.card-save-btn,.card-iso-btn{flex-shrink:0;font-size:var(--app-t-base);padding:0 var(--app-space-4)}
.card-save-btn.saved{background:var(--color-accent);border-color:var(--color-accent);color:var(--brand-light);font-weight:600}
.card-save-btn.loading{opacity:0.6;pointer-events:none}

/* ── MAPA (Leaflet) ──────────────────────────────────────────── */
#mapContainer{position:absolute;top:0;left:0;right:0;bottom:0;transition:right 0.25s var(--ease-out);background:var(--color-sunken)}
/* Único indicio de profundidad permitido: desenfoque bajo los paneles
   que flotan sobre el mapa. Nunca sombra. */
/* Zoom: tira horizontal centrada abajo, por encima de la barra GIS. En
   vertical a la derecha chocaba con la pestaña del panel GIS. */
#zoomSliderWrap{position:absolute;left:50%;right:auto;top:auto;bottom:52px;transform:translateX(-50%);z-index:1000;display:flex;flex-direction:row;align-items:center;gap:var(--app-space-3);background:rgba(241,239,232,0.97);border:1px solid var(--rule-strong);border-radius:var(--radius);padding:var(--app-space-2) var(--app-space-4);backdrop-filter:blur(8px)}
#zoomSliderWrap button{background:transparent;border:none;color:var(--color-mid);font-family:var(--font-body);font-size:var(--app-t-lg);cursor:pointer;line-height:1;padding:0 var(--app-space-2);min-width:18px;transition:color 0.18s var(--ease-out)}
#zoomSliderWrap button:hover{color:var(--color-accent)}
#zoomSlider{writing-mode:horizontal-tb;direction:ltr;width:170px;height:3px;accent-color:var(--color-accent);cursor:pointer}
#zoomSliderVal{font-family:var(--font-mono);font-size:var(--app-t-xs);color:var(--color-faint);letter-spacing:0.04em;font-variant-numeric:slashed-zero tabular-nums;min-width:14px;text-align:center}
/* La barra del clima empuja la barra GIS hacia arriba; el zoom la sigue. */
body:has(#mapGisBar.bar-raised) #zoomSliderWrap{bottom:114px}
.leaflet-popup-content-wrapper{background:var(--color-raised)!important;color:var(--color-primary)!important;border:1px solid var(--rule-strong)!important;border-radius:var(--radius)!important;box-shadow:none!important}
.leaflet-popup-tip{background:var(--color-raised)!important;box-shadow:none!important}
.leaflet-popup-content{margin:0!important;padding:0!important}
/* Foco SÓLO por teclado. Con :focus, hacer clic en un polígono le daba el
   foco y el navegador dibujaba el contorno del bounding box del trazado —
   el cuadrado que aparecía alrededor del concelho seleccionado. Con
   :focus-visible el ratón no lo dispara y el teclado sigue teniendo foco. */
.leaflet-interactive:focus{outline:none!important}
.leaflet-interactive:focus-visible{outline:2px solid var(--map-select)!important;outline-offset:2px}
.tooltip-concelho,.leaflet-tooltip-gis{background:var(--color-raised);border:1px solid var(--rule-strong);color:var(--color-primary);font-size:var(--app-t-base);padding:var(--app-space-2) var(--app-space-3);border-radius:var(--radius);box-shadow:none}
/* pointer-events:none para não bloquear o mapa; só o × volta a recebê-los */
.map-hint{position:absolute;top:var(--app-space-4);left:50%;transform:translateX(-50%);z-index:999;display:flex;align-items:center;gap:var(--app-space-3);background:rgba(241,239,232,0.97);border:1px solid var(--rule-strong);border-radius:var(--radius);padding:var(--app-space-2) var(--app-space-3) var(--app-space-2) var(--app-space-6);font-size:var(--app-t-base);color:var(--color-mid);letter-spacing:0.05em;pointer-events:none;white-space:nowrap;backdrop-filter:blur(8px);max-width:calc(100% - 20px)}
.map-hint span{overflow:hidden;text-overflow:ellipsis}
.map-hint-close{pointer-events:auto;flex-shrink:0;background:none;border:none;color:var(--color-faint);cursor:pointer;font-size:var(--app-t-md);line-height:1;padding:0 var(--app-space-2);transition:color 0.18s var(--ease-out)}
.map-hint-close:hover{color:var(--color-accent)}

/* ── PANEL GIS ───────────────────────────────────────────────── */
.gis-legend{position:absolute;left:10px;bottom:130px;top:auto;right:auto;z-index:1001;background:rgba(241,239,232,0.97);border:1px solid var(--rule-strong);border-radius:var(--radius);padding:var(--app-space-4) var(--app-space-9) var(--app-space-4) var(--app-space-5);display:none;min-width:150px;max-width:210px;backdrop-filter:blur(8px)}
.gis-legend.visible{display:block}
/* Em desktop o contentor não existe visualmente: cada painel mantém o seu
   position:absolute de sempre. Em móvel (ver media query) vira coluna. */
.map-info-stack{display:contents}
.gis-legend-title{font-family:var(--font-body);font-size:var(--app-t-sm);font-weight:500;color:var(--color-mid);letter-spacing:0.12em;text-transform:uppercase;margin-bottom:var(--app-space-3);display:flex;align-items:center;gap:var(--app-space-4)}
.gis-legend-title::before{content:'';width:16px;height:1px;background:var(--color-accent);flex-shrink:0}
.gis-legend-item{display:flex;align-items:center;gap:var(--app-space-3);font-size:var(--app-t-base);color:var(--color-mid);padding:1px 0;line-height:1.3}
.gis-legend-swatch{width:10px;height:10px;border-radius:var(--radius);flex-shrink:0;border:1px solid var(--rule)}
#gisInfoPanel{display:none!important}
.gis-panel-right{position:absolute;right:0;top:0;bottom:0;width:220px;background:rgba(241,239,232,0.98);border-left:1px solid var(--rule-strong);z-index:1002;transition:transform 0.25s var(--ease-out);overflow-y:auto;padding:var(--app-space-5);backdrop-filter:blur(8px);scrollbar-width:thin;scrollbar-color:var(--rule-strong) transparent}
.gis-panel-right.collapsed{transform:translateX(210px)}
/* el toggle es HERMANO del panel (fuera del overflow-y:auto).
   Geometría y estados compartidos con #sidebarToggleBtn más arriba. */
.gis-panel-toggle{right:0;border-right:none;z-index:1003;margin-right:-1px}
#gisPanelRight:not(.collapsed)+.gis-panel-toggle{right:220px}
.gis-panel-title{font-family:var(--font-body);font-size:var(--app-t-sm);font-weight:500;color:var(--color-mid);letter-spacing:0.12em;text-transform:uppercase;margin-bottom:var(--app-space-3);display:flex;align-items:center;gap:var(--app-space-4)}
.gis-panel-title::before{content:'';width:16px;height:1px;background:var(--color-accent);flex-shrink:0}
.gis-section{margin-bottom:var(--app-space-5);border-bottom:1px solid var(--rule);padding-bottom:var(--app-space-5)}
.gis-section:last-child{border-bottom:none}
.gis-section-title{font-family:var(--font-body);font-size:var(--app-t-sm);font-weight:500;letter-spacing:0.12em;color:var(--color-mid);text-transform:uppercase;margin-bottom:var(--app-space-4);display:flex;align-items:center;gap:var(--app-space-4)}
.gis-section-title::before{content:'';width:16px;height:1px;background:var(--color-accent);flex-shrink:0}
.gis-radio-group label{display:block;font-size:var(--app-t-base);color:var(--color-mid);cursor:pointer;margin:var(--app-space-2) 0;line-height:1.3}
.gis-var-group{margin-bottom:var(--app-space-3)}
.gis-var-group-title{font-size:var(--app-t-base);color:var(--color-faint);cursor:pointer;margin:var(--app-space-2) 0;transition:color 0.18s var(--ease-out)}
.gis-var-group-title:hover{color:var(--color-accent)}
.gis-var-btn{display:block;width:100%;text-align:left;background:none;border:none;border-left:1px solid transparent;color:var(--color-mid);font-family:var(--font-body);font-size:var(--app-t-base);padding:var(--app-space-1) var(--app-space-4);cursor:pointer;line-height:1.3;transition:color 0.18s var(--ease-out),border-color 0.18s var(--ease-out)}
.gis-var-btn:hover{color:var(--color-accent)}
.gis-var-btn.active{color:var(--color-accent);font-weight:600;border-left-color:var(--color-accent)}
.gis-var-btn.na{color:var(--color-placeholder)!important;cursor:default;text-decoration:line-through;opacity:0.55}
.gis-btn-link{display:flex;width:100%;margin:var(--app-space-1) 0;font-size:var(--app-t-base);padding:0 var(--app-space-4);justify-content:flex-start}
.gis-note{font-size:var(--app-t-sm);color:var(--color-faint);margin-top:var(--app-space-3);line-height:1.5}
#radiusSelect{height:var(--ctrl-sm);background:var(--color-raised);border:1px solid var(--rule-strong);color:var(--color-mid);padding:0 var(--app-space-3);border-radius:var(--radius);font-family:var(--font-body);font-size:var(--app-t-base);cursor:pointer}
.choropleth-legend{margin-top:var(--app-space-4)}
.choropleth-legend-bar{display:flex;height:8px;border-radius:var(--radius);overflow:hidden;margin-bottom:var(--app-space-2);border:1px solid var(--rule)}
.choropleth-legend-bar div{flex:1}
.choropleth-legend-labels{display:flex;justify-content:space-between;font-family:var(--font-mono);font-size:var(--app-t-xs);color:var(--color-faint);font-variant-numeric:slashed-zero tabular-nums}
.gis-ctx-section{display:none}
.gis-ctx-section.ctx-visible{display:block}
.gis-ctx-wms-info{font-size:var(--app-t-base);color:var(--color-mid);line-height:1.5;padding:var(--app-space-2) 0}
.gis-ctx-wms-info b{color:var(--color-primary);font-weight:500}
.gis-pdm-warn{margin-top:var(--app-space-3);font-size:var(--app-t-sm);color:var(--color-warning);background:var(--tint-warning);border:1px solid var(--tint-warning-rule);border-radius:var(--radius);padding:var(--app-space-3) var(--app-space-4);line-height:1.5}
/* Barra GIS del mapa: mismo tamaño que el resto de controles */
#mapGisBar .btn-sm{height:var(--ctrl-sm);font-size:var(--app-t-base);padding:0 var(--app-space-4);letter-spacing:0.04em;background:rgba(241,239,232,0.97);border-color:var(--rule-strong);color:var(--color-mid);backdrop-filter:blur(8px)}
/* El selector con ID gana al :hover genérico, así que hay que repetir aquí
   el texto claro: si no, el rótulo se queda gris sobre el relleno de tinta. */
#mapGisBar .btn-sm:hover{color:var(--brand-light);border-color:var(--color-accent)}
#mapGisBar .btn-sm.active{background:var(--color-accent);border-color:var(--color-accent)!important;color:var(--brand-light);font-weight:600}
#mapGisBar select{height:var(--ctrl-sm);font-size:var(--app-t-base);padding:0 var(--app-space-3);background:rgba(241,239,232,0.97);border:1px solid var(--rule-strong);border-radius:var(--radius);color:var(--color-mid)}
#mapGisBar.bar-raised{bottom:calc(62px + env(safe-area-inset-bottom,0))!important}
#climaBar .btn-sm{background:var(--color-raised);border-color:var(--rule-strong);color:var(--color-mid)}
#climaBar .btn-sm:hover{color:var(--brand-light);border-color:var(--color-accent)}
#climaBar .btn-sm.active{background:var(--color-accent);border-color:var(--color-accent);color:var(--brand-light);font-weight:600}

/* ── ETIQUETAS DE LOCALIZACIÓN ───────────────────────────────── */
.loc-tags{display:flex;flex-wrap:wrap;gap:var(--app-space-2);min-height:22px;padding:var(--app-space-1) 0}
.loc-tag{background:var(--tint-accent);border:1px solid var(--tint-accent-rule);color:var(--color-accent);border-radius:var(--radius);font-size:var(--app-t-base);padding:2px 7px;display:flex;align-items:center;gap:var(--app-space-2);line-height:1.4}
.loc-tag-x{cursor:pointer;color:rgba(62,58,55,0.55);font-weight:500;margin-left:var(--app-space-1);font-size:var(--app-t-md);line-height:1;transition:color 0.18s var(--ease-out)}
.loc-tag-x:hover{color:var(--color-accent)}
.loc-empty{font-size:var(--app-t-sm);color:var(--color-faint)}

/* ── ESTADO VACÍO ────────────────────────────────────────────── */
.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--rule-strong);gap:var(--app-space-5)}
/* Cruceta de dos filetes de 1px en lugar del emoji de 3rem */
.empty-icon{position:relative;width:40px;height:40px;flex-shrink:0;font-size:0}
.empty-icon::before,.empty-icon::after{content:'';position:absolute;left:50%;top:50%;background:var(--rule-strong)}
.empty-icon::before{width:40px;height:1px;transform:translate(-50%,-50%)}
.empty-icon::after{width:1px;height:40px;transform:translate(-50%,-50%)}
.empty-text{font-size:var(--app-t-lg);letter-spacing:0.08em;color:var(--color-mid)}
.empty-hint{font-size:var(--app-t-base);color:var(--color-faint);letter-spacing:0.04em;text-align:center;max-width:280px;line-height:1.5}

/* ── AVISOS Y PANELES FLOTANTES ──────────────────────────────── */
#saveToast{position:fixed;bottom:24px;left:50%;transform:translateX(-50%);z-index:3000;background:var(--color-primary);color:var(--color-on-dark);padding:var(--app-space-5) var(--app-space-7);border-radius:var(--radius);font-size:var(--app-t-md);display:none;max-width:340px;text-align:center;line-height:1.5}
#saveToast a{color:var(--color-accent-on-dark);word-break:break-all}
#saveToast .save-toast-copy{margin-left:var(--app-space-4);cursor:pointer;font-size:var(--app-t-base);color:var(--color-accent-on-dark);text-decoration:underline}
#loadingToast{display:none;position:fixed;top:56px;left:50%;transform:translateX(-50%);z-index:4000;background:var(--color-primary);border:1px solid var(--rule-on-dark);border-radius:var(--radius);padding:var(--app-space-3) var(--app-space-7);font-size:var(--app-t-base);color:var(--color-on-dark);letter-spacing:0.06em;pointer-events:none;white-space:nowrap}
#analysisToast{display:none;position:fixed;top:56px;left:50%;transform:translateX(-50%);z-index:4001;background:var(--color-primary);border:1px solid var(--color-accent-on-dark);border-radius:var(--radius);padding:var(--app-space-4) var(--app-space-8);font-size:var(--app-t-base);color:var(--color-accent-on-dark);letter-spacing:0.04em;cursor:pointer;white-space:nowrap;transition:background-color 0.18s var(--ease-out)}
#analysisToast:hover{background:var(--brand-dark)}
.portal-status-panel{border-top:1px solid var(--rule);padding:var(--app-space-4) var(--app-space-6);flex-shrink:0;font-size:var(--app-t-sm);display:none;background:var(--color-raised)}
.portal-status-panel.visible{display:block}
.psp-grid{display:flex;gap:var(--app-space-5);flex-wrap:wrap}
.psp-item{display:flex;align-items:center;gap:var(--app-space-2);color:var(--color-faint)}
.psp-item strong{font-family:var(--font-mono);font-weight:500;color:var(--color-mid);font-variant-numeric:slashed-zero tabular-nums}
.psp-item.ok strong{color:var(--color-success)}
.psp-item.warn strong{color:var(--color-warning)}
.psp-item.err strong{color:var(--color-error)}

#selectionBar{display:none;position:fixed;top:50px;right:10px;left:auto;z-index:2000;background:var(--color-raised);border:1px solid var(--color-accent);border-radius:var(--radius);padding:var(--app-space-3) var(--app-space-5);align-items:center;gap:var(--app-space-3);max-width:calc(100vw - 20px);flex-wrap:wrap}
.sel-count{font-family:var(--font-mono);color:var(--color-accent);font-size:var(--app-t-md);font-weight:600;flex:1;font-variant-numeric:slashed-zero tabular-nums}
.sel-btn{height:var(--ctrl-sm);padding:0 var(--app-space-5);font-size:var(--app-t-base);font-weight:500}
.sel-btn-primary{height:var(--ctrl-sm);padding:0 var(--app-space-5);font-size:var(--app-t-base);letter-spacing:0.06em}
.sel-btn-secondary{border:1px solid var(--rule-strong);color:var(--color-mid)}
.sel-iso-btn{padding:0 var(--app-space-4);font-size:var(--app-t-base)}
.sel-iso-btn.active{background:var(--color-accent);border-color:var(--color-accent);color:var(--brand-light);font-weight:600}
.sel-modal-btn{padding:0 var(--app-space-4);font-size:var(--app-t-base);font-weight:500}

/* Modales flotantes de resultados */
.result-modal{display:none;position:fixed;top:56px;right:12px;left:auto;transform:none;z-index:3500;background:rgba(241,239,232,0.97);border:1px solid var(--rule-strong);border-radius:var(--radius);padding:var(--app-space-5) var(--app-space-6);max-width:460px;width:calc(100% - 24px);max-height:75vh;overflow-y:auto;backdrop-filter:blur(8px);scrollbar-width:thin;scrollbar-color:var(--rule-strong) transparent}
.result-modal.visible{display:block}
.result-modal-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:var(--app-space-4);padding-bottom:var(--app-space-3);border-bottom:1px solid var(--rule)}
.result-modal-title{font-family:var(--font-body);font-size:var(--app-t-sm);font-weight:500;color:var(--color-mid);letter-spacing:0.12em;text-transform:uppercase;display:flex;align-items:center;gap:var(--app-space-4)}
.result-modal-title::before{content:'';width:16px;height:1px;background:var(--color-accent);flex-shrink:0}
.result-modal-close{background:none;border:none;color:var(--color-faint);cursor:pointer;font-size:var(--app-t-xl);line-height:1;padding:0 var(--app-space-1);transition:color 0.18s var(--ease-out)}
.result-modal-close:hover{color:var(--color-accent)}

/* Superposición de búsqueda */
#searchOverlay{display:none;position:fixed;inset:0;z-index:3800;background:rgba(246,245,240,0.96);backdrop-filter:blur(8px);flex-direction:column;align-items:center;justify-content:center;gap:var(--app-space-8);padding:32px}
#searchOverlay.active{display:flex}
.sov-title{font-family:var(--font-display);font-size:var(--app-t-2xl);color:var(--color-primary);letter-spacing:-0.015em;font-weight:500;line-height:1.14;text-align:center}
.sov-coverage{font-family:var(--font-mono);font-size:var(--app-t-md);color:var(--color-accent);letter-spacing:0.08em;text-align:center;font-variant-numeric:slashed-zero tabular-nums}
.sov-bar-wrap{width:220px;height:2px;background:var(--rule);border-radius:var(--radius);overflow:hidden}
.sov-bar{height:100%;background:var(--color-accent);border-radius:var(--radius);animation:sovSlide 2s var(--ease-out) infinite alternate}
@keyframes sovSlide{0%{width:20%}100%{width:95%}}
.sov-disclaimer{font-size:var(--app-t-sm);color:var(--color-faint);text-align:center;max-width:360px;line-height:1.6}
@keyframes spin{to{transform:rotate(360deg)}}
.spin{display:inline-block;animation:spin 1s linear infinite}

/* ── INSIGNIAS DE PLAN ───────────────────────────────────────── */
.ux-nav-back{color:var(--color-faint);font-size:var(--app-t-base);letter-spacing:0.06em;text-decoration:none;font-family:var(--font-body);transition:color 0.18s var(--ease-out)}
.ux-nav-back:hover{color:var(--color-accent)}
#ux-tier-badge{font-family:var(--font-body);font-size:var(--app-t-xs);letter-spacing:0.12em;font-weight:600;padding:2px var(--app-space-4);border-radius:var(--radius);text-transform:uppercase;line-height:1.6}
#ux-tier-badge.tier-free{background:transparent;color:var(--color-faint);border:1px solid var(--rule-strong)}
#ux-tier-badge.tier-demo{background:transparent;color:var(--color-success);border:1px solid var(--tint-success-rule)}
#ux-tier-badge.tier-home_match{background:transparent;color:var(--color-accent);border:1px solid var(--tint-accent-rule)}
#ux-tier-badge.tier-lifestyle_match{background:var(--tint-accent);color:var(--color-accent);border:1px solid var(--tint-accent-rule)}
#ux-tier-badge.tier-business_match{background:var(--tint-accent);color:var(--color-accent);border:1px solid var(--color-accent)}
#ux-tier-badge.tier-investment_match{background:var(--tint-accent);color:var(--color-accent);border:1px solid var(--color-accent)}
#ux-tier-badge.tier-professional,#ux-tier-badge.tier-agency,#ux-tier-badge.tier-pro_investor{background:var(--color-accent);color:var(--brand-light);border:1px solid var(--color-accent)}
.ux-upgrade-hint{display:none;font-size:var(--app-t-sm);color:var(--color-mid);letter-spacing:0.04em;text-decoration:none;border:1px solid var(--rule);border-radius:var(--radius);padding:2px 7px;flex-shrink:0;cursor:pointer;white-space:nowrap;transition:color 0.18s var(--ease-out),border-color 0.18s var(--ease-out)}
.ux-upgrade-hint:hover{color:var(--color-accent);border-color:var(--color-accent)}

/* ── PANEL DE DEPURACIÓN (sólo desarrollo, fuera del ámbito de marca) ── */
#debugBtn{display:none;position:fixed;bottom:14px;right:14px;z-index:3000;background:var(--color-primary);border:1px solid var(--rule-on-dark);color:var(--on-dark-55);padding:5px 10px;border-radius:var(--radius);cursor:pointer;font-size:var(--app-t-sm);font-family:var(--font-mono);transition:bottom 0.18s var(--ease-out),color 0.18s var(--ease-out),border-color 0.18s var(--ease-out)}
#debugBtn:hover{color:var(--color-accent-on-dark);border-color:var(--color-accent-on-dark)}
body.sel-active #debugBtn{bottom:62px}
body.debug-visible #debugBtn{display:block}
#debugPanel{position:fixed;bottom:44px;right:14px;z-index:2999;width:500px;max-height:380px;background:#0a0a0a;border:1px solid #2a2a2a;border-radius:var(--radius);display:none;flex-direction:column;font-family:var(--font-mono);font-size:var(--app-t-sm)}
#debugPanel.open{display:flex}
#debugPanelHead{display:flex;justify-content:space-between;align-items:center;padding:7px 10px;border-bottom:1px solid #1a1a1a;color:var(--color-accent-on-dark);font-weight:600}
#debugPanelHead button{background:transparent;border:1px solid #333;color:#888;padding:2px 7px;border-radius:var(--radius);cursor:pointer;font-size:var(--app-t-xs)}
#debugPanelHead button:hover{color:var(--color-accent-on-dark)}
#debugLog{overflow-y:auto;padding:7px 10px;flex:1;display:flex;flex-direction:column;gap:2px}
#debugLog::-webkit-scrollbar{width:3px}
#debugLog::-webkit-scrollbar-thumb{background:#2a2a2a}
.dbg-line{color:#888;line-height:1.4}
.dbg-ok{color:#7fb08f}.dbg-warn{color:#d0a55a}.dbg-err{color:#e2947c}.dbg-info{color:#8fa8bd}

/* ── AGENTE LIFESTYLE ────────────────────────────────────────── */
#agentPanel{display:none;flex-direction:column;height:100%;overflow:hidden;background:var(--color-sunken)}
#agentHeader{padding:var(--app-space-5) var(--app-space-6);border-bottom:1px solid var(--rule);display:flex;justify-content:space-between;align-items:center;flex-shrink:0}
#agentThread{flex:1;overflow-y:auto;padding:var(--app-space-5) var(--app-space-6);display:flex;flex-direction:column;gap:var(--app-space-5);scroll-behavior:smooth;scrollbar-width:thin;scrollbar-color:var(--rule-strong) var(--color-sunken)}
#agentThread::-webkit-scrollbar{width:3px}
#agentThread::-webkit-scrollbar-thumb{background:var(--rule-strong);border-radius:var(--radius)}
#agentInputArea{padding:var(--app-space-5) var(--app-space-6);border-top:1px solid var(--rule);display:flex;flex-direction:column;gap:var(--app-space-3);flex-shrink:0}
#agentOptions{display:flex;flex-wrap:wrap;gap:var(--app-space-3)}
#agentTextInput{width:100%;box-sizing:border-box;resize:none;border:1px solid var(--rule-strong);border-radius:var(--radius);padding:var(--app-space-4) 9px;font-size:var(--app-t-base);background:var(--color-raised);color:var(--color-primary);font-family:var(--font-body);transition:border-color 0.18s var(--ease-out)}
#agentTextInput::placeholder{color:var(--color-placeholder)}
#agentTextInput:focus{outline:2px solid var(--color-accent);outline-offset:1px;border-color:var(--color-accent)}
#agentSendBtn{width:100%}
#agentMapClickInstr{display:none;font-size:var(--app-t-base);color:var(--color-mid);background:var(--tint-accent);border:1px solid var(--tint-accent-rule);border-radius:var(--radius);padding:var(--app-space-4) var(--app-space-5);text-align:center;line-height:1.5}
#agentIterBadge{font-family:var(--font-mono);font-size:var(--app-t-xs);color:var(--color-faint);background:var(--color-raised);border:1px solid var(--rule);padding:2px 7px;border-radius:var(--radius);white-space:nowrap;font-variant-numeric:slashed-zero tabular-nums}
.agent-bubble{padding:var(--app-space-4) var(--app-space-5);border-radius:var(--radius);font-size:var(--app-t-base);line-height:1.55;max-width:100%;word-break:break-word;overflow-wrap:break-word;white-space:pre-wrap}
.agent-bubble-bot{background:var(--color-raised);border:1px solid var(--rule);color:var(--color-primary)}
.agent-bubble-user{background:var(--tint-accent);border:1px solid var(--tint-accent-rule);color:var(--color-primary);text-align:right;align-self:flex-end}
.agent-btn{height:auto;min-height:var(--ctrl-sm);padding:var(--app-space-2) var(--app-space-5);white-space:normal;max-width:100%;word-break:break-word;font-size:var(--app-t-base);line-height:1.4}
.agent-zone-card{background:var(--color-raised);border:1px solid var(--rule);border-radius:var(--radius);padding:var(--app-space-5);cursor:pointer;transition:border-color 0.18s var(--ease-out);font-size:var(--app-t-base)}
.agent-zone-card:hover{border-color:var(--color-accent)}
.agent-zone-card h4{margin:0 0 var(--app-space-2);font-family:var(--font-display);font-size:var(--app-t-md);color:var(--color-primary);font-weight:500;line-height:1.14;letter-spacing:-0.015em}
.agent-zone-card p{margin:0 0 var(--app-space-3);color:var(--color-mid);line-height:1.5}
.agent-zone-pros{color:var(--color-success);font-size:var(--app-t-sm);line-height:1.5}
.agent-zone-cons{color:var(--color-faint);font-size:var(--app-t-sm);margin-top:var(--app-space-1);line-height:1.5}
.agent-zone-select-btn{width:100%;margin-top:var(--app-space-4);font-size:var(--app-t-base);font-weight:600}
#btnAgentMode{width:100%;margin-bottom:var(--app-space-4);display:inline-flex;align-items:center;justify-content:center;position:relative;overflow:hidden;isolation:isolate;height:var(--ctrl-md);background:transparent;border:1px solid var(--color-accent);border-radius:var(--radius);color:var(--color-accent);font-family:var(--font-body);font-size:var(--app-t-base);font-weight:600;cursor:pointer;letter-spacing:0.08em;text-transform:uppercase;transition:color 0.2s var(--ease-out),border-color 0.2s var(--ease-out)}
#btnAgentMode::after{content:'';position:absolute;inset:0;z-index:-1;background:var(--color-accent);transform:scaleY(0);transform-origin:bottom;transition:transform 0.2s var(--ease-out)}
#btnAgentMode:hover{color:var(--brand-light)}
#btnAgentMode:hover::after{transform:scaleY(1)}
#btnAgentModeBack{width:100%;height:var(--ctrl-sm);background:transparent;border:1px solid var(--rule-strong);color:var(--color-faint);border-radius:var(--radius);font-family:var(--font-body);font-size:var(--app-t-base);cursor:pointer;letter-spacing:0.04em;margin-top:var(--app-space-3);transition:color 0.18s var(--ease-out),border-color 0.18s var(--ease-out)}
#btnAgentModeBack:hover{border-color:var(--color-mid);color:var(--color-mid)}
.agent-thinking{display:flex;gap:var(--app-space-2);align-items:center;padding:var(--app-space-3) var(--app-space-5)}
.agent-thinking span{width:5px;height:5px;background:var(--color-accent);border-radius:50%;animation:agentDot 1.2s infinite}
.agent-thinking span:nth-child(2){animation-delay:0.2s}
.agent-thinking span:nth-child(3){animation-delay:0.4s}
@keyframes agentDot{0%,80%,100%{transform:scale(0.6);opacity:0.4}40%{transform:scale(1);opacity:1}}

/* ── RESPONSIVE ──────────────────────────────────────────────── */
@media(max-width:1300px){.grid-view{grid-template-columns:repeat(3,1fr)}}
@media(max-width:900px){.grid-view{grid-template-columns:repeat(2,1fr)}}
@media(max-width:600px){.grid-view{grid-template-columns:1fr}}
/* Objetivos táctiles: se suben las alturas, no los huecos */
@media(pointer:coarse){
  .app-btn,.btn-sm,.sort-btn,.type-btn,.dedup-toggle,.card-btn,.card-save-btn,.card-iso-btn,
  .sel-btn,.sel-iso-btn,.sel-modal-btn,.agent-btn,.lang-btn,.gis-btn-link,.agent-zone-select-btn,
  .filter-select,.filter-input,#radiusSelect{height:40px}
  .app-btn--primary,.search-btn,#agentSendBtn{height:44px}
  header .btn-sm,header .lang-btn,#ux-nav-upgrade,.header-right .ux-nav-link{height:40px}
}
@media(max-width:768px){
  /* ── M1 · CABECERA ────────────────────────────────────────────
     Una sola fila que NUNCA se desplaza en horizontal: marca + cambio de
     vista + menú. Todo lo demás se va al panel deslizante. */
  header{overflow:visible;justify-content:space-between;flex-wrap:nowrap;gap:var(--app-space-3);padding:var(--app-space-3) var(--app-space-5)}
  .brand-wordmark,.brand-version{display:none}
  .header-brand{gap:var(--app-space-3);min-width:0}

  /* Os três controlos da barra têm de medir o mesmo: 40px de altura e os dois
     de vista a mesma largura. Sem o min-width, "Grid" e "Mapa" ficavam com
     larguras diferentes por causa do rótulo; sem a altura explícita, os
     .btn-sm ficavam a 32px contra os 40px do botão de menu. */
  /* `header .view-toggle .btn-sm` (0,2,1) na secção de escritório vencia um
     `header .btn-sm` (0,1,1) daqui: os botões de vista ficavam a 32px e o de
     menu a 40px. Repete-se o selector completo para igualar especificidade. */
  header .btn-sm,header .view-toggle .btn-sm,.nav-menu-btn{height:40px;min-height:40px}
  .view-toggle{margin:0 0 0 auto;gap:0;flex-shrink:0}
  .view-toggle .btn-sm{padding:0 var(--app-space-4);min-width:92px;justify-content:center}
  .view-toggle .btn-sm+.btn-sm{border-left:none}

  .nav-menu-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;
    width:40px;height:40px;padding:0;background:transparent;
    border:1px solid var(--rule-strong);border-radius:var(--radius);
    color:var(--color-mid);cursor:pointer;
    transition:color 0.18s var(--ease-out),border-color 0.18s var(--ease-out)}
  .nav-menu-btn:hover{border-color:var(--color-accent);color:var(--color-accent)}

  /* ── M2 · PANEL DESLIZANTE ───────────────────────────────────
     El mismo nodo que en escritorio era display:contents. */
  .nav-drawer{display:flex;flex-direction:column;gap:var(--app-space-7);
    position:fixed;top:0;right:0;bottom:0;width:min(84vw,320px);
    background:var(--color-raised);border-left:1px solid var(--rule-strong);
    padding:var(--app-space-6);padding-bottom:max(14px,env(safe-area-inset-bottom,14px));
    z-index:2200;overflow-y:auto;overscroll-behavior:contain;
    transform:translateX(101%);transition:transform 0.25s var(--ease-out)}
  .nav-drawer.open{transform:none}
  .nav-drawer-head{display:flex;align-items:center;justify-content:space-between;
    padding-bottom:var(--app-space-4);border-bottom:1px solid var(--rule)}
  .nav-drawer-title{font-family:var(--font-body);font-size:var(--app-t-sm);font-weight:500;
    letter-spacing:0.12em;text-transform:uppercase;color:var(--color-mid)}
  .nav-drawer-close{background:none;border:none;color:var(--color-faint);cursor:pointer;
    font-size:var(--app-t-xl);line-height:1;padding:0 var(--app-space-2)}
  .nav-drawer-close:hover{color:var(--color-accent)}
  /* Dentro del panel todo es una pila a ancho completo. Una sola altura
     (44px), un solo hueco (8px) y un filete entre grupos: sin esto los
     controles heredan anchos y alturas distintos de la barra superior. */
  .nav-drawer .header-actions,.nav-drawer .header-right{
    display:flex;flex-direction:column;align-items:stretch;gap:var(--app-space-4);margin:0;flex:none}
  .nav-drawer .header-right{padding-top:var(--app-space-7);border-top:1px solid var(--rule)}
  .nav-drawer .btn-sm,
  .nav-drawer .ux-nav-link,
  .nav-drawer #ux-nav-upgrade,
  .nav-drawer .ux-nav-back,
  .nav-drawer .lang-btn{
    display:inline-flex;align-items:center;justify-content:flex-start;
    width:100%;height:44px;min-height:44px;padding:0 var(--app-space-5);
    margin:0;flex:none;gap:var(--app-space-4);
    font-size:var(--app-t-md);letter-spacing:0.04em;text-transform:none;
    border:1px solid var(--rule-strong);border-radius:var(--radius)}
  .nav-drawer .ux-nav-back{font-size:var(--app-t-md);color:var(--color-mid)}
  .nav-drawer #ux-nav-upgrade{justify-content:center;letter-spacing:0.1em;text-transform:uppercase}
  /* El selector de idioma sí es una fila: tres segmentos iguales */
  .nav-drawer .lang-selector{margin:0;display:flex;gap:0}
  .nav-drawer .lang-btn{flex:1 1 0;width:auto;justify-content:center;padding:0}
  .nav-drawer .lang-selector .lang-btn+.lang-btn{border-left:none}

  .nav-scrim{display:block;position:fixed;inset:0;z-index:2150;
    background:rgba(62,58,55,0.38);border:none;opacity:0;
    transition:opacity 0.25s var(--ease-out)}
  .nav-scrim.open{opacity:1}
  .nav-scrim[hidden]{display:none}

  /* ── M3 · HOJA DE FILTROS A PANTALLA COMPLETA ────────────────
     255px de columna no es usable a lo ancho de un teléfono. */
  /* absolute dentro de .main, no fixed al viewport: así la hoja ocupa el área
     de contenido y queda POR DEBAJO de la cabecera en vez de intentar taparla
     (no podría: <header> crea contexto propio y siempre pintaría encima,
     escondiendo el título y el botón de cerrar de la hoja). */
  /* Desliza com `left`, NÃO com transform: um antecessor transformado faz o
     Chromium colocar mal o popup nativo dos <select>, que era o que os
     mandava para fora do ecrã. Sem transform, o popup ancora onde deve. */
  #sidebarPanel{position:absolute;top:0;bottom:0;left:0;right:auto;width:100%;z-index:2100;
    border-right:none;transform:none;
    transition:left 0.25s var(--ease-out)}
  /* Se anula el riel de escritorio: aquí la hoja está dentro o fuera */
  #sidebarPanel.collapsed{width:100%!important;left:-100%;transform:none}

  /* Controlos de formulário: alvo tátil sem inchar. 40px chega — 44px com
     16px de texto tornava a folha de filtros um muro de caixas enormes. */
  .filter-select,.filter-input{height:40px;font-size:var(--app-t-md);max-width:100%}
  .filter-label{font-size:var(--app-t-sm)}
  .range-sep{font-size:var(--app-t-md)}
  .type-btn{height:34px;font-size:var(--app-t-base)}
  .portal-row{padding:var(--app-space-2) var(--app-space-1);font-size:var(--app-t-base)}
  .portal-row input[type=checkbox]{width:16px;height:16px}
  .portal-rpp{height:30px;width:50px;font-size:var(--app-t-base)}
  .weight-row{min-height:30px}
  /* Nada de scroll horizontal dentro da folha */
  #sidebarPanel,.sidebar-scroll{overflow-x:hidden}
  .filter-group{min-width:0}
  .sidebar.collapsed>*{visibility:visible}
  .sidebar.collapsed .sidebar-scroll,.sidebar.collapsed .sidebar-footer{padding:var(--app-space-6)!important;overflow:visible!important}
  .sidebar.collapsed .sidebar-scroll{overflow-y:auto!important}
  .sheet-head{display:flex;align-items:center;justify-content:space-between;flex-shrink:0;
    padding:var(--app-space-5) var(--app-space-6);border-bottom:1px solid var(--rule);
    padding-top:max(12px,env(safe-area-inset-top,12px))}
  .sheet-title{font-family:var(--font-body);font-size:var(--app-t-sm);font-weight:500;
    letter-spacing:0.12em;text-transform:uppercase;color:var(--color-mid)}
  .sheet-close{background:none;border:none;color:var(--color-faint);cursor:pointer;
    font-size:var(--app-t-xl);line-height:1;padding:0 var(--app-space-2)}
  .sheet-close:hover{color:var(--color-accent)}
  .sidebar-scroll{-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
  .sidebar-footer{padding-bottom:max(14px,env(safe-area-inset-bottom,14px))}

  /* Disparador de filtros: pastilla rotulada abajo a la izquierda, no una
     lengüeta al canto. Queda oculta bajo la hoja cuando ésta se abre. */
  #sidebarToggleBtn{position:fixed;left:var(--app-space-5);right:auto;
    top:auto;bottom:calc(16px + env(safe-area-inset-bottom,0));transform:none;
    width:auto;height:40px;padding:0 var(--app-space-5);gap:var(--app-space-3);
    margin:0;z-index:1101;
    background:var(--color-accent);color:var(--brand-light);border:1px solid var(--color-accent)}
  #sidebarPanel+#sidebarToggleBtn,#sidebarPanel.collapsed+#sidebarToggleBtn{left:var(--app-space-5)}
  #sidebarToggleBtn:hover{background:var(--color-accent-dark);color:var(--brand-light)}
  #sidebarToggleBtn .app-icon{transform:none!important}
  #sidebarToggleBtn.is-collapsed .app-icon{transform:none!important}
  .toggle-label{display:inline;font-family:var(--font-body);font-size:var(--app-t-md);font-weight:500;letter-spacing:0.04em}

  /* ── M4 · MAPA ───────────────────────────────────────────────── */
  /* Sem lingueta ao canto em móvel: o painel abre-se pelos botões da barra
     GIS e fecha-se pelo × do seu cabeçalho. */
  #gisPanelToggleBtn{display:none!important}
  #zoomSliderWrap{display:none!important}

  /* Painel GIS como folha INFERIOR: ocupa pouco mais de metade do ecrã e
     deixa o mapa à vista por cima, que é o que interessa ao escolher uma
     variável — vê-se a coropleta a mudar. Antes estava display:none, o que
     tornava estas funções inalcançáveis no telemóvel. */
  #gisPanelRight.gis-panel-right{display:flex;flex-direction:column;
    position:absolute;left:0;right:0;bottom:0;top:auto;
    width:auto;height:min(58vh,420px);z-index:2050;
    background:var(--color-raised);
    border-left:none;border-top:1px solid var(--rule-strong);
    padding:var(--app-space-6);
    padding-bottom:max(14px,env(safe-area-inset-bottom,14px));
    overflow-y:auto;overscroll-behavior:contain;
    transform:translateY(0);transition:transform 0.25s var(--ease-out)}
  #gisPanelRight.gis-panel-right.collapsed{transform:translateY(101%)}
  /* O cabeçalho do painel fica fixo ao topo da folha para o × estar sempre à mão */
  #gisPanelRight>div:first-child{position:sticky;top:calc(var(--app-space-6) * -1);
    background:var(--color-raised);z-index:1;
    padding-top:var(--app-space-6);margin-top:calc(var(--app-space-6) * -1)}
  #gisPanelRight>div:first-child button{width:40px;height:40px;display:inline-flex;
    align-items:center;justify-content:center;font-size:var(--app-t-xl)}
  /* ── Painéis de info do mapa ─────────────────────────────────
     Empilham-se em coluna a toda a largura: antes a legenda e o
     #thematicInfoBox estavam ambos ancorados ao canto superior esquerdo e
     sobrepunham-se, e o max-width cortava a escala de cores à direita. */
  .map-info-stack{display:flex;flex-direction:column;gap:var(--app-space-2);
    position:absolute;top:var(--app-space-4);left:var(--app-space-4);right:var(--app-space-4);
    z-index:1001;max-height:42vh;overflow-y:auto;overscroll-behavior:contain;
    pointer-events:none}
  .map-info-stack>*{pointer-events:auto}
  /* relative, não static: o × da legenda é position:absolute dentro dela e
     com static passaria a ancorar-se ao .map-view. */
  .gis-legend,#thematicInfoBox{position:relative!important;
    left:auto!important;right:auto!important;top:auto!important;bottom:auto!important;
    width:auto!important;min-width:0!important;max-width:none!important;flex:none}
  /* As escalas de cor são linhas flex inline: deixá-las quebrar em vez de
     transbordarem para fora do ecrã. */
  .gis-legend div,#thematicInfoBox div{flex-wrap:wrap}
  .gis-legend{padding:var(--app-space-4) var(--app-space-8) var(--app-space-4) var(--app-space-5)}

  /* ── Barra do clima ──────────────────────────────────────────
     Passa a assentar POR CIMA da barra GIS em vez de a empurrar para cima,
     e encolhe: os inline styles do markup obrigam a !important. */
  #mapGisBar.bar-raised{bottom:0!important}
  /* Uma linha só, altura fixa: assim sabe-se exactamente onde acaba e o
     botão Filtros pode ser posto por cima sem adivinhar. */
  /* Barra flutuante encostada aos cantos com folga, não de bordo a bordo:
     ganha ar dos dois lados e lê-se como um painel sobre o mapa. */
  #climaBar{bottom:88px!important;top:auto;height:44px!important;
    left:var(--app-space-4)!important;right:var(--app-space-4)!important;
    padding:0 var(--app-space-3)!important;
    border:1px solid var(--rule-strong)!important;
    flex-wrap:nowrap;gap:var(--app-space-2)!important;z-index:1000}
  /* Os rótulos são longos ("Precipitação"): reticências em vez de esticar
     a barra para lá do ecrã. */
  #climaBar .btn-sm{height:30px;font-size:var(--app-t-sm);padding:0 var(--app-space-3);
    flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;display:block;line-height:28px}
  #climaBar>div:first-child{display:flex;gap:var(--app-space-2);flex:0 1 auto;min-width:0}
  #climaBar #climaSlider{min-width:36px;flex:1 1 36px}
  #climaBar #climaSliderLabel{font-size:var(--app-t-sm);flex-shrink:0;min-width:26px}
  /* A atribuição do IPMA é secundária: não vale espaço no telemóvel */
  #climaBar>span:last-child{display:none}
  /* Com o clima ligado a barra ocupa 88→132px: o botão sobe para não tapar
     os controlos de temperatura/precipitação. O gancho .bar-raised já é
     posto pelo próprio toggle do clima. */
  body.view-map:has(#mapGisBar.bar-raised) #sidebarToggleBtn{bottom:calc(142px + env(safe-area-inset-bottom,0))}

  /* Aviso de plano no painel GIS: era um bloco enorme numa folha de 58vh */
  #gis-free-hint{padding:var(--app-space-4) var(--app-space-5)!important;
    margin-bottom:var(--app-space-4)!important;text-align:left!important}
  #gis-free-hint>div:first-child{font-size:var(--app-t-base)!important;margin-bottom:2px!important}
  #gis-free-hint>div:nth-child(2){font-size:var(--app-t-sm)!important;line-height:1.4!important;
    margin-bottom:var(--app-space-3)!important;
    display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
  #gis-free-hint a{font-size:var(--app-t-sm)!important;padding:var(--app-space-2) var(--app-space-4)!important}
  /* Alvos táteis dentro do painel */
  .gis-var-btn{padding:var(--app-space-3) var(--app-space-4);min-height:38px}
  .gis-radio-group label{padding:var(--app-space-2) 0;min-height:34px;display:flex;align-items:center}
  .gis-var-group-title{min-height:34px;padding:var(--app-space-2) 0}

  /* Barra GIS: se envuelve en varias filas en vez de desplazarse en
     horizontal. Tope de altura para no comerse el mapa. */
  #mapGisBar{bottom:0!important;display:flex!important;flex-wrap:wrap!important;
    overflow-x:visible!important;max-height:88px;overflow-y:auto;
    row-gap:var(--app-space-2);
    padding-bottom:max(6px,env(safe-area-inset-bottom,6px))}
  /* Na vista de mapa o botão sobe acima da barra GIS; na grelha não há barra. */
  body.view-map #sidebarToggleBtn{bottom:calc(100px + env(safe-area-inset-bottom,0))}

  /* ── M5 · CONTENIDO ──────────────────────────────────────────── */
  .content{min-width:0;width:100%}
  .results-header{flex-wrap:wrap;gap:var(--app-space-2);padding:var(--app-space-3) var(--app-space-5)}
  .result-modal{left:8px!important;right:8px!important;max-width:none!important;top:auto;bottom:0;max-height:70vh}
  #debugPanel{width:calc(100vw - 28px)!important;right:14px!important;left:14px!important}
  .grid-view{padding:var(--app-space-4)}
  /* Rede de segurança para o Crisp: em móvel não chega a carregar-se, mas se
     a janela for estreitada depois de carregar, o widget já cá está. */
  .crisp-client,#crisp-chatbox{display:none!important}
  #selectionBar{left:8px;right:8px;top:auto;bottom:calc(100px + env(safe-area-inset-bottom,0))}
}

/* Só em ecrãs táteis: abaixo de 16px o Safari do iOS faz zoom ao focar um
   campo e desalinha a página. Num browser de secretária estreitado isso não
   acontece, e 16px aí só fazia os controlos parecerem enormes. */
@media(max-width:768px) and (pointer:coarse){
  .filter-select,.filter-input,.filter-input[type=number]{font-size:16px}
}

/* ── MOVIMIENTO REDUCIDO ─────────────────────────────────────── */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{transition:none!important;animation:none!important}
}
