/* ============================================================
   Constructivist Poster design system
   Canto vivo · tinta plana · diagonal y trama · sin difuminado

   Cartel constructivista de los anos 20 cruzado con la serie
   serigrafiada pop: negro, crema y bermellon como base, y una tinta
   distinta por libro, como quien reimprime la misma plancha con otro
   color.

   REGLA DE ALCANCE: el cartel manda en el cromo (portada, catalogo,
   navegacion, botones). Dentro del capitulo manda la legibilidad: papel
   limpio, medida acotada y el estilo solo en los titulos. Un cartel a
   todo volumen debajo de 192 capitulos cansa la vista.
   ============================================================ */

:root {
  /* --- Papel y tinta ---------------------------------------------------
     Ratios MEDIDOS contra --paper #F2EFE4, no estimados. El sistema
     anterior documentaba sus ratios contra un color que la hoja no
     llegaba a pintar; aqui cada numero sale de calcularlo contra el
     crema real de arriba.
       --ink       16.40  AA texto
       --muted      7.70  AA texto
       --blue       5.99  AA texto  (bermellon oscuro: enlaces y CTA)
       --vermillion 3.50  AA solo en titular grande / bloque de color
       --red        8.41  AA texto  (peligro)
       --orange     5.24  AA texto
       --warn       1.61  SOLO relleno (amarillo de aviso, nunca texto) */
  --paper: #F2EFE4;        /* crema de imprenta */
  --paper-2: #E8E3D4;      /* crema en sombra */
  --ink: #111111;          /* tinta negra */
  --muted: #4A4A4A;        /* tinta gris */

  /* Bermellon: el color de marca. Va en DOS valores a proposito, porque
     un solo rojo no puede hacer los dos trabajos. El saturado tiene la
     fuerza del cartel pero se queda en 3.50 sobre crema, asi que solo
     vale para bloques y titulares grandes; el oscuro es el que se puede
     leer en cuerpo pequeno. */
  --vermillion: #E8402F;   /* relleno y display grande */
  --vermillion-ink: #B3170F; /* el mismo rojo, legible en pequeno */

  /* PELIGRO. Antes esta era la marca; ahora la marca es roja, asi que el
     peligro necesitaba separarse o quedaba indistinguible de un boton
     normal. Se oscurece, y ADEMAS se marca con forma (la trama diagonal
     de --hazard) para no depender solo del color. */
  --red: #8B0F08;
  --warn: #F5B301;         /* amarillo de aviso: relleno, jamas texto */
  --orange: #A34608;       /* estado archivado */
  --hazard: repeating-linear-gradient(45deg, #111111 0 10px, #F5B301 10px 20px);

  /* --- Alias historicos -------------------------------------------------
     No son residuo: son la API real de la hoja. --blue se referencia 53
     veces y --cyan 17, frente a 14 de los canonicos. Por eso el rediseno
     cambia lo que VALEN y no como se llaman: se recolorea el sitio entero
     sin tocar los 70 sitios que los consumen.
     Lo que manda es el rol, no el nombre del color. */
  --blue: var(--vermillion-ink);  /* rol: acento primario, enlaces, CTA */
  --cyan: var(--ink);             /* rol: companero, filetes, citas */
  --blue-soft: #F6C9C4;           /* rol: decorativo (tinte palido) */
  --green: var(--vermillion-ink);
  --green-deep: var(--ink);
  --green-soft: #F6C9C4;
  --yellow: var(--warn);

  /* Superficies. Antes eran blanco translucido con backdrop-filter; ahora
     son opacas y con filete negro. Cambiar estos dos tokens aplana de golpe
     las 47 referencias a --glass-line y las 22 a --glass. */
  --glass: #FFFFFF;
  --glass-line: var(--ink);
  --line: rgba(17, 17, 17, 0.18);

  /* Sombra de bloque impreso: dura y desplazada, sin desenfoque. Una
     serigrafia no tiene sombra suave. */
  --shadow: 5px 5px 0 var(--ink);
  --radius: 0;             /* canto vivo (era 22px, el sistema "Crystal") */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --step: steps(4, end);   /* movimiento mecanico, no organico */

  /* --- Escala tipografica ----------------------------------------------
     La hoja no tenia NINGUN token de tamano: todo eran literales. Estos
     se aplican a lo que el rediseno toca; el resto se queda como esta,
     porque retrofitar 2299 lineas no cambiaria nada visible. */
  --t-xs: 0.72rem;
  --t-sm: 0.82rem;
  --t-md: 1rem;
  --t-lg: 1.25rem;
  --t-xl: clamp(1.6rem, 3vw, 2.2rem);
  --t-2xl: clamp(2.2rem, 5vw, 3.4rem);
  --t-3xl: clamp(2.8rem, 8vw, 6rem);
  --tracking-tight: -0.025em;   /* titulares */
  --tracking-wide: 0.28em;      /* antetitulos en mayuscula */
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  font-family: "Inter", "Segoe UI", system-ui, sans-serif;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }

/* Fondo de imprenta -------------------------------------------
   Sustituye a la capa "viva" anterior: un <canvas> animado, tres manchas con
   blur(30px) y cuatro degradados radiales. Todo eso era curvo y difuso, que es
   lo contrario de un cartel.

   Ahora son dos capas estaticas en CSS puro: trama de semitono (los puntos de
   la serigrafia) y una barra diagonal de tinta. Cero JavaScript, cero canvas,
   cero pintado continuo.

   De paso se va el azul lavanda rgba(122,160,255,.20) que quedaba de una
   paleta anterior y tenia la esquina superior de TODAS las paginas. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  background-color: var(--paper);
  background-image:
    /* barra diagonal: una sola franja ancha cruzando la esquina */
    linear-gradient(115deg, transparent 0 62%, rgba(232, 64, 47, 0.10) 62% 74%, transparent 74%),
    /* trama de semitono. La alfa va en el color del punto, no en un
       pseudo-elemento encima: a plena opacidad la trama picaria debajo del
       texto, y bajarla aqui deja el fondo siendo exactamente --paper. */
    radial-gradient(rgba(17, 17, 17, 0.13) 1.1px, transparent 1.2px);
  background-size: 100% 100%, 10px 10px;
  pointer-events: none;
}

/* Content wrappers ------------------------------------------- */
.wrap { position: relative; z-index: 2; width: min(1120px, 92%); margin: 0 auto; }

/* Barra de tinta a sangre. El box-shadow gigante + clip-path extiende el negro
   hasta los bordes de la ventana sin sacar la nav del .wrap, que es lo que
   mantiene alineada la marca con el resto de la pagina. */
.nav-bar {
  position: relative;
  z-index: 3;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 0;
  color: var(--paper);
  margin-bottom: 26px;
}
/* El negro se extiende a todo el ancho con un pseudo-elemento, no con un
   box-shadow gigante: 100vmax en un movil de 390px son 850px de sombra a cada
   lado y algunos navegadores la cuentan para el scroll horizontal. Este es
   ademas el mismo patron que ya usaba la nav de la biblioteca mas abajo, asi
   que hay una sola tecnica de sangrado en toda la hoja. */
.nav-bar::before {
  content: ""; position: absolute; inset: 0 calc(50% - 50vw); z-index: -1;
  background: var(--ink);
}
.mark {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-weight: 900; font-size: 1.05rem;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--paper);
}
.mark-row { display: flex; align-items: center; gap: 12px; min-width: 0; }

.links { display: flex; gap: 8px; align-items: center; }
.links a {
  padding: 8px 14px; font-size: var(--t-sm); color: var(--paper);
  text-transform: uppercase; letter-spacing: 0.12em; font-weight: 600;
  transition: color var(--t-rapido, 120ms), background var(--t-rapido, 120ms);
}
.links a:hover, .links a:focus-visible { color: var(--ink); background: var(--vermillion); }

/* Menú de páginas (hamburguer): en móvil, los links del footer se colapsan
   aquí, junto al toggle de idioma. Oculto en escritorio (lo revela el media
   query de móvil). Lo construye app.js clonando .foot-links. */
.nav-menu-wrap { position: relative; display: none; }
.nav-menu-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 34px; border-radius: 0; cursor: pointer;
  color: var(--muted); background: var(--glass); border: 1px solid var(--glass-line);
  transition: color 0.2s var(--ease), background 0.2s var(--ease);
}
.nav-menu-toggle:hover { color: var(--ink); background: #fff; }
.nav-menu {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 40; display: none;
  flex-direction: column; min-width: 190px; padding: 8px;
  background: rgba(255, 255, 255, 0.94); border: 1px solid var(--glass-line);
  border-radius: 0; box-shadow: var(--shadow);}
.nav-menu a { padding: 10px 12px; border-radius: 0; color: var(--ink); font-size: 0.92rem; white-space: nowrap; }
.nav-menu a:hover { background: rgba(18, 38, 30, 0.05); }
.nav-menu-wrap.open .nav-menu { display: flex; animation: fade 0.2s var(--ease); }
/* Home affordance lives in the brand mark (replaces the decorative dot) */
.mark-home { display: inline-flex; align-items: center; justify-content: center; color: var(--vermillion); flex: 0 0 auto; }
.mark-home svg { display: block; }
.mark-home:hover { color: var(--paper); }
.mark-title { color: inherit; text-decoration: none; }
a.mark-title:hover { color: var(--vermillion); }

/* Logo de marca -----------------------------------------------
   El lockup ya dice HUMAN BOOKSHELF con la misma tipografia de palo grueso
   que usa .mark, asi que SUSTITUYE al texto en vez de acompanarlo: poner la
   marca al lado de si misma es decir dos veces lo mismo. El nombre sigue
   estando para lectores de pantalla y para cuando la imagen no carga, en el
   alt de la <img>.

   Manda la altura y el ancho sale del aspecto (2.83:1). Asi la barra negra
   no cambia de alto entre paginas: la nav mide lo que mide el logo, no lo
   que mide un archivo que alguien reexporte con otro tamano. */
.mark-logo { display: inline-flex; align-items: center; padding: 2px 0; }
.mark-logo img { display: block; height: 48px; width: auto; }

/* En las paginas de lectura el hueco de texto ya lo ocupa el titulo del
   libro, asi que ahi va solo el emblema (cara + libro abierto) haciendo de
   boton de inicio, en lugar del icono de casita. Es el mismo recorte del
   logo, no un dibujo aparte. */
.mark-home img { display: block; height: 34px; width: auto; }
/* El :hover del icono vectorial era un cambio de color; sobre un mapa de
   bits no aplica, asi que el afordance pasa a ser opacidad. */
.mark-home img { transition: opacity var(--t-rapido, 120ms); }
.mark-home:hover img { opacity: 0.72; }

/* Hero ------------------------------------------------------- */
.hero {
  position: relative; z-index: 2;
  min-height: 78vh;
  display: flex; flex-direction: column; justify-content: center;
  padding: 40px 0 60px;
}
/* Antetitulo: mayuscula muy espaciada sobre barra roja. El tracking amplio ya
   era el sello del sitio; aqui se le anade la regla de tinta. */
.hero .eyebrow, .home-intro .eyebrow {
  display: inline-block;
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-size: var(--t-xs); font-weight: 700;
  letter-spacing: var(--tracking-wide); text-transform: uppercase;
  color: var(--paper); background: var(--vermillion);
  padding: 6px 12px; margin-bottom: 22px; opacity: 0;
  animation: rise 1s var(--ease) 0.1s forwards;
}
.hero h1 {
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-size: var(--t-3xl);
  line-height: 0.92; letter-spacing: var(--tracking-tight); font-weight: 900;
  text-transform: uppercase;
  max-width: 14ch; margin: 0; opacity: 0;
  animation: rise 1.1s var(--ease) 0.25s forwards;
}
.hero h1 em {
  font-style: normal;
  color: var(--vermillion);
  text-shadow: 4px 4px 0 var(--ink);
}
.hero .lead {
  margin-top: 26px; color: var(--muted);
  font-size: clamp(1rem, 1.6vw, 1.15rem); max-width: 46ch; opacity: 0;
  animation: rise 1.1s var(--ease) 0.45s forwards;
}
.actions { margin-top: 40px; display: flex; gap: 14px; flex-wrap: wrap; opacity: 0; animation: rise 1.1s var(--ease) 0.65s forwards; }

@keyframes rise {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Single-page home: intro next to chat --------------------- */
.home-split {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: 1fr 1fr; gap: 44px;
  align-items: stretch; min-height: calc(100vh - 172px); min-height: calc(100dvh - 172px); padding: 4px 0 24px;
}
.home-intro { display: flex; flex-direction: column; justify-content: center; }
.home-intro .eyebrow {
  font-size: 0.78rem; letter-spacing: 0.28em; text-transform: uppercase;
  color: var(--blue); margin-bottom: 20px; opacity: 0; animation: rise 1s var(--ease) 0.1s forwards;
}
.home-intro h1 {
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-size: var(--t-2xl); line-height: 0.92;
  letter-spacing: var(--tracking-tight); font-weight: 900; text-transform: uppercase;
  max-width: 14ch; margin: 0; opacity: 0; animation: rise 1.1s var(--ease) 0.25s forwards;
}
.home-intro h1 em {
  font-style: normal;
  color: var(--vermillion);
  text-shadow: 4px 4px 0 var(--ink);
}
.home-intro .lead {
  margin-top: 22px; color: var(--muted); font-size: clamp(1rem, 1.5vw, 1.12rem);
  max-width: 42ch; opacity: 0; animation: rise 1.1s var(--ease) 0.45s forwards;
}

/* Pagina "Que es esto": el texto tiene que caber de una pantalla, sin bajar.
   Es una pagina de dos parrafos y un boton; si obliga a hacer scroll, algo esta
   ocupando mas de lo que merece. Se acorta el aire entre bloques y se ensancha
   un poco la medida para que cada parrafo ocupe menos alto. */
body.about-body .home-intro .eyebrow { margin-bottom: 12px; }
body.about-body .home-intro .lead { margin-top: 14px; max-width: 54ch; line-height: 1.55; }
body.about-body .home-intro .actions { margin-top: 22px; }
body.about-body .home-split { min-height: 0; }
.home-intro .actions { margin-top: 32px; }
.home-split .chat { height: min(calc(100vh - 172px), 760px); height: min(calc(100dvh - 172px), 760px); opacity: 0; animation: rise 1.1s var(--ease) 0.55s forwards; }

/* Modal ---------------------------------------------------- */
.modal-overlay {
  position: fixed; inset: 0; z-index: 50; display: none; align-items: center; justify-content: center;
  padding: 20px; background: rgba(18, 38, 30, 0.28);}
.modal-overlay.open { display: flex; animation: fade 0.3s var(--ease); }
.modal {
  position: relative; width: min(480px, 100%); max-height: 90vh; max-height: 90dvh; overflow: auto; padding: 30px;
  border-radius: var(--radius); background: rgba(255, 255, 255, 0.75); border: 1px solid var(--glass-line);
box-shadow: var(--shadow); animation: rise 0.4s var(--ease);
}
.modal-close {
  position: absolute; top: 12px; right: 16px; border: 0; background: transparent;
  font-size: 1.5rem; line-height: 1; cursor: pointer; color: var(--muted);
}
.modal-close:hover { color: var(--ink); }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

/* Saludo del asistente en el modal */
.modal-greet { display: flex; align-items: center; gap: 12px; margin: 4px 0 22px; }
.greet-avatar {
  flex: 0 0 auto; width: 48px; height: 48px; border-radius: 0; overflow: hidden;
  box-shadow: 0 0 0 2px rgba(24, 117, 71, 0.25), 0 6px 16px -6px rgba(18, 38, 30, 0.4);
  animation: greet-bob 3s var(--ease) infinite;
}
.greet-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.greet-bubble {
  position: relative; background: #fff; border: 1px solid var(--line);
  border-radius: 0; border-bottom-left-radius: 5px; padding: 10px 14px;
  font-size: 0.92rem; color: var(--ink); box-shadow: var(--shadow);
  transform-origin: left center; opacity: 0;
  animation: greet-pop 0.55s var(--ease) 0.15s forwards;
}
.greet-bubble::before {
  content: ""; position: absolute; left: -7px; bottom: 8px;
  width: 12px; height: 12px; background: #fff;
  border-left: 1px solid var(--line); border-bottom: 1px solid var(--line);
  transform: rotate(45deg);
}
@keyframes greet-bob {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-4px) rotate(-3deg); }
}
@keyframes greet-pop {
  0%   { opacity: 0; transform: scale(0.85) translateX(-6px); }
  60%  { opacity: 1; transform: scale(1.04); }
  100% { opacity: 1; transform: scale(1); }
}

/* Buttons ---------------------------------------------------- */
/* Boton = bloque impreso: rectangulo, filete negro y sombra dura y desplazada.
   Al pulsar se desplaza sobre su propia sombra, como un sello que baja. */
.btn {
  position: relative; display: inline-flex; align-items: center; gap: 10px;
  padding: 13px 22px;
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-size: var(--t-sm); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em;
  border: 2px solid var(--ink); cursor: pointer;
  background: var(--paper); color: var(--ink);
  box-shadow: 4px 4px 0 var(--ink);
  transition: transform var(--t-rapido, 120ms), box-shadow var(--t-rapido, 120ms);
}
.btn:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 var(--ink); }
.btn:active { transform: translate(4px, 4px); box-shadow: 0 0 0 var(--ink); }
.btn.primary { background: var(--vermillion-ink); color: var(--paper); border-color: var(--ink); }
.btn.ghost, .btn.secondary { background: var(--paper); border-color: var(--ink); color: var(--ink); }
/* PELIGRO. El rojo ya no sirve para avisar (ahora es la marca), asi que el
   borrado se marca con la trama diagonal: forma ademas de color, que es lo que
   pide accesibilidad y lo que distingue de un boton normal. */
.btn.danger, .note-item-btn--del, .note-bar-btn--del {
  color: var(--red); font-weight: 700;
}
.btn.danger { background: var(--hazard); color: var(--ink); border-color: var(--ink); text-shadow: 0 0 3px var(--warn); }
.btn .arrow { transition: transform 0.4s var(--ease); }
.btn:hover .arrow { transform: translateX(4px); }

/* Pastilla de "hablar" (avatar del asistente + icono) */
.talk-pill {
  display: inline-flex; align-items: center; gap: 12px;
  padding: 7px 18px 7px 7px; cursor: pointer;
  background: var(--vermillion-ink); color: var(--paper);
  border: 2px solid var(--ink); box-shadow: 4px 4px 0 var(--ink);
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-size: var(--t-sm); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em;
  transition: transform var(--t-rapido, 120ms), box-shadow var(--t-rapido, 120ms);
}
.talk-pill:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 var(--ink); }
.talk-avatar {
  width: 40px; height: 40px; object-fit: cover; flex: 0 0 auto;
  border: 2px solid var(--ink);
}
.talk-text { white-space: nowrap; }
.talk-icon { color: #fff; flex: 0 0 auto; transition: transform 0.4s var(--ease); }
.talk-pill:hover .talk-icon { transform: translateX(3px) translateY(-2px); }

/* Circular send button in the chat composer */
.chat-send { flex: 0 0 auto; width: 48px; height: 48px; padding: 0; justify-content: center; }

/* Crystal cards ---------------------------------------------- */
.crystal {
  position: relative; padding: 26px 24px; border-radius: var(--radius);
  background: var(--glass); border: 1px solid var(--glass-line);
  box-shadow: var(--shadow); overflow: hidden;
  transition: transform 0.5s var(--ease), box-shadow 0.5s var(--ease);
}
.crystal::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(140deg, rgba(255,255,255,0.6), transparent 40%);
  opacity: 0.7; pointer-events: none;
}
.crystal::after {
  content: ""; position: absolute; width: 140px; height: 140px; border-radius: 0;
  top: -50px; right: -40px;
  background: radial-gradient(circle, var(--accent, var(--blue-soft)), transparent 70%);
  opacity: 0.35; filter: blur(6px);
}
.crystal:hover { transform: translateY(-6px); box-shadow: 0 30px 70px -26px rgba(18, 38, 30, 0.45); }
.crystal .glyph { width: 40px; height: 40px; margin-bottom: 16px; }
.crystal h3 { margin: 0 0 6px; font-size: 1.05rem; font-weight: 600; }
.crystal p { margin: 0; color: var(--muted); font-size: 0.92rem; line-height: 1.5; }
.c1 { --accent: var(--blue-soft); }
.c2 { --accent: var(--cyan); }
.c3 { --accent: var(--orange); }

.mini-title {
  position: relative; z-index: 2;
  font-size: 0.76rem; letter-spacing: 0.26em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 20px;
}

/* Chat / FAQ ------------------------------------------------- */
.stage { position: relative; z-index: 2; padding: 30px 0 90px; }
.split { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: 18px; }


.chat {
  border-radius: var(--radius); background: var(--glass); border: 1px solid var(--glass-line);
box-shadow: var(--shadow);
  padding: 16px; display: flex; flex-direction: column; min-height: 420px; overflow: hidden;
}
.chat .log { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 6px 4px 12px; display: flex; flex-direction: column; gap: 12px; }
.bubble { max-width: 82%; padding: 11px 14px; border-radius: 0; font-size: 0.92rem; line-height: 1.45; animation: rise 0.5s var(--ease); }
.msg { display: flex; align-items: flex-end; gap: 10px; }
.msg.assistant { flex-direction: row; }
.msg.user { flex-direction: row; justify-content: flex-end; }
.msg.assistant .bubble { background: #fff; border: 1px solid var(--line); border-bottom-left-radius: 6px; }
.msg.user .bubble { background: var(--ink); color: var(--paper); }

.avatar {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 0; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--paper-2); border: 1px solid var(--glass-line);
  box-shadow: 0 4px 12px -4px rgba(18, 38, 30, 0.35);
}
.msg.assistant .avatar { box-shadow: 0 0 0 2px rgba(24, 117, 71, 0.25), 0 4px 12px -4px rgba(18, 38, 30, 0.35); }
.avatar-img { width: 100%; height: 100%; object-fit: cover; display: block; }

.composer { display: flex; gap: 10px; margin-top: 10px; }
.composer input {
  flex: 1; border: 1px solid var(--glass-line); background: rgba(255,255,255,0.7);
  border-radius: 0; padding: 13px 18px; font-size: 0.95rem; outline: none;
  transition: box-shadow 0.4s var(--ease);
}
.composer input:focus { box-shadow: 0 0 0 4px rgba(24, 117, 71,0.15); }

.chat-disclaimer {
  margin: 10px 4px 2px; font-size: 0.72rem; line-height: 1.5; color: var(--muted);
  opacity: 0.8; text-align: left;
}
.chat-disclaimer::before {
  content: "AI"; display: inline-block; vertical-align: middle; margin-right: 6px;
  font-size: 0.58rem; font-weight: 700; letter-spacing: 0.04em;
  padding: 2px 6px; border-radius: 0; color: var(--blue);
  background: rgba(24, 117, 71, 0.10); border: 1px solid rgba(24, 117, 71, 0.20);
}
.disclaimer-link {
  border: 0; background: transparent; padding: 0; cursor: pointer; font: inherit;
  color: var(--blue); font-weight: 600; text-decoration: underline;
  text-underline-offset: 2px; transition: color 0.3s var(--ease);
}
.disclaimer-link:hover { color: var(--cyan); }

/* Chat toolbar + maximize ------------------------------------ */
.debug-toggle {
  display: inline-flex; align-items: center; gap: 10px; cursor: pointer;
  font-size: 0.9rem; color: var(--ink); user-select: none;
}
.debug-toggle input { width: 18px; height: 18px; cursor: pointer; accent-color: var(--blue); }
.debug-toggle-nav {
  gap: 8px; padding: 6px 12px; border-radius: 0;
  background: var(--glass); border: 1px solid var(--glass-line);
font-size: 0.82rem; color: var(--muted);
}
.debug-toggle-nav:hover { color: var(--ink); }
.debug-toggle-nav input { width: 16px; height: 16px; }

.chat-head { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin: -2px 2px 8px; }
.chat-icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 0; cursor: pointer;
  color: var(--muted); background: rgba(255, 255, 255, 0.5);
  border: 1px solid var(--glass-line); transition: color 0.3s var(--ease), background 0.3s var(--ease), transform 0.3s var(--ease);
}
.chat-icon-btn:hover { color: var(--ink); background: #fff; transform: translateY(-1px); }
.chat-icon-btn .ic-collapse { display: none; }

/* Modo voz de la IA (chat-voice): micrófono + botón 🔊 por mensaje */
/* Borde e icono azules, coherentes con el botón de enviar. */
.cv-mic { display: inline-flex; align-items: center; justify-content: center; cursor: pointer; color: var(--blue); border-color: var(--blue); }
.cv-mic--dictate {
  flex: 0 0 auto; width: 44px; min-height: 44px; border-radius: 0;
  background: rgba(24, 117, 71, 0.08); border: 1px solid var(--blue);
  transition: color 0.25s var(--ease), background 0.25s var(--ease);
}
.cv-mic--dictate:hover { color: #fff; background: var(--blue); }
.cv-mic.cv-on { color: #fff; background: var(--blue); border-color: var(--blue); }         /* modo voz activo */
.cv-mic.cv-listening { color: #fff; background: var(--rojo-k, #187547); border-color: transparent; } /* escuchando */
@media (prefers-reduced-motion: no-preference) {
  .cv-mic.cv-listening { animation: cvPulse 1.2s ease-in-out infinite; }
}
@keyframes cvPulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(24, 117, 71, 0.45); } 50% { box-shadow: 0 0 0 6px rgba(24, 117, 71, 0); } }
/* Botón 🔊 en la burbuja de la IA: burbuja propia para que el icono resalte */
.cv-say {
  flex: 0 0 auto; align-self: flex-end; margin-left: 2px; cursor: pointer;
  width: 26px; height: 26px; border-radius: 0; padding: 0; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center; font-size: 0.8rem;
  color: var(--blue); background: rgba(24, 117, 71, 0.10); border: 1px solid var(--blue);
  box-shadow: 0 1px 3px rgba(18, 38, 30, 0.12);
  transition: background 0.2s var(--ease), color 0.2s var(--ease), transform 0.2s var(--ease);
}
.cv-say:hover, .cv-say:focus-visible { color: #fff; background: var(--blue); transform: translateY(-1px); }
.chat-mini-btn {
  display: none; align-items: center; gap: 8px;
  margin-right: auto; padding: 7px 14px;
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-size: var(--t-xs); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--paper); background: var(--ink); border: 0;
}

.chat.maximized {
  position: fixed; top: 88px; right: 14px; bottom: 84px; left: 14px;
  z-index: 60; width: auto; height: auto;
  max-height: none; min-height: 0; margin: 0; opacity: 1;
  animation: rise 0.35s var(--ease) forwards;
}
.home-split .chat.maximized { height: auto; opacity: 1; }
.chat.maximized .chat-mini-btn { display: inline-flex; }
.chat.maximized .chat-head .ic-expand { display: none; }
.chat.maximized .chat-head .ic-collapse { display: block; }
body.chat-maxed { overflow: hidden; }

/* Forms ------------------------------------------------------ */
.form-card {
  position: relative; z-index: 2; max-width: 560px; padding: 30px; border-radius: var(--radius);
  background: var(--glass); border: 1px solid var(--glass-line);
box-shadow: var(--shadow);
}
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 0.82rem; color: var(--muted); margin-bottom: 6px; }
.field input, .field textarea {
  width: 100%; border: 1px solid var(--glass-line); background: rgba(255,255,255,0.7);
  border-radius: 0; padding: 12px 14px; font-size: 0.95rem; outline: none;
  transition: box-shadow 0.4s var(--ease);
}
.field input:focus, .field textarea:focus { box-shadow: 0 0 0 4px rgba(24, 117, 71,0.15); }
.field textarea { min-height: 120px; resize: vertical; }

/* Footer ----------------------------------------------------- */
.foot {
  position: relative; z-index: 2; margin-top: 30px; padding: 16px 0 22px;
  color: var(--ink); font-size: var(--t-sm);
  border-top: 3px solid var(--ink);
  display: flex; justify-content: flex-start; align-items: center; gap: 8px 18px; flex-wrap: wrap;
}
.foot-copy { white-space: nowrap; }
.foot-links { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
.foot-links a {
  color: var(--ink); text-decoration: none;
  font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; font-size: var(--t-xs);
}
.foot-links a:hover { color: var(--paper); background: var(--ink); }
.lang-toggle { display: inline-flex; gap: 0; padding: 0; border-radius: 0; background: var(--paper); border: 2px solid var(--paper); }
.lang-toggle button { border: 0; background: transparent; cursor: pointer; padding: 5px 12px; border-radius: 0; font-weight: 700; font-size: var(--t-xs); letter-spacing: 0.1em; color: var(--ink); }
.lang-toggle button:hover { background: var(--vermillion); color: var(--paper); }
.lang-toggle button.active { background: var(--ink); color: #fff; }

/* Hidden admin access — a subtle dot next to the copyright */
.admin-access {
  display: inline-block;
  width: 7px; height: 7px;
  margin-left: 9px;
  border-radius: 0;
  background: rgba(18, 38, 30, 0.18);
  vertical-align: middle;
  transition: background 0.4s var(--ease), transform 0.4s var(--ease);
}
.admin-access:hover { background: var(--blue); transform: scale(1.3); }

/* Aqui vivian .reveal / .reveal.in: un fade-in por scroll que activaba
   living-bg.js anadiendo la clase .in. Al borrar ese script la regla se
   quedaba con opacity:0 y sin nadie que la quitara, asi que cualquier
   elemento con class="reveal" habria sido invisible para siempre y sin dar
   ningun error. Se retira entera. */

/* Admin (crystal variant) ------------------------------------ */
.admin-grid { position: relative; z-index: 2; display: grid; grid-template-columns: 240px 1fr; gap: 18px; padding: 20px 0 60px; }
.sidebar, .panel {
  border-radius: var(--radius); background: var(--glass); border: 1px solid var(--glass-line);
box-shadow: var(--shadow); padding: 16px;
}
.tab-btn { width: 100%; text-align: left; margin-bottom: 8px; }
.hidden { display: none; }

/* Admin full-screen layout: use the whole viewport, scroll inside panels */
body.admin-body { height: 100vh; height: 100dvh; overflow: hidden; }
body.admin-body .wrap {
  width: 98%; max-width: 2200px; height: 100vh; height: 100dvh;
  display: flex; flex-direction: column;
}
body.admin-body .nav-bar { padding: 12px 0; flex: 0 0 auto; }
body.admin-body .admin-grid {
  flex: 1 1 auto; min-height: 0; padding: 0 0 12px;
  grid-template-columns: 210px 1fr; gap: 12px;
}
body.admin-body .sidebar {
  align-self: stretch; overflow-y: auto; padding: 12px;
}
body.admin-body .panel {
  min-height: 0; overflow-y: auto; padding: 18px 22px;
}
body.admin-body .panel label { margin: 9px 0 4px; }
body.admin-body .panel input,
body.admin-body .panel textarea,
body.admin-body .panel select { padding: 8px 12px; border-radius: 0; }
body.admin-body .panel textarea { min-height: 84px; }
body.admin-body .cta-row { margin-top: 12px; }
.small { color: var(--muted); font-size: 0.9rem; }

/* Bare form elements inside admin panel */
.panel label { display: block; font-size: 0.82rem; color: var(--muted); margin: 12px 0 6px; }
.panel input, .panel textarea, .panel select {
  width: 100%; border: 1px solid var(--glass-line); background: rgba(255,255,255,0.7);
  border-radius: 0; padding: 11px 14px; font-size: 0.95rem; outline: none;
  transition: box-shadow 0.4s var(--ease);
}
.panel input:focus, .panel textarea:focus { box-shadow: 0 0 0 4px rgba(24, 117, 71,0.15); }
.panel textarea { min-height: 110px; resize: vertical; }
.panel h2 { margin-top: 0; font-weight: 600; }
.panel ul { list-style: none; padding: 0; margin: 0; }
.cta-row { margin-top: 18px; display: flex; gap: 12px; flex-wrap: wrap; }

.admin-search {
  width: 100%; margin: 0 0 14px; padding: 10px 14px; border-radius: 0;
  border: 1px solid var(--glass-line); background: rgba(255,255,255,0.75);
  font-size: 0.95rem; outline: none; transition: box-shadow 0.4s var(--ease);
}
.admin-search:focus { box-shadow: 0 0 0 4px rgba(24, 117, 71,0.15); }

/* Contacts messaging ----------------------------------------- */
.btn.danger { background: rgba(192, 57, 43,0.12); border: 1px solid rgba(192, 57, 43,0.35); color: var(--red); }
.btn.danger:hover { background: var(--red); color: #fff; }

.nav-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 6px; margin-left: 6px;
  border-radius: 0; font-size: 0.72rem; font-weight: 700; line-height: 1;
  color: #fff; background: var(--red); vertical-align: middle;
}

.contacts-layout { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 14px; align-items: start; }
.contacts-layout.notes-open:not(.context-open) { grid-template-columns: 240px minmax(0, 1fr) 320px; }
.contacts-layout.context-open:not(.notes-open) { grid-template-columns: 240px minmax(0, 1fr) 340px; }
.contacts-layout.notes-open.context-open { grid-template-columns: 240px minmax(0, 1fr) 320px 340px; }
.contacts-list { max-height: 72vh; overflow-y: auto; overflow-x: hidden; display: flex; flex-direction: column; gap: 8px; }
.contact-item {
  padding: 11px 13px; border-radius: 0; cursor: pointer; min-width: 0;
  background: rgba(255,255,255,0.55); border: 1px solid var(--glass-line);
  transition: background 0.25s var(--ease), transform 0.25s var(--ease);
}
.contact-item:hover { background: #fff; transform: translateY(-1px); }
.contact-item.is-active { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(24, 117, 71,0.14); }
.contact-item.is-unread { border-left: 3px solid var(--blue); }
.contact-item-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; }
.contact-item-top > strong { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.contact-item-preview { color: var(--muted); font-size: 0.82rem; margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.contact-item-date { margin-top: 4px; font-size: 0.72rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.status-chip { font-size: 0.66rem; font-weight: 700; padding: 2px 8px; border-radius: 0; white-space: nowrap; }
.status-new { color: var(--blue); background: rgba(24, 117, 71,0.12); }
.status-read { color: var(--muted); background: rgba(20,22,26,0.08); }
.status-replied { color: #187547; background: rgba(24,117,71,0.12); }
.status-archived { color: var(--orange); background: rgba(150, 97, 15,0.14); }

.contact-chips { display: inline-flex; align-items: center; gap: 6px; }
.lang-chip {
  font-size: 0.62rem; font-weight: 700; letter-spacing: 0.04em;
  padding: 2px 6px; border-radius: 0; color: var(--cyan);
  background: rgba(15, 122, 98,0.14); border: 1px solid rgba(15, 122, 98,0.3);
}
.lang-chip-lg { font-size: 0.72rem; padding: 4px 10px; border-radius: 0; }
.reply-right-head { display: flex; align-items: center; gap: 10px; }
.thread-unread {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 0;
  font-size: 0.66rem; font-weight: 700; color: #fff; background: var(--red);
}
.thread { display: flex; flex-direction: column; gap: 12px; }
.msg-card {
  padding: 12px 14px; border-radius: 0;
  background: rgba(255,255,255,0.6); border: 1px solid var(--glass-line);
}
.msg-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.msg-row { display: flex; align-items: flex-start; gap: 12px; }
.msg-row .contact-message { flex: 1; min-width: 0; background: var(--paper); margin: 0; }
.msg-icons { display: flex; flex-direction: row; gap: 6px; flex: 0 0 auto; }
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 0; cursor: pointer;
  background: rgba(255,255,255,0.7); border: 1px solid var(--glass-line);
  color: var(--muted); transition: color 0.25s var(--ease), background 0.25s var(--ease), transform 0.25s var(--ease);
}
.icon-btn:hover { transform: translateY(-1px); }
.icon-btn.icon-reply:hover { color: #fff; background: var(--blue); border-color: var(--blue); }
.icon-btn.icon-archive:hover { color: var(--orange); border-color: rgba(150, 97, 15,0.4); }
.icon-btn.icon-trash:hover { color: #fff; background: var(--red); border-color: var(--red); }
.msg-card .contact-history { margin-top: 12px; padding-top: 10px; }

.contact-detail {
  min-height: 200px; max-height: 72vh; overflow-y: auto; padding: 18px; border-radius: 0;
  background: rgba(255,255,255,0.55); border: 1px solid var(--glass-line);
}
.contact-empty { margin: 0; }
.contact-detail-head h3 { margin: 0 0 4px; }
.contact-detail-head p { margin: 0 0 14px; }
.detail-title-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.context-toggle { padding: 7px 14px; font-size: 0.85rem; flex: 0 0 auto; }

/* AI context: right-hand pane (three-pane inbox layout) */
.context-pane { display: none; min-width: 0; }
.contacts-layout.context-open .context-pane { display: block; }

/* Notes / journal side pane */
.notes-pane {
  display: none; min-width: 0; max-height: 72vh; overflow-y: auto;
  padding: 12px 14px; border-radius: 0;
  background: rgba(15, 122, 98,0.06); border: 1px solid rgba(15, 122, 98,0.25);
}
.contacts-layout.notes-open .notes-pane { display: block; }
.notes-pane .journal { margin-top: 0; border-top: 0; padding-top: 0; }
.detail-toggles { display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.context-pane .context-box {
  margin: 0; max-height: 72vh; overflow-y: auto;
  background: rgba(24, 117, 71,0.06); border: 1px solid rgba(24, 117, 71,0.2);
}
.context-pane .context-body { max-height: none; }
.context-head-right { display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.context-refresh { width: 34px; height: 34px; }
.context-refresh:hover { color: #fff; background: var(--blue); border-color: var(--blue); }
.context-refresh.is-loading { opacity: 0.7; cursor: wait; }
.context-refresh.is-loading svg { animation: ctx-spin 0.8s linear infinite; transform-origin: center; }
@keyframes ctx-spin { to { transform: rotate(360deg); } }
.context-close {
  border: 0; background: transparent; cursor: pointer; color: var(--muted);
  font-size: 1.3rem; line-height: 1; padding: 0 2px;
}
.context-close:hover { color: var(--ink); }

/* AI context memory box */
.context-box {
  margin: 0 0 16px; padding: 12px 14px; border-radius: 0;
  background: rgba(24, 117, 71,0.06); border: 1px solid rgba(24, 117, 71,0.2);
}
.context-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.context-btns { display: inline-flex; gap: 6px; flex: 0 0 auto; }
.context-btn { padding: 7px 14px; font-size: 0.85rem; }
.context-btn.is-loading { opacity: 0.5; cursor: wait; }
.context-meta { margin-bottom: 8px; }
.context-body { white-space: pre-wrap; word-break: break-word; font-size: 0.9rem; line-height: 1.5; max-height: 34vh; overflow-y: auto; }
.contact-message {
  white-space: pre-wrap; word-break: break-word; line-height: 1.5;
  padding: 10px 12px; border-radius: 0; background: rgba(255,255,255,0.7);
  border: 1px solid var(--glass-line);
}
.contact-actions { display: flex; gap: 10px; flex-wrap: wrap; margin: 16px 0; }
.contact-reply { margin-top: 18px; border-top: 1px solid var(--glass-line); padding-top: 16px; }
.contact-reply h4 { margin: 0 0 10px; font-weight: 600; }
.reply-send { margin-top: 12px; }

.contact-history { margin-top: 12px; border-top: 1px solid var(--glass-line); padding-top: 10px; }
.contact-history h4 { margin: 0 0 12px; font-weight: 600; }
.history-toggle {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  border: 0; background: transparent; padding: 0; margin: 0 0 4px;
  font: inherit; font-weight: 600; color: var(--ink);
}
.history-toggle:hover { color: var(--blue); }
.history-arrow { color: var(--blue); font-size: 0.8rem; }
.history-list { margin-top: 12px; }

/* Reply modal form fields (outside .panel, need their own styling) */
.reply-modal { width: min(560px, 100%); text-align: left; }
.reply-modal-wide { width: min(980px, 100%); }
.reply-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; }
.reply-col-left {
  border-right: 1px solid var(--glass-line); padding-right: 26px;
  display: flex; flex-direction: column; min-width: 0;
}
.reply-col-left .contact-message { flex: 1; overflow-y: auto; max-height: 55vh; margin: 0; }
.conv-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.conv-summary {
  margin-bottom: 12px; padding: 12px 14px; border-radius: 0; white-space: pre-wrap;
  background: rgba(245,197,66,0.12); border: 1px solid rgba(245,197,66,0.4);
  font-size: 0.9rem; line-height: 1.5; max-height: 30vh; overflow-y: auto;
}
.conv-history { flex: 1; overflow-y: auto; max-height: 55vh; display: flex; flex-direction: column; gap: 10px; padding-right: 4px; }
.conv-item { padding: 9px 11px; border-radius: 0; border: 1px solid var(--glass-line); }
.conv-in { background: rgba(255,255,255,0.6); border-left: 3px solid var(--muted); }
.conv-out { background: rgba(24, 117, 71,0.06); border-left: 3px solid var(--blue); }
.conv-out.conv-failed { border-left-color: var(--red); }
.conv-item-head { font-weight: 600; margin-bottom: 4px; }
.conv-item-text { white-space: pre-wrap; word-break: break-word; font-size: 0.88rem; line-height: 1.45; }
.reply-col-right { min-width: 0; }
.reply-modal label { display: block; font-size: 0.82rem; color: var(--muted); margin: 12px 0 6px; }
.reply-modal input, .reply-modal textarea, .reply-modal select {
  width: 100%; border: 1px solid var(--glass-line); background: rgba(255,255,255,0.8);
  border-radius: 0; padding: 10px 13px; font-size: 0.95rem; outline: none;
  transition: box-shadow 0.4s var(--ease);
}
.reply-modal input:focus, .reply-modal textarea:focus, .reply-modal select:focus { box-shadow: 0 0 0 4px rgba(24, 117, 71,0.15); }
.reply-modal textarea { min-height: 150px; resize: vertical; }

/* AI polish assistant inside reply modal */
.ai-assist { margin-top: 14px; border-top: 1px dashed var(--glass-line); padding-top: 14px; }
.ai-assist-row { display: flex; gap: 8px; align-items: stretch; flex-wrap: nowrap; }
.ai-assist-row select { flex: 1; min-width: 120px; }
.ai-assist-row .btn { white-space: nowrap; }
.ai-icon-btn {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 42px; border-radius: 0; cursor: pointer; font-size: 1.05rem;
  background: rgba(255,255,255,0.8); border: 1px solid var(--glass-line);
  transition: background 0.25s var(--ease), transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.ai-icon-btn:hover { transform: translateY(-1px); box-shadow: 0 8px 20px -12px rgba(24, 117, 71,0.6); }
.ai-icon-btn.is-loading { opacity: 0.5; cursor: wait; }
.ai-icon-btn:disabled { cursor: wait; }
.ai-suggestion {
  margin-top: 12px; padding: 12px 14px; border-radius: 0;
  background: rgba(15, 122, 98,0.08); border: 1px solid rgba(15, 122, 98,0.3);
}
.ai-suggestion-label { font-weight: 700; color: var(--cyan); margin-bottom: 6px; }
.ai-suggestion-text { white-space: pre-wrap; word-break: break-word; line-height: 1.55; font-size: 0.95rem; }
.ai-suggestion .cta-row { margin-top: 12px; }

/* Chat session AI verdict (keep vs delete) */
.verdict {
  margin: 14px 0 0; padding: 12px 14px; border-radius: 0;
  white-space: pre-wrap; word-break: break-word; line-height: 1.5; font-size: 0.92rem;
  background: rgba(20,22,26,0.05); border: 1px solid var(--glass-line); color: var(--ink);
}
.verdict.verdict-keep { background: rgba(24,117,71,0.10); border-color: rgba(24,117,71,0.4); color: #14603a; }
.verdict.verdict-delete { background: rgba(192, 57, 43,0.10); border-color: rgba(192, 57, 43,0.4); color: #8f2a1f; }

/* Journal / interaction notes */
.journal { margin-top: 18px; border-top: 1px solid var(--glass-line); padding-top: 14px; }
.journal-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.journal-head h4 { margin: 0; font-weight: 600; }
.journal-head-right { display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.journal-list { display: flex; flex-direction: column; gap: 10px; }
.journal-item {
  padding: 10px 12px; border-radius: 0;
  background: rgba(255,255,255,0.6); border: 1px solid var(--glass-line); border-left: 3px solid var(--cyan);
}
.journal-item-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.journal-when { flex: 1; min-width: 0; }
.journal-item-actions { display: inline-flex; gap: 6px; flex: 0 0 auto; }
.journal-item-actions .icon-btn { width: 28px; height: 28px; }
.journal-item-title { font-weight: 600; margin-bottom: 4px; }
.journal-item-body { white-space: normal; word-break: break-word; font-size: 0.9rem; line-height: 1.5; }
.journal-item-body code { background: rgba(20,22,26,0.08); padding: 1px 5px; border-radius: 0; font-size: 0.85em; }
.journal-item-body a { color: var(--blue); text-decoration: underline; }

.note-type {
  font-size: 0.64rem; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase;
  padding: 2px 8px; border-radius: 0; white-space: nowrap;
  color: var(--blue); background: rgba(24, 117, 71,0.12);
}
.note-type-call { color: #187547; background: rgba(24,117,71,0.12); }
.note-type-meeting { color: var(--orange); background: rgba(150, 97, 15,0.14); }
.note-type-document { color: var(--muted); background: rgba(20,22,26,0.08); }

.note-form {
  margin-bottom: 12px; padding: 12px 14px; border-radius: 0;
  background: rgba(24, 117, 71,0.05); border: 1px solid rgba(24, 117, 71,0.2);
}
.note-fields { display: flex; gap: 12px; flex-wrap: wrap; }
.note-fields .note-field { flex: 1; min-width: 140px; }
.note-field { display: block; margin-bottom: 8px; }
.note-label { display: block; font-size: 0.78rem; color: var(--muted); margin-bottom: 4px; }
.note-form input, .note-form select, .note-form textarea {
  width: 100%; border: 1px solid var(--glass-line); background: rgba(255,255,255,0.8);
  border-radius: 0; padding: 8px 11px; font-size: 0.92rem; outline: none;
}
.note-form textarea { resize: vertical; min-height: 90px; }
.note-form input:focus, .note-form select:focus, .note-form textarea:focus { box-shadow: 0 0 0 4px rgba(24, 117, 71,0.15); }
.history-item {
  padding: 9px 11px; margin-bottom: 8px; border-radius: 0;
  background: rgba(255,255,255,0.6); border: 1px solid var(--glass-line);
  border-left: 3px solid #187547;
}
.history-item.history-failed { border-left-color: var(--red); }
.history-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 4px; flex-wrap: wrap; }
.history-body { white-space: pre-wrap; word-break: break-word; font-size: 0.86rem; line-height: 1.45; color: var(--muted); }

@media (max-width: 1200px) {
  /* Below 1200 the extra columns get too tight: stack notes/context
     full-width under the messages (in-flow, no fixed positioning). */
  .contacts-layout.notes-open:not(.context-open),
  .contacts-layout.context-open:not(.notes-open),
  .contacts-layout.notes-open.context-open { grid-template-columns: 240px minmax(0, 1fr); }
  .contacts-layout.context-open .context-pane,
  .contacts-layout.notes-open .notes-pane { grid-column: 1 / -1; }
  .context-pane .context-box { max-height: 46vh; }
  .notes-pane { max-height: 50vh; }
}

@media (max-width: 900px) {
  .split { grid-template-columns: 1fr; }
  .admin-grid { grid-template-columns: 1fr; }
  .home-split { grid-template-columns: 1fr; min-height: 0; gap: 28px; }
  .home-split .chat { height: 56vh; height: 56dvh; min-height: 0; }
  .contacts-layout, .contacts-layout.context-open { grid-template-columns: 1fr; }
  .contacts-layout.notes-open, .contacts-layout.notes-open.context-open { grid-template-columns: 1fr; }
  .contacts-list { max-height: 40vh; }
  .contact-detail { max-height: none; overflow: visible; }
  .reply-cols { grid-template-columns: 1fr; gap: 16px; }
  .reply-col-left { border-right: 0; padding-right: 0; border-bottom: 1px solid var(--glass-line); padding-bottom: 16px; }
  .reply-col-left .contact-message { max-height: 28vh; }
  body.admin-body { height: auto; overflow: auto; }
  body.admin-body .wrap { height: auto; }
  body.admin-body .admin-grid { grid-template-columns: 1fr; }
  body.admin-body .panel, body.admin-body .sidebar { overflow: visible; }
  /* Admin tabs as a horizontal scrollable row */
  .sidebar { display: flex; flex-direction: row; overflow-x: auto; gap: 8px; padding: 10px; -webkit-overflow-scrolling: touch; }
  .tab-btn { width: auto; white-space: nowrap; margin-bottom: 0; flex: 0 0 auto; }
}

@media (max-width: 600px) {
  /* Prevent iOS auto-zoom: form fields must be >= 16px */
  .composer input,
  .modal input, .modal textarea, .modal select,
  .reply-modal input, .reply-modal textarea, .reply-modal select,
  .panel input, .panel textarea, .panel select { font-size: 16px; }

  /* Comfortable touch targets (>= 44px) */
  .icon-btn, .chat-icon-btn { width: 44px; height: 44px; }
  .ai-icon-btn { width: 44px; height: 44px; }
  .msg-icons { gap: 8px; }

  /* El logo baja a 36px en movil: a 48 se come el ancho que necesitan el
     toggle de idioma y el hamburguer, y la nav se parte en dos lineas. */
  .mark-logo img { height: 36px; }
  .mark-home img { height: 28px; }

  /* Lighten GPU load on phones: drop the animated canvas and blobs */


  /* Los links del footer se colapsan en el hamburguer del nav (junto al toggle).
     Scoped a has-nav-menu: páginas sin nav conservan sus links en el footer. */
  .nav-menu-wrap { display: inline-flex; }
  body.has-nav-menu .foot-links { display: none; }

  /* Roomier chat on phones; cap to the visible viewport so the keyboard
     never hides the composer or the messages. */
  .home-split .chat { height: min(68dvh, calc(var(--vvh, 100dvh) - 96px)); }

  /* Mobile stacking order: eyebrow -> chat -> h1 -> lead -> actions */
  .home-split { display: flex; flex-direction: column; gap: 18px; }
  .home-intro { display: contents; }
  .home-intro .eyebrow { order: 1; margin-bottom: 0; font-size: 0.68rem; letter-spacing: 0.2em; }
  .home-split .chat { order: 2; }
  .home-intro h1 { order: 3; font-size: 1.45rem; line-height: 1.22; font-weight: 600; max-width: none; }
  .home-intro .lead { order: 4; margin-top: 10px; font-size: 0.95rem; }
  .home-intro .actions { order: 5; margin-top: 6px; }

  /* Compact modals + kill nested scroll areas inside the reply modal */
  .modal { padding: 18px; }
  .reply-modal-wide { width: 100%; }
  .conv-history, .conv-summary { max-height: none; }
  .reply-col-left .contact-message { max-height: none; }
  .ai-assist-row { flex-wrap: wrap; }
  .ai-assist-row select { min-width: 100%; }

  /* Maximized chat: full-screen app-like takeover (ChatGPT/Claude style),
     height bound to the visible viewport so the composer stays above the keyboard */
  body.chat-maxed .foot,
  body.chat-maxed .nav-bar { display: none; }
  .home-split .chat.maximized {
    top: 0; bottom: auto; left: 0; right: 0; height: var(--vvh, 100dvh); border-radius: 0;
    padding: calc(env(safe-area-inset-top) + 12px) 14px calc(env(safe-area-inset-bottom) + 10px);
    animation: none;
  }
  .chat.maximized .chat-head { margin: 0 0 10px; padding-bottom: 10px; border-bottom: 1px solid var(--line); }
  .chat.maximized .log { gap: 14px; padding: 4px 2px 14px; }
  .chat.maximized .bubble { max-width: 88%; font-size: 0.98rem; }
  .chat.maximized .composer { margin-top: 12px; }
  .chat.maximized .chat-disclaimer { display: none; }

  /* Contacts master-detail: show one pane at a time */
  .contacts-layout .contact-detail { display: none; }
  .contacts-layout.has-detail .contacts-list { display: none; }
  .contacts-layout.has-detail .contact-detail { display: block; }
  .detail-back { display: inline-flex; margin-bottom: 12px; }
}

.detail-back { display: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ============================================================ */
/* Free course                                                  */
/* ============================================================ */

/* Home CTA pill (secondary to talk-pill) */
.course-pill {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 11px 18px; border-radius: 0; cursor: pointer; text-decoration: none;
  background: var(--glass); border: 1px solid var(--glass-line);  color: var(--ink); font-size: 1rem; font-weight: 600;
  transition: transform 0.4s var(--ease), box-shadow 0.4s var(--ease), background 0.4s var(--ease);
}
.course-pill:hover { transform: translateY(-2px); background: #fff; box-shadow: var(--shadow); }
.course-icon { color: var(--blue); flex: 0 0 auto; }
.course-pill-badge {
  font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  /* Texto blanco: el gradiente bronce/oliva es oscuro, así que el texto oscuro
     original quedaba en 2.65 de contraste. Blanco da 5.23-5.32 en todo el
     recorrido del gradiente, AA en ambos extremos. */
  background: var(--orange); color: var(--paper);
  padding: 2px 8px; border-radius: 0;
}

/* Landing */
.course-hero { position: relative; z-index: 2; max-width: 820px; margin: 20px 0 40px; }
.course-hero h1 {
  font-size: clamp(2.1rem, 6vw, 3.4rem); line-height: 1.05; margin: 8px 0 0; letter-spacing: -0.02em;
  color: var(--vermillion);
  text-shadow: 4px 4px 0 var(--ink);
}
.course-hero .course-subtitle { margin: 6px 0 0; color: var(--blue); font-weight: 600; font-size: clamp(1.05rem, 2vw, 1.35rem); letter-spacing: -0.01em; }
.course-hero .lead { margin-top: 16px; color: var(--muted); max-width: none; font-size: clamp(0.85rem, 1.05vw, 0.98rem); line-height: 1.65; }
.course-stats { list-style: none; display: flex; flex-wrap: wrap; gap: 12px; margin: 22px 0 0; padding: 0; }
.course-stats li {
  display: flex; flex-direction: column; gap: 3px; padding: 12px 18px; border-radius: 0;
  background: var(--glass); border: 1px solid var(--glass-line); min-width: 92px;
}
.cs-num {
  font-size: 1.5rem; font-weight: 700; line-height: 1; letter-spacing: -0.02em;
  color: var(--vermillion-ink);
}
.cs-lbl { font-size: 0.72rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; }
.course-progress { display: flex; align-items: center; gap: 12px; margin-top: 24px; max-width: 460px; }
.course-progress-bar { flex: 1; height: 8px; border-radius: 0; background: rgba(18, 38, 30,0.1); overflow: hidden; }
.course-progress-bar span { display: block; height: 100%; width: 0; background: var(--vermillion); transition: width 0.6s var(--ease); }

/* Completed-topic checkmark (shared by the reader sidebar and sitemap) */
.rn-topic.is-done .rn-check { background: var(--blue); border-color: var(--blue); }
.rn-topic.is-done .rn-check::after {
  content: ""; position: absolute; left: 5px; top: 1px; width: 5px; height: 10px;
  border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.course-empty { position: relative; z-index: 2; color: var(--muted); padding: 40px 0; }

/* Course library (catalog of courses shown as cards) */
.course-library {
  position: relative; z-index: 2; display: grid; gap: 18px; padding-bottom: 40px;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}
/* Portada = bloque de tinta a sangre, no una tarjeta blanca con filete.
   --card-accent es la tinta del libro y --card-ink el color de texto que le
   corresponde; los dos los emite library/_card.php desde PHP, porque el par
   correcto depende de la luminancia del color y CSS todavia no puede calcularlo
   de forma fiable (color-contrast() no tiene soporte). Sin --card-ink, la mitad
   de las nueve portadas quedarian ilegibles. */
.course-card {
  --card-accent: var(--vermillion);
  --card-ink: var(--paper);
  display: flex; flex-direction: column; gap: 10px; text-decoration: none;
  background: var(--card-accent); color: var(--card-ink);
  border: 2px solid var(--ink); border-radius: 0;
  padding: 22px; position: relative; overflow: hidden;
  box-shadow: 5px 5px 0 var(--ink);
  transition: transform var(--t-rapido, 120ms), box-shadow var(--t-rapido, 120ms);
}
/* Trama de semitono sobre la tinta: la textura de la serigrafia. */
.course-card::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(currentColor 1px, transparent 1.1px);
  background-size: 9px 9px; opacity: 0.16;
}
.course-card:hover { transform: translate(-3px, -3px); box-shadow: 8px 8px 0 var(--ink); }
.course-card > * { position: relative; z-index: 1; }
.course-card-title {
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-weight: 900; font-size: var(--t-lg);
  letter-spacing: var(--tracking-tight); line-height: 0.98;
  text-transform: uppercase; color: var(--card-ink);
}
/* Dentro de la portada NADA usa --muted ni --card-accent como color de texto:
   el fondo ya es la tinta del libro, asi que un texto en esa misma tinta seria
   invisible y uno gris no tendria contraste. Todo hereda --card-ink y se
   gradua con opacidad. */
.course-card-summary { color: var(--card-ink); opacity: 0.88; font-size: 0.92rem; line-height: 1.5; }
.course-card-meta { font-size: var(--t-xs); color: var(--card-ink); opacity: 0.75; margin-top: 2px; }
.course-card-cta {
  margin-top: auto; padding-top: 10px; color: var(--card-ink);
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-weight: 700; font-size: var(--t-xs);
  text-transform: uppercase; letter-spacing: 0.14em;
}

/* Hero + save-progress side by side at the top of a course page */
.course-top {
  position: relative; z-index: 2; display: grid; align-items: start; gap: 28px;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); margin: 20px 0 40px; /* ~60 / 40 */
}
.course-top .course-hero { margin: 0; max-width: none; }
.course-enroll-side { margin: 0; max-width: none; position: sticky; top: 20px; }
@media (max-width: 820px) {
  .course-top { grid-template-columns: 1fr; }
  .course-enroll-side { position: static; }
}

/* Single-screen course page: everything fits the viewport, no page scroll */
/* Sin `overflow: hidden` aqui a proposito. La barra de navegacion pinta su
   banda negra con un ::before que se sale del .wrap para llegar a los bordes de
   la ventana, y cualquier overflow en el contenedor la RECORTA: la banda se
   cortaba justo donde acaba el .wrap y quedaban dos franjas crema a los lados.
   El recorte vertical que esta pagina si necesita vive ahora en
   .course-modules-k, que es el bloque que de verdad puede desbordarse. */
.course-fit .wrap {
  width: min(1360px, 96%); height: 100vh; height: 100dvh;
  display: flex; flex-direction: column;
}
.course-fit .nav-bar { flex: 0 0 auto; }
.course-fit .course-top { flex: 0 0 auto; margin: 8px 0 10px; gap: 24px; }
.course-fit .course-hero h1 { font-size: clamp(1.5rem, 3vw, 2.15rem); }
.course-fit .course-hero .lead { margin-top: 8px; font-size: 0.92rem; }
.course-fit .course-stats { margin-top: 16px; gap: 10px; }
.course-fit .course-stats li { padding: 9px 15px; min-width: 80px; }
.course-fit .cs-num { font-size: 1.3rem; }
.course-fit .course-progress { margin-top: 14px; }
.course-fit .course-hero .actions { margin-top: 14px; }
.course-fit .course-enroll-side { padding: 16px 18px; position: static; }
.course-fit .course-enroll-side h2 { font-size: 1.05rem; }
.course-fit .course-enroll-side > p.small { font-size: 0.82rem; }
.course-fit .course-enroll-side .enroll-form { margin-top: 10px; gap: 8px; }
.course-fit .foot { flex: 0 0 auto; padding: 8px 0; }
@media (max-width: 820px) {
  /* On small screens, fall back to normal flow (a phone can't fit 27 topics). */
  .course-fit .wrap { height: auto; overflow: visible; display: block; }
}

.course-enroll {
  position: relative; z-index: 2; margin: 20px 0 50px; padding: 24px; border-radius: var(--radius);
  background: var(--glass); border: 1px solid var(--glass-line);max-width: 720px;
}
.course-enroll h2 { margin: 0 0 6px; font-size: 1.2rem; }
.enroll-form { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin-top: 14px; }
.enroll-form input[type=email], .enroll-form input:not([type]) {
  flex: 1 1 200px; padding: 11px 14px; border-radius: 0; border: 1px solid var(--line); background: #fff; font: inherit;
}
.enroll-news { display: inline-flex; align-items: center; gap: 6px; font-size: 0.9rem; color: var(--muted); }
.enroll-status { min-height: 1.2em; color: var(--blue); }

/* Botón que se ve como enlace (disparadores "Continuar donde ibas") */
.linklike {
  font: inherit; background: none; border: none; cursor: pointer; padding: 0;
  color: var(--azul-k); text-decoration: underline; text-underline-offset: 2px;
}
.linklike:hover { color: var(--ink); }
/* En la nav del lector, que combine con los pills de .links a */
.links .linklike {
  padding: 9px 16px; border-radius: 0; font-size: 0.92rem; color: var(--muted);
  text-decoration: none; transition: color 0.4s var(--ease), background 0.4s var(--ease);
}
.links .linklike:hover { color: var(--ink); background: var(--glass);}
/* "Continuar progreso" (pill secundario junto al CTA): JS lo muestra/oculta con el
   atributo hidden, que debe ganar sobre el display:inline-flex de .course-pill. */
.course-pill[hidden] { display: none; }

/* Reader layout: sidebar | content | tutor */
.reader-grid { position: relative; z-index: 2; display: grid; grid-template-columns: 250px minmax(0, 1fr) 320px; gap: 24px; align-items: start; padding-bottom: 40px; }
.reader-nav { position: sticky; top: 20px; max-height: calc(100vh - 40px); overflow-y: auto; }
.reader-nav-toggle { display: none; }
/* Light "chat-like" panel around the collapsible module list */
.reader-nav-inner { background: var(--glass); border: 1px solid var(--glass-line); border-radius: 0; padding: 8px;}
.rn-module { margin-bottom: 2px; }
.rn-module:last-child { margin-bottom: 0; }
/* Module header = collapsible accordion summary */
summary.rn-module-title {
  cursor: pointer; user-select: none; list-style: none;
  display: flex; align-items: center; gap: 8px; padding: 8px; border-radius: 0;
  font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted);
  transition: color 0.2s var(--ease), background 0.2s var(--ease);
}
summary.rn-module-title::-webkit-details-marker { display: none; }
summary.rn-module-title:hover { color: var(--ink); background: #fff; }
summary.rn-module-title::after {
  content: ""; margin-left: auto; flex: 0 0 auto; width: 6px; height: 6px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(-45deg); transition: transform 0.25s var(--ease);
}
details.rn-module[open] > summary.rn-module-title { color: var(--ink); }
details.rn-module[open] > summary.rn-module-title::after { transform: rotate(45deg); }
.rn-module ul { list-style: none; margin: 3px 0 6px; padding: 0 0 0 4px; display: grid; gap: 2px; }
.rn-topic { display: flex; align-items: center; gap: 8px; text-decoration: none; color: var(--muted); padding: 6px 8px; border-radius: 0; font-size: 0.9rem; }
.rn-topic:hover { background: #fff; color: var(--ink); }
.rn-topic.current { background: #fff; color: var(--ink); font-weight: 600; box-shadow: var(--shadow); }
.rn-check { flex: 0 0 auto; width: 15px; height: 15px; border-radius: 0; border: 2px solid var(--line); position: relative; }

.reader-main { min-width: 0; }
.reader-head h1 { font-size: var(--t-xl); line-height: 0.98; margin: 6px 0; }

/* ---------- SUPERFICIE DE LECTURA ----------
   Aqui el cartel NO entra. Son 192 capitulos y la gente lee horas seguidas:
   fondo liso, tipografia de cuerpo y nada de tramas debajo del texto. El
   estilo aparece solo en los titulos de seccion, que ademas hacen de
   separador.

   MEDIDA DE LINEA: antes no habia ninguna. La columna la fijaba solo el grid
   (una barra de 260px, el texto, y un chat de 360px dentro de un .wrap de
   hasta 1800px), asi que en una pantalla ancha la linea llegaba a ~110
   caracteres, muy por encima de los 65-75 que se leen comodos. El max-width
   en ch es el arreglo de mas impacto de todo el rediseno, y no tiene nada que
   ver con el estilo. */
.reader-content {
  background: #FFFFFF; border: 2px solid var(--ink);
  border-radius: 0; padding: clamp(20px, 3vw, 44px); box-shadow: none;
  font-size: clamp(1.06rem, 1.05vw, 1.18rem); line-height: 1.72;
  color: var(--ink); overflow-wrap: break-word;
  max-width: 68ch;
}
/* Titulo de seccion: lo unico del texto con tratamiento de cartel. La regla
   roja encima separa secciones mejor que el espacio en blanco solo. */
.reader-content h2 {
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-size: 1.5rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: -0.01em; line-height: 1.1;
  margin: 2em 0 0.6em; padding-top: 0.55em;
  border-top: 6px solid var(--vermillion);
}
.reader-content h2:first-child { margin-top: 0.2em; }
.reader-content h3 {
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-size: 1.2rem; font-weight: 700; margin: 1.5em 0 0.4em; color: var(--ink);
}
/* h4 no tenia NINGUNA regla: salia con el defecto del navegador dentro de la
   superficie mas leida del sitio. Aparece 140 veces en los capitulos. */
.reader-content h4 {
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-size: 1rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.08em; margin: 1.4em 0 0.3em; color: var(--muted);
}
.reader-content p { margin: 0.85em 0; }
.reader-content a { color: var(--blue); text-decoration: underline; text-underline-offset: 2px; }

/* Listas, enfasis y cajas: tampoco tenian regla. Entre las cuatro suman mas de
   14.000 apariciones en los capitulos, todas saliendo con el defecto del
   navegador. */
.reader-content ul, .reader-content ol { margin: 0.85em 0; padding-left: 1.4em; }
.reader-content li { margin: 0.35em 0; }
.reader-content ul { list-style: none; padding-left: 1.2em; }
.reader-content ul > li { position: relative; }
.reader-content ul > li::before {
  content: ""; position: absolute; left: -1.1em; top: 0.62em;
  width: 7px; height: 7px; background: var(--vermillion);
}
.reader-content ol > li::marker {
  font-family: var(--f-display, 'Jost', system-ui, sans-serif); font-weight: 700;
}
.reader-content strong { font-weight: 700; }
.reader-content em { font-style: italic; }
.reader-content .course-box {
  margin: 1.2em 0; padding: 14px 18px;
  border: 2px solid var(--ink); border-left-width: 8px; background: var(--paper);
}
.reader-content .course-box > *:first-child { margin-top: 0; }
.reader-content .course-box > *:last-child { margin-bottom: 0; }
.reader-content .course-example {
  margin: 1.1em 0; padding: 12px 18px; border-left: 8px solid var(--ink);
  background: var(--paper); font-style: italic; color: var(--muted); border-radius: 0;
}
/* Callout: caja de imprenta con cabecera en tinta plana. */
.reader-content .callout {
  margin: 1.4em 0; border-radius: 0; overflow: hidden; border: 2px solid var(--ink);
}
.reader-content .callout-head {
  padding: 8px 14px; color: var(--paper);
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-weight: 700; font-size: var(--t-sm);
  text-transform: uppercase; letter-spacing: 0.12em;
}
.reader-content .callout-body { padding: 12px 16px; }
.reader-content .callout-body p:first-child { margin-top: 0; }
.reader-content .callout-body p:last-child { margin-bottom: 0; }
/* Las tres variantes conservan hue distinto para poder distinguirse entre si;
   lo que cambia es que ahora son tinta plana en vez de tinte translucido. */
.reader-content .callout--concept .callout-head { background: var(--ink); }
.reader-content .callout--concept { background: var(--paper); }
.reader-content .callout--exercise .callout-head { background: var(--orange); }
.reader-content .callout--exercise { background: #FBF3E8; }
.reader-content .callout--reflect .callout-head { background: var(--vermillion-ink); }
.reader-content .callout--reflect { background: #FBEEEC; }

/* Tabla: cabecera en negativo y filete de tinta. `th` no tenia NINGUNA regla
   (solo `td` llevaba borde), asi que las cabeceras salian sueltas y sin caja. */
.reader-content .course-table { width: 100%; border-collapse: collapse; margin: 1.4em 0; font-size: 0.98rem; }
.reader-content .course-table th {
  background: var(--ink); color: var(--paper);
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-weight: 700; font-size: var(--t-sm);
  text-transform: uppercase; letter-spacing: 0.08em;
  padding: 9px 12px; text-align: left; border: 1px solid var(--ink);
}
.reader-content .course-table td { border: 1px solid var(--ink); padding: 8px 12px; vertical-align: top; }
.reader-content .course-table tr:nth-child(even) td { background: var(--paper); }
.reader-content .course-table.glossary td:first-child { font-weight: 700; width: 30%; }

/* Collapsible "How to use this book" intro (collapsed by default) */
.reader-content .course-howto {
  margin: 0.4em 0 1.4em; border: 2px solid var(--ink); border-radius: 0;
  background: var(--paper); overflow: hidden;
}
.reader-content .course-howto > summary {
  cursor: pointer; list-style: none; padding: 12px 16px;
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-size: var(--t-sm); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--ink); display: flex; align-items: center; gap: 10px; user-select: none;
}
.reader-content .course-howto > summary::-webkit-details-marker { display: none; }
.reader-content .course-howto > summary::before {
  content: "▸"; color: var(--vermillion); transition: transform var(--t-rapido, 120ms); flex: 0 0 auto;
}
.reader-content .course-howto[open] > summary::before { transform: rotate(90deg); }
.reader-content .course-howto > summary:hover { background: var(--paper-2); }
.reader-content .course-howto .howto-body { padding: 0 16px 8px; }
.reader-content .course-howto .howto-body > *:first-child { margin-top: 0; }

.reader-controls { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 24px 0; flex-wrap: wrap; }
.reader-controls .btn { max-width: 44%; }
#markComplete.is-done { background: var(--ink); color: var(--paper); }

.reader-tutor {
  position: sticky; top: 20px; display: flex; flex-direction: column;
  height: calc(100vh - 40px); max-height: 760px;
  background: rgba(255,255,255,0.55); border: 1px solid var(--glass-line);  border-radius: var(--radius); padding: 16px; box-shadow: var(--shadow);
}
.tutor-head { display: flex; align-items: center; gap: 10px; font-weight: 600; margin-bottom: 10px; }
.tutor-head .greet-avatar { width: 34px; height: 34px; border-radius: 0; overflow: hidden; flex: 0 0 auto; }
.tutor-head .greet-avatar img { width: 100%; height: 100%; object-fit: cover; }
.reader-tutor .log { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 4px; display: flex; flex-direction: column; gap: 12px; }

/* Responsive */
@media (max-width: 1080px) {
  .reader-grid { grid-template-columns: minmax(0, 1fr); }
  .reader-nav { position: static; max-height: none; }
  .reader-nav-inner { display: none; }
  .reader-nav.open .reader-nav-inner { display: block; }
  .reader-nav-toggle {
    display: inline-block; padding: 10px 16px; border-radius: 0; border: 1px solid var(--glass-line);
    background: var(--glass);font: inherit; font-weight: 600; cursor: pointer; margin-bottom: 10px;
  }
  .reader-tutor { position: static; height: 60vh; height: 60dvh; margin-top: 20px; }
}

/* Desktop reader: full-width, full-height 3-pane app layout with independent
   scrolling panes. Scoped to the reader so home/landing/mobile are unaffected. */
@media (min-width: 1081px) {
  body.course-reader { overflow: hidden; }
  body.course-reader .wrap {
    width: 96%; max-width: 1800px; height: 100vh; height: 100dvh;
    display: flex; flex-direction: column;
  }
  body.course-reader .reader-grid {
    flex: 1; min-height: 0; align-items: stretch; padding-bottom: 0;
    grid-template-columns: 260px minmax(0, 1fr) 360px;
    /* Fila acotada a la altura del grid: sin esto la fila es `auto` y crece
       con la columna más alta (un chat largo), rompiendo el height:100% de los
       paneles y su scroll interno. Con minmax(0,1fr) cada panel (nav, main y el
       chat del asistente) queda a altura fija y scrollea por dentro. */
    grid-template-rows: minmax(0, 1fr);
  }
  body.course-reader .reader-nav {
    position: static; top: auto; height: 100%; max-height: none; overflow-y: auto; padding-right: 6px;
  }
  body.course-reader .reader-main {
    height: 100%; overflow-y: auto; padding-right: 12px;
  }
  body.course-reader .reader-tutor {
    position: static; top: auto; height: 100%; max-height: none;
  }
  body.course-reader .foot { flex: 0 0 auto; margin-top: 10px; }
}



/* Slim, discreet scrollbars for the reader panes */
.reader-nav, .reader-main, .reader-tutor .log { scrollbar-width: thin; scrollbar-color: rgba(18, 38, 30,0.28) transparent; }
.reader-nav::-webkit-scrollbar, .reader-main::-webkit-scrollbar, .reader-tutor .log::-webkit-scrollbar { width: 10px; }
.reader-nav::-webkit-scrollbar-thumb, .reader-main::-webkit-scrollbar-thumb, .reader-tutor .log::-webkit-scrollbar-thumb {
  background: rgba(18, 38, 30,0.22); border-radius: 0; border: 2px solid transparent; background-clip: padding-box;
}
.reader-nav::-webkit-scrollbar-thumb:hover, .reader-main::-webkit-scrollbar-thumb:hover, .reader-tutor .log::-webkit-scrollbar-thumb:hover {
  background: rgba(18, 38, 30,0.4); background-clip: padding-box;
}
.reader-nav::-webkit-scrollbar-track, .reader-main::-webkit-scrollbar-track, .reader-tutor .log::-webkit-scrollbar-track { background: transparent; }

/* ============================================================ */
/* Kandinsky hybrid layer — course pages only (scoped .course-body) */
/* "El lienzo es neutro; Kandinsky habla solo donde comunica algo."  */
/* Flatter Bauhaus discipline over the existing Crystal identity.    */
/* ============================================================ */
.course-body {
  /* Roles estrictos, ahora en clave de cartel. Los nombres vienen de la guia
     Kandinsky original (rojo=accion, azul=navegacion, amarillo=progreso) y
     resulta que ahora dicen la verdad: la accion SI es roja y la navegacion SI
     es tinta plana. Ratios medidos contra --paper #F2EFE4 (el crema real de
     :root, no un color inventado):
       accion      5.99  AA texto
       navegacion 16.40  AA texto
       progreso    3.50  AA grafico (solo la barra de avance, nunca texto)
       completado 16.40  AA texto */
  --k-accion: #B3170F;     /* acción: CTA, "estás aquí" */
  --k-navegacion: #111111; /* navegación: enlaces, hover, foco */
  --k-progreso: #E8402F;   /* progreso: la barra que avanza */
  --k-completado: #111111; /* completado */

  /* Alias historicos: 73 referencias que no hace falta reescribir. */
  --rojo-k: var(--k-accion);
  --azul-k: var(--k-navegacion);
  --amarillo-k: var(--k-progreso);
  --verde-check: var(--k-completado);
  --linea-k: #111111;     /* filetes y divisores: regla negra, no gris */
  --radio-k: 0;           /* canto vivo (era 10px) */
  --lienzo-hover: #E8E3D4;
  --f-display: 'Jost', 'Futura', system-ui, sans-serif;
  --t-rapido: 120ms var(--step);
  --t-recompensa: 320ms var(--step);
}

/* Titulares: Jost al maximo peso, en mayuscula y muy apretados.
   El sello ya existia en la hoja (tracking negativo en titulos, muy positivo en
   antetitulos); el rediseno solo lo lleva al extremo del cartel. */
.course-body .course-hero h1,
.course-body .course-card-title,
.course-body .reader-head h1,
.course-body .k-mod-title {
  font-family: var(--f-display);
  font-weight: 900;
  letter-spacing: var(--tracking-tight);
  line-height: 0.94;
  text-transform: uppercase;
}

/* En el lector la trama del fondo baja aun mas: el texto manda. */
.course-body::before { background-image: none; background-color: var(--paper); }

/* Focus visible (guide §8): contorno 2px azul con offset */
.course-body a:focus-visible,
.course-body button:focus-visible,
.course-body input:focus-visible,
.course-body textarea:focus-visible,
.course-body .k-pt:focus-visible {
  outline: 2px solid var(--azul-k); outline-offset: 2px; border-radius: 0;
}

/* ---------- Componente firma: el mapa de avance (.k-map) ----------
   Era una linea fina de 2px con discos de 16px encima, cada uno con un halo del
   color del papel que recortaba la linea por detras. Muy elegante y muy curvo.

   Ahora es una BARRA GRUESA con casillas cuadradas: el mismo dato (por donde
   vas y cuanto llevas) contado como una escala impresa. El halo se conserva
   porque sigue haciendo el mismo trabajo — separar la casilla de la barra —
   solo que en cuadrado.

   Lo que NO cambia: .is-done marca con una palomita en ::after. Eso es forma
   ademas de color, o sea accesibilidad, no adorno. */
.k-map {
  position: relative; z-index: 2;
  display: flex; align-items: center; justify-content: space-between;
  gap: 4px; margin: 18px 0 6px; padding: 12px 6px;
}
.k-map .k-line {
  position: absolute; left: 10px; right: 10px; top: 50%; height: 6px;
  transform: translateY(-50%); background: var(--linea-k);
}
.k-map .k-line-fill {
  display: block; height: 100%; width: 0;
  background: var(--amarillo-k); transition: width var(--t-recompensa, 400ms) var(--step);
}
.k-pt {
  position: relative; z-index: 1; flex: 0 0 auto;
  width: 16px; height: 16px;
  background: var(--paper); border: 2px solid var(--linea-k);
  box-shadow: 0 0 0 3px var(--paper); /* recorta la barra detrás de la casilla */
  transition: transform var(--t-rapido, 120ms), background var(--t-rapido, 120ms);
}
.k-pt:hover { background: var(--amarillo-k); transform: scale(1.25); }
.k-pt.is-done { background: var(--ink); border-color: var(--ink); }
.k-pt.is-done::after { /* palomita: forma, no solo color */
  content: ""; position: absolute; left: 4px; top: 1px; width: 4px; height: 8px;
  border: solid var(--paper); border-width: 0 2px 2px 0; transform: rotate(45deg);
}
/* "Estas aqui": casilla roja con doble halo cuadrado. */
.k-pt.current {
  background: var(--rojo-k); border-color: var(--ink);
  box-shadow: 0 0 0 3px var(--paper), 0 0 0 6px var(--ink);
}
.k-map--compact { margin: 0 0 14px; padding: 8px 6px; }
/* En el lector, el mapa compacto queda fijo arriba de la columna de contenido */
body.course-reader .reader-main > .k-map--compact { position: sticky; top: 0; z-index: 3; background: var(--paper); }
.k-map--compact .k-line { height: 4px; }
.k-map--compact .k-pt { width: 12px; height: 12px; }
.k-map--compact .k-pt.is-done::after { left: 2.5px; top: 0.5px; width: 3px; height: 6px; }

/* Barra sticky del lector: k-map + fila de controles (pager superior + read-aloud).
   Se mueve el sticky del k-map a este contenedor, así los controles nunca se pierden
   al hacer scroll. Mínimo espacio: 2 filas finas; eyebrow y h1 quedan fuera. */
body.course-reader .reader-main > .reader-toolbar {
  position: sticky; top: 0; z-index: 3; background: var(--paper);
  padding-top: 4px; margin-bottom: 12px; border-bottom: 1px solid var(--linea-k);
}
.reader-toolbar .k-map--compact { margin: 0; }
.reader-toolbar-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 6px 0; }
.reader-toolbar-row:empty { display: none; }
/* read-aloud dentro de la barra: sin caja glass, más compacto, alineado a la izquierda */
.reader-toolbar .read-aloud { order: 1; margin: 0; padding: 0; background: none; border: none;gap: 8px; }
.reader-toolbar .read-aloud .ra-btn { min-height: 34px; padding: 6px 12px; }
.reader-toolbar .read-aloud .ra-speed { margin-left: 0; }
.reader-toolbar .read-aloud .ra-hint { display: none; }
@media (min-width: 1100px) { .reader-toolbar .read-aloud .ra-hint { display: inline; } }
/* pager superior empujado a la derecha de la fila */
.reader-toolbar .reader-pager--top { order: 2; margin-left: auto; }

/* ---------- Vista 1 · Catálogo ----------
   Antes este bloque aplanaba la tarjeta a blanco (var(--plano, #fff), un token
   que nunca existio y siempre caia al fallback). Ahora la portada ES el color,
   asi que solo queda el borde. */
.course-body .course-card {
  border: 2px solid var(--ink);
  border-radius: 0;
}
.course-body .course-card:hover {
  transform: none; background: #fff; box-shadow: none; border-color: var(--azul-k);
}
/* Al aplanarse a blanco, la portada deja de ser el fondo de color, y todo lo que
   se pinta con --card-ink se queda sin fondo que lo sostenga: esa tinta es crema
   en cuatro de los diez libros (equipos-y-turnos, pagos, seguridad-alimentaria y
   administracion-basica), asi que el texto, el glifo y la pildora desaparecian
   sobre el blanco sin que nada avisara. En reposo NO se toca: ahi --card-ink es
   el par correcto para la tinta del libro, medido en 23-poster-colorways.sql.

   El glifo entra aqui porque dibuja en currentColor (ver course_glyph() en
   library/_data.php); con el hex horneado que tenia antes, esta regla no le
   habria hecho nada. */
.course-body .course-card:hover .course-card-title,
.course-body .course-card:hover .course-card-summary,
.course-body .course-card:hover .course-card-meta { color: var(--ink); }
/* La pildora se invierte en vez de apagarse: sobre el blanco pasa a ser el chip
   de color del libro, y el par accent/ink es el mismo que ya cumple AA. */
.course-body .course-card:hover .course-card-cat {
  color: var(--card-ink); background: var(--card-accent);
}
.course-body .course-card:hover .course-card-glyph {
  color: var(--ink); transform: translate(3px, -2px) rotate(4deg);
}
.course-card-glyph { width: 44px; height: 44px; display: block; }
.course-card-glyph svg { width: 100%; height: 100%; overflow: visible; transition: transform 150ms var(--ease); }
/* La CTA solo se pinta con la tinta de navegacion cuando la tarjeta esta
   aplanada a blanco. Antes lo hacia SIEMPRE, y es del mismo lote que el hover:
   sobra de cuando la tarjeta era blanca tambien en reposo. Sobre la portada de
   color quedaba un "Empezar" casi negro con 2,4 de contraste en las cuatro
   tintas oscuras — y sobre la de Seguridad alimentaria, que es #111111, negro
   sobre negro: invisible. En reposo hereda --card-ink, que es el par medido. */
.course-body .course-card:hover .course-card-cta { color: var(--azul-k); }
.course-card-progress {
  display: none; align-items: center; gap: 8px; margin-top: 4px;
}
.course-card.has-progress .course-card-progress { display: flex; }
.course-card-progress .ccp-bar { flex: 1; height: 6px; border-radius: 0; background: rgba(18, 38, 30,0.1); overflow: hidden; }
.course-card-progress .ccp-fill { display: block; height: 100%; width: 0; background: var(--amarillo-k); border-radius: 0; transition: width 0.6s var(--ease); }
.course-card-progress .ccp-lbl { font-size: 0.72rem; color: var(--tinta-suave, var(--muted)); text-transform: uppercase; letter-spacing: 0.05em; }

/* ---------- Vista 2 · Temario (módulos en columnas, flat Kandinsky) ---------- */
/* Columnas responsivas para aprovechar el ancho y caber sin scroll (como antes) */
/* Temario = mapa de contenido tipo sitemap: columnas limpias, sin paneles,
   sin minutos, sin scroll. La estructura la dan la línea divisora y las columnas. */
.course-modules-k {
  position: relative; z-index: 2; display: grid; align-content: start;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 6px 28px; padding-bottom: 24px;
}
.k-module { break-inside: avoid; }
.k-mod-head { display: flex; align-items: baseline; gap: 8px; margin: 8px 0 6px; padding-bottom: 5px; border-bottom: 1px solid var(--linea-k); }
.k-mod-roman { font-family: var(--f-display); font-weight: 700; font-size: 0.85rem; color: var(--rojo-k); letter-spacing: 0.04em; }
.k-mod-title { font-size: 0.95rem; margin: 0; line-height: 1.2; }
.k-topics { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; }
.k-topic {
  display: flex; align-items: center; gap: 9px; text-decoration: none; color: var(--muted);
  padding: 3px 0; font-size: 0.9rem; line-height: 1.3;
  transition: color 150ms var(--ease);
}
.k-topic:hover { color: var(--azul-k); }
.k-topic-label { flex: 1 1 auto; min-width: 0; }
.k-topic-check { flex: 0 0 auto; width: 13px; height: 13px; border-radius: 0; border: 1.5px solid var(--linea-k); position: relative; }
.k-topic.is-done .k-topic-check { background: var(--verde-check); border-color: var(--verde-check); }
.k-topic.is-done .k-topic-check::after { content: ""; position: absolute; left: 3px; top: 0.5px; width: 3px; height: 6px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg); }
.k-topic.is-done .k-topic-label { opacity: 0.7; }
/* Vista course-fit (una sola pantalla): sin scroll; el sitemap denso cabe. */
/* Se lleva el recorte que antes hacia el .wrap. Con `auto` en vez de `hidden`
   el temario que no cabe se puede alcanzar haciendo scroll dentro del bloque,
   en vez de quedar cortado sin mas: un libro de 39 capitulos no entra en una
   pantalla y antes el resto simplemente no existia. */
.course-fit .course-modules-k { flex: 1 1 auto; min-height: 0; overflow-y: auto; gap: 4px 26px; }
@media (max-width: 820px) {
  /* Teléfono: una columna y filas táctiles cómodas. */
  .course-fit .course-modules-k { grid-template-columns: 1fr; }
  .k-topic { padding: 8px 0; }
}

/* ---------- Vista 3 · Lección (aplanado + extras) ---------- */
.course-body .reader-content {
  background: #fff; border: 2px solid var(--ink); box-shadow: none;
  border-radius: 0;
}
.course-body .reader-nav-inner,
.course-body .reader-tutor { border-radius: var(--radio-k); }
/* Prev/next: "Siguiente" en rojo (única acción roja), "Anterior" enlace azul */
.reader-controls .rc-next {
  display: inline-flex; flex-direction: column; align-items: flex-end; gap: 2px;
  background: var(--rojo-k); color: #fff; border: none; border-radius: var(--radio-k);
  padding: 10px 16px; text-decoration: none; max-width: 48%;
}
.reader-controls .rc-next .rc-kicker { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.06em; opacity: 0.85; }
.reader-controls .rc-next .rc-title { font-weight: 600; font-size: 0.95rem; }
.reader-controls .rc-prev {
  color: var(--azul-k); background: none; border: none; text-decoration: none;
  font-weight: 500; max-width: 40%;
}
.reader-controls .rc-prev:hover { text-decoration: underline; }
.course-body #markComplete.is-done { background: var(--verde-check); }
/* Paginación del lector: una sección <h2> por "página" */
.reader-page[hidden] { display: none; }
.course-body .reader-controls[hidden] { display: none !important; }
.reader-page { animation: kFade 220ms var(--ease); }
@keyframes kFade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.reader-pager {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin: 22px 0 4px; flex-wrap: wrap;
}
.reader-pager .rp-prev {
  background: none; border: none; color: var(--azul-k); font: inherit; font-weight: 500;
  cursor: pointer; padding: 10px 4px; min-height: 44px;
}
.reader-pager .rp-prev:hover { text-decoration: underline; }
.reader-pager .rp-prev[hidden] { visibility: hidden; display: inline-block; } /* keep layout */
.reader-pager .rp-next {
  background: var(--rojo-k); color: #fff; border: none; border-radius: var(--radio-k);
  font: inherit; font-weight: 600; cursor: pointer; padding: 11px 20px; min-height: 44px;
}
.reader-pager .rp-next[hidden] { display: none; }
.reader-pager .rp-ind { display: inline-flex; align-items: center; gap: 10px; color: var(--muted); }
.reader-pager .rp-count { font-size: 0.78rem; letter-spacing: 0.04em; }
.reader-pager .rp-dots { display: inline-flex; align-items: center; gap: 2px; flex-wrap: wrap; }
/* Dots = clickable buttons that jump to a page. Small visual disc in ::before,
   larger transparent hit area around it for touch. */
.reader-pager .rp-dot {
  appearance: none; -webkit-appearance: none; border: none; background: none;
  padding: 5px 3px; margin: 0; cursor: pointer; line-height: 0; display: inline-flex;
}
.reader-pager .rp-dot::before {
  content: ""; display: block; width: 6px; height: 6px; border-radius: 0;
  background: var(--linea-k); transition: background 150ms var(--ease), transform 150ms var(--ease);
}
.reader-pager .rp-dot.seen::before { background: var(--amarillo-k); }
.reader-pager .rp-dot.current::before { background: var(--ink); transform: scale(1.3); }
.reader-pager .rp-dot:hover::before { background: var(--azul-k); }

/* Mini-pager compacto (barra superior y barra flotante): flechas planas, sin
   bloque rojo. Las reglas se comparten entre las variantes --top y --float. */
.rh-top { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.reader-pager--top { margin: 0; gap: 8px; flex: 0 0 auto; }
.reader-pager--top .rp-txt,
.reader-pager--float .rp-txt { display: none; }
.reader-pager--top .rp-prev, .reader-pager--top .rp-next,
.reader-pager--float .rp-prev, .reader-pager--float .rp-next {
  background: none; color: var(--azul-k); border: none; border-radius: 0;
  padding: 4px 6px; min-height: 0; font-size: 1.05rem; font-weight: 600;
}
.reader-pager--top .rp-prev:hover, .reader-pager--top .rp-next:hover,
.reader-pager--float .rp-prev:hover, .reader-pager--float .rp-next:hover { text-decoration: none; color: var(--ink); }
.reader-pager--top .rp-next[hidden], .reader-pager--top .rp-prev[hidden],
.reader-pager--float .rp-next[hidden], .reader-pager--float .rp-prev[hidden] { visibility: hidden; }
.reader-pager--top .rp-count { font-size: 0.72rem; }

/* Barra flotante en dos filas: fila --read (play, enfoque, guardar) y fila --nav
   (velocidad · páginas). Cada fila es un flex propio, sin envoltura desordenada. */
/* wrap: la fila paso de 2 botones a 3 (Escuchar, Guardar, Notas) y en un
   telefono estrecho el ultimo se salia de la burbuja. Envolviendo, se reparten
   en dos lineas en vez de desbordarse. */
.ra-float-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ra-float-row--read .ra-play { flex: 1 1 auto; justify-content: center; } /* play prominente */
.ra-float-row--read .ra-focus.ra-focus--show,
.ra-float-row--read .ra-save,
.ra-float-row--read .ra-notes { flex: 0 0 auto; }                       /* chips: no estiran */
/* En lo mas estrecho la etiqueta sobra: el icono ya identifica el mando y asi
   los tres caben en una linea. */
@media (max-width: 460px) {
  .ra-float-row--read .ra-notes .ra-lbl,
  .ra-float-row--read .ra-save .ra-lbl { display: none; }
}
.ra-float-row--nav { justify-content: space-between; }                    /* velocidad izq · páginas der */
.ra-float-row--nav .reader-pager--float { margin: 0; gap: 6px; flex: 0 0 auto; }
/* Selector de velocidad dentro de la barra flotante (los estilos de .read-aloud
   .ra-speed están acotados a esa barra, así que se replican aquí). */
.ra-float .ra-speed { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); font-size: 0.85rem; }
.ra-float .ra-speed-lbl { display: none; } /* ahorra ancho: el select ya muestra "1×" */
.ra-float .ra-speed select {
  font: inherit; color: var(--ink); background: #fff; border: 1px solid var(--linea-k);
  border-radius: 0; padding: 6px 8px; min-height: 40px; cursor: pointer;
}

/* Desplegable de páginas: en desktop se ven los dots; en móvil (≤1080px) se
   ocultan y aparece un botón "Página X / N ▾" con una lista de páginas donde las
   ya leídas muestran checkmark. */
.reader-pager .rp-ind { position: relative; }
.reader-pager .rp-jump {
  display: none; align-items: center; gap: 6px; font: inherit; font-size: 0.8rem;
  background: none; border: 1px solid var(--linea-k); border-radius: 0;
  color: var(--ink); padding: 6px 12px; min-height: 36px; cursor: pointer;
}
.reader-pager .rp-jump:hover { border-color: var(--azul-k); color: var(--azul-k); }
.reader-pager .rp-caret { font-size: 0.7rem; }
.reader-pager .rp-menu {
  position: absolute; z-index: 7; left: 0; bottom: calc(100% + 6px); min-width: 200px;
  max-height: 50vh; overflow-y: auto; margin: 0; padding: 6px; list-style: none;
  background: #fff; border: 1px solid var(--linea-k); border-radius: var(--radio-k); box-shadow: var(--shadow);
}
.reader-pager--top .rp-menu { top: calc(100% + 6px); bottom: auto; } /* barra sticky: abre hacia abajo */
.reader-pager .rp-mi {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  font: inherit; font-size: 0.9rem; color: var(--muted); background: none; border: none;
  border-radius: 0; padding: 8px 10px; min-height: 40px; cursor: pointer;
}
.reader-pager .rp-mi:hover { background: var(--glass); color: var(--ink); }
.reader-pager .rp-mi--current { color: var(--ink); font-weight: 600; background: var(--glass); }
.reader-pager .rp-mi-check {
  flex: 0 0 auto; width: 15px; height: 15px; border-radius: 0;
  border: 2px solid var(--line); position: relative;
}
.reader-pager .rp-mi--read .rp-mi-check { background: var(--blue); border-color: var(--blue); }
.reader-pager .rp-mi--read .rp-mi-check::after {
  content: ""; position: absolute; left: 3px; top: 1px; width: 4px; height: 8px;
  border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
@media (max-width: 1080px) {
  /* Móvil: fuera el toolbar superior completo (k-map + controles + pager); basta la
     barra flotante inferior con play/pausa/velocidad/enfoque y el navegador de páginas. */
  body.course-reader .reader-main > .reader-toolbar { display: none; }
  /* El pager (ahora en la barra flotante) usa botón + desplegable, no dots. */
  .reader-pager .rp-dots { display: none; }
  .reader-pager .rp-count { display: none; }
  .reader-pager .rp-jump { display: inline-flex; }
}

/* Modo lectura en voz alta (read-aloud): barra de controles + resaltado karaoke */
.read-aloud {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 10px 0 4px; padding: 8px 10px;
  background: var(--glass); border: 1px solid var(--glass-line); border-radius: var(--radio-k);
}
.read-aloud .ra-btn {
  display: inline-flex; align-items: center; gap: 7px; font: inherit; font-weight: 600;
  cursor: pointer; min-height: 40px; padding: 8px 16px; border-radius: var(--radio-k);
  border: 1px solid var(--azul-k); background: none; color: var(--azul-k);
  transition: background 0.18s var(--ease), color 0.18s var(--ease);
}
.read-aloud .ra-btn:hover { background: var(--azul-k); color: #fff; }
.read-aloud .ra-btn:focus-visible { outline: 2px solid var(--azul-k); outline-offset: 2px; }
.read-aloud .ra-play[aria-pressed="true"] { background: var(--azul-k); color: #fff; }
.read-aloud .ra-play .ra-ico { font-size: 0.9rem; line-height: 1; }
.read-aloud .ra-hint { color: var(--muted); font-size: 0.8rem; }
.read-aloud .ra-speed { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; color: var(--muted); font-size: 0.85rem; }
.read-aloud .ra-speed select {
  font: inherit; color: var(--ink); background: #fff; border: 1px solid var(--linea-k);
  border-radius: 0; padding: 6px 8px; min-height: 36px; cursor: pointer;
}
/* Palabras clicables: el alumno toca una para empezar la lectura desde ahí */
.reader-content .ra-word { cursor: pointer; border-radius: 3px; }
/* Solo donde hay puntero de verdad: en tactil el :hover se queda "pegado" tras
   un toque y deja palabras resaltadas al azar. */
@media (hover: hover) {
  .reader-content .ra-word:hover { background: rgba(242, 183, 5, 0.28); }
}
/* Palabra que se está pronunciando */
.ra-word.ra-active {
  background: var(--amarillo-k); color: #1c2027; border-radius: 3px;
  box-shadow: 0 0 0 2px var(--amarillo-k);
}
@media (prefers-reduced-motion: no-preference) {
  .ra-word { transition: background 0.12s var(--ease); }
}

/* ---------------------------------------------------------------------------
   Subrayados y notas del lector (text-anchor.js + notes.js)

   Un subrayado no envuelve nodos nuevos: pone una clase en los .ra-word que ya
   existen. Por eso convive con el resaltado karaoke de la lectura en voz alta
   sin pelearse por el DOM: .ra-active gana visualmente mientras narra y el
   subrayado reaparece al parar.

   Los cuatro colores van a baja opacidad a proposito: se leen encima del texto
   sin bajarle el contraste, que es lo que pasa con un subrayado saturado.
--------------------------------------------------------------------------- */
.reader-content .ra-word.hl { border-radius: 3px; padding: 1px 0; }
.reader-content .ra-word.hl--yellow { background: rgba(242, 183, 5, 0.34); }
.reader-content .ra-word.hl--green  { background: rgba(24, 117, 71, 0.20); }
.reader-content .ra-word.hl--blue   { background: rgba(14, 90, 102, 0.20); }
.reader-content .ra-word.hl--pink   { background: rgba(192, 57, 43, 0.18); }
/* La palabra que se narra manda sobre el subrayado: si no, no se ve por donde va. */
.reader-content .ra-word.hl.ra-active { background: var(--amarillo-k); }

.reader-content .ra-word.hl-flash {
  box-shadow: 0 0 0 3px var(--k-accion);
  background: rgba(24, 117, 71, 0.30);
}
@media (prefers-reduced-motion: no-preference) {
  .reader-content .ra-word.hl-flash { animation: hlFlash 1.6s var(--ease); }
  @keyframes hlFlash {
    0%, 60% { box-shadow: 0 0 0 3px var(--k-accion); }
    100%    { box-shadow: 0 0 0 0 transparent; }
  }
}

/* Chincheta: marca los subrayados que ademas llevan nota escrita. */
.note-pin {
  border: 0; background: none; cursor: pointer; padding: 0 2px;
  color: var(--k-accion); font-size: 0.85em; line-height: 1; vertical-align: super;
}
.note-pin:hover { color: var(--k-navegacion); }

/* Barra flotante sobre la seleccion. UN mando (mas "Quitar" si el pasaje ya
   estaba subrayado): los cuatro colores se mudaron al modal, porque cinco
   objetivos apretados encima de una seleccion recien hecha no se aciertan con el
   dedo — y en movil competian con el menu del sistema por el mismo hueco. */
/* z-index 45: por encima de la navegacion (40) y por debajo de los modales (50)
   y del panel de notas (55). Estaba en 60, o sea POR ENCIMA de todo modal del
   sitio, asi que la barra se quedaba flotando sobre el editor de la nota y
   sobre el del email, tapandolos. Esconderla al abrir el editor arregla el caso
   concreto; esto arregla la clase entera. */
.note-bar {
  position: absolute; z-index: 45; display: flex; align-items: center; gap: 6px;
  padding: 4px; border-radius: 0;
  background: var(--ink); border: 2px solid var(--ink); box-shadow: var(--shadow);
}
.note-bar[hidden] { display: none; }
.note-bar-btn {
  border: 0; background: none; cursor: pointer; font: inherit; font-size: 0.85rem;
  font-weight: 700; letter-spacing: 0.02em;
  color: var(--paper); padding: 6px 12px; border-radius: 0;
}
/* El subrayador. El icono va como pseudo-elemento y esto SI puede ser un glifo:
   la barra vive en <body>, fuera de #readerContent, asi que TextAnchor no la
   recorre y no hay indices de palabra que desplazar. */
.note-bar-btn--hl::before {
  content: "\2691 "; color: var(--amarillo-k);
}
.note-bar-btn--del { color: var(--vermillion); }
.note-bar-btn:hover, .note-bar-btn:focus-visible {
  background: var(--paper); color: var(--ink); outline: none;
}
.note-bar-btn--hl:hover::before, .note-bar-btn--hl:focus-visible::before { color: var(--vermillion); }

/* Editor de la nota: reutiliza .modal-overlay / .modal del sitio. */
.note-editor .modal { width: min(520px, 100%); }

/* Los colores, ahora dentro del modal. Cuadrados grandes y con el estado
   marcado por un borde de tinta: el color de fondo por si solo no distingue
   "elegido" de "disponible" para quien no percibe bien ese matiz. */
.note-colors { display: flex; gap: 8px; margin: 0 0 12px; }
.note-swatch {
  width: 34px; height: 34px; border-radius: 0; cursor: pointer;
  border: 2px solid rgba(18, 38, 30, 0.18);
}
.note-swatch--yellow { background: rgba(242, 183, 5, 0.75); }
.note-swatch--green  { background: rgba(24, 117, 71, 0.55); }
.note-swatch--blue   { background: rgba(14, 90, 102, 0.55); }
.note-swatch--pink   { background: rgba(192, 57, 43, 0.48); }
.note-swatch:hover { outline: 2px solid var(--k-navegacion); outline-offset: 1px; }
.note-swatch[aria-checked="true"] {
  border-color: var(--ink); box-shadow: inset 0 0 0 2px var(--paper);
}
.note-quote {
  margin: 0 0 12px; padding: 10px 14px; border-left: 3px solid var(--k-accion);
  background: var(--paper-2); color: var(--muted); font-style: italic;
  max-height: 8em; overflow-y: auto;
}
.note-input {
  width: 100%; padding: 10px 12px; border-radius: 0; border: 1px solid var(--line);
  background: #fff; font: inherit; resize: vertical;
}

/* Panel lateral "Mis notas". */
/* Panel "Mis notas".
   Se abre a la IZQUIERDA del chat, nunca encima: el asistente sigue a la vista
   mientras repasas lo que subrayaste, que es justo cuando quieres preguntarle.

   Tres comportamientos segun el ancho, porque una columna de verdad no cabe en
   cualquier pantalla:
     - movil/tablet (<=1080): cajon a la derecha. Ahi el chat va apilado ABAJO,
       asi que no hay nada que tapar.
     - escritorio (1081-1499): cajon anclado al borde izquierdo del chat. Se
       superpone al texto, pero deja el chat entero visible.
     - escritorio ancho (>=1500): CUARTA COLUMNA real entre el texto y el chat.
       No se superpone a nada; el hueco sale de la holgura que ya tenia la
       columna de lectura, porque .reader-content esta topado a 68ch. */
.notes-panel {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(380px, 92vw); z-index: 55;
  background: var(--paper); border-left: 2px solid var(--ink);
  box-shadow: var(--shadow); display: flex; flex-direction: column;
}
.notes-panel[hidden] { display: none; }

/* Colocacion del panel. Va DESPUES de la regla base a proposito: ambas usan el
   mismo selector .notes-panel, asi que con igual especificidad manda la ultima
   que aparece en el archivo. Puesto antes, el `right: 0` de arriba ganaba y el
   panel volvia a caer encima del chat. */
@media (min-width: 1081px) and (max-width: 1499px) {
  /* El cajon se ancla al borde izquierdo del chat en vez de al de la ventana:
     360px es la columna del chat y 24px el hueco de la rejilla. Se superpone al
     texto, pero deja el chat entero a la vista. */
  body.course-reader .reader-grid > .notes-panel {
    /* absolute, no fixed: asi el `right` se mide contra la REJILLA (que ya es
       position: relative) y no contra la ventana. Con fixed habia que restar a
       mano el margen del .wrap, y bastaba equivocarse por 2px para que el panel
       mordiera el chat. Contra la rejilla, 360px+24px son exactamente la
       columna del chat mas el hueco: pega justo a su borde izquierdo. */
    position: absolute; top: 0; bottom: 0;
    right: calc(360px + 24px);
    width: min(360px, 34vw); height: auto;
    border: 2px solid var(--ink);
  }
}

/* >=1500px: hay sitio para una columna de verdad. El panel deja de flotar y se
   mete en la rejilla entre el texto y el chat, asi que no se superpone a nada.
   El umbral no es arbitrario: por debajo, meter 340px mas dejaria la columna de
   lectura por debajo de ~45 caracteres por linea, que ya es incomodo. */
@media (min-width: 1500px) {
  body.course-reader .reader-grid.notes-open {
    grid-template-columns: 260px minmax(0, 1fr) 340px 360px;
  }
  /* Fila explicita ademas de columna. La rejilla declara UNA sola fila
     (grid-template-rows: minmax(0,1fr)), y el panel se anade al final del DOM:
     sin fijar grid-row, el auto-placement ve el cursor ya pasado de la columna 3
     y lo manda a una segunda fila, debajo del texto. */
  body.course-reader .reader-grid.notes-open > .notes-panel {
    position: static; grid-column: 3; grid-row: 1;
    width: auto; height: 100%; z-index: auto;
    border: 2px solid var(--ink); box-shadow: none;
  }
  body.course-reader .reader-grid.notes-open > .reader-tutor { grid-column: 4; grid-row: 1; }
}

.notes-panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 20px; border-bottom: 1px solid var(--line);
}
.notes-panel-head h2 { margin: 0; font-size: 1.1rem; }
.notes-panel-head .modal-close { position: static; }
.notes-list { padding: 16px 20px 28px; overflow-y: auto; flex: 1; }

.note-item {
  padding: 12px 14px; margin-bottom: 14px; border-radius: 0;
  background: #fff; border: 1px solid var(--line); border-left: 4px solid var(--line);
}
.note-item--yellow { border-left-color: rgba(242, 183, 5, 0.9); }
.note-item--green  { border-left-color: var(--k-accion); }
.note-item--blue   { border-left-color: var(--k-navegacion); }
.note-item--pink   { border-left-color: var(--red); }
.note-item.is-orphan { opacity: 0.72; }

.note-item-quote {
  display: block; width: 100%; text-align: left; border: 0; background: none;
  font: inherit; font-style: italic; color: var(--muted); cursor: pointer;
  padding: 0; margin-bottom: 6px;
}
.note-item-quote:hover { color: var(--ink); text-decoration: underline; }
.note-item.is-orphan .note-item-quote { cursor: default; text-decoration: none; }
.note-item-text { margin: 0 0 8px; white-space: pre-wrap; }
.note-item-orphan { margin: 0 0 8px; color: var(--orange); }
.note-item-actions { display: flex; gap: 10px; }
.note-item-btn {
  border: 0; background: none; cursor: pointer; font: inherit; font-size: 0.82rem;
  color: var(--k-navegacion); padding: 0;
}
.note-item-btn--del { color: var(--red); }

/* Boton de la barra del lector que abre el panel. */
#notesToggle { position: relative; }
.notes-badge {
  position: absolute; top: -6px; right: -6px; min-width: 17px; height: 17px;
  padding: 0 4px; border-radius: 0; background: var(--k-accion); color: #fff;
  font-size: 0.68rem; line-height: 17px; text-align: center;
}
.notes-badge[hidden] { display: none; }

/* Objetivos tactiles. El sitio ya usa 44px en el paginador y en la burbuja; los
   controles de notas se habian quedado en 22px (colores) y ~12px (chincheta),
   que en un dedo no se aciertan. No habia NINGUNA regla @media para .note-bar. */
@media (max-width: 1080px) {
  .note-bar { gap: 10px; padding: 4px; }
  .note-colors .note-swatch { width: 44px; height: 44px; }
  .note-bar-btn { min-height: 44px; padding: 8px 16px; font-size: 1rem; }
  .note-pin { font-size: 1.1em; padding: 6px 8px; }
  .note-item-btn { min-height: 44px; padding: 4px 2px; }
  .notes-panel .modal-close { min-width: 44px; min-height: 44px; }
}

/* Botón de enfoque ("volver a la lectura"): oculto por defecto; solo se muestra
   cuando el usuario se aleja de la palabra activa (read-aloud.js lo alterna con
   .ra-focus--show). Acento amarillo para que resalte del resto de controles. */
.ra-btn.ra-focus { display: none; border-color: var(--amarillo-k); color: #1c2027; background: var(--amarillo-k); }
.ra-btn.ra-focus.ra-focus--show { display: inline-flex; }
.ra-btn.ra-focus:hover { background: var(--amarillo-k); color: #1c2027; filter: brightness(0.94); }
.ra-btn.ra-focus .ra-ico { font-size: 1rem; line-height: 1; }

/* Barra flotante inferior: control de lectura al alcance del pulgar en móvil.
   Fija abajo, respeta la safe-area, y solo aparece en el lector en pantallas
   estrechas (en desktop la barra superior sticky ya cubre estos controles). */
.ra-float {
  position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 6;
  display: none; flex-direction: column; align-items: stretch; gap: 8px;
  padding: 8px; padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
  background: var(--glass); border: 1px solid var(--glass-line); border-radius: var(--radio-k);
box-shadow: var(--shadow);
}
/* Botones de la barra flotante: mismo look pill que en .read-aloud (esos estilos
   están acotados a .read-aloud, así que se replican aquí). */
.ra-float .ra-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  font: inherit; font-weight: 600; cursor: pointer; min-height: 44px; padding: 8px 14px;
  border-radius: var(--radio-k); border: 1px solid var(--azul-k); background: none; color: var(--azul-k);
  transition: background 0.18s var(--ease), color 0.18s var(--ease);
}
.ra-float .ra-btn:hover { background: var(--azul-k); color: #fff; }
.ra-float .ra-btn:focus-visible { outline: 2px solid var(--azul-k); outline-offset: 2px; }
.ra-float .ra-play[aria-pressed="true"] { background: var(--azul-k); color: #fff; }
.ra-float .ra-play .ra-ico { font-size: 0.9rem; line-height: 1; }
/* Enfoque en la flotante: acento amarillo y oculto salvo cuando el usuario se aleja
   (reglas explícitas para ganar sobre .ra-float .ra-btn de arriba). */
.ra-float .ra-focus { display: none; border-color: var(--amarillo-k); color: #1c2027; background: var(--amarillo-k); }
.ra-float .ra-focus.ra-focus--show { display: inline-flex; }
.ra-float .ra-focus:hover { background: var(--amarillo-k); color: #1c2027; filter: brightness(0.94); }
@media (max-width: 1080px) {
  .ra-float { display: flex; }
  /* Deja aire al final para que la barra flotante no tape los controles finales. */
  body.course-reader .reader-main { padding-bottom: 84px; }
}
/* Oculta la barra flotante mientras se escribe en un campo (chat/autoevaluación). */
.ra-float.ra-float--hidden { display: none !important; }

@media (prefers-reduced-motion: reduce) { .reader-page { animation: none; } .reader-pager .rp-dot::before { transition: none; } }

/* Pantalla de fin de curso ("el plano completo") */
.k-done-screen {
  position: relative; z-index: 2; margin: 30px 0; padding: 40px 28px; text-align: center;
  border: 1px solid var(--linea-k); border-radius: var(--radio-k); background: #fff;
}
.k-done-screen.hidden { display: none; }
.k-done-screen h2 { font-family: var(--f-display); font-size: 1.6rem; margin: 0 0 6px; }
.k-done-screen p { color: var(--muted); max-width: 46ch; margin: 0 auto 20px; }
.k-done-screen .k-map { justify-content: center; gap: 6px; max-width: 520px; margin: 0 auto 24px; }
.k-done-cta {
  display: inline-block; background: var(--rojo-k); color: #fff; font-weight: 600;
  padding: 12px 22px; border-radius: var(--radio-k); text-decoration: none;
}

@media (prefers-reduced-motion: reduce) {
  .course-body .k-line-fill, .course-body .k-pt,
  .course-body .course-card, .course-body .course-card-glyph svg { transition: none !important; }
}


/* ============================================================ */
/* El Taller interactivo v2 (course-worksheet.js · Módulo III)  */
/* Manipulación directa: chips, arrastrar-soltar, tarjetas que  */
/* giran, torno, demoler, rueda-acordeón. Tokens Kandinsky.     */
/* ============================================================ */
.ws-block { position: relative; z-index: 2; margin: 1.4em 0; padding: 18px 18px 22px;
  border: 1px solid var(--linea-k); border-left: 4px solid var(--orange); border-radius: 0; background: var(--paper); }
.ws-eyebrow { font-family: var(--f-display); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; font-size: 0.72rem; color: var(--orange); }
.ws-title { font-family: var(--f-display); font-weight: 600; font-size: 1.2rem; margin: 2px 0 14px; color: var(--ink); }
.ws-h4 { font-family: var(--f-display); font-weight: 600; font-size: 1.02rem; margin: 18px 0 4px; color: var(--ink); }
.ws-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.ws-form { display: flex; flex-direction: column; gap: 14px; }
.ws-label { font-weight: 600; font-size: 0.95rem; color: var(--ink); }
.ws-hint { margin: 0; font-size: 0.85rem; color: var(--muted); }
.ws-field { display: flex; flex-direction: column; gap: 6px; }
.ws-input { width: 100%; box-sizing: border-box; font: inherit; font-size: 0.95rem; color: var(--ink);
  background: #fff; border: 1px solid var(--linea-k); border-radius: 0; padding: 9px 11px; resize: vertical; }
.ws-input:focus { border-color: var(--azul-k); outline: none; }
.ws-add { align-self: flex-start; font: inherit; font-size: 0.88rem; font-weight: 600; color: var(--azul-k);
  background: none; border: 1px dashed var(--linea-k); border-radius: 0; padding: 6px 12px; cursor: pointer; }
.ws-add:hover { border-color: var(--azul-k); background: var(--lienzo-hover); }
.ws-addrow { display: flex; gap: 8px; flex-wrap: wrap; }
.ws-addrow .ws-input { flex: 1; min-width: 160px; }

/* chips arrastrables / tomar-y-colocar */
.ws-chip { font: inherit; font-size: 0.9rem; cursor: grab; padding: 7px 13px; border-radius: 0;
  border: 1px solid var(--linea-k); background: #fff; color: var(--ink); text-align: left;
  transition: border-color var(--t-rapido), background var(--t-rapido), transform var(--t-rapido); }
.ws-chip:hover { border-color: var(--azul-k); }
.ws-chip.is-grabbed { border-color: var(--rojo-k); background: rgba(24, 117, 71,0.08); box-shadow: 0 0 0 2px rgba(24, 117, 71,0.25); cursor: grabbing; }
.ws-chip.is-nature { border-color: var(--verde-check); }
.ws-palette, .ws-pool { display: flex; flex-wrap: wrap; gap: 8px; padding: 4px 0; }

/* zonas de drop */
.ws-drop { border: 2px dashed var(--linea-k); border-radius: 0; background: rgba(255,255,255,0.5); transition: border-color var(--t-rapido), background var(--t-rapido); }
.ws-drop.is-over { border-color: var(--azul-k); background: var(--lienzo-hover); }
.ws-drop:focus-visible { outline: 2px solid var(--azul-k); outline-offset: 2px; }

/* 205 — tablero de análogos */
.ws-board { display: flex; flex-direction: column; gap: 10px; }
.ws-slotrow { display: grid; grid-template-columns: minmax(140px, 220px) 1fr; gap: 10px; align-items: stretch; }
.ws-slot { display: flex; align-items: center; gap: 8px; padding: 10px; min-height: 48px; }
.ws-slot-n { display: inline-grid; place-items: center; width: 22px; height: 22px; border-radius: 0;
  background: var(--azul-k); color: #fff; font-weight: 700; font-size: 0.8rem; flex: 0 0 auto; }
.ws-slot-chip { flex: 1; min-height: 24px; display: flex; }
.ws-natflag { font-weight: 700; color: var(--verde-check); }
.ws-natline { margin: 2px 0 0; min-height: 1.2em; }
.ws-distill { line-height: 2.1; }
.ws-domword { font: inherit; cursor: pointer; padding: 2px 6px; border-radius: 0; border: 1px solid var(--linea-k);
  background: #fff; color: var(--ink); }
.ws-domword:hover { border-color: var(--rojo-k); }
.ws-domword.is-peeled { text-decoration: line-through; color: var(--muted); background: var(--lienzo-hover); opacity: 0.55; }
.ixs-replay { margin-top: 6px; }

/* tarjetas que giran (206) */
.ws-deck { display: flex; flex-direction: column; gap: 10px; }
.ws-flipcard { perspective: 900px; }
.ws-flip-inner { position: relative; transition: transform 500ms var(--ease); transform-style: preserve-3d; min-height: 64px; }
.ws-flipcard.is-flipped .ws-flip-inner { transform: rotateY(180deg); }
.ws-flip-face { border: 1px solid var(--linea-k); border-radius: 0; padding: 10px 12px; background: #fff;
  backface-visibility: hidden; -webkit-backface-visibility: hidden; display: flex; flex-direction: column; gap: 6px; }
.ws-flip-back { position: absolute; inset: 0; transform: rotateY(180deg); background: rgba(24, 117, 71,0.05); border-color: var(--rojo-k); }
.ws-flip-front { position: relative; }
.ws-flip-hero .ws-flip-front { background: rgba(43,93,168,0.06); border-color: var(--azul-k); }
.ws-flip-tag { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--azul-k); }
.ws-flip-tag.ws-tag-danger { color: var(--rojo-k); }
.ws-flip-btn { align-self: flex-start; font: inherit; font-size: 0.82rem; font-weight: 600; color: var(--azul-k);
  background: none; border: 1px solid var(--linea-k); border-radius: 0; padding: 5px 10px; margin-top: 6px; cursor: pointer; }
.ws-flip-btn:hover { border-color: var(--azul-k); }
.ws-invert-btn { align-self: flex-start; }
/* medidor de sabotaje */
.ws-meter-wrap { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ws-meter-lbl { font-size: 0.85rem; color: var(--muted); }
.ws-meter { position: relative; flex: 1; min-width: 140px; height: 10px; border-radius: 0; background: var(--linea-k); overflow: hidden; }
.ws-meter-fill { display: block; height: 100%; width: 0; background: var(--rojo-k); transition: width var(--t-recompensa); }
.ws-meter.is-full .ws-meter-fill { background: var(--verde-check); }

/* 207 — el torno */
.ws-limchips, .ws-wheel-tools { display: flex; flex-wrap: wrap; gap: 8px; }
.ws-limchip { font: inherit; font-size: 0.9rem; cursor: pointer; padding: 7px 13px; border-radius: 0;
  border: 1px solid var(--linea-k); background: #fff; color: var(--ink); }
.ws-limchip:hover { border-color: var(--azul-k); }
.ws-limchip.is-on { background: var(--amarillo-k); border-color: var(--amarillo-k); color: var(--ink); font-weight: 600; }
.ws-vise { position: relative; display: flex; align-items: stretch; gap: 0; margin: 6px 0; }
.ws-vise-inner { flex: 1; border: 2px solid var(--amarillo-k); border-radius: 0; padding: 12px; background: rgba(242,183,5,0.06);
  display: flex; flex-direction: column; gap: 6px; transition: max-width var(--t-recompensa), margin var(--t-recompensa); max-width: 100%; margin: 0 auto; }
.ws-vise-jaw { width: 10px; align-self: stretch; background: repeating-linear-gradient(45deg, var(--linea-k) 0 4px, transparent 4px 8px); border-radius: 3px; }
.ws-vise[data-level="a"] .ws-vise-inner { max-width: 78%; }
.ws-vise[data-level="b"] .ws-vise-inner { max-width: 58%; }
.ws-vise[data-level="c"] .ws-vise-inner { max-width: 40%; }

/* 208 — clasificar + demoler */
.ws-bins { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.ws-bin { padding: 10px; min-height: 96px; }
.ws-bin-h { display: flex; align-items: center; gap: 6px; font-weight: 700; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 8px; }
.ws-bin-ley { border-color: var(--linea-k); background: rgba(20,22,26,0.03); }
.ws-bin-ley .ws-bin-h { color: var(--muted); }
.ws-bin-hab { border-color: var(--rojo-k); background: rgba(24, 117, 71,0.04); }
.ws-bin-hab .ws-bin-h { color: var(--rojo-k); }
.ws-bin-body { display: flex; flex-direction: column; gap: 8px; }
.ws-bin-ley .ws-chip { border-color: var(--linea-k); }
.ws-habwrap { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; transition: opacity var(--t-rapido); }
.ws-habwrap .ws-chip { border-color: var(--rojo-k); }
.ws-demolish { font: inherit; font-size: 0.8rem; font-weight: 600; cursor: pointer; padding: 5px 10px; border-radius: 0;
  border: 1px solid var(--rojo-k); background: var(--rojo-k); color: #fff; }
.ws-demolish:disabled { background: var(--verde-check); border-color: var(--verde-check); cursor: default; }
.ws-habwrap.is-demolished .ws-chip { text-decoration: line-through; opacity: 0.5; transform: rotate(-1.5deg); }
.ws-recon { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.ws-reconrow { display: flex; flex-direction: column; gap: 4px; padding: 8px 10px; border-left: 3px solid var(--verde-check); background: rgba(46,125,79,0.05); border-radius: 0; }
.ws-recon-q { font-weight: 600; color: var(--ink); font-size: 0.9rem; }

/* 209 — rueda + acordeón */
.ws-accordion { display: flex; flex-direction: column; gap: 6px; }
.ws-acc-item { border: 1px solid var(--linea-k); border-radius: 0; overflow: hidden; }
.ws-acc-h { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; font: inherit; cursor: pointer;
  padding: 10px 12px; background: #fff; border: none; color: var(--ink); }
.ws-acc-h:hover { background: var(--lienzo-hover); }
.ws-acc-h.is-open { background: var(--lienzo-hover); }
.ws-acc-h.is-done { background: rgba(46,125,79,0.06); }
.ws-acc-p { padding: 4px 12px 12px; display: flex; flex-direction: column; gap: 6px; }
.ws-acc-q { margin: 0; font-size: 0.88rem; color: var(--muted); }
.ws-scamper-k { display: inline-grid; place-items: center; width: 26px; height: 26px; flex: 0 0 auto;
  font-family: var(--f-display); font-weight: 700; color: #fff; background: var(--azul-k); border-radius: 0; }
.ws-scamper-v { font-weight: 600; color: var(--ink); }
.ws-pip { width: 12px; height: 12px; flex: 0 0 auto; border-radius: 0; border: 2px solid var(--linea-k);
  background: transparent; transition: background var(--t-rapido), border-color var(--t-rapido); }
.ws-pip.is-done { background: var(--verde-check); border-color: var(--verde-check); }

/* acciones */
.ws-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 20px; }
.ws-block .btn { padding: 9px 16px; border-radius: var(--radio-k); font-size: 0.9rem; border: none; cursor: pointer; font: inherit; font-weight: 600; }
.ws-jp { background: var(--rojo-k); color: #fff; }
.ws-jp:hover { filter: brightness(1.05); }
.ws-block .btn.ghost { background: #fff; border: 1px solid var(--linea-k); color: var(--ink); }
.ws-block .btn.ghost:hover { border-color: var(--azul-k); color: var(--azul-k); }
.ws-actions-note { color: var(--muted); flex-basis: 100%; }

/* micro-quiz */
.ix-quiz { margin: 0 0 16px; padding: 14px 16px; background: var(--lienzo-hover); border-radius: 0; }
.ix-quiz-prompt { margin: 0 0 10px; font-weight: 600; color: var(--ink); }
.ix-quiz-item { margin: 0 0 12px; }
.ix-quiz-item:last-child { margin-bottom: 0; }
.ix-quiz-q { margin: 0 0 7px; color: var(--ink); }
.ix-quiz-opts { display: flex; flex-wrap: wrap; gap: 8px; }
.ix-quiz-opt { font: inherit; font-size: 0.88rem; cursor: pointer; padding: 6px 14px; border-radius: 0;
  border: 1px solid var(--linea-k); background: #fff; color: var(--ink); transition: border-color var(--t-rapido), background var(--t-rapido); }
.ix-quiz-opt:hover:not(:disabled) { border-color: var(--azul-k); }
.ix-quiz-opt:disabled { cursor: default; opacity: 0.9; }
.ix-quiz-opt.is-correct { background: var(--verde-check); border-color: var(--verde-check); color: #fff; }
.ix-quiz-opt.is-wrong { background: var(--rojo-k); border-color: var(--rojo-k); color: #fff; }
.ix-quiz-fb { margin: 7px 0 0; font-size: 0.86rem; color: var(--muted); display: none; }
.ix-quiz-fb.show { display: block; }

/* figura SVG */
.ix-svg { margin: 0 0 12px; text-align: center; }
.ix-svg-box { display: inline-block; max-width: 100%; }
.ix-svg-box svg { max-width: 100%; height: auto; }
.ix-svg-cap { margin: 8px auto 0; max-width: 52ch; font-size: 0.84rem; color: var(--muted); }
.ixs text { font-family: var(--f-cuerpo, 'Inter', sans-serif); font-size: 11px; fill: var(--ink); }
.ixs-panel-t { font-weight: 700; }
.ixs-target { fill: var(--ink); }
.ixs-ray { stroke-width: 2.5; stroke-linecap: round; stroke-dasharray: 46; stroke-dashoffset: 0; }
.ixs-wheel-hub { fill: #fff; stroke: var(--linea-k); stroke-width: 2; }
.ixs-wheel-n { font-family: var(--f-display); font-weight: 700; font-size: 13px; fill: var(--ink); }
.ixs-wheel-l { font-size: 8px; fill: var(--muted); letter-spacing: 0.08em; }
.ixs-wheel.is-complete .ixs-wheel-hub { stroke: var(--verde-check); }
.ixs-verb { cursor: pointer; }
.ixs-verb circle { fill: #fff; stroke: var(--linea-k); stroke-width: 2; transition: fill var(--t-rapido), stroke var(--t-rapido); }
.ixs-verb text { font-family: var(--f-display); font-weight: 700; fill: var(--muted); font-size: 13px; }
.ixs-verb.is-done circle { fill: var(--verde-check); stroke: var(--verde-check); }
.ixs-verb.is-done text { fill: #fff; }
.ixs-verb.is-hint circle { stroke: var(--rojo-k); stroke-width: 3; }
.ixs-verb:focus-visible circle { stroke: var(--azul-k); stroke-width: 3; }

/* movimiento (solo si el usuario lo permite) */
@media (prefers-reduced-motion: no-preference) {
  .ix-svg-box:not(.reduce) .ixs-rays[data-play="1"] .ixs-ray { stroke-dashoffset: 46; animation: ixs-converge 1200ms var(--ease) forwards; }
}
@keyframes ixs-converge { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) {
  .ws-flip-inner, .ws-vise-inner, .ws-meter-fill, .ws-chip, .ixs-verb circle { transition: none !important; }
}

/* responsive */
@media (max-width: 640px) {
  .ws-slotrow { grid-template-columns: 1fr; }
  .ws-bins { grid-template-columns: 1fr; }
  .ws-vise[data-level="a"] .ws-vise-inner,
  .ws-vise[data-level="b"] .ws-vise-inner,
  .ws-vise[data-level="c"] .ws-vise-inner { max-width: 100%; }
}

/* impresión: solo la hoja */
@media print {
  .ws-printing body * { visibility: hidden !important; }
  .ws-printing .ws-print-target, .ws-printing .ws-print-target * { visibility: visible !important; }
  .ws-printing .ws-print-target { position: absolute; left: 0; top: 0; width: 100%; border: none; }
  .ws-printing .ws-actions, .ws-printing .ix-quiz { display: none !important; }
  .ws-print-target .ws-input { border: 1px solid #999; }
}

/* =====================================================================
   Food Safety Handbook — listas de verificación y bitácoras
   ===================================================================== */

/* Tablas anchas (almacenamiento, temperaturas): el contenedor se desplaza,
   nunca el cuerpo de la página. */
.reader-content .table-scroll { overflow-x: auto; margin: 1.2em 0; -webkit-overflow-scrolling: touch; }
.reader-content .table-scroll .course-table { margin: 0; min-width: 480px; }
.reader-content .course-table td:first-child { min-width: 180px; }

/* Listas de verificación de fin de capítulo. Son casillas reales para que se
   puedan marcar al recorrer el turno; no persisten (son de un solo uso). */
.fs-checklist { list-style: none; margin: 0; padding: 0; }
.fs-checklist li { position: relative; padding: 4px 0 4px 30px; line-height: 1.5; }
.fs-checklist li::before {
  content: ""; position: absolute; left: 0; top: 8px;
  width: 15px; height: 15px; border: 1.5px solid var(--line);
  border-radius: 3px; background: var(--paper);
}
.fs-checklist li:hover::before { border-color: var(--blue); }

/* Bitácoras del C12. Sin JS queda la tabla estática imprimible; course-logs.js
   la convierte en un formulario rellenable. */
.fs-log { margin: 1.2em 0; }
.fs-log-input {
  width: 100%; box-sizing: border-box; border: none; background: transparent;
  font: inherit; color: inherit; padding: 2px 0; min-width: 60px;
}
.fs-log-input:focus { outline: 2px solid var(--blue); outline-offset: 1px; border-radius: 2px; }
.fs-log-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; align-items: center; }
.fs-log-btn {
  font: inherit; font-size: .88rem; padding: 6px 12px; cursor: pointer;
  border: 1px solid var(--line); border-radius: 0;
  background: var(--paper); color: var(--ink);
}
.fs-log-btn:hover { border-color: var(--blue); color: var(--blue); }
.fs-log-status { font-size: .82rem; color: var(--muted); }

@media print {
  .fs-log-actions { display: none !important; }
  .fs-log-input { border-bottom: 1px solid #999; }
  .reader-content .table-scroll { overflow: visible; }
}

/* Enlace a la casa matriz (pie de pagina y eyebrow de /company/).
   Sin esto hereda el estilo de enlace por defecto del navegador —subrayado
   azul— que canta en un pie de pagina apagado. Hereda el color del contenedor
   y solo marca el subrayado, para que se note que es clicable sin gritar. */
.brand-parent {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
  text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
  transition: color 0.3s var(--ease), text-decoration-color 0.3s var(--ease);
}
.brand-parent:hover,
.brand-parent:focus-visible {
  color: var(--green);
  text-decoration-color: currentColor;
}

/* ============================================================
   Biblioteca filtrable (/course/ y /course/categoria/<slug>/)
   Panel lateral de facetas + rejilla. El filtrado lo hace
   assets/library.js ocultando tarjetas: aquí solo vive el layout.
   ============================================================ */

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* El atributo `hidden` NO puede contra un `display` de autor: la regla
   [hidden]{display:none} vive en la hoja del navegador y cualquier declaración
   de esta hoja le gana, tenga la especificidad que tenga. Como .course-card,
   .lf-group y .library-empty declaran display, hay que decirlo explícitamente
   o library.js marca las tarjetas como ocultas y se siguen viendo todas.
   Es el mismo patrón que .course-pill[hidden] y .reader-page[hidden] de arriba.
   Nada de una regla [hidden] global con !important: .reader-pager .rp-prev[hidden]
   usa display:inline-block a propósito para conservar su hueco. */
.course-card[hidden],
.library-empty[hidden],
.lf-group[hidden] { display: none !important; }

/* Ruta de migas de la página de categoría */
.crumbs {
  position: relative; z-index: 2; display: flex; gap: 8px; align-items: center;
  font-size: 0.85rem; color: var(--muted); margin: 4px 0 2px;
}
.crumbs a { color: var(--muted); text-decoration: none; }
.crumbs a:hover, .crumbs a:focus-visible { color: var(--green); text-decoration: underline; }

/* Altos de referencia de la página de biblioteca. El panel, el contenido y el
   pie los calculan a partir de aquí: cambiar la nav es cambiar una línea. */
body.course-library-body {
  --lib-nav-h: 76px;
  --lib-foot-h: 44px;
  /* `clip` recorta igual que el `overflow-x: hidden` global de html/body, pero
     NO crea un contenedor de scroll. Con `hidden`, body se vuelve su propio
     scroller y el `position: sticky` del panel deja de pegarse: se va con la
     página. Este es el arreglo, y por eso está acotado a esta página. */
  overflow-x: clip;
}

/* La nav se queda arriba, como en la referencia: es el tope contra el que se
   clava el panel. */
body.course-library-body .nav-bar {
  position: sticky; top: 0; z-index: 40;
  padding: 14px 0;
}
/* Aqui la nav va pegada arriba y acompana todo el scroll del catalogo, asi que
   el logo se queda en 38px en vez de 48: la diferencia son 10px de alto que en
   una pagina de navegacion se los come el listado, no la marca. */
body.course-library-body .mark-logo img { height: 38px; }
/* La nav vive dentro del .wrap centrado, así que su fondo se cortaría a 1120px
   y las tarjetas se verían pasar por los lados al hacer scroll. Este pseudo lo
   estira a todo el ancho de la ventana sin sacar la nav de su contenedor. */
body.course-library-body .nav-bar::before {
  content: ""; position: absolute; inset: 0 calc(50% - 50vw); z-index: -1;
  background: var(--ink);
}

/* Rejilla a ancho completo: el panel es un raíl izquierdo, no una columna
   flotando dentro del contenedor centrado. */
.library-layout {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: 268px minmax(0, 1fr);
  align-items: start;
}

/* --- panel de facetas --- */
.library-filters {
  position: sticky; top: var(--lib-nav-h);
  height: calc(100dvh - var(--lib-nav-h) - var(--lib-foot-h));
  display: flex; flex-direction: column; gap: 18px;
  padding: 20px 18px 26px; overflow-y: auto;
  background: var(--glass); border-right: 1px solid var(--glass-line);
}

/* La columna derecha es un panel de altura fija, igual que el raíl de filtros:
   el título y la barra de resultados quedan clavados arriba y lo único que
   scrollea es la rejilla de libros. */
.library-main {
  min-width: 0;
  height: calc(100dvh - var(--lib-nav-h) - var(--lib-foot-h));
  display: flex; flex-direction: column;
  padding: 20px clamp(16px, 4vw, 40px) 0;
  overflow: hidden;
}
.library-main > .course-hero--library,
.library-main > .lf-results { flex: 0 0 auto; }
.library-main > .course-library,
.library-main > .library-empty {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  padding-bottom: calc(var(--lib-foot-h) + 36px);
}
/* Las tarjetas llevan overflow:hidden (para el borde redondeado y la barra de
   acento), así que como ítems de grid su mínimo automático es 0. Con la rejilla
   a altura fija (es flex:1 dentro del panel), el grid repartiría esa altura
   entre las filas y las aplastaría por debajo de su contenido en vez de
   desbordar. max-content fija cada fila a su contenido: así se ven enteras y la
   zona hace scroll. */
.library-main > .course-library { grid-auto-rows: max-content; align-content: start; }

/* La página de categoría no lleva panel: una sola columna, pero con la misma
   tarjeta y el mismo respiro que la biblioteca. */
.library-layout--cat { grid-template-columns: minmax(0, 1fr); }
.library-layout--cat .library-main { max-width: 1120px; margin: 0 auto; width: 100%; }
.lead--cat { max-width: 640px; }
.lf-head h2 { margin: 0; font-size: 1rem; letter-spacing: -0.01em; }
.lf-total { margin: 2px 0 0; font-size: 0.8rem; color: var(--muted); }

.lf-search input {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 0.9rem;
  padding: 9px 12px; border-radius: 0; color: var(--ink);
  border: 1px solid var(--line); background: rgba(255, 255, 255, 0.7);
}
.lf-search input:focus-visible { outline: 2px solid var(--green); outline-offset: 1px; }

.lf-group { display: flex; flex-direction: column; gap: 7px; }
.lf-group h3 {
  margin: 0 0 2px; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted);
}
.lf-opt {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 8px;
  font-size: 0.88rem; line-height: 1.3; cursor: pointer; padding: 3px 0;
}
.lf-opt input { accent-color: var(--green); width: 15px; height: 15px; margin: 0; cursor: pointer; }
.lf-opt:hover span { color: var(--green); }
.lf-opt b { font-weight: 500; font-size: 0.76rem; color: var(--muted); font-variant-numeric: tabular-nums; }

.lf-actions { margin-top: 2px; }
.lf-clear {
  font: inherit; font-size: 0.85rem; font-weight: 600; cursor: pointer;
  padding: 8px 14px; border-radius: 0; color: var(--ink);
  background: rgba(255, 255, 255, 0.6); border: 1px solid var(--line);
}
.lf-clear:hover { border-color: var(--green); color: var(--green); }

/* --- cabecera de resultados --- */
.lf-results {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  flex-wrap: wrap; margin: 0 0 14px;
}
.lf-count { margin: 0; font-size: 0.9rem; font-weight: 600; color: var(--muted); }
.lf-count--static { position: relative; z-index: 2; margin: 0 0 14px; }
.lf-sort select {
  font: inherit; font-size: 0.85rem; padding: 7px 10px; border-radius: 0;
  color: var(--ink); border: 1px solid var(--line); background: rgba(255, 255, 255, 0.7); cursor: pointer;
}
.lf-sort select:focus-visible { outline: 2px solid var(--green); outline-offset: 1px; }

.library-empty {
  position: relative; z-index: 2; text-align: center; padding: 40px 20px;
  color: var(--muted); display: flex; flex-direction: column; align-items: center; gap: 14px;
}

/* --- píldora de categoría en la tarjeta --- */
.course-card-cat {
  align-self: flex-start;
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-size: var(--t-xs); font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--card-accent); background: var(--card-ink);
  padding: 3px 9px; border-radius: 0;
}

/* --- la tarjeta en la biblioteca: una por fila, en horizontal ---
   Misma anatomía que la referencia (icono · contenido · acción). Fuera de la
   biblioteca (si algún día se reutiliza la tarjeta) sigue siendo la vertical. */
.library-main .course-library { grid-template-columns: 1fr; gap: 12px; padding-bottom: 8px; }
.library-main .course-card {
  display: grid; grid-template-columns: 46px minmax(0, 1fr) auto;
  gap: 18px; align-items: center; padding: 16px 20px;
}
.library-main .cc-body { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.library-main .cc-side {
  display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
  text-align: right; flex: 0 0 auto;
}
.library-main .course-card-summary {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.library-main .course-card-cta { margin-top: 0; padding-top: 0; white-space: nowrap; }
.library-main .course-card-progress { margin-top: 0; width: 140px; }

@media (max-width: 620px) {
  /* En teléfono la columna de la derecha no cabe: vuelve a apilarse. */
  .library-main .course-card { grid-template-columns: 40px minmax(0, 1fr); gap: 14px; }
  .library-main .cc-side {
    grid-column: 1 / -1; flex-direction: row; align-items: center;
    justify-content: space-between; text-align: left; width: 100%;
  }
  .library-main .course-card-progress { width: auto; flex: 1; }
}

/* --- enlaces entre categorías --- */
.cat-nav { position: relative; z-index: 2; margin: 30px 0 10px; }
.cat-nav h2 { font-size: 1rem; margin: 0 0 12px; }
.cat-nav-links { display: flex; flex-wrap: wrap; gap: 10px; }
.cat-nav-links a {
  display: inline-flex; align-items: center; gap: 7px; text-decoration: none;
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-size: var(--t-xs); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink);
  padding: 8px 14px; border-radius: 0;
  background: var(--paper); border: 2px solid var(--ink); border-left-width: 8px;
}
.cat-nav-links a:hover, .cat-nav-links a:focus-visible { color: var(--paper); background: var(--ink); }
.cat-nav-links a b { font-weight: 500; font-size: 0.72rem; opacity: 0.7; }
.cat-nav-links .cat-nav-all { border-left-width: 2px; }

/* --- botón flotante, solo móvil --- */
.library-filter-toggle {
  display: none; position: fixed; right: 16px; bottom: 16px; z-index: 40;
  font: inherit; font-size: 0.9rem; font-weight: 600; cursor: pointer; gap: 6px;
  padding: 12px 18px; border-radius: 0; color: #fff; background: var(--green);
  border: 0; box-shadow: var(--shadow);
}

/* --- hero compacto: el manifiesto vive dentro de un desplegable ---
   El texto sigue en el HTML (Google lo indexa igual), pero deja de empujar la
   biblioteca fuera de la pantalla. Mismo lenguaje visual que .course-howto. */
/* Título más contenido que en el resto del sitio: cada píxel de hero es un
   píxel que empuja la primera tarjeta fuera de la pantalla. */
.course-hero--library { margin: 4px 0 16px; }
.course-hero--library h1 { font-size: clamp(1.8rem, 3.4vw, 2.6rem); }
.course-hero--library .course-subtitle { font-size: clamp(0.95rem, 1.4vw, 1.1rem); }
.course-intro {
  margin-top: 10px; border: 1px solid var(--line); border-radius: 0;
  background: rgba(18, 38, 30, 0.03); overflow: hidden; max-width: 640px;
}
.course-intro > summary {
  cursor: pointer; list-style: none; padding: 9px 14px; font-size: 0.88rem; font-weight: 600;
  color: var(--muted); display: flex; align-items: center; gap: 9px; user-select: none;
}
.course-intro > summary::-webkit-details-marker { display: none; }
.course-intro > summary::before {
  content: "▸"; color: var(--green); transition: transform 0.2s var(--ease); flex: 0 0 auto;
}
.course-intro[open] > summary::before { transform: rotate(90deg); }
.course-intro > summary:hover { background: rgba(24, 117, 71, 0.05); color: var(--ink); }
.course-intro .lead { margin: 0; padding: 0 14px 12px; font-size: 0.9rem; }

/* El hero vive dentro de .library-main (columna derecha de la rejilla), así que
   solo hay sitio para poner "¿Qué es esto?" a la derecha del título cuando la
   ventana es ancha. Por debajo de 1200px se apila bajo el título. */
@media (min-width: 1200px) {
  .course-hero--library {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 440px);
    grid-template-areas:
      "eyebrow  intro"
      "title    intro"
      "subtitle intro";
    align-items: start;
    column-gap: clamp(24px, 4vw, 48px);
    max-width: none;
  }
  .course-hero--library .eyebrow         { grid-area: eyebrow; }
  .course-hero--library h1               { grid-area: title; }
  .course-hero--library .course-subtitle { grid-area: subtitle; }
  .course-hero--library .course-intro {
    grid-area: intro;
    margin-top: 0;
    align-self: start;
    max-width: none;
    justify-self: end;
  }
}

/* --- pie fijo abajo, como el de la referencia --- */
body.course-library-body .foot {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  height: var(--lib-foot-h); margin: 0; padding: 0 clamp(16px, 4vw, 40px);
  background: rgba(244, 241, 234, 0.92); border-top: 1px solid var(--line);
  font-size: 0.78rem; overflow: hidden; flex-wrap: nowrap;
}
/* El copyright es nowrap y en una pantalla estrecha se salía del pie. Se
   encoge la tipografía en vez de recortarlo: así no se pierde el punto de
   acceso al admin, que va pegado al final de esa línea (footer.php). */
@media (max-width: 620px) {
  body.course-library-body .foot { font-size: 0.66rem; }
}

@media (max-width: 900px) {
  body.course-library-body { --lib-nav-h: 64px; }
  .library-layout { grid-template-columns: minmax(0, 1fr); }
  .library-filters {
    position: fixed; top: var(--lib-nav-h); bottom: 0; left: 0; right: auto;
    z-index: 61; width: min(300px, 86vw); height: auto;
    border-right: 1px solid var(--glass-line); border-radius: 0;
    transform: translateX(-102%); transition: transform 0.28s var(--ease);
    background: rgba(255, 255, 255, 0.96);
  }
  .library-filters.is-open { transform: none; }
  .library-filter-toggle { display: inline-flex; align-items: center; }
  /* En móvil la página scrollea normal: se anula el panel de altura fija para
     que no quede la columna comprimida con scroll anidado. */
  .library-main {
    display: block; height: auto; overflow: visible;
    padding-left: 16px; padding-right: 16px;
    padding-bottom: calc(var(--lib-foot-h) + 36px);
  }
  .library-main > .course-library,
  .library-main > .library-empty { overflow: visible; padding-bottom: 0; }
  /* El botón flotante se sube para no chocar con el pie fijo. */
  .library-filter-toggle { bottom: calc(var(--lib-foot-h) + 14px); }
}

@media (prefers-reduced-motion: reduce) {
  .library-filters { transition: none; }
}

/* ============================================================
   Merch (escaparate de Printify)
   ============================================================
   La rejilla se reutiliza tal cual: .course-library ya es
   repeat(auto-fill, minmax(300px, 1fr)) y sirve igual para productos.

   Lo que NO se reutiliza es .course-card. Esa es un bloque de tinta a sangre
   con semitono y un --card-ink calculado por luminancia desde PHP: una portada
   para libros que no tienen portada. Un producto SI tiene imagen, y lo que
   necesita es un hueco donde ponerla. De ahi una tarjeta propia, con el mismo
   idioma del poster: filete de 2px, sombra dura, esquinas rectas, cero blur. */
/* Antetitulo de la cabecera de /merch/. Iba en .merch-hero, que es el nombre
   del bloque CTA de la portada: al compartirlo, esta cabecera heredaba su
   display:inline-flex y su animacion de entrada. Ahora cada uno tiene el suyo. */
.merch-head .eyebrow {
  display: inline-block;
  font-size: 0.78rem; letter-spacing: var(--tracking-wide); text-transform: uppercase;
  color: var(--blue); margin-bottom: 8px; font-weight: 700;
}

.merch-card {
  display: flex; flex-direction: column;
  background: var(--paper); color: var(--ink);
  border: 2px solid var(--ink); border-radius: 0;
  box-shadow: var(--shadow);
  overflow: hidden;
  /* Se anima transform Y box-shadow, a proposito.
     Probe a sacar la sombra a una capa aparte para mover solo transforms, pero
     .merch-card lleva overflow:hidden y esa capa quedaba RECORTADA dentro de la
     tarjeta: la sombra desaparecia. Un box-shadow es la unica forma de dibujar
     fuera de la caja sin quitar el recorte.
     El coste real es despreciable: solo se anima la tarjeta bajo el cursor, una
     cada vez, no las veinte de la rejilla. Lo que si habia que evitar --- y se
     evita--- es animar algo asi en bucle y en todas a la vez, que es lo que hace
     el carrusel, y ese va con opacidad pura. */
  transition: transform 0.32s var(--ease), box-shadow 0.32s var(--ease);
}
.merch-card:hover { transform: translate(-4px, -4px); box-shadow: 9px 9px 0 var(--ink); }

/* aspect-ratio fija el alto ANTES de que cargue la imagen: sin esto la rejilla
   da un salto (CLS) cuando entran las fotos. El fondo crema es la otra mitad
   del truco: las imagenes se enlazan en caliente desde el CDN de Printify, asi
   que si una URL caduca lo que se ve es un bloque de color, no el icono de
   imagen rota del navegador. */
/* object-fit: contain y no cover. Los mockups de Printify ya vienen cuadrados y
   con el producto centrado; recortarlos cortaba justo los bordes de la camiseta
   o el asa de la taza. Con contain se ve el producto ENTERO, y el hueco que
   sobra queda del color del papel, que es exactamente lo que se quiere. */
/* El marco cuadrado ahora es el BOTON, no la imagen: dentro se apilan dos capas
   para poder cruzarlas, y necesitan un contenedor con tamano propio.
   Como todas las columnas miden lo mismo, aspect-ratio 1:1 deja todas las fotos
   exactamente del mismo tamano y las filas cuadradas. */
.merch-card-imgbtn {
  position: relative; display: block; width: 100%; padding: 0;
  aspect-ratio: 1 / 1;
  border: 0; border-bottom: 2px solid var(--ink);
  background: var(--paper-2);
  cursor: zoom-in; font: inherit; line-height: 0;
}
/* object-fit: contain y no cover: se prefiere una franja del color del papel
   antes que recortarle el asa a una taza. */
.merch-card-img {
  position: absolute; inset: 0;
  display: block; width: 100%; height: 100%; object-fit: contain;
  padding: 6px;
  opacity: 0;
  /* --step (steps(4,end)) es el token del sitio para "movimiento mecanico, no
     organico": el cruce ocurre en cuatro fotogramas y se lee como un cambio de
     vineta impresa, no como el fundido suave de una presentacion.
     Solo opacidad: sin layout y sin repintado. */
  transition: opacity 0.36s var(--step);
}
.merch-card-img.is-on { opacity: 1; }
.merch-card-img--empty { display: block; }

.merch-card-body { display: flex; flex-direction: column; gap: 8px; padding: 18px; flex: 1; }
.merch-card-title {
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-size: 1.05rem; font-weight: 700; line-height: 1.2; margin: 0;
  letter-spacing: var(--tracking-tight);
}
.merch-card-blurb { margin: 0; color: var(--muted); font-size: var(--t-sm); line-height: 1.5; }
.merch-card-opts { margin: 0; color: var(--muted); font-size: var(--t-xs); }
.merch-card-price {
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-weight: 800; font-size: 1.15rem; color: var(--vermillion-ink);
}
.merch-card-foot { margin-top: auto; padding-top: 12px; display: flex; flex-direction: column; gap: 8px; }

.merch-sold-out {
  display: inline-block; align-self: flex-start;
  font-size: var(--t-xs); text-transform: uppercase; letter-spacing: 0.14em; font-weight: 700;
  background: var(--ink); color: var(--paper); padding: 4px 10px;
}

/* Estado sin enlace de compra. Es un <span>, no un <a href="">: un href vacio
   recarga la pagina en silencio, que es peor que no ofrecer el boton. */
.merch-card-foot .btn[aria-disabled="true"] {
  opacity: 0.5; cursor: not-allowed; box-shadow: none; pointer-events: none;
}

.merch-note { color: var(--muted); font-size: var(--t-xs); line-height: 1.4; }

/* Aviso de que el precio y el stock reales estan en la otra tienda. La BD solo
   se actualiza al sincronizar a mano, asi que esto no es letra pequena de
   compromiso: es lo unico honesto que se puede decir. */
.merch-disclaimer {
  position: relative; z-index: 2;
  color: var(--muted); font-size: var(--t-sm); line-height: 1.6;
  border-left: 3px solid var(--ink); padding: 4px 0 4px 14px; margin: 0 0 28px;
  max-width: 60ch;
}

/* CTA secundario de la portada (el merch, junto al de la biblioteca).
   Mismo componente que .course-pill pero mas callado: sin relleno solido y con
   la tinta atenuada. La jerarquia es deliberada --- la biblioteca es a lo que se
   viene, el merch es un extra--- y por eso no lleva insignia. */
.course-pill--soft {
  background: transparent;
  border-color: var(--line);
  color: var(--muted);
  font-weight: 500;
}
.course-pill--soft .course-icon { color: var(--muted); }
.course-pill--soft:hover {
  background: var(--glass);
  border-color: var(--glass-line);
  color: var(--ink);
}
.course-pill--soft:hover .course-icon { color: var(--blue); }

/* Cuadro de salida del panel de merch (resultado de "Probar conexion" y de la
   sincronizacion). Existe porque el texto de un alert() del navegador no se
   puede copiar, y es justo lo que hay que pegar para diagnosticar: IDs de
   tienda, permisos del token y el error crudo de Printify. */
.merch-out {
  border: 2px solid var(--ink); background: var(--paper-2);
  margin: 14px 0; border-radius: 0;
}
.merch-out-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 10px; border-bottom: 2px solid var(--ink);
}
.merch-out-head .btn { padding: 4px 10px; font-size: var(--t-xs); }
.merch-out pre {
  margin: 0; padding: 12px; max-height: 340px; overflow: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.8rem; line-height: 1.5; color: var(--ink);
  white-space: pre-wrap; word-break: break-word;
  /* Seleccionable a proposito: el sitio pone user-select:none en algunos
     controles del panel y aqui seria justo lo contrario de lo que se quiere. */
  user-select: text;
}

/* ---- Panel de merch: configuracion plegada, barra de acciones y tabla ---- */
.merch-summary {
  cursor: pointer; font-weight: 700; padding: 10px 12px;
  border: 2px solid var(--ink); background: var(--paper-2);
  list-style: none; user-select: none;
}
.merch-summary::-webkit-details-marker { display: none; }
.merch-summary::before { content: "\25B8  "; display: inline-block; transition: transform 0.2s var(--ease); }
#merch_config[open] .merch-summary::before { transform: rotate(90deg); }
#merch_config { margin-bottom: 18px; }
#merch_config[open] .merch-summary { margin-bottom: 14px; }

.merch-bar { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin: 6px 0 10px; }

.merch-table-wrap { overflow-x: auto; margin-top: 12px; }
.merch-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.merch-table th {
  text-align: left; font-size: var(--t-xs); text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--muted); font-weight: 700;
  border-bottom: 2px solid var(--ink); padding: 8px 10px; white-space: nowrap;
}
.merch-table td { padding: 10px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.merch-table tr.is-missing { opacity: 0.55; }
.merch-table .btn { padding: 4px 10px; font-size: var(--t-xs); }
.merch-thumb {
  width: 44px; height: 44px; object-fit: cover;
  border: 2px solid var(--ink); display: block; background: var(--paper-2);
}
.merch-warn { color: var(--red); font-weight: 600; }
.merch-state {
  display: inline-block; font-size: var(--t-xs); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em; padding: 3px 8px;
}
.merch-state.is-on { background: var(--ink); color: var(--paper); }
.merch-state.is-off { background: transparent; color: var(--muted); border: 1px solid var(--line); }

/* El modal generico del sitio es de 480px y con fondo translucido; el de merch
   lleva un formulario de dos columnas, asi que se ensancha y se opaca para que
   el texto no compita con lo que hay detras. */
.merch-modal { width: min(680px, 100%); background: var(--paper); border: 2px solid var(--ink); }

/* ============================================================
   Merch: reclamo estilo comic (onomatopeya)
   ============================================================
   Estrella de comic con la palabra dentro. Encaja con el cartel constructivista
   del sitio --- tinta plana, filete negro, cero blur, cero degradados--- y le
   anade lo unico que le faltaba: ruido.

   El clip-path dibuja la estrella de 16 puntas; el filete negro se consigue
   apilando dos estrellas (la de atras un poco mas grande y negra), porque
   border no sigue a clip-path. */
.merch-burst {
  position: relative; display: inline-grid; place-items: center;
  width: 92px; height: 92px; flex: 0 0 auto;
}
.merch-burst::before,
.merch-burst::after {
  content: ""; position: absolute; inset: 0;
  clip-path: polygon(50% 0%, 60% 18%, 78% 8%, 78% 28%, 96% 26%, 87% 43%,
                     100% 50%, 87% 57%, 96% 74%, 78% 72%, 78% 92%, 60% 82%,
                     50% 100%, 40% 82%, 22% 92%, 22% 72%, 4% 74%, 13% 57%,
                     0% 50%, 13% 43%, 4% 26%, 22% 28%, 22% 8%, 40% 18%);
}
.merch-burst::before { background: var(--ink); transform: scale(1.06); }
.merch-burst::after { background: var(--vermillion); }
.merch-burst-word {
  position: relative; z-index: 2;
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  /* "MERCH" son 5 letras y no 4 como la onomatopeya que habia antes: con el
     cuerpo anterior se salia de las puntas de la estrella. */
  font-weight: 900; font-size: 0.92rem; line-height: 1;
  color: var(--paper); text-transform: uppercase;
  letter-spacing: -0.03em; transform: rotate(-8deg);
  text-shadow: 2px 2px 0 var(--ink);
}

/* --- Version fija en la portada y al final del libro --- */
.merch-comic {
  display: inline-flex; align-items: center; gap: 14px; text-decoration: none;
  color: var(--ink); padding: 6px 16px 6px 6px;
  border: 2px solid var(--ink); background: var(--paper);
  box-shadow: var(--shadow); border-radius: 0;
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.merch-comic:hover { transform: translate(-3px, -3px); box-shadow: 8px 8px 0 var(--ink); }
.merch-comic .merch-burst { width: 66px; height: 66px; }
.merch-comic .merch-burst-word { font-size: 0.6rem; }
.merch-comic-text {
  display: flex; flex-direction: column; gap: 2px;
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
}
.merch-comic-text b { font-size: 1.05rem; font-weight: 800; text-transform: uppercase; letter-spacing: -0.01em; }
.merch-comic-text span { font-size: var(--t-xs); color: var(--muted); font-family: inherit; }

/* --- Version flotante, esquina superior derecha del escaparate --- */
.merch-pop {
  position: fixed; top: 86px; right: 18px; z-index: 45;
  animation: merch-pop-in 0.5s var(--ease) both;
}
.merch-pop[hidden] { display: none; }
.merch-pop-link {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  text-decoration: none; color: var(--ink);
}
.merch-pop-burst {
  position: relative; display: grid; place-items: center; width: 92px; height: 92px;
  animation: merch-wobble 3.4s var(--ease) infinite;
}
.merch-pop-burst::before,
.merch-pop-burst::after {
  content: ""; position: absolute; inset: 0;
  clip-path: polygon(50% 0%, 60% 18%, 78% 8%, 78% 28%, 96% 26%, 87% 43%,
                     100% 50%, 87% 57%, 96% 74%, 78% 72%, 78% 92%, 60% 82%,
                     50% 100%, 40% 82%, 22% 92%, 22% 72%, 4% 74%, 13% 57%,
                     0% 50%, 13% 43%, 4% 26%, 22% 28%, 22% 8%, 40% 18%);
}
.merch-pop-burst::before { background: var(--ink); transform: scale(1.07); }
.merch-pop-burst::after { background: var(--vermillion); }
.merch-pop-word {
  position: relative; z-index: 2;
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-weight: 900; font-size: 0.92rem; color: var(--paper);
  text-transform: uppercase; letter-spacing: -0.03em; transform: rotate(-8deg);
  text-shadow: 2px 2px 0 var(--ink);
}
.merch-pop-text {
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-weight: 800; font-size: 0.78rem; text-transform: uppercase;
  letter-spacing: 0.12em; background: var(--ink); color: var(--paper);
  padding: 2px 8px;
}
.merch-pop-close {
  position: absolute; top: -6px; right: -6px; z-index: 3;
  width: 22px; height: 22px; line-height: 1; cursor: pointer;
  border: 2px solid var(--ink); background: var(--paper); color: var(--ink);
  font-size: 0.9rem; padding: 0; border-radius: 0;
}
.merch-pop-close:hover { background: var(--ink); color: var(--paper); }
.merch-pop-link:hover .merch-pop-burst { animation-play-state: paused; transform: scale(1.06); }

@keyframes merch-pop-in {
  from { opacity: 0; transform: scale(0.4) rotate(-25deg); }
  70%  { opacity: 1; transform: scale(1.12) rotate(4deg); }
  to   { opacity: 1; transform: scale(1) rotate(0); }
}
@keyframes merch-wobble {
  0%, 100% { transform: rotate(-3deg); }
  50%      { transform: rotate(3deg); }
}

/* En movil el reclamo flotante estorba mas de lo que aporta: se encoge y baja a
   la esquina inferior, donde no tapa la navegacion. */
@media (max-width: 720px) {
  .merch-pop { top: auto; bottom: 16px; right: 12px; }
  .merch-pop-burst { width: 68px; height: 68px; }
  .merch-pop-word { font-size: 0.66rem; }
  .merch-pop-text { font-size: 0.62rem; }
}

/* Sin animacion para quien la ha desactivado en su sistema. La insignia se ve
   igual: lo unico que se quita es el movimiento. */
@media (prefers-reduced-motion: reduce) {
  .merch-pop { animation: none; }
  .merch-pop-burst { animation: none; }
  .merch-comic { transition: none; }
}

/* El bloque del merch va justo debajo del CTA de la biblioteca, asi que no
   necesita el aire completo de .actions (40px) ni repetir su animacion. */
.merch-actions { margin-top: 16px; animation-delay: 0.8s; }
/* El reclamo del final de libro va centrado bajo el CTA, con aire propio. */
.k-done-merch { margin-top: 22px; }

/* ---- Bloque de merch de la portada ----
   Reutiliza la estrella del reclamo flotante (.merch-pop-burst) tal cual: es el
   mismo objeto y no tiene sentido dibujarlo dos veces. Debajo, los tipos de
   producto que hay de verdad en la tienda, con su icono. */
.merch-hero {
  display: inline-flex; flex-direction: column; align-items: flex-start; gap: 10px;
  text-decoration: none; color: var(--ink); margin-top: 26px;
  opacity: 0; animation: rise 1.1s var(--ease) 0.8s forwards;
}
.merch-hero .merch-pop-burst { width: 104px; height: 104px; }
.merch-hero .merch-pop-word { font-size: 1.05rem; }
.merch-hero-title {
  font-family: var(--f-display, 'Jost', system-ui, sans-serif);
  font-weight: 800; font-size: 1.05rem; text-transform: uppercase;
  letter-spacing: -0.01em; background: var(--ink); color: var(--paper);
  padding: 4px 10px;
}
.merch-hero-sub { color: var(--muted); font-size: var(--t-sm); }

.merch-hero-kinds { display: flex; flex-wrap: wrap; gap: 8px; }
.merch-kind {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 11px; border: 2px solid var(--ink); background: var(--paper);
  color: var(--ink); font-size: var(--t-xs); font-weight: 600;
  /* Entran escalonadas: el --i lo emite el PHP por cada icono, asi la fila se
     arma sola en cascada en vez de aparecer de golpe. */
  opacity: 0; animation: merch-kind-in 0.5s var(--ease) forwards;
  animation-delay: calc(1s + var(--i, 0) * 0.09s);
  transition: transform 0.2s var(--ease), background 0.2s var(--ease);
}
.merch-kind em { font-style: normal; text-transform: uppercase; letter-spacing: 0.06em; }
.merch-kind svg { color: var(--vermillion-ink); flex: 0 0 auto; }
.merch-hero:hover .merch-kind { background: var(--paper-2); }
.merch-hero:hover .merch-kind:nth-child(odd) { transform: translateY(-3px); }
.merch-hero:hover .merch-kind:nth-child(even) { transform: translateY(3px); }
.merch-hero:hover .merch-pop-burst { animation-play-state: paused; transform: scale(1.05); }

@keyframes merch-kind-in {
  from { opacity: 0; transform: translateY(8px) scale(0.9); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .merch-hero { animation: none; opacity: 1; }
  .merch-kind { animation: none; opacity: 1; transition: none; }
  .merch-hero:hover .merch-kind { transform: none; }
}

/* ---- Imagen ampliable de la tarjeta ---- */
.merch-card-imgbtn:focus-visible { outline: 3px solid var(--vermillion-ink); outline-offset: -3px; }
.merch-zoom {
  position: absolute; right: 8px; bottom: 8px;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 7px; background: var(--ink); color: var(--paper);
  font-size: var(--t-xs); font-weight: 700; line-height: 1;
  opacity: 0; transition: opacity 0.2s var(--ease);
}
.merch-card:hover .merch-zoom,
.merch-card-imgbtn:focus-visible .merch-zoom { opacity: 1; }
/* En tactil no hay hover, asi que la pista tiene que verse siempre o no existe. */
@media (hover: none) { .merch-zoom { opacity: 1; } }

/* ---- Galeria a pantalla completa ---- */
.merch-lb {
  position: fixed; inset: 0; z-index: 80;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 20px; background: rgba(17, 17, 17, 0.92);
  animation: fade 0.2s var(--ease);
}
.merch-lb[hidden] { display: none; }
/* Se bloquea el scroll del fondo mientras esta abierta: si no, la rueda del
   raton mueve la pagina de detras y al cerrar apareces en otro sitio. */
body.merch-lb-open { overflow: hidden; }

.merch-lb-figure {
  margin: 0; display: flex; flex-direction: column; align-items: center; gap: 10px;
  max-width: min(900px, 92vw);
}
.merch-lb-figure img {
  max-width: 100%; max-height: 74vh; object-fit: contain; display: block;
  background: var(--paper); border: 2px solid var(--paper);
}
.merch-lb-figure figcaption {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: center;
  color: var(--paper); font-size: var(--t-sm);
  font-family: var(--f-display, 'Jost', system-ui, sans-serif); font-weight: 600;
}
.merch-lb-count { color: rgba(242, 239, 228, 0.65); font-weight: 400; }

.merch-lb-close,
.merch-lb-nav {
  flex: 0 0 auto; cursor: pointer; border: 2px solid var(--paper);
  background: transparent; color: var(--paper); border-radius: 0;
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.merch-lb-close:hover,
.merch-lb-nav:hover { background: var(--paper); color: var(--ink); }
.merch-lb-close {
  position: absolute; top: 16px; right: 16px;
  width: 40px; height: 40px; font-size: 1.6rem; line-height: 1; padding: 0;
}
.merch-lb-nav { width: 46px; height: 66px; font-size: 2rem; line-height: 1; padding: 0; }
.merch-lb-nav[hidden] { display: none; }

.merch-lb-dots {
  position: absolute; bottom: 20px; left: 0; right: 0;
  display: flex; justify-content: center; gap: 7px;
}
.merch-lb-dots[hidden] { display: none; }
.merch-lb-dot {
  width: 11px; height: 11px; padding: 0; cursor: pointer; border-radius: 0;
  border: 2px solid var(--paper); background: transparent;
}
.merch-lb-dot.is-on { background: var(--vermillion); border-color: var(--vermillion); }

@media (max-width: 720px) {
  .merch-lb { padding: 12px; gap: 4px; }
  .merch-lb-nav { width: 34px; height: 54px; font-size: 1.5rem; }
  .merch-lb-figure img { max-height: 62vh; }
}
@media (prefers-reduced-motion: reduce) {
  .merch-lb { animation: none; }
  .merch-zoom { transition: none; }
}

/* ---- /merch/: filtros a la izquierda + rejilla compacta ---- */
/* Se sale del .wrap (1120px) para ocupar la ventana entera: un escaparate se
   ve mejor ancho. Mismo truco que la barra de tinta de la nav; el overflow-x:
   hidden global de html/body evita la barra horizontal que suele traer 100vw. */
.merch-layout {
  position: relative; z-index: 2;
  width: 100vw; margin-left: calc(50% - 50vw);
  padding: 0 clamp(16px, 3vw, 40px) 40px;
  display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 28px;
  align-items: start;
}
.merch-layout--nofilters { grid-template-columns: minmax(0, 1fr); }
.merch-filters { position: sticky; top: 20px; }

/* Cuatro por fila, fijas. Con auto-fill y el ancho completo el numero bailaba
   segun la pantalla; asi la rejilla es la misma para todo el mundo. */
.merch-grid {
  display: grid; gap: 18px;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.merch-card[hidden] { display: none !important; }
.merch-empty[hidden] { display: none; }

/* Tarjetas mas apretadas: menos relleno y tipografia algo menor. */
.merch-card-body { padding: 12px; gap: 6px; }
.merch-card-title { font-size: 0.95rem; }
.merch-card-blurb { font-size: var(--t-xs); line-height: 1.45; }
.merch-card-price { font-size: 1rem; }
.merch-card-foot { padding-top: 8px; gap: 6px; }
.merch-card-foot .btn { padding: 7px 12px; font-size: var(--t-sm); }

/* El boton de la imagen se ajusta EXACTO a la caja 1:1: sin line-height ni
   espacio de linea heredado debajo del <img>, que era lo que dejaba una banda
   muerta bajo cada foto y alargaba todas las tarjetas. */

@media (max-width: 900px) {
  /* El panel sale de pantalla y se abre con el boton flotante, igual que en la
     biblioteca. */
  .merch-layout { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .merch-filters {
    position: fixed; inset: 0 auto 0 0; z-index: 60; width: min(300px, 86vw);
    overflow-y: auto; padding: 20px; background: var(--paper);
    border-right: 2px solid var(--ink); box-shadow: var(--shadow);
    transform: translateX(-102%); transition: transform 0.28s var(--ease);
  }
  .merch-filters.is-open { transform: none; }
  .merch-filter-toggle { display: inline-flex; align-items: center; }
}
@media (prefers-reduced-motion: reduce) {
  .merch-filters { transition: none; }
}

/* ---- Carrusel dentro de la tarjeta ---- */
.merch-card-media { position: relative; line-height: 0; }

.merch-media-dots {
  position: absolute; left: 0; right: 0; bottom: 8px; z-index: 2;
  display: flex; justify-content: center; gap: 5px; line-height: 0;
}
.merch-media-dot {
  width: 7px; height: 7px; background: var(--paper);
  border: 1px solid var(--ink); display: block;
}
.merch-media-dot.is-on { background: var(--vermillion); border-color: var(--vermillion); }

/* Escalones de la rejilla, de mayor a menor anchura Y EN ESE ORDEN: todos son
   max-width y la misma especificidad, asi que a 800px encajan el de 1200 y el de
   900 a la vez y gana el ultimo que aparezca. Puestos al reves, una tableta
   acabaria con tres columnas en vez de dos. */
@media (max-width: 1200px) {
  .merch-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .merch-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
}
@media (max-width: 520px) {
  .merch-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ---- Cabecera de /merch/ en dos columnas ----
   Titulo a la izquierda, explicacion a la derecha, en la misma fila. Apilada
   ocupaba media pantalla antes del primer producto; aqui el contenido son los
   productos, no la introduccion. */
.merch-head {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  gap: 12px 40px; align-items: end;
  margin: 16px 0 26px;
}
.merch-head-title { min-width: 0; }
.merch-head h1 {
  margin: 0; line-height: 1.02; letter-spacing: -0.02em;
  font-size: clamp(1.8rem, 4vw, 2.8rem);
  color: var(--vermillion); text-shadow: 3px 3px 0 var(--ink);
}
.merch-head-lead {
  margin: 0 0 4px; color: var(--muted);
  font-size: var(--t-sm); line-height: 1.55; max-width: 62ch;
}

@media (max-width: 820px) {
  /* Apilada en movil: en una columna estrecha, dos columnas dejarian el texto
     en un canal de cuatro palabras. */
  .merch-head { grid-template-columns: minmax(0, 1fr); gap: 8px; align-items: start; margin-bottom: 20px; }
  .merch-head-lead { font-size: var(--t-xs); }
}

/* ---- Corte de comic entre fotos del carrusel ----
   El sitio ya define --step: steps(4, end) para "movimiento mecanico, no
   organico". Aplicado a la opacidad da un fundido de cuatro fotogramas: se lee
   como un cambio de vineta impresa, no como un crossfade de presentacion.
   Ademas es lo mas barato que hay --- opacidad pura, sin layout ni pintado--- .

   Dos clases con los MISMOS keyframes, que el JS alterna: asi la animacion se
   relanza sin forzar un reflow sincrono en cada cambio. */
/* Los puntos cambian con la misma cadencia mecanica. */
.merch-media-dot { transition: background-color 0.2s var(--step); }

/* Entrada de la galeria: escala + opacidad, las dos compuestas por GPU. */
.merch-lb-figure { animation: merch-lb-in 0.28s var(--ease) both; }
@keyframes merch-lb-in {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}

/* La lupa entra desde abajo en vez de solo aparecer. */
.merch-zoom { transform: translateY(4px); transition: opacity 0.22s var(--ease), transform 0.22s var(--ease); }
.merch-card:hover .merch-zoom,
.merch-card-imgbtn:focus-visible .merch-zoom { opacity: 1; transform: translateY(0); }

/* Las casillas del filtro responden al pasar por encima, sin mover nada de
   sitio: solo color, que no provoca reflow. */
.lf-opt span { transition: color 0.18s var(--ease); }

@media (prefers-reduced-motion: reduce) {
  /* Nada se mueve, pero todo sigue siendo visible y utilizable. */
  .merch-card, .merch-zoom, .lf-opt span { transition: none; }
  .merch-card:hover { transform: none; box-shadow: var(--shadow); }
  .merch-card-img { transition: none; }
  .merch-lb-figure { animation: none; }
  .merch-zoom { transform: none; }
}
/* Etiquetas de Printify en la tabla del panel. Se cortan si son muchas: son
   una referencia para definir colecciones, no el contenido de la fila. */
.merch-tags {
  color: var(--muted); max-width: 320px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---- Pie de tarjeta: pedir al 80 %, coleccion al 20 % ----
   La accion que importa es comprar, asi que se lleva el ancho. La coleccion es
   navegacion lateral: un icono basta y el nombre va en title/aria-label. */
.merch-card-actions {
  display: grid; grid-template-columns: 4fr 1fr; gap: 6px; align-items: stretch;
}
/* Sin coleccion, el boton de pedir ocupa la fila entera. Se resuelve en CSS y no
   con una clase condicional en el PHP: una regla menos que mantener en dos sitios. */
.merch-card-actions > :only-child { grid-column: 1 / -1; }
.merch-card-actions .btn { width: 100%; }
.merch-col-btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 7px 0;
}
