/* ============================================================
   Tribufam — Capa visual de la app CON SESIÓN INICIADA
   ------------------------------------------------------------
   Se carga LA ÚLTIMA en app.html (después de theme.css), así
   que solo afecta a lo que se ve dentro de la sesión: la
   portada, el acceso y el panel de admin quedan intactos.

   Qué arregla: la app era correcta pero PLANA. El fondo de la
   página y el de los paneles eran el mismo color, todas las
   tarjetas eran rectángulos blancos con un borde gris de 1px y
   cada pantalla empezaba con un título suelto. Aquí se añade
   profundidad (fondo ambiental, elevación real), un ancla de
   color en cada vista y jerarquía tipográfica, casi todo sin
   tocar el HTML que pinta app.js.
   ============================================================ */

/* ── 1. FUNDAMENTOS ─────────────────────────────────────────── */
:root {
  /* El gris de los paneles pasa a ser un verde muy lavado: dentro de una tarjeta
     blanca ahora SE VE que es un panel. Antes valía #faf9f6, el mismo color que
     el fondo de la página, y todo se fundía. Lo heredan decenas de bloques que
     ya pintaban con var(--c) desde app.js, así que no hay que tocarlos. */
  --c:#eef6f3;

  /* Superficies y contornos */
  --bdr:#e4efeb;
  --bdr-soft:rgba(16,32,28,.07);

  /* Elevación en capas (sombra de contacto + sombra de ambiente) */
  --sh:0 1px 2px rgba(16,32,28,.04), 0 6px 16px -10px rgba(16,32,28,.18);
  --sh2:0 2px 6px rgba(16,32,28,.05), 0 22px 44px -20px rgba(16,32,28,.28);
  --sh-lift:0 4px 10px rgba(16,32,28,.05), 0 26px 48px -22px rgba(13,110,95,.42);
  --sh-brand:0 8px 20px -8px rgba(15,160,138,.55);

  /* Degradados de marca */
  --grad-brand:linear-gradient(135deg,#0d8d79 0%,#12a891 52%,#3ec9ae 100%);
  --grad-btn:linear-gradient(135deg,#12a891 0%,#0c8474 100%);
  --grad-warm:linear-gradient(135deg,#ff8a68 0%,#ff6f4d 100%);

  --r:20px; --rs:13px;
}

/* accent-color: las casillas del perfil y de los modales salían del azul del
   sistema, que chocaba con el verde de todo lo demás. */
body { background:#f4f9f7; accent-color:var(--teal); }
/* El fondo ambiental va en una capa fija detrás de todo: así no se estira con la
   página larga ni depende de background-attachment (que da tirones en móvil). */
body::before {
  content:''; position:fixed; inset:0; z-index:-1; pointer-events:none;
  background:
    radial-gradient(1200px 640px at 8% -10%, rgba(15,160,138,.16), transparent 62%),
    radial-gradient(900px 520px at 96% 2%,  rgba(255,122,89,.11), transparent 64%),
    radial-gradient(700px 700px at 50% 118%, rgba(15,160,138,.09), transparent 66%),
    linear-gradient(180deg,#f8fcfa 0%,#f1f7f5 100%);
}

.page { padding:26px 24px 64px; }
.main-view.active { gap:20px; }

/* ── 2. CABECERA Y NAVEGACIÓN (escritorio) ──────────────────── */
.site-header {
  background:rgba(255,255,255,.78);
  backdrop-filter:saturate(1.6) blur(14px);
  -webkit-backdrop-filter:saturate(1.6) blur(14px);
  border-bottom:1px solid transparent;
  box-shadow:0 1px 0 rgba(16,32,28,.05);
  transition:box-shadow .25s ease, background .25s ease;
}
/* Al bajar, la cabecera se apoya en una sombra (la clase la pone app.html) */
.site-header.desplazada {
  background:rgba(255,255,255,.93);
  box-shadow:0 1px 0 rgba(16,32,28,.06), 0 10px 28px -18px rgba(16,32,28,.55);
}
.header-inner { height:70px; gap:22px; }
.logo img { filter:drop-shadow(0 2px 6px rgba(13,125,109,.28)); }

.nav-items { gap:2px; align-items:center; }
.nav-item {
  padding:10px 15px; border-radius:12px; font-size:14px;
  transition:color .16s ease, background .16s ease;
}
.nav-item:hover { background:rgba(15,160,138,.08); }
.nav-item.active { background:var(--teal-pale); color:var(--teal2); }
/* La barrita de debajo sobraba: con la píldora ya se sabe dónde estás, y con las
   dos cosas a la vez la cabecera se veía cargada. */
.nav-item.active::after { display:none; }
.badge-count {
  top:2px; right:-2px; background:var(--grad-warm); box-shadow:0 3px 8px rgba(255,111,77,.45);
  border:2px solid #fff; padding:1px 5px; min-width:19px;
}

.nav-r { gap:12px; }
/* Punto de "conectado en tiempo real": ahora late, para que se lea como un estado
   y no como una mota de polvo en la pantalla. */
.dot { position:relative; background:#22c08a; box-shadow:0 0 0 3px rgba(34,192,138,.18); }
.dot::after {
  content:''; position:absolute; inset:-4px; border-radius:50%;
  border:2px solid rgba(34,192,138,.5); animation:tfLatido 2.4s ease-out infinite;
}
@keyframes tfLatido { 0%{transform:scale(.7);opacity:.9} 70%,100%{transform:scale(1.5);opacity:0} }

.user-menu-btn {
  background:rgba(255,255,255,.9); border:1px solid var(--bdr);
  border-radius:999px; padding:5px 15px 5px 5px; gap:10px;
  box-shadow:0 1px 2px rgba(16,32,28,.04);
  transition:border-color .16s, box-shadow .16s, transform .16s;
}
.user-menu-btn:hover { border-color:var(--teal3); box-shadow:0 6px 18px -10px rgba(13,110,95,.55); transform:translateY(-1px); }
.user-av { width:32px; height:32px; box-shadow:0 0 0 2px #fff, 0 0 0 3.5px rgba(15,160,138,.35); }

/* ── 3. MENÚ DE USUARIO ─────────────────────────────────────── */
.user-dropdown {
  /* +safe-area: la cabecera lleva ese hueco arriba (theme.css) y el menú cuelga de ella. */
  top:calc(78px + env(safe-area-inset-top)); border-radius:18px; border:1px solid var(--bdr-soft);
  box-shadow:var(--sh2); min-width:284px;
  /* overflow:hidden NO: el menú es position:fixed y cuelga de la cabecera, así
     que en una pantalla baja (móvil en apaisado) hay que poder desplazarlo. */
  max-height:calc(var(--alto-vista,100vh) - 100px); overflow-y:auto;
}
.dd-account { background:var(--grad-brand); border-bottom:none; padding:18px; color:#fff; }
.dd-account .profile-av-lg { box-shadow:0 0 0 3px rgba(255,255,255,.55); background:rgba(255,255,255,.22); }
.dd-account .profile-info .pname { color:#fff; font-size:15px; }
.dd-account .profile-info .prole { color:rgba(255,255,255,.85); }
.dd-account .stars-display { color:#ffd9a8; }
.dd-account .stars-display small { color:rgba(255,255,255,.82); }
.dd-item { padding:12px 18px; font-size:13.5px; }
.dd-item:hover { background:var(--teal-pale); }

/* Barra de la pantalla de verificación. renderVerificationGate() reemplaza el <body>
   entero y la marca con .topbar, una clase que SOLO estaba definida en admin.html:
   dentro de la app se veía el logo pegado a la esquina y el botón de cerrar sesión
   suelto en la línea de abajo, sin ningún estilo. */
.topbar {
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  flex-shrink:0; height:70px; padding:0 24px;
  background:rgba(255,255,255,.9); border-bottom:1px solid var(--bdr);
  box-shadow:0 1px 0 rgba(16,32,28,.05);
}
.topbar .logo img { height:34px; }

/* ── 4. CABECERA DE CADA VISTA (el ancla de color) ──────────── */
/* Antes cada pantalla abría con un título negro sobre fondo crema y nada más: es
   lo que más "sosa" hacía a la app. Ahora es un panel de marca con el título, la
   frase de contexto y la acción principal. */
.view-header {
  position:relative; overflow:hidden; isolation:isolate;
  align-items:center; padding:24px 28px; border-radius:24px;
  background:var(--grad-brand); color:#fff;
  box-shadow:0 18px 38px -22px rgba(10,90,78,.85);
}
.view-header::before {
  content:''; position:absolute; z-index:-1; inset:0;
  background:
    radial-gradient(420px 220px at 100% 0%, rgba(255,255,255,.28), transparent 70%),
    radial-gradient(280px 280px at 88% 130%, rgba(255,196,164,.35), transparent 70%);
}
.view-header::after {
  content:''; position:absolute; z-index:-1; right:-38px; top:-58px;
  width:190px; height:190px; border-radius:50%;
  border:26px solid rgba(255,255,255,.10);
}
/* Nunca se encoge: dentro de #view-chat, que tiene altura fija, flexbox le robaba
   alto al panel y como la cabecera lleva overflow:hidden se COMÍA su propio texto
   (en el móvil el subtítulo salía cortado a media línea). */
.main-view.active > .view-header { flex-shrink:0; }
.view-title { color:#fff; font-size:30px; font-weight:800; letter-spacing:-.6px; }
.view-sub { color:rgba(255,255,255,.88); font-size:14px; margin-top:6px; line-height:1.55; }
.view-header .pub-ad-btn {
  background:#fff; color:var(--teal2); border-radius:13px; padding:12px 22px;
  box-shadow:0 10px 22px -10px rgba(6,60,52,.9);
}
.view-header .pub-ad-btn:hover { background:#fff; color:#0a6f61; filter:none; transform:translateY(-1px); }

/* Encabezado de sección con una marca de color delante */
.section-head { display:flex; align-items:center; gap:10px; font-size:18px; font-weight:800; }
.section-head::before {
  content:''; width:4px; height:17px; border-radius:4px; flex:0 0 4px;
  background:var(--grad-btn);
}

/* ── 5. FILTROS ─────────────────────────────────────────────── */
.filters-card {
  background:rgba(255,255,255,.86);
  backdrop-filter:saturate(1.3) blur(8px); -webkit-backdrop-filter:saturate(1.3) blur(8px);
  border:1px solid var(--bdr-soft); border-radius:20px; padding:16px 18px;
  box-shadow:var(--sh); gap:16px;
  /* Alineados por ARRIBA: al alinearlos por abajo, el campo de tarifa —que lleva una
     nota debajo— subía su etiqueta y la fila salía escalonada. */
  align-items:flex-start;
}
.filters-card > .filter-check, .filters-card > .btn-chat { align-self:flex-end; }
/* Etiquetas: verde oscuro a plena opacidad. Rebajadas (que es como quedaban mejor)
   no llegaban al contraste mínimo de la WCAG para texto pequeño. */
.filter-field > label { color:#0a6f61; opacity:1; font-size:10.5px; }
.filter-field .form-input, .filter-field .form-select { padding:9px 12px; border-radius:11px; }
/* Los filtros de tipo pasan a ser un control segmentado */
.fbar { background:var(--c); border-radius:999px; padding:4px; gap:2px; }
.fbtn { background:transparent; border:none; border-radius:999px; padding:7px 16px; color:var(--txm); }
.fbtn:hover { color:var(--teal2); }
.fbtn.active { background:#fff; color:var(--teal2); box-shadow:0 2px 8px -2px rgba(16,32,28,.22); }
.filter-check { border-radius:10px; padding:7px 11px; background:var(--c); color:var(--txm); font-weight:600; }

/* Búsqueda básica + filtros plegados (Canguros, Clases y Mayores). La tarjeta abría
   con siete campos, tres casillas y un botón antes del primer resultado; ahora se ve
   la zona y un botón «Filtros» con cuántos hay puestos, y el resto se despliega. */
.filtros-lista { flex-direction:column; align-items:stretch; }
.filtros-basicos { display:flex; align-items:flex-end; gap:10px; flex-wrap:wrap; }
/* Base pequeña a propósito: en un móvil de 375px la zona y el botón caben en la
   misma línea (con 220px el botón se caía a una segunda fila). */
.filtros-basicos .filtro-zona { flex:1 1 150px; min-width:0; }
.filtros-basicos .filtro-zona .form-input { width:100% !important; }
.filtro-colegio-elegido { padding-bottom:4px; }
.filtros-btn { display:inline-flex; align-items:center; gap:7px; white-space:nowrap; padding:9px 14px; }
.filtros-btn[aria-expanded="true"] { background:var(--teal); color:#fff; border-color:var(--teal); }
.filtros-num {
  display:inline-flex; align-items:center; justify-content:center;
  min-width:19px; height:19px; padding:0 6px; border-radius:999px;
  background:var(--amber); color:#fff; font-size:11px; font-weight:800;
}
.filtros-num[hidden] { display:none; }
.filtros-avanzados { display:flex; flex-wrap:wrap; gap:14px; align-items:flex-start; padding-top:12px; border-top:1px dashed var(--bdr-soft); }
.filtros-avanzados[hidden] { display:none; }
.filtros-avanzados > .filter-check { align-self:flex-end; }
.filtros-pie { flex:1 1 100%; display:flex; justify-content:flex-end; }
/* «Publicar esta búsqueda como anuncio» va al final de los resultados: es donde
   está la familia cuando decide que nadie de la lista le encaja. */
.feed-pie { display:flex; align-items:center; justify-content:center; gap:10px; flex-wrap:wrap; padding:4px 0 0; font-size:13px; color:var(--txm); }

/* Mis anuncios: lo anterior (servicios terminados, anuncios caducados) va plegado y a
   una línea por anuncio; al tocarla se despliega la tarjeta de siempre. */
.ads-anteriores { margin-top:4px; }
.ads-anteriores > summary {
  list-style:none; cursor:pointer; display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  padding:12px 16px; background:var(--w); border:1px solid var(--bdr-soft); border-radius:16px;
  font-weight:800; font-size:14px; color:var(--txm);
}
.ads-anteriores > summary::-webkit-details-marker { display:none; }
.ads-anteriores > summary::before { content:'\25B8'; font-size:12px; color:var(--txl); transition:transform .15s ease; }
.ads-anteriores[open] > summary::before { transform:rotate(90deg); }
.ads-anteriores[open] > summary { border-radius:16px 16px 0 0; }
.ads-anteriores-num { background:var(--c); color:var(--txm); border-radius:999px; padding:1px 9px; font-size:12px; }
.ads-anteriores-sub { flex-basis:100%; font-weight:500; font-size:12.5px; color:var(--txl); }
.ad-prev { background:var(--w); border:1px solid var(--bdr-soft); border-top:none; }
.ad-prev:last-child { border-radius:0 0 16px 16px; }
.ad-prev-row {
  width:100%; display:flex; align-items:center; gap:10px; padding:12px 16px;
  background:none; border:none; cursor:pointer; text-align:left; font-family:inherit; color:var(--txt);
}
.ad-prev-row:hover { background:var(--c); }
.ad-prev-main { flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
.ad-prev-title { font-weight:700; font-size:14px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.ad-prev-meta { font-size:12px; color:var(--txm); }
.ad-prev-caret { color:var(--txl); font-size:12px; transition:transform .15s ease; }
.ad-prev.abierto .ad-prev-caret { transform:rotate(180deg); }
.ad-prev-body { display:none; padding:0 10px 12px; }
.ad-prev.abierto .ad-prev-body { display:block; }

/* ── 6. TARJETAS ────────────────────────────────────────────── */
.ad-card, .rating-card, .filters-card, .profile-card, .chat-panel { border-color:var(--bdr-soft); }
.ad-card {
  border-radius:20px; padding:22px 24px 22px 26px; overflow:hidden;
  box-shadow:var(--sh); transition:transform .2s cubic-bezier(.22,.7,.3,1), box-shadow .22s ease;
}
/* El filo de color pasa de ser un borde plano a un degradado: distingue urgente de
   normal de un vistazo sin gritar. */
.ad-card.normal, .ad-card.urgent { border-left:1px solid var(--bdr-soft); }
.ad-card::before {
  content:''; position:absolute; left:0; top:0; bottom:0; width:5px;
  background:linear-gradient(180deg,#3ec9ae,#0c8474);
}
.ad-card.urgent::before { background:linear-gradient(180deg,#ffab8d,#e14b3b); }
.ad-card.urgent { background:linear-gradient(180deg,#fffaf8 0%,#fff 42%); }
.ad-card:hover { transform:translateY(-3px); box-shadow:var(--sh-lift); }

.ad-top { margin-bottom:12px; }
/* Título en tinta, no en verde: con todo verde no había jerarquía y el ojo no
   sabía dónde posarse. El verde queda para lo que se puede pulsar. */
.ad-title { color:var(--txt); font-size:19.5px; font-weight:800; letter-spacing:-.35px; margin-bottom:7px; }
.ad-desc { font-size:14px; color:var(--txm); }
.ad-meta { gap:8px; margin-top:12px; margin-bottom:14px; }
.ad-meta span {
  background:var(--c); color:var(--txm); border-radius:9px; padding:5px 10px;
  font-size:11.5px; font-weight:600;
}
.ad-time { font-size:11.5px; color:var(--txm); background:var(--c); border-radius:8px; padding:4px 9px; }
.ad-footer { border-top:1px solid var(--bdr); padding-top:14px; }
.author-info .aname { font-size:13px; color:var(--txt); font-weight:700; }
.postulantes-bar { border-top:1px solid var(--bdr); margin-top:14px; }

/* Las listas (antes con display:flex en un style= suelto de app.html) */
.feed { display:flex; flex-direction:column; gap:14px; }
/* En pantalla ancha los anuncios van a DOS columnas: una sola columna de 1.130 px
   para una tarjeta con tres líneas de texto era justo lo que hacía que la app se
   viera vacía en el ordenador. Los avisos y los estados vacíos ocupan el ancho.
   Lo que hay que dejar fuera es el MODO COMPACTO —la WebView de la app maqueta a
   1440-1600px y sin el :not() un teléfono acababa con el feed a dos columnas (ver
   pantalla.js)—, y eso lo hace el :not() por sí solo. NO se exige (pointer:fine):
   se probó y se llevaba por delante a las tabletas de verdad y a los 2-en-1 en
   modo tableta, que a 1280px sí deben ver dos columnas (medido: el feed se caía a
   una sola columna en una táctil de 1280x800). */
@media (min-width:1180px) {
  :where(html:not(.pantalla-compacta)) .feed-anuncios { display:grid; grid-template-columns:1fr 1fr; align-items:start; gap:16px; }
  :where(html:not(.pantalla-compacta)) .feed-anuncios > *:not(.ad-card) { grid-column:1 / -1; }
  /* El esqueleto de carga imita la rejilla final: si no, al llegar la lista el
     bloque saltaba de una columna a dos. */
  :where(html:not(.pantalla-compacta)) .feed-anuncios > .sk-list { display:grid; grid-template-columns:1fr 1fr; gap:16px; }
}

/* Tarjeta de proveedor (canguros / profesores). Las clases las pone renderProviders. */
.prov-card { padding:20px 22px 20px 24px; }
.prov-row { display:flex; align-items:flex-start; gap:16px; }
.prov-av { flex:0 0 auto; }
.prov-av > div { box-shadow:0 0 0 3px #fff, 0 0 0 4.5px rgba(15,160,138,.28); }
.prov-main { flex:1; min-width:0; }
.prov-name {
  font-family:var(--font-display); font-weight:800; font-size:17.5px; color:var(--txt);
  letter-spacing:-.3px; line-height:1.4;
}
.prov-sub { font-size:12.5px; color:var(--txm); margin-top:3px; }
.prov-bio { font-size:13px; color:var(--txm); margin-top:8px; line-height:1.55; }
.prov-actions { display:flex; flex-direction:column; gap:8px; align-items:stretch; flex:0 0 auto; }
.prov-actions .pub-ad-btn, .prov-actions .btn-chat { width:100%; }
.prov-fav.on { background:var(--amber-pale); color:var(--amber); border-color:rgba(255,122,89,.4); font-weight:700; }

/* ── 7. BADGES Y CHIPS ──────────────────────────────────────── */
.badge {
  padding:4px 10px; font-size:10.5px; font-weight:700; border-radius:8px;
  border:1px solid transparent; letter-spacing:.15px;
}
.b-urg  { background:var(--red-pale);   color:#c33a2b;     border-color:rgba(225,75,59,.22); }
.b-norm { background:var(--teal-pale);  color:var(--teal2); border-color:rgba(15,160,138,.2); }
.b-new  { background:var(--green-pale); color:var(--teal2); border-color:rgba(15,160,138,.2); }
.b-fee  { background:var(--amber-pale); color:#c2542f;     border-color:rgba(255,122,89,.25); }
.b-cerr { background:#eef1f0;           color:var(--txm);   border-color:rgba(16,32,28,.08); }
.b-cat  { background:#e9eefb;           color:#2b5fb0;     border-color:rgba(43,95,176,.18); }
.b-acc  { background:#e3f6f2;           color:#0a7565;     border-color:rgba(10,117,101,.22); }
.b-tarifa { background:#fdf4e3;         color:#9a7326;     border-color:rgba(182,134,47,.25); }
/* La urgencia lleva un punto que late: es la única etiqueta que pide reaccionar ya. */
.b-urg::before {
  content:''; width:6px; height:6px; border-radius:50%; background:#e14b3b;
  animation:tfPunto 1.6s ease-in-out infinite;
}
@keyframes tfPunto { 0%,100%{opacity:.35;transform:scale(.75)} 50%{opacity:1;transform:scale(1)} }

.chip { border-radius:9px; padding:5px 11px; font-size:11.5px; border:1px solid rgba(15,160,138,.18); }
.chip.amber { border-color:rgba(255,122,89,.24); }
.post-chip { border-radius:999px; padding:5px 12px 5px 5px; border:1px solid rgba(15,160,138,.18); transition:.16s; }
.post-chip:hover { background:var(--teal3); color:#0a4a40; }

/* ── 8. BOTONES ─────────────────────────────────────────────── */
.pub-ad-btn, .btn-post, .btn-primary {
  background:var(--grad-btn); border-radius:13px; box-shadow:var(--sh-brand);
  transition:transform .16s ease, box-shadow .18s ease, filter .16s ease;
}
.pub-ad-btn:hover, .btn-post:hover, .btn-primary:hover {
  background:var(--grad-btn); filter:brightness(1.06);
  transform:translateY(-1px); box-shadow:0 12px 26px -10px rgba(15,160,138,.7);
}
.btn-post.urg { background:var(--grad-warm); box-shadow:0 8px 20px -8px rgba(225,75,59,.6); }
.btn-post.urg:hover { background:var(--grad-warm); }
.btn-post:disabled, .pub-ad-btn:disabled { box-shadow:none; filter:grayscale(.35); }
.btn-chat, .new-chat-btn {
  background:#fff; border:1.5px solid var(--bdr); color:var(--teal2); border-radius:12px;
  padding:9px 15px; font-weight:600;
  transition:background .16s, border-color .16s, transform .16s, box-shadow .16s;
}
.btn-chat:hover, .new-chat-btn:hover {
  background:var(--teal-pale); border-color:var(--teal3);
  transform:translateY(-1px); box-shadow:0 8px 18px -12px rgba(13,110,95,.7);
}
.btn-secondary { border-radius:12px; background:var(--teal-pale); }
.accept-chip { background:var(--grad-btn); box-shadow:0 5px 14px -7px rgba(15,160,138,.8); padding:6px 14px; }
.reject-chip { padding:6px 14px; border:1px solid rgba(225,75,59,.22); }
.btn-loc { border-radius:11px; }

/* ── 9. ESTADOS VACÍOS Y ESQUELETOS DE CARGA ────────────────── */
.empty-feed {
  background:rgba(255,255,255,.75); border:1px dashed var(--teal3); border-radius:22px;
  padding:52px 26px; color:var(--txm); line-height:1.6;
}
.empty-feed::before {
  content:''; display:block; width:56px; height:56px; margin:0 auto 16px; border-radius:18px;
  background:var(--teal-pale) center/26px 26px no-repeat;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230c8474' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.6-3.6'/%3E%3C/svg%3E");
  box-shadow:inset 0 0 0 1px rgba(15,160,138,.16);
}

/* Esqueletos: mientras llega la lista se ve la FORMA de lo que va a venir, no un
   texto de "cargando" sobre un vacío. */
.sk-list { display:flex; flex-direction:column; gap:12px; }
.sk-card {
  background:#fff; border:1px solid var(--bdr-soft); border-radius:20px;
  padding:22px 24px; box-shadow:var(--sh);
}
.sk-line { height:12px; border-radius:7px; margin-bottom:11px; background:var(--c); position:relative; overflow:hidden; }
.sk-line:last-child { margin-bottom:0; }
.sk-line.t { height:19px; width:46%; }
.sk-line.s { width:88%; }
.sk-line.xs { width:34%; }
.sk-line::after {
  content:''; position:absolute; inset:0; transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.92),transparent);
  animation:tfBrillo 1.5s infinite;
}
@keyframes tfBrillo { 100%{transform:translateX(100%)} }
.sr-only { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }
@media (prefers-reduced-motion:reduce) {
  .sk-line::after, .dot::after, .b-urg::before { animation:none; }
}

/* ── 10. MENSAJES ───────────────────────────────────────────── */
/* La altura del panel estaba clavada a mano (100vh − 210px), un número calculado
   para la cabecera de vista de antes. Al crecer esa cabecera, el campo de escribir
   se salía por abajo — en el móvil quedaba tapado por la barra de navegación. Ahora
   la altura la fija la VISTA y el panel se queda con lo que sobre: así se recoloca
   solo pase lo que pase encima de él. */
#view-chat.active { height:calc(100vh - 70px - 26px - 64px); min-height:520px; }
#view-chat .chat-panel { height:auto; flex:1 1 auto; min-height:0; }
/* Esa altura no descuenta los avisos de <main>: la tarjeta del cambio legal, que es
   larga, empujaría la caja de escribir por debajo de la barra. En el chat se aparta
   y vuelve al salir; se descarta con un toque desde cualquier otra pestaña. */
.page:has(#view-chat.active) #avisoLegal { display:none; }
.chat-panel { border-radius:22px; box-shadow:var(--sh2); }
.chat-side { background:rgba(255,255,255,.7); }
.chat-side-head { padding:16px 18px; }
.chat-item { border-bottom:1px solid var(--bdr); position:relative; padding:13px 16px; }
.chat-item::before {
  content:''; position:absolute; left:0; top:8px; bottom:8px; width:3px; border-radius:0 4px 4px 0;
  background:var(--teal); opacity:0; transition:opacity .16s;
}
.chat-item.active::before { opacity:1; }
.chat-item.active { background:var(--teal-pale); }
.chat-name { font-size:13.5px; font-weight:700; }
.chat-unread { background:var(--grad-warm); box-shadow:0 3px 8px -3px rgba(255,111,77,.7); padding:3px 7px; }
.msgs-wrap {
  background:
    radial-gradient(circle at 22% 18%, rgba(15,160,138,.055) 0 1.5px, transparent 1.6px) 0 0/26px 26px,
    linear-gradient(180deg,#f3faf7,#eef6f3);
  padding:22px;
}
.msg-bubble { border-radius:18px; padding:11px 15px; box-shadow:0 1px 2px rgba(16,32,28,.05); }
.msg.mine .msg-bubble { background:var(--grad-btn); border-bottom-right-radius:6px; box-shadow:0 6px 16px -10px rgba(15,160,138,.9); }
.msg.theirs .msg-bubble { background:#fff; border-bottom-left-radius:6px; }
.msg.system .msg-bubble { background:rgba(255,255,255,.85); border:1px dashed var(--teal3); color:var(--teal2); border-radius:12px; }
.chat-input-wrap { padding:14px 18px; }
.chat-input { background:var(--c); border-color:transparent; border-radius:999px; padding:12px 18px; }
.chat-input:focus { background:#fff; border-color:var(--teal3); }
.send-btn { background:var(--grad-btn); box-shadow:var(--sh-brand); width:44px; height:44px; }
.send-btn:hover { background:var(--grad-btn); filter:brightness(1.07); transform:translateY(-1px); }
/* Sin conversación abierta, el panel derecho comparte el mismo lienzo que los
   mensajes: si no, se veía una banda de color y debajo un rectángulo blanco. */
.no-chat-open { flex-direction:column; background:linear-gradient(180deg,#f3faf7,#eef6f3); }
.no-chat-open::before {
  content:''; display:block; width:64px; height:64px; margin:0 auto 18px; border-radius:20px;
  background:var(--teal-pale) center/30px 30px no-repeat;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230c8474' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 4H4a1 1 0 0 0-1 1v11a1 1 0 0 0 1 1h3v4l5-4h8a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1Z'/%3E%3C/svg%3E");
}

/* ── 11. PERFIL ─────────────────────────────────────────────── */
/* Portada de marca + avatar montado encima: el perfil abría con un círculo verde
   sobre blanco y una rejilla de cajas grises, y era la pantalla más apagada. */
.profile-card { position:relative; overflow:hidden; padding:0 28px 28px; border-radius:24px; box-shadow:var(--sh2); }
.profile-card::before {
  content:''; position:absolute; top:0; left:0; right:0; height:112px;
  background:var(--grad-brand);
}
.profile-card::after {
  content:''; position:absolute; top:-70px; right:-40px; width:210px; height:210px;
  border-radius:50%; border:28px solid rgba(255,255,255,.12); pointer-events:none;
}
.profile-top {
  position:relative; z-index:1; flex-direction:column; align-items:flex-start;
  gap:14px; padding-top:62px; margin-bottom:24px;
}
.profile-big-av {
  width:104px; height:104px; font-size:38px;
  border:4px solid #fff; box-shadow:0 12px 26px -12px rgba(6,60,52,.9);
}
.avatar-edit { width:30px; height:30px; background:var(--grad-btn); box-shadow:0 4px 10px -4px rgba(15,160,138,.9); }
.profile-details .pdname { font-size:26px; letter-spacing:-.5px; }
.profile-details .pdverif { margin-top:8px; padding:4px 12px; font-weight:700; }

.info-grid { gap:12px; }
.info-item {
  background:var(--c); border:1px solid transparent; border-radius:15px; padding:14px 16px;
  transition:border-color .16s, background .16s, transform .16s;
}
.info-item:hover { background:#fff; border-color:var(--teal3); transform:translateY(-1px); }
.info-label { color:#0a6f61; opacity:1; letter-spacing:.9px; }
.info-val { font-weight:600; }
.bio-box { background:var(--c); border-radius:15px; padding:16px 18px; font-size:13.5px; }
.rating-card { border-radius:18px; padding:16px; box-shadow:var(--sh); }
.rating-tipo { border-radius:8px; padding:3px 9px; }
.dispo-cell { border-radius:8px; }
.dispo-cell.on { background:var(--grad-btn); border-color:transparent; box-shadow:0 3px 8px -4px rgba(15,160,138,.9); }

/* ── 12. MODALES Y FORMULARIOS ──────────────────────────────── */
.modal-ov { background:rgba(10,40,34,.5); backdrop-filter:blur(4px); -webkit-backdrop-filter:blur(4px); }
.modal { border-radius:24px; padding:30px; box-shadow:0 40px 90px -30px rgba(6,40,34,.65); }
.modal-title { font-size:23px; letter-spacing:-.4px; }
.modal-close { width:32px; height:32px; border-radius:50%; background:var(--c); color:var(--txm); transition:.16s; }
.modal-close:hover { background:var(--bdr); color:var(--txt); }
.form-label { font-size:12.5px; font-weight:700; color:var(--txm); }
/* Publicar anuncio, formulario sencillo (17/09): día + horas en una rejilla corta y
   las «Opciones avanzadas» plegadas en un <details>. */
.pub-horario { display:grid; grid-template-columns:1.35fr 1fr 1fr; gap:12px; }
.pub-avanzadas { margin:4px 0 16px; border:1px solid var(--bdr-soft); border-radius:14px; background:var(--c); }
.pub-avanzadas > summary {
  list-style:none; cursor:pointer; position:relative; display:flex; flex-direction:column; gap:2px;
  padding:12px 14px 12px 34px; font-weight:800; font-size:14px; color:var(--teal2);
}
.pub-avanzadas > summary::-webkit-details-marker { display:none; }
.pub-avanzadas > summary::before { content:'\25B8'; position:absolute; left:14px; top:13px; font-size:13px; color:var(--txl); transition:transform .15s ease; }
.pub-avanzadas[open] > summary::before { transform:rotate(90deg); }
.pub-avanzadas > summary small { font-weight:500; font-size:11.5px; color:var(--txm); line-height:1.4; }
.pub-avanzadas-cuerpo { padding:12px 14px 2px; border-top:1px dashed var(--bdr-soft); }
/* min-width:0 — sin esto, en una rejilla 1fr 1fr los campos de fecha imponen su
   ancho mínimo intrínseco (~200px cada uno) y se salen del modal en un móvil. */
.form-input, .form-select, .form-textarea { border-radius:12px; padding:12px 14px; min-width:0; }
.form-input:focus, .form-select:focus, .form-textarea:focus { box-shadow:0 0 0 3.5px rgba(15,160,138,.15); }
.up-opt, .apl-card { border-radius:16px; }
.tut-ico { border-radius:20px; background:var(--grad-brand); box-shadow:0 12px 26px -14px rgba(6,60,52,.9); }
.tut-ico svg { stroke:#fff; color:#fff; }
.tut-dot.on { background:var(--teal); box-shadow:0 0 0 3px rgba(15,160,138,.2); }

/* Avisos */
.safety-note, .verify-banner { border-radius:15px; padding:13px 16px; border-color:rgba(255,122,89,.22); }
.fee-band { border-radius:12px; }
.alumno-band { border-radius:13px; }

/* ── 13. AVISO FLOTANTE ─────────────────────────────────────── */
.toast {
  border-radius:14px; padding:13px 20px; background:#10201c; font-size:13.5px;
  box-shadow:0 20px 40px -18px rgba(0,0,0,.6);
}
.toast.error { background:#b83a2c; }

/* Pie legal (lo inyecta legal.js con su propio <style> en el <head>, por eso hace
   falta el id para ganarle). Aquí solo se pone a tono con la paleta de la app. */
#cyLegalFooter .cy-legal-footer {
  background:transparent; border-top:1px solid var(--bdr); color:var(--txm); padding:26px 22px;
}
#cyLegalFooter .cy-legal-links a { color:var(--teal2); }

/* Barra de desplazamiento algo más presente y de marca */
::-webkit-scrollbar { width:9px; height:9px; }
::-webkit-scrollbar-thumb { background:rgba(15,160,138,.25); border-radius:10px; border:2px solid transparent; background-clip:padding-box; }
::-webkit-scrollbar-thumb:hover { background:rgba(15,160,138,.42); background-clip:padding-box; }

/* ── 14. MÓVIL ──────────────────────────────────────────────── */
/* Mismo par de condiciones que el resto de la app. El tope de 1100px del término
   táctil se MANTIENE: quitarlo mandaba al layout de teléfono —barra fija abajo
   cruzando la pantalla— a cualquier táctil ancha de verdad (iPad apaisado, tableta
   Android de 10", tableta Windows). La WebView que maqueta a 1440-1600px la cubre
   el gemelo html.pantalla-compacta que va justo después de este bloque. */
@media (max-width:900px), (pointer:coarse) and (max-width:1100px) {
  /* La cabecera NO puede llevar backdrop-filter: crearía un containing block y la
     barra inferior fija se anclaría a ella (ver theme.css). */
  /* OPACA del todo, y sin nada que la promocione a capa propia. Sin desenfoque (no
     puede llevarlo: ver theme.css), cualquier transparencia deja ver el contenido
     pasando por debajo. Se fija con la propiedad LARGA y se quita la transición del
     fondo: con `transition:background` sobre un elemento sticky, Chrome compone la
     cabecera en su propia capa y la pinta translúcida aunque la CSSOM diga
     rgb(255,255,255) — se reprodujo en las capturas de 360px. */
  .site-header {
    background:none; background-color:#fff;
    backdrop-filter:none; -webkit-backdrop-filter:none;
    transition:box-shadow .25s ease;
  }
  .site-header.desplazada { background-color:#fff; }
  .header-inner { height:60px; }
  .topbar { height:60px; padding:0 16px; }
  .topbar .logo .wordmark { display:none; }

  /* Altura real que ocupa la barra inferior fija, incluida la zona segura del
     iPhone. La usan el hueco del final de la página y el alto del chat. */
  :root { --nav-alto:calc(70px + env(safe-area-inset-bottom)); }
  .page { padding:16px 14px calc(var(--nav-alto) + 26px); }
  .main-view.active { gap:16px; }

  /* Cabecera de vista compacta */
  .view-header { padding:20px; border-radius:20px; align-items:flex-start; }
  .view-header::after { right:-52px; top:-70px; width:160px; height:160px; border-width:22px; }
  .view-title { font-size:23px; }
  .view-sub { font-size:13px; }
  .view-header .pub-ad-btn { width:100%; }

  /* Barra inferior: fondo sólido, esquinas redondeadas y píldora en la activa */
  .nav-items {
    background:rgba(255,255,255,.97); border-radius:22px 22px 0 0;
    border-top:1px solid var(--bdr-soft);
    box-shadow:0 -8px 26px -12px rgba(16,32,28,.35);
    padding:8px 6px; padding-bottom:calc(8px + env(safe-area-inset-bottom));
  }
  /* display:flex explícito: el bloque móvil de app.html pone flex-direction/align en
     .nav-item pero NUNCA el display, así que los botones seguían siendo inline-block e
     ignoraban esas tres reglas. Solo "Canguros" y "Clases" quedaban en flex, porque a
     esos dos app.js les pone display:flex en línea al mostrarlos — y salían 4 px más
     altos que el resto. Con la píldora de la pestaña activa se notaba. */
  .nav-item { display:flex; min-height:50px; border-radius:14px; padding:7px 2px 6px; gap:4px; font-size:10.5px; }
  .nav-item:hover { background:none; }
  .nav-item.active { background:var(--teal-pale); }
  .nav-item .nav-ico svg { width:22px; height:22px; transition:transform .2s cubic-bezier(.3,1.4,.5,1); }
  .nav-item.active .nav-ico svg { transform:translateY(-1px) scale(1.08); }
  .nav-item .badge-count { top:2px; left:calc(50% + 5px); }

  /* Tarjetas: más aire vertical y menos lateral, que la pantalla es estrecha */
  /* Los distintivos se comían tres líneas de una tarjeta en una pantalla de 360px */
  .badges { gap:4px; }
  .badge { padding:3px 8px; font-size:10px; }
  .ad-meta { gap:6px; }
  .ad-meta span { padding:4px 9px; font-size:11px; }

  .ad-card { padding:18px 16px 18px 18px; border-radius:18px; }
  .ad-card:hover { transform:none; box-shadow:var(--sh); }
  .ad-title { font-size:17.5px; }

  /* Proveedores: en columna. Antes eran tres botones apretados a la derecha de
     una ficha, y en 390 px no cabían. */
  .prov-row { flex-wrap:wrap; gap:12px; }
  .prov-av { order:1; }
  .prov-main { flex:1 1 100%; order:2; }
  .prov-actions { flex:1 1 100%; order:3; flex-direction:row; flex-wrap:wrap; }
  .prov-actions > * { flex:1 1 140px; }

  /* Filtros a DOS por fila: apilados de uno en uno, la tarjeta medía más de 600 px
     y empujaba los resultados fuera de la pantalla antes de empezar a mirarlos.
     Los que necesitan el ancho entero (el control segmentado, el buscador de
     colegios y los desplegables múltiples) se quedan a una columna. */
  .filters-card { border-radius:18px; padding:14px; gap:10px 12px; }
  .filter-field { flex:1 1 calc(50% - 12px); min-width:140px; }
  .filter-field:has(.fbar),
  .filter-field:has(.colegio-lista),
  .filter-field:has(.msel) { flex-basis:100%; }
  .filter-field .form-input, .filter-field .form-select, .filter-field .msel summary { width:100% !important; }
  .filter-field small { max-width:none !important; }
  .filter-check { flex:1 1 calc(50% - 12px); justify-content:center; padding-bottom:7px; }
  .filters-card > .btn-chat { flex:1 1 100%; margin-left:0 !important; }
  .fbar { width:100%; }
  .fbtn { flex:1; text-align:center; padding:8px 10px; }

  /* Mensajes: la vista ocupa lo que queda entre la cabecera y la barra inferior,
     y el panel se estira dentro. Sin el hueco de más al final de la página, para
     que el chat no se pueda desplazar por debajo de la barra. */
  #view-chat.active { height:calc(100dvh - 60px - env(safe-area-inset-top) - 16px - var(--nav-alto) - 10px); min-height:400px; }
  .page:has(#view-chat.active) { padding-bottom:calc(var(--nav-alto) + 10px); }
  .chat-panel { border-radius:18px; min-height:0; }
  /* min-height:0 en el panel de la conversación. Sin esto, como casilla de una
     rejilla su tamaño mínimo automático es el de su contenido (~900px), la rejilla
     no puede encogerlo y se desborda hacia ARRIBA: la cabecera de la conversación
     —con el nombre y los botones de valorar, bloquear y denunciar— se salía fuera
     de la pantalla y en el móvil no había forma de llegar a ella. Ya pasaba antes
     de esta hoja; se arregla aquí porque es donde vive ahora el alto del chat. */
  .chat-open { min-height:0; }
  /* Y la cabecera se aprieta un poco: 155px de 525 era demasiado para un teléfono. */
  .chat-head { padding:10px 14px; gap:8px; }
  .chat-head .hbtns { gap:6px; }
  .chat-head .hbtns .btn-chat { padding:7px 11px; font-size:12px; }
  .msgs-wrap { padding:16px; }
  .msg { max-width:84%; }

  /* Perfil */
  .profile-card { padding:0 18px 22px; border-radius:20px; }
  .profile-card::before { height:96px; }
  .profile-top { padding-top:50px; }
  .profile-big-av { width:88px; height:88px; font-size:32px; }
  .profile-details .pdname { font-size:22px; }

  .modal { border-radius:20px; padding:22px; }
  /* Publicar: el día a lo ancho y las dos horas debajo, una al lado de la otra. */
  .pub-horario { grid-template-columns:1fr 1fr; }
  .pub-horario > .pub-dia { grid-column:1 / -1; }
  /* Inicio y Fin, uno debajo del otro: dos campos de fecha no caben a lo ancho de un
     teléfono y el de Fin se salía del modal. El !important es necesario: la rejilla
     va en un style= en línea del propio app.html y si no, gana él. */
  .modal .form-group:has(input[type="datetime-local"]) { grid-template-columns:1fr !important; }

  /* El aviso flotante no puede quedar debajo de la barra inferior */
  .toast { left:14px; right:14px; bottom:calc(var(--nav-alto) + 14px); max-width:none; text-align:center; }

  /* El pie legal es lo último de la página: sin este hueco, sus últimas líneas
     quedaban tapadas por la barra de navegación. */
  #cyLegalFooter .cy-legal-footer { padding-bottom:calc(26px + var(--nav-alto)); }
}

/* ── 14b. GEMELO DE MODO COMPACTO ───────────────────────────
   En modo compacto documentElement.clientWidth vale ~1440 aunque la pantalla mida
   390, así que el @media de arriba NO casa y la app se quedaba con el layout de
   escritorio dentro del teléfono. pantalla.js marca ese caso con
   html.pantalla-compacta, que es un SELECTOR y no cabe dentro de un @media: de ahí
   la repetición. Copia literal del bloque 14, generada mecánicamente (mismas
   declaraciones, mismo orden), con el prefijo puesto.
   Van con :where(), que NO suma especificidad, para que cada gemelo pese
   EXACTAMENTE lo mismo que la regla original del @media. Con el prefijo desnudo el
   gemelo subía a 0-2-1 y le ganaba a reglas que hoy le ganan: medido, .filter-field
   .form-input de app.html (0-2-0, 13px) se iba a 16px SOLO en modo compacto.
   ⚠️ Si tocas el bloque 14, toca también este gemelo. */
:where(html.pantalla-compacta) .site-header { background:none; background-color:#fff; backdrop-filter:none; -webkit-backdrop-filter:none; transition:box-shadow .25s ease; }
:where(html.pantalla-compacta) .site-header.desplazada { background-color:#fff; }
:where(html.pantalla-compacta) .header-inner { height:60px; }
:where(html.pantalla-compacta) .topbar { height:60px; padding:0 16px; }
:where(html.pantalla-compacta) .topbar .logo .wordmark { display:none; }
:root:where(.pantalla-compacta) { --nav-alto:calc(70px + env(safe-area-inset-bottom)); }
:where(html.pantalla-compacta) .page { padding:16px 14px calc(var(--nav-alto) + 26px); }
:where(html.pantalla-compacta) .main-view.active { gap:16px; }
:where(html.pantalla-compacta) .view-header { padding:20px; border-radius:20px; align-items:flex-start; }
:where(html.pantalla-compacta) .view-header::after { right:-52px; top:-70px; width:160px; height:160px; border-width:22px; }
:where(html.pantalla-compacta) .view-title { font-size:23px; }
:where(html.pantalla-compacta) .view-sub { font-size:13px; }
:where(html.pantalla-compacta) .view-header .pub-ad-btn { width:100%; }
:where(html.pantalla-compacta) .nav-items { background:rgba(255,255,255,.97); border-radius:22px 22px 0 0; border-top:1px solid var(--bdr-soft); box-shadow:0 -8px 26px -12px rgba(16,32,28,.35); padding:8px 6px; padding-bottom:calc(8px + env(safe-area-inset-bottom)); }
:where(html.pantalla-compacta) .nav-item { display:flex; min-height:50px; border-radius:14px; padding:7px 2px 6px; gap:4px; font-size:10.5px; }
:where(html.pantalla-compacta) .nav-item:hover { background:none; }
:where(html.pantalla-compacta) .nav-item.active { background:var(--teal-pale); }
:where(html.pantalla-compacta) .nav-item .nav-ico svg { width:22px; height:22px; transition:transform .2s cubic-bezier(.3,1.4,.5,1); }
:where(html.pantalla-compacta) .nav-item.active .nav-ico svg { transform:translateY(-1px) scale(1.08); }
:where(html.pantalla-compacta) .nav-item .badge-count { top:2px; left:calc(50% + 5px); }
:where(html.pantalla-compacta) .badges { gap:4px; }
:where(html.pantalla-compacta) .badge { padding:3px 8px; font-size:10px; }
:where(html.pantalla-compacta) .ad-meta { gap:6px; }
:where(html.pantalla-compacta) .ad-meta span { padding:4px 9px; font-size:11px; }
:where(html.pantalla-compacta) .ad-card { padding:18px 16px 18px 18px; border-radius:18px; }
:where(html.pantalla-compacta) .ad-card:hover { transform:none; box-shadow:var(--sh); }
:where(html.pantalla-compacta) .ad-title { font-size:17.5px; }
:where(html.pantalla-compacta) .prov-row { flex-wrap:wrap; gap:12px; }
:where(html.pantalla-compacta) .prov-av { order:1; }
:where(html.pantalla-compacta) .prov-main { flex:1 1 100%; order:2; }
:where(html.pantalla-compacta) .prov-actions { flex:1 1 100%; order:3; flex-direction:row; flex-wrap:wrap; }
:where(html.pantalla-compacta) .prov-actions > * { flex:1 1 140px; }
:where(html.pantalla-compacta) .filters-card { border-radius:18px; padding:14px; gap:10px 12px; }
:where(html.pantalla-compacta) .filter-field { flex:1 1 calc(50% - 12px); min-width:140px; }
:where(html.pantalla-compacta) .filter-field:has(.fbar),
:where(html.pantalla-compacta) .filter-field:has(.colegio-lista),
:where(html.pantalla-compacta) .filter-field:has(.msel) { flex-basis:100%; }
:where(html.pantalla-compacta) .filter-field .form-input,
:where(html.pantalla-compacta) .filter-field .form-select,
:where(html.pantalla-compacta) .filter-field .msel summary { width:100% !important; }
:where(html.pantalla-compacta) .filter-field small { max-width:none !important; }
:where(html.pantalla-compacta) .filter-check { flex:1 1 calc(50% - 12px); justify-content:center; padding-bottom:7px; }
:where(html.pantalla-compacta) .filters-card > .btn-chat { flex:1 1 100%; margin-left:0 !important; }
:where(html.pantalla-compacta) .fbar { width:100%; }
:where(html.pantalla-compacta) .fbtn { flex:1; text-align:center; padding:8px 10px; }
:where(html.pantalla-compacta) #view-chat.active { height:calc(100dvh - 60px - env(safe-area-inset-top) - 16px - var(--nav-alto) - 10px); min-height:400px; }
:where(html.pantalla-compacta) .page:has(#view-chat.active) { padding-bottom:calc(var(--nav-alto) + 10px); }
:where(html.pantalla-compacta) .chat-panel { border-radius:18px; min-height:0; }
:where(html.pantalla-compacta) .chat-open { min-height:0; }
:where(html.pantalla-compacta) .chat-head { padding:10px 14px; gap:8px; }
:where(html.pantalla-compacta) .chat-head .hbtns { gap:6px; }
:where(html.pantalla-compacta) .chat-head .hbtns .btn-chat { padding:7px 11px; font-size:12px; }
:where(html.pantalla-compacta) .msgs-wrap { padding:16px; }
:where(html.pantalla-compacta) .msg { max-width:84%; }
:where(html.pantalla-compacta) .profile-card { padding:0 18px 22px; border-radius:20px; }
:where(html.pantalla-compacta) .profile-card::before { height:96px; }
:where(html.pantalla-compacta) .profile-top { padding-top:50px; }
:where(html.pantalla-compacta) .profile-big-av { width:88px; height:88px; font-size:32px; }
:where(html.pantalla-compacta) .profile-details .pdname { font-size:22px; }
:where(html.pantalla-compacta) .modal { border-radius:20px; padding:22px; }
:where(html.pantalla-compacta) .pub-horario { grid-template-columns:1fr 1fr; }
:where(html.pantalla-compacta) .pub-horario > .pub-dia { grid-column:1 / -1; }
:where(html.pantalla-compacta) .modal .form-group:has(input[type="datetime-local"]) { grid-template-columns:1fr !important; }
:where(html.pantalla-compacta) .toast { left:14px; right:14px; bottom:calc(var(--nav-alto) + 14px); max-width:none; text-align:center; }
:where(html.pantalla-compacta) #cyLegalFooter .cy-legal-footer { padding-bottom:calc(26px + var(--nav-alto)); }

/* Modo compacto (pantalla.js): cuando el navegador ignora la meta viewport, vh/dvh
   miden el viewport real (más alto que el aparente) y las alturas salen largas.
   --alto-vista la pone pantalla.js ya en unidades del zoom.
   Estas DOS no son gemelos: son reglas propias del modo compacto que tienen que
   GANARLE al gemelo de arriba (que ya fija .page y #view-chat.active). Por eso van
   con el prefijo desnudo y NO con :where() — aquí la especificidad de más es
   deliberada, al revés que en los gemelos. */
html.pantalla-compacta .page { padding-bottom:calc(var(--nav-alto,96px) + 26px); }
html.pantalla-compacta #view-chat.active {
  height:calc(var(--alto-vista,100vh) - 60px - 16px - var(--nav-alto,96px) - 10px);
}

/* ── 20. SIN backdrop-filter EN TÁCTIL ───────────────────────────
   En un Xiaomi, con la v6 ya bien maquetada, la app empezaba a dejar HUECOS EN
   BLANCO a medio pintar y acababa con la pantalla entera vacía (solo el fondo)
   a los ~15 s de uso. Un error de JavaScript no pinta media tarjeta: eso es la
   WebView fallando al componer capas.

   `backdrop-filter` obliga al motor a recomponer, en cada fotograma, una copia
   desenfocada de TODO lo que hay detrás del elemento. En un elemento fijo y a
   pantalla completa eso es una capa de GPU del tamaño de la pantalla, viva
   durante todo el scroll. La WebView de Android la lleva mucho peor que Chrome
   y termina soltando las texturas: primero huecos, luego la página en blanco.

   La prueba está en el vídeo: la tarjeta que aparece medio sin pintar es
   `.filters-card`, que es justo una de las que lo llevaba. Y el fichero ya
   avisaba de este filtro por otro motivo (crea containing block y descolocaba
   la barra inferior), así que en la cabecera ya se había quitado; faltaban
   estas tres.

   Lo que se pierde es imperceptible: `.nav-items` va sobre un fondo que ya es
   97 % opaco, así que el desenfoque aportaba un 3 %. Aquí NO se pone tope de
   ancho —a diferencia de los bloques de maquetación— porque esto no cambia el
   layout: es coste de pintado, y una tableta táctil lo paga igual. */
@media (pointer: coarse) {
  .nav-items {
    backdrop-filter: none; -webkit-backdrop-filter: none;
    background: #fff;
  }
  .filters-card {
    backdrop-filter: none; -webkit-backdrop-filter: none;
    background: var(--w, #fff);
  }
  .modal-ov {
    backdrop-filter: none; -webkit-backdrop-filter: none;
  }
}
