/* Colores: vienen de ../tokens.css (raíz de talleres, copiado de miweb; normativa en
   miweb/docs/colores.md). Aquí solo se usan los roles --color-*, nunca un
   hex suelto; las variantes se sacan con color-mix(). La excepción son los
   colores de marca del corazón de Lovable, que pinta el canvas (js/main.js).
   Misma estructura que la portada de portfolio-web-ia: el corazón de
   burbujas ocupa el sitio del diente de león. */
:root {
  color-scheme: dark;
  /* tira de logos, nombre y fecha: en ../portada/portada.css (común a todos los talleres) */
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
/* barra de scroll sin fondo: solo se ven la barrita y las flechas */
html { scrollbar-color: color-mix(in srgb, var(--color-text-muted) 45%, transparent) transparent; }
body {
  background:
    radial-gradient(900px circle at 0% 0%, var(--color-glow), transparent 60%),
    var(--color-bg);
  background-color: var(--color-bg);
  color: var(--color-text);
  font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}

/* evita que la primera pintura anime título/índice cuando se llega con las burbujas ya explotadas */
.no-anim, .no-anim * { transition: none !important; }

/* pompas de fondo arriba a la derecha (en el sitio de las nubes de
   portfolio-web-ia, la malla voronoi de maceta-3d y los puntos de
   app-ar-unity): solo el contorno, de varios tamaños, que se desvanecen hacia
   fuera de la esquina. En la capa más al fondo, para no tapar nunca el
   corazón ni el texto. Las genera js/burbujas.js; aquí solo el color. Algunas
   "respiran" despacio (salvo con movimiento reducido) */
.top-bubbles {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}
.top-bubbles svg {
  position: absolute;
  top: 0;
  right: 0;
  overflow: visible;
}
.bubbles { opacity: 0.45; }
.bubbles circle { fill: none; stroke: var(--color-accent-soft); stroke-width: 1.5px; }
.bubbles path { fill: none; stroke: var(--color-text); stroke-width: 1.5px; stroke-linecap: round; }
.bubbles .breathe { animation: bubble-breathe 4.5s ease-in-out infinite; }
@keyframes bubble-breathe {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.2; }
}
@media (prefers-reduced-motion: reduce) {
  .bubbles .breathe { animation: none; }
}

canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
  cursor: default;
}
/* hasta explotar las burbujas, toda la pantalla es clicable */
canvas.clickable { cursor: pointer; }
/* sobre una burbuja que flota, la mano: se puede explotar (lo marca main.js).
   Va también en el índice, que tapa el canvas cuando ya se ha soltado */
body.over-bubble,
body.over-bubble canvas,
body.over-bubble .index { cursor: pointer; }

/* botón invisible sobre el corazón (lo dibuja el canvas; main.js coloca el
   botón encima): para explotarlas con teclado y lector de pantalla. Solo se
   ve su foco */
.pop-btn {
  position: fixed;
  z-index: 3;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
}
.pop-btn:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 3px; }
.pop-btn[hidden] { display: none; }

/* pantallas verticales o cuadradas: el corazón va abajo a la izquierda, así
   que el título se centra en el hueco entre el logo y el corazón
   (--scene-top lo pone main.js) */
@media (max-aspect-ratio: 5/4) {
  .message {
    top: var(--below-logo);
    bottom: calc(100% - var(--scene-top, 70%) + 0.5rem);
    padding-block: 0;
  }
}
/* en dos líneas equilibradas: max-width en em (crece con la letra) para que
   no quepa en una, y text-wrap: balance para repartirlo. Si la pantalla es
   estrecha y salen tres, main.js (fitTitle) reduce la letra */
.message h1 {
  margin: 0;
  max-width: 21em;
  font-size: clamp(2rem, 5.5vw, 4rem);
  font-weight: 700;
  line-height: 1.2;
  text-wrap: balance;
  text-shadow: 0 0 24px var(--color-bg), 0 0 8px var(--color-bg);
  color: var(--color-heading);
  opacity: 1;
  transition: opacity .9s ease;
}
body.popped .message h1,
body.popped .message .subtitle,
body.popped .message .subtitle-date {
  opacity: 0;
  transition-delay: .3s;
}

/* ---------- Índice (aparece al explotar las burbujas) ---------- */
.index {
  position: fixed;
  inset: 0;
  z-index: 2;
  opacity: 0;
  pointer-events: none;
  transition: opacity .9s ease;
}
body.popped .index {
  opacity: 1;
  pointer-events: auto;
  transition-delay: 1.1s;
}

/* La caja del índice ocupa todo el hueco libre (a la derecha del corazón;
   empieza en --index-left, igual en todos los talleres, entre el borde de
   arriba y el pie) y centra las tarjetas dentro.
   Las columnas (--index-cols) y la escala del texto (--index-scale) las
   ajusta main.js midiendo, para que siempre quepan sin scroll. */
.index-grid {
  position: absolute;
  left: var(--index-left);         /* común a todos los talleres (portada.css) */
  right: min(7rem, 5vw);
  top: var(--below-logo);         /* por debajo de la franja de logos */
  bottom: 3.5rem;
  display: grid;
  grid-template-columns: repeat(var(--index-cols, 1), 1fr);
  align-content: center;
  gap: 1.1em;
  font-size: calc(var(--index-scale, 1) * 1rem);
}
/* verticales o cuadradas: el corazón ya no deja una columna libre a su
   derecha, así que el índice va centrado a lo ancho, por debajo del logo
   y por encima del pie (que en estrecho ocupa dos filas) */
@media (max-aspect-ratio: 5/4) {
  .index-grid {
    left: 0;
    right: 0;
    width: min(90%, 760px);
    margin-inline: auto;
    top: var(--below-logo);
    bottom: 4.25rem;
  }
}

/* Títulos y subtítulos en Plus Jakarta Sans 700; el texto sigue en Inter */
.message h1,
.content-header h1,
.index-card h3 {
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  letter-spacing: 0.01em; /* Plus Jakarta viene algo apretada en 700 */
}

/* Tarjetas de cristal (translúcidas, con desenfoque), esquinas rectas y sin
   borde. Título malva y descripción Paper. Al pasar por encima se alargan hacia
   la derecha (del 92 % al 100 %; el relleno derecho crece lo mismo para que el
   texto no salte), el fondo se aclara y el título pasa a naranja */
.index-card {
  display: block;
  width: 92%;
  background: var(--color-surface-glass);
  backdrop-filter: blur(8px);
  color: var(--color-text);
  padding: 1.5em 1.85em;
  text-decoration: none;
  transition: width .25s ease, padding-right .25s ease, background-color .25s ease;
}
a.index-card { cursor: pointer; }
a.index-card:hover,
a.index-card:focus-visible,
a.index-card:active {
  width: 100%;
  padding-right: calc(1.85em + 8%);
  background: var(--color-surface-glass-hover);
}
a.index-card:hover h3,
a.index-card:focus-visible h3,
a.index-card:active h3 {
  color: var(--color-accent);
}
a.index-card:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}
.index-card h3 {
  margin: 0 0 0.5em;
  font-size: 1.35em;
  font-weight: 700;
  color: var(--color-heading);
  transition: color .25s ease;
}
.index-card p {
  margin: 0;
  font-size: 0.9em;
  font-weight: 400;
  line-height: 1.5;
  color: inherit;
}

.byline {
  position: fixed;
  left: 50%;
  bottom: 1rem;
  transform: translateX(-50%);
  margin: 0;
  font-size: 0.75rem;
  color: var(--color-text-soft);
  opacity: 0;
  z-index: 2;
  pointer-events: none;
  text-align: center;
  transition: opacity .9s ease;
}
body.popped .byline {
  opacity: 0.65;
  transition-delay: .8s;
}

.credit {
  position: fixed;
  right: 1.25rem;
  bottom: 1rem;
  margin: 0;
  font-size: 0.8rem;
  color: var(--color-text-soft);
  opacity: 0.65;
  z-index: 2;
  pointer-events: none;
}
/* en una sola fila, nombre (centrado) y crédito (derecha) se pisan por
   debajo de ~800px: se apilan a la derecha, con "Inflar otro" a la izquierda */
@media (max-width: 820px) {
  .byline {
    left: auto;
    right: 1rem;
    bottom: 2.35rem;
    transform: none;
    text-align: right;
  }
  .credit { right: 1rem; }
}
/* móviles muy estrechos: no caben el botón y el crédito lado a lado; el
   crédito es lo prescindible, y nombre y correo pasan a dos líneas */
@media (max-width: 440px) {
  .credit { display: none; }
  .byline { bottom: 0.9rem; line-height: 1.4; }
  .byline-sep { display: none; }
  .byline-part { display: block; }
}

.replant-btn {
  position: fixed;
  left: 1.5rem;
  bottom: 1.1rem;
  font: 500 0.8rem/1 inherit;
  font-family: inherit;
  letter-spacing: 2px; /* como las etiquetas de la portada de miweb */
  color: var(--color-text-on-button);
  background: var(--color-button);
  border: none;
  padding: 0.6rem 1rem;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  z-index: 2;
  transition: opacity .6s ease, color .2s ease, background-color .2s ease;
}
/* se ilumina: naranja con texto Ink */
.replant-btn:hover,
.replant-btn:focus-visible,
.replant-btn:active { background: var(--color-accent); color: var(--color-text-on-accent); }
.replant-btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; }
body.popped .replant-btn {
  opacity: 1;
  pointer-events: auto;
  /* el retraso es solo para aparecer tras explotar las burbujas; si fuera un transition-delay
     general, también retrasaría el color del hover */
  transition: opacity .6s ease .8s, color .2s ease, background-color .2s ease;
}

/* ---------- Páginas de contenido (una por cada tema del índice) ---------- */
body.content-page {
  overflow: auto;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  /* el degradado radial de .message está pensado para una pantalla fija;
     en una página larga con scroll dejaba ver el borde del círculo, así
     que aquí el fondo es plano */
  background: var(--color-bg);
  background-color: var(--color-bg);
}
.content-header {
  max-width: 760px;
  margin: 0 auto;
  padding: 2rem 1.5rem 1.5rem;
}
/* Navegación fija (Índice / Anterior / Siguiente): botones cuadrados de fondo
   liso --color-button (Powder Blue apagado) con texto Ink (5.9), como
   "Inflar otro"; opacos, para que se lean aunque el
   contenido pase por debajo al hacer scroll. Al pasar por encima se iluminan
   (naranja con texto Ink); no se alargan */
.back-link,
.prev-link,
.next-link {
  position: fixed;
  z-index: 3;
  padding: 0.55rem 1rem;
  background: var(--color-button);
  color: var(--color-text-on-button);
  text-decoration: none;
  font-size: 0.85rem;
  font-weight: 500;
  letter-spacing: 2px; /* como las etiquetas de la portada de miweb */
  line-height: 1.2;
  transition: color .2s ease, background-color .2s ease;
}
.back-link { top: 1rem; left: 1rem; }
.prev-link { bottom: 1rem; left: 1rem; }
.next-link { bottom: 1rem; right: 1rem; }
.back-link:hover,
.prev-link:hover,
.next-link:hover,
.back-link:focus-visible,
.prev-link:focus-visible,
.next-link:focus-visible,
.back-link:active,
.prev-link:active,
.next-link:active { background: var(--color-accent); color: var(--color-text-on-accent); }
.back-link:focus-visible,
.prev-link:focus-visible,
.next-link:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; }

/* pantallas estrechas: el título ya ocupa todo el ancho, así que baja lo
   justo para quedar bajo "← Índice"; y abajo se reserva el hueco de
   Anterior/Siguiente para que el final del contenido no quede tapado */
@media (max-width: 720px) {
  .content-header { padding-top: 3.75rem; }
  body .content-body.no-scroll { padding-bottom: 4rem; }
}
/* móvil: franjas del color del fondo, con borde recto, detrás de "← Índice"
   (arriba) y de Anterior / Siguiente (abajo), para que el texto pase por
   debajo sin verse. El fondo de estas páginas es liso, así que no se
   distinguen; los rellenos de .content-header (3.75rem) y .content-body
   (5rem, o 4rem en las no-scroll) dejan leer todo al final del scroll */
@media (max-width: 720px) {
  body.content-page::before,
  body.content-page::after {
    content: "";
    position: fixed;
    left: 0;
    right: 0;
    height: 3.75rem;
    background: var(--color-bg);
    z-index: 2; /* por debajo de los botones (3) */
    pointer-events: none;
  }
  body.content-page::before { top: 0; }
  body.content-page::after { bottom: 0; }
}
.content-header h1 {
  margin: 0 0 1rem;
  text-align: center;
  font-size: clamp(1.8rem, 4vw, 2.75rem);
  font-weight: 700;
  line-height: 1.15;
  color: var(--color-heading);
}
.content-header h1.no-wrap {
  white-space: nowrap;
  font-size: clamp(1rem, 3vw, 2.75rem);
}
.content-header .lead {
  margin: 0.75rem 0 0;
  text-align: center;
  color: var(--color-text);
  font-size: 1.05rem;
  font-weight: 500;
  line-height: 1.6;
}

.content-body {
  max-width: 760px;
  margin: 0 auto;
  padding: 0 1.5rem 5rem;
  color: var(--color-text);
  font-size: 1rem;
  line-height: 1.75;
}
.content-body.wide { max-width: 1000px; }
.content-body p { margin: 0 0 1.25rem; }
.content-body.no-scroll { padding-bottom: 0; }

/* Subtítulos de sección, todos iguales: mismo tamaño, negrita, color
   --color-subheading (el Slate de las fichas, aclarado para que se lea) */
.section-title {
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  letter-spacing: 0.01em;
  font-size: clamp(1.25rem, 3vw, 1.6rem);
  font-weight: 700;
  color: var(--color-subheading);
  max-width: 640px;
  margin: 0 auto 2.5rem;
  text-align: center;
}

/* ---------- Apartados de texto ---------- */
/* mismo aire entre apartados que en Evolución (10rem) */
.guide-section {
  max-width: 720px;
  margin: 6rem auto 10rem;
}
.guide-section a {
  color: var(--color-accent);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--color-accent) 40%, transparent);
  text-underline-offset: 0.2em;
}
.guide-section a:hover { text-decoration-color: currentColor; }

/* subtítulo que viene después de un párrafo dentro del mismo bloque: aire
   por encima para que se lea como apartado nuevo */
.guide-section p + .section-title { margin-top: 3rem; }

/* pasos numerados (como en portfolio-web-ia): solo el número en azul claro
   y en negrita, sin círculo, en la misma línea que el texto. El número va
   posicionado a la izquierda (no con grid/flex) para que la negrita, los
   enlaces o la cursiva del texto no se partan en columnas */
.steps-list {
  list-style: none;
  counter-reset: step;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.steps-list > li {
  counter-increment: step;
  position: relative;
  padding-left: 2.25rem;
  color: var(--color-text);
  line-height: 1.7;
}
.steps-list > li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  color: var(--color-accent-soft);
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.7rem;
}

/* listas de viñetas (como en portfolio-web-ia): la viñeta es una rayita que,
   al pasar por encima, se alarga y pasa a naranja, y el texto se aclara */
.feature-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.feature-list li {
  display: flex;
  align-items: center;
  gap: 1rem;
  color: var(--color-text-soft);
  font-size: 0.95rem;
  font-weight: 400;
  transition: color .25s ease;
}
.feature-list li::before {
  content: '';
  width: 28px;
  height: 1px;
  flex: 0 0 auto;
  background: var(--color-border-strong);
  transition: width .25s ease, background-color .25s ease;
}
.feature-list li:hover {
  color: var(--color-text);
}
.feature-list li:hover::before {
  width: 44px;
  background: var(--color-accent);
}
/* variante para textos largos (varias líneas): la rayita se alinea con la
   primera línea en vez de quedar centrada contra todo el párrafo */
.feature-list.stacked li { align-items: flex-start; }
.feature-list.stacked li::before { margin-top: 0.6em; }
/* la lista, como bloque centrado bajo la frase, con el texto alineado a la izquierda */
.feature-list.centered-list,
.steps-list.centered-list {
  width: fit-content;
  max-width: 100%;
  margin: 0.5rem auto 0;
}

/* subpuntos de un paso (como en portfolio-web-ia): 2.1, 2.2… igual que los
   números de los pasos, algo más pequeños */
.substeps {
  list-style: none;
  counter-reset: substep;
  margin: 0.6rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.substeps > li {
  counter-increment: substep;
  position: relative;
  padding-left: 2.5rem;
}
.substeps > li::before {
  content: counter(step) "." counter(substep);
  position: absolute;
  left: 0;
  color: var(--color-accent-soft);
  font-size: 0.9rem;
  font-weight: 700;
  line-height: 1.7rem; /* misma línea que el texto (1rem × 1.7), para que cuadre la base */
}

/* código dentro del texto: plano y cuadrado como las teclas (kbd)
   de portfolio-web-ia, en letra monoespaciada; si no cabe, se parte */
.guide-section code {
  padding: 0.1em 0.4em;
  background: var(--color-surface-raised);
  color: var(--color-text);
  font-family: ui-monospace, "Cascadia Code", Consolas, "Liberation Mono", monospace;
  font-size: 0.88em;
  overflow-wrap: anywhere;
}

/* puntos con título (Elementos principales, Clasificación…): el nombre en
   negrita en su propia línea, la explicación debajo y, si hay, el ejemplo o
   la nota en texto secundario */
.steps-list .step-title {
  display: block;
  font-weight: 700;
  color: var(--color-text);
}
.steps-list .step-note {
  display: block;
  margin-top: 0.3rem;
  color: var(--color-text-soft);
  font-size: 0.95rem;
  font-style: italic;
}

/* imagen grande (como el esquema de la impresora en maceta-3d): cabe entera
   en una pantalla */
.guide-figure {
  display: block;
  max-width: 100%;
  max-height: calc(100dvh - 14rem);
  width: auto;
  height: auto;
  margin: 0 auto;
}

/* bloque con la imagen a la izquierda y la lista a la derecha (Elementos
   principales): más ancho que el resto de la página para que la imagen no
   quede diminuta; en pantallas estrechas, imagen arriba y lista debajo. La
   imagen enlaza a sí misma, para verla a tamaño completo */
.guide-section.split-section,
html.snap .snap-slide .guide-section.split-section {
  max-width: none;
  width: min(1200px, calc(100vw - 3rem));
  margin-inline: calc(50% - min(600px, 50vw - 1.5rem));
}
.split {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 2.5rem;
  align-items: center;
}
.split .steps-list { gap: 1.1rem; font-size: 0.95rem; }
.figure-link { display: block; }
.figure-link:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 3px; }
.split-figure {
  display: block;
  width: 100%;
  height: auto;
}
@media (max-width: 860px) {
  .split { grid-template-columns: 1fr; gap: 1.75rem; }
}

/* comprobación entre dos pasos: sin número (no cuenta como paso), alineada
   con el texto de los pasos y destacada en azul claro y cursiva */
.steps-list > li.step-check {
  counter-increment: none;
  color: var(--color-accent-soft);
  font-weight: 700;
  font-style: italic;
}
.steps-list > li.step-check::before { content: none; }

/* párrafo centrado bajo un subtítulo */
.content-body p.centered-text { text-align: center; }

/* enlace destacado en azul claro dentro del texto, sin subrayado; al pasar, a naranja */
.guide-section a.soft-link {
  color: var(--color-accent-soft);
  font-weight: 500;
  text-decoration: none;
  transition: color .2s ease;
}
.guide-section a.soft-link:hover,
.guide-section a.soft-link:focus-visible {
  color: var(--color-accent);
}

/* captura de una web, a todo el ancho del bloque; enlaza a esa web */
.screenshot-link {
  display: block;
  margin-top: 1.5rem;
}
.screenshot-link:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 3px;
}
.screenshot {
  display: block;
  width: 100%;
  height: auto;
}

/* recuadro de palabras clave: bloque de cristal plano, sin borde; la
   etiqueta y las palabras se reparten a lo ancho */
.content-body p.keywords {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  margin: 2.5rem 0 0;
  padding: 1rem 1.5rem;
  background: var(--color-surface-glass);
  color: var(--color-text);
}
.keywords strong { color: var(--color-accent-soft); }

/* ---------- Columnas con subtítulo de nivel 3 ---------- */
/* como Ventajas / Limitaciones en portfolio-web-ia: cada columna con su
   subtítulo de nivel 3 (azul claro, más pequeño, en negrita) y una lista
   de viñetas debajo. Dos columnas, o tres con .three; una en pantallas
   estrechas */
.info-columns {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 2.5rem 3rem;
  max-width: 900px;
  margin: 0 auto;
}
.info-columns.three { grid-template-columns: repeat(3, 1fr); max-width: 1000px; }
@media (max-width: 860px) {
  .info-columns.three { grid-template-columns: 1fr; gap: 2.5rem; }
}
@media (max-width: 720px) {
  .info-columns { grid-template-columns: 1fr; gap: 2.5rem; }
}
.info-column h3 {
  margin: 0 0 1.4rem;
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  letter-spacing: 0.01em;
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--color-accent-soft);
}
/* precio de cada plan, bajo su nombre */
.info-column .price {
  margin: -0.9rem 0 1.2rem;
  font-size: 1.05rem;
  font-weight: 500;
  color: var(--color-text);
}

/* nota pequeña al pie de un bloque (fecha de los precios, aclaraciones) */
.content-body p.small-note {
  max-width: 900px;
  margin: 2.5rem auto 0;
  text-align: center;
  color: var(--color-text-soft);
  font-size: 0.85rem;
  font-style: italic;
}

/* inicio de una parte de la página (La interfaz): título grande, como el de
   la página, en una pantalla para él solo */
.part-title {
  margin: 0;
  text-align: center;
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  letter-spacing: 0.01em;
  font-size: clamp(1.8rem, 4vw, 2.75rem);
  font-weight: 700;
  line-height: 1.15;
  color: var(--color-heading);
}
.part-lead {
  margin: 1rem 0 0;
  text-align: center;
  color: var(--color-text-soft);
}

/* ---------- Flujo con flechas (Describe → Construye → Publica) ---------- */
/* tres pasos en fila con flechas entre ellos y, debajo, una flecha en U de
   vuelta de Construye a Describe (Itera). Todo quieto. En pantallas
   estrechas, en columna y con la vuelta como texto */
.flow {
  list-style: none;
  margin: 2.5rem auto 0;
  padding: 0;
  max-width: 820px;
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr;
  align-items: start;
  gap: 0 1rem;
}
.flow-step {
  text-align: center;
  color: var(--color-text-soft);
  font-size: 0.95rem;
  line-height: 1.5;
}
.flow-num {
  display: block;
  color: var(--color-accent-soft);
  font-weight: 700;
  font-size: 1.6rem;
  line-height: 1.2;
}
.flow-step strong {
  display: block;
  margin: 0.15rem 0 0.35rem;
  color: var(--color-text);
  font-size: 1.1rem;
}
/* flechas (flujo y esquema): SVG con la raya y las puntas en un solo trazo
   de 2px, sobre píxeles enteros para que se vean nítidas; quietas */
.arrow-svg {
  display: block;
  fill: none;
  stroke: var(--color-accent-soft);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.flow-arrow { margin-top: 1.25rem; }
/* la vuelta: una flecha en U del mismo trazo que las de arriba, de debajo
   del centro de Construye al centro de Describe, con la punta hacia arriba.
   La U va de la mitad de la 1.ª columna a la mitad de la 3.ª: cada columna
   de paso mide (100% − 3rem de la flecha − 2 huecos de 1rem) / 2 */
.flow-loop {
  grid-column: 1 / 4;
  margin-top: 0.9rem;
  text-align: center;
  color: var(--color-accent-soft);
  font-size: 0.9rem;
  font-style: italic;
}
.flow-loop-line {
  position: relative;
  display: block;
  height: 1.75rem;
  margin: 0 calc((100% - 5rem) / 4) 0.75rem;
  border: 2px solid var(--color-accent-soft);
  border-top: none;
  border-radius: 0 0 1rem 1rem;
}
/* punta: SVG de 12px centrado sobre el trazo izquierdo (que va de −2px a
   0px), con un trocito de raya que la une a él */
.flow-loop-head {
  position: absolute;
  left: -7px;
  top: -2px;
}
@media (max-width: 720px) {
  .flow { grid-template-columns: 1fr; gap: 0.75rem; max-width: 22rem; }
  .flow-arrow { justify-self: center; margin: 1.5rem 0; transform: rotate(90deg); }
  .flow-loop { grid-column: auto; margin: 0.5rem 0 0; }
  .flow-loop-line { display: none; }
  .flow-loop span::before { content: "↺ "; font-style: normal; }
}

/* ---------- Esquema de lo que hay debajo (Qué hay debajo) ---------- */
/* como el diagrama del PDF: Lovable en el centro con su stack, el backend
   encima, el código a la izquierda (con los editores debajo) y los servicios
   a la derecha. Bloques de cristal planos; los logos llevan su color de
   marca. En pantallas estrechas, todo en una columna */
.stack-map {
  display: grid;
  grid-template-columns: 1fr auto 1.35fr auto 1fr;
  grid-template-areas:
    ".       .     backend .     ."
    ".       .     up      .     ."
    "git     left  core    right services"
    "down    .     .       .     ."
    "editors .     .       .     .";
  align-items: center;
  gap: 0.6rem 1rem;
  max-width: 1000px;
  margin: 0 auto;
}
.map-backend  { grid-area: backend; }
.map-core     { grid-area: core; }
.map-git      { grid-area: git; }
.map-editors  { grid-area: editors; }
.map-services { grid-area: services; }
.map-arrow-up    { grid-area: up; }
.map-arrow-left  { grid-area: left; }
.map-arrow-right { grid-area: right; }
.map-arrow-down  { grid-area: down; }

.map-backend, .map-core, .map-git, .map-editors, .map-services {
  background: var(--color-surface-glass);
  backdrop-filter: blur(8px);
  padding: 1.1rem 1.25rem;
}
.map-label {
  display: block;
  margin-bottom: 0.75rem;
  color: var(--color-text-soft);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 2px;
  text-transform: uppercase;
  line-height: 1.4;
}
.map-backend { text-align: center; }
.map-choice {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem 0.75rem;
}
.map-chip { white-space: nowrap; }
.map-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--color-text);
  font-weight: 500;
}
.map-or { color: var(--color-accent-soft); font-style: italic; }
.map-core { text-align: center; padding-block: 1.5rem; }
.map-title {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.75rem;
  margin: 0 0 1.25rem;
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  letter-spacing: 0.01em;
  font-size: 2.2rem;
  font-weight: 700;
  color: var(--color-text);
}
.map-logos {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
  font-size: 0.9rem;
  color: var(--color-text);
}
.map-core .map-logos { grid-template-columns: repeat(2, auto); justify-content: center; gap: 0.75rem 1.5rem; text-align: left; }
.map-logos li { display: flex; align-items: center; gap: 0.55rem; }
/* "y más": puntos suspensivos bajo la lista, alineados con los logos */
.map-logos li.map-more {
  justify-content: center;
  width: 1.4rem;
  color: var(--color-text-soft);
  font-size: 1.2rem;
  line-height: 0.6;
}
.map-logos img, .map-chip img { flex: 0 0 auto; width: 1.4rem; height: 1.4rem; }
.map-title img { width: 2.5rem; height: 2.5rem; }
.map-arrow {
  justify-self: center;
  align-self: center;
}
@media (max-width: 860px) {
  .stack-map {
    grid-template-columns: 1fr;
    grid-template-areas: "backend" "up" "core" "right" "services" "left" "git" "down" "editors";
    max-width: 26rem;
  }
  /* en columna, las horizontales se giran: el giro de 90° no mueve los
     píxeles de sitio */
  .map-arrow-h { transform: rotate(90deg); margin-block: 1.1rem; }
}

/* ---------- Iconos y botones de la interfaz de Lovable ---------- */
/* el sprite con los iconos (Lucide) no ocupa sitio; cada icono se pinta
   con <use> y toma el color del texto */
.icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.ic {
  width: 1.05em;
  height: 1.05em;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* "botón" tal y como se ve en Lovable (icono y/o texto): plano y cuadrado
   como las teclas (kbd), para que se reconozca de un vistazo dónde buscar */
.ui {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.12em 0.45em;
  background: var(--color-surface-raised);
  color: var(--color-text);
  font-size: 0.88em;
  font-weight: 500;
  line-height: 1.45;
  white-space: nowrap;
  vertical-align: 0.05em;
}
.ui .ic + .ic { margin-left: -0.1em; }
.section-title .ui, .info-column h3 .ui { font-size: 0.8em; vertical-align: 0.1em; }

/* teclas (Alt P…): planas y cuadradas, como en portfolio-web-ia */
.guide-section kbd {
  display: inline-block;
  padding: 0 0.45em;
  background: var(--color-surface-raised);
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.85em;
  line-height: 1.5;
}

/* ---------- Vibe coding: frase destacada y prompts de ejemplo ---------- */
/* frase destacada (No pidas «hazme una web entera»…): grande y centrada */
.content-body p.callout {
  max-width: none;
  margin: 2.5rem auto 0;
  text-align: center;
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  letter-spacing: 0.01em;
  font-size: clamp(1.2rem, 2.6vw, 1.55rem);
  font-weight: 700;
  line-height: 1.35;
  color: var(--color-text);
}
@media (min-width: 900px) {
  .content-body p.callout { white-space: nowrap; }
}
/* texto de cada columna (sin lista): secundario, como el de las listas */
.info-column > p {
  margin: 0;
  color: var(--color-text-soft);
  font-size: 0.95rem;
  line-height: 1.6;
}
/* prompt de ejemplo: bloque de cristal plano, con una etiqueta pequeña
   arriba (como las del esquema de Qué hay debajo) y el prompt en blanco */
.prompt-example {
  max-width: 760px;
  margin: 2.5rem auto 0;
  padding: 1.1rem 1.4rem 1.2rem;
  background: var(--color-surface-glass);
  backdrop-filter: blur(8px);
}
.prompt-example figcaption {
  margin-bottom: 0.5rem;
  color: var(--color-accent-soft);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 2px;
  text-transform: uppercase;
}
.prompt-example .prompt-note {
  margin-left: 0.5rem;
  color: var(--color-text-soft);
  letter-spacing: normal;
  text-transform: none;
  font-style: italic;
  font-size: 0.85rem;
}
.content-body .prompt-example p {
  margin: 0;
  color: var(--color-text);
  font-size: 1.02rem;
  line-height: 1.6;
}

/* ---------- Enlaces destacados (documentación de Lovable) ---------- */
/* las mismas tarjetas de cristal que el índice del taller (.index-card),
   apiladas y centradas. Dentro de .guide-section no llevan el color ni el
   subrayado de los enlaces del texto */
.link-cards {
  display: grid;
  gap: 1.1rem;
  max-width: 760px;
  margin: 2rem auto 0;
}
.guide-section a.index-card {
  color: var(--color-text);
  text-decoration: none;
}

/* ---------- De Lovable a tu editor ---------- */
/* Lovable ⇄ GitHub ⇄ tu editor: los nombres con su logo y las flechas del
   esquema de Qué hay debajo. En pantallas estrechas, en columna */
.sync-line {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 1.25rem;
  margin: 0 auto 3rem;
}
.sync-node {
  gap: 0.6rem;
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  letter-spacing: 0.01em;
  font-size: 1.35rem;
  font-weight: 700;
}
.sync-node img { width: 2rem; height: 2rem; }
@media (max-width: 720px) {
  .sync-line { flex-direction: column; gap: 0; }
  .sync-line .map-arrow-h { transform: rotate(90deg); margin-block: 1.1rem; }
}
/* logo delante del título de una columna (VS Code, Cursor) */
.h3-logo { display: inline-flex; vertical-align: -0.2em; margin-right: 0.5rem; }
.h3-logo img { width: 1.3rem; height: 1.3rem; }
/* los pasos, debajo de las columnas */
.steps-list.editor-steps { margin-top: 2.5rem; }
/* bloque de código (configuración JSON): plano y cuadrado como el código
   dentro del texto, en monoespaciada; si no cabe, se desplaza a lo ancho */
.code-block {
  margin: 0.75rem 0;
  padding: 0.9rem 1rem;
  background: var(--color-surface-raised);
  color: var(--color-text);
  font-family: ui-monospace, "Cascadia Code", Consolas, "Liberation Mono", monospace;
  font-size: 0.8rem;
  line-height: 1.5;
  overflow-x: auto;
}
.guide-section .code-block code { padding: 0; background: none; font-size: inherit; overflow-wrap: normal; }
.info-column > p + p,
.info-column > .code-block + p { margin-top: 0.5rem; }
/* comandos de la terminal: bloque más ancho y centrado, con los
   comentarios en gris; debajo, las notas */
.code-block.code-wide { max-width: 640px; margin: 0 auto; font-size: 0.9rem; }
.code-comment { color: var(--color-text-soft); }
.code-notes { margin-top: 2rem; }
.steps-list .code-block { margin: 0.6rem 0 0; }
/* enlaces en el esquema y en los títulos (GitHub, VS Code, Cursor): sin el
   color ni el subrayado de los enlaces del texto; al pasar, a naranja */
.guide-section a.sync-node,
.guide-section a.sync-logo,
.guide-section a.h3-link {
  color: inherit;
  text-decoration: none;
  transition: color .2s ease;
}
.guide-section a.sync-node:hover,
.guide-section a.h3-link:hover,
.guide-section a.sync-node:focus-visible,
.guide-section a.h3-link:focus-visible { color: var(--color-accent); }
.sync-logo { display: inline-flex; }
.sync-logo:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 3px; }

/* ---------- Backend e IA: esquema, mosaicos y prompts ---------- */
/* esquema: tu app ⇄ Lovable Cloud, con sus partes. Bloques de cristal como
   los de Qué hay debajo; en pantallas estrechas, en columna */
.backend-map {
  display: grid;
  grid-template-columns: 1fr auto 2fr;
  align-items: center;
  gap: 1.25rem;
  max-width: 820px;
  margin: 0 auto;
}
.backend-app, .backend-cloud {
  background: var(--color-surface-glass);
  backdrop-filter: blur(8px);
  padding: 1.25rem;
  text-align: center;
}
.backend-app strong { display: block; color: var(--color-text); font-size: 1.1rem; }
.backend-app .tile-icon { margin: 0.25rem 0 0.5rem; }
.backend-parts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem 0.75rem;
}
.backend-parts li {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  color: var(--color-text);
  font-size: 0.95rem;
}
.backend-parts .ic { width: 1.6rem; height: 1.6rem; color: var(--color-accent-soft); }
.content-body p.backend-caption { margin-top: 2rem; }
@media (max-width: 720px) {
  .backend-map { grid-template-columns: 1fr; }
  .backend-map .map-arrow-h { transform: rotate(90deg); margin-block: 1.1rem; }
}

/* mosaico de fichas (lo que hay en Más, métodos de inicio de sesión):
   icono grande en azul claro, nombre, una línea y, si hace falta, una
   etiqueta pequeña abajo */
.tile-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  max-width: 900px;
  margin: 0 auto;
}
@media (max-width: 720px) { .tile-grid { grid-template-columns: repeat(2, 1fr); } }
.tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  padding: 1.25rem 1rem;
  background: var(--color-surface-glass);
  backdrop-filter: blur(8px);
  text-align: center;
}
.tile strong { color: var(--color-text); font-size: 1.05rem; }
.tile > span:not(.tile-icon):not(.tile-tag) { color: var(--color-text-soft); font-size: 0.88rem; line-height: 1.45; }
.tile-icon { display: inline-flex; color: var(--color-accent-soft); }
.tile-icon .ic, .tile-icon img { width: 1.9rem; height: 1.9rem; }
.tile-tag {
  margin-top: 0.35rem;
  color: var(--color-accent-soft);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 2px;
  text-transform: uppercase;
}

/* lo que puede hacer la IA: etiquetas con icono, en una fila que se parte */
.ai-chips {
  list-style: none;
  margin: 0 auto 2rem;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  max-width: 760px;
}
.ai-chips li {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 1rem;
  background: var(--color-surface-glass);
  color: var(--color-text);
  font-weight: 500;
}
.ai-chips .ic { width: 1.25rem; height: 1.25rem; color: var(--color-accent-soft); }

.info-column h3 img { vertical-align: -0.15em; margin-right: 0.35rem; }

/* ---------- ¿Qué es una webapp? Página web frente a webapp ---------- */
/* dos columnas, una fila por diferencia, separadas por rayas finas como
   las de las listas. La columna de la webapp, en blanco y sobre cristal,
   porque es lo que vamos a hacer */
.compare {
  display: grid;
  grid-template-columns: 1fr 1fr;
  max-width: 820px;
  margin: 2.5rem auto 0;
}
.compare-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  padding: 1rem 1.25rem 0.75rem;
  font-family: "Plus Jakarta Sans", system-ui, sans-serif;
  letter-spacing: 0.01em;
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--color-accent-soft);
}
.compare-head .ic { width: 1.3rem; height: 1.3rem; }
.compare-cell {
  padding: 0.7rem 1.25rem;
  border-top: 1px solid var(--color-border);
  color: var(--color-text-soft);
  font-size: 0.95rem;
  line-height: 1.5;
}
.compare .compare-app {
  background: var(--color-surface-glass);
  color: var(--color-text);
}
/* el gif, justo debajo del título grande ¿Qué es Lovable? */
.guide-section.gif-section,
html.snap .snap-slide .guide-section.gif-section { margin-top: 2rem; }

/* ---------- Conectores ---------- */
/* fichas con los logos que llevan a la sección de cada conector: como las
   del backend, y al pasar el ratón el nombre se ilumina en naranja */
.tile-grid.tile-grid-5 { grid-template-columns: repeat(5, 1fr); margin-top: 2.5rem; }
@media (max-width: 860px) { .tile-grid.tile-grid-5 { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 520px) { .tile-grid.tile-grid-5 { grid-template-columns: repeat(2, 1fr); } }
.guide-section a.tile-link {
  gap: 0.6rem;
  color: var(--color-text);
  text-decoration: none;
  transition: background-color .25s ease;
}
.guide-section a.tile-link strong { font-size: 0.95rem; transition: color .25s ease; }
.guide-section a.tile-link:hover,
.guide-section a.tile-link:focus-visible { background: var(--color-surface-glass-hover); }
.guide-section a.tile-link:hover strong,
.guide-section a.tile-link:focus-visible strong { color: var(--color-accent); }
.tile-link img { width: 2rem; height: 2rem; }

/* cada conector: título con su logo (enlaza a su web); a la izquierda los
   pasos y a la derecha el prompt de ejemplo, la nota y el enlace a la
   documentación. En pantallas estrechas, uno debajo de otro */
.connector-title a { display: inline-flex; align-items: center; gap: 0.6rem; }
.connector-title img { width: 2rem; height: 2rem; }
.guide-section.connector,
html.snap .snap-slide .guide-section.connector { max-width: 1000px; }
.connector-body {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: 2.5rem;
  align-items: start;
}
@media (max-width: 860px) { .connector-body { grid-template-columns: 1fr; } }
.connector-body .steps-list { gap: 1.1rem; font-size: 0.95rem; }
.connector-side .prompt-example { margin: 0; }
.connector-side .link-cards { margin-top: 1.25rem; }
/* Calendly: en cada columna, los pasos y debajo su prompt y el enlace */
.connector .info-column .steps-list { gap: 1rem; font-size: 0.95rem; }
.connector .info-column .prompt-example { margin: 1.5rem 0 0; }
.connector .info-column .link-cards { margin-top: 1rem; }
.content-body p.connector-note {
  margin: 1.25rem 0 0;
  color: var(--color-text-soft);
  font-size: 0.9rem;
  font-style: italic;
}

/* ---------- Scroll por secciones (páginas con <html class="snap">) ---------- */
/* Solo en ordenador (ratón y pantalla con altura suficiente): cada
   .snap-slide ocupa una pantalla con su contenido centrado y el scroll salta
   de una a otra. En móvil y tablet el scroll es normal y valen los márgenes
   de siempre. js/secciones.js marca la sección activa para el fundido. */
/* la flechita de js/secciones.js solo existe en ordenador con encaje */
.scroll-hint { display: none; }
@media (min-width: 900px) and (min-height: 640px) and (hover: hover) and (pointer: fine) {
  html.snap {
    scroll-snap-type: y mandatory;
    scroll-behavior: smooth;    /* teclado y flechas: desplazamiento animado, no a saltos */
  }
  html.snap .content-body { padding-bottom: 0; }
  html.snap .snap-slide {
    min-height: 100dvh;
    scroll-snap-align: start;
    scroll-snap-stop: always;   /* una sección por gesto, sin saltarse ninguna */
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-block: 3.75rem;     /* hueco para Índice (arriba) y Anterior/Siguiente (abajo) */
  }

  /* la pantalla con el título no se centra: el título va a la misma altura
     que en el resto de páginas (mismo padding de .content-header) y lo que
     viene debajo se centra en el hueco que queda */
  html.snap .snap-slide:has(> .content-header) {
    padding-top: 0;
    justify-content: flex-start;
  }
  /* dentro de una pantalla sobran los márgenes grandes entre apartados */
  html.snap .snap-slide .guide-section { max-width: 860px; margin: 0 auto; }
  /* bajo el título, el bloque no se centra en el hueco (quedaba demasiado
     aire entre título y subtítulo): el aire que sobra se reparte un tercio
     entre título y bloque (la cabecera crece, con el título arriba) y dos
     tercios debajo del bloque (::after). Si el bloque es alto y no sobra
     nada, quedan al menos 2rem bajo el título */
  html.snap .snap-slide:has(> .content-header) > .content-header { flex: 1 0 auto; }
  html.snap .snap-slide:has(> .content-header)::after { content: ""; flex: 2 0 auto; }
  html.snap .snap-slide > .content-header ~ .guide-section { margin: 2rem auto 0; }

  /* fundido: la sección activa entera, las demás atenuadas mientras pasan */
  html.snap.snap-fade .snap-slide {
    opacity: 0.25;
    transition: opacity .9s cubic-bezier(.4, 0, .2, 1);
  }
  html.snap.snap-fade .snap-slide.is-active { opacity: 1; }

  /* mientras queden secciones por debajo (html.snap-pending, lo pone
     js/secciones.js) no se ven Anterior/Siguiente, sino una flechita centrada
     que baja a la siguiente; en la última sección vuelven los botones */
  .prev-link,
  .next-link { transition: color .2s ease, background-color .2s ease, opacity .25s ease, visibility .25s; }
  html.snap-pending .prev-link,
  html.snap-pending .next-link { opacity: 0; visibility: hidden; }
  .scroll-hint {
    position: fixed;
    z-index: 3;
    bottom: 1rem;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    padding: 0.3rem;
    border: 0;
    background: none;
    color: var(--color-text-soft);
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transition: color .2s ease, opacity .25s ease, visibility .25s;
  }
  .scroll-hint svg { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
  html.snap-pending .scroll-hint { opacity: 1; visibility: visible; }
  .scroll-hint:hover,
  .scroll-hint:focus-visible { color: var(--color-accent); }
  .scroll-hint:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; }
}
@media (prefers-reduced-motion: reduce) {
  html.snap.snap-fade .snap-slide { transition: none; }
  html.snap { scroll-behavior: auto; }
}
