/* ============================================================
   Pelis Sí o Sí — tokens y componentes base (fase 0)
   Paleta y tipografía reales del kit actual (correcciones §1.3).
   ============================================================ */

:root {
  --c-primary: #2DD4BF;
  --c-primary-dark: #0D9488;
  --c-accent: #EC4899;
  --c-ink: #374151;
  --c-ink-soft: #6B7280;
  --c-bg: #FFF7ED;
  --c-rose: #B88585;
  --c-paper: #FFFFFF;
  --c-border: #E5E7EB;
  --radius: 12px;
  --shadow: 0 1px 3px rgba(55, 65, 81, .12);
  --tap: 44px; /* objetivo táctil mínimo */
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: Roboto, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 16px;
  line-height: 1.55;
  color: var(--c-ink);
  background: var(--c-bg);
}

a { color: var(--c-primary-dark); }
h1, h2 { line-height: 1.2; }
h1 { font-size: 1.6rem; }
h2 { font-size: 1.15rem; }
.meta { color: var(--c-ink-soft); font-size: .9rem; }

.container { max-width: 1100px; margin: 0 auto; padding: 16px; }

/* --- Cabecera --- */
.site-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 16px;
  background: linear-gradient(135deg, var(--c-primary-dark), var(--c-primary));
}
.site-header .brand {
  color: #fff; text-decoration: none; font-weight: 700; font-size: 1.2rem;
  /* 👆 El 95% del uso es móvil: el logotipo es un enlace a la portada y tiene
     que ser tan pulsable como cualquier otro. Sin esto medía 30 px de alto. */
  display: inline-flex; align-items: center; min-height: var(--tap);
}
.site-header .brand span { color: #CFFAFE; }
.site-header nav a { color: #ECFEFF; font-size: .9rem; }

.site-footer { padding: 24px 16px; text-align: center; color: var(--c-ink-soft); font-size: .85rem; }
/* 👆 Los enlaces del pie eran de 18 px de alto: cuatro dianas seguidas
   («✨ ¿Qué te apetece?», «🧬 Mezclador», «Créditos y fuentes» y
   «Privacidad») a un dedo de distancia unas de otras. `inline-block` +
   relleno vertical los sube a los 44 px de `--tap` sin tocar el marcado ni
   los separadores «·», que siguen siendo texto suelto del <p>. */
.site-footer p a {
  display: inline-block; min-height: var(--tap);
  padding: 12px 6px; line-height: 20px;
}
.attribution { color: var(--c-ink-soft); font-size: .78rem; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* --- Buscador de cabecera + sugerencias --- */
.header-search { position: relative; flex: 1; max-width: 420px; margin-left: 16px; }
.header-search input {
  /* 44px, no 40: es el buscador de cabecera y en móvil se pulsa con el pulgar. */
  width: 100%; min-height: var(--tap); padding: 8px 14px;
  border: none; border-radius: 999px; font-size: 1rem;
  background: rgba(255, 255, 255, .92); color: var(--c-ink);
}
.header-search input:focus { outline: 3px solid var(--c-accent); }
.suggest {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 30;
  background: var(--c-paper); border: 1px solid var(--c-border);
  border-radius: var(--radius); box-shadow: 0 8px 24px rgba(55, 65, 81, .18);
  overflow: hidden;
}
.suggest__item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; min-height: 44px;
  text-decoration: none; color: var(--c-ink); font-size: .95rem;
}
.suggest__item img { border-radius: 4px; flex-shrink: 0; }
.suggest__item small { color: var(--c-ink-soft); }
.suggest__item:hover, .suggest__item.is-active { background: #CCFBF1; }
.suggest__mini {
  width: 28px; height: 42px; display: inline-flex; align-items: center;
  justify-content: center; background: #F3F4F6; border-radius: 4px; flex-shrink: 0;
}

/* --- Home --- */
.hero { margin: 8px 0 18px; }
.hero h1 { margin: 0 0 4px; color: var(--c-primary-dark); }

/* --- Buscador de momento --- */
.wizard { text-align: center; padding: 4vh 0; }
.wizard h1 { font-size: 1.7rem; }
.wizard-crumb { color: var(--c-ink-soft); font-size: .9rem; text-align: left; }
.mood-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px; max-width: 560px; margin: 20px auto 0;
}
.mood-grid--row { max-width: 720px; }
.mood-card {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  justify-content: center; min-height: 110px; padding: 14px 10px;
  background: var(--c-paper); border-radius: var(--radius); box-shadow: var(--shadow);
  text-decoration: none; color: var(--c-ink);
  border: 2px solid transparent; transition: border-color .12s ease;
}
.mood-card:hover { border-color: var(--c-primary); }
.mood-card__emoji { font-size: 1.9rem; }
.mood-card small { color: var(--c-ink-soft); }
.mood-card--skip { min-height: 64px; background: transparent; box-shadow: none; border: 1px dashed var(--c-border); }

.momento-results h1 { color: var(--c-primary-dark); }
.card-why { margin: 6px 0 0; font-size: .78rem; color: var(--c-ink-soft); }
.card-why--exception { color: var(--c-accent); }

.flash {
  background: #CCFBF1; border: 1px solid var(--c-primary);
  border-radius: var(--radius); padding: 10px 14px; margin-bottom: 14px;
}
.flash--warn { background: #FEF3C7; border-color: #FCD34D; }

.filter-sheet {
  background: var(--c-paper); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 4px 16px 8px; margin-bottom: 16px;
}
.filter-sheet summary {
  cursor: pointer; min-height: var(--tap); display: flex; align-items: center;
  font-weight: 600; color: var(--c-primary-dark);
}
.filter-sheet fieldset { border: none; margin: 8px 0; padding: 0; }
.filter-sheet legend { font-weight: 600; margin-bottom: 6px; }
.filter-sheet select { max-width: 320px; min-height: var(--tap); padding: 8px 12px; border: 1px solid var(--c-border); border-radius: 10px; font-size: 1rem; }
.filter-actions { display: flex; gap: 10px; }

.chip-group { display: flex; flex-wrap: wrap; gap: 8px; }
.chip-input { display: inline-block; margin: 0; }
.chip-input input { position: absolute; opacity: 0; width: 0; height: 0; }
.chip-input span {
  display: inline-flex; align-items: center; min-height: var(--tap);
  padding: 8px 14px; border-radius: 999px;
  background: #F3F4F6; border: 2px solid var(--c-border);
  font-size: .95rem; cursor: pointer; user-select: none;
}
.chip-input input:checked + span { background: #CCFBF1; border-color: var(--c-primary-dark); font-weight: 600; }
.chip-input input:focus-visible + span { outline: 3px solid var(--c-accent); outline-offset: 2px; }

.btn {
  display: inline-block; min-height: var(--tap); padding: 10px 16px;
  border-radius: 10px; border: 1px solid var(--c-border);
  background: var(--c-paper); color: var(--c-ink);
  font-size: 1rem; cursor: pointer; text-decoration: none; text-align: center;
}
.btn--primary { background: var(--c-primary-dark); border-color: var(--c-primary-dark); color: #fff; }

.card-oneliner { margin: 6px 0 0; font-size: .82rem; color: var(--c-rose); }
.search-title { font-size: 1.3rem; }

/* --- Ficha: bloques nuevos --- */
/* .dim-list se retiró con la sección «Cuándo verla» (§7.2). */
.before-watching { background: #FEF3C7; border-radius: 8px; padding: 8px 12px; }
.video-buttons { display: flex; flex-wrap: wrap; gap: 10px; margin: 0; }
.btn-video {
  display: inline-flex; align-items: center; min-height: var(--tap);
  padding: 8px 18px; border-radius: 999px; text-decoration: none;
  background: var(--c-accent); color: #fff; font-weight: 500;
}
.btn-video:hover { opacity: .9; }
.legal { max-width: 720px; }

@media (max-width: 480px) {
  .site-header { flex-wrap: wrap; gap: 8px; }
  .header-search { max-width: none; margin-left: 0; flex-basis: 100%; }
}

/* --- Chips y sellos --- */
.chip {
  display: inline-block;
  padding: 4px 12px;
  margin: 2px 4px 2px 0;
  border-radius: 999px;
  font-size: .82rem;
  font-weight: 500;
  background: var(--c-paper);
  border: 1px solid var(--c-border);
}
.chip--valuation.chip--peli_siosi { background: var(--c-primary); border-color: var(--c-primary-dark); color: #063f3a; }
.chip--valuation.chip--recomiendo { background: #CCFBF1; border-color: var(--c-primary); }
.chip--valuation.chip--pasable { background: #FEF3C7; border-color: #FCD34D; }
.chip--valuation.chip--mala { background: #FEE2E2; border-color: #FCA5A5; }
.chip--seal-alfonso { background: var(--c-accent); border-color: var(--c-accent); color: #fff; }
.chip--seal-auto { background: #F3F4F6; border-color: var(--c-border); color: var(--c-ink-soft); font-style: italic; }

/* ADN-EN-LA-WEB §3 · LOS TRES ESTADOS DE FICHA.
   Un chip por estado, con la misma forma que los demás y tres lecturas
   distintas de un vistazo. Los textos salen de config (config/vibes.php,
   clave `estados`); aquí solo está el color.

     ✅ Analizada por Alfonso  el rosa de marca: es la firma de la casa
     🔦 Propuesta del Acomodador  turquesa claro con el borde punteado, que
        dice «hay rúbrica, pero todavía no está firmada»
     ⬜ Sin analizar  gris y en cursiva, como la nota al pie que es

   Ni un color nuevo: todo sale de los tokens de :root. */
.chip--estado { font-family: Roboto, var(--emoji), sans-serif; }
.chip--estado.est--alfonso { background: var(--c-accent); border-color: var(--c-accent); color: #fff; }
.chip--estado.est--acomodador {
  background: #CCFBF1; border-color: var(--c-primary-dark);
  border-style: dashed; color: var(--c-primary-dark); font-weight: 600;
}
.chip--estado.est--vacia {
  background: #F3F4F6; border-color: var(--c-border);
  color: var(--c-ink-soft); font-style: italic;
}

/* 🧬 EL CHIP «Tiene ADN» de la cabecera de la ficha (ADN-EN-LA-WEB §1.2).
   Va con los otros chips, pero es el único que además ES UN ENLACE: baja a la
   receta. Se distingue por eso —fondo turquesa clarito y subrayado al pasar—,
   no por un color nuevo. Objetivo táctil de 44 px como todo lo pulsable. */
.chip--adn {
  display: inline-flex; align-items: center; min-height: var(--tap);
  background: #CCFBF1; border-color: var(--c-primary-dark);
  color: var(--c-primary-dark); font-weight: 600; text-decoration: none;
  font-family: Roboto, var(--emoji), sans-serif;
}
.chip--adn:hover { background: var(--c-primary); color: #063f3a; }
.chip--adn:focus-visible { outline: 3px solid var(--c-primary-dark); outline-offset: 2px; }
/* El destino del salto: que no quede pegado al borde de arriba, y que el foco
   que le pone public.js no dibuje un recuadro raro alrededor de la sección. */
.adn-block { scroll-margin-top: 12px; }
.adn-block:focus { outline: none; }
.adn-block:focus-visible { outline: 3px solid var(--c-primary); outline-offset: 2px; }

/* §3 · LA LÍNEA HONESTA de la ficha vacía: «Alfonso todavía no la ha
   analizado. Está aquí porque es ingrediente o hermana de películas de la
   casa.» No es una advertencia ni un error, así que ni rojo ni icono de
   alarma: el papel de la caja con el filete turquesa a la izquierda, como una
   nota del que te atiende. El texto vive en config. */
.ficha__honesta {
  margin: 10px 0 0;
  padding: 10px 14px;
  background: var(--c-tint);
  border-left: 3px solid var(--c-primary);
  border-radius: 0 10px 10px 0;
  color: var(--c-ink-soft);
  font-size: .92rem;
  line-height: 1.5;
  max-width: 62ch;
}

/* --- Barra de verificación (sprint 1) --- */
.verify-bar { margin-bottom: 16px; }
.pill {
  display: inline-block; margin: 2px 6px 2px 0; padding: 4px 10px;
  background: var(--c-paper); border: 1px solid var(--c-border);
  border-radius: 8px; font-size: .85rem; color: var(--c-ink-soft);
}
.pill b { color: var(--c-primary-dark); }

/* --- Rejilla de tarjetas ---
   AJUSTES-INTERFAZ §2 · FILAS DE ALTURA IGUAL. Antes iba `align-items: start`
   y cada tarjeta medía lo suyo: una con one-liner quedaba un dedo más alta que
   su vecina y la parrilla se leía como una dentadura. Con el `stretch` por
   defecto de la rejilla, todas las tarjetas de una fila miden EXACTAMENTE lo
   que mide la más alta de esa fila; el reparto interno en zonas fijas (cartel
   de proporción fija, título de 2 líneas, Vibra de 1, chips de 2 y la barra de
   afinidad pegada al botón) hace que además queden alineadas entre sí.

   Los separadores de sección y los botones de tanda ocupan la fila entera
   (`grid-column: 1 / -1`), así que nunca comparten fila con una tarjeta. */
.movie-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}
@media (min-width: 600px) {
  .movie-grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
}

.movie-card {
  display: block;
  background: var(--c-paper);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  transition: transform .12s ease;
}
.movie-card:hover { transform: translateY(-2px); }
.movie-card__body { padding: 10px 12px 12px; }
.movie-card h2 { font-size: .98rem; margin: 0 0 4px; }
.movie-card .meta { margin: 0 0 6px; }

.poster {
  display: block; width: 100%; aspect-ratio: 2 / 3;
  object-fit: cover; background: #E7E5E4;
}
.poster--empty {
  display: flex; align-items: center; justify-content: center;
  font-size: 2rem; color: var(--c-ink-soft);
}

/* ============================================================
   LA FICHA · LA CABECERA, MÓVIL PRIMERO
   ------------------------------------------------------------
   Traslado de plantillas-ficha/generar.py · ficha_def() (maqueta
   aprobada del 27-8-2026). Tres áreas y UN SOLO HTML: el orden
   lo decide el grid, no la plantilla.

     ≤680 px      >680 px
     ---------    -------------------
     texto        [ media ][ texto   ]
     media        [ media ][ detalle ]
     detalle

   En móvil (el 95 % del uso) lo primero es TÍTULO + VEREDICTO
   —que es la respuesta a «¿la veo?»—, y justo debajo el cartel y
   «📺 Dónde verla» EN FILA, que ahorra media pantalla. En
   escritorio el cartel vuelve a la izquierda, ocupando las dos
   filas, como manda la maqueta.
   ============================================================ */
.cab {
  display: grid;
  grid-template-areas: "media texto" "media detalle";
  grid-template-columns: minmax(0, 280px) minmax(0, 1fr);
  gap: 8px 26px;
  align-items: start;
  margin-bottom: 18px;
}
.cab-media { grid-area: media; min-width: 0; }
.cab-texto { grid-area: texto; min-width: 0; }
.cab-detalle { grid-area: detalle; min-width: 0; }

/* El cartel. `height:auto` es necesario: el <img> lleva height="513" y ese
   atributo gana sobre aspect-ratio, con lo que el cartel salía estirado. */
.cartel {
  border: 2px solid var(--c-primary); border-radius: 8px; overflow: hidden;
  box-shadow: 0 8px 26px rgba(0, 0, 0, .28); background: var(--c-tint);
}
.cartel img { width: 100%; height: auto; aspect-ratio: 2 / 3; object-fit: cover; display: block; }
.cartel--vacio {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 2 / 3; font-family: var(--emoji); font-size: 2.4rem; color: var(--c-ink-soft);
}

/* EL RÓTULO PEQUEÑO. Es el `.etq` de la maqueta (plantillas-ficha/generar.py ·
   BASE_CSS): versalita gris con tracking, la etiqueta que va encima de un
   bloque sin robarle el sitio al bloque. Lo usan los DOS modos —«En una
   frase» y «📺 Dónde verla» en la ficha; «La sesión», «👯 Pelis hermanas» y
   «Ha sido ingrediente de» en el margen de la revista—, así que vive aquí
   arriba y no dentro de ninguno de los dos.

   Se trajeron en su día las dos EXCEPCIONES (`.verla .etq` cambia el display y
   `.frase .etq` el color) pero no la regla de la que son excepción, así que
   estos rótulos se estaban pintando como texto corrido de 16 px. */
.etq {
  font-size: .72rem; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--c-ink-soft);
  font-family: Roboto, var(--emoji), sans-serif;
}

/* 📺 Dónde verla, junto al cartel (sin sticky: es donde miras primero). */
.verla {
  background: var(--c-paper); border: 1.5px solid var(--c-primary);
  border-radius: 10px; padding: 12px; margin-top: 12px; text-align: center;
}
.verla .etq { display: block; margin-bottom: 8px; }
.verla-logos { display: flex; flex-wrap: wrap; gap: 5px; justify-content: center; }
.verla-logos img { width: 38px; height: 38px; border-radius: 8px; }
.verla small { display: block; margin-top: 4px; color: var(--c-ink-soft); }
/* Es un enlace de navegación de verdad (baja a «Dónde verla» entero), así que
   es un objetivo táctil de verdad: 44 px aunque la letra sea pequeña. */
.verla small a {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); padding: 0 6px;
}

.cab-texto h1 { margin: 0 0 2px; font-size: 2rem; color: var(--c-primary-dark); }
.original-title { margin: 0 0 4px; color: var(--c-ink-soft); font-style: italic; }
/* El veredicto y el ↗ Compartir en la misma línea: la respuesta y lo que se
   hace con ella. `align-items:center` para que el botón no baile con los chips. */
.acciones {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin: 8px 0 6px;
}

/* Facetas objetivas de la línea meta (stamps de categoría 'perfil'): hechos
   como 🎨 Animación o 👻 Terror. Chip pequeño y apagado a propósito: no debe
   competir con la Vibra titular ni con los chips de veredicto. */
.meta-faceta {
  display: inline-flex; align-items: center; gap: 4px;
  margin-left: 6px; padding: 1px 8px;
  border: 1px solid var(--c-border); border-radius: 999px;
  background: var(--c-paper);
  font-size: .72rem; font-weight: 500; color: var(--c-ink-soft);
  font-family: Roboto, var(--emoji), sans-serif;
  white-space: nowrap;
}

/* ------------------------------------------------------------
   «EN UNA FRASE» — sobria: rótulo pequeño en rosa y la frase en
   serif grande. SIN fondo, SIN degradado y SIN comillas: las
   quitó la tercera vuelta de la maqueta a propósito.
   Sin frase (63 de 87 películas hoy) la plantilla no pinta el
   bloque, así que aquí no hace falta ninguna regla de «vacío».
   ------------------------------------------------------------ */
.frase { margin: 14px 0 4px; }
.frase .etq { color: var(--c-accent); }
.frase p {
  margin: 2px 0 0;
  font-family: "Roboto Slab", Georgia, "Times New Roman", serif;
  font-size: 1.35rem; line-height: 1.5; color: var(--c-ink);
}

/* La vibra titular y sus compañeras de identidad, en una línea. */
.vibra-linea { margin: 12px 0 8px; font-size: 1rem; font-family: Roboto, var(--emoji), sans-serif; }
.vibra-linea .vx { font-size: 1.45rem; font-family: var(--emoji); vertical-align: -4px; }
.vibra-linea b { color: var(--c-primary-dark); font-weight: 800; }
.vibra-linea .tambien { color: var(--c-ink-soft); }

/* La sesión: las cinco dimensiones de la rúbrica, una por línea. */
.dims {
  list-style: none; margin: 8px 0 10px; padding: 0;
  display: grid; gap: 6px; font-size: .94rem;
  font-family: Roboto, var(--emoji), sans-serif;
}
.dims li { display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: baseline; }
.dims .d-etq { font-weight: 700; color: var(--c-primary-dark); white-space: nowrap; }
.dims .d-val { color: var(--c-ink-soft); }
.dims .d-sep { color: var(--c-primary); font-weight: 700; }

/* --- MÓVIL: lo primero, porque es el 95 % del uso -------------------- */
@media (max-width: 680px) {
  .cab {
    grid-template-areas: "texto" "media" "detalle";
    grid-template-columns: minmax(0, 1fr);
    gap: 6px;
  }
  /* Cartel y «Dónde verla», EN FILA. Media pantalla ganada.
     Estos dos porcentajes son los que declara el `sizes` del cartel en
     templates/public/movie.php (44 % con plataformas, 62 % sin ellas, menos el
     borde de .cartel) para elegir entre el derivado de 342 y el de 780: si se
     tocan aquí, se tocan allí. */
  .cab-media { display: grid; grid-template-columns: 44% minmax(0, 1fr); gap: 12px; align-items: start; }
  /* Sin plataformas no hay segunda columna: el cartel se queda solo y
     centrado, sin dejar medio hueco a su derecha. */
  .cab-media--sola { grid-template-columns: minmax(0, 62%); justify-content: center; }
  .verla { margin-top: 0; }
  .verla-logos img { width: 34px; height: 34px; }
  .cab-texto h1 { font-size: 1.6rem; }
  .frase p { font-size: 1.12rem; }
  .dims { font-size: .9rem; }
}
@media (max-width: 899px) and (min-width: 681px) {
  .cab { grid-template-columns: minmax(0, 230px) minmax(0, 1fr); gap: 8px 18px; }
  .cab-texto h1 { font-size: 1.7rem; }
}

.ficha section { background: var(--c-paper); border-radius: var(--radius); box-shadow: var(--shadow); padding: 14px 16px; margin-bottom: 14px; }
.ficha section h2 { margin-top: 0; color: var(--c-primary-dark); }

/* Los ejes 0-3 de la guía de estilo (.axes) se fueron con §7: el público ya no
   los pinta y no queda ninguna plantilla que los use. */
.one-liner { color: var(--c-rose); font-weight: 500; margin: 10px 0 0; }

.opinion__text { white-space: normal; }

/* --- Relaciones: similares, ADN y mezclador --- */
.similar-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.similar-item {
  display: flex; align-items: center; gap: 10px; min-height: 56px;
  text-decoration: none; color: var(--c-ink);
  border: 1px solid var(--c-border); border-radius: 10px; padding: 6px 10px;
}
.similar-item:hover { border-color: var(--c-primary); }
.similar-item img { border-radius: 6px; flex-shrink: 0; }
.similar-item small { display: block; color: var(--c-ink-soft); }

/* ============================================================
   🧬 EL ADN COMO RECETA · ADN-EN-LA-WEB §1.1
   ------------------------------------------------------------
   La sección deja de ser una lista de títulos y pasa a leerse
   como una FÓRMULA:

     [cartel] Cabaret  +  [cartel] Romeo…  +  [cartel] Chicago
              1972 ⬜             1996 ⬜             2002 ⬜
                  …y de esa mezcla sale Moulin Rogue

   POR QUÉ NO SE PARECE A «👯 Pelis hermanas»: las hermanas son
   una LISTA de fichas anchas, una debajo de otra, con su «por
   qué» en texto. El ADN es una FILA de tarjetas estrechas unidas
   por signos +, centrada y con una frase de cierre. No comparten
   ni la forma, ni el color de fondo, ni el verbo: aunque el ojo
   se salte los rótulos, no puede confundirlas.
   ============================================================ */
.adn-cocina { margin: 0 0 10px; }

.adn-receta {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; align-items: stretch;
  justify-content: center; gap: 6px 4px;
}
/* Cada ingrediente: la tarjeta mini y, pegado a su derecha, el + que la une
   con la siguiente (menos en la última).
   `align-items: stretch` a propósito: los tres recuadros miden LO MISMO de
   alto aunque un título ocupe cinco líneas y otro una («Romeo + Julieta de
   William Shakespeare» al lado de «Chicago»). Tres cajas desiguales se leen
   como una lista mal alineada; tres iguales, como los términos de una suma.
   Los títulos NO se recortan: en una receta lo que importa es reconocer la
   peli, y media palabra no la reconoce nadie. */
.adn-ing { display: flex; align-items: stretch; }
.adn-op {
  display: flex; align-items: center; align-self: center;
  font-size: 1.3rem; font-weight: 700; color: var(--c-primary-dark);
  padding: 0 6px; user-select: none;
}

/* La tarjeta mini enlazada: mini-cartel + título + año (+ chip si es vacía).
   Es un objetivo táctil de verdad, no un enlace de texto: 44 px de sobra. */
.adn-ing__box {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  width: 104px; min-height: var(--tap); padding: 8px 6px;
  border: 1px solid var(--c-border); border-top: 3px solid var(--c-border);
  border-radius: 10px; background: var(--c-paper);
  text-decoration: none; color: var(--c-ink); text-align: center;
}
a.adn-ing__box:hover { border-color: var(--c-primary); box-shadow: var(--shadow); }
a.adn-ing__box:focus-visible { outline: 3px solid var(--c-primary-dark); outline-offset: 2px; }
/* Un ingrediente sin ficha publicada se pinta pero no se enlaza (<span>). */
span.adn-ing__box { cursor: default; opacity: .8; }

/* El cartel arriba y el año abajo del todo: con las cajas estiradas, el año
   pegado al borde inferior alinea los tres pies aunque los títulos midan
   distinto. */
.adn-ing__poster { width: 72px; height: 108px; object-fit: cover; border-radius: 6px; flex-shrink: 0; }
.adn-ing__t { margin-top: 2px; }
.adn-ing__y { margin-top: auto; }
.adn-ing__poster--vacio {
  display: flex; align-items: center; justify-content: center;
  background: var(--c-tint); font-family: var(--emoji); font-size: 1.5rem;
}
.adn-ing__t { font-size: .82rem; line-height: 1.25; font-weight: 700; }
.adn-ing__y { font-size: .75rem; color: var(--c-ink-soft); }
/* §1.1 · «Sin analizar», en pequeño y sin gritar: es un dato, no un aviso. */
.adn-ing__estado {
  font-size: .68rem; line-height: 1.3; padding: 1px 6px;
  border: 1px dashed var(--c-border); border-radius: 999px;
  background: #F3F4F6; color: var(--c-ink-soft); font-style: italic;
  font-family: Roboto, var(--emoji), sans-serif;
}

/* §1.1 · «si tiene veredicto de Alfonso, su franja de color»: el filete de
   arriba de la tarjeta, con los MISMOS colores que los chips de veredicto de
   la cabecera (.chip--valuation). Ni un color nuevo. */
.adn-ing--peli_siosi .adn-ing__box { border-top-color: var(--c-primary); }
.adn-ing--recomiendo .adn-ing__box { border-top-color: var(--c-primary-dark); }
.adn-ing--pasable .adn-ing__box { border-top-color: #FCD34D; }
.adn-ing--mala .adn-ing__box { border-top-color: #FCA5A5; }

/* La frase de cierre: es el resultado de la fórmula, así que va centrada,
   debajo de la fila y con el mismo peso que un titular pequeño. */
.adn-cierre {
  margin: 12px 0 0; text-align: center;
  font-size: 1.02rem; font-weight: 700; color: var(--c-primary-dark);
}
/* La note de la MEZCLA (la que explica el conjunto), en cursiva. */
.adn-nota {
  margin: 6px 0 0; text-align: center; font-style: italic;
  color: var(--c-rose); max-width: 62ch; margin-inline: auto;
}
.adn-mezclador { margin: 8px 0 0; font-size: .9rem; }
/* 44 px de alto, que en la ficha es el último enlace de la caja del ADN y se
   toca con el pulgar. (En /adn esta línea no se pinta: ya estás en él.) */
.adn-mezclador a {
  display: inline-flex; align-items: center; min-height: var(--tap); padding: 0 2px;
}

/* EN MÓVIL LA FÓRMULA SIGUE SIENDO UNA FÓRMULA. Con las medidas de escritorio
   (104 px por ingrediente) los tres no caben en los 311 px útiles de un móvil
   de 375 y el tercero se va a una segunda línea, dejando un «+» colgando al
   final de la primera: exactamente la lista que §1.1 no quiere. Así que aquí
   la tarjeta encoge —84 px y cartel de 56— y los tres siguen en una línea:
   3×84 + 2 operadores + los huecos = 294 px de 311. El `flex-wrap` se queda
   como red por si un título muy largo o un tamaño de letra grande obligan. */
@media (max-width: 420px) {
  .adn-ing__box { width: 84px; padding: 6px 4px; }
  .adn-ing__poster { width: 56px; height: 84px; }
  .adn-ing__poster--vacio { font-size: 1.2rem; }
  .adn-ing__t { font-size: .76rem; }
  .adn-ing__y { font-size: .7rem; }
  .adn-ing__estado { font-size: .62rem; padding: 1px 4px; }
  .adn-op { padding: 0 4px; font-size: 1.1rem; }
  .adn-receta { gap: 6px 0; }
}

/* La consulta inversa se queda como estaba: lista simple. */
.adn-items { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
/* «Ha sido ingrediente de» es la puerta de salida de una ⬜ ficha vacía: en
   móvil tiene que ser un objetivo táctil de verdad, no un enlace de 21 px. El
   `li` se estira con él para que la nota «(aporta: …)» quede a su altura. */
.adn-items li { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; }
.adn-items li > a { display: inline-flex; align-items: center; min-height: var(--tap); }

/* 👯 PELIS HERMANAS (§2.4) · La línea que las separa del 🔮 de arriba y del
   🧬 de abajo: dice de dónde salen y que van en las dos direcciones. */
.hermanas__entrada { margin: 0 0 10px; color: var(--c-ink-soft); font-size: .9rem; max-width: 62ch; }
.hermana__porque { display: block; color: var(--c-ink-soft); }

.mixer h1 { color: var(--c-primary-dark); }
.mixer-picker { background: var(--c-paper); border-radius: var(--radius); box-shadow: var(--shadow); padding: 12px 14px; }
.mixer-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
.mixer-chip {
  display: inline-flex; align-items: center; gap: 8px;
  background: #CCFBF1; border: 1px solid var(--c-primary-dark);
  border-radius: 999px; padding: 4px 6px 4px 6px; font-size: .92rem;
}
.mixer-chip img { border-radius: 4px; }
.mixer-chip__remove {
  border: none; background: none; font-size: 1.1rem; cursor: pointer;
  min-width: 32px; min-height: 32px; color: var(--c-ink-soft);
}
.mixer-search { position: relative; }
/* El campo con el que se monta la mezcla era un <input> pelado: 21 px de alto,
   la mitad de la diana mínima, y es el control principal de /adn. Mismo trato
   que el buscador de la cabecera. */
.mixer-search input {
  width: 100%; max-width: 320px; min-height: var(--tap); padding: 8px 14px;
  border: 1px solid var(--c-border); border-radius: 999px;
  font: inherit; font-size: 1rem; background: var(--c-paper); color: var(--c-ink);
}
.mixer-search input:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 1px; }
.mixer-search .suggest { position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 20; }
.suggest button.suggest__item { width: 100%; border: none; background: none; font: inherit; cursor: pointer; text-align: left; }

.mixer-result { background: var(--c-paper); border-radius: var(--radius); box-shadow: var(--shadow); padding: 14px 16px; margin-top: 16px; }
.mixer-result h2 { margin-top: 0; color: var(--c-primary-dark); }
/* OJO: la regla era `.mixer-hija a` y ahora está acotada a la clase. Desde
   ADN-EN-LA-WEB §2.1 dentro de `.mixer-hija` va la receta entera (la parcial
   _adn_receta.php), con sus tres enlaces de ingrediente: un selector por
   etiqueta se los llevaba por delante. */
.mixer-hija__link { display: flex; align-items: center; gap: 14px; text-decoration: none; color: var(--c-ink); font-size: 1.15rem; margin-bottom: 8px; }
/* La receta dentro del mezclador no repite la caja blanca: ya está dentro de
   `.mixer-result`, que es la caja. */
.mixer-hija .adn-block { background: none; box-shadow: none; padding: 0; margin: 12px 0 0; }
.mixer-parcial { margin: 0 0 4px; }
/* §2.1 · La marca ⬜ de un ingrediente elegido que es ficha vacía. */
.mixer-chip__estado { color: var(--c-ink-soft); font-style: italic; font-size: .78rem; }
/* Y la misma marca en el desplegable de sugerencias (cabecera y mezclador). */
.suggest__estado { color: var(--c-ink-soft); font-style: italic; }
.mixer-hija img { border-radius: 10px; box-shadow: var(--shadow); }
.mixer-cerca { padding: 8px 0; border-bottom: 1px dashed var(--c-border); }
.mixer-cerca:last-child { border-bottom: none; }
.mixer-propose { display: flex; gap: 8px; flex-wrap: wrap; }
.mixer-propose input[type="text"] { flex: 1; min-width: 220px; }

.credits ul { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 6px 14px; }
.credits li { display: flex; justify-content: space-between; gap: 8px; border-bottom: 1px dashed var(--c-border); padding: 4px 0; }

/* --- Sistema de diseño (styleguide) --- */
.swatches { display: flex; flex-wrap: wrap; gap: 12px; }
.swatch { text-align: center; font-size: .8rem; color: var(--c-ink-soft); }
.swatch i { display: block; width: 84px; height: 52px; border-radius: 8px; border: 1px solid var(--c-border); margin-bottom: 4px; }

.empty-state { text-align: center; padding: 48px 16px; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ============================================================
   Tarjeta de película — estructura y proporciones de la tarjeta
   original de pelisiosi.com (loop item de Elementor):
   cartel + franja turquesa con la valoración en vertical y los
   logos de plataformas, separadores fucsia, banda de sellos,
   los seis ejes y el botón de ficha.
   ============================================================ */

:root {
  --c-tint: rgba(184, 133, 133, .15); /* la banda rosa pálida del original */
  --emoji: "Segoe UI Emoji", "Apple Color Emoji", "Noto Color Emoji", sans-serif;
}

.peli-card {
  /* El ancho de la franja lateral turquesa: 28 px de logo + 5 de aire a cada
     lado. Es la única medida que la tarjeta necesita saber de memoria, y vive
     aquí para que el cartel pueda reservarle el hueco (§2). */
  --card-side: 40px;
  position: relative;
  display: flex;
  flex-direction: column;
  /* La rejilla estira la tarjeta hasta el alto de su fila; esto asegura que la
     tarjeta lo ocupe entero también donde no sea hija directa de la rejilla. */
  height: 100%;
  background: var(--c-paper);
  border: 2px solid var(--c-primary);
  border-radius: 5px;
  box-shadow: 0 0 5px 0 rgba(0, 0, 0, .5);
  overflow: hidden;
}

/* --- AJUSTES-INTERFAZ §3 · EL AURA de las 🎬 Peli Sí o Sí ------------------
   La línea rosa de 3 px que llevaban arriba (.peli-card--siosi::before) se
   RETIRA: se leía como un error de maquetación, no como una distinción.

   En su lugar, la tarjeta entera lleva un aura: dos sombras superpuestas del
   rosa de marca sobre el borde redondeado —una CERCANA y tenue (14 px, .20) y
   otra AMPLIA y casi imperceptible (44 px, .09)— y el borde en rosa REBAJADO
   (el mismo #EC4899 al 45 %, no el saturado) para que el halo tenga filo. La
   sombra negra de siempre se queda debajo: el aura se suma, no sustituye.

   Sutil es el requisito: al lado de una tarjeta normal se distingue de un
   vistazo, pero no hay neón. En hover o foco el halo se abre un punto.

   El ancho del borde NO cambia (siguen 2 px, como en toda tarjeta): la
   geometría interna tiene que ser idéntica en las 87 para que los carteles de
   una fila midan lo mismo, que es lo que pide §2. Lo que cambia es el color.

   La franja vertical del veredicto («🎬 Peli Sí o Sí» girado) se queda como
   estaba: eso ya funcionaba. */
.peli-card--siosi {
  border-color: rgba(236, 72, 153, .45);
  box-shadow: 0 0 5px 0 rgba(0, 0, 0, .5),
              0 2px 14px rgba(236, 72, 153, .20),
              0 10px 44px rgba(236, 72, 153, .09);
  transition: box-shadow .18s ease;
}
.peli-card--siosi:hover,
.peli-card--siosi:focus-within {
  box-shadow: 0 0 5px 0 rgba(0, 0, 0, .5),
              0 3px 18px rgba(236, 72, 153, .28),
              0 14px 56px rgba(236, 72, 153, .14);
}

/* Lo mismo en la ficha (§3, segunda mitad). La maqueta definitiva se llevó por
   delante la caja de la rúbrica —ahora la vibra y la sesión van sueltas, sin
   recuadro— así que el aura se muda AL CARTEL, que es lo que se mira primero y
   lo que hace de «portada» de la película. Mismos dos halos y mismo borde rosa
   rebajado que en la tarjeta: ni un color nuevo, ni un efecto nuevo. Sigue
   siendo permanente, porque es una señal de nobleza de la película y no el
   resultado de ningún filtro. */
.ficha--siosi .cartel {
  border-color: rgba(236, 72, 153, .55);
  box-shadow: 0 8px 26px rgba(0, 0, 0, .28),
              0 2px 14px rgba(236, 72, 153, .20),
              0 10px 44px rgba(236, 72, 153, .09);
  transition: box-shadow .18s ease;
}
.ficha--siosi .cartel:hover {
  box-shadow: 0 8px 26px rgba(0, 0, 0, .28),
              0 3px 18px rgba(236, 72, 153, .28),
              0 14px 56px rgba(236, 72, 153, .14);
}

@media (prefers-reduced-motion: reduce) {
  .peli-card--siosi,
  .ficha--siosi .cartel { transition: none; }
}

/* -- fila superior: cartel + franja lateral --
   §2 · El cartel manda el alto de esta zona y su proporción es FIJA (2/3), así
   que dos tarjetas del mismo ancho tienen el mismo cartel, tengan el póster
   que tengan. La franja lateral va posicionada sobre el hueco que le reserva
   el margen derecho del cartel: si fuera un ítem más del flex, una peli con
   cuatro logos de plataforma estiraría la fila entera. */
.peli-card__top {
  position: relative;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  border-bottom: 2px solid var(--c-accent);
}

.peli-card__poster {
  flex: 1 1 auto;
  min-width: 0;
  display: block;
  line-height: 0;
  background: #E7E5E4;
  /* El hueco de la franja lateral. */
  margin-right: var(--card-side);
  aspect-ratio: 2 / 3;
}
/* OJO AL TOCAR ESTO: el `sizes` del cartel (templates/public/_card.php) declara
   estas mismas medidas para elegir entre el derivado de 342 y el de 780. En
   móvil el cartel mide 100vw − 76 px (16+16 del .container, 2+2 de borde y los
   40 de --card-side), o sea 299 px en un 375 —598 reales con DPR 2, que es por
   lo que hacía falta el de 780—; de 600 px para arriba lo más ancho que llega a
   medir son 324 px. Si cambia --card-side o el minmax de .movie-grid, cambia
   también el `sizes` o los carteles vuelven a salir borrosos. */
.peli-card__poster img {
  width: 100%; height: 100%; display: block;
  object-fit: cover;
}

.peli-card__noposter {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; width: 100%; height: 100%; padding: 18px;
  text-align: center; line-height: 1.4;
  background: linear-gradient(160deg, var(--c-bg), #FFE9D6);
  color: var(--c-primary-dark);
}
.peli-card__noposter span { font-size: 2.2rem; font-family: var(--emoji); }
.peli-card__noposter b { font-size: 1rem; }
.peli-card__noposter small { color: var(--c-ink-soft); font-size: .75rem; }

/* franja turquesa: valoración en vertical arriba, plataformas abajo.
   Ancla al alto del cartel (no al revés): lo que no quepa se recorta antes que
   estirar la tarjeta. Con 4 logos —el máximo del catálogo— sobra sitio. */
.peli-card__side {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: var(--card-side);
  display: flex; flex-direction: column;
  justify-content: space-between; align-items: center;
  overflow: hidden;
  background: var(--c-primary);
  padding: 8px 0 10px;
}
.peli-card__verdict {
  writing-mode: vertical-rl;
  font-family: Roboto, var(--emoji), sans-serif;
  font-size: .95rem; font-weight: 600; color: var(--c-ink);
  text-shadow: 0 0 39px #fff;
  margin: 5px 4px;
  white-space: nowrap;
}
.peli-card__logos { display: flex; flex-direction: column; gap: 4px; padding: 0 5px; }
.peli-card__logos img { width: 28px; height: 28px; border-radius: 6px; display: block; }

/* -- título --
   §2 · Zona de DOS LÍNEAS clavadas: `min-height` para que un título corto no
   suba el resto de la tarjeta y `line-clamp` para que uno largo se recorte con
   puntos suspensivos en vez de crecer. El título entero sigue disponible: es
   el texto del enlace, y el lector de pantalla lo lee completo. */
.peli-card__title {
  margin: 0; padding: 7px 10px;
  text-align: center; font-size: .92rem; line-height: 1.3;
  min-height: calc(2.6em + 14px);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
}
.peli-card__title a { color: var(--c-primary-dark); text-decoration: none; font-weight: 600; }
.peli-card__title a:hover { text-decoration: underline; }
.peli-card__title .original { color: var(--c-ink-soft); font-weight: 400; }

/* La banda de tipos y «🔖 Sellos especiales» (.peli-card__stamps, .stamp) y los
   seis ejes 🟩⬛ (.peli-card__axes, .axis) se retiraron en la segunda entrega
   (NOVEDADES-FILTRADO §7.1): la rúbrica pública son las vibras. El aviso «Sin
   analizar» se conserva con estilo propio (.peli-card__auto, más abajo). */

.peli-card__notes { padding: 8px 12px 0; }
.peli-card__notes p { margin: 0 0 4px; }
/* §2 · El one-liner es la única pieza de largo imprevisible de la tarjeta: se
   recorta a 3 líneas para que una cita kilométrica no estire la fila entera. */
.peli-card__notes .card-oneliner {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3;
  overflow: hidden;
}

/* -- botón --
   §2 · SIEMPRE pegado abajo. El `margin-top: auto` se lo come todo el hueco
   sobrante de la tarjeta estirada... salvo que haya barra de afinidad: como
   .afin va antes en el DOM y lleva el mismo `margin-top: auto`, es ella la que
   se queda el hueco y el botón la sigue, pegado. Así la barra y el botón viajan
   juntos al fondo de la tarjeta, que es lo que pide la zona. */
.peli-card__cta {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin-top: auto; min-height: 44px; padding: 9px 12px;
  background: var(--c-accent); color: #fff;
  font-size: .92rem; font-weight: 700; text-decoration: none;
}
.peli-card__cta:hover { background: #D92D86; }
.peli-card__cta:focus-visible { outline: 3px solid var(--c-primary-dark); outline-offset: -3px; }

/* -- §9.3 · «Dónde verla», versión mini y al final de la ficha --------------
   La parrilla de cajones (.watch-list / .watch-item) ocupaba media pantalla
   repitiendo lo que ya dice «Ya la puedes ver en» de la cabecera. Ahora es una
   línea por tipo de oferta: etiqueta corta a la izquierda y logos desnudos de
   28 px a la derecha, con el nombre en `title` (tooltip al pasar por encima) y
   en `alt` (para el lector de pantalla). Ni cajas, ni bordes, ni botones. */
.donde-verla--mini h2 { margin-bottom: 8px; }
.wmini {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px;
  margin: 0 0 8px;
}
.wmini__et {
  flex: 0 0 auto; min-width: 108px;
  font-size: .82rem; font-weight: 600; color: var(--c-ink-soft);
}
.wmini__logos { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.wmini__logos img { width: 28px; height: 28px; border-radius: 6px; display: block; }
/* Plataforma sin logo guardado: el nombre en texto, que valga igual. */
.wmini__nom { font-size: .82rem; color: var(--c-ink-soft); }
.donde-verla--mini .attribution { margin-top: 10px; }

@media (max-width: 599px) {
  /* En móvil la etiqueta se pone en su propia línea antes que estrujarse. */
  .wmini__et { min-width: 100%; }
}

@media (max-width: 599px) {
  .peli-card__verdict { font-size: .95rem; }
}

/* ============================================================
   Filtrado por vibras — barra, paneles y anotaciones de tarjeta
   (FILTRADO-Y-WIZARD.md §2). Se apoya en los tokens de arriba:
   teal para lo elegido, fucsia para lo que llama a la acción,
   crema de fondo. No rediseña nada: extiende.
   ============================================================ */

/* Las tarjetas y los chips llevan display propio, así que el `hidden` del
   navegador se queda corto: aquí se le da la última palabra. */
[hidden] { display: none !important; }

/* --- Hero del catálogo -----------------------------------------------------
   AJUSTES-INTERFAZ §5 · UNA SOLA PUERTA A LA GUIADA. El hero pierde sus tres
   botones grandes —entre ellos el segundo «🧭 Búsqueda guiada», que duplicaba
   la tarjeta de debajo—: quedan el título, el claim y, a la derecha (debajo en
   móvil), dos ENLACES secundarios discretos al wizard rápido y al ADN. Así la
   única llamada a la acción grande de la página es la tarjeta de la guiada. */
.hero--catalogo {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: 2px 20px;
  margin: 8px 0 12px;
}
.hero--catalogo h1 { font-size: 1.5rem; }
.hero__txt { flex: 1 1 320px; min-width: 0; }
.hero__ayuda { display: inline-block; }

/* Los dos enlaces secundarios: peso de enlace, área táctil de botón. Nada de
   fondo ni de borde — si pesaran como un botón volveríamos a tener tres
   llamadas a la acción compitiendo, que es justo lo que §5 viene a quitar. */
.hero__links {
  flex: 0 1 auto;
  display: flex; flex-wrap: wrap; align-items: center; gap: 2px 16px;
  margin: 0;
}
.hero__enlace {
  display: inline-flex; align-items: center;
  min-height: var(--tap); padding: 4px 2px;
  border: 0; background: none; cursor: pointer;
  font: inherit; font-size: .92rem; font-weight: 600;
  font-family: Roboto, var(--emoji), sans-serif;
  color: var(--c-primary-dark);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--c-border);
}
.hero__enlace:hover { text-decoration-color: var(--c-primary); }
.hero__enlace:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; border-radius: 6px; }

.btn-wiz {
  background: var(--c-accent); border-color: var(--c-accent); color: #fff; font-weight: 700;
}
.btn-wiz:hover { background: #D92D86; }

/* La búsqueda guiada es la entrada principal (§2): fucsia sólido y con más
   cuerpo que el resto de CTAs del hero, que quedan como apoyo. */
.btn--guiada {
  background: var(--c-accent); border-color: var(--c-accent); color: #fff;
  font-weight: 800; padding: 10px 20px;
}
.btn--guiada:hover { background: #D92D86; }
.btn--guiada:focus-visible { outline: 3px solid var(--c-primary-dark); outline-offset: 2px; }

/* --- Tarjeta-invitación del recorrido (armazón; guiada.js la expande) ------
   Plegada bajo el hero. Los ids son el contrato con assets/js/guiada.js:
   #recorrido-invitacion (la tarjeta), #btn-guiada (empezar) y #recorrido (el
   hueco donde se expande el recorrido, aquí mismo). */
.rec-invita {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
  background: var(--c-paper); border: 1.5px dashed var(--c-primary);
  border-radius: var(--radius); padding: 12px 14px; margin: 0 0 12px;
}
.rec-invita__txt { flex: 1 1 220px; min-width: 0; }
.rec-invita__t { margin: 0; font-size: 1.05rem; color: var(--c-primary-dark); }
.rec-invita__claim { margin: 2px 0 0; font-size: .88rem; color: var(--c-ink-soft); }
.rec:not([hidden]) { margin: 0 0 12px; }

/* --- El recorrido de 6 pasos (NOVEDADES-FILTRADO.md §1) --------------------
   NO es un overlay: es un bloque que se expande EN la página, en el hueco que
   deja la tarjeta-invitación. Por debajo de 600 px pasa a bottom sheet, el
   mismo patrón (y el mismo velo) que los paneles de la barra. Ni un color ni
   una medida nuevos: teal lo elegido, fucsia lo que empuja, 44 px de dedo. */
.rec__velo { position: fixed; inset: 0; z-index: 45; background: rgba(38, 50, 65, .35); }

.rec__caja {
  position: relative;
  background: var(--c-paper); border: 1.5px solid var(--c-primary); border-radius: 18px;
  padding: 16px 18px 14px;
  box-shadow: 0 10px 30px rgba(55, 65, 81, .14);
  animation: rec-entra .18s ease-out;
}
@keyframes rec-entra { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
.rec__caja:focus { outline: none; }

/* Cabecera SIEMPRE visible: progreso, «Paso x de 6» y la ✕ (§1.3). */
.rec__cab { display: flex; align-items: center; gap: 10px; }
.rec__pasos { display: flex; gap: 6px; flex: 0 0 auto; }
.rec__punto { width: 22px; height: 4px; border-radius: 999px; background: var(--c-border); }
.rec__punto.on { background: var(--c-primary); }
.rec__cuenta {
  margin: 0; flex: 1 1 auto;
  font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--c-ink-soft);
}
/* Misma ✕ que los paneles: círculo de 34 px con área táctil de 44. */
.rec__x {
  position: relative; flex: 0 0 auto;
  border: 0; background: none; cursor: pointer; font: inherit;
  width: 34px; height: 34px; border-radius: 999px; color: var(--c-ink-soft);
}
.rec__x::after { content: ""; position: absolute; inset: -5px; }
.rec__x:hover { background: #F3F4F6; }
.rec__x:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }

/* «N cumplen todo lo elegido»: aria-live, así que reserva su alto aunque esté
   vacío — el bloque no puede dar un salto la primera vez que se llena. */
.rec__total {
  margin: 8px 0 0; min-height: 1.2em;
  font-size: .82rem; font-weight: 700; color: var(--c-primary-dark);
  font-variant-numeric: tabular-nums;
}
.rec__q { margin: 2px 0 4px; font-size: 1.3rem; font-weight: 800; color: var(--c-primary-dark); line-height: 1.2; }
.rec__opcional { font-size: .8rem; font-weight: 600; color: var(--c-ink-soft); }
.rec__matiz { margin: 0 0 12px; font-size: .88rem; color: var(--c-ink-soft); }

.rec__ops { max-height: 46vh; overflow-y: auto; }
.rec__chips { display: flex; flex-wrap: wrap; gap: 7px; }

/* Jerarquía de familias del paso «Cómo te deja»: igual que en el panel de la
   barra, título clicable que marca o desmarca sus hijas en bloque. */
.rec__fam-bloque { width: 100%; }
.rec__fam {
  display: flex; align-items: center; gap: 8px; width: 100%;
  border: 0; background: none; cursor: pointer; font: inherit;
  margin: 10px 0 6px; padding: 4px 2px; min-height: 34px;
  font-size: .75rem; letter-spacing: .08em; text-transform: uppercase;
  font-weight: 600; color: var(--c-ink-soft); text-align: left;
}
.rec__fam-bloque:first-child .rec__fam { margin-top: 0; }
.rec__fam:hover, .rec__fam.on { color: var(--c-primary-dark); }
.rec__fam:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }
.rec__fam-x { margin-left: auto; }

.rec__chip {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--tap); padding: 8px 13px;
  border: 1.5px solid var(--c-border); border-radius: 999px;
  background: #F3F4F6; color: var(--c-ink); font: inherit; font-size: .88rem; cursor: pointer;
}
.rec__chip:hover { border-color: var(--c-primary); }
.rec__chip:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }
.rec__chip.on { background: var(--c-primary-dark); border-color: var(--c-primary-dark); color: #fff; font-weight: 700; }
/* Diferencia deliberada con la barra (§1.4): conteo a 0 = atenuado PERO
   clicable. Aquí no hay callejones sin salida — el recorrido acaba en Amplio
   y esa preferencia sí puntúa, así que nada de `disabled`. */
.rec__chip.cero { opacity: .45; }
.rec__chip.cero.on { opacity: 1; }
/* Paso con muchas opciones (config: `compacto`): chips más apretados para que
   los 20 de Vibra no se coman la pantalla. El dedo NO se toca: siguen a 44 px. */
.rec__ops--compacto .rec__chips { gap: 6px; }
.rec__ops--compacto .rec__chip { padding: 6px 11px; font-size: .82rem; gap: 5px; }
.rec__chip-e { font-family: var(--emoji); }
.rec__chip-n { font-size: .72rem; color: var(--c-ink-soft); font-variant-numeric: tabular-nums; }
.rec__chip.on .rec__chip-n { color: #CCFBF1; }

.rec__nav { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 14px; }
.rec__nav-der { display: flex; align-items: center; gap: 8px; }
.rec__atras, .rec__igual {
  min-height: var(--tap); padding: 8px 16px; cursor: pointer; font: inherit; font-size: .88rem;
  background: none; border: 1.5px solid var(--c-border); border-radius: 999px; color: var(--c-ink-soft);
  white-space: nowrap;
}
.rec__atras:hover, .rec__igual:hover { border-color: var(--c-primary); color: var(--c-primary-dark); }
.rec__atras:focus-visible, .rec__igual:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }
/* Paso opcional: saltarlo deja de ser el plan B y se pinta como lo que es,
   una salida de primera clase (§1.2). */
.rec__igual--fuerte { border-color: var(--c-primary); color: var(--c-primary-dark); font-weight: 700; }
.rec__sig { white-space: nowrap; }

.rec__salida { margin: 10px 0 0; text-align: center; }
.rec__ya {
  min-height: var(--tap); padding: 6px 10px; cursor: pointer;
  background: none; border: 0; font: inherit; font-size: .82rem;
  color: var(--c-ink-soft); text-decoration: underline;
}
.rec__ya:hover { color: var(--c-primary-dark); }
.rec__ya:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }
/* §Fase 6 · El separador «Afinar (opcional)» que abre los pasos de afinado,
   y el «Ver resultados ya» subido de rango dentro de ese bloque: quien pare
   ahí ya tiene una buena búsqueda, y el botón deja de ser letra pequeña. */
.rec__afinar {
  margin: 0 0 10px; padding-top: 10px; border-top: 1px dashed var(--c-border);
  font-size: .85rem; color: var(--c-ink-soft);
}
.rec__afinar b { color: var(--c-primary-dark); text-transform: uppercase; letter-spacing: .04em; font-size: .78rem; }
.rec__ya--fuerte {
  font-size: .95rem; font-weight: 700; color: var(--c-primary-dark);
  border: 2px solid var(--c-primary-dark); border-radius: var(--radius);
  padding: 8px 16px; text-decoration: none;
}
/* §Fase 6 · El enlace al tutorial en la tarjeta-invitación de la guiada. */
.rec-invita__tutorial { margin-left: .6em; font-size: .85em; color: var(--c-primary-dark); white-space: nowrap; }

@media (max-width: 599px) {
  /* Bottom sheet, mismo patrón que .fpanel: sube de abajo y el velo tapa. */
  .rec__caja {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
    max-height: 88vh; overflow-y: auto;
    border-radius: 18px 18px 0 0; border-left: 0; border-right: 0; border-bottom: 0;
    padding: 14px 14px 20px;
    box-shadow: 0 -8px 30px rgba(55, 65, 81, .3);
    animation: rec-sube .18s ease-out;
  }
  @keyframes rec-sube { from { transform: translateY(100%); } to { transform: translateY(0); } }
  html.rec-abierto { overflow: hidden; }
  .rec__q { font-size: 1.15rem; }
  .rec__ops { max-height: 44vh; }
  /* Los tres botones no caben en una línea de 375 px sin partir palabras: el
     principal baja a su propia fila, a lo ancho. «Atrás» se queda arriba (y
     su hueco sigue reservado en el paso 1). */
  .rec__nav { flex-wrap: wrap; row-gap: 8px; }
  .rec__nav-der { flex: 1 1 100%; }
  .rec__igual { flex: 0 0 auto; }
  .rec__sig { flex: 1 1 auto; }
}

/* --- Atajos (presets): ya no lo primero, fila de apoyo bajo la barra (§2) ---
   Discretos de tamaño de letra, pero el dedo conserva sus 44 px. */
.fatajos { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0 0 14px; }
.fatajos__et {
  font-size: .78rem; font-weight: 700; color: var(--c-ink-soft);
  letter-spacing: .04em; margin-right: 2px;
}
.fpreset {
  min-height: var(--tap); padding: 6px 13px;
  background: var(--c-paper); border: 1.5px solid var(--c-border); border-radius: 999px;
  font: inherit; font-size: .82rem; color: var(--c-ink-soft); cursor: pointer;
}
.fpreset:hover { border-color: var(--c-primary); color: var(--c-ink); }
.fpreset:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }
/* Atajo encendido = la selección de la barra es EXACTAMENTE la suya. Tocarlo
   otra vez lo deshace (§3), así que se pinta como lo que es: un interruptor. */
.fpreset.on {
  background: var(--c-primary-dark); border-color: var(--c-primary-dark);
  color: #fff; font-weight: 700;
}

/* ============================================================
   §2 · La tira 📺 Mis plataformas, arriba del todo
   ------------------------------------------------------------
   Fina y SIEMPRE visible: es la respuesta permanente a «¿se
   está teniendo esto en cuenta o no?». Dos zonas tocables
   hermanas (nada de un botón dentro de otro): el cuerpo abre el
   panel de siempre y el indicador enciende y apaga el reparto
   por plataformas sin perder la selección.
   ============================================================ */
.ftira {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px;
  margin: 0 0 10px; padding: 4px 6px;
  background: var(--c-paper); border: 1px solid var(--c-border); border-radius: 999px;
}
/* Sin ninguna marcada la tira es una invitación larga: deja de ser píldora y
   se comporta como una línea de texto que envuelve sin cortarse. */
.ftira--vacia { border-style: dashed; border-radius: var(--radius); }
.ftira__abre {
  display: flex; flex: 1 1 auto; flex-wrap: wrap; align-items: center; gap: 4px 8px;
  min-width: 0; min-height: 36px; padding: 4px 10px;
  border: 0; border-radius: 999px; background: none; cursor: pointer;
  font: inherit; font-size: .85rem; color: var(--c-ink-soft); text-align: left;
}
.ftira__abre:hover { background: #F3F4F6; color: var(--c-ink); }
.ftira__abre:focus-visible { outline: 3px solid var(--c-accent); outline-offset: -2px; }
.ftira__et { font-weight: 700; color: var(--c-ink); font-family: Roboto, var(--emoji), sans-serif; }
.ftira__vacia { flex: 1 1 200px; min-width: 0; }
.ftira__logos { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.ftira__logo { width: 24px; height: 24px; border-radius: 6px; display: block; }
.ftira__logo--vacio {
  font-family: var(--emoji); font-size: .8rem; line-height: 24px; text-align: center;
  background: #F3F4F6; color: var(--c-ink-soft);
}
.ftira__cambiar { text-decoration: underline; font-size: .8rem; }

/* El interruptor «✓ activo / — en pausa»: el corazón de §2.1. Encendido va en
   teal (está actuando); en pausa, gris y con el borde punteado. */
.ftira__ind {
  flex: 0 0 auto; min-height: 36px; padding: 5px 13px;
  border: 1.5px solid var(--c-border); border-radius: 999px;
  background: var(--c-paper); color: var(--c-ink-soft);
  font: inherit; font-size: .8rem; font-weight: 700; white-space: nowrap; cursor: pointer;
  font-family: Roboto, var(--emoji), sans-serif;
}
.ftira__ind:hover { border-color: var(--c-primary); }
.ftira__ind:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }
.ftira__ind.on { border-color: var(--c-primary-dark); background: #CCFBF1; color: var(--c-primary-dark); }
/* §10.2: la nota de pausa se lleva una línea entera para sí. */
.ftira__nota {
  flex: 0 0 100%; margin: 0; padding: 0 12px 4px;
  font-size: .78rem; color: var(--c-accent);
}

/* ============================================================
   §3 · La barra «Explorar»: la mesa de mandos
   ------------------------------------------------------------
   Tarjeta contenedora con identidad propia (crema un punto más
   oscuro y borde suave), distinta de la guiada —que es
   conversación— y de la parrilla. Tres piezas y una escala de
   espaciado de 8/12/16: cabecera (etiqueta + contador FUERA de
   toda zona que escrolee o recorte), fila de mandos que
   ENVUELVE, y chips activos en su propia línea.

   Criterio de aceptación (§3.2 · §10.6): nada se corta a 360,
   768, 1080 ni 1440 px. Por eso `flex-wrap: wrap` y NI UN
   `overflow: hidden` sobre la fila.
   ============================================================ */
/* La tarjeta ya NO va pegada arriba (`position: sticky`). Con los botones
   envolviendo mide entre dos y cuatro filas según el ancho; pegada al borde
   superior se comería entre un quinto y un tercio de la pantalla en cada
   scroll, que es justo lo contrario de lo que pide esta entrega. Se queda
   donde está, con identidad de tarjeta, y los separadores de sección de la
   parrilla tampoco son sticky (§1.3): la página entera baja limpia. */
.fbar {
  background: linear-gradient(180deg, #FFFDF9, #FDF3E7);
  border: 1.5px solid var(--c-border); border-radius: 18px;
  box-shadow: 0 10px 30px rgba(55, 65, 81, .10);
  padding: 12px 16px; margin: 0 0 12px;
}

.fbar__cab {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  margin: 0 0 8px;
}
.fbar__et {
  font-size: .78rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
  color: var(--c-ink-soft); font-family: Roboto, var(--emoji), sans-serif;
}

/* La fila de mandos. Jamás se recorta ni se esconde nada.
   AJUSTES-INTERFAZ §4 · UNA SOLA LÍNEA. Al retirarse el toggle «🎬 Sí o Sí
   primero» quedan OCHO piezas —🎲, las seis dimensiones y ⏱️— y caben en una
   línea a los anchos que pide §8.6 (1080 y 1440 px). El `flex-wrap: wrap` de
   antes se queda solo como red de seguridad para anchos raros; la primera
   respuesta a un ancho justo es COMPACTAR el interior de los botones (menos
   relleno, menos hueco, letra un punto menor), que es lo que hacen las dos
   consultas de más abajo. El contador y «Limpiar todo» siguen fuera de esta
   fila, en la cabecera y en la línea de chips activos.
   Por debajo de 600 px manda el bloque de móvil: scroll horizontal. */
.fbar__row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

.fdim, .fdado, .fextra {
  font: inherit; cursor: pointer; border-radius: 999px;
  border: 1.5px solid var(--c-border); background: var(--c-paper); color: var(--c-ink);
}
.fdim {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--tap); padding: 7px 13px; font-size: .88rem; white-space: nowrap;
}
.fdim:hover { border-color: var(--c-primary); }
.fdim:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }
.fdim.open { border-color: var(--c-primary-dark); box-shadow: 0 0 0 2px rgba(45, 212, 191, .35); }
.fdim.has { border-color: var(--c-primary-dark); background: #CCFBF1; font-weight: 700; }
/* El badge, alineado ópticamente con el texto (no con la caja). */
.fdim__n {
  background: var(--c-primary-dark); color: #fff; font-weight: 700; font-size: .72rem;
  border-radius: 999px; padding: 1px 7px; line-height: 1.5;
  position: relative; top: -1px;
}
.fdado { flex: 0 0 auto; width: var(--tap); height: var(--tap); font-size: 1.1rem; }
.fdado:hover { border-color: var(--c-accent); }
.fdado:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }

/* El contador: pieza FIJA de la cabecera, fuera de la fila que envuelve.
   Texto completo, «87 pelis», nunca «87 p» (§3.1). */
.fcount { flex: 0 0 auto; margin: 0; font-weight: 800; font-size: .95rem; white-space: nowrap; }
.fcount b { color: var(--c-primary-dark); font-size: 1.2rem; font-variant-numeric: tabular-nums; }

/* --- Chips activos: su propia línea, con fondo sutil DENTRO de la tarjeta --- */
.factivos {
  display: flex; flex-wrap: wrap; gap: 7px; align-items: center;
  margin: 12px 0 0; padding: 8px 10px;
  background: rgba(45, 212, 191, .08); border-radius: 12px;
}
.factivos:empty { display: none; }

/* --- Móvil: la alternativa que autoriza §3.1 ------------------------------
   Por debajo de 600 px las nueve píldoras envuelven en cuatro filas y la mesa
   de mandos se comería media pantalla antes de la primera película. Así que
   ahí la fila pasa a scroll horizontal con `scroll-snap` y degradados en los
   bordes que avisan de que hay más.

   NI UN `overflow: hidden`: aquí no se corta nada, se desliza. Y las dos
   piezas que la spec exige fuera del scroll ya lo están por estructura: el
   CONTADOR vive en la cabecera y «Limpiar todo», en la línea de chips activos.

   Los degradados son el truco clásico de sombras de scroll: las dos capas
   `local` viajan con el contenido y tapan la sombra cuando ya no hay más que
   ver, y las dos `scroll` se quedan quietas en los bordes. Sin una línea de
   JS y sin un nodo de más. */
@media (max-width: 599px) {
  .fbar { padding: 12px; border-radius: var(--radius); }
  .fbar__row {
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    /* Aire vertical para que el foco (outline de 3 px con 2 de separación) y
       el halo del panel abierto quepan dentro del contenedor de scroll. */
    padding: 5px 0;
    background:
      linear-gradient(90deg, #FFFBF4 45%, rgba(255, 251, 244, 0)) left center / 30px 100% no-repeat local,
      linear-gradient(90deg, rgba(255, 251, 244, 0), #FFFBF4 55%) right center / 30px 100% no-repeat local,
      radial-gradient(farthest-side at 0 50%, rgba(55, 65, 81, .20), rgba(55, 65, 81, 0)) left center / 14px 100% no-repeat scroll,
      radial-gradient(farthest-side at 100% 50%, rgba(55, 65, 81, .20), rgba(55, 65, 81, 0)) right center / 14px 100% no-repeat scroll;
  }
  .fbar__row::-webkit-scrollbar { display: none; }
  .fbar__row > * { flex: 0 0 auto; scroll-snap-align: start; }
}
.fachip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--c-primary-dark); color: #fff;
  border-radius: 999px; padding: 5px 6px 5px 12px; font-size: .85rem; font-weight: 600;
}
.fachip button {
  position: relative;
  border: 0; cursor: pointer; font: inherit; font-size: .7rem; font-weight: 700; line-height: 1;
  width: 22px; height: 22px; border-radius: 999px;
  background: rgba(0, 0, 0, .22); color: #fff;
}
/* La ✕ se ve pequeña (es una píldora), pero el dedo tiene sus 44 px: el área
   se estira con un pseudoelemento invisible, sin mover nada de sitio (§2.10). */
.fachip button::after { content: ""; position: absolute; inset: -11px; }
.fachip button:hover { background: rgba(0, 0, 0, .4); }
/* 🔮 El chip de `menos=<slug>` (§9.4): no es una vibra elegida, es una peli
   apartada — va en el rosa de marca para que se lea como otra cosa. */
.fachip--menos { background: var(--c-accent); font-family: Roboto, var(--emoji), sans-serif; }
.flimpiar {
  border: 0; background: none; cursor: pointer; font: inherit;
  font-size: .85rem; font-weight: 700; color: var(--c-accent);
  text-decoration: underline; padding: 6px 8px; min-height: var(--tap);
}

/* --- El toggle del resultado, DENTRO de la barra (§3.1) --------------------
   ⏱️ Menos de 2 h FILTRA, y aplica al tocarlo: aquí tampoco hay botón
   «Aplicar». Mismo aire que las dimensiones para que la fila se lea como una
   sola familia de mandos.
   AJUSTES-INTERFAZ §4 · Eran dos: al lado iba «🎬 Sí o Sí primero», que
   ORDENABA. Se ha retirado —el motor ya pone las Peli Sí o Sí delante solo—, y
   con su hueco la fila cabe en una línea. La regla .fextra--orden se va con él.
   (La fila .fextras de debajo de la barra desapareció con §2.3, y con ella el
   globito de una sola vez: la tira 📺 de arriba dice lo mismo, siempre.) */
.fextra {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--tap); padding: 7px 13px;
  border: 1.5px solid var(--c-border); border-radius: 999px;
  background: var(--c-paper); color: var(--c-ink);
  font: inherit; font-size: .88rem; white-space: nowrap; cursor: pointer;
}
.fextra:hover { border-color: var(--c-primary); }
.fextra:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }
/* Encendido: el mismo teal de «esto está actuando» de los botones con selección. */
.fextra.on { border-color: var(--c-primary-dark); background: #CCFBF1; font-weight: 700; }

/* --- ADN-EN-LA-WEB §3.1 · EL INTERRUPTOR Alfonso/Acomodador ----------------
   Fila propia dentro de la barra, entre los mandos y los chips activos: la
   fila de mandos tiene que caber en UNA línea con sus ocho piezas (§4) y una
   novena la rompería.

   Dos botones pegados, con forma de segmentado, para que se lea como UNA cosa
   con dos posiciones y no como dos filtros sueltos. La posición puesta lleva
   el mismo teal de «esto está actuando» que el resto de la barra: ni un color
   nuevo. En móvil los dos botones ocupan la mitad cada uno y el texto se
   ajusta, porque «También las del Acomodador 🔦» no cabe en una línea corta. */
.funiverso {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin: 10px 0 0;
}
.funi {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); padding: 7px 14px;
  border: 1.5px solid var(--c-border); border-radius: 999px;
  background: var(--c-paper); color: var(--c-ink-soft);
  font: inherit; font-size: .85rem; line-height: 1.25; cursor: pointer;
  font-family: Roboto, var(--emoji), sans-serif;
}
.funi:hover { border-color: var(--c-primary); }
.funi:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }
.funi.on {
  border-color: var(--c-primary-dark); background: #CCFBF1;
  color: var(--c-ink); font-weight: 700;
}
/* La aclaración de §3.1 («las fichas vacías no entran en ninguna de las dos»):
   una marca discreta que solo se lee al posarse encima o con lector de
   pantalla. No compite con los botones. */
.funi__nota {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 999px;
  border: 1px solid var(--c-border);
  color: var(--c-ink-soft); font-size: .7rem; font-weight: 700;
  cursor: help;
}
@media (max-width: 599px) {
  .funi { flex: 1 1 0; min-width: 0; padding: 7px 8px; font-size: .8rem; }
  .funi__nota { flex: 0 0 auto; }
}

/* --- AJUSTES-INTERFAZ §4 · LA BARRA «EXPLORAR», EN UNA LÍNEA ---------------
   Va aquí, al final, y no arriba con el resto de .fbar: las medidas que
   compacta (.fdim y .fextra) se declaran en dos bloques distintos de este
   fichero y una consulta de medios NO añade especificidad, así que puesta
   antes la pisaba la regla de reposo. Detrás de las dos, gana.

   Retirado el toggle 🎬, la fila son OCHO piezas: 🎲 · las seis dimensiones ·
   ⏱️. El hueco que tienen es `min(1100, ventana) − 64` (los 16+16 de
   .container y los 16+16 de .fbar). Medido en el navegador con el catálogo
   real y las etiquetas de config:

     ventana   hueco   sin contadores   con los 6 contadores
     1440 px   1034      953 px           951 px (compactada)
     1080 px    999      953 px           951 px (compactada)
     1060 px    979      953 px           951 px (compactada)
     1024 px    943      809 (compactada) 951 px → envuelve en dos
      900 px    819      953 px           —      → envuelve en dos

   La fila NO lleva `flex-wrap: nowrap`: envolver es la red de seguridad, no el
   plan. Lo que mantiene la línea entera es la COMPACTACIÓN —menos relleno,
   menos hueco, letra un punto menor—, que es el orden exacto que pide §4:
   primero cede el interior de los botones, y solo si aun así no cabe (por
   debajo de 1024, o ahí con muchas dimensiones puestas) la fila envuelve en
   dos, como estaba, sin cortar ni esconder nada. Por debajo de 600 px manda el
   bloque de móvil: scroll horizontal con scroll-snap y degradados.

   El contador («87 pelis») y «Limpiar todo» no entran nunca en esta cuenta:
   viven fuera de la fila —en la cabecera y en la línea de chips activos—, así
   que no los alcanza ni el scroll de móvil ni la compactación.

   Compactar tiene DOS disparadores, porque la fila no crece solo con el ancho
   de la ventana: cada dimensión con selección se lleva su contador
   (`.fdim__n`), que suma unos 29 px. Con las seis puestas la fila pediría
   1134 px de reposo y no cabría ni a 1440. De ahí:

     · por ANCHO, de 960 a 1059 px;
     · por CONTENIDO, en cuanto hay DOS dimensiones con selección — que es lo
       que dice `:has(.fdim.has ~ .fdim.has)`: existen dos botones encendidos,
       uno detrás de otro. Compactada, la fila con los seis contadores pide
       951 px y sigue entrando en una línea a 1080 y a 1440. */
@media (min-width: 960px) and (max-width: 1059px) {
  .fbar__row { gap: 6px; }
  .fdim, .fextra { padding: 7px 8px; gap: 4px; font-size: .82rem; }
  .fdim__n { padding: 1px 5px; font-size: .7rem; }
  .fdado { width: 38px; font-size: 1rem; }
}
@media (min-width: 960px) {
  .fbar__row:has(.fdim.has ~ .fdim.has) { gap: 6px; }
  .fbar__row:has(.fdim.has ~ .fdim.has) .fdim,
  .fbar__row:has(.fdim.has ~ .fdim.has) .fextra { padding: 7px 8px; gap: 4px; font-size: .82rem; }
  .fbar__row:has(.fdim.has ~ .fdim.has) .fdim__n { padding: 1px 5px; font-size: .7rem; }
  .fbar__row:has(.fdim.has ~ .fdim.has) .fdado { width: 38px; font-size: 1rem; }
}

/* --- §1.3 · Los separadores de sección de la lista unificada ---------------
   Nodos de la propia parrilla (ocupan la fila entera), con contador vivo.
   Visualmente ligeros: una línea con degradado y la etiqueta, no un cartelón.
   En móvil NO son sticky: ocupan poco y estorbarían. */
.fsec {
  grid-column: 1 / -1;
  display: flex; align-items: baseline; gap: 8px;
  margin: 8px 0 0; padding-bottom: 6px;
  border-bottom: 2px solid transparent;
  border-image: linear-gradient(90deg, var(--c-primary), rgba(45, 212, 191, 0)) 1;
  font-size: 1rem; color: var(--c-primary-dark);
  animation: fsec-entra .18s ease-out;
}
.fsec:first-child { margin-top: 0; }
/* «Casi casi» y «Fuera de tus plataformas» pesan menos que las que encajan. */
.fsec--casi, .fsec--honesto {
  color: var(--c-ink-soft);
  border-image: linear-gradient(90deg, var(--c-border), rgba(229, 231, 235, 0)) 1;
}
.fsec--fuera {
  color: var(--c-ink-soft);
  border-image: linear-gradient(90deg, var(--c-rose), rgba(184, 133, 133, 0)) 1;
}
/* Una sección a cero se sigue enseñando (dice por qué no hay nada ahí), pero
   sin robarle presencia a la que sí tiene películas. */
.fsec--vacia { opacity: .6; }
.fsec__t { font-family: Roboto, var(--emoji), sans-serif; font-weight: 700; }
.fsec--honesto .fsec__t { font-weight: 600; font-style: italic; }
.fsec__n { font-size: .82rem; font-weight: 700; color: var(--c-ink-soft); font-variant-numeric: tabular-nums; }
@keyframes fsec-entra { from { opacity: 0; } to { opacity: 1; } }

/* La mini-etiqueta de las exactas que cayeron a «Fuera de tus plataformas»:
   la información no se pierde al bajar de sección (§1.1). */
.mini-exacta {
  font-size: .72rem; font-weight: 700; color: var(--c-primary-dark);
  font-family: Roboto, var(--emoji), sans-serif;
}

/* --- AJUSTES-INTERFAZ §1 · Tandas y plegado -------------------------------
   Dos controles que ocupan la fila entera de la parrilla, como los
   separadores: el botón de tanda («Ver 22 más») y el enlace discreto que abre
   «Se acercan» («Ver 15 que se acercan ›»). Ninguno pide nada al servidor:
   las 87 tarjetas ya están en el DOM y esto solo cambia visibilidad. */
.fmas {
  grid-column: 1 / -1;
  justify-self: center;
  min-height: var(--tap);
  margin: 4px 0 2px; padding: 10px 22px;
  border: 1px solid var(--c-border); border-radius: 999px;
  background: var(--c-paper); color: var(--c-primary-dark);
  font: inherit; font-weight: 700; font-family: Roboto, var(--emoji), sans-serif;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.fmas:hover, .fmas:focus-visible { background: var(--c-tint); border-color: var(--c-primary); }

/* El enlace de plegado pesa MENOS que un botón: es una salida discreta, no
   una llamada a la acción. Va delante del separador que destapa. */
.fplegado {
  grid-column: 1 / -1;
  justify-self: start;
  min-height: var(--tap);
  margin: 8px 0 0; padding: 6px 2px;
  border: 0; background: none; cursor: pointer;
  font: inherit; font-size: .9rem; color: var(--c-ink-soft);
  font-family: Roboto, var(--emoji), sans-serif;
  text-align: left;
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--c-border);
  transition: color .15s ease;
}
.fplegado:hover, .fplegado:focus-visible { color: var(--c-primary-dark); text-decoration-color: var(--c-primary); }

/* El separador al que se le da el foco tras abrir la sección no debe pintar
   un contorno de «campo editable»: basta con el que ya pone :focus-visible. */
.fsec:focus { outline: none; }
.peli-card:focus { outline: none; }

@media (prefers-reduced-motion: reduce) {
  .fmas, .fplegado { transition: none; }
}

/* --- Panel de dimensión: popover en escritorio --- */
.fvelo { position: fixed; inset: 0; z-index: 45; background: rgba(38, 50, 65, .35); }
.fpanel {
  position: absolute; z-index: 50;
  background: var(--c-paper); border: 1px solid var(--c-border); border-radius: 16px;
  box-shadow: 0 8px 28px rgba(55, 65, 81, .22);
  padding: 14px; max-width: 640px; min-width: 290px;
}
.fpanel:focus { outline: none; }
.fpanel__cab { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.fpanel__t { margin: 0; font-size: 1rem; color: var(--c-primary-dark); }
.fpanel__x {
  position: relative;
  border: 0; background: none; cursor: pointer; font: inherit;
  width: 34px; height: 34px; border-radius: 999px; color: var(--c-ink-soft);
}
/* Mismo truco que la ✕ de los chips activos: círculo de 34, dedo de 44. */
.fpanel__x::after { content: ""; position: absolute; inset: -5px; }
.fpanel__x:hover { background: #F3F4F6; }
.fpanel__pq { margin: 2px 0 10px; font-size: .8rem; color: var(--c-ink-soft); }
.fchips { display: flex; flex-wrap: wrap; gap: 7px; }

.fchip {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--tap); padding: 8px 13px;
  border: 1.5px solid var(--c-border); border-radius: 999px;
  background: #F3F4F6; color: var(--c-ink); font: inherit; font-size: .88rem; cursor: pointer;
}
.fchip:hover { border-color: var(--c-primary); }
.fchip:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }
.fchip.on { background: var(--c-primary-dark); border-color: var(--c-primary-dark); color: #fff; font-weight: 700; }
/* Atenuado: además del color va `disabled` de verdad (§2.10). */
.fchip.off, .fchip[disabled] { opacity: .4; cursor: not-allowed; }
.fchip__n { font-size: .72rem; color: var(--c-ink-soft); font-variant-numeric: tabular-nums; }
.fchip.on .fchip__n { color: #CCFBF1; }

.ffam-bloque { width: 100%; }
.ffam {
  display: flex; align-items: center; gap: 8px; width: 100%;
  border: 0; background: none; cursor: pointer; font: inherit;
  margin: 10px 0 6px; padding: 4px 2px; min-height: 34px;
  font-size: .75rem; letter-spacing: .08em; text-transform: uppercase;
  font-weight: 600; color: var(--c-ink-soft); text-align: left;
}
.ffam-bloque:first-of-type .ffam { margin-top: 0; }
.ffam:hover { color: var(--c-primary-dark); }
.ffam.on { color: var(--c-primary-dark); }
.ffam:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }

/* --- Panel de 📺 Mis plataformas: mismo patrón que los de dimensión, con la
   lista en columna. Cada fila ENTERA es el objetivo táctil (§9.10). --- */
.fpanel--plat { max-width: 380px; min-width: 300px; }
.fplats { display: flex; flex-direction: column; gap: 2px; max-height: 46vh; overflow-y: auto; }
.fplat-row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  min-height: var(--tap); padding: 5px 8px;
  border: 0; border-radius: 10px; background: none;
  font: inherit; font-size: .9rem; color: var(--c-ink); text-align: left; cursor: pointer;
}
.fplat-row:hover { background: #F3F4F6; }
.fplat-row:focus-visible { outline: 3px solid var(--c-accent); outline-offset: -3px; }
.fplat-row.on { background: #CCFBF1; }
.fplat-box {
  flex: 0 0 auto; width: 20px; height: 20px;
  border: 2px solid var(--c-border); border-radius: 6px; background: var(--c-paper);
}
.fplat-row.on .fplat-box { background: var(--c-primary-dark); border-color: var(--c-primary-dark); }
.fplat-row.on .fplat-box::after {
  content: "✓"; display: block; color: #fff; font-size: .78rem; line-height: 16px; text-align: center;
}
.fplat-logo { flex: 0 0 auto; width: 28px; height: 28px; border-radius: 7px; display: block; }
.fplat-logo--vacio {
  font-family: var(--emoji); font-size: .95rem; line-height: 28px; text-align: center;
  background: #F3F4F6; color: var(--c-ink-soft);
}
.fplat-n { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fplat-c { flex: 0 0 auto; font-size: .75rem; color: var(--c-ink-soft); font-variant-numeric: tabular-nums; }
/* §7 · La raya fina entre las destacadas y el resto alfabético. Un pelo de
   línea y aire a los lados: se ve que hay dos bloques sin gritar «título». */
.fplats__sep {
  flex: 0 0 auto; height: 1px; margin: 7px 8px;
  background: var(--c-border); border-radius: 1px;
}
.fpanel__pie {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 10px; padding-top: 6px; border-top: 1px solid var(--c-border);
  font-size: .78rem; color: var(--c-ink-soft);
}
.fpanel__pie .flimpiar { font-size: .78rem; padding: 6px 2px; }

/* --- Panel en móvil: bottom sheet a media pantalla --- */
@media (max-width: 599px) {
  .fpanel {
    position: fixed !important;
    top: auto !important; left: 0 !important; right: 0; bottom: 0;
    max-width: none; min-width: 0; max-height: 60vh; overflow-y: auto;
    border-radius: 18px 18px 0 0; padding: 14px 14px 24px;
    box-shadow: 0 -8px 30px rgba(55, 65, 81, .3);
    animation: fsube .18s ease-out;
  }
  @keyframes fsube { from { transform: translateY(100%); } to { transform: translateY(0); } }
  .fcount b { font-size: 1.1rem; }
  /* El de plataformas también es bottom sheet: su ancho propio no manda aquí
     (tiene más especificidad que .fpanel, así que hay que repetirlo). */
  .fpanel--plat { max-width: none; min-width: 0; }
  .fplats { max-height: 42vh; }
}

/* --- Cero resultados --- */
.fvacio { text-align: center; padding: 44px 16px; }
.fvacio h2 { font-size: 1.3rem; margin: 0 0 6px; }
.fvacio p { color: var(--c-ink-soft); margin: 0 0 14px; }
.fvacio__botones { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }

.catalogo__pie { color: var(--c-ink-soft); font-size: .8rem; margin: 26px 0 0; }

/* --- Añadidos de la tarjeta: vibra principal, coincidencias y encaje --- */
.peli-card__aviso { font-family: var(--emoji); font-size: .9rem; }
/* 🧬 ADN-EN-LA-WEB §1.2 · La marca de «tiene ADN» en la tarjeta: junto al 📵 y
   NADA MÁS —la tarjeta ya va cargada—. Discreta de verdad: mismo tamaño que el
   📵 y medio apagada, para que no compita con la Vibra ni con la afinidad. */
.peli-card__adn { font-family: var(--emoji); font-size: .9rem; opacity: .75; }
/* §8 · La Vibra titular como CINTA protagonista, no como línea de texto.
   Bloque a lo ancho de la tarjeta bajo el título, degradado suave del teal de
   marca, esquinas redondeadas; dentro, el kicker VIBRA en versalitas con
   tracking abierto y, debajo, el emoji grande (1.4em) con el nombre en
   semibold. Es el mismo lenguaje visual que la caja VIBRA de la ficha
   (.ficha__vibra-et + .ficha__vibra b), que ya funcionaba bien.
   La regla vieja .peli-card__vibra («Vibra: 🧙‍♂️ Friki» en plano) se retira:
   ningún template la usa ya. */
.peli-card__cinta {
  display: flex; flex-direction: column; gap: 1px;
  margin: 0 10px 8px; padding: 6px 10px 7px;
  border-radius: 10px;
  background: linear-gradient(135deg, #CCFBF1 0%, #F0FDFA 70%, var(--c-paper) 100%);
  box-shadow: inset 0 0 0 1px rgba(45, 212, 191, .35);
  text-align: center;
}
.peli-card__cinta-k {
  font-size: .62rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--c-primary-dark); opacity: .85; line-height: 1.4;
}
.peli-card__cinta-v {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  font-size: .92rem; font-weight: 600; line-height: 1.25;
  color: var(--c-primary-dark);
  font-family: Roboto, var(--emoji), sans-serif;
}
.peli-card__cinta-e { font-size: 1.4em; font-family: var(--emoji); line-height: 1; flex: 0 0 auto; }
/* §2 · La Vibra titular ocupa UNA línea. Un nombre largo se recorta con puntos
   suspensivos; el lector de pantalla sigue leyéndolo entero, y la ficha de la
   película lo lleva completo. */
.peli-card__cinta-n { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* En las 🎬 Peli Sí o Sí la cinta se viste de rosa, a juego con el aura de §3:
   la tarjeta entera habla el mismo idioma sin necesidad de banners. */
.peli-card__cinta--siosi {
  background: linear-gradient(135deg, #FCE7F3 0%, #FDF2F8 70%, var(--c-paper) 100%);
  box-shadow: inset 0 0 0 1px rgba(236, 72, 153, .32);
}
.peli-card__cinta--siosi .peli-card__cinta-k,
.peli-card__cinta--siosi .peli-card__cinta-v { color: #BE185D; }
/* §Fase 5 · Cinta sin titular: hasta tres vibras de identidad en fila, del
   mismo tamaño, sin jerarquía. El mismo hueco de la cinta normal; si no
   caben, la fila se recorta con puntos suspensivos, nunca crece. */
.peli-card__cinta--fila .peli-card__cinta-v { gap: .55em; }
.peli-card__cinta-i { white-space: nowrap; }
.peli-card__cinta-i + .peli-card__cinta-i { overflow: hidden; text-overflow: ellipsis; }
/* §2 · Zona de chips: DOS LÍNEAS como mucho, ni una más.
   La cuenta sale exacta y no depende del largo de los nombres:
     · cada chip mide como mucho la MITAD del ancho útil (`50% - 2px`, que con
       el hueco de 4 px suma justo el 100 %), así que caben DOS por línea y
       nunca tres — un nombre largo se recorta con puntos suspensivos;
     · el recorte de config (`secciones.chips_max`) deja como mucho CUATRO
       piezas, contando el «+3» como una de ellas, así que 4 piezas = 2 líneas
       llenas y jamás una tercera.
   El `max-height` es el cinturón de seguridad y el `min-height` reserva la
   primera línea siempre, para que las tarjetas de una fila no se descuadren.
   20 px de chip + 4 de hueco + 20 = 44. */
.peli-card__match {
  display: flex; flex-wrap: wrap; gap: 4px; justify-content: center;
  padding: 0 8px 6px;
  min-height: calc(20px + 6px); max-height: calc(44px + 6px);
  overflow: hidden;
}
.mchip {
  order: 1;
  display: inline-flex; align-items: center; gap: 4px;
  height: 20px;
  max-width: 100%;
  background: #F3F4F6; border-radius: 999px; padding: 0 8px;
  font-size: .72rem; line-height: 1; color: var(--c-ink-soft);
  font-family: Roboto, var(--emoji), sans-serif;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.peli-card__match .mchip { flex: 0 1 auto; max-width: calc(50% - 2px); }
/* Las que coinciden con el filtro activo: teal y delante de todas. */
.mchip.coincide { order: 0; background: #CCFBF1; color: var(--c-primary-dark); font-weight: 600; }
/* §2 · «+3»: los chips que no caben en las dos líneas, resumidos. No es un
   chip de vibra (no lleva `data-slug`), va el último y se lee como una cuenta,
   no como una etiqueta más. */
.mmas {
  order: 2;
  flex: 0 0 auto;
  display: inline-flex; align-items: center; height: 20px; padding: 0 6px;
  font-size: .7rem; font-weight: 700; line-height: 1; color: var(--c-ink-soft);
  font-variant-numeric: tabular-nums;
}
/* Aviso de ficha sin criterio de Alfonso: no es rúbrica, va en gris y en
   cursiva para que se lea como una nota al pie, no como un sello. */
.peli-card__auto { margin: 0; padding: 0 8px 6px; text-align: center; }
.mchip--auto { background: transparent; border: 1px dashed var(--c-border); font-style: italic; }
/* ADN-EN-LA-WEB §3 · Los mismos tres estados, en tamaño tarjeta. En el
   catálogo solo se ven ⬜ y 🔦 (una ficha vacía no entra en la parrilla y la ✅
   es el caso normal); en /buscar se ven los tres, que es lo que pide §3.1. */
.mchip.est--vacia { background: transparent; border: 1px dashed var(--c-border); font-style: italic; }
.mchip.est--acomodador {
  background: #CCFBF1; border: 1px dashed var(--c-primary-dark);
  color: var(--c-primary-dark); font-weight: 600; font-style: normal;
}
.mchip.est--alfonso {
  background: transparent; border: 1px solid var(--c-accent);
  color: var(--c-accent); font-weight: 600;
}
/* ============================================================
   AJUSTES-INTERFAZ §2 · LA BARRA DE AFINIDAD
   ------------------------------------------------------------
   Va justo encima del botón de ficha y dice dos cosas a la vez:

     ▓▓▓▓▓▓▓▓░░░  cumple 3 de 4
     le falta: 🧠 Qué te pide          ← al pasar el ratón / con foco

   OJO, son DOS CUENTAS DISTINTAS y las dos son ciertas (§1):
     · el ANCHO es la afinidad PONDERADA (la Vibra pesa 2), que llega en la
       variable `--afinidad` del propio <article>;
     · el TEXTO cuenta DIMENSIONES: «cumple 1 de 2».
   Pides Vibra + Con quién y una peli cumple solo la Vibra → barra al 67 % y
   texto «cumple 1 de 2». Ninguna de las dos se calcula aquí: el servidor las
   deja en los `data-` de la tarjeta y filtros.js las reescribe en cada gesto.

   SIN FILTROS NO HAY BARRA: sin `data-afinidad` no hay nada que cumplir, así
   que el bloque entero desaparece. Es la misma condición que usa el JS para
   borrar los atributos, de modo que las dos puntas no pueden discrepar.
   ============================================================ */
.afin {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 3px 8px;
  /* Con la tarjeta estirada, el hueco sobrante se lo queda esta caja: así la
     barra y el botón se quedan pegados abajo (§2). */
  margin-top: auto;
  padding: 2px 10px 7px;
}
/* Sin filtros no hay barra que pintar. */
.peli-card:not([data-afinidad]) .afin { display: none; }

.afin__barra {
  flex: 1 1 70px; min-width: 44px;
  height: 6px; border-radius: 999px;
  background: rgba(45, 212, 191, .18);
  overflow: hidden;
}
.afin__relleno {
  display: block; height: 100%; border-radius: 999px;
  width: var(--afinidad, 0%);
  background: var(--c-primary-dark);
  transition: width .2s ease, background-color .2s ease;
}
/* Al 100 % la barra se completa y pasa al rosa de marca: un acento más vivo
   para la única respuesta que no tiene peros. */
.peli-card[data-afinidad="100"] .afin__relleno { background: var(--c-accent); }

.encaja-nota {
  flex: 0 0 auto;
  font-size: .7rem; color: var(--c-ink-soft);
  font-family: Roboto, var(--emoji), sans-serif;
  font-variant-numeric: tabular-nums;
}
.encaja-nota .enc { font-variant-numeric: tabular-nums; }
/* El ✓ de «encaja del todo» lo pone la presentación, no el texto de config:
   así el rótulo sigue sirviendo igual en cualquier otro sitio. */
.peli-card[data-afinidad="100"] .encaja-nota .enc {
  color: var(--c-accent); font-weight: 700;
}
.peli-card[data-afinidad="100"] .encaja-nota .enc::before { content: "✓ "; }

/* «le falta: 🧠 Qué te pide». Ocupa su propia línea y el hueco está SIEMPRE
   reservado (una línea de .68rem), así que descubrirla no mueve ni un píxel de
   la parrilla. En escritorio aparece al pasar el ratón o al llevar el foco
   dentro de la tarjeta; en móvil (más abajo) vive siempre a la vista. */
.afin .falta {
  flex: 0 0 100%;
  min-height: 1.25em;
  font-size: .68rem; line-height: 1.25; color: var(--c-accent);
  font-family: Roboto, var(--emoji), sans-serif;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  opacity: 0;
  transition: opacity .15s ease;
}
.peli-card:hover .afin .falta,
.peli-card:focus-within .afin .falta { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .afin__relleno, .afin .falta { transition: none; }
}

@media (max-width: 599px) {
  /* En móvil no hay ratón que pasar por encima: la línea va bajo la barra, en
     pequeño y siempre visible (§2). */
  .afin .falta { opacity: 1; }
}

/* --- 🎲 Sorpréndeme: borde fucsia animado sobre la elegida --- */
.peli-card.destacada { outline: 3px solid var(--c-accent); outline-offset: 2px; animation: fpop .5s; }
@keyframes fpop {
  0% { transform: scale(.97); }
  60% { transform: scale(1.02); }
  100% { transform: scale(1); }
}

/* ============================================================
   El wizard «¿Qué te apetece?» (FILTRADO-Y-WIZARD.md §3)
   Overlay crema con la tarjeta en blanco: mismos tokens de la
   casa (teal lo elegible, fucsia lo que empuja). A menos de
   600 px ocupa la pantalla entera.
   ============================================================ */

.wiz { position: fixed; inset: 0; z-index: 80; display: flex; align-items: center; justify-content: center; padding: 16px; }
.wiz__velo { position: absolute; inset: 0; background: rgba(255, 247, 237, .9); backdrop-filter: blur(6px); }
.wiz__caja {
  position: relative; width: 100%; max-width: 620px; max-height: calc(100vh - 32px);
  overflow-y: auto; padding: 26px 24px 20px;
  background: var(--c-paper); border: 1px solid var(--c-border); border-radius: 22px;
  box-shadow: 0 18px 50px rgba(55, 65, 81, .28);
}
.wiz__caja:focus { outline: none; }
html.wiz-abierto { overflow: hidden; }

/* Progreso: tres puntos, encendidos hasta el paso actual incluido. */
.wiz__pasos { display: flex; gap: 6px; margin-bottom: 12px; }
.wiz__punto { width: 26px; height: 4px; border-radius: 999px; background: var(--c-border); }
.wiz__punto.on { background: var(--c-primary); }

.wiz__cuenta {
  margin: 0 0 2px; font-size: .72rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--c-ink-soft);
}
.wiz__q { margin: 0 0 4px; font-size: 1.45rem; font-weight: 800; color: var(--c-primary-dark); line-height: 1.2; }
.wiz__matiz { margin: 0 0 16px; font-size: .9rem; color: var(--c-ink-soft); }

.wiz__ops { display: grid; grid-template-columns: repeat(auto-fit, minmax(165px, 1fr)); gap: 10px; }
.wiz__op {
  display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  min-height: 88px; padding: 13px 14px; cursor: pointer; text-align: left;
  font: inherit; color: var(--c-ink);
  background: var(--c-paper); border: 1.5px solid var(--c-border); border-radius: 14px;
}
.wiz__op:hover { border-color: var(--c-primary); background: #F0FDFA; }
.wiz__op:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }
.wiz__op-e { font-size: 1.5rem; font-family: var(--emoji); line-height: 1.2; }
.wiz__op-n { font-size: .98rem; font-weight: 700; line-height: 1.25; font-family: Roboto, var(--emoji), sans-serif; }
.wiz__op-m { font-size: .8rem; color: var(--c-ink-soft); line-height: 1.3; }
/* El comodín: punteado y siempre el último. */
.wiz__op--abierto { border-style: dashed; background: transparent; grid-column: 1 / -1; }
.wiz__op--abierto:hover { background: transparent; border-color: var(--c-primary); }

/* §6.3 · El paso 4, «Afina el tiro». Dos diferencias con los demás pasos:
   «✨ Así está bien» va primero, a lo ancho y con cuerpo de botón principal
   (es la salida por defecto: no añade nada y termina), y cada vibra lleva su
   cuenta REAL pegada al nombre, en teal y con cifras tabulares para que la
   columna de números no baile. */
.wiz__ops--afina .wiz__op { min-height: 76px; }
.wiz__op--afina-ok {
  grid-column: 1 / -1;
  align-items: center; text-align: center; min-height: var(--tap);
  border-color: var(--c-primary); background: #F0FDFA;
}
.wiz__op--afina-ok .wiz__op-n { font-size: 1.05rem; color: var(--c-primary-dark); }
.wiz__op--afina-ok:hover { background: #CCFBF1; }
.wiz__op-c {
  color: var(--c-primary-dark); font-weight: 700; font-size: .88rem;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* §4 · El puente al recorrido fino: discreto, bajo las opciones y solo en el
   último paso. No compite con las opciones; es la puerta de al lado. */
.wiz__puente {
  display: block; margin: 14px 0 0; padding: 12px 4px; min-height: var(--tap);
  font-size: .85rem; color: var(--c-ink-soft); text-align: center;
  text-decoration: underline; font-family: Roboto, var(--emoji), sans-serif;
}
.wiz__puente:hover { color: var(--c-accent); }
.wiz__puente:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }

.wiz__nav { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 18px; }
.wiz__atras, .wiz__cerrar {
  min-height: var(--tap); padding: 8px 16px; cursor: pointer; font: inherit; font-size: .9rem;
  background: none; border: 1.5px solid var(--c-border); border-radius: 999px; color: var(--c-ink-soft);
}
.wiz__atras:hover, .wiz__cerrar:hover { border-color: var(--c-primary); color: var(--c-primary-dark); }
.wiz__atras:focus-visible, .wiz__cerrar:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }

@media (max-width: 599px) {
  .wiz { padding: 0; align-items: stretch; }
  .wiz__caja {
    max-width: none; max-height: none; height: 100%; border: 0; border-radius: 0;
    padding: 20px 16px 24px;
  }
  .wiz__q { font-size: 1.25rem; }
  .wiz__ops { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
}

/* ============================================================
   Ficha: la vibra y la sesión en la cabecera.
   ------------------------------------------------------------
   La caja de la rúbrica (.ficha__vibras, .vtag, .vdim) se retiró
   con la maqueta definitiva: la vibra titular pasó a ser una
   línea suelta (.vibra-linea) y las cinco dimensiones una lista
   sin recuadro (.dims), las dos declaradas arriba, en el bloque
   de la cabecera. El aura de las 🎬 Peli Sí o Sí se mudó al
   cartel (.ficha--siosi .cartel). Aquí solo queda el 📵.
   ============================================================ */

.ficha__aviso {
  font-size: .78rem; font-weight: 700; color: var(--c-accent); white-space: nowrap;
  font-family: Roboto, var(--emoji), sans-serif; vertical-align: middle;
}

/* ============================================================
   §9.2 · El bloque de relaciones, junto: 🔮 vibras parecidas,
   misma vibración, ADN, ingrediente de y más del director. Es
   un contenedor sin estilo propio (sus hijas siguen siendo
   `.ficha section` de toda la vida): lo único que hace es
   mantenerlas pegadas en el orden que pide la spec.
   ============================================================ */
.ficha__relaciones { display: contents; }

/* §9.4 · El botón que salta al catálogo con las vibras de identidad de esta
   película y `menos=<slug>` para no recomendarte la que ya estás mirando. Es
   un enlace normal a una URL normal: nada de scroll forzado, para que el
   «atrás» del navegador caiga donde estaba (§10.7). */
.parecidas {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
}
.btn-parecidas {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); padding: 10px 18px;
  background: var(--c-accent); color: #fff;
  border-radius: 999px; text-decoration: none;
  font-size: .95rem; font-weight: 700;
  font-family: Roboto, var(--emoji), sans-serif;
}
.btn-parecidas:hover { background: #D92D86; }
.btn-parecidas:focus-visible { outline: 3px solid var(--c-primary-dark); outline-offset: 2px; }

/* ============================================================
   LA BARRA DE MODO · 📄 Ficha / 📰 Revista / 🖍️ / ↗
   ------------------------------------------------------------
   Traslado de plantillas-ficha/generar.py · barra_modo().

   UNA DIFERENCIA CON LA MAQUETA, a propósito: allí la barra es
   `position:fixed` porque la maqueta era una página suelta. Aquí
   hay una cabecera de sitio encima, y una barra fija la taparía
   en cuanto cargas. Con `sticky` se queda donde le toca —debajo
   de la cabecera— y sigue haciendo lo suyo: en cuanto pasas de
   90 px (`data-esconde`) se va, porque a partir de ahí lo que
   quieres es leer la ficha, no cambiar de modo.
   ============================================================ */
.modo-barra {
  position: sticky; top: 0; z-index: 40;
  /* Rompe el padding de .container para tocar los dos bordes. */
  margin: -16px -16px 12px;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 7px 12px;
  background: rgba(255, 255, 255, .96);
  border-bottom: 1.5px solid var(--c-primary);
  box-shadow: 0 2px 12px rgba(0, 0, 0, .08);
  transition: transform .25s ease, opacity .25s ease;
}
.modo-barra.oculta { transform: translateY(-110%); opacity: 0; pointer-events: none; }

.modo-grupo {
  display: flex; border: 1.5px solid var(--c-primary-dark);
  border-radius: 999px; overflow: hidden;
}
.modo-grupo > * {
  display: inline-flex; align-items: center; min-height: var(--tap);
  padding: 9px 16px; font-size: .85rem; font-weight: 700;
  color: var(--c-primary-dark); text-decoration: none;
  font-family: Roboto, var(--emoji), sans-serif;
}
.modo-grupo .on { background: var(--c-primary-dark); color: #fff; }
/* 📰 Revista todavía sin ruta: se ve, pero no se toca. Mejor apagada que un
   enlace a un 404. Se enciende sola cuando exista PublicController::revista(). */
.modo-grupo .apagada { color: var(--c-ink-soft); opacity: .55; cursor: default; }

.modo-sub {
  min-height: var(--tap); padding: 9px 13px;
  background: var(--c-bg); border: 1.5px solid var(--c-primary); border-radius: 999px;
  font: inherit; font-size: .85rem; font-weight: 700;
  color: var(--c-primary-dark); cursor: pointer;
  font-family: Roboto, var(--emoji), sans-serif;
}
body.subrayado .modo-sub { background: var(--c-primary-dark); color: #fff; border-color: var(--c-primary-dark); }
.modo-sub:focus-visible { outline: 3px solid var(--c-primary-dark); outline-offset: 2px; }

/* ↗ Compartir. En móvil vive en la barra (a mano del pulgar) y en escritorio
   en la cabecera, junto al veredicto. Es el mismo botón dos veces, no dos
   botones distintos: los dos leen el mismo textarea. */
.btn-comp {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); padding: 9px 16px;
  background: none; border: 1.5px solid var(--c-primary-dark); border-radius: 999px;
  font: inherit; font-size: .88rem; font-weight: 700;
  color: var(--c-primary-dark); cursor: pointer;
  font-family: Roboto, var(--emoji), sans-serif;
}
.btn-comp:hover { background: var(--c-primary-dark); color: #fff; }
.btn-comp:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }
.btn-comp.hecho { background: var(--c-primary-dark); color: #fff; }
.btn-comp--barra { margin-left: auto; }
@media (max-width: 680px) {
  .modo-grupo > * { padding: 9px 12px; font-size: .8rem; }
  .modo-sub { font-size: .78rem; padding: 9px 10px; }
  .btn-comp--barra { padding: 9px 12px; font-size: .82rem; }
  /* En móvil manda el de la barra: dos botones iguales a un dedo de distancia
     serían dos maneras de hacer lo mismo. */
  .btn-comp--cab { display: none; }
}
@media (min-width: 681px) {
  .btn-comp--barra { display: none; }
}

/* ============================================================
   LOS SUBRAYADOS ==así== DE LA OPINIÓN
   ------------------------------------------------------------
   El <mark> viene ya puesto del servidor (App\Core\Text). Aquí
   solo se enciende: sin la clase en el <body> el resaltado no se
   ve, y con ella aparece el trazo teal de rotulador. El
   interruptor 🖍️ vive en la barra de modo y recuerda la
   elección en localStorage (con try/catch, en ficha.js).

   `background:transparent` de partida es importante: es el
   estilo por defecto del navegador (amarillo chillón) el que hay
   que apagar, no el nuestro el que hay que encender.
   ============================================================ */
mark {
  background: transparent; color: inherit;
  border-radius: 3px; padding: 0 2px;
  transition: background .35s ease;
}
body.subrayado mark {
  background: linear-gradient(120deg, rgba(45, 212, 191, .45), rgba(45, 212, 191, .28));
}
@media (prefers-reduced-motion: reduce) {
  mark { transition: none; }
}

/* ============================================================
   🧬 EL ADN Y 👯 LAS HERMANAS, EN FILA
   ------------------------------------------------------------
   Maqueta: `.relaciones{grid-template-columns:3fr 2fr}` — el ADN
   ancho (lleva tres carteles) y las hermanas estrechas (llevan
   una lista). En móvil, columna única.

   Si solo hay una de las dos —hoy 67 películas no tienen ADN y
   56 no tienen hermanas— ocupa el ancho entero (.relaciones--una)
   en vez de dejar media caja y medio hueco.
   ============================================================ */
.relaciones {
  display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  gap: 16px; align-items: start; margin: 18px 0;
}
.relaciones--una { grid-template-columns: minmax(0, 1fr); }
/* Las dos cajas son hermanas de verdad: misma altura, cada una con su color.
   `.ficha section` ya les pone fondo, radio y sombra; aquí solo el borde que
   las distingue —rosa el ADN (MEZCLA), teal las hermanas (SE PARECEN)— y que
   el margen inferior no las descuadre dentro del grid. */
.relaciones > section { margin-bottom: 0; height: 100%; }
.relaciones .adn-block { border: 2px solid var(--c-accent); }
.relaciones .adn-block h2 { color: var(--c-accent); }
.relaciones .hermanas { border: 1.5px solid var(--c-primary); }
.hermanas__entrada { margin: 0 0 10px; color: var(--c-ink-soft); font-size: .88rem; }
/* Dentro de la columna estrecha las hermanas van una debajo de otra: dos
   columnas de 200 px se leerían como fichas recortadas. */
.similar-list--her { grid-template-columns: minmax(0, 1fr); }
.hermana__porque { display: block; color: var(--c-ink-soft); font-size: .8rem; line-height: 1.35; }

/* La receta, DENTRO de la ficha, se pinta como la maqueta: los carteles a lo
   ancho de la caja y el «aporta» debajo de cada uno. En /adn (el mezclador) la
   receta se queda como estaba —fila de tarjetas de 104 px unidas por «+»—,
   porque allí no hay dos columnas que llenar. */
.relaciones .adn-receta {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  justify-content: stretch; gap: 10px;
}
.relaciones .adn-ing { display: block; }
.relaciones .adn-ing__box { width: auto; height: 100%; }
.relaciones .adn-ing__poster { width: 100%; height: auto; aspect-ratio: 2 / 3; }
/* El «+» de la fórmula sobra cuando los ingredientes ya están en rejilla: en
   una columna estrecha se comía el ancho de un cartel. La fórmula la siguen
   diciendo la entrada («se cocina con:») y el cierre («…y de esa mezcla sale»). */
.relaciones .adn-op { display: none; }

/* QUÉ APORTA CADA INGREDIENTE (movie_mix_items.note). Debajo de su cartel, en
   cursiva y en teal: el cartel dice CUÁL, esto dice PARA QUÉ. El ingrediente
   que no la tenga no pinta la línea — ni hueco ni «aporta» a secas. */
.adn-ing__aporta {
  display: block; margin-top: 4px;
  font-size: .74rem; line-height: 1.3; font-style: italic;
  color: var(--c-primary-dark);
}

@media (max-width: 680px) {
  .relaciones { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .relaciones .adn-receta { gap: 8px; }
  .adn-ing__aporta { font-size: .72rem; }
}

/* ============================================================
   🔦 LAS BUTACAS DEL ACOMODADOR · «¿No era tu butaca?»
   ------------------------------------------------------------
   Traslado de _butacas_css(formal=False) de la maqueta: caja de
   borde discontinuo teal, la PISTA arriba, el cartel borroso con
   «¿Adivinas? · toca para verla», el revelado «🎉 ¡Era X!» y el
   botón «Ir a ella →».

   El desenfoque solo existe si el JS está vivo (body.butacas-
   vivas, que pone ficha.js): sin JS nadie se queda mirando dos
   carteles borrosos que no se pueden desvelar — se ven nítidos y
   el enlace está a la vista desde el principio.
   ============================================================ */
.ficha .butacas {
  background: linear-gradient(120deg, rgba(13, 148, 136, .07), rgba(236, 72, 153, .07));
  border: 2px dashed var(--c-primary-dark);
  border-radius: 16px; padding: 20px; margin: 22px 0;
  box-shadow: none;
}
.butacas h2 { margin: 0; color: var(--c-primary-dark); font-size: 1.3rem; font-family: Roboto, var(--emoji), sans-serif; }
.butacas .sub { color: var(--c-ink-soft); margin: 4px 0 16px; font-size: .92rem; }
.butacas .filas { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }

.butaca {
  display: flex; flex-direction: column; text-align: center;
  background: var(--c-paper); border: 1.5px solid var(--c-primary);
  border-radius: 14px; padding: 14px;
}
.butaca .dir { font-weight: 800; color: var(--c-accent); font-size: .85rem; }
/* La pista: el `one_liner` de la peli destino. Solo 24 de 87 lo tienen, así
   que la butaca sin pista NO pinta este párrafo (ni el hueco). El `min-height`
   alinea las dos cuando las dos la tienen, que es el caso que se nota. */
.butaca .pista {
  margin: 10px 0 12px; min-height: 4em;
  font-family: "Roboto Slab", Georgia, "Times New Roman", serif;
  font-style: italic; font-size: .95rem; line-height: 1.45; color: var(--c-ink);
}
.butaca .mist {
  display: block; position: relative; overflow: hidden;
  width: 132px; max-width: 100%; margin: 0 auto;
  min-height: var(--tap); padding: 0;
  background: none; border: none; border-radius: 9px; cursor: pointer;
}
.butaca .mist img { width: 100%; height: auto; aspect-ratio: 2 / 3; object-fit: cover; display: block; }
.butaca .mist--vacio {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 2 / 3; background: var(--c-tint);
  font-family: var(--emoji); font-size: 2rem;
}
.butaca .mist:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 3px; }
/* El desenfoque, solo con JS vivo. SIN `transition` en este estado y CON ella
   en el de abierta, y no al revés: la clase `butacas-vivas` se la pone el JS
   al cargar, así que una transición aquí haría que el cartel entrara nítido y
   se fuera emborronando medio segundo — o sea, enseñando la respuesta en cada
   carga. Entrar borroso es instantáneo; lo que se anima es el revelado, que es
   lo único que el usuario pide ver. */
body.butacas-vivas .butaca .mist img,
body.butacas-vivas .butaca .mist--vacio {
  filter: blur(14px) saturate(1.2); transform: scale(1.15);
}
body.butacas-vivas .butaca.abierta .mist img,
body.butacas-vivas .butaca.abierta .mist--vacio {
  filter: none; transform: none;
  transition: filter .5s ease, transform .5s ease;
}
.butaca .adivinas {
  position: absolute; inset: 0; display: none;
  flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  color: #fff; text-shadow: 0 2px 8px #000;
}
body.butacas-vivas .butaca .adivinas { display: flex; }
body.butacas-vivas .butaca.abierta .adivinas { display: none; }
.butaca .adivinas b { font-size: 1.25rem; }
.butaca .adivinas small { font-size: .68rem; opacity: .9; }
/* El nombre solo existe una vez desvelada: sin JS y sin clic está vacío, y un
   div vacío no ocupa nada (nada de min-height que deje un escalón). */
.butaca .nombre {
  font-weight: 800; color: var(--c-primary-dark); margin-top: 10px;
  font-family: Roboto, var(--emoji), sans-serif;
}
.butaca .nombre:empty { display: none; }
.butaca .fila-n { color: var(--c-ink-soft); font-size: .75rem; margin-top: 6px; }
.butaca .ir {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); margin: 10px auto 0; padding: 12px 26px;
  background: var(--c-accent); color: #fff; text-decoration: none;
  border-radius: 999px; font-weight: 800;
}
.butaca .ir:hover { background: #D92D86; }
.butaca .ir:focus-visible { outline: 3px solid var(--c-primary-dark); outline-offset: 2px; }

@media (max-width: 680px) {
  .ficha .butacas { padding: 16px 14px; }
  .butacas .filas { grid-template-columns: minmax(0, 1fr); }
  /* En una sola columna no hay nada que alinear: fuera el hueco reservado. */
  .butaca .pista { min-height: 0; }
}
@media (prefers-reduced-motion: reduce) {
  body.butacas-vivas .butaca.abierta .mist img,
  body.butacas-vivas .butaca.abierta .mist--vacio { transition: none; }
}

/* ============================================================
   📰 EL MODO REVISTA · /peli/{slug}/revista
   ------------------------------------------------------------
   Traslado de plantillas-ficha/generar.py · revista_def(). La
   misma película en modo lectura: mancheta, apertura con el
   fotograma en duotono, entradilla en serif, artículo a dos
   columnas con capitular y ficha técnica al margen.

   COMPARTE con la ficha todo lo que ya está declarado arriba:
   .modo-barra, .btn-comp, mark / body.subrayado mark, los chips
   de veredicto y estado, .etq y TODO el bloque de .butacas —de
   ahí que aquí abajo solo aparezca `.revista .butacas`, que es
   la variante sobria de la caja (la maqueta ya la tenía prevista
   con `_butacas_css(formal=True)`) y nada más—.

   MÓVIL PRIMERO: en ≤820 px el margen NO es una columna
   estrujada, es un bloque debajo del artículo separado por un
   filete teal. Lo dice la regla del final, no un `float` que se
   rompa.
   ============================================================ */

/* El papel de la revista es un punto más claro que el de la web: es lo que
   separa «estoy leyendo» de «estoy decidiendo». */
.revista {
  --papel-rev: #FFFDF8;
  background: var(--papel-rev);
  /* Rompe el padding de .container para que la apertura llegue a los bordes. */
  margin: 0 -16px;
  padding: 0 16px 24px;
}

/* --- La barra de progreso de lectura. 4 px arriba del todo, y la pinta
   ficha.js. Sin JS se queda a cero: no molesta y no miente. --- */
.progreso {
  position: fixed; top: 0; left: 0; right: 0; height: 4px; z-index: 60;
  background: transparent; pointer-events: none;
}
.progreso i { display: block; height: 100%; width: 0; background: var(--c-accent); }
body.progreso-viva .progreso i { transition: width .1s linear; }
@media (prefers-reduced-motion: reduce) {
  body.progreso-viva .progreso i { transition: none; }
}

/* --- La mancheta: la cabecera del medio. --- */
.mancheta {
  display: flex; flex-wrap: wrap; gap: 4px 16px;
  justify-content: space-between; align-items: baseline;
  padding: 10px 0 6px; margin-bottom: 12px;
  border-bottom: 1px solid var(--c-ink);
  font-size: .78rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--c-ink-soft);
}
.mancheta b { color: var(--c-accent); }
.mancheta__seccion { letter-spacing: .12em; }

/* --- LA APERTURA: el fotograma real en DUOTONO SUAVE.
   La receta clásica: la foto a gris y encima dos pasadas de color —teal en
   `multiply` para las sombras y rosa en `screen` para las luces—. Luego un
   fundido al papel por abajo, para que el titular no se apoye en una foto a
   pelo. Si `mix-blend-mode` no existiera, quedan la foto gris y el fundido:
   se ve bien igual, solo que sin el tinte. --- */
.apertura { position: relative; margin: 0 -16px 14px; }
.apertura__foto { position: relative; overflow: hidden; background: var(--c-ink); }
.apertura__foto img {
  width: 100%; height: 260px; object-fit: cover; display: block;
  filter: grayscale(1) contrast(1.06) brightness(1.02);
}
.apertura__foto::before,
.apertura__foto::after { content: ""; position: absolute; inset: 0; pointer-events: none; }
.apertura__foto::before {
  background: linear-gradient(120deg, #0D9488, #134E4A);
  mix-blend-mode: multiply; opacity: .78;
}
.apertura__foto::after {
  background: linear-gradient(120deg, rgba(236, 72, 153, .55), rgba(255, 247, 237, .75));
  mix-blend-mode: screen; opacity: .62;
}
/* El fundido al papel, fuera del contenedor del blend para que no se tiña. */
.apertura::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to bottom, rgba(255, 253, 248, 0) 55%, var(--papel-rev) 98%);
}
.apertura__pie {
  position: absolute; bottom: 10px; right: 20px; z-index: 1;
  font-size: .7rem; color: #fff; text-shadow: 0 1px 5px rgba(0, 0, 0, .9);
}

/* --- Titular, entradilla y firma --- */
.rev-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0 0 6px; }
.revista h1 {
  margin: .1em 0 .05em; line-height: 1.04;
  font-family: "Roboto Slab", Georgia, "Times New Roman", serif;
  font-size: 2.6rem; color: var(--c-ink);
}
/* LA ENTRADILLA: serif limpio, sin fondos y sin comillas. */
.entradilla {
  margin: .35em 0 .5em;
  font-family: "Roboto Slab", Georgia, "Times New Roman", serif;
  font-size: 1.3rem; line-height: 1.5; color: var(--c-primary-dark);
}
.rev-honesta { margin: 0 0 8px; color: var(--c-ink-soft); font-size: .92rem; }
.firma {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px;
  margin: 0 0 6px; padding-top: 6px;
  border-top: 3px solid var(--c-accent);
}
.firma__t { color: var(--c-ink-soft); font-style: italic; font-size: .92rem; }
.btn-comp--firma { padding: 7px 14px; font-size: .82rem; }

/* --- EL CUERPO: artículo y margen --- */
.cuerpo {
  display: grid; grid-template-columns: minmax(0, 1fr) 280px;
  gap: 34px; align-items: start; margin-top: 18px;
}
.cuerpo--una { grid-template-columns: minmax(0, 1fr); }
.articulo { min-width: 0; }
.articulo p { font-size: 1.05rem; }
/* LA CAPITULAR. Va por clase y no por `:first-of-type`: con 0 párrafos de
   opinión el primer <p> del artículo es una línea del despiece, y la letra
   capital habría caído dentro de la caja. */
.articulo .capitular::first-letter {
  float: left; line-height: .8; padding: 6px 10px 0 0;
  font-family: "Roboto Slab", Georgia, "Times New Roman", serif;
  font-size: 3.3em; font-weight: 700; color: var(--c-accent);
}
.rev-h2 {
  margin: 24px 0 6px; color: var(--c-ink);
  font-family: "Roboto Slab", Georgia, "Times New Roman", serif; font-size: 1.4rem;
}
.rev-creditos { margin: 18px 0 0; font-size: .92rem; color: var(--c-ink-soft); }
.rev-creditos b { color: var(--c-ink); }

/* LA DESTACADA: la Vibra titular, serif rosa, centrada y sin comillas.
   VA ESCRITA `.revista .destacada` y no `.destacada` a secas porque ese nombre
   YA ESTABA COGIDO: 🎲 Sorpréndeme se lo pone a la tarjeta elegida del catálogo
   (`.peli-card.destacada`, arriba) y assets/js/filtros.js se lo quita a los dos
   segundos. Sin el prefijo, esta regla —que va después en el fichero— le caía
   encima a esa tarjeta y la dejaba centrada, en serif y en rosa. */
.revista .destacada {
  margin: 26px 0; text-align: center;
  font-family: "Roboto Slab", Georgia, "Times New Roman", serif;
  font-size: 1.5rem; line-height: 1.35; color: var(--c-accent);
}

/* 🧬 EL DESPIECE DEL ADN: el mismo ADN de la ficha, aquí como TEXTO y SIN
   IMÁGENES (así se aprobó la maqueta). Caja de recorte de revista. */
.despiece {
  display: block; background: var(--c-bg); border: 2px solid var(--c-accent);
  border-radius: 12px; padding: 16px; margin: 20px 0;
}
.despiece h2 {
  margin: 0 0 4px; color: var(--c-accent);
  font-family: "Roboto Slab", Georgia, "Times New Roman", serif; font-size: 1.25rem;
}
.despiece__entrada { margin: 0; color: var(--c-ink-soft); font-size: .95rem; }
.despiece__linea { margin: 9px 0; font-size: 1.02rem; }
.despiece__linea b { color: var(--c-primary-dark); }
.despiece__linea small { color: var(--c-ink-soft); }
.despiece__linea i { color: var(--c-ink); }
/* Cada ingrediente es un enlace de verdad a su ficha (el grafo de §2.2), así
   que es un objetivo táctil de verdad: 44 px aunque sea una línea de texto. */
.despiece__linea a {
  display: inline-flex; align-items: center; min-height: var(--tap);
  text-decoration: none;
  /* El alto ya llegaba a 44; el ANCHO no, porque lo pone el título: «Mud» o
     «Ran» se quedaban en 43 px o menos. El relleno lateral ensancha la diana y
     el margen negativo lo devuelve a su sitio, así que la línea se sigue
     leyendo igual —el año y el «aporta» no se mueven— y el dedo tiene los
     44 px por los dos lados. */
  padding: 0 9px; margin: 0 -9px;
}
.despiece__linea a:hover b { text-decoration: underline; }
.despiece__linea a:focus-visible { outline: 3px solid var(--c-accent); outline-offset: 2px; }
.despiece__cierre { margin: 10px 0 0; font-style: italic; font-size: .98rem; }

/* --- LA FICHA TÉCNICA AL MARGEN --- */
.margen { min-width: 0; border-left: 3px solid var(--c-primary); padding-left: 18px; }
.margen .etq { display: block; margin: 16px 0 6px; }
.margen > .etq:first-child { margin-top: 0; }
.fichita {
  background: var(--c-paper); border: 1px solid var(--c-primary);
  border-radius: 10px; padding: 14px; margin-bottom: 16px;
}
/* AJUSTES-INTERFAZ §3 · el aura rosa permanente de las 🎬 Peli Sí o Sí. En la
   ficha vive en el cartel; aquí, en la cajita del margen, que es donde vive el
   cartel en modo revista. Mismos halos que allí, ni un color nuevo. Sin hover
   ni transición: esta caja no se toca, se lee. */
.revista--siosi .fichita {
  border-color: rgba(236, 72, 153, .55);
  box-shadow: 0 2px 14px rgba(236, 72, 153, .20),
              0 10px 44px rgba(236, 72, 153, .09);
}
/* El ancho real del cartel del margen —229 px en escritorio: los 280 de la
   columna menos el filete (3), la sangría (18), el borde (1+1) y el relleno
   (14+14)— es el que declara el `sizes` de templates/public/revista.php para
   elegir derivado. Si cambian el relleno de .fichita o la columna de .cuerpo,
   cambia también allí. */
.fichita__cartel { width: 100%; height: auto; aspect-ratio: 2 / 3; object-fit: cover; border-radius: 6px; }
.fichita__vibra { margin: 10px 0 0; font-family: Roboto, var(--emoji), sans-serif; }
.fichita__vibra b { color: var(--c-primary-dark); }
.plat { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; }
.plat img { width: 30px; height: 30px; border-radius: 6px; }

.margen-dim { margin-bottom: 12px; font-family: Roboto, var(--emoji), sans-serif; }
.margen-dim b { color: var(--c-primary-dark); font-size: .88rem; }
.margen-dim small { display: block; color: var(--c-ink-soft); font-size: .82rem; line-height: 1.4; }

.her {
  display: flex; gap: 10px; align-items: center; margin: 0 0 10px;
  min-height: var(--tap); text-decoration: none; color: var(--c-ink);
}
.her:hover b { text-decoration: underline; }
.her:focus-visible { outline: 3px solid var(--c-primary-dark); outline-offset: 2px; }
.her img { width: 46px; height: 69px; object-fit: cover; border-radius: 5px; flex-shrink: 0; }
.her small { font-size: .82rem; line-height: 1.35; }
.her b { color: var(--c-primary-dark); }
.her__porque { display: block; color: var(--c-ink-soft); }

.margen-ing { margin: 0 0 8px; font-size: .88rem; }
.margen-ing a { display: inline-flex; align-items: center; min-height: var(--tap); text-decoration: none; }
.margen-ing a:hover b { text-decoration: underline; }
.margen-ing small { display: block; color: var(--c-ink-soft); font-size: .8rem; }

/* --- 🔦 LAS BUTACAS, VARIANTE SOBRIA DE REVISTA.
   Es `_butacas_css(formal=True)` de la maqueta: borde fino de tinta en vez del
   discontinuo teal, fondo de papel en vez del degradado y el título en serif.
   El marcado, el JS y el cálculo son los MISMOS que en la ficha. --- */
.revista .butacas {
  background: var(--papel-rev); border: 1px solid var(--c-ink);
  border-radius: 16px; padding: 20px; margin: 26px 0 0;
}
.revista .butacas h2 {
  font-family: "Roboto Slab", Georgia, "Times New Roman", serif;
  color: var(--c-ink);
}
/* La rejilla de las dos butacas, el desenfoque, el revelado y el «Ir a ella →»
   los pone el bloque de arriba tal cual: no se repiten aquí. */

/* ------------------------------------------------------------
   MÓVIL: EL MARGEN PASA DEBAJO DEL ARTÍCULO, con su propia regla
   ------------------------------------------------------------ */
@media (max-width: 820px) {
  .cuerpo { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .margen {
    border-left: none; padding-left: 0;
    border-top: 3px solid var(--c-primary); padding-top: 16px;
  }
  .revista h1 { font-size: 1.9rem; }
  .entradilla { font-size: 1.1rem; }
  .revista .destacada { font-size: 1.22rem; margin: 20px 0; }
  .apertura__foto img { height: 190px; }
  .articulo p { font-size: 1.02rem; }
  .rev-h2 { font-size: 1.25rem; }
  /* En una columna la fichita no necesita el cartel a tamaño de póster: al
     lado de sus datos ocupa la mitad y se lee entera de una vez. */
  .fichita { display: grid; grid-template-columns: 40% minmax(0, 1fr); gap: 12px; align-items: start; }
  .fichita__cartel { grid-row: span 3; }
  .fichita__vibra { margin: 0; }
}
@media (max-width: 680px) {
  .revista h1 { font-size: 1.7rem; }
  .despiece { padding: 14px 12px; }
  .despiece__linea { font-size: .98rem; }
  .revista .butacas { padding: 16px 14px; }
  .articulo .capitular::first-letter { font-size: 2.9em; }
}
