/* ==========================================================================
   Living Water · estilos del sitio (LOOP.md 5.1, 5.3 a 5.5)
   Reset, tipografía, retícula y componentes base. Los valores salen de la
   maqueta del demo ("futurista mínima"); aquí solo cambian los tokens, que
   viven en tokens.css. El armazón (cabecera, menú, pie, flotantes, cortina,
   "Sigue", barra de la maqueta, rótulos y entrada de página) va en su propio
   bloque, antes de "Movimiento reducido".

   Reglas: hover de 200 a 250 ms, nada de degradados ni sombras sólidas,
   controles de 44 px o más, texto de 13 px o más (12 px solo en rótulos
   monoespaciados en mayúsculas), foco de 2 px del acento.
   ========================================================================== */

/* ---- Base ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
/* Texto solo para el lector de pantalla ("pestaña nueva", títulos en otro
   idioma): fuera de la vista, pero en el árbol de accesibilidad. */
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
html {
  color-scheme: var(--scheme);
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 400 16px/1.6 var(--f-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
img, svg, video { display: block; max-width: 100%; }
img, video { height: auto; }
a { color: inherit; text-underline-offset: .2em; text-decoration-thickness: 1px; }
h1, h2, h3, h4, p, figure, blockquote, ul, ol, dl, dd { margin: 0; }
ul, ol { padding: 0; list-style: none; }
button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; }
strong, b { font-weight: var(--w-body-strong); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px; }
::selection { background: var(--accent); color: var(--accent-fg); }

/* ---- Tipografía -----------------------------------------------------------
   h1 y h2 usan --f-display; h3 y el texto grande que no es titular usan
   --f-head. Las clamp() van literales: desde que el sistema tiene una sola
   tipografía (2026-09-18) ya no hay factor de escala por juego. */
:where(h1), .h1 {
  font-family: var(--f-display);
  font-weight: var(--w-display);
  font-size: clamp(35px, 9.2vw, 124px);
  line-height: .98;
  letter-spacing: var(--track-display);
  text-wrap: balance;
}
:where(h2), .h2 {
  font-family: var(--f-display);
  font-weight: var(--w-display);
  font-size: clamp(30px, 4.6vw, 66px);
  line-height: 1.04;
  letter-spacing: calc(var(--track-display) * .8);
  text-wrap: balance;
}
:where(h3), .h3 {
  font-family: var(--f-head);
  font-weight: var(--w-head);
  font-size: clamp(19px, 1.7vw, 24px);
  line-height: 1.25;
  letter-spacing: var(--track-head);
}
/* Titulares de dos tonos: la segunda frase va en <span class="dim">. */
.dim { color: var(--dim); }
.lead { font-size: clamp(17px, 1.45vw, 21px); line-height: 1.55; color: var(--muted); max-width: 56ch; }
.text { color: var(--muted); max-width: 62ch; }
.small { font-size: 14px; color: var(--muted); }
.mono { font-family: var(--f-mono); font-variant-numeric: tabular-nums; }
/* Datos: fechas, horarios, teléfonos, EIN. */
.data { font: 400 14px/1.5 var(--f-mono); font-variant-numeric: tabular-nums; }

/* Rótulo: monoespaciada 12 px en mayúsculas con el cuadrito del acento. */
.label {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font: 500 12px/1.4 var(--f-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
}
.label::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 1px;
  background: var(--accent);
  flex: none;
}
.label.plain::before { content: none; }
.label a { display: inline-flex; align-items: center; min-height: 24px; text-decoration: none; }
.label a:hover { color: var(--fg); }
.label img { width: 20px; height: 20px; border-radius: 4px; flex: none; }

/* Cita: el texto grande que no es titular usa --f-head. */
.quote {
  font-family: var(--f-head);
  font-weight: var(--w-display);
  font-size: clamp(23px, 3.1vw, 44px);
  line-height: 1.22;
  letter-spacing: calc(var(--track-display) * .7);
  text-wrap: balance;
}

/* Prosa larga (doctrina, textos legales): 66 caracteres de ancho. */
.prose { display: flex; flex-direction: column; gap: 18px; max-width: 66ch; color: var(--muted); }
.prose :where(h2, h3) { color: var(--fg); margin-top: 14px; }
.prose h2 { font-size: clamp(24px, 2.6vw, 34px); line-height: 1.15; }
.prose > :first-child { margin-top: 0; }
.prose strong { color: var(--fg); }
.prose a { color: var(--fg); text-decoration-color: var(--accent); text-underline-offset: 4px; transition: color var(--t-hover) ease; }
.prose a:hover { color: var(--accent-2); }
.prose ul { display: flex; flex-direction: column; gap: 8px; }
.prose li { display: flex; gap: 12px; }
.prose li::before { content: ""; width: 6px; height: 6px; margin-top: 10px; border-radius: 1px; background: var(--accent); flex: none; }

/* ---- Retícula --------------------------------------------------------------
   Contenedor de 1400 px, 12 columnas con canal de 24 px; riel = columnas 1 a 3
   para el rótulo y 4 a 12 para el contenido. Bajo 900 px todo se apila. */
.wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); }
.sec {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  padding-block: var(--sec);
  border-top: 1px solid var(--line);
}
.grid12 { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: 24px; row-gap: 20px; }
.c-rail { grid-column: 1 / 4; align-self: start; padding-top: clamp(6px, 1.5vw, 24px); }
.c-main { grid-column: 4 / 13; }
.c-half-a { grid-column: 1 / 7; }
.c-half-b { grid-column: 7 / 13; }
.c-full { grid-column: 1 / -1; }
/* La columna de contenido partida en dos: texto (4 a 7) y medio (8 a 12).
   Bajo 1100 px el texto quedaba en unos 300 px: se apilan dentro del riel. */
.c-main-a { grid-column: 4 / 8; }
.c-main-b { grid-column: 8 / 13; }
@media (max-width: 1100px) { .c-main-a, .c-main-b { grid-column: 4 / 13; } }
.v-center { align-items: center; }
@media (max-width: 900px) {
  .c-rail, .c-main, .c-half-a, .c-half-b, .c-main-a, .c-main-b { grid-column: 1 / -1; }
  .c-rail { padding-top: 0; }
}
.stack { display: flex; flex-direction: column; gap: 20px; }
.stack-lg { display: flex; flex-direction: column; gap: clamp(28px, 4vw, 48px); }
.actions { display: flex; flex-wrap: wrap; gap: 12px; }
.split { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 24px 48px; }

/* ---- Botones y chips -------------------------------------------------------
   48 px en píldora; la flecha de 16 px se corre 3 px al pasar el cursor. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  max-width: 100%;
  padding: 0 22px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  font: 500 15px/1.2 var(--f-body);
  text-decoration: none;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--t-hover) ease, border-color var(--t-hover) ease, color var(--t-hover) ease;
}
.btn svg { width: 16px; height: 16px; flex: none; transition: transform var(--t-hover) var(--ease-out); }
.btn:hover svg { transform: translateX(3px); }
.btn-primary { background: var(--accent); color: var(--accent-fg); }
.btn-primary:hover { background: color-mix(in srgb, var(--accent) 86%, var(--fg)); }
.btn-solid { background: var(--fg); color: var(--bg); }
.btn-solid:hover { background: color-mix(in srgb, var(--fg) 84%, var(--bg)); }
/* Los contornos de los controles van en tinta al 24 %: --line casi no se ve
   en oscuro ni sobre la foto de la portada. */
.btn-ghost { background: transparent; color: var(--fg); border-color: color-mix(in srgb, var(--fg) 24%, transparent); }
.btn-ghost:hover { border-color: var(--fg); }
.btn-sm { min-height: 44px; padding: 0 18px; font-size: 14px; }
/* ---- Botones en el teléfono (≤ 560 px) ---------------------------------------
   Regla del sistema (2026-09-19): en un teléfono, un botón es un botón de
   teléfono. Todo .btn de contenido va a todo el ancho, a 52 px de alto y con
   letra de 16 px, y dos botones juntos (.actions) se apilan con el principal
   arriba. Antes convivían 44, 48 y 52 px, unos a todo el ancho y otros chicos
   en línea: un botón chico metido entre el texto se toca mal con el pulgar y
   se pierde. .btn-sm deja de ser más chico aquí: en el teléfono no hay botón
   "secundario por tamaño", la jerarquía la da el relleno (primario, contorno).

   Quedan fuera los que viven en barras compactas o dentro de un componente
   con su propia maqueta: la cabecera y la fila superior del menú y de la
   cortina (.bar, .shell-top), la tarjeta flotante de eventos y el muestrario.
   Los de solo ícono (.icon-btn) y los chips no son .btn. */
@media (max-width: 560px) {
  .btn:not(:is(.bar, .shell-top, .event-float, .kit-inline) .btn) {
    display: flex;
    width: 100%;
    min-height: 52px;
    padding: 10px 20px;
    font-size: 16px;
    white-space: normal;
  }
  /* width: 100% porque .actions suele ser hijo de un .split (flex): sin él se
     encoge al ancho del botón más largo y "a todo el ancho" se queda en nada. */
  .actions { flex-direction: column; align-items: stretch; gap: 10px; width: 100%; }
}

/* Botón de solo ícono: círculo de 44 px (lleva aria-label). */
.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--fg) 24%, transparent);
  background: transparent;
  color: inherit;
  cursor: pointer;
  flex: none;
  text-decoration: none;
  transition: border-color var(--t-hover) ease, background-color var(--t-hover) ease;
}
.icon-btn svg { width: 18px; height: 18px; }
.icon-btn:hover { border-color: var(--fg); }

/* Chip: 44 px, píldora, monoespaciada 13 px. Activo con aria-pressed o aria-current. */
.chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 16px;
  border-radius: var(--r-pill);
  border: 1px solid color-mix(in srgb, var(--fg) 24%, transparent);
  background: transparent;
  color: inherit;
  font: 500 13px/1 var(--f-mono);
  letter-spacing: .02em;
  text-decoration: none;
  cursor: pointer;
  transition: border-color var(--t-hover) ease, background-color var(--t-hover) ease, color var(--t-hover) ease;
}
.chip:hover { border-color: var(--fg); }
.chip[aria-pressed="true"],
.chip[aria-current="page"],
.chip[aria-current="true"] { background: var(--fg); color: var(--bg); border-color: var(--fg); }
.chip img, .chip svg { width: 16px; height: 16px; flex: none; }

/* Interruptor de tema de la cabecera: tres íconos apilados en el mismo botón
   de 44 px (automático, claro, oscuro). El activo lo elige el CSS por
   <html data-theme> —sin el atributo, el tema es automático—, así que el botón
   sale bien desde el primer pintado, sin esperar a site.js. */
.theme-btn { position: relative; }
.theme-btn .t-ico {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  opacity: 0;
  transform: scale(.7) rotate(-40deg);
  transition: opacity .2s var(--ease-out), transform .2s var(--ease-out);
}
html:not([data-theme]) .theme-btn .t-ico[data-t="auto"],
html[data-theme="light"] .theme-btn .t-ico[data-t="light"],
html[data-theme="dark"] .theme-btn .t-ico[data-t="dark"] { opacity: 1; transform: none; }

/* ---- Control segmentado ------------------------------------------------------
   Píldora de 48 px con los segmentos a partes iguales y un pulgar relleno que
   se desliza al activo. El pulgar es un solo elemento absoluto: su ancho sale
   de --seg-n (cuántos segmentos hay) y su posición de --seg-i (cuál está
   marcado), así que no hay que medir nada en JavaScript. El de idioma fija
   --seg-i en el marcado (el idioma no cambia sin recargar) y el de tema lo
   deriva de <html data-theme>, para que también salga bien al primer pintado.
     <div class="seg" style="--seg-n: 3" role="radiogroup" aria-labelledby="…">
       <span class="seg-thumb" aria-hidden="true"></span>
       <button class="seg-item" role="radio" aria-checked="true" …>…</button>
   Los segmentos miden 40 px, pero el área táctil llega a 44 con el relleno. */
.seg {
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  width: 100%;
  max-width: 360px;
  height: 48px;
  padding: 4px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: color-mix(in srgb, var(--panel) 40%, transparent);
}
.seg-thumb {
  position: absolute;
  top: 4px;
  left: 4px;
  z-index: 0;
  width: calc((100% - 8px) / var(--seg-n, 2));
  height: 40px;
  border-radius: var(--r-pill);
  background: var(--fg);
  transform: translateX(calc(var(--seg-i, 0) * 100%));
  transition: transform .25s var(--ease-out);
}
.seg-item {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 0;
  height: 40px;
  padding: 0 8px;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--muted);
  font: 500 14px/1 var(--f-body);
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: color var(--t-hover) ease;
}
.seg-item svg { width: 16px; height: 16px; flex: none; }
.seg-item:hover { color: var(--fg); }
.seg-item[aria-checked="true"],
.seg-item[aria-current="true"] { color: var(--bg); }
/* El anillo de foco va POR DENTRO del segmento: con el offset de fábrica (3 px)
   el foco en "Auto" y el pulgar en "Claro" se leían como dos marcados. */
.seg-item:focus-visible { outline-offset: -3px; }
/* El segmentado del tema saca su posición del mismo atributo que los íconos de
   la cabecera, así que el pulgar ya está donde toca en el primer pintado. */
html:not([data-theme]) [data-theme-seg] { --seg-i: 0; }
html[data-theme="light"] [data-theme-seg] { --seg-i: 1; }
html[data-theme="dark"] [data-theme-seg] { --seg-i: 2; }

/* ---- Filas de datos --------------------------------------------------------
   Teléfonos, correo, dirección, estatus legal: rótulo a la izquierda y el dato
   en monoespaciada. Regla superior en tinta, como las filas. */
.facts { display: flex; flex-direction: column; border-top: 1px solid var(--fg); }
.facts > div {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 5fr);
  align-items: baseline;
  gap: 4px 24px;
  padding-block: 14px;
  border-bottom: 1px solid var(--line);
}
.facts dt { font: 500 12px/1.4 var(--f-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.facts dd { font: 400 14px/1.5 var(--f-mono); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.facts dd small { display: block; font: 400 14px/1.5 var(--f-body); color: var(--muted); }
.facts a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  transition: color var(--t-hover) ease, border-color var(--t-hover) ease;
}
.facts a:hover { color: var(--accent-2); border-color: currentColor; }
@media (max-width: 560px) { .facts > div { grid-template-columns: minmax(0, 1fr); } }

/* ---- Portadas ----------------------------------------------------------------
   .cover: portada con foto (Inicio, LWRC). Panel de radio grande dentro del
   contenedor, foto con la capa de 5.7 y el titular en --sand. Siempre oscura
   (tokens.css). .phead: portada compacta de las páginas interiores. */
.cover {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: clamp(20px, 3vw, 36px);
  min-height: clamp(420px, 72svh, 760px);
  /* Aire bajo la cabecera pegajosa, el mismo de su margin-top (.bar): sin
     él las píldoras quedaban montadas sobre la foto. .phead no lo necesita:
     ya empieza con su propio relleno superior. */
  margin-top: 12px;
  padding: clamp(24px, 5vw, 72px);
  border-radius: var(--r-lg);
  background: var(--bg);
}
.cover > img {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(var(--cover-scale, 1));
}
.cover::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--veil); }
.cover :where(h1, .h1) { color: var(--sand); }
.cover :where(h1, .h1) .dim { display: block; color: var(--dim); }
/* Segundo tono a la mitad del tamaño (Inicio): a tamaño completo el h1 de
   Inicio medía cinco líneas y la portada pasaba de un pantallazo. Nunca baja
   de 24 px (--dim solo va en 24 px o más). El tracking y el espacio entre
   palabras se vuelven a calcular sobre su propio tamaño. */
.cover :where(h1, .h1) .h1-sub {
  margin-top: .3em;
  font-size: max(24px, .5em);
  line-height: 1.04;
  letter-spacing: calc(var(--track-display) * .8);
}
/* Versículo de la portada: la cita y su referencia. */
.verse { display: flex; flex-direction: column; gap: 10px; }
/* Sobre la foto el rótulo y la entradilla van en tinta: --muted no llega a
   4.5:1 donde la foto es clara. */
.cover .label, .cover .lead { color: var(--fg); }
/* La portada ya separa: la sección que la sigue no lleva regla arriba. */
.cover + .sec { border-top: 0; }

.phead {
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 3vw, 36px);
  padding-block: clamp(40px, 6vw, 88px) clamp(44px, 6vw, 84px);
}
.phead :where(h1, .h1) {
  font-size: clamp(34px, 6.6vw, 96px);
  line-height: 1;
  max-width: 17ch;
}

/* ---- Medios ------------------------------------------------------------------
   Radio de medios, object-fit: cover y leyendas de vidrio oscuro. */
.media { position: relative; overflow: hidden; border-radius: var(--r-md); background: var(--panel-2); max-width: 100%; }
.media > img, .media > video { width: 100%; height: 100%; object-fit: cover; }
.media > figcaption {
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 14px;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-end;
  gap: 8px 12px;
  pointer-events: none;
}
/* En el teléfono, una sola leyenda: dos bajan a dos líneas y tapan la foto. */
@media (max-width: 560px) { .media > figcaption > .tag ~ .tag { display: none; } }
.ar-45 { aspect-ratio: 4 / 5; }
.ar-32 { aspect-ratio: 3 / 2; }
.ar-169 { aspect-ratio: 16 / 9; }
.ar-219 { aspect-ratio: 21 / 9; }
@media (max-width: 760px) { .ar-219 { aspect-ratio: 16 / 10; } }

/* Leyenda de vidrio: el único color literal, porque va sobre foto. */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
  padding: 0 12px;
  border-radius: var(--r-pill);
  font: 500 12px/1 var(--f-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--glass-fg);
  background: var(--glass);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

/* Video con póster: el iframe de YouTube se inyecta al pulsar play (U4).
   El play va en la esquina inferior izquierda, no al centro, para no tapar
   lo que el póster trae escrito (el de "Quiénes somos" dice PANAMÁ); las
   leyendas se corren a su derecha y quedan alineadas con él por abajo. */
.video { aspect-ratio: 16 / 9; }
.video > iframe { position: absolute; inset: 0; z-index: 2; width: 100%; height: 100%; border: 0; }
.video > figcaption { left: 110px; min-height: 84px; }
/* La etiqueta "YouTube" del póster es un enlace al video (la pone site.js) y,
   al reproducir, debajo queda "¿No carga? Ver en YouTube": YouTube a veces se
   niega a reproducir incrustado y no se puede saber desde fuera. El ::after
   le da área de toque a la etiqueta sin agrandarla. */
.tag-link { position: relative; display: inline-flex; align-items: center; gap: 6px; text-decoration: none; cursor: pointer; }
.tag-link::after { content: ""; position: absolute; inset: -12px -8px; }
.tag-link svg { width: 12px; height: 12px; flex: none; }
.video-alt { margin-top: 10px; font-size: 14px; color: var(--muted); }
.video-alt a { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; color: var(--fg); text-underline-offset: 4px; }
.video-alt a svg { width: 14px; height: 14px; flex: none; }
.play {
  position: absolute;
  left: 14px;
  bottom: 14px;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--glass-fg) 28%, transparent);
  background: var(--glass);
  color: var(--glass-fg);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  cursor: pointer;
  transition: background-color var(--t-hover) ease, color var(--t-hover) ease, border-color var(--t-hover) ease;
}
.play svg { width: 26px; height: 26px; margin-left: 4px; }
.play:hover { background: var(--accent); color: var(--accent-fg); border-color: transparent; }
/* En el teléfono el póster mide unos 200 px de alto: a 84 px el play rozaba el
   texto del póster, así que baja a 64 px (sigue pasando de 44). */
@media (max-width: 560px) {
  .play { left: 12px; bottom: 12px; width: 64px; height: 64px; }
  .play svg { width: 22px; height: 22px; margin-left: 3px; }
  .video > figcaption { left: 88px; bottom: 12px; min-height: 64px; }
}

/* ---- Marcador de contenido pendiente (D10) ---------------------------------
   <div class="ph" data-need="id-de-PENDIENTES">FALTA · qué · quién</div>
   Toma la forma de lo que reemplaza: .ph-photo (foto 4:5), .ph-text (un
   párrafo de tres líneas), .ph-logo, .ph-wide (bloque 16:9). */
.ph {
  display: grid;
  place-items: center;
  align-content: center;
  min-height: 120px;
  max-width: 100%;
  padding: 20px;
  border-radius: var(--r-md);
  border: 1px dashed var(--faint);
  background: var(--panel-2);
  color: var(--muted);
  font: 500 12px/1.5 var(--f-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  text-align: center;
  overflow-wrap: anywhere;
}
.ph-photo { aspect-ratio: 4 / 5; }
.ph-wide { aspect-ratio: 16 / 9; }
.ph-text { place-items: center start; text-align: left; min-height: 118px; border-radius: var(--r-sm); }
.ph-logo { width: min(100%, 240px); min-height: 0; aspect-ratio: 5 / 2; padding: 12px; border-radius: var(--r-sm); }
/* Dentro de una fila de datos o de un párrafo (EIN, un correo que falta). */
.ph-inline { display: inline-flex; min-height: 32px; padding: 6px 12px; border-radius: var(--r-sm); text-align: left; }

/* ---- Vista de trabajo y vista de presentación (2026-09-19) -------------------
   El mismo sitio en dos vistas. Cuál está puesta lo decide, ANTES del primer
   pintado, el script en línea del <head>, que deja <html data-view="trabajo">
   o <html data-view="presentacion"> (mismo patrón que data-theme).

   - trabajo (de fábrica): se ven los marcadores "FALTA · …". Es la vista de
     todos los días: dice qué contenido falta y a quién pedírselo.
   - presentación (?vista=presentacion): ni un solo marcador, para enseñarle
     el sitio al cliente.

   El contrato entero, con ejemplos, está en docs/revamp/ENTREGA.md, sección
   "Vista de trabajo y vista de presentación":
     .ph                          se oculta en presentación
     [data-only="trabajo"]        solo se ve en trabajo
     [data-only="presentacion"]   solo se ve en presentación
     [data-collapse]              site.js lo esconde en presentación si, sin
                                  los .ph, se queda sin contenido visible
     .empty                       estado vacío diseñado, para ponerlo en su
                                  lugar cuando el hueco se nota                */
:root[data-view="presentacion"] .ph { display: none; }
:root[data-view="presentacion"] [data-only="trabajo"] { display: none; }
/* Con :not() y no con [data-view="trabajo"]: si el script del <head> fallara
   y no hubiera atributo, la vista que se ve tiene que ser la de trabajo. */
:root:not([data-view="presentacion"]) [data-only="presentacion"] { display: none; }
/* Lo que site.js colapsó por quedarse vacío. Va con !important, como [hidden]:
   el elemento puede traer su propio display de una clase más específica. */
[data-collapsed] { display: none !important; }

/* ---- Estado vacío diseñado (.empty) -------------------------------------------
   Va donde, quitado el marcador, queda un hueco que se nota: una lista sin
   entradas, una sección sin material. Sobrio y sin ilustraciones: rótulo
   monoespaciado, un título corto, una línea en --muted y, si hace falta, un
   botón. En una cápsula clara o, con .empty-line, solo con una regla fina
   arriba (para listas y filas, donde un panel pesaría demasiado).
     <div class="empty" data-only="presentacion">
       <span class="label plain">Boletines</span>
       <p class="h3">Pronto, el primero.</p>
       <p class="text">Cuando salga el primer boletín, lo vas a encontrar aquí.</p>
       <a class="btn btn-ghost" href="/es/contacto/">Escríbenos</a>
     </div>                                                                      */
.empty {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  padding: clamp(24px, 3.4vw, 40px);
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--panel);
}
.empty > .label { margin-bottom: 2px; }
.empty .text { color: var(--muted); max-width: 52ch; }
.empty > .btn { margin-top: 10px; }
/* Sin panel: solo la regla fina de arriba. */
.empty-line {
  padding: clamp(24px, 3.4vw, 40px) 0 0;
  border: 0;
  border-top: 1px solid var(--line);
  border-radius: 0;
  background: none;
}

/* ---- Filas (.rows / .row) ----------------------------------------------------
   Ministerios, boletines y preguntas. Columnas 4fr 5fr 2.4fr 44px; al pasar el
   cursor la fila se sangra 12 px y el círculo se llena del acento. */
.rows { border-top: 1px solid var(--fg); }
.row {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 5fr) minmax(0, 2.4fr) 44px;
  align-items: center;
  gap: 8px 24px;
  padding-block: 24px;
  border-bottom: 1px solid var(--line);
  color: inherit;
  text-decoration: none;
  transition: padding var(--t-hover) var(--ease-out);
}
.row:hover { padding-inline: 12px; }
.row-text { color: var(--muted); font-size: 15.5px; }
.row-meta { font: 500 13px/1.4 var(--f-mono); color: var(--muted); text-align: right; }
.row-go {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--fg) 24%, transparent);
  transition: background-color var(--t-hover) ease, color var(--t-hover) ease, border-color var(--t-hover) ease;
}
.row-go svg { width: 16px; height: 16px; }
.row:hover .row-go { background: var(--accent); color: var(--accent-fg); border-color: transparent; }
/* Fila sin .row-text (nombre, dato y flecha): el dato se arrima a la flecha. */
@media (min-width: 761px) {
  .row:not(:has(.row-text)) { grid-template-columns: minmax(0, 1fr) auto 44px; }
}
@media (max-width: 760px) {
  .row { grid-template-columns: minmax(0, 1fr) 44px; padding-block: 20px; }
  .row-title, .row-text, .row-meta { grid-column: 1; }
  .row-meta { text-align: left; }
  .row-go { grid-column: 2; grid-row: 1 / span 3; }
  .row:hover { padding-inline: 0; }
}

/* ---- Cifras (.stats) ---------------------------------------------------------
   Solo con datos que existen. Cuatro columnas; dos en el teléfono. */
.stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border-top: 1px solid var(--fg); }
.stat { display: flex; flex-direction: column; gap: 10px; padding: 24px 20px 0 0; }
.stat + .stat { padding-left: 24px; border-left: 1px solid var(--line); }
.stat strong {
  font-family: var(--f-head);
  font-weight: var(--w-display);
  font-size: clamp(40px, 5.4vw, 80px);
  line-height: 1;
  letter-spacing: var(--track-display);
  font-variant-numeric: tabular-nums;
}
.stat span { font: 500 12px/1.45 var(--f-mono); letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
@media (max-width: 760px) {
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 28px; }
  .stat:nth-child(3) { padding-left: 0; border-left: 0; }
}

/* ---- Nombres en grande (iglesias que apoyan) ---------------------------------
   Texto en lugar de logos mientras no lleguen. Va en --muted, no en --faint:
   son nombres reales y tienen que leerse. Sirve con <span> o como lista
   (<ul class="logos"><li>), que el lector de pantalla anuncia como tal. */
.logos { display: flex; flex-wrap: wrap; align-items: center; gap: 18px clamp(28px, 4.5vw, 64px); color: var(--muted); }
.logos > :is(span, li) { font-family: var(--f-head); font-weight: var(--w-head); font-size: clamp(18px, 1.8vw, 24px); line-height: 1.15; letter-spacing: var(--track-head); }
.logos > :is(span, li):nth-child(2n) { font-weight: 500; font-size: clamp(14px, 1.2vw, 16px); letter-spacing: .14em; text-transform: uppercase; }
.logos > :is(span, li):nth-child(3n) { font-family: var(--f-mono); font-weight: 400; font-size: clamp(15px, 1.3vw, 17px); letter-spacing: 0; text-transform: none; }

/* ---- Cinta de nombres (.marquee) ---------------------------------------------
   Cintas que corren de derecha a izquierda (data-dir="left"), que es como
   se lee: el nombre entra por su principio. En el Inicio van dos apiladas
   (.marquee-rows) en el MISMO sentido, con letra más chica: en una sola
   cinta las 17 iglesias tardaban demasiado en pasar (Daniel, 2026-10-03).
   Dos filas en sentidos opuestos ya se habían probado y la que iba hacia la
   derecha costaba leerla (2026-09-30); data-dir="right" sigue soportado por
   si hiciera falta en otra página.
   La pista va duplicada en el HTML (la copia con aria-hidden) para que el
   bucle no salte: se corre una pista entera y la copia queda justo donde
   estaba la primera. El separador es el cuadrito de 6 px del acento, que va
   detrás de cada nombre (también detrás del último: así el salto entre las dos
   pistas mide lo mismo que el de dentro).
   Sin JS corren con la animación de CSS y se detienen con el cursor encima y
   con el foco dentro. Con JS (.is-js, site.js) la animación se apaga y el
   script mueve las pistas con transform: pausa con el cursor encima, con el
   botón (WCAG 2.2.2) y fuera de pantalla, y deja arrastrar con el mouse o el
   dedo (touch-action: pan-y deja pasar el scroll vertical).
   La máscara desvanece los dos bordes; el contenedor recorta, así que nada
   desborda a 360 px. */
/* El rótulo y el botón de pausa van centrados a la altura de la cinta: el
   riel (.c-rail) se alinea arriba y trae un padding pensado para titulares,
   que aquí dejaba el rótulo más abajo que los nombres. */
.marquee-head { display: flex; align-items: center; gap: 12px 16px; flex-wrap: wrap; align-self: center; padding-top: 0; }
/* Sin esto la pista (que mide su contenido) agrandaría la columna de la
   retícula y la página desbordaría a lo ancho. */
.marquee-col { min-width: 0; }
.marquee-rows { display: grid; gap: 14px; min-width: 0; }
.marquee {
  display: flex;
  min-width: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee-track {
  display: flex;
  align-items: center;
  flex: none;
  min-width: max-content;
  /* 100 s por cinta (8 o 9 iglesias con ciudad y estado, letra de las
     .marquee-rows). Es solo el respaldo sin JS: con JS la velocidad la pone
     site.js en px/s. */
  animation: lw-marquee 100s linear infinite;
}
.marquee-track > li {
  display: flex;
  align-items: center;
  flex: none;
  font-family: var(--f-display);
  font-weight: var(--w-display);
  font-size: clamp(22px, 2.6vw, 36px);
  line-height: 1.25;
  letter-spacing: var(--track-display);
  color: var(--muted);
  white-space: nowrap;
}
/* Apiladas, la letra baja para que las dos filas quepan sin pesar más que
   la cinta sola. */
.marquee-rows .marquee-track > li { font-size: clamp(18px, 1.8vw, 26px); }
.marquee-track > li::after {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 1px;
  background: var(--accent);
  margin-inline: clamp(22px, 3.2vw, 48px);
  flex: none;
}
@keyframes lw-marquee { to { transform: translateX(-100%); } }
.marquee:hover .marquee-track,
.marquee:focus-within .marquee-track { animation-play-state: paused; }
.marquee[data-dir="right"] .marquee-track { animation-direction: reverse; }
/* Con JS manda site.js: sin animación de CSS y con arrastre. */
.marquee.is-js .marquee-track { animation: none; will-change: transform; }
.marquee.is-js { cursor: grab; touch-action: pan-y; user-select: none; -webkit-user-select: none; }
.marquee.is-dragging { cursor: grabbing; }
/* El botón cambia de ícono con aria-pressed: pausa cuando corre, play cuando
   está detenida. */
.marquee-toggle .i-play { display: none; }
.marquee-toggle[aria-pressed="true"] .i-pause { display: none; }
.marquee-toggle[aria-pressed="true"] .i-play { display: block; }

@media (prefers-reduced-motion: reduce) {
  /* Quieta: los nombres quedan en filas que envuelven, como antes, y el botón
     no hace falta (no hay nada que pausar). */
  .marquee { overflow: visible; flex-wrap: wrap; -webkit-mask-image: none; mask-image: none; }
  .marquee-track { animation: none; flex: 1 1 auto; min-width: 0; flex-wrap: wrap; row-gap: 8px; }
  /* Quieta, el cuadrito del último nombre queda colgando. */
  .marquee-track > li:last-child::after { display: none; }
  .marquee-track[aria-hidden="true"],
  .marquee-toggle { display: none; }
  /* Con JS la cinta no corre sola pero sí se arrastra: queda en una fila
     recortada, como la animada, y con su copia para el bucle. */
  .marquee.is-js { overflow: hidden; flex-wrap: nowrap; -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
  .marquee.is-js .marquee-track { flex: none; min-width: max-content; flex-wrap: nowrap; }
  .marquee.is-js .marquee-track > li:last-child::after { display: flex; }
  .marquee.is-js .marquee-track[aria-hidden="true"] { display: flex; }
}

/* ---- Cápsulas ----------------------------------------------------------------
   Panel de esquinas redondas DENTRO del contenedor, nunca banda a sangre.
   .capsule.inv = colores inversos (llamado a donar, LWF USA); .capsule sola =
   panel claro (boletín). */
.capsule {
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 4vw, 56px);
  padding: clamp(28px, 5vw, 72px);
  border-radius: var(--r-lg);
}
.capsule:not(.inv) { background: var(--panel); border: 1px solid var(--line); }
/* Suscripción en línea: correo + botón. */
.nl { display: flex; flex-wrap: wrap; gap: 10px; flex: 1 1 360px; max-width: 560px; }
.nl .input { flex: 1 1 220px; min-width: 0; }
.nl .label { flex: 1 1 100%; }
/* Suscripción con varios campos (.form.nl-form, Inicio) y el texto que la
   acompaña en un .split: los dos al ancho de .nl. */
.nl-copy, .nl-form { flex: 1 1 360px; max-width: 560px; }

/* ---- Galería (.bento) ----------------------------------------------------------
   Doce fotos en cuatro columnas: la 1 ocupa 2×2, la 2 (vertical) una columna
   por dos filas y el resto una celda 3:2. En el teléfono, dos columnas. Cada
   celda es un .media; el botón .open (transparente, encima de la foto) abre el
   visor. */
.bento { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(8px, 1.2vw, 16px); grid-auto-flow: dense; }
.bento > .media { aspect-ratio: 3 / 2; }
.bento > .media:nth-child(1) { grid-column: span 2; grid-row: span 2; }
.bento > .media:nth-child(2) { grid-column: 4; grid-row: 1 / span 2; }
.bento > .media:nth-child(-n+2) { aspect-ratio: auto; }
.bento > .media:nth-child(-n+2) > img { position: absolute; inset: 0; }
.bento .open {
  position: absolute;
  inset: 0;
  z-index: 1;
  border: 0;
  padding: 0;
  background: transparent;
  cursor: zoom-in;
  border-radius: inherit;
}
.bento .open:focus-visible { outline-offset: -4px; }
@media (max-width: 760px) {
  .bento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bento > .media:nth-child(1) { grid-column: 1 / -1; grid-row: auto; aspect-ratio: 3 / 2; }
  .bento > .media:nth-child(2) { grid-column: 1; grid-row: span 2; }
  .bento > .media:nth-child(1) > img { position: static; }
}

/* Visor de la galería: <dialog class="viewer"> a pantalla completa, siempre
   oscuro. El comportamiento (anterior, siguiente, Escape) es de U7. */
.viewer {
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--bg);
}
.viewer[open] { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; }
.viewer::backdrop { background: var(--d-bg); }
.viewer-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: calc(env(safe-area-inset-top, 0px) + 12px) var(--gutter) 12px;
}
.viewer-count { font: 500 13px/1 var(--f-mono); color: var(--muted); }
.viewer-img { display: grid; place-items: center; min-height: 0; padding-inline: var(--gutter); }
.viewer-img img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; border-radius: var(--r-md); }
.viewer-nav { display: flex; justify-content: center; gap: 12px; padding: 12px var(--gutter) calc(env(safe-area-inset-bottom, 0px) + 16px); }

/* ---- Personas (.team / .person) ------------------------------------------------
   Foto 4:5 con radio de medios, nombre en h3, rol en rótulo y bio en --muted.
   Sin tarjeta ni sombra. */
.team {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr));
  gap: clamp(28px, 3vw, 40px) clamp(12px, 1.6vw, 24px);
}
@media (max-width: 560px) { .team { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.person { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.person > .media, .person > .ph { aspect-ratio: 4 / 5; }
.person-info { display: flex; flex-direction: column; gap: 6px; }
.person-info > p { color: var(--muted); font-size: 15px; }

/* ---- Equipo: carrusel (.carousel / .car-*) ------------------------------------
   Una familia a la vez, reusable con data-carousel (site.js, parte 5).
   Sin JS (o sin .is-ready) las cinco diapositivas se ven apiladas, una debajo
   de otra, y los controles no se pintan: el contenido se lee igual.
   Con JS y de 900 px para arriba las cinco ocupan la misma celda y se cruzan
   con un fundido de 500 ms y 24 px de corrida; foto en las columnas 1 a 5 y
   texto en las 7 a 12. Por debajo de 900 px son una pista horizontal con
   scroll-snap (una diapositiva por pantalla) que se desliza con el dedo. */
.carousel { display: flex; flex-direction: column; gap: clamp(24px, 3vw, 40px); min-width: 0; }
.car-stage { display: flex; flex-direction: column; gap: clamp(36px, 6vw, 56px); min-width: 0; }
.car-slide { display: grid; gap: clamp(18px, 2.4vw, 28px); min-width: 0; }
/* 4:5 y radio grande. En el teléfono no pasa de 62svh: con la pantalla llena
   de foto no se vería que debajo hay texto. */
.car-photo { aspect-ratio: 4 / 5; max-height: 62svh; border-radius: var(--r-lg); }
/* team-weets-randy-donna.jpg: la pareja sale chica y al fondo del edificio.
   La foto se agranda un 65 % anclada al borde de abajo, que es donde están
   ellos, para que se vean de cuerpo entero y llenen medio marco. */
.car-photo-zoom > img { transform: scale(1.65); transform-origin: 46% 100%; }
.car-text { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; min-width: 0; }
.car-name { max-width: 14ch; }
.carousel:not(.is-ready) .car-controls { display: none; }

/* Controles: anterior, siguiente, pausa, barra de progreso y miniaturas.
   En escritorio quedan bajo la columna del texto (7 a 12). */
.car-controls { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: 24px; }
.car-bottom { grid-column: 1 / -1; display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.car-nav { display: flex; gap: 8px; }
.car-toggle .i-play { display: none; }
.car-toggle[aria-pressed="true"] .i-pause { display: none; }
.car-toggle[aria-pressed="true"] .i-play { display: block; }
/* Barra de progreso: se llena durante el intervalo y vuelve a cero en cada
   cambio. La pinta site.js con transform, así que se para con el carrusel. */
.car-progress { height: 2px; border-radius: 2px; background: var(--line); overflow: hidden; }
.car-progress > span { display: block; height: 100%; background: var(--accent); transform: scaleX(0); transform-origin: left center; }
.car-thumbs { display: flex; flex-wrap: wrap; gap: 10px; }
.car-thumb {
  width: 56px;
  height: 70px;
  padding: 0;
  border: 0;
  border-radius: 12px;
  overflow: hidden;
  background: var(--panel-2);
  opacity: .62;
  cursor: pointer;
  transition: opacity var(--t-hover) ease, box-shadow var(--t-hover) ease;
}
.car-thumb > img { width: 100%; height: 100%; object-fit: cover; }
.car-thumb:hover { opacity: 1; }
.car-thumb[aria-current="true"] { opacity: 1; box-shadow: 0 0 0 2px var(--accent); }

@media (min-width: 900px) {
  .car-slide { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: 24px; align-items: center; }
  .car-photo { grid-column: 1 / 6; max-height: none; }
  .car-text { grid-column: 7 / 13; }
  .car-bottom { grid-column: 7 / 13; }
  .carousel.is-ready .car-stage { display: grid; gap: 0; }
  /* visibility, además de la opacidad, por dos motivos: la diapositiva que no
     se ve queda de verdad fuera (ni el buscador de la página la encuentra) y
     la capa deja de estar compuesta, que es lo que hacía salir las cinco
     encimadas en las capturas de página completa. Se apaga al terminar el
     fundido (transition-delay) y se enciende de una. */
  .carousel.is-ready .car-slide {
    grid-area: 1 / 1;
    opacity: 0;
    visibility: hidden;
    transform: translateX(24px);
    pointer-events: none;
    transition: opacity .5s var(--ease-out), transform .5s var(--ease-out), visibility 0s linear .5s;
  }
  .carousel.is-ready .car-slide.is-on {
    opacity: 1;
    visibility: visible;
    transform: none;
    pointer-events: auto;
    transition: opacity .5s var(--ease-out), transform .5s var(--ease-out), visibility 0s;
  }
}

/* Clones de la pista infinita del teléfono (los crea site.js): en escritorio
   las diapositivas van apiladas en la misma celda y no hay pista, así que no
   se pintan. El !important es a propósito: una página puede cambiarle el
   display a .car-slide (Nosotros usa display: contents) y el clon no debe
   aparecer nunca ahí. */
@media (min-width: 900px) {
  .car-slide[data-clone] { display: none !important; }
}

@media (max-width: 899px) {
  .carousel.is-ready .car-stage {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 100%;
    gap: 0;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }
  .carousel.is-ready .car-stage::-webkit-scrollbar { width: 0; height: 0; }
  .carousel.is-ready .car-slide { scroll-snap-align: center; scroll-snap-stop: always; }
}

@media (prefers-reduced-motion: reduce) {
  /* Sin avance automático: el cambio es instantáneo y no hay barra que llenar
     ni nada que pausar. */
  .carousel.is-ready .car-slide { transition: none; }
  .car-progress,
  .car-toggle { display: none; }
}

/* ?slide=N (solo QA, site.js pone data-still): apaga el fundido además de fijar
   la diapositiva. Con la transición encendida cada diapositiva vive en su propia
   capa compuesta y la captura de página completa las sacaba todas encimadas,
   aunque las escondidas ya estuvieran en visibility: hidden. */
.carousel[data-still] .car-slide,
.carousel[data-still] .car-slide.is-on { transition: none; }

/* ---- Línea de tiempo -----------------------------------------------------------
   Filas año · título · texto, con el año en --accent-2 monoespaciada.
   .timeline.with-media agrega una cuarta columna con la foto. */
.timeline { border-top: 1px solid var(--fg); }
.timeline > li {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 4fr) minmax(0, 6fr);
  align-items: start;
  gap: 8px 24px;
  padding-block: 22px;
  border-bottom: 1px solid var(--line);
}
.timeline time { font: 500 13px/1.8 var(--f-mono); letter-spacing: .04em; text-transform: uppercase; color: var(--accent-2); }
.timeline p { color: var(--muted); font-size: 15.5px; }
.timeline.with-media > li { grid-template-columns: minmax(0, 1.4fr) minmax(0, 3.2fr) minmax(0, 4.4fr) minmax(0, 3fr); }
.timeline .media { aspect-ratio: 3 / 2; border-radius: var(--r-sm); }
@media (max-width: 760px) {
  .timeline > li { grid-template-columns: minmax(0, 1fr); }
  /* En el teléfono la foto va chica a la derecha, cuadrada. */
  .timeline.with-media > li { grid-template-columns: minmax(0, 1fr) clamp(88px, 26vw, 140px); column-gap: 16px; }
  .timeline.with-media > li > :not(.media) { grid-column: 1; }
  .timeline.with-media .media { grid-column: 2; grid-row: 1 / span 3; aspect-ratio: 1 / 1; }
}

/* ---- Preguntas y acordeones (.faq) ---------------------------------------------
   <details> con el círculo "+" que gira al abrir. */
.faq { border-top: 1px solid var(--fg); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  min-height: 44px;
  padding-block: 22px;
  cursor: pointer;
  list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary i {
  position: relative;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--fg) 24%, transparent);
  flex: none;
  transition: border-color var(--t-hover) ease, transform .25s var(--ease-out);
}
.faq summary i::before,
.faq summary i::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 14px;
  height: 1.5px;
  background: currentColor;
  transform: translate(-50%, -50%);
}
.faq summary i::after { transform: translate(-50%, -50%) rotate(90deg); transition: transform .25s var(--ease-out); }
.faq summary:hover i { border-color: var(--fg); }
.faq details[open] summary i { transform: rotate(180deg); }
.faq details[open] summary i::after { transform: translate(-50%, -50%) rotate(0deg); }
.faq details > :not(summary) { padding: 0 64px 26px 0; color: var(--muted); max-width: 68ch; }
@media (max-width: 560px) { .faq details > :not(summary) { padding-right: 0; } }

/* ---- Formularios ---------------------------------------------------------------
   Prototipos (D13): data-todo="backend" en el <form>, no envían nada.
   Campo de 52 px, radio --r-sm, borde --faint (--line no llega al 3:1 de WCAG
   1.4.11), fondo --panel; la etiqueta es un rótulo sin cuadrito. */
.form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.field { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.field.wide { grid-column: 1 / -1; }
.field > label, .field-label { font: 500 12px/1.4 var(--f-mono); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.input {
  width: 100%;
  min-height: 52px;
  padding: 14px 16px;
  border-radius: var(--r-sm);
  border: 1px solid var(--faint);
  background: var(--panel);
  color: var(--fg);
  font-size: 16px;
  line-height: 1.4;
  transition: border-color var(--t-hover) ease;
}
.input:hover { border-color: var(--muted); }
/* El placeholder es texto: --muted para el 4.5:1 de WCAG 1.4.3. */
.input::placeholder { color: var(--muted); opacity: 1; }
.input:focus { outline: 2px solid var(--accent); outline-offset: 1px; border-color: transparent; }
/* Un campo de una sola línea mide 52 px EXACTOS, no "52 o lo que pida el
   texto": con min-height, la línea de 16 px por 1.4 daba 52,4 px y el campo de
   fecha —que sí lleva alto fijo desde el arreglo de iOS— quedaba medio píxel
   más bajo que el de al lado. En una fila de cuatro campos eso se ve. */
input.input, select.input { height: 52px; }
textarea.input { min-height: 132px; resize: vertical; }

/* ---- Desplegables: la flecha es nuestra (2026-09-20) --------------------------
   El <select> sin tocar pinta la flecha del sistema operativo, pegada al borde
   y de un gris que no es ninguno de los tokens: al lado de campos de contorno
   fino se ve como una pieza prestada. Con appearance:none el navegador deja de
   pintarla y el chevrón lo dibuja el envoltorio con dos bordes girados 45°: sin
   imagen ni data-URI, con el color en var(), así que sigue al tema solo. Hace
   falta el envoltorio porque un <select> no admite pseudo-elementos propios.

     <div class="field"><label for="x">Asunto</label>
       <div class="select"><select class="input" id="x" name="x">…</select></div>
     </div>

   La etiqueta se queda fuera, como hermana del envoltorio, para que siga siendo
   hija de .field (la columna del campo) y el globo de error del navegador siga
   saliendo pegado al control.

   Lo que NO se puede diseñar: la lista de opciones que se despliega la pinta el
   sistema. Aquí solo se le pide el color del texto y el fondo, que es lo único
   que respeta, para que en modo oscuro no salga blanca. */
.select { position: relative; display: block; min-width: 0; }
select.input {
  -webkit-appearance: none;
  appearance: none;
  padding-block: 0;
  padding-right: 48px;      /* el hueco del chevrón */
  cursor: pointer;
  text-overflow: ellipsis;  /* una opción larga se corta, no empuja la columna */
}
.select::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 20px;
  width: 9px;
  height: 9px;
  margin-top: -7px;         /* la "v" queda con su masa bajo el centro geométrico */
  border-right: 1.5px solid var(--muted);
  border-bottom: 1.5px solid var(--muted);
  transform: rotate(45deg);
  pointer-events: none;     /* el clic es del select, no del adorno */
  transition: border-color var(--t-hover) ease;
}
.select:hover::after,
.select:focus-within::after { border-right-color: var(--fg); border-bottom-color: var(--fg); }
/* Mientras no hay opción elegida, el texto del select es un placeholder y va en
   --muted como el de los demás campos. La marca la pone site.js con data-empty
   en vez de :required:invalid, porque hay selects sin required (kit.html) y esa
   pseudoclase no los alcanzaría. */
select.input[data-empty] { color: var(--muted); }
select.input option { color: var(--fg); background: var(--panel); }

/* ---- Campos de fecha: nativo por dentro, nuestro por fuera (2026-09-20) -------
   El input[type=date] se queda: trae el selector del teléfono, el mínimo (min),
   el teclado que toca y la validación. Lo que se cambia es lo que se ve, porque
   lo nativo desentonaba en tres cosas: el ícono negro de calendario, el
   "mm/dd/yyyy" en inglés dentro de una página en español y, vacío, un campo que
   no decía nada.

     <div class="field"><label for="rs-llegada">Llegada</label>
       <div class="date">
         <input class="input" id="rs-llegada" name="llegada" type="date" required>
         <span class="date-show" aria-hidden="true"></span>
       </div>
     </div>

   El <span> va DESPUÉS del input a propósito: así lo tapa (los dos son
   posicionados y gana el último) y basta el combinador ~ para esconderlo con el
   foco de teclado. Lo rellena site.js: el placeholder cuando está vacío o la
   fecha escrita en el idioma de la página. aria-hidden porque es un duplicado:
   el valor real lo anuncia el input.

   El texto nativo se vuelve transparente salvo cuando se llegó al campo con el
   teclado: ahí sí se ve el editor por segmentos, que es lo que deja escribir la
   fecha a mano.

   "Con el teclado" son DOS condiciones, no una. :focus-visible sola no basta:
   la especificación de CSS dice que un campo donde se escribe siempre la
   cumple, también con el ratón (así un campo de texto nunca se queda sin
   anillo de foco), y se comprobó en Chrome. Tal cual, al hacer clic volvía a
   salir el "mm/dd/yyyy" que este arreglo viene a quitar. Por eso site.js marca
   el campo con data-puntero cuando el foco llegó con el ratón o con el dedo, y
   lo quita en cuanto alguien teclea. */
.date {
  position: relative;
  display: block;
  min-width: 0;
  /* La silueta del ícono (ver .date::after). Vive aquí, en el componente, y no
     en tokens.css: es una forma, no un token de la paleta. */
  --i-cal: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2.5'/%3E%3Cpath d='M8 3v4M16 3v4M3 10h18'/%3E%3C/svg%3E");
}
/* Campos de fecha en iOS (visto en un iPhone el 2026-09-19): Safari pinta los
   input[type=date] con su propia apariencia y entonces NO obedece ni el alto ni
   el ancho del campo: salían más altos que los demás, vacíos, y el segundo se
   salía de su columna por el ancho intrínseco del formato de fecha. Sin la
   apariencia nativa el campo vuelve a ser una caja normal (el selector de
   fecha del teléfono se sigue abriendo al tocarlo), y el valor se alinea a la
   izquierda como en los demás campos en vez de centrado. */
input[type="date"].input {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  position: relative;       /* el indicador nativo se estira contra esta caja */
  min-width: 0;
  max-width: 100%;
  height: 52px;
  padding-right: 48px;      /* el hueco del ícono */
  color: transparent;       /* lo que se lee es .date-show */
}
input[type="date"].input::-webkit-date-and-time-value { min-height: 1.4em; margin: 0; text-align: left; }
input[type="date"].input::-webkit-datetime-edit { color: transparent; }
/* Con el tabulador sí se ve el editor por segmentos, y el nuestro se aparta. */
input[type="date"].input:focus-visible:not([data-puntero]) { color: var(--fg); }
input[type="date"].input:focus-visible:not([data-puntero])::-webkit-datetime-edit { color: var(--fg); }
.date > .input:focus-visible:not([data-puntero]) ~ .date-show { display: none; }
/* El indicador nativo (el cuadrito del calendario) se estira sobre todo el
   campo y se vuelve invisible: así un toque en cualquier parte abre el
   calendario, no solo en una esquina de 16 px. Donde no existe ese
   pseudo-elemento, site.js llama a showPicker(). */
input[type="date"].input::-webkit-calendar-picker-indicator {
  position: absolute;
  inset: 0;
  width: auto;
  height: auto;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: pointer;
}
.date-show {
  position: absolute;
  inset: 1px;               /* justo por dentro del borde del campo */
  padding: 14px 48px 14px 16px;   /* el mismo relleno del texto de los demás campos */
  font-size: 16px;
  line-height: 1.4;
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;     /* el clic sigue siendo del input */
  border-radius: calc(var(--r-sm) - 1px);
  background: var(--panel);
}
.date-show[data-empty] { color: var(--muted); }
/* El ícono: un calendario de trazo fino, como los demás del sitio. Va de
   máscara y no de imagen de fondo a propósito — una máscara solo aporta la
   silueta, y el color lo pone background con un token, así que cambia con el
   tema sin duplicar el archivo. El #000 del SVG es opacidad, no color: de una
   máscara solo se usa el canal alfa. */
.date::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 16px;
  width: 20px;
  height: 20px;
  margin-top: -10px;
  background-color: var(--muted);   /* el color del ícono: la máscara solo da la forma */
  -webkit-mask: var(--i-cal) center / 20px 20px no-repeat;
  mask: var(--i-cal) center / 20px 20px no-repeat;
  pointer-events: none;
  /* Solo cambia de color, como el borde de los campos. El bloque "Movimiento
     reducido" deja pasar los fundidos de color a propósito. */
  transition: background-color var(--t-hover) ease;
}
.date:hover::after,
.date:focus-within::after { background-color: var(--fg); }

/* ---- Número: sin las flechitas (2026-09-20) -----------------------------------
   El par de flechas de arriba y abajo solo aparece con el puntero encima, se
   pinta con el estilo del sistema y en un campo de 52 px queda apretado. Fuera:
   el teclado numérico (inputmode) y las flechas del teclado siguen ahí. */
input[type="number"].input { -moz-appearance: textfield; appearance: textfield; }
input[type="number"].input::-webkit-outer-spin-button,
input[type="number"].input::-webkit-inner-spin-button { -webkit-appearance: none; appearance: none; margin: 0; }

.form .btn { align-self: flex-start; }
/* Estado "enviado" que pinta site.js (región viva role="status"). Vacía
   queda fuera de la vista pero en el árbol de accesibilidad, para que el
   lector de pantalla anuncie el mensaje cuando llega; tampoco suma un hueco
   a la cuadrícula del formulario. */
.form-status {
  grid-column: 1 / -1;
  flex: 1 1 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  font: 500 13px/1.5 var(--f-mono);
  color: var(--fg);
}
.form-status::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--ok); flex: none; }
.form-status:empty { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* Error al enviar: sin color de error en el sistema, se marca con el acento
   en el borde y el punto; el texto sigue en --fg para que se lea bien. */
.form-status.is-error { padding-left: 12px; border-left: 3px solid var(--accent); }
.form-status.is-error::before { background: var(--accent); }
.form-status.is-error a { color: var(--fg); text-decoration-color: var(--accent); text-underline-offset: 4px; }
/* Campo trampa para bots: fuera de la vista, pero presente en el formulario. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }

/* Enviado con éxito (2026-10-14): el formulario cede su lugar al panel
   .form-done que mete site.js. Misma familia que .empty (borde --line, radio
   grande), pero centrado y con el ícono en --accent. La altura mínima es la
   de un formulario corto, para que la página no salte al cambiar. */
form.is-sent > :not(.form-done) { display: none; }
.form-done {
  grid-column: 1 / -1;
  flex: 1 1 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 280px;
  padding: clamp(32px, 5vw, 56px);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--bg);
  text-align: center;
  animation: form-done-in .35s ease both;
}
.form-done:focus { outline: none; }
.form-done:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.form-done-icon { width: 48px; height: 48px; color: var(--accent); flex: none; margin-bottom: 6px; }
.form-done .h3 { margin: 0; }
.form-done .text { max-width: 40ch; margin: 0; }
.form-done .btn { margin-top: 14px; align-self: center; }
form[data-form="boletin"] .form-done { min-height: 160px; }
@keyframes form-done-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .form-done { animation: none; } }
@media (max-width: 560px) {
  .form-done { padding: 28px 20px; }
  .form-done .btn { align-self: stretch; }
}
@media (max-width: 560px) {
  .form { grid-template-columns: minmax(0, 1fr); }
  .form .btn { align-self: stretch; min-height: 52px; }
}

/* ==========================================================================
   Lo que se ABRE en los formularios (2026-09-21)
   ==========================================================================
   Los dos bloques de arriba dejaron los campos CERRADOS con la cara del sitio.
   Lo que faltaba es lo que se despliega al abrirlos: el calendario del
   input[type=date] y la lista del <select> los pinta el sistema operativo, con
   su tipografía, sus colores y sus esquinas, y no hay CSS que los alcance —
   no son parte de la página. En el escritorio de Linux del cliente eso
   desentona con todo lo demás. La única salida es no usarlos y dibujar el
   panel nosotros.

   Solo donde hay RATÓN. En una pantalla táctil, la rueda de iOS y el
   calendario de Android son justo lo que la persona espera y sabe usar; un
   panel de 320 px con celdas de 40 px sería peor. Por eso el interruptor no
   está aquí sino en site.js (Parte 4), que enciende esto únicamente si se
   cumple (hover: hover) and (pointer: fine); en el teléfono nada lleva las
   clases ni los atributos que piden estas reglas, así que ni se activan. Sin
   JavaScript tampoco: queda el control nativo, entero.

   El <input type="date"> y el <select> de verdad SIGUEN en el marcado y son la
   fuente de la verdad: el valor, el name, required, min, data-after, la
   validación del navegador y el prefill por URL son suyos. El panel solo les
   escribe el valor y dispara input y change, así que todo lo que ya escuchaba
   (.date-show, el mínimo de "Salida", el estado enviado) sigue igual.

   Los dos paneles comparten caja: mismo borde, mismo radio, la sombra de la
   tarjeta flotante y la misma entrada. Van con position: fixed y colgando de
   <body> para que ningún contenedor con overflow los recorte, y site.js les
   calcula left/top contra el campo. El z-index queda por encima de todo lo que
   flota en la página (44 a 46) y por debajo de la cabecera pegajosa (50), que
   es lo único que debe pasarles por encima. */
.cal,
.lb {
  position: fixed;
  z-index: 47;
  border-radius: var(--r-md);
  /* El mismo canto que la tarjeta flotante: --line casi no se ve contra el
     fondo oscuro, y la tinta al 16 % sí se distingue en los dos modos. */
  border: 1px solid color-mix(in srgb, var(--fg) 16%, transparent);
  background: var(--panel);
  box-shadow: var(--shadow-float);
  color: var(--fg);
  animation: lw-pop .16s var(--ease-out) both;
}
@keyframes lw-pop {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

/* ---- Calendario (.cal) ---------------------------------------------------------
   320 px: siete columnas de 40 px más el aire de los lados. Ese ancho es lo que
   deja que el número del día quepa centrado con su círculo de 36 px sin que la
   cuadrícula se vea apretada. */
.cal { width: 320px; padding: 12px 12px 6px; }
.cal-head { display: flex; align-items: center; gap: 8px; padding: 2px 0 10px 8px; }
/* El mes en la tipografía de los titulares, como los h3 del sitio. */
.cal-title {
  flex: 1 1 auto;
  min-width: 0;
  font: var(--w-head) 17px/1.2 var(--f-head);
  letter-spacing: var(--track-head);
}
/* Los de mes anterior y siguiente son .icon-btn del sistema, un punto más
   pequeños: dentro de un panel de 320 px, 44 px se comen la cabecera. */
.cal .icon-btn { width: 36px; height: 36px; }
.cal .icon-btn svg { width: 16px; height: 16px; }
.cal .icon-btn[disabled] { color: var(--faint); border-color: var(--faint); cursor: default; }
.cal .icon-btn[disabled]:hover { border-color: var(--faint); }

.cal-row { display: grid; grid-template-columns: repeat(7, 1fr); }
/* Los días de la semana son un rótulo, como los demás del sitio: monoespaciada
   pequeña en --muted. Los nombres los da Intl con el idioma de la página. */
.cal-dow {
  display: grid;
  place-items: center;
  height: 28px;
  font: 500 11px/1 var(--f-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
.cal-cell { position: relative; }
/* La banda del tramo elegido va en la CELDA y no en el botón: así llega de
   borde a borde y las celdas seguidas forman una sola barra sin cortes. En los
   dos extremos solo se pinta la mitad que mira hacia dentro, para que la barra
   nazca y muera debajo del círculo relleno. */
.cal-cell[data-range]::before {
  content: "";
  position: absolute;
  top: 2px;
  bottom: 2px;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}
.cal-cell[data-range="in"]::before { left: 0; right: 0; }
.cal-cell[data-range="start"]::before { left: 50%; right: 0; }
.cal-cell[data-range="end"]::before { left: 0; right: 50%; }
.cal-cell[data-range="solo"]::before { content: none; }

/* El día: el botón ocupa la celda entera (40 px de área de clic) y el círculo
   lo dibuja un pseudo-elemento de 36 px centrado. Al revés —un botón redondo de
   36 px— el clic fallaría en las esquinas de la celda. */
.cal-day {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--fg);
  font: 400 14px/1 var(--f-body);
  cursor: pointer;
}
.cal-day > span { position: relative; z-index: 1; }
.cal-day::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 36px;
  height: 36px;
  margin: -18px 0 0 -18px;
  border-radius: 50%;
  transition: background-color var(--t-hover) ease;
}
.cal-day:hover::before { background: var(--panel-2); }
/* Hoy: un anillo fino, que señala sin competir con el día elegido. */
.cal-day[aria-current="date"]::before { box-shadow: inset 0 0 0 1.5px var(--accent); }
/* El elegido: círculo lleno del acento. Gana al anillo si son el mismo día.
   data-extremo es lo mismo para el otro extremo del tramo (la llegada mientras
   se elige la salida, y al revés): se ve igual porque es la misma cosa, aunque
   el aria-selected solo le toca al valor de ESTE campo. */
.cal-day[aria-selected="true"],
.cal-day[data-extremo] { color: var(--accent-fg); }
.cal-day[aria-selected="true"]::before,
.cal-day[data-extremo]::before { background: var(--accent); box-shadow: none; }
.cal-day[aria-disabled="true"] { color: var(--faint); cursor: default; }
.cal-day[aria-disabled="true"]:hover::before { background: transparent; }
.cal-day:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Pie: "Hoy" y "Borrar" son dos atajos, no acciones principales; van como
   enlaces de texto en monoespaciada, del tamaño de los rótulos. */
.cal-foot { display: flex; gap: 6px; padding: 6px 4px 6px; }
.cal-link {
  min-height: 32px;
  padding: 0 8px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--muted);
  font: 500 12px/32px var(--f-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color var(--t-hover) ease;
}
.cal-link:hover { color: var(--fg); }

/* Con el calendario propio encendido, el indicador nativo deja de existir: es
   el cuadrito invisible que el bloque de arriba estira sobre todo el campo para
   que un toque abra el selector del sistema. Quitándolo, un clic en el campo
   solo lo enfoca —y el panel lo abre site.js—, que es justo lo que se busca:
   que no salga el calendario del sistema operativo. */
.date[data-cal] > .input::-webkit-calendar-picker-indicator { display: none; }

/* ---- Lista del desplegable (.lb) -----------------------------------------------
   El <select> de verdad se queda, pero transparente y encima del campo, y
   delante va un botón con la misma cara. Transparente y del tamaño del campo, y
   no encogido a un píxel como .vh, por dos razones: un control con display:none
   o visibility:hidden sigue contando para la validación pero ya no se puede
   enfocar, y entonces Chrome no muestra su globo de error ("An invalid form
   control is not focusable"); y aunque se pueda, el globo sale donde esté la
   caja del control, así que si mide un píxel aparece en una esquina y no
   pegado al campo. pointer-events: none deja que el clic sea del botón. */
.select.is-lista > select.input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  pointer-events: none;
}
/* El botón repite el campo: los 52 px, el borde, el radio, el hueco del
   chevrón. No hereda de .input todo lo que necesita porque un <button> no toma
   la tipografía de la página por su cuenta. */
.lb-btn {
  display: flex;
  align-items: center;
  height: 52px;
  padding-right: 48px;   /* el mismo hueco del chevrón que pide el select */
  text-align: left;
  cursor: pointer;
}
.lb-btn > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Sin opción elegida el texto es un placeholder, igual que en el select. */
.lb-btn > span[data-empty] { color: var(--muted); }
/* El chevrón del envoltorio da media vuelta mientras la lista está abierta.
   Son 180° sobre los 45° que ya tiene, y el ajuste vertical cambia de signo
   porque la "v" queda mirando hacia arriba. */
.select[data-open]::after { transform: rotate(225deg); margin-top: -2px; }

.lb { padding: 6px; max-height: 320px; overflow-y: auto; overscroll-behavior: contain; }
.lb-opt {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 10px 14px;
  border-radius: var(--r-sm);
  font-size: 16px;
  line-height: 1.4;
  cursor: pointer;
}
/* Una sola marca visual para "donde está el cursor" y "donde está el teclado":
   con ratón y con flechas se ve lo mismo, así que no hay dos estados que
   compitan. */
.lb-opt[data-active] { background: var(--panel-2); }
/* El visto de la opción elegida: dos bordes girados, como el chevrón. Se
   reserva su sitio siempre (visibility) para que el texto no salte. */
.lb-opt::after {
  content: "";
  flex: none;
  margin-left: auto;
  width: 6px;
  height: 11px;
  border-right: 1.5px solid var(--accent);
  border-bottom: 1.5px solid var(--accent);
  transform: rotate(45deg) translate(-1px, -1px);
  visibility: hidden;
}
.lb-opt[aria-selected="true"]::after { visibility: visible; }
.lb-opt[data-empty] { color: var(--muted); }

/* El campo inválido, una sola regla para el campo nativo y para el botón.
   :user-invalid (y no :invalid) porque solo entra después de que la persona
   tocó el campo o intentó enviar: un formulario recién abierto no se marca
   entero. El botón de la lista no es un control validable, así que site.js le
   pone aria-invalid cuando el <select> que representa no pasa. La paleta no
   tiene token de error, así que la señal es el contorno en --fg doblado con un
   anillo por dentro: destaca sobre el --faint de los campos en calma y se ve
   igual de claro en los dos modos. */
.input:user-invalid,
.lb-btn[aria-invalid="true"] { border-color: var(--fg); box-shadow: inset 0 0 0 1px var(--fg); }

@media (prefers-reduced-motion: reduce) {
  .cal, .lb { animation: none; }
  .cal-day::before, .cal-link { transition: none; }
}

/* ---- Scrollbar propio (D9, escritorio) -------------------------------------------
   Barra fina del acento. En pantallas táctiles el sistema no deja pintarla: U2
   agrega ahí un indicador fino a la derecha. */
@media (hover: hover) and (pointer: fine) {
  ::-webkit-scrollbar { width: 12px; height: 12px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb {
    min-height: 56px;
    border: 4px solid transparent;
    border-radius: var(--r-pill);
    background: var(--accent);
    background-clip: padding-box;
  }
  ::-webkit-scrollbar-thumb:hover { border-width: 3px; }
  ::-webkit-scrollbar-corner { background: transparent; }
  @supports not selector(::-webkit-scrollbar) {
    html { scrollbar-width: thin; scrollbar-color: var(--accent) transparent; }
  }
}

/* ==========================================================================
   Eventos (2026-09-19)
   Retiros en el centro, viajes misioneros y recaudaciones. Los pinta
   revamp/js/events.js en tres sitios —la sección del Inicio, la página
   Eventos y el detalle— más la tarjeta flotante de promoción. Todo lo de
   aquí es del sistema: los tres sitios usan los mismos componentes.

     .event-date      el bloque de fecha (día grande + mes en monoespaciada);
                      con .event-date--glass va sobre la foto
     .badge-example   la insignia "Ejemplo" / "Example" de los eventos de
                      demostración: píldora monoespaciada con borde
                      discontinuo, como los marcadores .ph
     .event-card      la tarjeta (Inicio y "Otros eventos"); .events-grid la
                      coloca en una, dos o tres columnas según [data-n]
     .event-row       la fila de la página Eventos, sobre .rows/.row
     .event-float     la tarjeta flotante de promoción

   Muestra viva en kit.html (sección 19).
   ========================================================================== */

:root {
  /* La única sombra del sitio, y solo para lo que flota encima de la página y
     necesita separarse de lo que tapa: la tarjeta de promoción y, desde el
     2026-09-21, los paneles del calendario y de la lista de los formularios.
     Sale de --l-fg (la tinta clara), así que es la misma sombra en los dos
     modos y no hay ningún color literal.

     Dos capas: la ancha y difusa despega la tarjeta de la página, y la
     estrecha y cerrada le dibuja el canto. Con una sola, la tarjeta se veía
     flotando pero con los bordes blandos. */
  --shadow-float:
    0 28px 64px -22px color-mix(in srgb, var(--l-fg) 46%, transparent),
    0 2px 10px -2px color-mix(in srgb, var(--l-fg) 18%, transparent);
}

/* ---- Insignia de ejemplo ------------------------------------------------- */
.badge-example {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  padding: 2px 10px;
  border-radius: var(--r-pill);
  border: 1px dashed var(--faint);
  color: var(--muted);
  font: 500 12px/1.3 var(--f-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ---- Bloque de fecha ------------------------------------------------------
   El día en la tipografía de los titulares y el mes en monoespaciada: es lo
   primero que se lee de un evento. Sobre la foto va en la pastilla de vidrio
   del sistema (la misma de .tag); en una fila, suelto sobre el fondo. */
.event-date {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  flex: none;
}
.event-date b {
  font-family: var(--f-display);
  font-weight: var(--w-display);
  font-size: 34px;
  line-height: 1;
  letter-spacing: var(--track-display);
  font-variant-numeric: tabular-nums;
}
.event-date i {
  font: 500 12px/1 var(--f-mono);
  font-style: normal;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
}
.event-date--glass {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 1;
  min-width: 66px;
  padding: 10px 10px 9px;
  border-radius: var(--r-sm);
  color: var(--glass-fg);
  background: var(--glass);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.event-date--glass i { color: inherit; }

/* ---- Lugar con el pin ----------------------------------------------------- */
.event-place {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font: 400 13px/1.45 var(--f-mono);
  color: var(--muted);
}
.event-place svg { width: 15px; height: 15px; flex: none; }
/* El lugar va entero, en las líneas que necesite: sin puntos suspensivos
   (2026-09-20). Un texto cortado con "…" obliga a adivinar lo que falta. */
.event-place { align-items: flex-start; }
.event-place > span { min-width: 0; overflow-wrap: anywhere; }

/* ---- Tarjeta de evento ----------------------------------------------------
   Una, dos o tres columnas según cuántos eventos haya ([data-n] lo pone
   events.js). Con uno solo la tarjeta se pone horizontal, con la foto a la
   izquierda: una tarjeta estrecha y solitaria en medio de la página se lee
   como un hueco. En el teléfono van apiladas (no en pista: con tres tarjetas
   como mucho, apilar se lee mejor y no hay riesgo de desborde). */
.events-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(22px, 2.6vw, 34px);
}
.events-grid[data-n="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.events-grid[data-n="1"] { grid-template-columns: minmax(0, 1fr); }
@media (max-width: 900px) {
  .events-grid, .events-grid[data-n="2"] { grid-template-columns: minmax(0, 1fr); }
}

.event-card {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}
.event-card-media { display: block; aspect-ratio: 4 / 3; }
.event-card-media img { transition: transform .5s var(--ease-out); }
.event-card:hover .event-card-media img { transform: scale(1.03); }
.event-card-body { display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; min-width: 0; }
.event-card-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.event-card-title { text-wrap: balance; transition: color var(--t-hover) ease; }
.event-card:hover .event-card-title { color: var(--accent-2); }
/* El resumen va entero (2026-09-20): es una frase corta por definición del
   dato (`summary`), y recortarla a dos líneas la dejaba a medias con "…". */
.event-card-sum {
  color: var(--muted);
  font-size: 15.5px;
  line-height: 1.55;
}
.event-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: auto;
  padding-top: 4px;
  font: 500 12px/1 var(--f-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
.event-card:hover .row-go { background: var(--accent); color: var(--accent-fg); border-color: transparent; }

@media (min-width: 901px) {
  .event-card--wide {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    align-items: center;
    gap: clamp(24px, 3vw, 48px);
  }
  .event-card--wide .event-card-media { aspect-ratio: 16 / 10; }
}

/* ---- Filas de la página Eventos -------------------------------------------
   Sobre .rows/.row: el bloque de fecha ocupa la primera columna y el resto
   sigue el patrón de siempre (título, tipo y flecha). */
.event-groups { display: flex; flex-direction: column; gap: clamp(28px, 3.4vw, 44px); }
.event-month-h { margin-bottom: 12px; }
.event-rows .row { grid-template-columns: 76px minmax(0, 6fr) minmax(0, 3fr) 44px; }
.event-rows .row:not(:has(.row-text)) { grid-template-columns: 76px minmax(0, 6fr) minmax(0, 3fr) 44px; }
.event-row .event-date { align-items: flex-start; }
.event-row .event-date b { font-size: 30px; }
.event-row-body { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.event-row-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  font: 500 13px/1.4 var(--f-mono);
  color: var(--muted);
}
.event-row--past .row-title { color: var(--muted); }
.evt-pasados { margin-top: clamp(28px, 3.4vw, 44px); }

@media (max-width: 760px) {
  .event-rows .row,
  .event-rows .row:not(:has(.row-text)) { grid-template-columns: 62px minmax(0, 1fr) 44px; }
  .event-row .event-date { grid-column: 1; grid-row: 1 / span 2; align-self: start; }
  .event-row .event-date b { font-size: 26px; }
  .event-row-body { grid-column: 2; }
  .event-row-meta { grid-column: 2; justify-content: flex-start; }
  .event-rows .row .row-go { grid-column: 3; grid-row: 1 / span 2; }
}

/* ---- Inicio y página: cabeceras y notas ------------------------------------ */
/* Como en Historia: el titular ocupa la línea y el botón cae a su derecha. */
.evt-head { align-items: flex-end; }
@media (min-width: 901px) { .evt-head > .btn { margin-inline-start: auto; } }
/* La sección de Eventos del Inicio va pegada a la portada, así que es ella la
   que no lleva regla arriba. Mientras events.js no ha pintado nada, el hueco
   sigue en el HTML con hidden: esta regla evita que "Quiénes somos" enseñe una
   regla que después no le toca. */
.cover + [data-events-home][hidden] + .sec { border-top: 0; }
.evt-nada { color: var(--muted); }
.evt-otros { margin-top: clamp(20px, 2.6vw, 36px); }
.evt-msg { min-height: 21px; }

/* ---- Detalle: miga y rótulo del tipo --------------------------------------- */
.event-crumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font: 500 12px/1.4 var(--f-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
.event-crumb a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  transition: color var(--t-hover) ease, border-color var(--t-hover) ease;
}
.event-crumb a:hover { color: var(--fg); border-color: currentColor; }
.evt-kind { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
/* La flecha diagonal del enlace al mapa dentro de una fila de datos. Sin
   tamaño, un <svg> sin width ni height se dibuja a 300×150 y se come la fila.
   Contacto ya traía esta regla para su bloque; aquí vale para cualquier
   .facts con enlaces con ícono. */
.facts a svg { width: 14px; height: 14px; margin-left: 6px; flex: none; }
/* El glifo de WhatsApp va en --wa-ink sobre los fondos de la página, pero
   sobre un botón RELLENO (el acento o la tinta) ese verde oscuro no se
   distingue: ahí toma el color del texto del botón, que es el que sí contrasta
   con su fondo. Sigue siendo el glifo de WhatsApp y sigue sin deslizarse. */
.btn.btn-primary[href*="whatsapp.com"] svg,
.btn.btn-primary[href*="wa.me"] svg,
.btn.btn-solid[href*="whatsapp.com"] svg,
.btn.btn-solid[href*="wa.me"] svg { color: currentColor; }

/* ---- Tarjeta flotante de promoción -----------------------------------------
   Sube ABAJO A LA IZQUIERDA. El botón de WhatsApp vive abajo a la derecha: en
   escritorio no se tocan y en el teléfono, donde la tarjeta ocupa el ancho
   menos los márgenes, sube por encima de él. No atrapa el foco ni tapa la
   página: es un aviso que se cierra y no vuelve para ese evento.

   Es un panel normal (--panel sobre --fg), no una cápsula inversa: la cápsula
   la dejaba apagada en los dos modos. Lo que da vida es la FOTO, a sangre
   arriba en escritorio, con el bloque de fecha de vidrio encima.

   En escritorio va vertical (340 px); a 760 px o menos pasa a horizontal y
   compacta, con la foto cuadrada de 96 px a la izquierda. El bloque de fecha y
   la insignia "Ejemplo" vienen duplicados en el marcado (ver events.js) y cada
   tamaño esconde la copia que no usa. */
.event-float {
  position: fixed;
  left: var(--gutter);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 16px);
  z-index: 44;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  width: 340px;
  max-width: calc(100vw - var(--gutter) * 2 - 76px);
  border-radius: var(--r-md);
  /* --line casi no se ve contra el --bg oscuro: el canto va en tinta al 16 %,
     que se distingue en los dos modos (lo mismo hacen los botones fantasma). */
  border: 1px solid color-mix(in srgb, var(--fg) 16%, transparent);
  background: var(--panel);
  color: var(--fg);
  overflow: hidden;
  box-shadow: var(--shadow-float);
  opacity: 0;
  transform: translateY(24px) scale(.96);
  transform-origin: bottom left;
  /* La entrada dura .5 s y la SALIDA .28 s, porque el JS borra la tarjeta a
     los 320 ms de quitarle data-in: una salida más lenta se cortaría a medias.
     El truco es que cada estado declara su propia transición y el navegador
     usa la del estado al que va. */
  transition: opacity .28s var(--ease-out), transform .28s var(--ease-out);
  /* Mientras no está a la vista (entrando, saliendo o guardada sobre la portada
     del Inicio) es transparente, pero seguiría recibiendo los toques. */
  pointer-events: none;
}
.event-float[data-in="1"] {
  pointer-events: auto;
  opacity: 1;
  transform: none;
  transition: opacity .5s var(--ease-out), transform .5s var(--ease-out);
}

/* ---- La foto ---------------------------------------------------------------
   A sangre y en 2:1. El radio lo recorta la tarjeta (overflow: hidden), así
   que la foto va con las esquinas cuadradas. */
.event-float-media {
  display: block;
  aspect-ratio: 2 / 1;
  border-radius: 0;
}
.event-float-media img { transition: transform .5s var(--ease-out); }
.event-float:hover .event-float-media img { transform: scale(1.04); }
.event-float-media .event-date--glass { top: 12px; left: 12px; }
/* La insignia sobre la foto: mismo vidrio que el bloque de fecha, porque el
   borde discontinuo en --faint se pierde sobre una foto clara. Sigue siendo la
   píldora discontinua, solo cambia de color. */
.event-float-media .badge-example {
  position: absolute;
  left: 12px;
  bottom: 12px;
  z-index: 1;
  border-color: color-mix(in srgb, var(--glass-fg) 45%, transparent);
  color: var(--glass-fg);
  background: var(--glass);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

/* ---- El cuerpo ------------------------------------------------------------- */
.event-float-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  padding: 16px 16px 0;
}
.event-float-top { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
/* El punto del rótulo, con un halo que late TRES veces y se queda quieto: lo
   justo para que el ojo lo encuentre sin que la tarjeta pulse para siempre.
   Solo se animan transform y opacity de un pseudo-elemento, que no obliga a
   recalcular la maqueta. */
.event-float-dot {
  position: relative;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}
.event-float-dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--accent);
  animation: lw-evt-pulse 1.4s var(--ease-out) .4s 3 both;
}
@keyframes lw-evt-pulse {
  0% { transform: scale(1); opacity: .5; }
  70%, 100% { transform: scale(3.4); opacity: 0; }
}
/* La fecha corta: solo en el teléfono, donde no cabe el bloque de vidrio. */
.event-float-when {
  display: none;
  font: 500 12px/1.4 var(--f-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
.event-float-top .badge-example { display: none; }
.event-float-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  font-family: var(--f-head);
  font-weight: var(--w-head);
  font-size: 20px;
  line-height: 1.2;
  letter-spacing: var(--track-head);
}
/* Lugar y cuenta regresiva en una línea. El lugar se corta con puntos
   suspensivos (el completo está en la ficha del detalle); la cuenta nunca,
   porque es la mitad del mensaje. */
.event-float-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 8px;
  min-width: 0;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.45;
}
/* Sin puntos suspensivos: si el nombre del lugar no cabe junto a la cuenta,
   la cuenta baja a la línea siguiente. */
.event-float-where { min-width: 0; }
.event-float-count { flex: none; white-space: nowrap; }
.event-float-count::before { content: "·"; margin-right: 8px; }

/* ---- Las acciones ---------------------------------------------------------- */
.event-float-acts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 4px 10px;
  padding: 12px 16px 16px;
}
/* El botón es el ÚNICO enlace de la tarjeta, y su ::after estirado cubre todo:
   así la foto y el título también llevan al detalle sin anidar un enlace
   dentro de otro (ni el teclado ni el lector de pantalla saben recorrer eso).
   El botón se queda en position: static a propósito, para que el inset: 0 se
   mida contra la tarjeta. El anillo de foco lo dibuja el botón, no el ::after,
   porque el outline sigue la caja del elemento y no la de su pseudo-elemento. */
.event-float-go::after { content: ""; position: absolute; inset: 0; }
/* Por encima del ::after: los dos controles que NO van al detalle. */
.event-float-more,
.event-float-x { position: relative; z-index: 1; }
.event-float-more {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 13px;
  color: var(--muted);
  text-decoration: none;
  transition: color var(--t-hover) ease;
}
.event-float-more:hover { color: var(--fg); }
/* Cerrar: 44 px de área táctil sobre la foto, en vidrio para que se lea sobre
   cualquier imagen. Al pasar el cursor toma el acento, como el botón de play. */
.event-float-x {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  color: var(--glass-fg);
  background: var(--glass);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  cursor: pointer;
  transition: background-color var(--t-hover) ease, color var(--t-hover) ease;
}
.event-float-x svg { width: 17px; height: 17px; }
.event-float-x:hover { background: var(--accent); color: var(--accent-fg); }

/* En el teléfono se pone HORIZONTAL y compacta: ocupa el ancho menos los
   márgenes y sube por encima del botón de WhatsApp (56 px más su aire), para
   no taparlo ni rozarlo. La foto pasa a un cuadrado de 96 px con aire
   alrededor (a sangre, en 96 px, la fecha de vidrio no cabría) y las acciones
   bajan a una fila propia a todo el ancho. */
@media (max-width: 760px) {
  .event-float {
    right: var(--gutter);
    width: auto;
    max-width: none;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 84px);
    grid-template-columns: 96px minmax(0, 1fr);
    align-items: start;
    gap: 12px;
    padding: 12px;
  }
  .event-float-media { aspect-ratio: 1 / 1; border-radius: var(--r-sm); }
  .event-float-media .event-date--glass,
  .event-float-media .badge-example { display: none; }
  /* Solo la fila del rótulo le deja sitio al botón de cerrar; el título y la
     meta usan la columna entera. */
  .event-float-body { padding: 0; gap: 6px; }
  .event-float-top { padding-right: 40px; }
  .event-float-when { display: inline; }
  .event-float-top .badge-example { display: inline-flex; }
  .event-float-title { font-size: 17px; }
  .event-float-acts { grid-column: 1 / -1; padding: 0; }
  .event-float-x {
    top: 4px;
    right: 4px;
    color: var(--muted);
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .event-float-x:hover { background: var(--panel-2); color: var(--fg); }
}

/* Movimiento reducido: la tarjeta solo se funde, el punto no late y la foto no
   se acerca. ?still=1 (las capturas) para el latido igual, sin tocar lo demás:
   una captura con el halo a medio crecer sale distinta en cada corrida. */
@media (prefers-reduced-motion: reduce) {
  .event-float,
  .event-float[data-in="1"] { transform: none; transition: opacity .2s ease; }
  .event-float-dot::after { animation: none; }
  .event-float-media img,
  .event-float:hover .event-float-media img { transform: none; transition: none; }
  .event-card-media img,
  .event-card:hover .event-card-media img { transform: none; transition: none; }
}
.event-float[data-still] .event-float-dot::after { animation: none; }

/* ==========================================================================
   Armazón (U2): lo pinta shell.js en todas las páginas (LOOP.md D7 a D9, D17).
   Valores de la maqueta del demo; aquí solo cambian los tokens. La marca, el
   menú, la cortina y "Sigue" usan --f-head, la misma familia de los titulares,
   solo h1 y h2.
   ========================================================================== */

/* ---- Saltar al contenido y anclas -------------------------------------------
   El enlace aparece solo con el teclado. Las anclas dejan espacio para la
   cabecera pegajosa. */
.skip {
  position: fixed;
  left: var(--gutter);
  top: calc(env(safe-area-inset-top, 0px) + 12px);
  z-index: 130;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 18px;
  border-radius: var(--r-pill);
  background: var(--fg);
  color: var(--bg);
  font: 500 14px/1 var(--f-body);
  text-decoration: none;
  transform: translateY(calc(-100% - 24px));
}
.skip:focus { transform: none; }
main [id] { scroll-margin-top: 96px; }

/* ---- Marca: la gota del logo a 36 px y "Living Water" ------------------------
   Desde el 2026-09-19 la marca usa /img/gota.png, que es SOLO la gota con el
   fondo transparente (recortada de brand/bgiconov2.png, 118x192). Antes iba
   LogoLivingWater.png —caligrafía incluida y fondo blanco opaco— agrandado y
   recortado con un clip-path a mano: la gota terminaba midiendo unos 16x27 px
   dentro de un cuadro de 28 y se veía diminuta. Ahora la caja es la de la gota
   y basta con darle alto. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  min-width: 0;
  padding: 0 16px 0 10px;
  font-family: var(--f-head);
  font-weight: var(--w-head);
  font-size: 19px;
  line-height: 1;
  letter-spacing: var(--track-head);
  white-space: nowrap;
  text-decoration: none;
  color: inherit;
}
.mark {
  display: block;
  width: auto;
  height: 36px;
  flex: none;
}
.mark img { width: auto; height: 100%; }
.crumb { font: 500 12px/1 var(--f-mono); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
@media (max-width: 640px) { .crumb { display: none; } }

/* ---- Cabecera: dos píldoras de vidrio pegajosas (D7) ------------------------- */
.bar { position: sticky; top: calc(env(safe-area-inset-top, 0px) + 12px); z-index: 50; margin-top: 12px; }
.bar-in { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.glass {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  padding: 6px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: color-mix(in srgb, var(--panel) 90%, transparent);
  -webkit-backdrop-filter: blur(16px) saturate(1.5);
  backdrop-filter: blur(16px) saturate(1.5);
  transition: background-color .25s ease, border-color .25s ease, color .25s ease;
}
/* Las dos píldoras van AL REVÉS del modo (shell.js les pone .inv): claras sobre
   la página oscura y oscuras sobre la página clara, para que la cabecera se
   despegue del fondo en vez de fundirse con él. Hay zonas que no siguen al
   modo (la portada con foto es siempre oscura; una cápsula o tarjeta inversa
   es lo contrario de la página): mientras una píldora pasa por encima, site.js
   le anota el esquema de esa zona en data-over y aquí toma el juego contrario,
   para no quedar oscuro sobre oscuro ni claro sobre claro. */
.bar .glass[data-over="dark"] {
  --bg: var(--l-bg); --panel: var(--l-panel); --panel-2: var(--l-panel-2);
  --fg: var(--l-fg); --muted: var(--l-muted); --faint: var(--l-faint);
  --dim: var(--l-dim); --line: var(--l-line); --accent: var(--l-accent);
  --accent-fg: var(--l-accent-fg); --accent-2: var(--l-accent-2);
  color-scheme: light;
  color: var(--fg);
}
.bar .glass[data-over="light"] {
  --bg: var(--d-bg); --panel: var(--d-panel); --panel-2: var(--d-panel-2);
  --fg: var(--d-fg); --muted: var(--d-muted); --faint: var(--d-faint);
  --dim: var(--d-dim); --line: var(--d-line); --accent: var(--d-accent);
  --accent-fg: var(--d-accent-fg); --accent-2: var(--d-accent-2);
  color-scheme: dark;
  color: var(--fg);
}
.bar .icon-btn { border-color: transparent; }
.bar .icon-btn:hover { background: var(--panel-2); }
/* Idioma: "ES · EN" con el actual en tinta; lleva a la misma página del otro lado. */
.lang-switch {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 14px;
  border-radius: var(--r-pill);
  font: 500 13px/1 var(--f-mono);
  letter-spacing: .04em;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--t-hover) ease, color var(--t-hover) ease;
}
.lang-switch b { font-weight: 500; color: var(--fg); }
.lang-switch:hover { background: var(--panel-2); color: var(--fg); }
.menu-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-width: 44px;
  min-height: 44px;
  padding: 0 18px;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: inherit;
  font: 500 14px/1 var(--f-body);
  cursor: pointer;
  transition: background-color var(--t-hover) ease;
}
.menu-btn:hover { background: var(--panel-2); }
.menu-btn svg { width: 18px; height: 18px; flex: none; }
/* En el teléfono quedan la marca, "Donar" y el botón del menú: el modo y el
   idioma están dentro del menú. */
@media (max-width: 560px) {
  .bar .hide-s { display: none; }
  .menu-btn { width: 44px; padding: 0; }
  .bar .btn-sm { padding: 0 16px; }
}
@media (max-width: 400px) {
  .bar-in { gap: 8px; }
  .bar .brand { gap: 8px; padding: 0 12px 0 8px; font-size: 17px; }
}

/* Fila superior del menú y de la cortina: misma altura que la cabecera, con la
   marca y el botón de cerrar donde están la marca y "Menú". */
.shell-top { min-height: 58px; }
.shell-top .brand { padding-left: 17px; }
.shell-top > .btn { margin-right: 7px; }

/* ---- Menú de pantalla completa (D7) --------------------------------------------
   Colores inversos (.inv), entra en 380 ms bajando 14 px. Ocho entradas en
   grande con su nota; la actual atenuada con "Estás aquí". */
html.menu-open, html.menu-open body { overflow: hidden; }
.menu {
  position: fixed;
  inset: 0;
  z-index: 100;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: clamp(24px, 4vw, 48px);
  padding-top: calc(env(safe-area-inset-top, 0px) + 12px);
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 28px);
  animation: lw-menu-in .38s var(--ease-out) both;
}
@keyframes lw-menu-in { from { opacity: 0; transform: translateY(-14px); } to { opacity: 1; transform: none; } }
.menu-body {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
  column-gap: clamp(32px, 6vw, 96px);
  row-gap: 40px;
  flex: 1 0 auto;
  align-content: start;
}
@media (max-width: 860px) { .menu-body { grid-template-columns: minmax(0, 1fr); } }
.menu-links { display: flex; flex-direction: column; }
.menu-links a {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 2px 16px;
  padding-block: clamp(10px, .85vw, 12px);
  border-bottom: 1px solid var(--line);
  text-decoration: none;
  font-family: var(--f-head);
  font-weight: var(--w-display);
  font-size: clamp(32px, 4.4vw, 62px);
  line-height: 1.05;
  letter-spacing: calc(var(--track-display) * .9);
  transition: padding-left .25s var(--ease-out), color .25s ease;
}
.menu-links a > span { min-width: 0; }
/* La nota salta a su propia línea si no cabe (teléfono con juego "original"). */
.menu-links small {
  margin-left: auto;
  font: 500 12px/1.3 var(--f-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: right;
}
.menu-links a:hover { padding-left: 14px; color: var(--accent-2); }
.menu-links a[aria-current="page"] { color: var(--faint); }
.menu-links a[aria-current="page"]:hover { padding-left: 0; }

.menu-side { display: flex; flex-direction: column; gap: 28px; padding-top: clamp(0px, 1.4vw, 18px); }
.menu-side dl { display: flex; flex-direction: column; gap: 22px; }
.menu-side dt { margin-bottom: 6px; font: 500 12px/1.4 var(--f-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.menu-side dd { font-size: 17px; line-height: 1.5; overflow-wrap: anywhere; }
.menu-side dd a {
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  transition: color var(--t-hover) ease, border-color var(--t-hover) ease;
}
.menu-side dd a:hover { color: var(--accent-2); border-color: currentColor; }
.menu-maps { display: flex; flex-wrap: wrap; gap: 4px 20px; margin-top: 10px; }
/* En presentación el marcador de la dirección no está: Maps y Waze quedan
   solos y no necesitan el aire que los separaba de él. */
:root[data-view="presentacion"] .menu-maps { margin-top: 0; }
.menu-maps a { display: inline-flex; align-items: center; gap: 6px; min-height: 24px; }
.menu-maps svg { width: 14px; height: 14px; flex: none; }
.menu-row { display: flex; flex-wrap: wrap; gap: 8px; }
/* Menú en el teléfono: lo que se toca, que sea botón. Maps y Waze, el
   WhatsApp y el correo eran enlaces de texto de 21 a 27 px de alto; ahora son
   botones de contorno (dos a la par los mapas, a todo el ancho los otros dos).
   Los chips de redes se reparten el ancho y suben a 48 px. "Donar" ya lo cubre
   la regla general de .btn. */
@media (max-width: 560px) {
  .menu-side dd a {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 52px;
    padding: 8px 18px;
    border: 1px solid color-mix(in srgb, var(--fg) 24%, transparent);
    border-radius: var(--r-pill);
    font-size: 16px;
    text-align: center;
  }
  .menu-side dd a:hover { border-color: var(--fg); color: var(--fg); }
  .menu-maps { flex-wrap: nowrap; gap: 10px; }
  .menu-maps a { flex: 1 1 0; min-width: 0; }
  .menu-row { gap: 10px; }
  .menu-row .chip { flex: 1 1 0; min-width: 0; min-height: 48px; justify-content: center; }
  .seg { height: 56px; max-width: none; }
  .seg-item { height: 48px; font-size: 15px; }
}

/* Preferencias del menú: idioma y tema, cada uno con su rótulo a la izquierda
   y un control segmentado a la derecha. .pref usa display: contents para que
   los cuatro hijos caigan en la rejilla de .prefs: así las dos columnas miden
   lo mismo en las dos filas y los controles quedan alineados. En el teléfono
   el rótulo se va arriba y el control ocupa todo el ancho. */
.prefs {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  align-items: start;
  column-gap: 16px;
  row-gap: clamp(20px, 3vw, 32px);
  padding-top: clamp(20px, 3vw, 32px);
  border-top: 1px solid var(--line);
}
.pref { display: contents; }
/* El rótulo se centra contra el control (48 px), no contra toda la fila: la
   del tema es más alta porque lleva la línea de ayuda debajo. */
.pref-h { padding-top: 16px; font: 500 12px/1.4 var(--f-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
/* Solo con el tema automático: explica a qué está siguiendo. */
.pref-hint { display: none; margin-top: 10px; font: 500 12px/1.4 var(--f-mono); letter-spacing: .04em; color: var(--muted); }
html:not([data-theme]) .pref-hint { display: block; }
@media (max-width: 560px) {
  .prefs { display: flex; flex-direction: column; align-items: stretch; gap: clamp(20px, 3vw, 32px); }
  .pref { display: flex; flex-direction: column; align-items: stretch; gap: 10px; }
  .pref-h { padding-top: 0; }
  .seg { max-width: none; }
}

/* ---- "Sigue" (D9) ----------------------------------------------------------------
   Enlace grande a la siguiente entrada del menú, con el círculo de flecha.
   Compactado el 2026-09-19: el título llegaba a 148 px y el bloque, con su
   aire, se comía casi una pantalla entera solo para decir "Sigue". Ahora el
   título tope en 76 px, el aire vertical en 56 y el círculo en 64. Vale igual
   para "Vuelve a" (las páginas de cada fundación), que usa el mismo marcado. */
.next {
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1.6vw, 16px);
  padding-block: clamp(28px, 4vw, 56px);
  border-top: 1px solid var(--line);
  color: inherit;
  text-decoration: none;
}
.next-row { display: flex; align-items: center; justify-content: space-between; gap: clamp(16px, 3vw, 24px); }
/* En el teléfono baja a 32 px para que "Ministerios" o "Newsletters" quepan
   con el círculo a 360 px. */
.next-title {
  min-width: 0;
  overflow-wrap: break-word;
  font-family: var(--f-head);
  font-weight: var(--w-display);
  font-size: clamp(32px, 5.2vw, 76px);
  line-height: 1;
  letter-spacing: calc(var(--track-display) * 1.1);
  transition: color .25s ease, transform .4s var(--ease-out);
}
.next:hover .next-title { color: var(--accent-2); transform: translateX(14px); }
.next .row-go { width: clamp(56px, 4.6vw, 64px); height: clamp(56px, 4.6vw, 64px); flex: none; }
.next .row-go svg { width: clamp(20px, 1.7vw, 24px); height: clamp(20px, 1.7vw, 24px); }
.next:hover .row-go { background: var(--accent); color: var(--accent-fg); border-color: transparent; }

/* ---- Pie ------------------------------------------------------------------------ */
.foot {
  display: flex;
  flex-direction: column;
  gap: clamp(40px, 6vw, 80px);
  padding-block: clamp(48px, 7vw, 96px) 28px;
  border-top: 1px solid var(--line);
}
.foot-top { display: grid; grid-template-columns: minmax(0, 5fr) repeat(3, minmax(0, 2.4fr)); gap: 36px 24px; }
.foot-brand { display: flex; flex-direction: column; align-items: flex-start; gap: 20px; }
.foot-brand .brand { padding-left: 0; font-size: 24px; }
.foot-brand .text { max-width: 34ch; }
.foot-h { margin-bottom: 14px; font: 500 12px/1.4 var(--f-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.foot li a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-block: 7px;
  text-decoration: none;
  overflow-wrap: anywhere;
  transition: color var(--t-hover) ease;
}
.foot li a:hover { color: var(--accent-2); }
.foot-bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 12px 24px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
  font: 400 13px/1.5 var(--f-mono);
  color: var(--muted);
}
.foot-bottom nav { display: flex; flex-wrap: wrap; gap: 6px 20px; }
.foot-bottom a { display: inline-flex; align-items: center; min-height: 44px; text-decoration: none; transition: color var(--t-hover) ease; }
.foot-bottom a:hover { color: var(--fg); }
/* Desde 761 px el botón flotante de WhatsApp queda encima del final de esta
   línea al llegar al pie (con o sin la barra de la maqueta): se le deja libre
   su ancho (56 px) más 16 px. En el teléfono la línea se apila a la izquierda
   y no choca. */
@media (min-width: 761px) { .foot-bottom { padding-right: 72px; } }
@media (max-width: 760px) {
  .foot-top { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .foot-top > :first-child, .foot-top > :last-child { grid-column: 1 / -1; }
}

/* ---- Botón flotante de WhatsApp --------------------------------------------------
   56 px con el verde de marca de WhatsApp (--wa, igual en claro y en oscuro:
   es el logo de otra marca, ver tokens.css). Hasta el 2026-09-18 iba monocromo
   en tinta, como pedía el brief; Daniel prefirió el verde. El anillo de --bg lo
   separa de una cápsula inversa que tenga detrás. */
.fab {
  position: fixed;
  right: var(--gutter);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 16px);
  z-index: 45;
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--wa);
  color: var(--wa-fg);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--bg) 40%, transparent);
  text-decoration: none;
  transition: background-color var(--t-hover) ease;
}
.fab svg { width: 26px; height: 26px; }
.fab:hover { background: var(--wa-hover); }
/* El acento teal sobre el verde no se distingue: el foco va en tinta. */
.fab:focus-visible { outline-color: var(--fg); }

/* Los demás enlaces a WhatsApp conservan su forma (botón de contorno, fila de
   datos): solo el glifo pasa a verde, con el tono que se lea sobre el fondo de
   cada modo (--wa-ink). El texto no cambia de color. */
a[href*="whatsapp.com"]:not(.fab) svg,
a[href*="wa.me"]:not(.fab) svg { color: var(--wa-ink); }
/* El glifo de WhatsApp no es una flecha: no se desliza al pasar el puntero
   (eso es para las flechas, que indican a dónde va el enlace) y va un punto
   más grande, porque la burbuja con el auricular necesita más aire que una
   flecha para leerse. */
.btn[href*="whatsapp.com"] svg,
.btn[href*="wa.me"] svg { width: 18px; height: 18px; }
.btn[href*="whatsapp.com"]:hover svg,
.btn[href*="wa.me"]:hover svg { transform: none; }

/* ---- Indicador de scroll táctil (D9) ------------------------------------------------
   Pista de 92 px y pulgar de 30 px; site.js lo mueve. Solo con puntero grueso. */
.sind {
  position: fixed;
  right: 5px;
  top: 50%;
  z-index: 40;
  display: none;
  width: 3px;
  height: 92px;
  margin-top: -46px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--fg) 14%, transparent);
  pointer-events: none;
}
.sind b { display: block; width: 3px; height: 30px; border-radius: var(--r-pill); background: var(--accent); will-change: transform; }
@media (hover: none) and (pointer: coarse) { .sind:not([hidden]) { display: block; } }

/* ---- Cortina entre páginas (D8) ------------------------------------------------------
   is-in: sube en 550 ms (desde la página). is-cover: aparece puesta (desde el
   menú, que ya es del mismo color). is-arrive: puesta al llegar, con el título
   quieto y la línea que termina de crecer. is-out: sale hacia arriba en 750 ms. */
.curtain {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 24px;
  padding-top: calc(env(safe-area-inset-top, 0px) + 12px);
  padding-bottom: calc(env(safe-area-inset-bottom, 0px) + clamp(28px, 6vw, 72px));
  will-change: transform;
}
.curtain.is-in { animation: lw-curtain-in .55s var(--ease-curtain) both; border-radius: var(--r-lg) var(--r-lg) 0 0; }
.curtain.is-out { animation: lw-curtain-out .75s var(--ease-curtain) both; border-radius: 0 0 var(--r-lg) var(--r-lg); }
@keyframes lw-curtain-in { from { transform: translateY(100%); } to { transform: none; } }
@keyframes lw-curtain-out { from { transform: none; } to { transform: translateY(-100%); } }
/* 5.3 pide clamp(52px,13vw,200px); el mínimo baja a 40 px para que
   "Ministerios" quepa entero a 360 px con el juego "original". */
.curtain-title {
  display: block;
  overflow: hidden;
  padding-bottom: .08em;
  font-family: var(--f-head);
  font-weight: var(--w-display);
  font-size: clamp(40px, 13vw, 200px);
  line-height: 1;
  letter-spacing: calc(var(--track-display) * 1.1);
}
.curtain-title > span { display: inline-block; animation: lw-title-up .6s .15s var(--ease-out) both; }
@keyframes lw-title-up { from { transform: translateY(105%); } to { transform: none; } }
.curtain-line { height: 2px; border-radius: 2px; background: var(--line); overflow: hidden; }
.curtain-line b { display: block; height: 100%; background: var(--accent); transform-origin: left; animation: lw-line-grow 1.25s cubic-bezier(.4, 0, .2, 1) both; }
@keyframes lw-line-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.curtain.is-arrive .curtain-title > span { animation: none; }
.curtain.is-arrive .curtain-line b { animation: lw-line-end .45s var(--ease-out) both; }
@keyframes lw-line-end { from { transform: scaleX(.6); } to { transform: scaleX(1); } }
/* Tapa mientras llega la cortina de verdad: el script del <head> pone
   data-curtain="1" antes del primer pintado y site.js lo cambia a "2" cuando
   muestra la cortina. Si site.js no carga, la tapa se va sola a los 1.5 s. */
html[data-curtain="1"] body[data-page]::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 119;
  background: var(--inv-bg);
  animation: lw-cover-off 0s linear 1.5s forwards;
}
@keyframes lw-cover-off { to { visibility: hidden; } }

/* ---- Entrada de cada página (5.5) ----------------------------------------------------
   Los tres primeros hijos de <main> suben 36 px con fundido en 900 ms,
   escalonados 80 ms. Solo CSS: la clase la pone el script del <head> (sin JS
   no hay clase y el contenido se ve tal cual). Si se llega con la cortina,
   empiezan cuando la cortina ya está saliendo. */
:root { --enter-delay: 0s; }
html[data-curtain] { --enter-delay: .5s; }
@keyframes lw-rise { from { opacity: 0; transform: translateY(36px); } to { opacity: 1; transform: none; } }
@keyframes lw-fade { from { opacity: 0; } to { opacity: 1; } }
.lw-enter body[data-page] > main > :nth-child(-n+3) { animation: lw-rise .9s var(--ease-out) var(--enter-delay) both; }
.lw-enter body[data-page] > main > :nth-child(2) { animation-delay: calc(var(--enter-delay) + 80ms); }
.lw-enter body[data-page] > main > :nth-child(3) { animation-delay: calc(var(--enter-delay) + 160ms); }
.lw-calm body[data-page] > main { animation: lw-fade .15s ease both; }

/* ---- Revelado al bajar y parallax de portada (2026-09-19) ---------------------
   REVELADO. Cada bloque entra con un fundido y 24 px de subida la primera vez
   que llega a la vista (IntersectionObserver en site.js, una sola vez por
   elemento). El estado oculto vive SOLO en los elementos que site.js marca con
   data-reveal: si site.js no carga, no hay atributo y no hay nada invisible.
   Es la diferencia con la entrada de página de arriba, que sí cuelga de una
   clase del <head>: aquella dura 900 ms y se acaba sola; esta esperaría al
   scroll para siempre.

   El escalonado (--rv-d) lo pone site.js en línea, elemento por elemento.
   --rv-y es cuánto sube: baja a 0 en los que ya tienen un antepasado
   revelándose, porque si no se sumarían los dos desplazamientos.

   Con movimiento reducido site.js no marca nada; el @media de abajo es el
   cinturón por si el ajuste cambia con la página ya abierta.
   Con ?still=1 (capturas) site.js tampoco marca: todo se ve de una.          */
[data-reveal] {
  opacity: 0;
  transform: translateY(var(--rv-y, 24px));
  transition: opacity .66s var(--ease-out) var(--rv-d, 0s),
              transform .66s var(--ease-out) var(--rv-d, 0s);
}
[data-reveal="in"] { opacity: 1; transform: none; }

/* PARALLAX. La foto de las portadas (.cover) se mueve hasta 40 px contra el
   scroll. La clase .lw-px la pone site.js: sin JS, sin movimiento o con
   ?still=1 la portada queda como siempre. La imagen se estira 96 px (48 por
   lado) para que el recorrido de 40 nunca destape un borde, y solo se anima
   transform, que no obliga a recalcular la maqueta. */
.lw-px .cover > img {
  top: -48px;
  bottom: auto;
  height: calc(100% + 96px);
  transform: translate3d(0, var(--px, 0px), 0) scale(var(--cover-scale, 1));
  will-change: transform;
}

/* ---- Rótulos de sección (D17) -------------------------------------------------------------
   Ocultos de fábrica desde el 2026-09-18, cuando salió la barra flotante que
   los encendía: ahora es ?rotulos=1 (site.js) lo que pone .show-blocks en
   <html>, y cada [data-block] lleva un contorno discontinuo del acento y una
   píldora con su nombre. Sirven para pedir cambios por nombre de sección. */
.show-blocks [data-block] { outline: 1px dashed color-mix(in srgb, var(--accent) 75%, transparent); outline-offset: -1px; }
.show-blocks [data-block]:not(.fab):not(.bar) { position: relative; }
.show-blocks [data-block]::after {
  content: attr(data-block);
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 6;
  padding: 7px 10px;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--accent-fg);
  font: 500 12px/1 var(--f-mono);
  letter-spacing: .04em;
  white-space: nowrap;
  pointer-events: none;
}
.show-blocks .fab::after { top: auto; right: 0; bottom: calc(100% + 6px); left: auto; }
.show-blocks .bar::after { top: calc(100% + 6px); left: var(--gutter); }

/* La única salida visible de los Rótulos: píldora fija abajo a la izquierda,
   en colores inversos (.inv), que solo existe mientras están puestos. Así
   nadie se queda con los contornos encima sin saber cómo quitarlos. Deja
   libre la esquina del botón de WhatsApp (56 px más aire). */
.blocks-note {
  position: fixed;
  left: var(--gutter);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 16px);
  z-index: 46;
  display: none;
  align-items: center;
  gap: 2px;
  max-width: calc(100% - var(--gutter) * 2 - 72px);
  height: 44px;
  padding-left: 14px;
  border-radius: var(--r-pill);
  font: 500 12px/1 var(--f-mono);
  letter-spacing: .04em;
}
.show-blocks .blocks-note { display: flex; }
.blocks-note b { min-width: 0; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.blocks-note button {
  flex: none;
  min-height: 44px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
  transition: background-color var(--t-hover) ease;
}
.blocks-note button:hover { background: var(--panel-2); }

/* ---- Movimiento reducido ----------------------------------------------------------
   Sin desplazamientos: quedan solo los cambios de color, que son fundidos. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .btn svg, .row, .faq summary i, .faq summary i::after { transition: none; }
  .btn:hover svg { transform: none; }
  .row:hover { padding-inline: 0; }
  /* Armazón: el menú (provocado) queda en un fundido de 150 ms; la cortina no
     se usa (site.js navega directo) y la página entra con fundido (lw-calm). */
  .menu { animation: lw-fade .15s ease both; }
  /* El ícono del tema y el pulgar del segmentado saltan al estado nuevo. */
  .theme-btn .t-ico, .seg-thumb { transition: none; }
  .menu-links a, .next-title { transition: color .25s ease; }
  .menu-links a:hover, .next:hover .next-title { padding-left: 0; transform: none; }
  /* Revelado y parallax: site.js ya no los enciende, esto es el cinturón. */
  [data-reveal] { opacity: 1; transform: none; transition: none; }
  .lw-px .cover > img { top: 0; bottom: 0; height: 100%; transform: scale(var(--cover-scale, 1)); }
}

/* ==========================================================================
   Intro "Dos aguas" (U3, LOOP.md 5.6): solo /index.html
   Una pantalla sin scroll, siempre oscura (.on-dark en el <body>), sin armazón.
   Estados, en <html>:
   - Sin clase (sin JS): el estado final, quieto. Las dos mitades se ven y
     funcionan como enlaces normales; el versículo muestra las dos líneas.
   - .intro-play (la pone intro.js antes del primer pintado): los tiempos van
     solo en CSS, con retrasos. 0.1 s el caligráfico se escribe (1.1 s);
     0.4 s "Ministries International"; 1.2 s el versículo y la capa de las
     mitades; 2.0 s el título sube, la línea crece y entran las mitades. Si
     intro.js fallara después, las animaciones terminan igual en el final.
     A los ~25 s intro.js la quita (WCAG 2.2.2): queda el estado sin clase.
   - .is-split (intro.js, cuando empieza el tiempo 3): habilita el hover.
   - .intro-calm: movimiento reducido. Todo quieto, un fundido de 200 ms.
   Capas: el video lleva la de 5.6 (.55) y cada mitad suma la suya (.38), que
   da .72 en total: con .55 sobre la gota clara el texto chico no llega a
   4.5:1. Al pasar el cursor la mitad baja a .65 en total y la otra sube a
   .82. Son los únicos colores literales: van sobre el video.
   ========================================================================== */
.intro {
  --cal-w: clamp(150px, 22vw, 320px);   /* ancho final del caligráfico (316 × 106) */
  --head-big: 1.6;                      /* escala del título mientras está al centro */
  --sub-fs: clamp(14px, 1.35vw, 19px);
  --vh50: 50vh;
  --head-top: calc(env(safe-area-inset-top, 0px) + clamp(16px, 3.5vh, 36px));
  --band-top: calc(var(--head-top) + var(--cal-w) * .3354 + 6px + var(--sub-fs) * 1.3 + clamp(20px, 4vh, 44px));
  --verse-bottom: calc(env(safe-area-inset-bottom, 0px) + clamp(16px, 3.5vh, 32px));
  --verse-lines: 2;
  --band-bottom: calc(var(--verse-bottom) + var(--verse-lines) * 19.5px + clamp(20px, 4vh, 44px));
  --pad-in: clamp(24px, 4.4vw, 64px);   /* del texto a la línea */
  --pad-mid: clamp(20px, 4vh, 40px);    /* lo mismo, en vertical */
  --word-fs: clamp(40px, 8vw, 120px); /* 5.6 */
  --fit: 18.8cqi;                       /* tope del titular: que "Bienvenido" quepa en su mitad */
  --veil-rest: rgba(2, 43, 53, .38);
  --veil-lift: rgba(2, 43, 53, .22);
  --veil-dim: rgba(2, 43, 53, .6);
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  overscroll-behavior: none;
}
@supports (height: 1svh) { .intro { --vh50: 50svh; } }
.intro-play .intro { --verse-lines: 1; }
@media (max-width: 640px) {
  .intro { --verse-lines: 4; }
  .intro-play .intro { --verse-lines: 2; }
}
/* Medido: "Bienvenido" mide 5.14 em en Sora 300; con el tope cabe aun en la
   mitad que se achica (1 : 1.35). */

/* ---- Fondo: póster y video con la capa de 5.6 ---- */
.intro-bg { position: fixed; inset: 0; z-index: 0; background: var(--bg); }
.intro-bg img,
.intro-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Sin src (sin JS, ahorro de datos o movimiento reducido) el video no se
   muestra: sin JS Chrome le pondría sus controles encima del póster. */
.intro-video:not([src]) { display: none; }
/* Respaldo de intro.js: el botón de play que WebKit pinta sobre un video al que
   le bloqueó el autoplay (iPhone en bajo consumo). El video es decorativo y
   nunca lleva controles, así que ese botón no debe verse ni un instante. */
.intro-video::-webkit-media-controls-start-playback-button { display: none !important; -webkit-appearance: none; }
.intro-bg::after { content: ""; position: absolute; inset: 0; background: rgba(2, 43, 53, .55); }

/* ---- Título: el caligráfico (texto accesible en el alt) y la bajada ---- */
.intro-head {
  position: fixed;
  top: var(--head-top);
  left: 0;
  right: 0;
  z-index: 2;
  width: max-content;
  max-width: calc(100% - 2 * var(--gutter));
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  font-family: var(--f-display);
  font-weight: var(--w-display);
  font-size: var(--sub-fs);
  line-height: 1.3;
  letter-spacing: .02em;
  word-spacing: normal;
  text-align: center;
  color: var(--sand);
  pointer-events: none;
}
.intro-cal { width: var(--cal-w); height: auto; }

/* ---- Las dos mitades: cada una es un <a> de pantalla completa ---- */
.intro-langs { position: fixed; inset: 0; z-index: 1; display: flex; }
.intro-half {
  position: relative;
  isolation: isolate;
  container-type: inline-size;
  flex: 1 1 0;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(14px, 2.2vh, 24px);
  padding-block: var(--band-top) var(--band-bottom);
  color: var(--fg);
  text-decoration: none;
  transition: flex-grow .45s var(--ease-out);
}
/* Las dos miran a la línea: español alineado a la derecha, inglés a la izquierda. */
.intro-half:first-child { align-items: flex-end; text-align: right; padding-inline: var(--gutter) var(--pad-in); }
.intro-half:last-child { align-items: flex-start; padding-inline: var(--pad-in) var(--gutter); }
.intro-half::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--veil-rest);
  transition: background-color .45s ease;
}
/* La línea de 1 px del acento, entre el título y el versículo. Es un
   elemento de ancho 0 entre las dos mitades: sigue a la frontera cuando una
   crece al pasar el cursor. */
.intro-line { position: relative; z-index: 1; flex: none; width: 0; }
.intro-line::before {
  content: "";
  position: absolute;
  top: var(--band-top);
  bottom: var(--band-bottom);
  left: 0;
  width: 1px;
  background: var(--accent);
}
/* Foco: marco de 2 px del acento por dentro de la mitad. No llega a los
   bordes para no cruzar el título ni el versículo, que van encima. */
.intro-half:focus-visible { outline: none; }
.intro-half::after {
  content: "";
  position: absolute;
  z-index: 1;
  inset: calc(var(--band-top) - 12px) 12px calc(var(--band-bottom) - 12px);
  border: 2px solid var(--accent);
  border-radius: var(--r-md);
  opacity: 0;
  pointer-events: none;
}
.intro-half:focus-visible::after { opacity: 1; }
.intro-half > * { flex: none; max-width: 100%; }
/* Sobre el video el rótulo va en tinta: --muted no llega a 4.5:1. */
.intro-label { color: var(--fg); }
.intro-word {
  display: block;
  white-space: nowrap;
  font-family: var(--f-display);
  font-weight: var(--w-display);
  font-size: min(var(--word-fs), var(--fit));
  /* Alto fijo: si la mitad se achica, la palabra baja de tamaño sin mover
     el rótulo ni "Entrar" (quedan alineados con los de la otra mitad). */
  line-height: calc(var(--word-fs) * 1.04);
  letter-spacing: var(--track-display);
  color: var(--sand);
}
.intro-enter { display: inline-flex; align-items: center; gap: 14px; min-height: 44px; font: 500 15px/1 var(--f-body); }

/* ---- Versículo: Juan 4:14 en los dos idiomas ---- */
.intro-verse {
  position: fixed;
  left: var(--gutter);
  right: var(--gutter);
  bottom: var(--verse-bottom);
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  font: 400 13px/1.5 var(--f-mono);
  color: var(--fg);
  text-align: center;
  text-wrap: balance;
  pointer-events: none;
}
/* Una sola línea a la vez: la de la mitad que se está mirando (intro.js pone
   .intro-verse-one en <html> y .is-en en el versículo). Las dos ocupan la
   misma celda y se cruzan con un fundido. Sin JS no hay clase y se ven las
   dos, una debajo de la otra. */
.intro-verse-one .intro-verse { display: grid; }
.intro-verse-one .intro-verse > span { grid-area: 1 / 1; align-self: end; transition: opacity .45s ease; }
.intro-verse-one .intro-verse > span + span,
.intro-verse-one .intro-verse.is-en > span:first-child { opacity: 0; }
.intro-verse-one .intro-verse.is-en > span + span { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .intro-verse-one .intro-verse > span { transition: none; }
}

/* ---- Hover: solo con cursor y ya divididas ---- */
@media (hover: hover) {
  :is(html:not(.intro-play), .is-split) .intro-langs:hover .intro-half::before { background-color: var(--veil-dim); }
  :is(html:not(.intro-play), .is-split) .intro-langs .intro-half:hover::before { background-color: var(--veil-lift); }
  :is(html:not(.intro-play), .is-split) .intro-half:hover .row-go { background: var(--accent); color: var(--accent-fg); border-color: transparent; }
}
/* Crece la mitad con el cursor o con el foco del teclado; solo en columnas,
   para que en filas cada una siga midiendo la mitad del alto. */
@media (orientation: landscape) and (prefers-reduced-motion: no-preference) {
  :is(html:not(.intro-play), .is-split) .intro-half:focus-visible { flex-grow: 1.35; }
}
@media (hover: hover) and (orientation: landscape) and (prefers-reduced-motion: no-preference) {
  :is(html:not(.intro-play), .is-split) .intro-half:hover { flex-grow: 1.35; }
}

/* ---- Tiempos (solo con .intro-play) ---- */
.intro-play .intro-cal { animation: intro-write 1.1s var(--ease-out) .1s backwards; }
.intro-play .intro-sub { animation: lw-fade .8s ease .4s backwards; }
.intro-play .intro-verse,
.intro-play .intro-half::before { animation: lw-fade .8s ease 1.2s backwards; }
.intro-play .intro-head { animation: intro-rise .9s var(--ease-curtain) 2s backwards; }
.intro-play .intro-line::before { animation: intro-line .9s var(--ease-curtain) 2.1s backwards; }
.intro-play .intro-half > * { animation: lw-rise .8s var(--ease-out) 2.3s backwards; }
.intro-play .intro-half:last-child > * { animation-delay: 2.38s; }
@keyframes intro-write { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes intro-rise {
  from { transform: translateY(calc(var(--vh50) - var(--head-top))) translateY(-50%) scale(var(--head-big)); }
}
/* Un solo nombre para columnas y filas: si el nombre cambiara con la
   orientación, al girar el teléfono la animación empezaría de nuevo. */
@keyframes intro-line { from { clip-path: inset(50%); } to { clip-path: inset(0); } }
.intro-calm .intro-bg,
.intro-calm .intro-main { animation: lw-fade .2s ease backwards; }

/* ---- Tiempo 4: el círculo del acento con el idioma elegido ----
   En el acento claro (#007E99): el blanco sobre el cyan oscuro da 2.1:1. */
.intro-go {
  position: fixed;
  inset: 0;
  z-index: 10;
  display: grid;
  place-items: center;
  padding: var(--gutter);
  background: var(--l-accent);
  color: var(--l-accent-fg);
  clip-path: circle(0% at 50% 50%);
}
.intro-calm .intro-go { clip-path: none; }
.intro-go > span {
  font-family: var(--f-head);
  font-weight: var(--w-display);
  font-size: clamp(40px, 13vw, 200px);
  line-height: 1;
  letter-spacing: calc(var(--track-display) * 1.1);
  text-align: center;
}

/* ---- En vertical: filas que se miran sobre la línea ----
   El título queda en una franja sobre la mitad de arriba y el versículo
   bajo la de abajo; cada mitad mide el 50 % del alto. */
@media (orientation: portrait) {
  .intro-langs { flex-direction: column; }
  .intro-half { flex-basis: 50%; } /* mitades exactas aunque el relleno difiera */
  .intro-half:first-child,
  .intro-half:last-child { align-items: center; text-align: center; padding-inline: var(--gutter); }
  .intro-half:first-child { justify-content: flex-end; padding-block: var(--band-top) var(--pad-mid); }
  .intro-half:last-child { justify-content: flex-start; padding-block: var(--pad-mid) var(--band-bottom); }
  .intro-half:first-child::after { inset: calc(var(--band-top) - 12px) 12px 12px; }
  .intro-half:last-child::after { inset: 12px 12px calc(var(--band-bottom) - 12px); }
  .intro-line { width: auto; height: 0; }
  .intro-line::before { top: 0; bottom: auto; left: var(--gutter); right: var(--gutter); width: auto; height: 1px; }
  .intro { --word-fs: clamp(32px, 10vw, 64px); }
}

/* ---- Movimiento reducido: el hover queda en fundidos de 200 ms ---- */
@media (prefers-reduced-motion: reduce) {
  .intro-half,
  .intro-half::before,
  .intro-half .row-go { transition-duration: .2s; }
}

/* ---- Nosotros (U5) ---- */
/* El árbol (.tree) de la sección Estructura se retiró el 2026-09-19 (tarde):
   Nosotros y About eran las dos únicas páginas que lo usaban, y ahí lo
   reemplazó el recorrido del apoyo (.recorrido, bloque "pagina:nosotros-lwf"),
   que dice lo mismo en mucho menos alto. Las tarjetas .founds que hubo entre
   medio, esa misma tarde, también se borraron con él. */

/* Los cuatro rótulos de cada fundación (propósito, estructura, misión, rol):
   dos columnas con regla superior en tinta y reglas finas; una en el teléfono. */
.pillars {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(24px, 3vw, 48px);
  border-top: 1px solid var(--fg);
}
.pillars > div { display: flex; flex-direction: column; gap: 14px; padding-block: 22px 26px; border-bottom: 1px solid var(--line); min-width: 0; }
.pillars dd { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; margin: 0; color: var(--muted); }
.pillars dd > .ph-text { align-self: stretch; }
@media (max-width: 760px) { .pillars { grid-template-columns: minmax(0, 1fr); } }

/* Lo que creemos: tres frases numeradas en --f-head, con regla superior en
   tinta y reglas finas, como la línea de tiempo. */
.beliefs { border-top: 1px solid var(--fg); counter-reset: creo; }
.beliefs > li {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr);
  gap: 4px 16px;
  padding-block: 22px;
  border-bottom: 1px solid var(--line);
  font-family: var(--f-head);
  font-weight: var(--w-head);
  font-size: clamp(19px, 1.9vw, 26px);
  line-height: 1.35;
  letter-spacing: var(--track-head);
  text-wrap: pretty;
}
.beliefs > li::before {
  counter-increment: creo;
  content: "0" counter(creo);
  font: 500 13px/2.2 var(--f-mono);
  letter-spacing: .04em;
  color: var(--accent-2);
}
.beliefs + .split .small { max-width: 52ch; }
@media (max-width: 560px) {
  .beliefs > li { grid-template-columns: 28px minmax(0, 1fr); column-gap: 10px; }
}

/* ===== Donar (U6) ===== */
/* Cómo funciona (.steps): tres pasos en columnas con regla superior en tinta
   y regla fina entre ellos, como los de la maqueta del demo; uno debajo del
   otro en el teléfono. */
.steps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.step { display: flex; flex-direction: column; gap: 14px; min-width: 0; padding: 28px 28px 8px 0; border-top: 1px solid var(--fg); }
.step + .step { padding-left: 28px; border-left: 1px solid var(--line); }
.step > .ph-text { align-self: stretch; }
@media (max-width: 760px) {
  .steps { grid-template-columns: minmax(0, 1fr); }
  .step, .step + .step { padding: 24px 0 28px; border-left: 0; }
  .step + .step { border-top-color: var(--line); }
}

/* Tarjetas de donación (.gives / .give): una por ministerio, con el tipo en
   rótulo, el nombre y abajo el botón "Donar" (o su marcador) y "Ver ficha".
   Panel claro con borde fino, sin sombra. Tres columnas, dos bajo 1000 px y
   una en el teléfono; el pie de cada tarjeta queda alineado abajo. */
.gives { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(12px, 1.6vw, 24px); }
@media (max-width: 1000px) { .gives { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .gives { grid-template-columns: minmax(0, 1fr); } }
.give {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  min-width: 0;
  min-height: clamp(200px, 17vw, 236px);
  padding: clamp(22px, 2.4vw, 32px);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--panel);
}
.give > .h3 { font-size: clamp(21px, 2vw, 28px); line-height: 1.2; }
.give-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; margin-top: auto; padding-top: 16px; }
.give-more {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 15px;
  color: var(--muted);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--fg) 24%, transparent);
  text-underline-offset: 4px;
  transition: color var(--t-hover) ease, text-decoration-color var(--t-hover) ease;
}
.give-more:hover { color: var(--fg); text-decoration-color: var(--accent); }
.give-general { align-items: center; }
/* En una sola columna el alto mínimo solo abría un hueco sobre el botón. */
@media (max-width: 600px) { .give { min-height: 0; } }

/* LWF USA: la cápsula inversa en dos columnas (texto y botones | datos). */
.give-usa { row-gap: clamp(28px, 4vw, 48px); }
@media (min-width: 901px) { .give-usa .facts { align-self: start; } }

/* ===== Ministerios (U6) ===== */
/* Fichas de ministerio (5.7): retrato 4:5 a la izquierda y el texto a la
   derecha, como la bio de dos columnas de Airtable (5.8). La foto va siempre
   del mismo lado: ocho fichas seguidas se leen como un índice y los nombres
   quedan alineados. La sección abre con la regla en tinta y cada ficha cierra
   con una fina, como .rows (la última no: debajo viene la regla de .sec). De
   561 a 900 px la foto sigue al lado, más angosta; en el teléfono se apila:
   foto, nombre, tipo, bio y botón. */
.fichas { border-top: 1px solid var(--fg); }
.ficha { align-items: start; padding-block: clamp(28px, 4.4vw, 64px); border-bottom: 1px solid var(--line); }
.ficha:last-child { border-bottom: 0; }
.ficha-photo { grid-column: 1 / 5; }
.ficha-body { grid-column: 6 / 13; display: flex; flex-direction: column; align-items: flex-start; gap: 24px; min-width: 0; }
.ficha-body > hgroup { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.ficha-body > .ph-text { align-self: stretch; }
/* Cierre "y otros que se sumen": el rótulo va en la columna de la foto, como
   el riel. */
.ficha-more .ficha-photo { padding-top: 4px; }
@media (max-width: 900px) {
  .ficha-photo { grid-column: 1 / 6; }
  .ficha-body { grid-column: 6 / 13; }
}
@media (max-width: 560px) {
  .ficha-photo, .ficha-body { grid-column: 1 / -1; }
  .ficha-body { gap: 20px; }
}

/* ===== Contacto (U7) ===== */
/* Formulario y Datos lado a lado, como la página de contacto de la maqueta
   del demo: el formulario en las columnas 1 a 6 y las filas de datos en las
   8 a 12, alineados arriba. Cada mitad es su propia <section>. Bajo 1000 px
   se apilan: primero el formulario, después los datos. */
.contact-grid { align-items: start; row-gap: clamp(48px, 7vw, 80px); }
.contact-form { grid-column: 1 / 7; min-width: 0; }
.contact-data { grid-column: 8 / 13; min-width: 0; }
/* (El asunto sin elegir se ve como un placeholder: eso lo hace ahora el
   sistema, con select.input[data-empty] en el bloque de formularios.) */
/* Filas de datos: la flecha de 14 px dice que el enlace se abre fuera. */
.contact-data .facts a svg { width: 14px; height: 14px; margin-left: 6px; flex: none; }
.contact-data .facts dd small { margin-top: 4px; }
.contact-data .facts dd .ph-inline { margin-top: 10px; }
/* La última fila no cierra con regla: debajo viene la de la sección Mapa
   (como la última ficha de Ministerios). */
.contact-data .facts > div:last-child { border-bottom: 0; }
.contact-links { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }

/* Mapa (lo comparten Contacto y "Cómo llegar" de LWRC): el texto a la
   izquierda y la captura de Google Maps en las mismas
   columnas que los datos (8 a 12), donde mide casi lo mismo que el archivo
   (523 px): más ancha se vería borrosa. Se recortan los últimos 45 px de la
   captura (la franja gris y los controles de Google Maps que trae abajo).
   Apilado, el mapa no pasa de 560 px. */
.map-copy { grid-column: 1 / 7; }
.map-coord { margin-right: 8px; font: 500 12px/1.4 var(--f-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.map-link { grid-column: 8 / 13; display: block; aspect-ratio: 523 / 396; }
.map-link > img { object-position: top; transition: opacity var(--t-hover) ease; }
.map-link:hover > img { opacity: .88; }
@media (max-width: 1000px) {
  .contact-form, .contact-data, .map-copy, .map-link { grid-column: 1 / -1; }
  .contact-form .form { max-width: 720px; }
  .map-link { width: 100%; max-width: 560px; }
}

/* ===== LWRC (U7) ===== */
/* Portada: facilities.jpg trae impreso en el centro "Living Water Retreat
   Center" en caligráfica, que quedaba debajo del h1 (texto sobre texto). Se
   desenfoca para que quede solo el paisaje; la escala tapa el borde claro
   que deja el desenfoque. Anclada a la izquierda, donde la foto no tiene
   letras. */
/* El scale va en --cover-scale y no en transform: el parallax (bloque
   "Revelado al bajar") compone su translate con este mismo transform. */
.lwrc-cover > img { object-position: 0% 50%; filter: blur(10px); --cover-scale: 1.1; }

/* Galería: la foto se acerca un poco al pasar el cursor, como aviso de que
   se abre. */
.bento .media > img { transition: transform .25s var(--ease-out); }
@media (hover: hover) { .bento .media:hover > img { transform: scale(1.03); } }

/* Visor (el comportamiento está en site.js, parte 4). El fondo no se mueve
   mientras está abierto. Las fotos miden 520 px de ancho: se agrandan hasta
   donde quepan entre las barras, sin deformarse (--ar = ancho / alto, lo
   pone site.js) y sin pasar de 960 px, para que no se vean muy blandas. */
html.viewer-open, html.viewer-open body { overflow: hidden; }
/* Deslizar a los lados cambia de foto (site.js): el navegador no lo toma
   como su gesto de "atrás". */
html.viewer-open { overscroll-behavior: none; }
.viewer[open] { animation: lw-fade .2s ease both; }
.viewer .viewer-img { container-type: size; touch-action: pan-y pinch-zoom; }
.viewer .viewer-img img {
  width: min(100cqw, calc(100cqh * var(--ar, 1.5)), 960px);
  height: auto;
  max-width: 100%;
  max-height: 100%;
}
.viewer-count { font-variant-numeric: tabular-nums; }
/* Región viva: la lee el lector de pantalla, no se ve. */
.viewer-live { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* Reserva tu retiro: el formulario en las columnas 1 a 7 y, a la derecha, la
   disponibilidad y la tarjeta LWF USA. Se apilan bajo 1000 px (como
   Contacto): primero el formulario. */
.reserva { align-items: start; row-gap: clamp(48px, 7vw, 80px); }
.reserva-main { grid-column: 1 / 8; min-width: 0; }
.reserva-side { grid-column: 9 / 13; min-width: 0; }
/* (El tipo de grupo sin elegir va en gris de placeholder por el sistema:
   select.input[data-empty] en el bloque de formularios.) */
.reserva-wa { align-items: center; padding-top: 24px; border-top: 1px solid var(--line); }
.reserva-wa .data { white-space: nowrap; }
/* El tamaño del glifo y el hover quieto vienen de la regla de WhatsApp de más
   arriba (.btn[href*="whatsapp.com"]), que vale para todo el sitio. */
.reserva-usa { gap: 16px; align-items: flex-start; padding: clamp(24px, 2.6vw, 36px); }
.btn.reserva-tel { font-family: var(--f-mono); font-size: 14px; letter-spacing: .02em; }
.btn.reserva-tel:hover svg { transform: none; }
@media (max-width: 1000px) {
  .reserva-main, .reserva-side { grid-column: 1 / -1; }
  .reserva-side { max-width: 560px; }
}

/* Cómo llegar: usa .map-copy y .map-link del bloque de Contacto. Aquí solo
   la leyenda "Abrir en Google Maps" sobre el mapa (también en Contacto). */
.map-link > .tag { position: absolute; left: 14px; bottom: 14px; z-index: 1; }
.map-link > .tag svg { width: 14px; height: 14px; flex: none; }

@media (prefers-reduced-motion: reduce) {
  .viewer[open] { animation: none; }
  .bento .media > img { transition: none; }
  .bento .media:hover > img { transform: none; }
}

/* ===== Boletines y 404 (U8) ===== */
/* Lista: archivo agrupado por año (Wise) en filas compactas fecha · título
   (Height). Cada año es un .grid12: el año en el riel, como encabezado del
   grupo, y sus filas en la columna de contenido; bajo 900 px el año queda
   arriba de sus filas. El año va en --accent-2 monoespaciada, como los de la
   línea de tiempo. */
.news-year { font: 500 13px/1.8 var(--f-mono); letter-spacing: .04em; text-transform: uppercase; color: var(--accent-2); }
/* Alineado con el contenido de la primera fila (regla de 1 px + 24 de aire). */
@media (min-width: 901px) { .c-rail.news-year { padding-top: 25px; } }

/* Fila: fecha, cuerpo (título y, debajo, el ministerio o socio) y flecha.
   Con el ministerio debajo del título la columna de contenido alcanza
   también entre 900 y 1100 px, donde mide unos 620 px. La fecha se alinea
   por la línea base con el título; la flecha, al centro. */
.news > .row { align-items: baseline; }
.news .row-go { align-self: center; }
.news-date { font: 500 13px/1.4 var(--f-mono); letter-spacing: .02em; color: var(--muted); font-variant-numeric: tabular-nums; }
.news-body { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; min-width: 0; }
.news .row-meta { text-align: left; }
@media (min-width: 761px) {
  .news > .row { grid-template-columns: 8rem minmax(0, 1fr) 44px; }
}
@media (max-width: 760px) {
  .news-date, .news-body { grid-column: 1; }
}
/* Las filas en marcador son <li>, no enlaces: sin sangría ni círculo lleno
   al pasar el cursor. Cuando cada fila sea un <a class="row"> recupera el
   efecto de las demás filas. */
.news > li.row:hover { padding-inline: 0; }
.news > li.row:hover .row-go { background: none; color: inherit; border-color: color-mix(in srgb, var(--fg) 24%, transparent); }

/* 404: la página es corta y, sin esto, el pie entraba en el primer
   pantallazo con el WhatsApp flotante encima de sus enlaces (.foot-top). La
   portada ocupa al menos el alto de la pantalla menos la cabecera (70 px:
   12 de margen y 58 de las píldoras), con el contenido centrado, y el pie
   empieza en el borde inferior: al final del scroll lo que queda junto al
   botón es .foot-bottom, que ya le reserva su espacio. */
body[data-page="404"] main {
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 70px);
  min-height: calc(100svh - 70px);
}
body[data-page="404"] .phead { flex: 1 0 auto; justify-content: center; }
/* El h1 de la 404 lleva una línea por idioma: sin el tope de 17ch y un poco
   más chico en escritorio, "This page does not exist." cabe entero. En el
   teléfono manda el mínimo de 34 px, igual que antes. */
body[data-page="404"] .phead h1 {
  font-size: clamp(34px, 5.4vw, 80px);
  max-width: none;
}

/* ==========================================================================
   Bloques por página (2026-09-19)
   Un bloque vacío por grupo de páginas, delimitado por sus dos marcadores.
   Existen para que varias personas (o varios agentes) puedan escribir el CSS
   de SU página en este mismo archivo al mismo tiempo sin pisarse: cada quien
   toca solo lo que hay entre sus dos marcadores.

   NO edites estos bloques a mano ni muevas los marcadores. Se escriben con:

     python3 docs/revamp/cssblock.py --show <grupo>          # ver lo que hay
     python3 docs/revamp/cssblock.py <grupo> mi-bloque.css   # reemplazarlo

   que toma un bloqueo de archivo y escribe de forma atómica. Los grupos son
   los cinco de abajo. Lo que es del sitio entero (componentes, armazón,
   tokens) no va aquí: va en su bloque de arriba, como siempre.
   ========================================================================== */

/* >>> pagina:doctrina >>> */
/* ==========================================================================
   Doctrina · /es/doctrina/ y /en/doctrine/ (rediseño del 2026-09-19)

   La declaración iba en una sola columna de texto chico y atenuado (.prose en
   --muted, 66ch), sin jerarquía: cuatro párrafos seguidos que nadie leía. El
   rediseño no toca una palabra del texto; lo que cambia es la forma:

   - la cita de Juan 4:14 en grande bajo la portada, con las reglas finas de
     .sec arriba y abajo y mucho aire (sin cápsula oscura);
   - los cuatro párrafos como cuatro apartados con riel: número mono en
     --accent-2 y título corto a la izquierda, párrafo a la derecha;
   - el cuerpo en tinta plena (--fg), 17 a 19 px, interlínea 1.65 y 62ch de
     medida, que es lo que hace que se lea de corrido.

   Todo va colgado de [data-page="doctrina"], que llevan las dos páginas: así
   ninguna de estas reglas se escapa al resto del sitio. Se reutilizan .sec,
   .grid12, .c-rail, .c-main, .quote, .label, .small, .btn y .actions; aquí
   solo está lo que faltaba.
   ========================================================================== */

/* ---- Cita: el versículo que abre la declaración --------------------------
   Más aire que una sección normal, porque es lo único que hay entre la
   portada y el primer apartado. La medida de 30ch la deja en dos líneas en
   escritorio (con el text-wrap: balance que ya trae .quote). */
[data-page="doctrina"] .doc-cita { padding-block: clamp(52px, 8vw, 116px); }
[data-page="doctrina"] .doc-cita-in {
  display: flex;
  flex-direction: column;
  gap: clamp(18px, 2.2vw, 28px);
}
[data-page="doctrina"] .doc-cita-in .quote {
  font-family: var(--f-display);
  max-width: 30ch;
}

/* ---- Apartados: riel con número y título, párrafo en la columna ancha ----
   .sec trae la regla fina de arriba, que es la separación entre apartados; lo
   único que se cambia es el aire vertical, que a 112 px por lado dejaba los
   párrafos demasiado lejos unos de otros. */
[data-page="doctrina"] .doc-item { padding-block: clamp(36px, 4.6vw, 68px); }
[data-page="doctrina"] .doc-rail {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 4px;
}
[data-page="doctrina"] .doc-num {
  font: 500 14px/1 var(--f-mono);
  letter-spacing: .1em;
  color: var(--accent-2);
  font-variant-numeric: tabular-nums;
}
/* Título corto: escala de h3 apenas subida, para que ordene sin competir con
   el h1 de la portada. */
[data-page="doctrina"] .doc-h {
  font-family: var(--f-head);
  font-weight: var(--w-head);
  font-size: clamp(21px, 1.9vw, 27px);
  line-height: 1.2;
  letter-spacing: var(--track-head);
  text-wrap: balance;
  color: var(--fg);
}
[data-page="doctrina"] .doc-main {
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 2.4vw, 28px);
}
/* El cuerpo de la declaración: tinta plena, no --muted. Es el texto principal
   de la página, no una nota al pie. */
[data-page="doctrina"] .doc-p {
  font-size: clamp(17px, 1.25vw, 19px);
  line-height: 1.65;
  color: var(--fg);
  max-width: 62ch;
}
/* Nota de traducción (ES) / línea que la ofrece (EN): .small ya la deja en
   14 px y --muted; solo le falta la medida y el subrayado del acento. */
[data-page="doctrina"] .doc-nota { max-width: 62ch; }
[data-page="doctrina"] .doc-nota a {
  color: var(--fg);
  text-decoration-color: var(--accent);
  text-underline-offset: 4px;
  transition: color var(--t-hover) ease;
}
[data-page="doctrina"] .doc-nota a:hover { color: var(--accent-2); }

/* ---- Cierre: adónde sigue el que acabó de leer ---------------------------
   Aquí iba la cápsula oscura de donar. Pedir dinero justo después de la
   declaración de fe queda fuera de lugar, así que el cierre es una línea y
   dos botones de contorno, con la regla fina de .sec por toda separación. */
[data-page="doctrina"] .doc-cierre {
  gap: clamp(20px, 2.4vw, 28px);
  padding-block: clamp(40px, 5vw, 76px);
}
[data-page="doctrina"] .doc-cierre-t {
  font-family: var(--f-head);
  font-weight: var(--w-display);
  font-size: clamp(21px, 2.2vw, 31px);
  line-height: 1.25;
  letter-spacing: calc(var(--track-display) * .6);
  text-wrap: balance;
  max-width: 26ch;
}
/* <<< pagina:doctrina <<< */

/* >>> pagina:ministerios-boletines >>> */
/* ===== Ministerios y Boletines ================================================
   MINISTERIOS · GRUPO "MINISTERIOS AFILIADOS" (2026-09-30). Todd agrupa IBNN,
   IBA, Cristo es la Roca y PCA bajo "Affiliated ministries · Pastors from 50
   local churches". La fila de grupo va antes de IBNN, en las dos vistas, con
   el mismo esqueleto que la ficha "y otros que se sumen": rótulo en la columna
   de la foto y la línea en la del texto. No es .ficha, así que ninguna regla
   de las fichas (ni las de presentación) la toca. */
.ficha-group {
  align-items: start;
  padding-block: clamp(28px, 4.4vw, 64px);
  border-bottom: 1px solid var(--line);
}
.ficha-group .ficha-photo { padding-top: 4px; }
.ficha-group .ficha-body > h2 { margin: 0; }

/* ===== Vista de presentación (2026-09-19, ajustado 2026-09-30) ================
   Lo de aquí abajo solo se aplica con <html data-view="presentacion">: en la
   vista de trabajo las dos páginas se quedan exactamente como están, que es lo
   que Daniel usa para pedir material.

   MINISTERIOS. En presentación los marcadores desaparecen (regla 1 del
   contrato), incluido el marco de la foto que todavía no llega. Hay dos casos:
   - Ficha sin foto NI bio: pasa a fila compacta —nombre en escala h3, rótulo
     de tipo y, si lo hay, el botón de donar a la derecha—.
   - Ficha sin foto pero CON bio (desde el 2026-09-30, casi todas): el nombre y
     el rótulo ocupan la columna de la foto y la bio y el botón la del texto,
     así no queda un cuadro vacío a la izquierda.
   Sin duplicar marcado ni anclas: todo sale de :has(). Cuando llegue la foto
   de un ministerio, la ficha recupera sola su forma grande.

   BOLETINES no necesita CSS propio: usa .empty + .empty-line del sistema.    */

/* --- Ficha sin foto ni bio: fila compacta --- */

/* La fila compacta respira como una .row (24 px), no como una ficha
   (hasta 64 px arriba y abajo). */
:root[data-view="presentacion"] .fichas > .ficha:not(:has(img)):not(:has(.text)) {
  padding-block: clamp(18px, 2vw, 26px);
}

/* El marco de foto ya se fue con los marcadores: el cuerpo toma las doce
   columnas y se ordena en fila, con el botón contra el borde derecho. Al
   apretarse (teléfono) el botón cae debajo del nombre. */
:root[data-view="presentacion"] .fichas > .ficha:not(:has(img)):not(:has(.text)) > .ficha-body {
  grid-column: 1 / -1;
  flex-flow: row wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
}

/* Nombre y rótulo de tipo, uno debajo del otro y alineados a la izquierda. */
:root[data-view="presentacion"] .fichas > .ficha:not(:has(img)):not(:has(.text)) .ficha-body > hgroup {
  flex: 1 1 auto;
  min-width: 0;
  gap: 6px;
}

/* En fila, el nombre va en la escala de h3: el h2 de la ficha grande
   (hasta 66 px) convertía cada fila en un titular. */
:root[data-view="presentacion"] .fichas > .ficha:not(:has(img)):not(:has(.text)) .ficha-body > hgroup > h2 {
  font-family: var(--f-head);
  font-weight: var(--w-head);
  font-size: clamp(19px, 1.7vw, 24px);
  line-height: 1.25;
  letter-spacing: var(--track-head);
}

/* --- Ficha sin foto pero con bio: nombre a la izquierda, bio a la derecha --- */

/* El cuerpo se "disuelve" (display: contents) y sus hijos pasan a ser celdas
   de la rejilla de 12 de la ficha: el hgroup a la columna de la foto, los
   párrafos y los botones a la del texto. La colocación automática pone el
   hgroup y el primer párrafo en la misma fila y los demás debajo. */
:root[data-view="presentacion"] .fichas > .ficha:not(:has(img)):has(.text) > .ficha-body {
  display: contents;
}
:root[data-view="presentacion"] .fichas > .ficha:not(:has(img)):has(.text) > .ficha-body > hgroup {
  grid-column: 1 / 5;
  gap: 10px;
}
:root[data-view="presentacion"] .fichas > .ficha:not(:has(img)):has(.text) > .ficha-body > :not(hgroup) {
  grid-column: 6 / 13;
}
/* En la columna angosta el h2 de 66 px partía los nombres en tres o cuatro
   líneas: aquí va en una escala intermedia entre h3 y h2. */
:root[data-view="presentacion"] .fichas > .ficha:not(:has(img)):has(.text) .ficha-body > hgroup > h2 {
  font-size: clamp(24px, 2.6vw, 36px);
  line-height: 1.15;
}
/* Los botones se separan de la bio como en la ficha grande (24 px en total
   con el row-gap de 20 px de .grid12). */
:root[data-view="presentacion"] .fichas > .ficha:not(:has(img)):has(.text) > .ficha-body > .actions {
  margin-top: 4px;
}
@media (max-width: 900px) {
  :root[data-view="presentacion"] .fichas > .ficha:not(:has(img)):has(.text) > .ficha-body > hgroup { grid-column: 1 / 6; }
  :root[data-view="presentacion"] .fichas > .ficha:not(:has(img)):has(.text) > .ficha-body > :not(hgroup) { grid-column: 6 / 13; }
}
@media (max-width: 560px) {
  /* hgroup y :not(hgroup) por separado: con "> *" la regla de 900 px ganaba
     por especificidad y el teléfono seguía en dos columnas. */
  :root[data-view="presentacion"] .fichas > .ficha:not(:has(img)):has(.text) > .ficha-body > hgroup,
  :root[data-view="presentacion"] .fichas > .ficha:not(:has(img)):has(.text) > .ficha-body > :not(hgroup) { grid-column: 1 / -1; }
}

/* "Y otros que se sumen" es de la vista de trabajo, así que en presentación la
   última ficha visible es la anterior: le quitamos la regla de cierre, porque
   debajo ya viene la de la sección (igual que hace .ficha:last-child). */
:root[data-view="presentacion"] .fichas > .ficha:has(+ .ficha-more) {
  border-bottom: 0;
}
/* <<< pagina:ministerios-boletines <<< */

/* >>> pagina:donar-contacto >>> */
/* ===== Donar y Contacto (2026-09-19) =====================================
   Lo que estas dos páginas necesitan además de los componentes que ya
   existen más arriba (.gives, .give, .facts, .ph…). Se escribe con
   docs/revamp/cssblock.py; no se edita a mano. */

/* ---- Donar › Ministerios: cuatro tarjetas, no nueve ----------------------
   Antes había una tarjeta por ministerio y cinco de las nueve eran solo
   marcador: la sección se leía como un formulario a medio llenar. Ahora la
   tarjeta es solo para quien ya tiene enlace de donación, y con cuatro caben
   en una fila de escritorio ancho. Al ser cuatro se les puede dar más
   presencia: más alto, más aire y el nombre un punto mayor.
   Van con .gives.gives-4 (dos clases) para ganarle a las medias consultas
   de .gives, que están más arriba en el archivo. */
.gives-wrap { display: flex; flex-direction: column; gap: clamp(20px, 2.4vw, 32px); }
.gives.gives-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(12px, 1.3vw, 18px); }
.gives-4 > .give {
  min-height: clamp(196px, 14.8vw, 228px);
  gap: 14px;
  padding: clamp(24px, 2.1vw, 32px);
}
.gives-4 > .give > .h3 { font-size: clamp(20px, 1.5vw, 24px); }
/* La tarjeta abre con una línea de acento: con solo cuatro, el borde fino
   solo no las sostenía en una fila tan ancha. */
.gives-4 > .give { position: relative; overflow: hidden; }
.gives-4 > .give::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: var(--accent);
}
/* Tableta: 2×2. Teléfono: una columna. */
@media (max-width: 1180px) { .gives.gives-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) {
  .gives.gives-4 { grid-template-columns: minmax(0, 1fr); }
  .gives-4 > .give { min-height: 0; }
}

/* ---- Donar › "Pronto también" -------------------------------------------
   Los cuatro ministerios que todavía no tienen enlace de donación. Sin
   tarjeta: rótulo, los nombres como enlaces de texto a su ficha y, al final,
   un solo marcador para los cinco que antes iban uno por tarjeta. En
   presentación el marcador se va y queda una línea sobria que dice que
   faltan por sumarse. */
.soon { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 28px; }
.soon > .label { flex: none; }
.soon-list { display: flex; flex-wrap: wrap; align-items: center; gap: 0 24px; min-width: 0; }
.soon-list a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 15px;
  color: var(--muted);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--fg) 24%, transparent);
  text-underline-offset: 4px;
  transition: color var(--t-hover) ease, text-decoration-color var(--t-hover) ease;
}
.soon-list a:hover { color: var(--fg); text-decoration-color: var(--accent); }
.soon > .ph-inline { flex: none; }
/* En el teléfono los nombres largos ocupaban una línea cada uno igual:
   mejor una columna declarada, que se lee como lista. */
@media (max-width: 700px) {
  .soon { flex-direction: column; align-items: flex-start; gap: 6px; }
  .soon-list { flex-direction: column; align-items: flex-start; gap: 0; }
  .soon > .ph-inline { margin-top: 6px; }
}

/* ---- Donar › Donación general -------------------------------------------
   Queda igual, pero ahora cierra la sección justo debajo de la fila
   "Pronto también": una regla fina la separa para que no se lea como parte
   de esa fila. */
.give-general { padding-top: clamp(24px, 3vw, 36px); border-top: 1px solid var(--line); }
/* <<< pagina:donar-contacto <<< */

/* >>> pagina:inicio-lwrc >>> */
/* ==========================================================================
   Inicio y LWRC. Lo que sigue es solo de estas cuatro páginas: lo del sistema
   (componentes, armazón, tokens) vive más arriba en site.css.
   ========================================================================== */

/* ---- Inicio › Historia: la línea de tiempo que avanza sola ------------------
   Hasta el 2026-09-20 eran cinco tarjetas a la vez (.hist-row): 797 px de alto
   en escritorio, 1 248 en el teléfono, y en tableta la pista dejaba ver "un
   pedacito" de la siguiente. El cliente pidió un carrusel automático, "no tan
   grande pero que se vea súper bien", sin texto recortado y sin nada asomando.

   Es el carrusel del sistema ([data-carousel] de site.js, el mismo de
   Nosotros › Equipo): una etapa a la vista, avance automático cada 7 s, pausa
   con el botón y pista infinita con el dedo en el teléfono. Aquí solo va la
   maqueta de la etapa y el riel de años.

   EL RIEL es lo que hace que no haya que pensar: una línea fina con cinco nodos
   y sus años como botones, y sobre ella la línea de avance del acento, que
   llega hasta el nodo activo y SIGUE llenándose hacia el siguiente mientras
   corre el tiempo de la etapa. O sea: es el índice, el progreso y el mando, los
   tres en el mismo sitio. Se calcula con las variables que publica site.js en el
   .carousel — --car-i (índice), --car-p (progreso 0 a 1) y --car-n (cuántas
   son) — sin una línea de JS propia:

       llena = (--car-i + --car-p) / (--car-n - 1)

   En pausa y con movimiento reducido site.js publica --car-p = 0, así que la
   línea descansa justo sobre el nodo activo. Nada de transiciones en esa línea:
   la variable ya cambia en cada fotograma mientras corre el tiempo, y un cambio
   de etapa se quiere instantáneo (el salto es la respuesta al clic).

   Sin JS (o antes de .is-ready) el carrusel apila las cinco etapas y el sistema
   esconde .car-controls, así que se lee la historia entera y no queda un riel
   mintiendo sobre un carrusel que no existe. */

/* El rótulo y el titular viven DENTRO del carrusel: así la sección tiene un
   solo hijo y no paga el aire de .sec (63 px a 1440) entre el titular y la
   etapa. El aire de aquí lo pone el propio .carousel, más ajustado. */
.hist-car { gap: clamp(18px, 2.2vw, 30px); }
.hist-intro { row-gap: 12px; }

/* La etapa. Apilada por defecto: es lo del teléfono y también lo de sin JS.
   El tope de 250 px de la foto es para las pantallas medianas: a 600 px el 3/2
   a todo el ancho daría 375 px de foto. En el teléfono no hace nada (a 390 la
   foto mide 239 y a 360, 219). */
.hist-etapa { gap: 14px; align-content: start; }
.hist-foto { aspect-ratio: 3 / 2; border-radius: var(--r-lg); max-height: min(62vw, 250px); }
.hist-txt { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
/* El año es la pieza grande de la etapa: tipografía de titulares en el acento
   como texto (--accent-2, el que pasa contraste sobre el fondo). "Hoy" va igual
   de grande que los años, que para el cliente es una fecha más de la lista. */
.hist-ano {
  font-family: var(--f-display);
  font-weight: var(--w-display);
  font-size: clamp(48px, 14vw, 64px);
  line-height: .95;
  letter-spacing: var(--track-display);
  color: var(--accent-2);
  font-variant-numeric: tabular-nums;
}
/* El texto va ENTERO, sin line-clamp y sin "…" (regla del cliente): la etapa
   mide lo que mide el texto más largo y todas las demás ocupan esa misma celda,
   así que la sección no cambia de alto al pasar de etapa. */
.hist-txt > p { color: var(--muted); font-size: 16px; line-height: 1.55; }

@media (min-width: 600px) {
  /* Dos columnas: foto a un lado y año, título y texto al otro, centrados entre
     sí. Quien manda en el alto de la sección es la foto, así que se le da el
     ALTO y el 3/2 le saca el ancho; la columna va en auto y queda justo de su
     tamaño. (Al revés —columna en fr y max-height— Chrome encoge la foto para
     conservar la proporción y deja un hueco muerto dentro de la columna.)
     300 px es lo que deja la sección por debajo de 700: con el 3/2 a todo el
     ancho de una columna del 45 % serían 390 px de foto y la sección se iría por
     encima de los 800, que es justo lo que se venía a bajar.
     Empieza en 600 y no en 900 (el corte del carrusel) a propósito: de 600 a 899
     la pista del teléfono sigue mandando —una etapa por pantalla, con el dedo—
     pero DENTRO de la etapa ya caben las dos columnas. Apilada, una tableta se
     comía la foto a todo lo ancho y la sección pasaba de 800 px. */
  .hist-etapa {
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: clamp(20px, 3.4vw, 56px);
    align-items: center;
  }
  .hist-foto { height: clamp(160px, 21vw, 300px); max-height: none; }
  .hist-txt { gap: 10px; }
  .hist-ano { font-size: clamp(64px, 7vw, 112px); line-height: .88; }
  /* 52 caracteres de ancho: la columna del texto pasa de 800 px y un párrafo de
     17 px a todo lo ancho serían 95 caracteres por línea, el doble de lo que se
     lee cómodo. */
  .hist-txt > p { font-size: clamp(16px, 1.2vw, 17px); max-width: 52ch; }
}

/* ---- El riel de años --------------------------------------------------------
   .car-controls es lo que el sistema esconde sin JS, así que el riel cuelga de
   esa misma caja y solo le cambia el display. A lo ancho de la sección, con los
   tres controles (anterior, siguiente, pausa) a su derecha; en el teléfono no
   caben en la misma línea y el flex los baja solos, arrimados a la derecha. */
.hist-ctl {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 28px;
  /* Los botones de año miden 44 px de alto por el área táctil, pero su texto
     ocupa la mitad de arriba: los 19 px de abajo son aire vacío y se le
     devuelven a la sección. Debajo quedan los 108 px de relleno de .sec (56 en
     el teléfono), así que no se nota. */
  margin-bottom: -16px;
}
/* El primer nodo va en el borde izquierdo del riel y el último en el derecho,
   no centrados en cinco columnas iguales: así la línea arranca a plomo con la
   foto y con el rótulo de la sección en vez de quedar metida hacia dentro, y la
   línea de avance llena es exactamente el ancho del riel.
   El alto va fijo porque los nodos están posicionados: 10 px del nodo y los 44
   del área táctil del botón que va debajo. */
.hist-riel {
  position: relative;
  flex: 1 1 300px;
  height: 54px;
  min-width: 0;
}
.hist-riel::before,
.hist-riel::after {
  content: "";
  position: absolute;
  top: 4px;                       /* el nodo mide 10 px: su centro está en 5 */
  left: 0;
  width: 100%;
  height: 2px;
  border-radius: 2px;
}
.hist-riel::before { background: var(--line); }
.hist-riel::after {
  background: var(--accent);
  transform-origin: left center;
  transform: scaleX(calc((var(--car-i, 0) + var(--car-p, 0)) / (var(--car-n, 5) - 1)));
}
/* Cada nodo en su sitio del recorrido: el k de n va en k / (n - 1) del ancho.
   Posicionado, además, se pinta ENCIMA de la línea de avance (un ::after del
   <ol> va después de los <li> en orden de pintado). Los de los extremos se
   arriman al borde en vez de centrarse, para no salirse del riel. */
.hist-riel > li {
  position: absolute;
  top: 0;
  left: calc(var(--n, 0) / (var(--car-n, 5) - 1) * 100%);
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
}
.hist-riel > li:first-child { transform: none; align-items: flex-start; }
.hist-riel > li:last-child { transform: translateX(-100%); align-items: flex-end; }
/* Los nodos de los extremos se salen medio punto (5 px) hacia el margen, para
   que su CENTRO caiga justo en el principio y en el final de la línea igual que
   los de en medio. El año se queda dentro, a plomo con la foto. Los 5 px caben
   de sobra en el canalón (--gutter, 16 px como mínimo). */
.hist-riel > li:first-child::before { margin-left: -5px; }
.hist-riel > li:last-child::before { margin-right: -5px; }
/* Índice de cada nodo, para saber si la línea ya le llegó. Se compara con
   aritmética de CSS: --car-i - n + 1 vale 1 o más cuando el nodo ya está
   alcanzado (el activo incluido) y 0 o menos cuando falta; clamp lo deja en 0
   o 1 y color-mix elige el color. Sin JS extra y sin un atributo por nodo. */
.hist-riel > li:nth-child(1) { --n: 0; }
.hist-riel > li:nth-child(2) { --n: 1; }
.hist-riel > li:nth-child(3) { --n: 2; }
.hist-riel > li:nth-child(4) { --n: 3; }
.hist-riel > li:nth-child(5) { --n: 4; }
.hist-riel > li::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: color-mix(in srgb,
    var(--accent) calc(clamp(0, calc(var(--car-i, 0) - var(--n, 0) + 1), 1) * 100%),
    var(--line));
}
/* El nodo de la etapa que se está viendo lleva un halo del acento: con cinco
   nodos del mismo tamaño hay que buscar cuál es el activo, y este es justo el
   "don't make me think" que pidió el cliente. Donde no haya :has() se queda sin
   halo y el año en tinta llena sigue diciendo cuál es. */
.hist-riel > li:has(> [aria-current="true"])::before {
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 20%, transparent);
}
/* El año: monoespaciada, como todos los datos del sitio. El texto se queda
   arriba (align-items: flex-start) y el resto de los 44 px es área táctil. */
.hist-nodo {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 8px 6px 0;
  border: 0;
  background: transparent;
  font: 500 13px/1.3 var(--f-mono);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  transition: color var(--t-hover) ease;
}
/* En los extremos el año se arrima al borde igual que su nodo, para que el
   punto caiga sobre el principio (o el final) del año y no a un lado. */
.hist-riel > li:first-child .hist-nodo { justify-content: flex-start; padding-left: 0; }
.hist-riel > li:last-child .hist-nodo { justify-content: flex-end; padding-right: 0; }
.hist-nodo:hover,
.hist-nodo[aria-current="true"] { color: var(--fg); }

@media (max-width: 899px) {
  /* En el teléfono cada etapa ocupa todo el ancho de la pista (lo pone el
     sistema con grid-auto-columns: 100 %), así que no asoma nada de la
     siguiente: se desliza con el dedo y se ve una etapa entera cada vez. */
  .hist-nodo { font-size: 12px; letter-spacing: .02em; padding-inline: 0; }
  /* El riel se queda con la línea entera y los tres controles bajan debajo,
     arrimados a la derecha. Acotado a .hist-ctl: .car-nav es del sistema y en
     Equipo vive dentro de una columna, donde un margen automático lo movería. */
  .hist-riel { flex: 1 1 100%; }
  .hist-ctl .car-nav { margin-left: auto; }
}

/* ---- LWRC › Reserva tu retiro: la columna de la derecha ----------------------
   Desde el 2026-10-03 no hay tarjeta de Disponibilidad (Todd no tiene
   calendario que publicar; Daniel la pidió fuera). La columna lleva solo la
   tarjeta de LWF USA: centrada contra el formulario, sin un hueco alto al
   lado. Antes era solo en presentación, donde el marcador se colapsaba. */
@media (min-width: 901px) {
  .reserva-side { align-self: center; }
}

/* ---- Inicio › Portada que se abre a pantalla completa (2026-09-19) ----------
   Al cargar, la portada se ve como la tarjeta de siempre (foto con esquinas
   redondas dentro del contenedor de 1400 px, bajo la cabecera flotante) y,
   cuando la página termina de cargar, el fondo se abre hasta ocupar la
   pantalla entera.

   La técnica: la sección ocupa DESDE EL PRINCIPIO su tamaño final —a sangre,
   100vw, 100svh de alto mínimo y arrancando en el borde superior de la
   página— y lo que se anima es un `clip-path` que la recorta al rectángulo de
   la tarjeta. Así el texto no se mueve ni refluye: animar el ancho o el alto
   de la caja obligaría a recalcular la maqueta en cada cuadro y el titular
   bailaría. El recorte solo cambia qué parte se ve.

   El recorte y el relleno salen de las MISMAS tres variables, así que la
   tarjeta y el texto no se pueden desalinear:

     --hero-top   donde empieza la tarjeta: el alto en flujo de la cabecera
                  (12 px de margen + 58 px de píldora) más los 12 px de aire
                  que .cover ya tenía. En un monitor normal son 82 px.
     --hero-side  el borde del contenedor: lo que separa el contenido del
                  borde de la pantalla, o sea (100vw - 1400px) / 2 más el
                  margen lateral. A 1920 px son 304 px; a 390, 16.
     --hero-bot   el aire de abajo de la tarjeta. A 1920x957 son unos 76 px,
                  como en el diseño de hoy.

   El relleno de la sección es cada una de esas variables MÁS el relleno que
   .cover ya tenía (--hero-pad), de manera que el texto cae dentro de la
   tarjeta con el mismo aire de siempre y en el estado final se queda
   exactamente en el mismo sitio.

   El recorte va sobre la sección entera y no sobre una capa aparte: el texto
   vive dentro del rectángulo de la tarjeta por construcción, así que recortar
   todo da el mismo resultado y deja el `transform` de la foto (el parallax)
   independiente del recorte. Si el recorte fuera sobre la foto, el borde de
   la tarjeta se movería con el parallax.

   Estados, en <html>:
     .hero-open   el recorte se abre (lo pone site.js al terminar la carga)
     .hero-done   se acabó la animación: fuera las transiciones, para que el
                  parallax no arrastre 1.1 s de retraso
     [data-hero="card"]  ?hero=card, el estado inicial congelado (capturas)

   Sin JavaScript no hay ninguna clase y la portada se queda como tarjeta,
   completa y legible. Con movimiento reducido se muestra directo el estado
   final, sin animación.

   Es un MODIFICADOR del componente .cover: el día que LWRC quiera lo mismo,
   basta con ponerle la clase (este bloque cubre Inicio y LWRC).            */
.hero--expand {
  --hero-head: calc(env(safe-area-inset-top, 0px) + 70px);
  --hero-top: calc(var(--hero-head) + 12px);
  --hero-side: calc(max(0px, (100vw - var(--max)) / 2) + var(--gutter));
  --hero-bot: clamp(20px, 8svh, 80px);
  --hero-pad: clamp(24px, 5vw, 72px);   /* el padding de .cover, tal cual */
  --hero-t: 1100ms;
  --hero-zoom: 1.06;

  /* A sangre: el margen negativo cancela el relleno del contenedor y el de
     arriba sube la sección hasta el borde de la página (la cabecera pegajosa
     queda flotando encima, con su z-index de 50). */
  width: 100vw;
  margin-top: calc(-1 * var(--hero-head));
  margin-inline: calc(-1 * var(--hero-side));
  min-height: 100svh;   /* min- y no height: en un apaisado bajo la portada
                           crece en vez de cortar el titular o los botones */
  padding: calc(var(--hero-top) + var(--hero-pad))
           calc(var(--hero-side) + var(--hero-pad))
           calc(var(--hero-bot) + var(--hero-pad));
  border-radius: 0;   /* las esquinas redondas las pone el recorte */
  clip-path: inset(var(--hero-top) var(--hero-side) var(--hero-bot) round var(--r-lg));
  transition: clip-path var(--hero-t) var(--ease-curtain);
}
/* 100vw cuenta la barra de scroll del escritorio: la sección sobra unos 7 px
   por lado y sin esto saldría una barra horizontal. `clip` no crea contenedor
   de scroll, así que la cabecera pegajosa sigue funcionando (`hidden` sí la
   rompería). Va con :has para que solo afecte a las páginas con esta portada
   y la compuerta de desborde siga vigilando a las demás. */
body:has(.hero--expand) { overflow-x: clip; }

/* La entrada de página sube los tres primeros hijos del <main> 36 px. Con la
   portada a sangre eso destaparía una franja de fondo arriba, así que aquí la
   entrada es solo un fundido: el texto no se mueve tampoco al cargar. */
.lw-enter body[data-page] > main > .hero--expand { animation-name: lw-fade; }

/* La foto entra con un acercamiento inverso (1.06 → 1) al mismo tiempo que el
   recorte. El parallax ya escribe --px y el desenfoque de LWRC ya usa
   --cover-scale: el zoom es una variable más y los tres transform conviven.
   La transición se quita con .hero-done para no frenar el parallax. */
.hero--expand > img,
.lw-px .hero--expand > img {
  transform: translate3d(0, var(--px, 0px), 0)
             scale(calc(var(--cover-scale, 1) * var(--hero-zoom, 1)));
  transition: transform var(--hero-t) var(--ease-curtain);
}
html.hero-open .hero--expand { clip-path: inset(0 round 0); }
html.hero-open .hero--expand > img { --hero-zoom: 1; }
html.hero-done .hero--expand,
html.hero-done .hero--expand > img { transition: none; }

/* Pista de scroll: con la portada a pantalla completa ya no se ve que hay más
   abajo. Sale al centro, a 24 px del borde inferior de la pantalla (la
   portada empieza en el borde de la página, así que 100svh es el pie del
   primer pantallazo aunque la sección sea más alta). site.js le pone
   data-hint solo si no choca con los botones. */
.hero-hint {
  position: absolute;
  left: 50%;
  top: calc(100svh - 72px);
  transform: translateX(-50%);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 44px;
  min-height: 48px;
  padding: 4px 14px;
  border-radius: var(--r-pill);
  color: var(--fg);
  font: 500 12px/1.4 var(--f-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  opacity: 0;
  pointer-events: none;
  transition: opacity .5s var(--ease-out), background-color var(--t-hover) ease;
}
.hero-hint svg { width: 18px; height: 18px; }
html.hero-done .hero--expand[data-hint] .hero-hint { opacity: 1; pointer-events: auto; }
.hero-hint:hover { background: color-mix(in srgb, var(--fg) 12%, transparent); }
/* Tres vaivenes y se queda quieta; con data-hint="2" (primer scroll) tampoco
   se mueve. */
@keyframes lw-hint-down { 0%, 100% { transform: none; } 50% { transform: translateY(5px); } }
html.hero-done .hero--expand[data-hint="1"] .hero-hint svg {
  animation: lw-hint-down 1.7s var(--ease-out) .5s 3 both;
}

/* Movimiento reducido: el estado final directo, sin animación ni vaivén.
   Cubre también el caso sin JavaScript. */
@media (prefers-reduced-motion: reduce) {
  .hero--expand { clip-path: inset(0 round 0); transition: none; }
  .hero--expand > img,
  .lw-px .hero--expand > img { --hero-zoom: 1; transition: none; }
  .hero-hint svg { animation: none; }
}
/* ?hero=card: el estado inicial congelado, para capturarlo. Va después del
   movimiento reducido a propósito: manda sobre él. */
html[data-hero="card"] .hero--expand {
  clip-path: inset(var(--hero-top) var(--hero-side) var(--hero-bot) round var(--r-lg));
  transition: none;
}
html[data-hero="card"] .hero--expand > img { --hero-zoom: 1.06; transition: none; }

/* La cabecera queda encima de la foto: las dos píldoras de vidrio suben de
   opacidad para que se sigan leyendo en claro y en oscuro. */
body:has(.hero--expand) .bar .glass {
  background: color-mix(in srgb, var(--panel) 88%, transparent);
  border-color: color-mix(in srgb, var(--fg) 12%, transparent);
}

/* ---- Inicio › Reserva LWRC: la tarjeta con la barra de reserva (2026-09-19) --
   El sitio vivo era el del centro de retiros y su objetivo era que las
   iglesias RESERVARAN. El rediseño lo convirtió en un bloque de dos columnas
   en quinta posición, con un botón "Conoce LWRC" y nada más. Ahora la reserva
   es la segunda sección del Inicio y tiene su propia tarjeta grande con una
   barra de reserva rápida.

   No inventa una capa de foto nueva: la tarjeta lleva .on-dark (tokens.css,
   el juego oscuro en los dos modos) y la misma capa --veil de las portadas, en
   un ::before, con la foto a sangre detrás en z-index negativo. Es el patrón
   de .cover; no se reusa la clase .cover porque este bloque no es una portada:
   no quiere su margen bajo la cabecera, ni su alto, ni el parallax (en el
   teléfono la foto sale del fondo y pasa al flujo, y un parallax ahí
   destaparía un borde).

   SIN barra de fechas (2026-09-19, misma tarde): hubo una con Llegada, Salida y
   Personas, pero el centro no publica disponibilidad en línea y un buscador de
   fechas prometía algo que no hay; además iOS pinta los input[type=date] a su
   manera y se salían del panel. Quedan dos salidas claras —el formulario de
   reserva de LWRC y WhatsApp— y el enlace al centro. El formulario de
   /es/lwrc/#reserva sigue aceptando ?llegada=…&salida=…&personas=… (site.js),
   por si se comparte un enlace con las fechas ya puestas.                    */
.rsv {
  --rsv-pad: clamp(20px, 5vw, 72px);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: clamp(18px, 2.4vw, 30px);
  min-height: clamp(560px, 40vw, 620px);
  padding: var(--rsv-pad);
  border-radius: var(--r-lg);
  background: var(--bg);
}
/* La foto a sangre dentro de la tarjeta y, encima, la capa de las portadas.
   Los hijos con z-index negativo se pintan SOBRE el fondo de la tarjeta y
   DEBAJO de su contenido, que es justo el orden que hace falta. */
.rsv > .rsv-foto {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.rsv::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--veil); }

.rsv-copy { display: flex; flex-direction: column; gap: 14px; max-width: 46ch; }
/* El titular de una sección sobre foto va en --sand, el token que existe para
   eso (D6); el segundo tono sigue en --dim, como en las portadas. A 66 px el
   h2 del sistema pesaba demasiado dentro de la tarjeta, así que aquí llega
   hasta 48. */
.rsv-copy .h2 { color: var(--sand); font-size: clamp(28px, 3.4vw, 48px); }
.rsv-copy .h2 .dim { display: block; color: var(--dim); }
/* Sobre la foto el rótulo y el texto van en tinta: --muted no llega a 4.5:1
   donde la foto es clara (la misma razón que .cover .label). */
.rsv-copy .label, .rsv-copy .text { color: var(--fg); }

.rsv-mas { align-items: center; gap: 12px 20px; }
/* "Conoce el centro": enlace de texto, no botón. Sobre la foto va en tinta,
   como el resto del texto de la tarjeta. */
.rsv-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  font-size: 15px;
  color: var(--fg);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--fg) 34%, transparent);
  text-underline-offset: 4px;
  transition: color var(--t-hover) ease, text-decoration-color var(--t-hover) ease;
}
.rsv-link svg { width: 15px; height: 15px; flex: none; transition: transform var(--t-hover) var(--ease-out); }
.rsv-link:hover { text-decoration-color: var(--accent); }
.rsv-link:hover svg { transform: translateX(3px); }

/* Teléfono y tableta angosta: la foto sale del fondo y pasa al flujo, arriba
   en 4:3 y a sangre (los márgenes negativos cancelan el relleno de la
   tarjeta). Debajo, el texto y los botones sobre la tarjeta oscura. La
   capa --veil ya no hace falta: no hay nada encima de la foto. */
@media (max-width: 760px) {
  .rsv {
    justify-content: flex-start;
    gap: 18px;
    min-height: 0;
    border: 1px solid var(--line);
  }
  .rsv::before { display: none; }
  /* max-width: none cancela el `img { max-width: 100% }` de la base, que si no
     recorta la foto justo en el ancho del contenido y deja una franja del
     fondo a la derecha. */
  .rsv > .rsv-foto {
    position: static;
    width: calc(100% + var(--rsv-pad) * 2);
    max-width: none;
    height: auto;
    aspect-ratio: 4 / 3;
    margin: calc(-1 * var(--rsv-pad)) calc(-1 * var(--rsv-pad)) 0;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
  }
  /* Los dos botones a todo el ancho, uno bajo el otro: en un teléfono un
     botón a medias junto a otro se toca mal. */
  .rsv-mas { flex-direction: column; align-items: stretch; }
  .rsv-mas .btn { width: 100%; justify-content: center; }
  .rsv-mas .rsv-link { align-self: flex-start; }
}

/* ---- LWRC › Misión y visión: dos columnas cortas (2026-09-19) ----------------
   "Nuestra misión" y "Nuestra visión" estaban en el Inicio, en "Quiénes
   somos", como si fueran del ministerio entero. No lo son: hablan de "un
   centro de retiro cuidadosamente diseñado y construido", o sea del LWRC. Aquí
   van palabra por palabra, en dos columnas, justo después de la portada.

   Es .prose (para que el "Nuestra misión." en negrita siga en tinta) con la
   columna partida en dos: sin el ancho de 66ch, que en una sola columna dejaba
   la mitad de la página vacía. Bajo 760 px se apilan.                       */
.mv { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 24px; max-width: none; }
.mv > p { max-width: 52ch; }
@media (max-width: 760px) { .mv { grid-template-columns: minmax(0, 1fr); } }

/* Inicio › Quiénes somos en tres columnas (2026-09-30). El titular y el
   video comparten la primera fila (6 y 3 columnas de la retícula); debajo,
   las tres ideas del párrafo de Todd lado a lado, cada una con su rótulo.
   Hasta 1100 px titular y video van a todo el ancho del c-main; en el
   teléfono todo apilado en una columna. */
.qs-title { grid-column: 4 / 10; }
.qs-video { grid-column: 10 / 13; align-self: start; }
/* En tres columnas el video es chico y sus dos etiquetas se amontonaban sobre
   el botón de reproducir; el botón y su texto oculto ya dicen que es YouTube. */
.qs-video figcaption { display: none; }
.qs-cols { grid-column: 4 / 13; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px 32px; }
.qs-col { display: flex; flex-direction: column; gap: 10px; }
.qs-actions { grid-column: 4 / 13; }
@media (max-width: 1100px) { .qs-title, .qs-video { grid-column: 4 / 13; } }
@media (max-width: 900px) {
  .qs-title, .qs-video, .qs-cols, .qs-actions { grid-column: 1 / -1; }
  .qs-cols { grid-template-columns: minmax(0, 1fr); }
}
/* <<< pagina:inicio-lwrc <<< */

/* >>> pagina:nosotros-lwf >>> */
/* ===== Nosotros y About (U5 / U9) — acortadas el 2026-09-19 (tarde) =====
   La página medía 9 804 px en escritorio y 10 789 px en el teléfono: nadie
   llegaba al final. Se hicieron cuatro cosas, y todo el CSS que las sostiene
   vive en este bloque:

     1. Fundaciones (.recorrido)  las tres secciones de las fundaciones en una
     2. Equipo (.team-car)        el carrusel a dos columnas
     3. Historia (.tl-low)        filas bajas con la foto chica a la derecha
     4. Creemos (.creo-3)         los tres enunciados en tres columnas

   Las cuatro páginas propias de cada fundación (/es/lwf-usa/, /es/lwf-panama/ y
   sus pares EN) comparten este bloque. Desde el 2026-10-14 usan la fila de
   verbos .verbos y la declaración .lwf-decl (sub-bloque al final de este
   bloque); no usan el recorrido. Lo demás que llevan (.prose, .quote) vive
   más arriba.

   Aire entre secciones: cada .sec pone var(--sec) arriba Y abajo, así que entre
   dos vecinas se sumaban 216 px a 1440. Aquí se reparte una sola medida entre
   las dos (54 px cada una). La regla vive en esta página, no en el sistema. */
[data-page="nosotros"] main > .sec { padding-block: calc(var(--sec) * .5); }
/* Y el aire de dentro (rótulo+titular contra el contenido) baja un punto: con
   seis secciones, los 63 px de fábrica a 1440 sumaban solos casi 200 px. */
[data-page="nosotros"] main > .sec { gap: clamp(24px, 3vw, 44px); }


/* ==========================================================================
   1 · Fundaciones: el recorrido del apoyo (.recorrido / .paso)

   Antes esto eran dos tarjetas, una por fundación, con filas de datos. El
   cliente las vio y dijo tres cosas: "parece ficha técnica", "las tarjetas son
   disparejas" y "debe ser otro enfoque de contenido". Y tenía razón: una
   tarjeta traía cuatro filas (estatus, teléfono, iglesias que apoyan, EIN) y la
   otra una lista de ocho nombres, así que ni medían lo mismo ni contaban lo
   mismo.

   Ahora la sección no describe dos entidades: cuenta CÓMO FLUYE EL APOYO, en
   tres pasos en fila — 01 LWF USA, 02 LWF Panamá, 03 los ocho ministerios y
   socios de ministerio. Sin cajas, sin tarjetas, sin tablas y sin filas de
   datos: los tres pasos van directamente sobre el fondo de la página, en tres
   columnas iguales con mucho aire entre ellas.

   Los datos que salieron no se perdieron: el estatus 501(c)(3), el teléfono,
   las iglesias que apoyan y el marcador del EIN viven en /es/lwf-usa/ (y su par
   EN) y en Donar; "qué es PCA", en /es/lwf-panama/ y en Ministerios; el enlace
   de donación de LWF Panamá, en /es/lwf-panama/.

   LA LÍNEA DEL RECORRIDO. Es el gesto de la marca: agua que corre. Una línea de
   2 px cruza los tres pasos por arriba, con un nodo de 12 px sobre cada uno y
   una punta de flecha llegando a los nodos 2 y 3. Empieza en el nodo 1 y acaba
   en el nodo 3 —sin cola— y se dibuja de izquierda a derecha una sola vez, en
   dos tramos de 600 ms encadenados (1,2 s en total); cada nodo se enciende
   justo cuando le llega el tramo.

   Cada paso pinta SU tramo con dos capas: el ::before es la base en --line, que
   se ve siempre, y el ::after el trazo en --accent, que arranca en scaleX(0). El
   nodo y la flecha son el ::before y el ::after del número. Así no hace falta ni
   un elemento de adorno en el HTML, ni un SVG, ni una imagen.

   SEGURO CONTRA FALLOS. El estado "sin dibujar" cuelga de data-reveal="" —el
   atributo que pone site.js, ver "Movimiento al bajar" en ENTREGA.md—, no de
   una clase del <head>: si site.js no carga, no hay atributo y la línea se ve
   completa. Con ?still=1 y con movimiento reducido site.js tampoco marca nada,
   así que las capturas salen con la línea entera. El @media del final es el
   cinturón por si el ajuste de movimiento cambia con la página ya abierta.

   ALTURAS IGUALES. Los seis elementos de cada paso (número, ícono, rótulo,
   nombre, frase y enlace) van en subgrid, así que se alinean fila por fila en las tres
   columnas aunque un nombre ocupe dos líneas y el de al lado una. La primera
   fila de la rejilla, de 12 px, es la del nodo: está vacía a propósito.
   ========================================================================== */
.recorrido, .recorrido-go {
  --paso-gap: clamp(32px, 3.6vw, 56px);   /* separación entre columnas */
  --paso-nodo: 12px;                      /* diámetro del nodo */
  --paso-vgap: 28px;                      /* separación vertical en el teléfono */
  --paso-dib: .6s;                        /* lo que tarda cada tramo de línea */
}
.recorrido {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: var(--paso-gap);
  row-gap: 10px;
}
.paso {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}

/* ---- La línea: base en --line y trazo en --accent ------------------------
   El tramo de cada paso llega hasta el nodo del siguiente, así que mide su
   columna más la separación. El último paso no pinta tramo: la línea acaba
   ahí, en su nodo. */
.paso::before,
.paso::after {
  content: "";
  position: absolute;
  left: 0;
  top: calc((var(--paso-nodo) - 2px) / 2);
  height: 2px;
  width: calc(100% + var(--paso-gap));
  border-radius: 2px;
}
.paso::before { background: var(--line); }
.paso::after { background: var(--accent); transform-origin: left; }
.paso:last-child::before,
.paso:last-child::after { content: none; }

/* ---- El nodo y la punta de flecha, colgados del número -------------------
   El número es el primer elemento del paso y cae justo debajo de la línea, así
   que sus pseudo-elementos son el sitio natural para el nodo (::before) y para
   la flecha que llega a él (::after). Van en posición absoluta contra el .paso,
   que es quien lleva position: relative. El halo de --bg es lo que hace que el
   nodo se recorte sobre la línea en vez de fundirse con ella. */
.paso-num {
  font: 500 12px/1 var(--f-mono);
  letter-spacing: .08em;
  color: var(--accent-2);
  font-variant-numeric: tabular-nums;
}
.paso-num::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: var(--paso-nodo);
  height: var(--paso-nodo);
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--bg);
}
/* La flecha: una caja de 8 px con dos bordes, girada 45°. Queda en el aire
   entre columnas, a unos 5 px del nodo al que llega. */
.paso:not(:first-child) .paso-num::after {
  content: "";
  position: absolute;
  left: -15px;
  top: 2px;
  width: 8px;
  height: 8px;
  border-top: 2px solid var(--accent);
  border-right: 2px solid var(--accent);
  transform: rotate(45deg);
}

/* ---- El dibujado, enganchado a data-reveal -------------------------------
   Sin el atributo (sin JS, con ?still=1, con movimiento reducido) la línea ya
   está donde está arriba: entera. data-reveal="" es el estado inicial que pone
   site.js y data-reveal="in" el de "ya entró en pantalla". */
.recorrido[data-reveal=""] .paso::after { transform: scaleX(0); }
.recorrido[data-reveal=""] .paso-num::before { background: var(--line); }
.recorrido[data-reveal=""] .paso-num::after { border-color: var(--line); }
.recorrido[data-reveal] .paso::after {
  transition: transform var(--paso-dib) var(--ease-out) var(--paso-d, 0s);
}
.recorrido[data-reveal] .paso-num::before,
.recorrido[data-reveal] .paso-num::after {
  transition: background-color .3s ease var(--paso-d, 0s), border-color .3s ease var(--paso-d, 0s);
}
.recorrido[data-reveal="in"] .paso::after { transform: scaleX(1); }
.recorrido[data-reveal="in"] .paso-num::before { background: var(--accent); }
.recorrido[data-reveal="in"] .paso-num::after { border-color: var(--accent); }
/* El retardo de cada paso: el tramo 1 sale de una, el 2 cuando el 1 termina.
   Los nodos se encienden al final del tramo que llega a ellos, así que el 3
   espera los dos tramos: 1,2 s en total. */
.paso:nth-child(2)::after { --paso-d: var(--paso-dib); }
.paso:nth-child(2) .paso-num::before,
.paso:nth-child(2) .paso-num::after { --paso-d: var(--paso-dib); }
.paso:nth-child(3) .paso-num::before,
.paso:nth-child(3) .paso-num::after { --paso-d: calc(var(--paso-dib) * 2); }

/* ---- Las cinco filas del paso ------------------------------------------- */
/* La fila del ícono mide 32 px y lo que se ve dentro también, que no es lo
   mismo que la caja: las banderas son SVG de twemoji con un lienzo de 36x36 en
   el que el dibujo solo ocupa 36x26, o sea cinco px de aire arriba y cinco
   abajo. Puestas a 32 px de caja se verían a 23 y la gota, que sí llena la
   suya, les ganaría. Por eso la bandera va a 44 px de caja (32 de dibujo) con
   -6 px de margen arriba y abajo: se sale de la fila por donde es transparente
   y no le roba aire ni al número ni al rótulo. */
.paso-ico { display: flex; align-items: center; height: 32px; }
.paso-ico img { width: auto; height: 44px; margin-block: -6px; }
/* La gota lleva dentro el árbol y "John 4:14": a 32 px es una mancha. Va a los
   mismos 36 px que en la cabecera y el pie, que es donde se reconoce. */
.paso-ico .paso-gota { height: 36px; margin-block: -2px; }
.paso-nombre {
  font-size: clamp(20px, 1.9vw, 27px);
  text-wrap: balance;
}
.paso-frase {
  color: var(--muted);
  font-size: clamp(16px, 1.25vw, 18px);
  line-height: 1.6;
  max-width: 34ch;
}

/* Los ocho ministerios: enlaces en línea separados por " · ", del mismo tamaño
   y color que las otras dos frases. Subrayado fino al pasar el puntero, nunca
   de entrada: de entrada serían ocho rayas y volvería a parecer una lista. El
   interlineado sube a 1,85 para que cada nombre tenga un área táctil cómoda sin
   que el padding descuadre la caja del párrafo. */
.paso-mins { max-width: none; line-height: 1.85; }
.paso-mins a {
  color: inherit;
  text-decoration: none;
  padding-block: 6px;
  transition: color var(--t-hover) ease;
}
.paso-mins a:hover { color: var(--accent-2); text-decoration: underline; text-decoration-thickness: 1px; }

/* "Conoce la fundación": enlace bajo la frase de los pasos 01 y 02, a la
   página propia de cada fundación (Daniel, 2026-10-14). Enlace de texto y no
   botón: dos botones más bajo los pasos pesarían, y la fila .recorrido-go ya
   lleva los botones de la sección. Flecha horizontal porque es interno. En
   --accent-2, que es el acento pensado para texto (#00697F en claro, #4FD9E0
   en oscuro), como el número del paso. Con subgrid va en su propia fila (la
   7), así los dos quedan a la misma altura aunque una frase tenga más líneas;
   el paso 03 deja esa celda vacía. */
.paso-go {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: start;
  justify-self: start;
  min-height: 44px;
  margin-top: 4px;
  font-weight: 500;
  font-size: clamp(15px, 1.15vw, 17px);
  color: var(--accent-2);
  text-decoration: none;
}
.paso-go svg { width: 18px; height: 18px; flex: none; transition: transform var(--t-hover) ease; }
.paso-go:hover { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .2em; }
.paso-go:hover svg { transform: translateX(3px); }

/* ---- Las alturas iguales, con subgrid ------------------------------------
   Las siete filas son: nodo, número, ícono, rótulo, nombre, frase y enlace. La primera
   queda vacía a propósito (el nodo va en posición absoluta) y las otras cinco
   llevan su fila ESCRITA. Escribirlas no es adorno: el acomodo automático de
   grid coloca primero lo que tiene fila fija y después lo demás empezando por
   la fila 1, así que con solo fijar el número el ícono se iba a la fila del
   nodo y se le montaba encima.

   Sin subgrid el paso se queda en la columna flex de arriba, que se ve bien
   salvo cuando un nombre ocupa dos líneas y el de al lado una: entonces las
   frases dejan de empezar a la misma altura, que es justo lo que subgrid
   arregla. */
@supports (grid-template-rows: subgrid) {
  @media (min-width: 761px) {
    .recorrido { grid-template-rows: var(--paso-nodo) auto auto auto auto auto auto; }
    .paso { display: grid; grid-template-rows: subgrid; grid-row: 1 / -1; }
    .paso-num { grid-row: 2; }
    .paso-ico { grid-row: 3; }
    .paso-tipo { grid-row: 4; }
    .paso-nombre { grid-row: 5; }
    .paso-frase { grid-row: 6; }
    .paso-go { grid-row: 7; }
  }
}

/* ---- La fila de acciones -------------------------------------------------
   Alineada a la misma rejilla de tres columnas: donar bajo el paso 1 y los
   ministerios bajo el paso 3. El aire de 40 px lo pone el gap de la sección
   (clamp(24px, 3vw, 44px)), no hace falta margen aquí. */
.recorrido-go {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: var(--paso-gap);
}
.recorrido-go > :first-child { grid-column: 1; justify-self: start; }
.recorrido-go > :last-child { grid-column: 3; justify-self: start; }

/* ---- El teléfono: el recorrido baja en vertical --------------------------
   La línea corre por la izquierda de arriba abajo —misma animación, con scaleY
   y transform-origin: top— con los tres nodos sobre ella y cada paso a su
   derecha. El tramo de cada paso va desde debajo de su nodo hasta el nodo del
   siguiente: de ahí el calc con --paso-vgap. */
@media (max-width: 760px) {
  .recorrido { grid-template-columns: minmax(0, 1fr); row-gap: var(--paso-vgap); }
  .paso { padding-left: 32px; gap: 8px; }
  .paso::before,
  .paso::after {
    left: calc((var(--paso-nodo) - 2px) / 2);
    top: calc(var(--paso-nodo) + 6px);
    width: 2px;
    height: calc(100% + var(--paso-vgap) - var(--paso-nodo) - 6px);
    transform-origin: top;
  }
  .recorrido[data-reveal=""] .paso::after { transform: scaleY(0); }
  .recorrido[data-reveal="in"] .paso::after { transform: scaleY(1); }
  /* La flecha apunta hacia abajo y se pone encima del nodo al que llega. */
  .paso:not(:first-child) .paso-num::after {
    left: 2px;
    top: -13px;
    transform: rotate(135deg);
  }
  .paso-nombre { font-size: clamp(20px, 5.4vw, 24px); }
  .paso-frase { font-size: 16px; max-width: none; }
  .paso-ico { height: 26px; }
  .paso-ico img { height: 36px; margin-block: -5px; }
  .paso-ico .paso-gota { height: 32px; margin-block: -3px; }
  /* Los dos botones en fila si caben y a todo el ancho si no. */
  .recorrido-go { display: flex; flex-wrap: wrap; gap: 12px; }
  .recorrido-go > .btn { flex: 1 1 200px; justify-content: center; }
}
@media (prefers-reduced-motion: reduce) {
  .recorrido[data-reveal=""] .paso::after { transform: none; }
  .recorrido[data-reveal=""] .paso-num::before { background: var(--accent); }
  .recorrido[data-reveal=""] .paso-num::after { border-color: var(--accent); }
  .recorrido[data-reveal] .paso::after,
  .recorrido[data-reveal] .paso-num::before,
  .recorrido[data-reveal] .paso-num::after { transition: none; }
}


/* ==========================================================================
   2 · Equipo: el carrusel a dos columnas

   El rótulo, el titular, la entradilla, el nombre de la familia y los controles
   van todos en la columna izquierda; la foto, en la derecha. Así la sección mide
   lo que mide la foto (1 470 px antes, con el titular encima y la foto a media
   página).

   La clave es que las cinco diapositivas ceden su caja (display: contents): la
   foto y el texto de cada una se colocan directamente en la retícula del
   carrusel, así que el titular —que NO está dentro de ninguna diapositiva— y la
   foto comparten la misma fila. Como la caja del .car-slide desaparece, el
   fundido va en sus hijos. Lo de arriba de 900 px nada más: en el teléfono el
   .car-stage sigue siendo la pista con scroll-snap del sistema.
   ========================================================================== */
.team-intro { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.team-intro > .text { max-width: 76ch; }
/* En media columna el titular de 66 px se iba a tres líneas y la entradilla
   quedaba pegada: aquí baja a 52, que es el tamaño con el que entra en dos.
   El nombre de la familia baja con él, para que no le gane al titular. */
@media (min-width: 900px) {
  .team-intro > .h2 { font-size: clamp(30px, 3.7vw, 52px); }
  .team-car .car-name { font-size: clamp(26px, 3vw, 40px); }
}

@media (min-width: 900px) {
  .team-car {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    column-gap: 24px;
    row-gap: clamp(16px, 1.8vw, 22px);
    align-items: start;
  }
  .team-intro { grid-column: 1 / 9; grid-row: 1; }
  .team-car.is-ready .car-stage,
  .team-car.is-ready .car-slide { display: contents; }
  /* La foto ocupa las tres filas de la izquierda: es la que marca el alto. */
  .team-car .car-photo { grid-column: 9 / 13; grid-row: 1 / span 3; max-height: 56svh; align-self: stretch; }
  .team-car .car-text { grid-column: 1 / 9; grid-row: 2; }
  .team-car .car-controls { grid-column: 1 / 9; grid-row: 3; display: block; }
  .team-car .car-name { max-width: 20ch; }
  /* A todo el ancho de la columna izquierda, la barra de progreso de 2 px
     parecía una regla de separación: se queda del largo de los controles. */
  .team-car .car-progress { max-width: 260px; }
  /* El fundido de 500 ms del sistema, movido a los hijos de la diapositiva
     porque la diapositiva ya no tiene caja que animar. */
  .team-car.is-ready .car-slide > * {
    opacity: 0;
    visibility: hidden;
    transform: translateX(24px);
    pointer-events: none;
    transition: opacity .5s var(--ease-out), transform .5s var(--ease-out), visibility 0s linear .5s;
  }
  .team-car.is-ready .car-slide.is-on > * {
    opacity: 1;
    visibility: visible;
    transform: none;
    pointer-events: auto;
    transition: opacity .5s var(--ease-out), transform .5s var(--ease-out), visibility 0s;
  }
  .team-car[data-still] .car-slide > *,
  .team-car[data-still] .car-slide.is-on > * { transition: none; }
}
@media (min-width: 900px) and (prefers-reduced-motion: reduce) {
  .team-car.is-ready .car-slide > * { transition: none; }
}
/* En el teléfono va todo apilado en el orden del HTML (título, foto, nombre,
   controles y miniaturas) y la foto no pasa de media pantalla. */
@media (max-width: 899px) {
  .team-car { gap: clamp(18px, 2.4vw, 32px); }
  .team-intro { gap: 12px; }
  .team-car .car-photo { max-height: 52svh; }
}
@media (max-width: 560px) {
  /* Miniaturas y aire de los controles más chicos: son cinco fotos de 56x70
     que en el teléfono valían 70 px de alto solo en la tira. */
  .team-car .car-bottom { gap: 10px; }
  .team-car .car-thumb { width: 46px; height: 58px; }
  .team-intro { gap: 10px; }
  .team-intro > .text { font-size: 15px; }
  .team-car .car-text { gap: 10px; }
}

/* ==========================================================================
   3 · Historia: filas bajas

   Los mismos cinco hitos, todos a la vista. Antes la foto iba a 3fr (310 px de
   ancho) y era ella la que marcaba el alto de la fila: 251 px por hito. Ahora
   mide 168x112 y la fila mide lo que mide el texto, que gana ancho.
   ========================================================================== */
.tl-low > li { grid-template-columns: minmax(0, 1.1fr) minmax(0, 2.8fr) minmax(0, 5.6fr) 168px; padding-block: 14px; gap: 6px 24px; }
.tl-low time { line-height: 1.5; }
.tl-low .media { width: 168px; aspect-ratio: 3 / 2; border-radius: var(--r-sm); align-self: center; }
.tl-low p { font-size: 15px; }

@media (max-width: 1100px) {
  .tl-low > li { grid-template-columns: minmax(0, 1.2fr) minmax(0, 3.4fr) minmax(0, 5fr) 140px; }
  .tl-low .media { width: 140px; }
}
@media (max-width: 760px) {
  /* La foto, chica y a la izquierda del título: así la fila mide lo que el
     texto y no se abre un hueco bajo una foto cuadrada. */
  /* Los selectores llevan .with-media porque los del sistema (más arriba en
     site.css) pesan lo mismo con esa clase puesta: sin ella, el texto se
     quedaba en la columna de 96 px de la foto y la fila se disparaba. */
  .tl-low.with-media > li { grid-template-columns: 96px minmax(0, 1fr); column-gap: 14px; row-gap: 4px; padding-block: 14px; }
  .tl-low.with-media > li > :not(.media) { grid-column: 2; }
  .tl-low.with-media .media { grid-column: 1; grid-row: 1 / span 3; width: 96px; aspect-ratio: 4 / 3; align-self: start; }
  .tl-low p { font-size: 14.5px; }
  .tl-low > li > .h3 { font-size: 17px; }
}
@media (max-width: 560px) {
  .tl-low.with-media > li { padding-block: 10px; }
  .tl-low > li > .h3 { font-size: 16.5px; }
  .tl-low p { font-size: 14px; }
}

/* ==========================================================================
   4 · Lo que creemos: tres columnas

   Los tres enunciados 01 a 03, uno por columna, con el número arriba en vez de
   a la izquierda y en tipografía de párrafo grande: en la de titular y apilados
   ocupaban 895 px. La nota y el botón quedan en una sola fila al pie (.split,
   del sistema).
   ========================================================================== */
.creo-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: clamp(24px, 3vw, 48px); }
.creo-3 > li {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-block: 18px 22px;
  font-family: var(--f-body);
  font-weight: 400;
  font-size: clamp(15.5px, 1.2vw, 17.5px);
  line-height: 1.5;
  letter-spacing: 0;
}
.creo-3 > li::before { line-height: 1.2; }
.creo-3 + .split { gap: 16px 40px; }
.creo-3 + .split .small { max-width: 64ch; }

@media (max-width: 900px) { .creo-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) {
  .creo-3 { grid-template-columns: minmax(0, 1fr); }
  .creo-3 > li { gap: 6px; padding-block: 10px 14px; font-size: 15px; }
  .creo-3 + .split { gap: 12px 40px; }
}

/* ==========================================================================
   5 · Equipo con bios (2026-09-30)

   Cada diapositiva trae ahora el rol (.car-role) y la bio completa (.car-bio,
   100 a 190 palabras). El rol va en el tono del texto principal, en la letra
   de párrafo, para que no se lea como un tercer rótulo debajo de los dos
   monoespaciados. Las bios se cortan a 62ch, igual que .text.

   Altura: en escritorio los .car-text de las cinco comparten la misma celda
   de la retícula (display: contents), así que la fila mide lo que mida la bio
   más larga y el carrusel no salta de alto al pasar. En el teléfono la pista
   es una fila de grid: cada diapositiva mide lo que la más alta. Nada se
   recorta.

   Con data-interval="0" no hay avance automático (site.js esconde el botón de
   pausa): la barra de progreso nunca se llenaría, así que se va también.
   ========================================================================== */
.car-role { font-family: var(--f-body); font-weight: 500; font-size: clamp(15px, 1.15vw, 17px); line-height: 1.4; color: var(--fg); max-width: 52ch; }
.team-car .car-bio { max-width: 62ch; font-size: clamp(15px, 1.1vw, 16.5px); line-height: 1.6; }
.carousel[data-interval="0"] .car-progress { display: none; }
@media (max-width: 899px) {
  /* El nombre y el rol pegados; la bio, un poco más separada. */
  .team-car .car-role { margin-top: -4px; }
}

/* Foto pendiente (2026-10-03): Davidson, Juliana Córdoba y Dan Aleks entran
   con sus bios antes que sus fotos. El recuadro guarda el lugar de la foto con
   las iniciales en la letra de titulares; en la vista de trabajo lleva además
   el marcador FALTA (el .ph se va en presentación). Cuando llegue la foto se
   cambia el contenido del <figure> por la <img> y se quita la clase. */
.car-photo-ph { display: grid; place-items: center; align-content: center; gap: 16px; border: 1px dashed var(--faint); }
.car-initials { font-family: var(--f-display); font-weight: var(--w-display); font-size: clamp(56px, 7vw, 104px); letter-spacing: var(--track-display); line-height: 1; color: var(--accent); }
.car-thumb-ph { display: grid; place-items: center; background: var(--panel-2); color: var(--accent); font: 500 13px/1 var(--f-mono); letter-spacing: .04em; }

/* Bio con "Leer más" (2026-10-03): con 100 a 190 palabras la bio se veía
   como un bloque largo (Daniel). site.js le pone .is-clamped y agrega el
   botón .bio-more debajo: se ven cuatro líneas que se desvanecen y el botón
   abre el resto ahí mismo. Sin JS no hay clase y la bio sale completa. El
   texto entero sigue en el HTML (buscadores y lectores de pantalla). Nada de
   "…": la última línea se desvanece en vez de cortarse. Lo mismo en las
   fichas de Ministerios: ahí site.js junta los párrafos de la bio en un
   .ficha-bio (con el mismo aire entre párrafos que tenía la ficha). */
.ficha-bio { display: flex; flex-direction: column; gap: 24px; align-self: stretch; }
@media (max-width: 899px) { .ficha-bio { gap: 20px; } }
.is-clamped:not(.is-open) {
  max-height: var(--clamp-h, 6.4em);  /* 4 líneas: site.js mide el interlineado */
  overflow: hidden;
  -webkit-mask-image: linear-gradient(#000 50%, transparent);
  mask-image: linear-gradient(#000 50%, transparent);
}
.bio-more {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  margin-top: -10px;
  padding: 0;
  border: 0;
  background: none;
  font: 500 15px/1.3 var(--f-body);
  color: var(--fg);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--fg) 34%, transparent);
  text-underline-offset: 4px;
  cursor: pointer;
  transition: text-decoration-color var(--t-hover) ease;
}
.bio-more:hover { text-decoration-color: var(--accent); }
.bio-more svg { width: 15px; height: 15px; flex: none; transition: transform var(--t-hover) var(--ease-out); }
.bio-more[aria-expanded="true"] svg { transform: rotate(180deg); }

/* <<< pagina:nosotros-lwf <<< */

/* ==========================================================================
   Teléfono: última palabra del sistema
   ========================================================================== */
/* Lo que se toca y NO es .btn, en el teléfono. Sale de la auditoría del
   2026-09-19 (las 14 páginas a 390 px, midiendo cada enlace, botón y campo):
   tras la regla de arriba quedaban estos casos.
     · Donar: el botón de cada tarjeta se quedaba a media anchura porque su
       fila (.give-foot) es un flex que se encoge; "Ver ficha" pasa debajo.
     · Datos de contacto (.facts): WhatsApp, teléfonos, correo y redes eran
       enlaces de texto de 24 px. Son justo lo que en un teléfono se toca para
       llamar o escribir: pasan a botones de contorno, como en el menú. Los
       demás enlaces de .facts (un mapa, una ficha) solo ganan área de toque.
     · Migas ("Nosotros / LWF USA", "Eventos / …"): 24 px de alto. Ganan área
       con relleno y margen negativo, sin mover nada de sitio.
   Va AL FINAL del archivo, después de los bloques de página, a propósito: son
   ajustes de teléfono sobre componentes que se definen más arriba (y algunos
   dentro de un bloque de página) con la misma especificidad, y en CSS gana la
   regla que llega última. cssblock.py solo reescribe entre sus marcadores, así
   que esto no lo toca. */
@media (max-width: 560px) {
  .give-foot { flex-direction: column; align-items: stretch; gap: 4px; width: 100%; }
  .soon-list a { min-width: 44px; }
  .give-more { display: inline-flex; align-items: center; align-self: flex-start; min-height: 44px; }

  .facts a { display: inline-flex; align-items: center; min-width: 44px; min-height: 44px; }
  .facts small a { display: inline; min-width: 0; min-height: 0; }
  .facts dd > a:is([href^="tel:"], [href^="mailto:"], [href*="whatsapp.com"], [href*="wa.me"]),
  .contact-links a {
    display: flex;
    justify-content: center;
    gap: 8px;
    width: 100%;
    min-height: 52px;
    margin-block: 4px;
    padding: 8px 18px;
    border: 1px solid color-mix(in srgb, var(--fg) 24%, transparent);
    border-radius: var(--r-pill);
    font: 500 16px/1.3 var(--f-body); /* los datos van en monoespaciada; un botón, no */
    letter-spacing: 0;
    text-align: center;
    text-decoration: none;
    overflow-wrap: anywhere;
  }
  .contact-links { align-items: stretch; gap: 6px; width: 100%; }

  .phead .label a,
  .event-crumb a { display: inline-block; min-width: 44px; margin-block: -14px; padding-block: 14px; }
}

/* Tarjeta flotante en el teléfono: el lugar y la cuenta regresiva van en dos
   líneas, sin el punto que los separa. En una sola línea el nombre del lugar
   se cortaba con "…", y al dejarlo entero la cuenta bajaba arrastrando un
   punto suelto al principio del renglón. */
@media (max-width: 760px) {
  .event-float-meta { flex-direction: column; gap: 0; }
  .event-float-count::before { content: none; }
}


/* ==========================================================================
   LWF USA / LWF Panamá: fila de verbos y declaración (2026-10-14)

   El resumen con que Todd cerró el correo del 2026-10-08 ("USA = connects,
   raises… / Panama = receives…") va como una fila de palabras sueltas,
   separadas por un punto medio. Primero fue un recorrido numerado con la
   línea de Nosotros; Daniel lo descartó el mismo día porque sugería una
   secuencia que el correo no dice. Por eso aquí no hay números, ni línea, ni
   tamaño de titular: el mismo cuerpo de letra que el párrafo de "Qué hace"
   (.prose no fija tamaño, así que se hereda), en peso 500 y en tinta para que
   se distinga del texto atenuado. En el teléfono la fila se parte sola; cada
   verbo baja entero ("Ministra en el terreno" no se parte por dentro).
   ========================================================================== */
.verbos {
  display: flex;
  flex-wrap: wrap;
  --verbos-aire: clamp(14px, 2vw, 28px);   /* a cada lado del punto */
  column-gap: var(--verbos-aire);
  row-gap: 8px;
  list-style: none;
  margin: 0;
  padding: 0;
  font-weight: 500;
  color: var(--fg);
}
.verbos li { white-space: nowrap; }
/* El punto va dentro del li siguiente, con el mismo aire a cada lado (el
   column-gap a la izquierda y el margin a la derecha). En el teléfono la fila
   se parte y el punto quedaría al principio del renglón, así que ahí no hay
   punto: las palabras se separan solo con el aire. */
.verbos li + li::before { content: "·"; color: var(--muted); margin-right: var(--verbos-aire); }
@media (max-width: 560px) {
  .verbos { column-gap: 18px; row-gap: 6px; }
  .verbos li + li::before { content: none; margin: 0; }
}


/* La declaración: el tercer párrafo del correo en .quote, más chico que el de
   fábrica (44 px) para que a 1440 entre en cuatro o cinco líneas en c-main y en
   el teléfono no pase de nueve. */
.lwf-decl .quote { font-size: clamp(21px, 2.3vw, 32px); max-width: 36ch; }


/* ==========================================================================
   Cinta de prueba (2026-10-20): la pinta shell.js solo fuera de producción
   (dev., local., localhost). Pegada arriba, amarilla, por encima de la
   cabecera; la cabecera (.bar) baja lo que mide la cinta (--devbar-h, que
   shell.js mide en píxeles) para no pasar por debajo al hacer scroll. El
   amarillo se oscurece un poco en modo oscuro (automático o elegido con
   <html data-theme="dark">); el texto siempre es oscuro.
   ========================================================================== */
:root { --devbar-h: 0px; }
.devbar {
  position: sticky; top: 0; z-index: 60;
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 2px 10px;
  padding: 7px 16px;
  background: #ffd84d; color: #1b1b1b;
  font-size: 13px; line-height: 1.35; text-align: center;
}
.devbar-tag { font-family: var(--f-mono); font-weight: 700; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; }
.devbar a { color: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.devbar a:hover { text-decoration-thickness: 2px; }
:root[data-dev="1"] .bar { top: calc(env(safe-area-inset-top, 0px) + 12px + var(--devbar-h)); }
@media (prefers-color-scheme: dark) { html:not([data-theme="light"]) .devbar { background: #f2c93c; } }
html[data-theme="dark"] .devbar { background: #f2c93c; }
