/* ═══════════════════════════════════════════════════════════════════════════════
   KitEventos · tokens y base
   Los valores salen del paquete de diseño (diseno/README.md) y son los definitivos.

   ⚠ CONTRASTE: los grises #8a7359, #9c8a72, #7a6749 y #6b5a48 se quitaron del diseño por no
     llegar a 4,5:1 sobre crema. No reintroducirlos. El mínimo que cumple es #6f5c44.
   ═══════════════════════════════════════════════════════════════════════════════ */

@import url('../fonts/fuentes.css');

:root {
  /* Paleta del panel · fija, no depende del tema de la invitación */
  --ke-fondo:        #efe6d8;
  --ke-tarjeta:      #fbf6ec;
  --ke-borde:        #ddcdb2;
  --ke-borde-sel:    #c9ab7d;
  --ke-lateral:      #1a1512;
  --ke-lateral-act:  #241d18;
  --ke-superior:     #0d0a08;

  --ke-tinta:        #2b211a;   /* texto principal */
  --ke-tinta-2:      #5c4b38;   /* secundario */
  --ke-tinta-3:      #6f5c44;   /* apagado · el mínimo que cumple 4,5:1 sobre crema */
  --ke-sobre-oscuro: #f0e3cc;
  --ke-sobre-oscuro-2:#b8a184;

  --ke-acento:       #9c3f22;
  --ke-laton:        #b98a3c;
  --ke-alerta:       #8c2f16;   /* choque de mesas */

  /* Estados */
  --ke-ok-fondo:  #e2ecdd;  --ke-ok-borde:  #b9cdae;  --ke-ok-tinta:  #3f5a33;
  --ke-pdte-fondo:#f6e6cd;  --ke-pdte-borde:#e0c795;  --ke-pdte-tinta:#7a5a1c;
  --ke-mal-fondo: #f0e0dc;  --ke-mal-borde: #ddbdb4;  --ke-mal-tinta: #8c4436;

  /* Tipografía */
  --ke-titulo: Bevan, Georgia, 'Times New Roman', serif;
  --ke-texto:  'EB Garamond', Georgia, 'Times New Roman', serif;

  /* Espaciado */
  --e2:2px; --e4:4px; --e6:6px; --e8:8px; --e10:10px; --e12:12px;
  --e14:14px; --e16:16px; --e18:18px; --e22:22px; --e26:26px; --e30:30px;

  /* Radios */
  --r-chip:3px; --r-boton:4px; --r-tarjeta:5px; --r-flotante:8px; --r-pastilla:99px;

  /* Sombras */
  --s-mueble:   0 1px 3px rgba(0,0,0,.25);
  --s-flotante: 0 8px 22px rgba(0,0,0,.4);
  --s-columna:  0 30px 80px rgba(0,0,0,.55);

  color-scheme: light;
}

/* ── Base ─────────────────────────────────────────────────────────────────── */

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

html, body {
  margin: 0; padding: 0;
  background: var(--ke-fondo);
  color: var(--ke-tinta);
  font: 17px/1.6 var(--ke-texto);
  /* Sin ajuste automático: en móvil, iOS agranda el texto de bloques anchos y descuadra el
     plano de mesas, que está calculado en píxeles por metro. */
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3 { font-family: var(--ke-titulo); font-weight: 400; line-height: 1.2; margin: 0 0 var(--e8); }
h1 { font-size: 26px; }
h2 { font-size: 21px; }
h3 { font-size: 19px; }

a { color: var(--ke-acento); text-decoration: none; border-bottom: 1px solid rgba(156,63,34,.35); }
a:hover { color: #7a2f19; border-bottom-color: #7a2f19; }

/* Rótulos en mayúsculas: 12 px con espaciado, como en el diseño. */
.ke-label {
  font-size: 12px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ke-tinta-3);
}

.ke-secundario { color: var(--ke-tinta-2); font-size: 15px; }
.ke-pie { color: var(--ke-tinta-3); font-size: 14px; }

/* ── Formularios ──────────────────────────────────────────────────────────── */

input, textarea, select, button { font-family: var(--ke-texto); font-size: 16px; }

/* 16 px en los campos NO es capricho: por debajo, Safari en iPhone hace zoom al enfocarlos y
   descoloca la pantalla entera. */
.ke-campo {
  width: 100%; padding: 11px 13px;
  border: 1px solid rgba(0,0,0,.2); border-radius: var(--r-chip);
  background: #fff; color: var(--ke-tinta); font-size: 16px;
}
.ke-campo:focus { outline: 2px solid rgba(156,63,34,.35); outline-offset: 1px; }

/* Los objetivos táctiles, 44 px de alto mínimo (criterio del diseño). */
.ke-boton {
  display: inline-block; min-height: 44px; padding: 11px 18px;
  border-radius: var(--r-boton); border: 1px solid var(--ke-acento);
  background: var(--ke-acento); color: #fff; font-size: 16px;
  cursor: pointer; text-align: center; text-decoration: none;
}
.ke-boton:hover { background: #883620; border-color: #883620; color: #fff; }
.ke-boton--sec {
  background: #fff; color: var(--ke-tinta); border-color: #cbb797;
}
.ke-boton--sec:hover { background: #f6efe1; color: var(--ke-tinta); }

/* ── Piezas ───────────────────────────────────────────────────────────────── */

.ke-tarjeta {
  background: var(--ke-tarjeta);
  border: 1px solid var(--ke-borde);
  border-radius: var(--r-tarjeta);
  padding: var(--e18);
}

.ke-pastilla {
  display: inline-block; font-size: 12px; letter-spacing: .08em; text-transform: uppercase;
  padding: 3px 9px; border-radius: var(--r-pastilla); white-space: nowrap;
}
.ke-pastilla--ok   { background: var(--ke-ok-fondo);   border: 1px solid var(--ke-ok-borde);   color: var(--ke-ok-tinta); }
.ke-pastilla--pdte { background: var(--ke-pdte-fondo); border: 1px solid var(--ke-pdte-borde); color: var(--ke-pdte-tinta); }
.ke-pastilla--mal  { background: var(--ke-mal-fondo);  border: 1px solid var(--ke-mal-borde);  color: var(--ke-mal-tinta); }

.ke-aviso {
  padding: var(--e12) var(--e14); border-radius: var(--r-boton);
  border: 1px solid var(--ke-mal-borde); background: var(--ke-mal-fondo);
  color: var(--ke-mal-tinta); font-size: 15px;
}
.ke-aviso--ok   { border-color: var(--ke-ok-borde);   background: var(--ke-ok-fondo);   color: var(--ke-ok-tinta); }
.ke-aviso--pdte { border-color: var(--ke-pdte-borde); background: var(--ke-pdte-fondo); color: var(--ke-pdte-tinta); }
/* El aviso base ya viste de error, así que esto es redundante HOY. Se escribe igual porque el día
   que alguien cambie el color base, los mensajes de error se volverían neutros sin que nadie lo
   note: un error que no parece un error no lo lee nadie. */
.ke-aviso--mal  { border-color: var(--ke-mal-borde);  background: var(--ke-mal-fondo);  color: var(--ke-mal-tinta); }

/* ── Pantallas de acceso ──────────────────────────────────────────────────── */

.ke-acceso {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: var(--e22);
}
.ke-acceso__caja { width: 100%; max-width: 420px; }
.ke-acceso__marca { text-align: center; margin-bottom: var(--e22); }
.ke-acceso__marca h1 { font-size: 26px; margin-bottom: var(--e2); }
.ke-acceso__marca p { margin: 0; color: var(--ke-tinta-2); font-size: 15px; }
.ke-acceso label { display: block; margin-bottom: var(--e14); }
.ke-acceso label > span { display: block; margin-bottom: var(--e4); font-size: 15px; color: var(--ke-tinta-2); }
.ke-acceso .ke-boton { width: 100%; margin-top: var(--e4); }
.ke-acceso__extra { margin: var(--e16) 0 0; text-align: center; font-size: 15px; }

/* ── Barras de scroll, como en el diseño ──────────────────────────────────── */

* { scrollbar-width: thin; scrollbar-color: #a8896a rgba(0,0,0,.08); }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: rgba(43,33,26,.07); border-radius: var(--r-pastilla); }
::-webkit-scrollbar-thumb {
  background: #a8896a; border-radius: var(--r-pastilla);
  border: 2px solid transparent; background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: #8a6c4e; background-clip: padding-box; }

/* ── Accesibilidad ────────────────────────────────────────────────────────── */

/* Quien haya pedido menos movimiento en su sistema, que no vea animaciones. Aquí hay confeti,
   coches que cruzan la pantalla y una simulación del día: no es un detalle menor. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
}

.ke-solo-lectores {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ═══════════════════════════════════════════════════════════════════════════════
   El panel · barra superior, lateral y contenido
   ═══════════════════════════════════════════════════════════════════════════════ */

.ke-panel {
  min-height: 100vh;
  display: grid;
  grid-template-rows: auto 1fr;
  grid-template-columns: 246px minmax(0, 1fr);
  grid-template-areas: "arriba arriba" "lado contenido";
  /* La lateral es sticky y por tanto solo mide lo que ocupa su contenido, así que su
     fondo oscuro se cortaba a media pantalla. Se pinta la franja en el contenedor: así
     llega siempre abajo del todo sin renunciar al sticky ni añadir un elemento vacío. */
  background: linear-gradient(to right, var(--ke-lateral) 0 246px, var(--ke-fondo) 246px);
}

/* La barra superior es sticky y la lateral se pega justo debajo. En el prototipo esto se
   resolvía midiendo la altura de la barra con JS y pasándosela a la lateral; con grid y
   position:sticky sale solo, y además no se descuadra cuando la barra envuelve en dos líneas
   (que era justo el fallo que obligó a medir en vez de usar 45 px fijos). */
.ke-barra {
  grid-area: arriba; position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: var(--e14); flex-wrap: wrap;
  padding: var(--e10) var(--e16);
  background: var(--ke-superior); color: var(--ke-sobre-oscuro);
}
.ke-barra__marca {
  font-family: var(--ke-titulo); font-size: 17px; letter-spacing: .04em;
  color: var(--ke-sobre-oscuro); margin-right: auto; border: 0;
}
.ke-barra__marca:hover { color: #fff; }
.ke-barra a, .ke-barra span { border: 0; color: var(--ke-sobre-oscuro-2); font-size: 15px; }
.ke-barra a:hover { color: #fff; }

.ke-lado {
  grid-area: lado; background: var(--ke-lateral); color: var(--ke-sobre-oscuro);
  position: sticky; top: 0; align-self: start; max-height: 100vh; overflow-y: auto;
  padding: var(--e18) 0;
}
.ke-lado__titulo { padding: 0 var(--e18) var(--e14); }
.ke-lado__titulo .ke-label { color: var(--ke-sobre-oscuro-2); }
.ke-lado__titulo h2 { font-size: 21px; color: var(--ke-sobre-oscuro); margin: var(--e2) 0; }
.ke-lado__titulo p { margin: 0; font-size: 14px; color: var(--ke-sobre-oscuro-2); }

.ke-lado a {
  display: flex; justify-content: space-between; gap: var(--e8);
  padding: var(--e12) var(--e18); border: 0;
  color: var(--ke-sobre-oscuro-2); font-size: 16px;
}
.ke-lado a:hover { background: var(--ke-lateral-act); color: var(--ke-sobre-oscuro); }
.ke-lado a[aria-current="page"] {
  background: var(--ke-lateral-act); color: var(--ke-sobre-oscuro);
  box-shadow: inset 3px 0 0 var(--ke-laton);
}
.ke-lado a small { color: var(--ke-sobre-oscuro-2); font-size: 14px; }

.ke-contenido { grid-area: contenido; padding: var(--e26); min-width: 0; }
.ke-contenido > h1 { margin-bottom: var(--e4); }
.ke-contenido > .ke-sub { margin: 0 0 var(--e22); color: var(--ke-tinta-2); }

/* Por debajo de 900 px la lateral pasa a ser una tira de pestañas horizontal. */
@media (max-width: 900px) {
  .ke-panel { grid-template-columns: minmax(0, 1fr); grid-template-areas: "arriba" "lado" "contenido";
               background: var(--ke-fondo); }
  .ke-lado {
    position: static; max-height: none; display: flex; overflow-x: auto; padding: 0;
    -webkit-overflow-scrolling: touch;
  }
  .ke-lado__titulo { display: none; }
  .ke-lado a { white-space: nowrap; padding: var(--e12) var(--e14); }
  .ke-lado a[aria-current="page"] { box-shadow: inset 0 -3px 0 var(--ke-laton); }
  .ke-contenido { padding: var(--e16); }
}

/* ── Tablas del panel ─────────────────────────────────────────────────────── */

.ke-tabla-caja { overflow-x: auto; border-radius: var(--r-tarjeta); }
.ke-tabla { width: 100%; border-collapse: collapse; background: var(--ke-tarjeta); font-size: 16px; }
.ke-tabla th, .ke-tabla td { padding: var(--e12) var(--e14); text-align: left; vertical-align: middle; }
.ke-tabla thead th {
  font-size: 12px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ke-tinta-3); font-weight: 400; border-bottom: 1px solid var(--ke-borde);
}
.ke-tabla tbody tr + tr td { border-top: 1px solid #ece0cb; }
.ke-tabla td .ke-boton { min-height: 36px; padding: 7px 12px; font-size: 15px; }

.ke-acciones { display: flex; gap: var(--e8); flex-wrap: wrap; }
.ke-rejilla { display: grid; gap: var(--e14); grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

/* Fechas y acciones no envuelven: partir «2026-08-18 20:35» en dos líneas o cortar un botón
   por la mitad hace que la tabla parezca rota aunque quepa. */
.ke-tabla td.ke-nowrap, .ke-tabla th.ke-nowrap { white-space: nowrap; }
.ke-tabla td .ke-acciones { flex-wrap: nowrap; }
.ke-tabla th, .ke-tabla td { padding: var(--e10) var(--e12); }

/* ═══════════════════════════════════════════════════════════════════════════════
   La invitación · móvil primero
   Aquí llega gente abriendo un enlace de WhatsApp con una mano. Columna estrecha, letra
   grande y el botón de confirmar sin tener que buscarlo.
   ═══════════════════════════════════════════════════════════════════════════════ */

.ke-inv {
  max-width: 470px;                 /* la columna del diseño */
  margin: 0 auto;
  background: #f4e8d4;              /* papel del tema «Oeste elegante» */
  color: #2b211a;
  box-shadow: 0 30px 80px rgba(0,0,0,.55);
  min-height: 100vh;
}
body:has(.ke-inv) { background: linear-gradient(#1b1410, #0f0b09); }

.ke-inv__portada {
  padding: 44px 24px 34px;
  text-align: center;
  background: linear-gradient(to top, rgba(20,12,7,.92) 0%, rgba(20,12,7,.55) 60%, rgba(20,12,7,.35) 100%),
              #3a2a1c;
  color: #f4e8d4;
}
.ke-inv__ante {
  display: block; font-size: 13px; letter-spacing: .32em; text-transform: uppercase;
  color: #d3a044; margin-bottom: 10px;
}
.ke-inv__portada h1 { font-size: 34px; margin: 0 0 6px; color: #fff; line-height: 1.1; }
.ke-inv__nombres { font-size: 25px; color: #d3a044; margin: 0 0 12px; font-family: var(--ke-titulo); }
.ke-inv__cuando  { font-size: 17px; margin: 0; color: #e8d9c0; }

.ke-inv__cuerpo { padding: 26px 22px 44px; }
.ke-inv__cuerpo h2 {
  font-size: 21px; margin: 30px 0 12px;
  border-top: 1px solid rgba(0,0,0,.12); padding-top: 22px;
}
.ke-inv__cuerpo h2:first-of-type { border-top: 0; padding-top: 0; }

.ke-inv__texto { font-size: 17px; line-height: 1.7; margin: 0 0 12px; }
.ke-inv__firma { font-style: italic; color: #5c4b38; margin: 0 0 22px; }

.ke-inv__ficha {
  background: rgba(255,255,255,.5); border: 1px solid rgba(0,0,0,.1);
  border-radius: 4px; padding: 14px 16px; margin-bottom: 12px;
}
.ke-inv__ficha p { margin: 6px 0 0; }

.ke-chip {
  display: inline-block; font-size: 14px; padding: 5px 11px; margin: 0 6px 6px 0;
  border-radius: 99px; border: 1px solid var(--ke-acento); color: var(--ke-acento);
}

.ke-inv__programa { list-style: none; margin: 0; padding: 0; }
.ke-inv__programa li {
  display: flex; gap: 14px; padding: 11px 0;
  border-bottom: 1px solid rgba(0,0,0,.08);
}
.ke-inv__hora {
  font-family: var(--ke-titulo); font-size: 17px; color: var(--ke-acento);
  min-width: 58px; flex-shrink: 0;
}

/* ── El formulario ────────────────────────────────────────────────────────── */

.ke-inv__sino { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.ke-inv__opcion {
  display: block; padding: 16px 12px; text-align: center; cursor: pointer;
  border: 1px solid rgba(0,0,0,.25); border-radius: 4px; background: rgba(255,255,255,.6);
  font-size: 16px;
}
/* :has() para que la tarjeta entera se marque al elegir, sin JS. Donde no exista, el radio
   sigue viéndose y funcionando: se pierde el resaltado, no la función. */
.ke-inv__opcion:has(input:checked) {
  background: var(--ke-acento); border-color: var(--ke-acento); color: #fff;
}
.ke-inv__opcion input { margin-right: 8px; }

.ke-inv__persona {
  border: 1px solid rgba(0,0,0,.14); border-radius: 4px; padding: 12px;
  margin: 0 0 10px; background: rgba(255,255,255,.45);
}
.ke-inv__persona-fila { display: flex; gap: 8px; align-items: center; }
/* `min-width: 0` no es un adorno: un <input> trae un ancho intrínseco de unos 200 px y en un
   contenedor flex NO encoge por debajo de él. Con el select de 104 y el botón de 44 al lado, la
   fila pedía ~370 px y en un móvil de 360 empujaba el documento entero: toda la invitación
   aparecía desplazada y cortada por la derecha, incluida la portada, que no tiene nada que ver.
   Costó encontrarlo porque el síntoma sale muy lejos de la causa. */
.ke-inv__persona-fila > input[type=text] { flex: 1 1 0; min-width: 0; }
.ke-inv__tipo { width: 104px; flex-shrink: 0; }
.ke-inv__quitar {
  width: 44px; height: 44px; flex-shrink: 0; font-size: 22px; line-height: 1;
  border: 1px solid rgba(0,0,0,.2); border-radius: 4px;
  background: rgba(255,255,255,.7); color: #8c4436; cursor: pointer;
}
.ke-inv__marcas { margin-top: 10px; display: grid; gap: 6px; font-size: 15px; }
.ke-inv__marcas label { display: flex; gap: 8px; align-items: center; }
/* 20 px para que se puedan marcar con el dedo sin apuntar. */
.ke-inv__marcas input { width: 20px; height: 20px; }
.ke-inv__detalle { margin-top: 10px; }

.ke-inv__enviar { width: 100%; margin-top: 22px; font-size: 17px; }

.ke-inv__normas { margin: 0; padding-left: 20px; }
.ke-inv__normas li { margin-bottom: 10px; }

.ke-inv__tel {
  display: block; padding: 12px 14px; margin-bottom: 8px; border: 0;
  background: rgba(255,255,255,.5); border-radius: 4px; color: var(--ke-tinta);
}
.ke-inv__tel span { display: block; font-size: 15px; }

@media (max-width: 480px) {
  .ke-inv__portada h1 { font-size: 28px; }
  .ke-inv__sino { grid-template-columns: 1fr; }
}

/* ── El hilo de conversación ──────────────────────────────────────────────── */

.ke-hilo {
  background: var(--ke-tarjeta); border: 1px solid var(--ke-borde);
  border-radius: var(--r-tarjeta); padding: var(--e18);
  max-width: 720px; margin-bottom: var(--e16);
  /* Alto acotado con el scroll dentro: así el cuadro de escribir queda siempre a la vista y no
     hay que bajar media pantalla para contestar. */
  max-height: 60vh; overflow-y: auto;
}
.ke-hilo__dia {
  text-align: center; font-size: 13px; color: var(--ke-tinta-3);
  margin: var(--e16) 0 var(--e10);
}
.ke-hilo__dia:first-child { margin-top: 0; }

.ke-hilo__msg {
  max-width: 82%; margin-bottom: var(--e10); padding: var(--e10) var(--e14);
  border-radius: var(--r-tarjeta); background: #efe6d8; border: 1px solid var(--ke-borde);
}
/* Los propios, a la derecha y en otro tono: es la convención que todo el mundo entiende sin
   que se lo expliquen. */
.ke-hilo__msg--mio {
  margin-left: auto; background: #e6ecdf; border-color: #c3d2b6;
}
.ke-hilo__quien {
  margin: 0 0 4px; font-size: 13px; color: var(--ke-tinta-2);
  display: flex; justify-content: space-between; gap: var(--e10);
}
.ke-hilo__quien span { color: var(--ke-tinta-3); }
.ke-hilo__texto { margin: 0; font-size: 16px; line-height: 1.55; overflow-wrap: anywhere; }

.ke-hilo__form { max-width: 720px; }
.ke-hilo__form .ke-boton { margin-top: var(--e10); }

/* El atributo `hidden` tiene que ganar SIEMPRE.
   El navegador lo aplica con `display: none`, pero cualquier regla propia con `display` lo pisa
   por especificidad y el elemento sigue viéndose. Pasó con una pastilla de aviso vacía, que salía
   como un óvalo suelto al lado del texto sin que nada explicara qué era. */
[hidden] { display: none !important; }

/* ══ Fotos del catálogo · arrastrar, soltar, ver en grande ═══════════════════ */

.ke-ficha {
  position: relative;
  padding: 0;
  overflow: hidden;
  transition: box-shadow .15s, border-color .15s, transform .15s;
}
.ke-ficha[hidden] { display: none; }

/* El hueco de la foto. Cuadrado fijo: con alturas distintas la rejilla baila cada vez que entra
   una foto nueva y se pierde de vista la ficha en la que estabas trabajando. */
.ke-foto {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  background: #e7dbc7;
  cursor: pointer;
  border: 0;
  padding: 0;
}
.ke-foto img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ke-foto--vacia {
  display: flex; align-items: center; justify-content: center;
  color: var(--ke-tinta-3); font-size: 14px;
  background: repeating-linear-gradient(45deg, #e7dbc7 0 10px, #e2d5bf 10px 20px);
}
.ke-foto:focus-visible { outline: 3px solid var(--ke-acento); outline-offset: -3px; }

/* Los iconos: discretos hasta que hacen falta. Se ven siempre en pantalla táctil, porque allí no
   existe el «pasar por encima» y si no serían inalcanzables. */
.ke-esquina {
  position: absolute; top: 6px; right: 6px;
  display: flex; gap: 4px;
  opacity: 0; transition: opacity .15s;
}
.ke-ficha:hover .ke-esquina,
.ke-ficha:focus-within .ke-esquina { opacity: 1; }
@media (hover: none) { .ke-esquina { opacity: .85; } }

.ke-icono {
  width: 30px; height: 30px; padding: 0;
  display: grid; place-items: center;
  border: 1px solid rgba(255,255,255,.35);
  border-radius: 8px;
  background: rgba(13,10,8,.62);
  color: #f0e3cc;
  font-size: 15px; line-height: 1;
  cursor: pointer;
  backdrop-filter: blur(3px);
}
.ke-icono:hover { background: rgba(13,10,8,.85); border-color: rgba(255,255,255,.6); }
.ke-icono:focus-visible { outline: 2px solid #f0e3cc; outline-offset: 1px; }

.ke-ficha__pie { padding: 10px 12px 12px; }

/* Arrastrando por encima */
.ke-ficha--encima {
  border-color: var(--ke-acento);
  box-shadow: 0 0 0 3px rgba(156,63,34,.28);
  transform: translateY(-2px);
}
.ke-ficha--encima .ke-foto::after {
  content: 'Soltar aquí';
  position: absolute; inset: 0;
  display: grid; place-items: center;
  background: rgba(156,63,34,.72); color: #fff;
  font-family: var(--ke-titulo); font-size: 15px; letter-spacing: .04em;
}

/* Subiendo: barra de indeterminado. No se sabe el porcentaje real —la reducción va por dentro
   del canvas— y una barra que miente es peor que una que solo dice «voy». */
.ke-ficha--subiendo { pointer-events: none; }
.ke-ficha--subiendo .ke-foto { opacity: .45; }
.ke-ficha--subiendo::after {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 4px;
  background: linear-gradient(90deg, transparent, var(--ke-acento), transparent);
  background-size: 45% 100%; background-repeat: no-repeat;
  animation: ke-avanza 1.1s linear infinite;
}
@keyframes ke-avanza {
  from { background-position: -50% 0; }
  to   { background-position: 150% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .ke-ficha--subiendo::after { animation: none; background-position: 30% 0; }
  .ke-ficha { transition: none; }
}

/* Velo de «estás arrastrando algo» sobre toda la página */
.ke-velo {
  position: fixed; inset: 0; z-index: 60;
  pointer-events: none;
  background: rgba(43,33,26,.28);
  display: grid; place-items: center;
}
.ke-velo span {
  background: var(--ke-tarjeta); color: var(--ke-tinta);
  padding: 14px 22px; border-radius: 12px; border: 2px dashed var(--ke-borde-sel);
  font-family: var(--ke-titulo); font-size: 16px;
}

/* Avisos flotantes */
.ke-avisos-flot {
  position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
  z-index: 90; display: flex; flex-direction: column; gap: 8px; align-items: center;
  pointer-events: none; width: min(92vw, 460px);
}
.ke-flot {
  background: #241d18; color: #f0e3cc;
  padding: 11px 16px; border-radius: 10px;
  font-size: 15px; line-height: 1.4; text-align: center;
  box-shadow: 0 6px 20px rgba(0,0,0,.28);
  transition: opacity .4s;
}
.ke-flot--mal { background: #7d2c15; }

/* ── Visor ─────────────────────────────────────────────────────────────────── */
.ke-visor { position: fixed; inset: 0; z-index: 100; display: grid; place-items: center; }
.ke-visor[hidden] { display: none; }
.ke-visor-fondo { position: absolute; inset: 0; background: rgba(13,10,8,.9); }
.ke-visor-caja {
  position: relative; margin: 0;
  max-width: min(94vw, 1100px); max-height: 92vh;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.ke-visor-img {
  max-width: 100%; max-height: 76vh; object-fit: contain;
  border-radius: 6px; background: #241d18;
}
.ke-visor-caja figcaption {
  color: #f0e3cc; text-align: center; display: flex; flex-direction: column; gap: 2px;
}
.ke-visor-tit { font-family: var(--ke-titulo); font-size: 17px; letter-spacing: .03em; }
.ke-visor-sub { color: var(--ke-sobre-oscuro-2); font-size: 14px; }

.ke-visor-botones { display: flex; gap: 8px; }
.ke-visor-b {
  background: rgba(240,227,204,.12); color: #f0e3cc;
  border: 1px solid rgba(240,227,204,.4); border-radius: 8px;
  padding: 8px 16px; font-size: 15px; font-family: var(--ke-texto); cursor: pointer;
}
.ke-visor-b:hover { background: rgba(240,227,204,.24); }

.ke-visor-cerrar, .ke-visor-nav {
  position: absolute; z-index: 2;
  background: rgba(13,10,8,.55); color: #f0e3cc;
  border: 1px solid rgba(240,227,204,.3); border-radius: 50%;
  width: 44px; height: 44px; font-size: 26px; line-height: 1;
  display: grid; place-items: center; cursor: pointer;
}
.ke-visor-cerrar { top: -6px; right: -6px; font-size: 22px; }
.ke-visor-nav--izq { left: -14px; top: 38%; }
.ke-visor-nav--der { right: -14px; top: 38%; }
.ke-visor-cerrar:hover, .ke-visor-nav:hover { background: rgba(13,10,8,.85); }
.ke-visor-cerrar:focus-visible, .ke-visor-nav:focus-visible, .ke-visor-b:focus-visible {
  outline: 2px solid #f0e3cc; outline-offset: 2px;
}
@media (max-width: 640px) {
  .ke-visor-nav--izq { left: 2px; }
  .ke-visor-nav--der { right: 2px; }
  .ke-visor-cerrar { top: 2px; right: 2px; }
}

/* Barra de herramientas del catálogo */
.ke-herramientas {
  display: flex; flex-wrap: wrap; gap: var(--e12); align-items: center;
  margin-bottom: var(--e16);
}
.ke-herramientas .ke-campo { max-width: 280px; margin: 0; }
.ke-herramientas label {
  display: flex; align-items: center; gap: 7px;
  font-size: 15px; color: var(--ke-tinta-2); cursor: pointer;
}
.ke-herramientas input[type=checkbox] { width: 18px; height: 18px; }

/* ══ Botoneras y altas de varias personas ═══════════════════════════════════ */

.ke-botonera { display: flex; flex-wrap: wrap; gap: var(--e8); align-items: center; }
.ke-botonera--min { gap: 5px; }
.ke-boton--min { padding: 5px 11px; min-height: 0; font-size: 14px; }

/* Una persona por fila. En pantalla estrecha los campos se apilan: tres campos de 190 px no
   caben en un móvil y se quedarían recortados a la mitad. */
.ke-fila-persona {
  display: grid;
  grid-template-columns: 1fr 1.3fr 0.9fr auto;
  gap: var(--e10);
  align-items: end;
  margin-bottom: var(--e10);
}
.ke-fila-persona .ke-campo { margin: 0; }
@media (max-width: 700px) {
  .ke-fila-persona {
    grid-template-columns: 1fr auto;
    padding-bottom: var(--e12);
    border-bottom: 1px solid var(--ke-borde);
  }
  .ke-fila-persona label { grid-column: 1 / -1; }
  .ke-fila-persona .ke-quitar-fila { grid-column: 2; justify-self: end; }
}

.ke-quitar-fila {
  width: 34px; height: 38px;
  background: none; border: 1px solid var(--ke-borde); border-radius: 4px;
  color: var(--ke-tinta-2); font-size: 19px; line-height: 1; cursor: pointer;
}
.ke-quitar-fila:hover { border-color: var(--ke-acento); color: var(--ke-acento); }

/* ══ Galería del evento ═════════════════════════════════════════════════════ */

.ke-soltar {
  display: flex; flex-direction: column; gap: 5px; align-items: center; text-align: center;
  padding: 30px 20px;
  border: 2px dashed var(--ke-borde-sel); border-radius: var(--r-tarjeta);
  background: var(--ke-tarjeta);
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.ke-soltar strong { font-family: var(--ke-titulo); font-size: 18px; letter-spacing: .03em; }
.ke-soltar span { color: var(--ke-tinta-2); font-size: 15px; max-width: 46ch; }
.ke-soltar:hover, .ke-soltar:focus-visible { background: #f6efe1; border-color: var(--ke-acento); }
.ke-soltar--encima {
  background: #f2e4d2; border-color: var(--ke-acento); border-style: solid;
}

.ke-progreso { margin-top: var(--e14); }
.ke-progreso__txt { margin: 0 0 6px; font-size: 15px; color: var(--ke-tinta-2); }
.ke-progreso__barra {
  height: 8px; border-radius: 4px; background: #e2d5bf; overflow: hidden;
}
.ke-progreso__barra span {
  display: block; height: 100%; width: 0;
  background: var(--ke-acento); transition: width .25s;
}

.ke-gfoto { position: relative; padding: 0; overflow: hidden; cursor: grab; }
.ke-gfoto:active { cursor: grabbing; }
.ke-gfoto .ke-foto { aspect-ratio: 1 / 1; }
.ke-gfoto .ke-ficha__pie { padding: 8px; }
.ke-gfoto .ke-pie-foto { margin: 0; font-size: 14px; padding: 6px 8px; min-height: 0; }
.ke-gfoto:hover .ke-esquina, .ke-gfoto:focus-within .ke-esquina { opacity: 1; }
/* Mientras se lleva de sitio: translúcida, para ver dónde va a caer. */
.ke-gfoto--movida { opacity: .35; }

/* ══ La galería dentro de la invitación ═════════════════════════════════════ */

/* Mosaico que se adapta solo. Las fotos escaneadas vienen en vertical y en horizontal mezcladas,
   así que la altura es fija y el recorte va al centro: en un mosaico con alturas distintas la
   vista salta y cuesta seguirlo. */
.ke-inv__galeria {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
  margin: 18px 0 26px;
}
.ke-inv__galeria figure { margin: 0; position: relative; }
.ke-inv__galeria img {
  width: 100%; height: 165px; object-fit: cover; display: block;
  border-radius: 3px; background: #e7dbc7;
  cursor: zoom-in;
  transition: transform .18s, box-shadow .18s;
}
.ke-inv__galeria img:hover { transform: scale(1.02); box-shadow: 0 5px 16px rgba(43,33,26,.28); }
/* El hueco pendiente de la galería: caja punteada que enseña qué foto va ahí.
   El trazo discontinuo es el lenguaje universal de «suelta aquí tu fichero». */
.ke-inv__hueco {
  display: flex; align-items: center; justify-content: center;
  min-height: 150px; border: 2px dashed rgba(43,33,26,.35);
  border-radius: 6px; background: rgba(43,33,26,.04);
  text-align: center; padding: 14px;
}
.ke-inv__hueco > div { display: grid; gap: 4px; font-size: 14px; color: var(--ke-tinta-2); }
.ke-inv__hueco-icono { font-size: 26px; opacity: .55; line-height: 1; }
.ke-inv__hueco small { font-size: 11.5px; opacity: .7; }
.ke-inv__galeria figcaption {
  margin-top: 5px; font-size: 13px; line-height: 1.35;
  color: var(--ke-tinta-2); text-align: center;
}
@media (max-width: 520px) {
  .ke-inv__galeria { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 8px; }
  .ke-inv__galeria img { height: 135px; }
}
@media (prefers-reduced-motion: reduce) {
  .ke-inv__galeria img { transition: none; }
  .ke-inv__galeria img:hover { transform: none; }
}

/* ══ El croquis del recinto ═════════════════════════════════════════════════ */

.ke-plano-caja {
  background: var(--ke-tarjeta);
  border: 1px solid var(--ke-borde);
  border-radius: var(--r-tarjeta);
  padding: 10px;
  margin-bottom: var(--e12);
}
.ke-plano { width: 100%; height: auto; display: block; }

.ke-plano__z { cursor: pointer; }
.ke-plano__z polygon { transition: filter .15s; }
.ke-plano__z:hover polygon { filter: brightness(1.16); }
.ke-plano__z:focus { outline: none; }
/* El foco se marca en el polígono, no con el contorno del navegador: sobre un SVG el outline
   dibuja un rectángulo que no tiene nada que ver con la forma de la zona. */
.ke-plano__z:focus-visible polygon,
.ke-plano__z--puesta polygon { stroke: #241d18; stroke-width: 4; filter: brightness(1.16); }

/* El rótulo de cada zona. El cuerpo lo pone el servidor según lo ancha que sea la
   forma, así que aquí NO se fija: `font-size` va en el atributo `style` de cada uno.
   El halo del color del fondo es lo que lo hace legible encima de un polígono de
   color —sin él, las letras se pierden justo donde el borde cambia de tono—. */
.ke-plano__i {
  font-family: var(--ke-texto); font-weight: 600; pointer-events: none;
  paint-order: stroke fill;
  stroke: rgba(30, 22, 14, .38); stroke-width: 3px; stroke-linejoin: round;
}
/* En las zonas claras el halo tiene que ser claro, o el texto oscuro se emborrona. */
.ke-plano__z--otro .ke-plano__i { stroke: rgba(255, 250, 240, .75); }
/* El rótulo que va FUERA de su forma cae sobre el fondo crema del plano, así que
   su halo tiene que ser crema —con el oscuro se emborronaría—. */
.ke-plano__i--fuera { stroke: rgba(243, 237, 225, .9); stroke-width: 3.5px; }
.ke-plano__n { font: 13px/1 var(--ke-titulo); pointer-events: none; }

/* Lo que dice la zona al pulsarla. Altura mínima reservada: sin ella, el texto aparece y empuja
   media pantalla hacia abajo justo cuando acabas de tocar. */
.ke-plano-dice {
  min-height: 3em; margin: 0 0 var(--e12);
  font-size: 16px; line-height: 1.5; color: var(--ke-tinta-2);
}
.ke-plano-dice strong { color: var(--ke-tinta); }

.ke-plano-leyenda {
  display: flex; flex-wrap: wrap; gap: 6px 18px;
  margin: 0 0 var(--e24); padding: 0; list-style: none;
  font-size: 14px; color: var(--ke-tinta-2);
}
.ke-plano-leyenda li { display: flex; align-items: center; gap: 7px; }
.ke-plano-leyenda span {
  width: 14px; height: 14px; border-radius: 3px; display: inline-block;
  border: 1px solid rgba(43,33,26,.25);
}
@media (prefers-reduced-motion: reduce) { .ke-plano__z polygon { transition: none; } }
.ke-plano__c { font: 13px/1 var(--ke-texto); letter-spacing: .08em; pointer-events: none; }

/* ══ Dedicatorias ═══════════════════════════════════════════════════════════ */

.ke-dedi {
  margin-bottom: var(--e16);
  cursor: grab;
  transition: box-shadow .15s;
}
.ke-dedi:active { cursor: grabbing; }
.ke-dedi[hidden] { display: none; }
.ke-dedi--movida { opacity: .4; }

.ke-dedi__cab {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: var(--e12); margin-bottom: var(--e12); flex-wrap: wrap;
}
.ke-dedi__autor { margin: 0; font-size: 17px; display: flex; align-items: center; gap: 8px; }
.ke-dedi__punto {
  width: 11px; height: 11px; border-radius: 50%; flex: none;
  border: 1px solid rgba(43,33,26,.3);
}
.ke-dedi__estado { flex: none; }

/* El botón de información: parece texto, se comporta como botón. Un icono más en una fila que ya
   tiene cinco botones se pierde; aquí la propia fecha es lo que se pulsa. */
.ke-dedi__info {
  background: none; border: 0; padding: 0;
  font: inherit; color: var(--ke-tinta-3);
  text-decoration: underline dotted; cursor: pointer;
}
.ke-dedi__info:hover { color: var(--ke-acento); }

.ke-dedi__reproductor { background: #241d18; border-radius: 6px; overflow: hidden; }
.ke-dedi__reproductor video {
  width: 100%; max-height: 340px; display: block; background: #241d18;
}
.ke-dedi__reproductor audio { display: block; width: 100%; padding: 10px; }

.ke-dedi__foto { width: 100%; max-height: 340px; object-fit: contain; border-radius: 6px;
                 background: #e7dbc7; display: block; }
.ke-dedi__texto {
  margin: 0; padding: 14px 18px; background: var(--ke-fondo);
  border-left: 3px solid var(--ke-borde-sel); border-radius: 0 6px 6px 0;
  font-size: 17px; line-height: 1.6;
}
.ke-dedi__pie { margin-top: var(--e12); }

/* ── El recortador ─────────────────────────────────────────────────────────── */
.ke-recorte {
  margin-top: var(--e14); padding-top: var(--e14);
  border-top: 1px solid var(--ke-borde);
}
.ke-recorte[hidden] { display: none; }
.ke-recorte__leyenda { margin: 0 0 var(--e12); font-size: 14px; color: var(--ke-tinta-2); }

.ke-recorte__barra {
  position: relative; height: 34px; border-radius: 6px;
  background: linear-gradient(var(--ke-borde-sel), var(--ke-borde));
  margin: 0 12px var(--e10);
}
/* Lo que se va a tirar, en gris encima de la barra: se ve de un golpe cuánto se está quitando. */
.ke-recorte__fuera {
  position: absolute; top: 0; bottom: 0;
  background: rgba(43,33,26,.55);
  pointer-events: none;
}
.ke-recorte__fuera--izq { left: 0; border-radius: 6px 0 0 6px; }
.ke-recorte__fuera--der { right: 0; border-radius: 0 6px 6px 0; }

.ke-recorte__tirador {
  position: absolute; top: -5px; width: 16px; height: 44px;
  margin-left: -8px; padding: 0;
  background: var(--ke-acento); border: 2px solid #fbf6ec; border-radius: 5px;
  cursor: ew-resize; touch-action: none;
  box-shadow: 0 2px 6px rgba(0,0,0,.3);
}
.ke-recorte__tirador:focus-visible { outline: 3px solid var(--ke-tinta); outline-offset: 2px; }

.ke-recorte__cifras {
  display: flex; flex-wrap: wrap; gap: 6px 20px;
  margin: 0 0 var(--e12); font-size: 15px; color: var(--ke-tinta-2);
}
.ke-recorte__cifras strong { color: var(--ke-tinta); font-variant-numeric: tabular-nums; }

.ke-visor-video { max-width: 100%; max-height: 78vh; border-radius: 6px; background: #241d18; }

/* ══ Mandar una dedicatoria, desde la invitación ════════════════════════════ */

.ke-dedi-form {
  background: var(--ke-tarjeta);
  border: 1px solid var(--ke-borde);
  border-radius: var(--r-tarjeta);
  padding: 18px;
  margin: 0 0 26px;
}
.ke-dedi-form .ke-campo { margin-bottom: 0; }
.ke-dedi-form__elegir {
  display: flex; flex-wrap: wrap; gap: var(--e10);
  margin: var(--e14) 0 0;
}
/* Los <label> que hacen de botón necesitan el cursor: sin él no parecen pulsables. */
.ke-dedi-form__elegir label { cursor: pointer; }

/* ── Elegir qué trozo del vídeo se manda, desde la invitación ─────────────
   Clase propia y no la del recortador del panel: aquel usa tiradores absolutos
   sobre una barra, y aquí van dos `input[type=range]` superpuestos porque esto
   lo toca un invitado con el dedo, de pie, y un range nativo ya trae el
   arrastre, el teclado y el lector de pantalla resueltos.

   `pointer-events` va en el PULGAR y no en el carril: si el range de arriba
   captase toda su caja, se tragaría los toques del de abajo y solo se podría
   mover uno de los dos. */
#dedi-recorte { display: grid; gap: 10px; margin-top: 4px; }
#dedi-recorte-video { width: 100%; max-height: 46vh; border-radius: 6px;
                      background: #241d18; display: block; }
.ke-inv-recorte { position: relative; height: 34px; }
.ke-inv-recorte input[type="range"] {
  position: absolute; inset: 0; width: 100%; margin: 0; height: 34px;
  background: none; -webkit-appearance: none; appearance: none; pointer-events: none;
}
.ke-inv-recorte input[type="range"]::-webkit-slider-runnable-track {
  height: 6px; border-radius: 3px; background: var(--ke-borde);
}
.ke-inv-recorte input[type="range"]::-moz-range-track {
  height: 6px; border-radius: 3px; background: var(--ke-borde);
}
.ke-inv-recorte input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; pointer-events: auto; cursor: ew-resize;
  width: 22px; height: 22px; border-radius: 50%; margin-top: -8px;
  background: var(--ke-acento); border: 2px solid #fbf6ec;
  box-shadow: 0 2px 6px rgba(0,0,0,.3);
}
.ke-inv-recorte input[type="range"]::-moz-range-thumb {
  pointer-events: auto; cursor: ew-resize;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--ke-acento); border: 2px solid #fbf6ec;
}
/* El segundo no repinta el carril: si lo hiciera taparía al primero. */
.ke-inv-recorte input[type="range"]:last-child::-webkit-slider-runnable-track { background: none; }
.ke-inv-recorte input[type="range"]:last-child::-moz-range-track { background: none; }
#dedi-recorte-ok[disabled] { opacity: .5; cursor: not-allowed; }

.ke-inv__reglas { margin: 0 0 18px; padding-left: 1.1rem; }
.ke-inv__reglas li { margin-bottom: 4px; }
.ke-dedi-form__txt { margin: var(--e14) 0 8px; font-size: 16px; }
.ke-dedi-form__error {
  margin: var(--e12) 0 0; padding: 11px 14px;
  background: var(--ke-mal-fondo); border: 1px solid var(--ke-mal-borde);
  border-radius: 6px; color: var(--ke-mal-tinta); font-size: 15px; line-height: 1.5;
}
.ke-dedi-form__ya {
  margin: 0 0 var(--e14); padding: 11px 14px;
  background: var(--ke-ok-fondo); border: 1px solid var(--ke-ok-borde);
  border-radius: 6px; color: var(--ke-ok-tinta); font-size: 16px;
}

/* ══ La portada de apertura ═════════════════════════════════════════════════ */

/* Mientras la portada está puesta, el cuerpo no se desplaza: si no, al abrir en el móvil se ve
   media invitación asomando por debajo y se pierde el efecto de telón. */
body.ke-cerrado { overflow: hidden; }

.ke-portada {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  padding: 24px 20px;
  background: #1a1512;
  transition: opacity .55s ease, transform .55s ease;
}
.ke-portada--fuera { opacity: 0; transform: scale(1.06); pointer-events: none; }

.ke-portada__fondo {
  position: absolute; inset: 0;
  background: #241d18 center/cover no-repeat;
  /* Sepia y algo desenfocada: la foto es el ambiente, no el contenido. Nítida compite con el
     texto y no se lee ni una cosa ni la otra. */
  filter: sepia(.45) saturate(.85) brightness(.55) blur(1px);
  transform: scale(1.04);   /* tapa el borde claro que deja el desenfoque */
}
.ke-portada__velo {
  position: absolute; inset: 0;
  background: radial-gradient(ellipse at center, rgba(26,21,18,.35) 0%, rgba(26,21,18,.88) 78%);
}

.ke-portada__centro {
  position: relative;
  text-align: center; color: #f0e3cc;
  max-width: 560px;
}
.ke-portada__ante {
  display: block; font-size: 13px; letter-spacing: .3em; text-transform: uppercase;
  color: var(--ke-sobre-oscuro-2); margin-bottom: 14px;
}
.ke-portada__titulo {
  font: 400 clamp(24px, 6.4vw, 50px)/1.12 var(--ke-titulo);
  margin: 0 0 6px; color: #f6efe1;
  text-shadow: 0 2px 14px rgba(0,0,0,.55);
  /* Bevan es muy ancha y un título largo se sale por los lados de un móvil estrecho. Con esto
     parte por donde toque en vez de desbordar, y `balance` reparte las líneas en vez de dejar
     una palabra sola abajo. */
  overflow-wrap: break-word;
  text-wrap: balance;
  max-width: 100%;
}
.ke-portada__nombres {
  margin: 0 0 14px;
  font: clamp(19px, 5vw, 26px)/1.25 var(--ke-texto);
  color: var(--ke-laton); font-style: italic;
  overflow-wrap: break-word;
}
.ke-portada__fecha {
  margin: 0 0 18px; font-size: clamp(16px, 4vw, 19px);
  color: var(--ke-sobre-oscuro);
}
.ke-portada__para {
  margin: 18px 0 0; font-size: 15px; color: var(--ke-sobre-oscuro-2);
  font-style: italic;
}

.ke-cuenta {
  display: flex; justify-content: center; gap: 22px; flex-wrap: wrap;
  margin: 0 0 8px; color: var(--ke-sobre-oscuro);
}
.ke-cuenta__parte { font-size: 14px; letter-spacing: .04em; }
.ke-cuenta__parte strong {
  display: block; font: 400 30px/1.15 var(--ke-titulo); color: var(--ke-laton);
  font-variant-numeric: tabular-nums;
}

.ke-portada__botones {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  margin-top: 26px;
}
.ke-portada__abrir {
  font-size: 18px; padding: 15px 34px;
}
.ke-portada__abrir span { opacity: .8; font-size: 15px; }
.ke-portada__silencio {
  background: none; border: 0; padding: 6px;
  color: var(--ke-sobre-oscuro-2); font: inherit; font-size: 15px;
  text-decoration: underline; cursor: pointer;
}
.ke-portada__silencio:hover { color: var(--ke-sobre-oscuro); }
.ke-portada__pie {
  margin: 20px auto 0; font-size: 13px; line-height: 1.55;
  color: var(--ke-sobre-oscuro-2); max-width: 44ch;
}

/* ── El botón de sonido, siempre a mano ────────────────────────────────────── */
.ke-son {
  position: fixed; right: 14px; bottom: 14px; z-index: 80;
  display: flex; align-items: center; gap: 7px;
  padding: 9px 14px;
  background: rgba(26,21,18,.86); color: var(--ke-sobre-oscuro);
  border: 1px solid rgba(240,227,204,.28); border-radius: 22px;
  font: 14px/1 var(--ke-texto); cursor: pointer;
  backdrop-filter: blur(4px);
}
.ke-son:hover { background: rgba(26,21,18,.96); }
.ke-son--on { color: var(--ke-laton); border-color: rgba(185,138,60,.55); }
.ke-son__icono { font-size: 15px; }
.ke-son:focus-visible { outline: 2px solid var(--ke-laton); outline-offset: 2px; }
@media (max-width: 420px) { .ke-son__txt { display: none; } }

@media (prefers-reduced-motion: reduce) {
  .ke-portada { transition: none; }
  .ke-portada--fuera { opacity: 0; transform: none; }
}

/* ══ El plano de mesas ══════════════════════════════════════════════════════ */

.ke-plano-caja2 {
  display: grid;
  grid-template-columns: 260px 1fr;
  gap: var(--e16);
  align-items: start;
}
@media (max-width: 900px) {
  /* En pantalla estrecha la lista va ARRIBA, no al lado: abajo obligaría a arrastrar a ciegas
     hacia un sitio que no se ve. */
  .ke-plano-caja2 { grid-template-columns: 1fr; }
  .ke-sinsitio { max-height: 230px; }
}

.ke-sinsitio {
  background: var(--ke-tarjeta); border: 1px solid var(--ke-borde);
  border-radius: var(--r-tarjeta); padding: var(--e14);
  max-height: 72vh; overflow-y: auto;
  position: sticky; top: var(--e14);
}
.ke-sinsitio h2 { margin: 0 0 10px; font-size: 17px; }

.ke-personas { list-style: none; margin: 0; padding: 0; }
.ke-persona {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 8px;
  padding: 7px 9px; margin-bottom: 5px;
  background: var(--ke-fondo);
  border: 1px solid var(--ke-borde);
  border-left: 4px solid var(--color, #5c4b38);
  border-radius: 5px;
  font-size: 15px; line-height: 1.3;
  cursor: grab;
}
.ke-persona:active { cursor: grabbing; }
.ke-persona:hover { border-color: var(--ke-borde-sel); }
.ke-persona--movida { opacity: .4; }
.ke-persona--elegida {
  outline: 2px solid var(--ke-acento); outline-offset: 1px;
  background: #f6e6d8;
}
.ke-persona__n { font-weight: 600; }
.ke-persona__n .ke-pie { font-weight: 400; }
.ke-persona__fam { grid-column: 1 / -1; font-size: 13px; color: var(--ke-tinta-3); }
.ke-persona__marcas { display: flex; gap: 4px; font-size: 13px; }
.ke-m-alim   { color: #b9782a; }
.ke-m-animal { color: #7a5a1c; }
.ke-m-movil  { color: #4a6b7c; }

.ke-plano-lienzo {
  background: var(--ke-tarjeta); border: 1px solid var(--ke-borde);
  border-radius: var(--r-tarjeta); padding: var(--e14);
  overflow-x: auto;
}
#ke-mesas {
  width: 100%; height: auto; display: block;
  /* Por debajo de esto los nombres de las sillas dejan de leerse y el plano no sirve para nada:
     antes que encogerlo más, que la caja tenga barra horizontal. */
  min-width: 460px;
  max-height: 68vh;
  touch-action: manipulation;
}

.ke-silla { cursor: pointer; }
.ke-silla circle { transition: r .12s, stroke-width .12s; }
.ke-silla:hover circle:first-of-type { stroke-width: 0.09; }
.ke-silla:focus { outline: none; }
.ke-silla:focus-visible circle:first-of-type { stroke: #241d18; stroke-width: 0.1; }
.ke-silla--diana circle:first-of-type { fill: #9c3f22; stroke: #241d18; stroke-width: 0.1; }
.ke-silla__txt { pointer-events: none; user-select: none; }

/* Mientras se coloca a alguien, las sillas libres piden ser vistas y las ocupadas se apagan:
   de un vistazo se sabe dónde se puede soltar. */
.ke-mesas--colocando .ke-silla:not(.ke-silla--ocupada) circle:first-of-type {
  stroke: var(--ke-acento); stroke-width: 0.09;
}
.ke-mesas--colocando .ke-silla--ocupada { opacity: .45; }

.ke-mesa__etq { pointer-events: none; user-select: none; font-family: var(--ke-texto); }
.ke-mesa--movida .ke-mesa__tablero { opacity: .75; }
.ke-mesa--choca .ke-mesa__tablero { stroke: #8c2f16; stroke-width: 0.12; }
.ke-zona text { pointer-events: none; user-select: none; font-family: var(--ke-texto); }
.ke-mesa__etq--edit:hover { fill: var(--ke-acento); text-decoration: underline; }

/* Pestañas del plano: 2D y 3D */
.ke-vistas { display: flex; gap: 4px; margin-bottom: var(--e12); }
.ke-vista {
  padding: 7px 16px; border: 1px solid var(--ke-borde); border-bottom: 0;
  border-radius: 6px 6px 0 0; background: var(--ke-fondo);
  font: 15px var(--ke-texto); color: var(--ke-tinta-2); cursor: pointer;
}
.ke-vista--on {
  background: var(--ke-tarjeta); color: var(--ke-tinta); font-weight: 600;
  border-color: var(--ke-borde-sel);
}
.ke-vista:focus-visible { outline: 2px solid var(--ke-acento); outline-offset: 1px; }

/* ══ El menú ════════════════════════════════════════════════════════════════ */

.ke-menu-cab { display: flex; gap: var(--e8); align-items: center; flex-wrap: wrap; }
.ke-menu-cab .ke-campo { flex: 1 1 200px; min-width: 0; }

.ke-platos { list-style: none; margin: var(--e12) 0 0; padding: 0; }
.ke-platos li { margin-bottom: 6px; }
.ke-plato-fila {
  display: grid;
  grid-template-columns: 1fr 200px auto auto;
  gap: var(--e8); align-items: center;
}
.ke-plato-fila .ke-campo { margin: 0; }
@media (max-width: 720px) {
  .ke-plato-fila { grid-template-columns: 1fr auto; }
  .ke-plato-fila .ke-campo:first-of-type { grid-column: 1 / -1; }
}

/* El menú en la invitación */
.ke-inv__platos { list-style: none; margin: 8px 0 0; padding: 0; }
.ke-inv__platos li {
  padding: 7px 0; border-top: 1px solid rgba(0,0,0,.08);
  font-size: 17px; line-height: 1.45;
}
.ke-inv__platos li:first-child { border-top: 0; }
/* El aviso del plato, en su propia línea y con color: es lo que busca quien no puede comer algo,
   y perdido dentro del renglón no se ve. */
.ke-inv__aviso {
  display: block; font-size: 14px; color: var(--ke-tinta-2); font-style: italic;
}
.ke-inv__pdte { border-left: 3px solid var(--ke-pdte-borde); }

/* ══ La lista de regalos ════════════════════════════════════════════════════ */

.ke-regalos { list-style: none; margin: 16px 0 0; padding: 0; }
.ke-regalo {
  display: flex; align-items: center; justify-content: space-between; gap: var(--e12);
  flex-wrap: wrap;
  padding: 12px 14px; margin-bottom: 8px;
  background: var(--ke-tarjeta); border: 1px solid var(--ke-borde);
  border-radius: var(--r-tarjeta);
  font-size: 17px;
}
.ke-regalo__n { flex: 1 1 200px; }
/* Cogido por otro: apagado pero legible. Tacharlo lo haría ilegible justo cuando alguien está
   comprobando si el suyo sigue libre. */
.ke-regalo--cogido { opacity: .68; }
.ke-regalo--mio {
  opacity: 1; border-color: var(--ke-ok-borde); background: var(--ke-ok-fondo);
}
.ke-regalo--mio .ke-regalo__n { font-weight: 600; }

/* Lo contratado, en la invitación */
.ke-inv__extras { list-style: none; margin: 14px 0 26px; padding: 0; }
.ke-inv__extras li {
  padding: 11px 14px; margin-bottom: 8px;
  background: var(--ke-tarjeta); border: 1px solid var(--ke-borde);
  border-left: 3px solid var(--ke-laton);
  border-radius: var(--r-tarjeta); font-size: 17px; line-height: 1.45;
}

/* ══ Los tablones, en la invitación ═════════════════════════════════════════ */

.ke-tablon {
  background: var(--ke-tarjeta); border: 1px solid var(--ke-borde);
  border-radius: var(--r-tarjeta); margin-bottom: 10px;
  overflow: hidden;
}
.ke-tablon > summary {
  padding: 14px 16px; cursor: pointer; font-size: 17px; line-height: 1.4;
  list-style: none;
}
.ke-tablon > summary::-webkit-details-marker { display: none; }
/* La flechita a la derecha, no la del navegador: cambia de forma según el sistema y con el texto
   a varias líneas se queda descolgada arriba. */
.ke-tablon > summary::after {
  content: '▾'; float: right; color: var(--ke-tinta-3); font-size: 15px;
}
.ke-tablon[open] > summary::after { content: '▴'; }
.ke-tablon > summary:hover { background: var(--ke-fondo); }

.ke-tablon__msgs { list-style: none; margin: 0; padding: 0 16px; }
.ke-tablon__msgs li {
  padding: 12px 0; border-top: 1px solid var(--ke-borde);
}
.ke-tablon__quien {
  margin: 0 0 4px; font-size: 14px;
  display: flex; justify-content: space-between; gap: var(--e10); flex-wrap: wrap;
}
.ke-tablon__quien span { color: var(--ke-tinta-3); }
.ke-tablon__txt { margin: 0; font-size: 16px; line-height: 1.55; overflow-wrap: anywhere; }
.ke-tablon__vacio { color: var(--ke-tinta-3); font-style: italic; font-size: 15px; }

.ke-tablon__form { padding: 14px 16px 16px; border-top: 1px solid var(--ke-borde); }
.ke-tablon__form .ke-campo { margin-bottom: 8px; }
.ke-tablon__form textarea { resize: vertical; }

/* Moderación */
.ke-mod-msg { padding: 10px 0; border-top: 1px solid var(--ke-borde); }
.ke-mod-msg--oculto { opacity: .55; }
.ke-mod-msg__cab {
  display: flex; gap: var(--e10); align-items: baseline; flex-wrap: wrap;
  font-size: 14px; margin-bottom: 4px;
}

/* ══ El asistente de la invitación ══════════════════════════════════════════ */

.ke-chat {
  background: var(--ke-tarjeta); border: 1px solid var(--ke-borde);
  border-radius: var(--r-tarjeta); padding: 14px; margin: 14px 0 26px;
}
/* Altura acotada y desplazamiento propio: si creciera sin fin, cada respuesta empujaría media
   invitación hacia abajo y habría que volver a buscar dónde estaba uno. */
.ke-chat__hilo {
  max-height: 320px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 8px;
}
.ke-chat__hilo:empty { display: none; }

.ke-chat__msg {
  max-width: 84%; padding: 9px 13px; border-radius: 12px;
  font-size: 16px; line-height: 1.5; white-space: pre-line; overflow-wrap: anywhere;
}
.ke-chat__msg--yo {
  align-self: flex-end; background: var(--ke-acento); color: #fff;
  border-bottom-right-radius: 3px;
}
.ke-chat__msg--ia {
  align-self: flex-start; background: var(--ke-fondo); border: 1px solid var(--ke-borde);
  border-bottom-left-radius: 3px;
}
.ke-chat__msg--nose { background: var(--ke-pdte-fondo); border-color: var(--ke-pdte-borde); }

.ke-chat__sug { display: flex; flex-wrap: wrap; gap: 6px; margin: 12px 0; }
.ke-chat__form { display: flex; gap: 8px; }
.ke-chat__form .ke-campo { flex: 1 1 auto; min-width: 0; margin: 0; }

/* ══ Subtítulos de las dedicatorias ═════════════════════════════════════════ */

.ke-subs { margin-top: var(--e12); padding-top: var(--e12); border-top: 1px solid var(--ke-borde); }
.ke-subs summary { cursor: pointer; font-size: 15px; }
.ke-subs__lineas { margin-top: var(--e10); max-height: 260px; overflow-y: auto; }
.ke-subs__linea { display: flex; gap: 8px; align-items: center; margin-bottom: 5px; }
.ke-subs__linea .ke-campo { margin: 0; font-size: 15px; padding: 6px 9px; min-height: 0; }
/* La marca de tiempo es un botón: lleva el vídeo a ese momento. Con aspecto de enlace porque no
   compite con los botones de acción de abajo. */
.ke-subs__t {
  flex: none; width: 52px; padding: 4px 0;
  background: none; border: 0; cursor: pointer;
  font: 13px/1 ui-monospace, Consolas, monospace; color: var(--ke-acento);
  text-decoration: underline dotted;
}
.ke-subs__t:hover { color: var(--ke-tinta); }

/* ── Recados de los anfitriones y consultas privadas ─────────────────────────
   Los recados se leen como una nota dejada encima de la mesa, no como un aviso
   del sistema: papel, un filete de latón a la izquierda y nada más. El que va
   dirigido SOLO a esa familia se distingue, porque es el que más importa. */
.ke-inv__recado {
  margin: 0 0 14px; padding: 14px 16px;
  border-left: 3px solid var(--ke-laton, #a9853f);
  border-radius: 0 6px 6px 0; background: rgba(43,33,26,.04);
}
.ke-inv__recado h3 { margin: 0 0 6px; font-size: 17px; }
.ke-inv__recado p  { margin: 0; line-height: 1.55; }
.ke-inv__recado--tuyo { background: rgba(169,133,63,.12); border-left-width: 4px; }
.ke-inv__solo {
  display: inline-block; margin-top: 8px; font-size: 11.5px; letter-spacing: .08em;
  text-transform: uppercase; opacity: .7;
}

/* La charla con los anfitriones: quién habla se ve por el lado, no por un nombre. */
.ke-inv__charla { display: flex; flex-direction: column; gap: 10px; margin: 12px 0 16px; }
.ke-inv__globo { padding: 10px 13px; border-radius: 12px; max-width: 86%; }
.ke-inv__globo p { margin: 3px 0 0; line-height: 1.5; }
.ke-inv__globo--tuyo { align-self: flex-end;   background: rgba(169,133,63,.16); }
.ke-inv__globo--suyo { align-self: flex-start; background: rgba(43,33,26,.06); }
.ke-inv__quien { font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase; opacity: .65; }
.ke-inv__aviso {
  margin: 0 0 12px; padding: 10px 13px; border-radius: 6px;
  background: var(--ke-ok-fondo, #e6efdd); color: var(--ke-ok-tinta, #2f4a22);
  border: 1px solid var(--ke-ok-borde, #c3d8b2);
}

/* ── Adjuntar ficheros a una conversación ────────────────────────────────────
   La caja de elegir no es un <input file> pelado: ese control no se puede vestir
   y en el móvil se ve distinto en cada teléfono. Aquí el input va oculto dentro
   de una etiqueta con aspecto de botón, que es lo que se toca. */
.ke-adj { margin: 10px 0 0; }
.ke-adj__elegir {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  padding: 8px 14px; border: 1px dashed rgba(43,33,26,.4); border-radius: 8px;
  font-size: 14px; color: var(--ke-tinta-2, #6b5b4a); background: rgba(43,33,26,.03);
}
.ke-adj__elegir:hover { border-color: var(--ke-laton, #a9853f); color: inherit; }
.ke-adj__lista { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 8px; }
.ke-adj__item {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 8px; border: 1px solid rgba(43,33,26,.14); border-radius: 8px;
}
.ke-adj__item img { width: 44px; height: 44px; object-fit: cover; border-radius: 5px; }
.ke-adj__icono {
  width: 44px; height: 44px; display: grid; place-items: center; border-radius: 5px;
  background: rgba(43,33,26,.08); font-size: 12px; font-weight: 700;
}
.ke-adj__nombre { flex: 1; min-width: 0; font-size: 13px; overflow: hidden;
                  text-overflow: ellipsis; white-space: nowrap; }
.ke-adj__quitar { border: 0; background: none; cursor: pointer; font-size: 15px;
                  color: var(--ke-tinta-2, #6b5b4a); padding: 4px 6px; }
.ke-adj__quitar:hover { color: #b3261e; }
.ke-adj__aviso { margin: 8px 0 0; font-size: 12.5px; }

/* Lo ya enviado, dentro del globo de la conversación */
.ke-adj-ver, .ke-inv__adj { display: block; margin-top: 8px; max-width: 260px; }
.ke-adj-ver img, .ke-inv__adj img,
.ke-adj-ver video, .ke-inv__adj video {
  display: block; width: 100%; height: auto; border-radius: 8px;
}
.ke-adj-doc, .ke-inv__adj-doc {
  display: inline-block; margin-top: 8px; padding: 7px 11px; border-radius: 8px;
  background: rgba(43,33,26,.07); font-size: 13.5px; text-decoration: none; color: inherit;
}
.ke-adj-doc:hover, .ke-inv__adj-doc:hover { background: rgba(169,133,63,.18); }

/* ── Avatares con marco ──────────────────────────────────────────────────────
   Cuatro maneras de vestir la misma foto. El tono lo pone cada perfil con
   --tono, así que el marco es una sola regla y no cuatro juegos de colores.
   Vale igual en el panel y en la invitación. */
.ke-avatar {
  position: relative; flex: none; width: 74px; height: 74px; border-radius: 50%;
  display: grid; place-items: center; overflow: hidden;
  background: color-mix(in srgb, var(--tono, #8a5f10) 16%, #fff);
  color: var(--tono, #8a5f10); font-family: Georgia, 'Times New Roman', serif; font-size: 30px;
}
.ke-avatar img { width: 100%; height: 100%; object-fit: cover; }
.ke-avatar--aro    { box-shadow: 0 0 0 2px var(--tono); }
.ke-avatar--filete { box-shadow: 0 0 0 2px var(--tono), 0 0 0 5px #fff, 0 0 0 6px var(--tono); }
.ke-avatar--sombra { box-shadow: 0 4px 14px color-mix(in srgb, var(--tono) 55%, transparent); }
/* El festón se dibuja con una máscara de puntos: el borde ondulado de siempre,
   sin imagen ni SVG de por medio. */
.ke-avatar--feston {
  box-shadow: 0 0 0 2px var(--tono);
  -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 66%, transparent 67%),
                      repeating-conic-gradient(from 0deg, #000 0 12deg, transparent 12deg 24deg);
          mask-image: radial-gradient(circle at 50% 50%, #000 66%, transparent 67%),
                      repeating-conic-gradient(from 0deg, #000 0 12deg, transparent 12deg 24deg);
  -webkit-mask-composite: source-over;
          mask-composite: add;
}

/* Quién os invita, en la invitación */
.ke-inv__anfitriones { display: flex; gap: 22px; justify-content: center; flex-wrap: wrap;
                       margin: 6px 0 14px; }
.ke-inv__quien-es { display: grid; justify-items: center; gap: 7px; }
.ke-inv__quien-nombre { font-size: 14px; letter-spacing: .06em; }
.ke-inv__saludo {
  margin: 0 auto 22px; max-width: 34rem; text-align: center;
  font-family: var(--ke-display, Georgia, serif); font-size: 18px; line-height: 1.5;
  color: var(--ke-tinta-2, #6b5b4a);
}

/* ── Los temas de la invitación ──────────────────────────────────────────────
   Un tema es solo un juego de variables. No cambia dónde está cada cosa, así que
   añadir uno nuevo es este bloque y una entrada en Temas.php — nada más, y sin
   poder romper la invitación de nadie.

   El panel NO se tiñe: `data-tema` solo se pone en el cuerpo de la invitación. */
body[data-tema="oeste"] {
  --ke-fondo: #e8dcc6; --ke-tarjeta: #f6ecd8; --ke-borde: #cbb28a; --ke-borde-sel: #b08f5c;
  --ke-acento: #8a4b1e; --ke-laton: #a9762f;
  --ke-tinta: #2e2318; --ke-tinta-2: #5b4630; --ke-tinta-3: #6b543a;
}
body[data-tema="jardin"] {
  --ke-fondo: #eaeee4; --ke-tarjeta: #f7faf3; --ke-borde: #c9d5c0; --ke-borde-sel: #a8bd9c;
  --ke-acento: #4d6b52; --ke-laton: #7d8f5e;
  --ke-tinta: #242b23; --ke-tinta-2: #47543f; --ke-tinta-3: #56634d;
}
body[data-tema="rosa"] {
  --ke-fondo: #f6ecee; --ke-tarjeta: #fdf7f8; --ke-borde: #e2c8cf; --ke-borde-sel: #cba7b1;
  --ke-acento: #a04a63; --ke-laton: #b1798c;
  --ke-tinta: #2c2126; --ke-tinta-2: #59414a; --ke-tinta-3: #6a4f59;
}
body[data-tema="azul"] {
  --ke-fondo: #e9eef2; --ke-tarjeta: #f7fafc; --ke-borde: #c4d3de; --ke-borde-sel: #9db6c7;
  --ke-acento: #3f5d78; --ke-laton: #6d8ba5;
  --ke-tinta: #1f2830; --ke-tinta-2: #3f5060; --ke-tinta-3: #4d6070;
}
/* El oscuro cambia el sentido de las tintas, no solo el tono: sobre fondo negro,
   «tinta» tiene que ser clara o no se lee nada. */
body[data-tema="noche"] {
  --ke-fondo: #16150f; --ke-tarjeta: #201e17; --ke-borde: #3a352a; --ke-borde-sel: #6b5a3a;
  --ke-acento: #d9b877; --ke-laton: #d9b877;
  --ke-tinta: #f2ece0; --ke-tinta-2: #cdc3b1; --ke-tinta-3: #b3a894;
  --ke-sobre-oscuro: #f2ece0; --ke-sobre-oscuro-2: #cdc3b1;
  --ke-ok-fondo: #24301f;  --ke-ok-borde: #3d5133;  --ke-ok-tinta: #cfe0c2;
  --ke-pdte-fondo: #322a18; --ke-pdte-borde: #574726; --ke-pdte-tinta: #e8d4a5;
  --ke-mal-fondo: #33211d;  --ke-mal-borde: #573731;  --ke-mal-tinta: #eec4b8;
}
body[data-tema="noche"] .ke-inv { box-shadow: 0 10px 40px rgba(0,0,0,.5); }

/* El selector de tema */
.ke-temas { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.ke-tema { display: block; cursor: pointer; }
.ke-tema input { position: absolute; opacity: 0; pointer-events: none; }
.ke-tema__caja {
  /* `display: block` y no por gusto: esto es un <span>, o sea inline, y un contenedor
     inline NO envuelve a los bloques que lleva dentro. Con la tira de colores en flex
     y el nombre en bloque, el borde y el fondo se quedaban en una línea de texto y el
     contenido se salía por encima del de al lado: las muestras aparecían flotando
     sobre los nombres y «El de ahora» caía en la tarjeta equivocada. */
  display: block;
  border: 2px solid var(--ke-borde); border-radius: 10px; padding: 14px;
  background: var(--ke-tarjeta); transition: border-color 200ms, transform 200ms;
}
.ke-tema:hover .ke-tema__caja { transform: translateY(-2px); }
.ke-tema input:checked + .ke-tema__caja { border-color: var(--ke-acento); }
.ke-tema input:focus-visible + .ke-tema__caja { outline: 2px solid var(--ke-acento); outline-offset: 2px; }
.ke-tema__tiras { display: flex; height: 46px; border-radius: 7px; overflow: hidden; margin-bottom: 10px; }
.ke-tema__tiras span { flex: 1; }
.ke-tema__elegido { font-size: 12px; letter-spacing: .1em; text-transform: uppercase;
                    color: var(--ke-acento); }

/* ── Quién más viene ─────────────────────────────────────────────────────────
   El cartel explicativo va ABIERTO mientras la familia no haya decidido, y se
   pliega solo cuando ya ha dicho que sí: nadie debería descubrir después que su
   nombre se veía. */
.ke-inv__cartel {
  margin: 0 0 16px; padding: 12px 14px; border-radius: 8px;
  background: rgba(43,33,26,.05); border: 1px solid var(--ke-borde);
}
.ke-inv__cartel summary { cursor: pointer; font-size: 14px; letter-spacing: .04em; }
.ke-inv__cartel > div { margin-top: 10px; }
.ke-inv__cartel p { margin: 0 0 8px; font-size: 14.5px; line-height: 1.55; }
.ke-inv__cartel p:last-child { margin-bottom: 0; }

.ke-inv__social { display: grid; gap: 10px; margin-top: 18px; }
.ke-inv__vecino {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 11px 13px; border-radius: 10px; background: rgba(43,33,26,.04);
}
.ke-inv__vecino img, .ke-inv__vecino-inicial {
  width: 48px; height: 48px; border-radius: 50%; flex: none; object-fit: cover;
}
.ke-inv__vecino-inicial {
  display: grid; place-items: center; background: rgba(169,133,63,.2);
  font-family: var(--ke-titulo); font-size: 21px; color: var(--ke-acento);
}
.ke-inv__vecino strong { display: block; }
.ke-inv__vecino-n { font-size: 12.5px; color: var(--ke-tinta-3); }
.ke-inv__vecino p { margin: 5px 0 0; font-size: 14.5px; line-height: 1.5; }

/* El aviso de cookies: abajo, discreto, y sin tapar la invitación. Un banner que
   ocupa media pantalla en un móvil hace que la gente acepte sin leer, que es
   justo lo contrario de lo que se busca. */
.ke-cookies {
  position: fixed; left: 10px; right: 10px; bottom: 10px; z-index: 60;
  max-width: 560px; margin: 0 auto; padding: 14px 16px; border-radius: 12px;
  background: #201d18; color: #f0e8da; box-shadow: 0 8px 30px rgba(0,0,0,.4);
  font-size: 14px; line-height: 1.5;
}
.ke-cookies p { margin: 0 0 12px; }
.ke-cookies a { color: #e0c07d; }
.ke-cookies__botones { display: flex; gap: 8px; flex-wrap: wrap; }
.ke-cookies button {
  flex: 1 1 auto; min-height: 42px; padding: 8px 16px; border: 0; border-radius: 8px;
  background: #d9b877; color: #23201a; font: inherit; font-weight: 600; cursor: pointer;
}
.ke-cookies__no { background: transparent !important; color: #cdc3b1 !important;
                  border: 1px solid #4a443a !important; }

/* Los dos botones de coger un regalo: llevarlo con nombre o sin decir quiénes sois.
   Van juntos y el segundo es más discreto, porque firmar es lo habitual. */
.ke-regalo__coger { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
@media (max-width: 460px) {
  .ke-regalo__coger { width: 100%; }
  .ke-regalo__coger .ke-boton { flex: 1 1 auto; }
}

/* ── El editor ───────────────────────────────────────────────────────────────
   Con lo justo: negrita, cursiva, listas y enlaces. Una barra con veinte botones
   invita a maquetar, y esto es para escribir cuatro líneas a los invitados. */
.ke-editor { padding: 0; overflow: hidden; }
.ke-ed__barra {
  display: flex; gap: 2px; padding: 5px 6px;
  border-bottom: 1px solid var(--ke-borde); background: rgba(43,33,26,.04);
}
.ke-ed__barra button {
  min-width: 32px; height: 30px; border: 0; border-radius: 5px; cursor: pointer;
  background: transparent; color: var(--ke-tinta-2); font-size: 14px; line-height: 1;
}
.ke-ed__barra button:hover { background: rgba(43,33,26,.1); color: var(--ke-tinta); }
.ke-ed__b { font-weight: 800; }
.ke-ed__i { font-style: italic; font-family: Georgia, serif; }
.ke-ed__zona { min-height: 108px; padding: 10px 12px; outline: none; line-height: 1.55; }
.ke-ed__zona:empty::before { content: attr(data-pista); color: var(--ke-tinta-3); }
.ke-ed__zona p { margin: 0 0 8px; }
.ke-ed__zona ul, .ke-ed__zona ol { margin: 0 0 8px; padding-left: 22px; }

/* Y el texto ya guardado, con su formato */
.ke-inv__rico p { margin: 0 0 8px; line-height: 1.55; }
.ke-inv__rico p:last-child { margin-bottom: 0; }
.ke-inv__rico ul, .ke-inv__rico ol { margin: 0 0 8px; padding-left: 22px; }
.ke-inv__rico a { color: var(--ke-acento); }

/* La cesión de imagen, dentro de la confirmación. Enmarcada y algo aparte del
   resto: es una pregunta de otra naturaleza y conviene que se lea, no que se
   marque de corrido con las demás. */
.ke-inv__cesion {
  margin: 20px 0 0; padding: 13px 15px; border-radius: 8px;
  border: 1px solid var(--ke-borde); background: rgba(43,33,26,.04);
}
.ke-inv__cesion label { display: flex; gap: 10px; align-items: flex-start; cursor: pointer; }
.ke-inv__cesion input { margin-top: 3px; flex: none; }
.ke-inv__cesion-pie { margin: 9px 0 0; font-size: 13px; line-height: 1.5;
                      color: var(--ke-tinta-3); }

/* ══ El tablón: hilos, fotos y acciones ═════════════════════════════════════ */

/* Las respuestas, un solo nivel y con su línea a la izquierda. Un nivel basta:
   anidar respuestas de respuestas acaba en una escalera de márgenes que no cabe
   en un móvil de 360 px, y esto se lee de pie y con una mano. */
.ke-tablon__hilo {
  list-style: none; margin: 10px 0 0; padding: 0 0 0 14px;
  border-left: 2px solid var(--ke-borde);
  display: grid; gap: 12px;
}
.ke-tablon__msg + .ke-tablon__msg { margin-top: 14px; }

.ke-tablon__acciones {
  display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: center;
  margin-top: 6px;
}
.ke-tablon__retirar { display: inline; margin: 0; }
.ke-tablon__enlace {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: 14px; color: var(--ke-tinta-2);
  text-decoration: underline; text-underline-offset: 3px;
}
.ke-tablon__enlace:hover { color: var(--ke-tinta); }
.ke-tablon__contestando {
  margin: 0 0 8px; font-size: 14px; color: var(--ke-tinta-2);
  background: var(--ke-borde-sel); border-radius: 6px; padding: 6px 10px;
}

/* Las fotos, como si estuvieran sobre la mesa. El giro va en `--giro` y lo pone
   PHP a partir del id: así una foto cae siempre igual y no baila al recargar,
   que es lo que pasaría eligiéndolo al azar en el navegador. */
.ke-polas { display: flex; flex-wrap: wrap; gap: 14px; margin: 10px 0 4px; padding: 4px 0; }
.ke-pola {
  display: block; background: #fbf8f1; padding: 7px 7px 22px;
  border-radius: 2px; box-shadow: 0 2px 8px rgba(0,0,0,.28);
  transform: rotate(var(--giro, 0deg));
  transition: transform .18s ease, box-shadow .18s ease;
}
.ke-pola:hover, .ke-pola:focus-visible {
  transform: rotate(0deg) scale(1.03); box-shadow: 0 6px 18px rgba(0,0,0,.34);
}
.ke-pola img { display: block; width: 132px; height: 132px; object-fit: cover; background: #ddd; }
.ke-tablon__doc {
  display: inline-block; padding: 7px 12px; border-radius: 6px;
  border: 1px solid var(--ke-borde); text-decoration: none; font-size: 14px;
}

@media (prefers-reduced-motion: reduce) {
  .ke-pola { transform: none; transition: none; }
  .ke-pola:hover, .ke-pola:focus-visible { transform: none; }
}

/* Un mensaje destacado: sube arriba del tablón y lo dice. Es para lo que hay que
   leer sí o sí —la hora del autocar, la cuenta del regalo— y que si no se pierde
   detrás de veinte respuestas. */
.ke-tablon__destacado {
  margin: 0 0 4px; font-size: 14px; font-weight: 600;
  color: var(--ke-acento);
}
.ke-tablon__mover { display: inline-block; }
.ke-tablon__mover select { font-size: 14px; padding: 2px 6px; min-height: 0; }
.ke-tablon--nuevo { margin-top: 6px; }

/* ══ Voz: grabar, dictar y caritas ══════════════════════════════════════════ */

.ke-voz { margin-top: 8px; }
.ke-voz__botones { display: flex; flex-wrap: wrap; gap: 8px; }
.ke-voz__eco { margin: 6px 0 0; min-height: 1.2em; }

/* La rejilla de caritas: tamaño de dedo, que esto se usa en un móvil. */
.ke-voz__caritas {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
  gap: 4px; margin-top: 8px; padding: 8px;
  border: 1px solid var(--ke-borde); border-radius: 8px;
  max-height: 190px; overflow-y: auto;
}
.ke-voz__caritas button {
  font-size: 22px; line-height: 1; padding: 8px 0;
  background: none; border: 0; border-radius: 6px; cursor: pointer;
}
.ke-voz__caritas button:hover { background: var(--ke-borde-sel); }

.ke-voz__previa { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 8px; }
.ke-voz__previa audio { max-width: 100%; }

/* Una nota de voz recibida. Ancho completo en el móvil: los controles nativos
   se aprietan y el de avanzar deja de poder cogerse. */
.ke-audio { width: 100%; max-width: 340px; margin: 6px 0 2px; display: block; }

/* Lo adjunto dentro de la conversación con los celebrantes. Ancho tope y no el
   del globo: una foto de plano a pantalla completa aplasta el resto del hilo. */
.ke-hilo__foto { display: block; max-width: 100%; width: 260px; height: auto;
                 border-radius: 6px; margin: 6px 0 2px; }
.ke-hilo__video { display: block; max-width: 100%; width: 320px; border-radius: 6px;
                  margin: 6px 0 2px; background: #241d18; }

/* ══ La ficha propia, arriba a la derecha ═══════════════════════════════════ */
/* Clase aparte y no `.ke-avatar`: aquel es el de los perfiles de invitados, de
   74 px y con sus marcos de fiesta. Este es de barra: pequeño y sin adorno. */

.ke-yo { display: inline-flex; align-items: center; gap: 8px; text-decoration: none;
         color: inherit; min-width: 0; }
.ke-yo:hover span:last-child { text-decoration: underline; }
.ke-yo > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ke-yo__foto {
  width: 30px; height: 30px; border-radius: 50%; flex: 0 0 auto;
  object-fit: cover; background: var(--ke-borde-sel);
  display: inline-flex; align-items: center; justify-content: center;
}
/* Las iniciales, para quien no ha puesto foto: se distingue igual de bien y no
   obliga a nadie a dar su cara. */
.ke-yo__foto--letras {
  font-size: 12px; font-weight: 600; color: var(--ke-tinta);
  border: 1px solid var(--ke-borde);
}
.ke-yo__foto--grande { width: 116px; height: 116px; font-size: 40px; }

/* La cara de quien escribe, dentro del globo. Pequeña —24 px— porque el nombre
   ya está al lado: aquí sirve para reconocer de un vistazo, no para mirarla. */
.ke-hilo__cara { width: 24px; height: 24px; font-size: 10px; vertical-align: -6px;
                 margin-right: 5px; }

/* ══ La sala en 3D ══════════════════════════════════════════════════════════
   Faltaba ENTERO, y por eso el 3D salía descentrado y sin poder manejarse:

   `<sala-3d>` es un elemento propio, y un elemento propio sin estilo es `inline`.
   Dentro, three.js llama a `setSize(w, h, false)` —el `false` significa «no
   toques el CSS del lienzo, que ya lo controla la hoja de estilos»—. Como esa
   hoja no existía, el lienzo se pintaba a su tamaño intrínseco: 1131 × 780 px
   dentro de un hueco de 764, empezando en mitad de la pantalla. Se salía por la
   derecha y por abajo, así que solo se veía su esquina y la escena parecía
   descentrada y atascada.

   Con esto el elemento ocupa su hueco, el lienzo lo llena, y `medir()` lee unas
   medidas que son las de verdad. */
sala-3d {
  display: block; position: relative;
  /* Apaisado a propósito: las salas de la casa son alargadas —La Carpa mide
     20 × 8— y en un lienzo cuadrado el montaje queda pequeño con bandas de prado
     arriba y abajo. Con la proporción parecida a la de la sala, lo mismo se ve
     mucho mayor sin tocar la cámara. */
  width: 100%; aspect-ratio: 16 / 9; height: auto;
  max-height: min(70vh, 620px);
  min-height: 320px;
  border-radius: var(--r-tarjeta, 8px); overflow: hidden;
  background: #241d18;
}
sala-3d canvas {
  display: block; width: 100%; height: 100%;
  touch-action: none;   /* el dedo mueve la cámara, no la página */
}

/* En pantalla completa manda la ventana entera. */
sala-3d:fullscreen, sala-3d:-webkit-full-screen {
  width: 100vw; height: 100vh; border-radius: 0;
}

@media (max-width: 720px) {
  sala-3d { height: min(58vh, 460px); }
}

/* ── La demo, marcada ────────────────────────────────────────────────────────
   En AZUL, y no es un capricho: toda la paleta de la casa es cálida (cremas y
   tierras) y los tres estados ya se reparten el verde, el ámbar y el rojo. Un
   cuarto tono cálido se leería como «otro estado más» en vez de como «esto no
   es real», que es justo lo que hay que entender sin leer.
   El color va acompañado de la palabra «Demostración»: quien no distinga el
   azul tiene que enterarse igual. */
:root {
  --ke-demo-tinta: #1f4f6b;
  --ke-demo-borde: #4a7f9e;
  --ke-demo-fondo: #e3edf3;
}

.ke-tarjeta--demo {
  border: 2px solid var(--ke-demo-borde);
  background:
    linear-gradient(var(--ke-demo-fondo), var(--ke-demo-fondo)) top / 100% 5px no-repeat,
    var(--ke-tarjeta);
  padding-top: 18px;
}

.ke-pastilla--demo {
  background: var(--ke-demo-fondo);
  border-color: var(--ke-demo-borde);
  color: var(--ke-demo-tinta);
  font-weight: 700;
  letter-spacing: .04em;
}

/* La banda de dentro del evento: la lleva cada pantalla de la demo, para que no
   haya forma de estar dentro y no saber en qué se está. */
.ke-banda-demo {
  display: flex;
  gap: 10px;
  align-items: baseline;
  flex-wrap: wrap;
  margin: 0 0 16px;
  padding: 10px 14px;
  border: 2px solid var(--ke-demo-borde);
  border-radius: var(--r-tarjeta);
  background: var(--ke-demo-fondo);
  color: var(--ke-demo-tinta);
}
.ke-banda-demo strong { letter-spacing: .04em }
.ke-banda-demo span   { font-size: .94rem }

/* Una tarjeta que reclama algo. Borde ámbar, no rojo: falta gente por mandar su vídeo, que es
   una tarea pendiente, no una avería. El rojo aquí gastaría la única señal de alarma que tiene
   la aplicación en algo que no lo es. */
.ke-falta {
  border-left: 4px solid var(--ke-pdte-borde);
  background: linear-gradient(var(--ke-pdte-fondo), var(--ke-pdte-fondo)) left / 100% 100% no-repeat;
  background-blend-mode: normal;
}
.ke-falta a { color: var(--ke-pdte-tinta) }

/* ── La lista de canciones ───────────────────────────────────────────────────── */
.ke-canciones {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: cancion;
}

.ke-cancion {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  margin-bottom: 8px;
  background: var(--ke-tarjeta);
  border: 1px solid var(--ke-borde);
  border-radius: var(--r-tarjeta);
  counter-increment: cancion;
}

/* El número va en un pseudoelemento y no en el marcado: al reordenar arrastrando, la
   numeración se recalcula sola sin tocar el DOM ni tener que renumerar nada a mano. */
.ke-cancion::before {
  content: counter(cancion);
  min-width: 1.6em;
  text-align: right;
  font-family: var(--ke-titulo);
  color: var(--ke-tinta-3, var(--ke-tinta-2));
}

.ke-cancion__asa {
  cursor: grab;
  color: var(--ke-tinta-2);
  font-size: 1.2rem;
  line-height: 1;
  user-select: none;
}
.ke-cancion.es-llevando { opacity: .45 }
.ke-cancion__que       { flex: 1 1 auto; min-width: 0 }
.ke-cancion__titulo    { margin: 0; font-weight: 600 }
.ke-cancion__quien     { margin: 2px 0 0; font-size: .9rem; color: var(--ke-tinta-2) }
.ke-cancion__trozo     { font-variant-numeric: tabular-nums }

.ke-cancion__botones {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* Una canción quitada no desaparece: se queda apagada y se puede devolver. Borrarla de la
   vista obligaría a recordar de memoria qué se quitó y por qué. */
.ke-cancion.es-quitada { opacity: .55 }
.ke-cancion.es-quitada .ke-cancion__titulo { text-decoration: line-through }

@media (max-width: 620px) {
  .ke-cancion { flex-wrap: wrap }
  .ke-cancion__botones { width: 100%; justify-content: flex-start }
  /* En el móvil no se ordena arrastrando —el arrastre nativo no va—, así que el asa sobra
     y solo estorbaría al pulsar. */
  .ke-cancion__asa { display: none }
}

/* ── La ventana de oír una canción ───────────────────────────────────────────── */
.ke-modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(0, 0, 0, .62);
}
.ke-modal[hidden] { display: none }

.ke-modal__caja {
  width: min(620px, 100%);
  max-height: 90vh;
  overflow: auto;
  padding: 16px;
  background: var(--ke-tarjeta);
  border-radius: var(--r-flotante);
  box-shadow: var(--s-flotante);
}
.ke-modal__cab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.ke-recorte { margin-top: 14px }
.ke-recorte label { display: block; margin-bottom: 8px }
.ke-recorte input[type=range] { width: 100%; margin-top: 4px }

/* El campo de duracion a mano, debajo de las sugerencias. */
.ke-dur__mano {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 10px;
}

/* La lista de canciones dentro de la tarjeta de una lista: la misma idea, en pequeño. */
.ke-canciones--mini { counter-reset: cancion; margin: 0 0 10px }
.ke-canciones--mini .ke-cancion {
  padding: 5px 8px;
  margin-bottom: 4px;
  gap: 8px;
  font-size: .93rem;
  background: var(--ke-fondo);
}
.ke-canciones--mini .ke-cancion::before { min-width: 1.2em; font-size: .85em }
.ke-canciones--mini .ke-cancion__que { flex: 1 1 auto }
/* El asa se ve al pasar por encima: en una tarjeta pequeña, tres puntos en cada fila son ruido
   permanente para una acción que se usa una vez. */
.ke-canciones--mini .ke-cancion__asa { opacity: .35; transition: opacity .12s }
.ke-canciones--mini .ke-cancion:hover .ke-cancion__asa { opacity: 1 }
