/* Guía FastAPI · bloques de contenido: prosa, tablas, diagramas, comparativas y contratos.
 * Consume los tokens de css/tokens.css. Ningún color literal vive aquí. */

/* ---------- Páginas y bloques de contenido ---------- */

/* Dos medidas, no una.
 *
 * La prosa se queda en `--g-max-content` porque una línea de texto muy larga se
 * lee peor: al saltar de renglón la vista pierde el punto de retorno. Pero esa
 * misma medida asfixiaba al código, a las tablas y a las comparativas, que no
 * se leen renglón a renglón sino de un vistazo: en una pantalla ancha quedaban
 * dos columnas de 35 caracteres con barra de desplazamiento a los lados y el
 * resto del monitor en blanco.
 *
 * Así que la página crece hasta `--g-max-ancho` y solo el texto conserva su
 * medida. Los bloques que ganan con el espacio lo ocupan.
 */
.module-page {
  max-width: var(--g-max-ancho);
  margin: 0 auto;
}

.module-page > .module-head,
.module-page > .block {
  max-width: var(--g-max-content);
  margin-inline: auto;
}

/* Secciones cuyo contenido principal aprovecha todo el ancho disponible. */
.module-page > .block:has(> .dbc),
.module-page > .block:has(> .compare),
.module-page > .block:has(> .contract),
.module-page > .block:has(> .table-wrap),
.module-page > .block:has(> .diagram),
.module-page > .block:has(> .sim-shell),
.module-page > .block:has(> .mermaid-src) {
  max-width: 100%;
}

/* El encabezado de esas secciones sigue el ritmo del texto: un `h3` estirado a
   120 caracteres se ve como un error de maquetación, no como jerarquía. */
.module-page > .block:has(> .dbc) > h3,
.module-page > .block:has(> .compare) > h3,
.module-page > .block:has(> .contract) > h3,
.module-page > .block:has(> .table-wrap) > h3,
.module-page > .block:has(> .diagram) > h3 {
  max-width: var(--g-max-content);
  margin-inline: auto;
}

.module-head { margin-bottom: var(--sdk-spacing-xl); }
.module-head__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sdk-spacing-sm);
  font-size: 0.75rem;
  color: var(--sdk-text-secondary);
}
.module-head__meta span {
  padding: 0.15rem 0.55rem;
  border: 1px solid var(--sdk-glass-border);
  border-radius: var(--sdk-radius-xl);
}
.module-head h2 {
  margin: var(--sdk-spacing-sm) 0 0;
  font-size: clamp(1.35rem, 1.1rem + 1.6vw, 2rem);
  line-height: 1.2;
}
.module-head p { color: var(--sdk-text-secondary); }

.block { margin-bottom: var(--sdk-spacing-xl); }
.block h3 {
  font-size: clamp(1.05rem, 0.98rem + 0.5vw, 1.3rem);
  margin-bottom: var(--sdk-spacing-sm);
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--sdk-glass-border);
}
.block h4 { font-size: 1rem; margin-bottom: 0.4rem; }
.block ul, .block ol { padding-left: 1.15rem; }
.block li { margin-bottom: 0.35rem; }

/* `minmax(0, 1fr)` y no `1fr`: la columna de un grid tiene `min-width: auto`,
   que es el ancho minimo del contenido. Con un identificador largo dentro de un
   `code` ese minimo empuja la pagina entera a 320 px. */
.callout {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--sdk-spacing-md);
  padding: var(--sdk-spacing-md);
  border-radius: var(--sdk-radius-md);
  border-left: 4px solid var(--g-info);
  background: var(--sdk-bg-card);
}
.callout__icon { font-size: 1.3rem; line-height: 1; }
.callout p:last-child { margin-bottom: 0; }
.callout--peligro { border-left-color: var(--g-danger); }
.callout--ojo { border-left-color: var(--g-warn); }
.callout--clave { border-left-color: var(--g-fastapi); }
.callout--bien { border-left-color: var(--g-ok); }
.callout--movil { border-left-color: var(--g-flutter); }

/* ---------- Tarjeta de código (respaldo) ----------
 *
 * Los listados los pinta el módulo compartido `DevBrainSDK.code`, con su propia
 * hoja de estilos (`css/vendor/devbrain-learner-sdk.css`, clase `.dbc`). Lo que
 * queda aquí solo se ve si ese módulo no cargó, y se conserva porque quedarse
 * sin resaltado es aceptable, quedarse sin el código no.
 */

/* La barra superior no decora: dice el lenguaje, la ruta del archivo donde va
   el fragmento y ofrece copiarlo. En una guía con más de treinta listados, esas
   tres cosas son la diferencia entre pegar y transcribir a mano. */
.code-card {
  border: 1px solid var(--sdk-glass-border);
  border-radius: var(--sdk-radius-md);
  background: var(--sdk-bg-code);
  overflow: hidden;
}

.code-card__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sdk-spacing-sm);
  padding: 0.4rem 0.6rem;
  background: var(--g-tint-strong);
  border-bottom: 1px solid var(--sdk-glass-border);
}

.code-card__lang {
  flex: 0 0 auto;
  padding: 0.05rem 0.4rem;
  font-family: var(--sdk-font-code);
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--g-on-accent);
  background: var(--g-fastapi);
  border-radius: var(--sdk-radius-sm);
}

.code-card__path {
  flex: 1 1 12rem;
  min-width: 0;
  font-family: var(--sdk-font-code);
  font-size: 0.74rem;
  line-height: 1.35;
  color: var(--sdk-text-secondary);
  /* Sin ellipsis: la ruta completa es información, no adorno. */
  overflow-wrap: anywhere;
}

.code-card__copy {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  min-height: 2rem;
  padding: 0.25rem 0.6rem;
  font: inherit;
  font-size: 0.74rem;
  color: var(--sdk-text-secondary);
  background: var(--sdk-bg-card);
  border: 1px solid var(--sdk-glass-border);
  border-radius: var(--sdk-radius-sm);
  cursor: pointer;
  transition: color var(--g-fast), border-color var(--g-fast);
}
.code-card__copy:hover { color: var(--sdk-text-primary); border-color: var(--g-fastapi); }
.code-card__copy.is-ok { color: var(--g-ok); border-color: var(--g-ok); }
.code-card__copy.is-fail { color: var(--g-danger); border-color: var(--g-danger); }
.code-card__copy-icon { font-size: 0.9rem; line-height: 1; }

pre.code {
  margin: 0;
  padding: var(--sdk-spacing-md);
  background: var(--sdk-bg-code);
  overflow-x: auto;
  font-family: var(--sdk-font-code);
  font-size: 0.82rem;
  line-height: 1.6;
  /* Se desplaza en horizontal, no se ajusta. Envolver una línea larga manda su
     resto al margen izquierdo y borra la sangría, que es la única señal de qué
     está dentro de qué. Mejor una barra de desplazamiento que un listado cuya
     estructura no se puede leer. */
  white-space: pre;
  tab-size: 2;
  color: var(--sdk-text-primary);
}

/* Bloque suelto sin tarjeta (respaldo). */
pre.code:only-child {
  border: 1px solid var(--sdk-glass-border);
  border-radius: var(--sdk-radius-md);
}

.table-wrap { overflow-x: auto; }
.table-wrap table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
.table-wrap th, .table-wrap td {
  padding: 0.55rem 0.7rem;
  text-align: left;
  border-bottom: 1px solid var(--sdk-glass-border);
  vertical-align: top;
}
.table-wrap th { color: var(--g-fastapi); font-weight: 600; }

.checklist { list-style: none; padding: 0; }
.checklist li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--sdk-spacing-sm);
  padding: 0.45rem 0;
  border-bottom: 1px dashed var(--sdk-glass-border);
}

/* ---------- Diagramas nativos ---------- */

.diagram {
  margin: 0;
  padding: var(--sdk-spacing-md);
  background: var(--sdk-bg-card);
  border: 1px solid var(--sdk-glass-border);
  border-radius: var(--sdk-radius-lg);
}
.diagram__caption {
  margin-top: var(--sdk-spacing-md);
  font-size: 0.82rem;
  color: var(--sdk-text-secondary);
}

.diag-flow {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--sdk-spacing-sm);
}

.diag-node {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.6rem 0.8rem;
  background: var(--sdk-bg-primary);
  border: 1px solid var(--sdk-glass-border);
  border-top: 3px solid var(--sdk-text-muted);
  border-radius: var(--sdk-radius-md);
  min-width: 0;
}
.diag-node__icon { font-size: 1.15rem; line-height: 1; }
.diag-node__label { font-size: 0.9rem; line-height: 1.25; }
.diag-node__sub { font-size: 0.74rem; color: var(--g-text-soft); line-height: 1.3; }

.diag-node--actual { border-top-color: var(--g-fastapi); background: var(--g-fastapi-soft); }
.diag-node--siguiente { border-top-color: var(--g-flutter); background: var(--g-flutter-soft); }
.diag-node--ok { border-top-color: var(--g-ok); }
.diag-node--alerta { border-top-color: var(--g-warn); }
.diag-node--fallo { border-top-color: var(--g-danger); }

.diag-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  transform: rotate(90deg);
}
.diag-arrow svg { width: 1.5rem; height: 0.75rem; overflow: visible; }
.diag-arrow__line { stroke: var(--sdk-text-muted); stroke-width: 1.5; fill: none; }
.diag-arrow__head { fill: var(--sdk-text-muted); }

.diag-stack { display: grid; gap: var(--sdk-spacing-sm); }
.diag-layer {
  padding: 0.65rem 0.85rem;
  background: var(--sdk-bg-primary);
  border: 1px solid var(--sdk-glass-border);
  border-left: 4px solid var(--sdk-text-muted);
  border-radius: var(--sdk-radius-md);
}
.diag-layer--actual { border-left-color: var(--g-fastapi); }
.diag-layer--siguiente { border-left-color: var(--g-flutter); }
.diag-layer--ok { border-left-color: var(--g-ok); }
.diag-layer--alerta { border-left-color: var(--g-warn); }
.diag-layer__head { display: flex; align-items: center; gap: 0.5rem; }
.diag-layer__sub { display: block; font-size: 0.76rem; color: var(--sdk-text-secondary); }
.diag-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.45rem; }
.diag-chip {
  padding: 0.1rem 0.45rem;
  font-family: var(--sdk-font-code);
  font-size: 0.72rem;
  background: var(--sdk-bg-code);
  border: 1px solid var(--sdk-glass-border);
  border-radius: var(--sdk-radius-sm);
}

.diag-seq { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sdk-spacing-sm); }
.diag-seq__step {
  padding: 0.6rem 0.8rem;
  background: var(--sdk-bg-primary);
  border: 1px solid var(--sdk-glass-border);
  border-radius: var(--sdk-radius-md);
  counter-increment: paso;
}
.diag-seq__actors { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
.diag-seq__actor {
  padding: 0.1rem 0.5rem;
  font-size: 0.76rem;
  background: var(--sdk-bg-card);
  border: 1px solid var(--sdk-glass-border);
  border-radius: var(--sdk-radius-xl);
}
.diag-seq__arrow { color: var(--g-fastapi); font-size: 1rem; }
.diag-seq__msg { margin-top: 0.35rem; font-size: 0.88rem; }
.diag-seq__note { margin-top: 0.2rem; font-size: 0.76rem; color: var(--sdk-text-secondary); }

.mermaid-src { margin-top: var(--sdk-spacing-sm); }
.mermaid-src summary {
  cursor: pointer;
  font-size: 0.78rem;
  color: var(--sdk-text-secondary);
  padding: 0.25rem 0;
}
.mermaid-src summary:hover { color: var(--sdk-text-primary); }
.mermaid-src[open] summary { margin-bottom: 0.4rem; }

/* ---------- Comparativa a dos columnas ---------- */

.compare { display: grid; gap: var(--sdk-spacing-md); }
.compare > * { min-width: 0; }
.compare__col {
  padding: var(--sdk-spacing-md);
  background: var(--sdk-bg-card);
  border: 1px solid var(--sdk-glass-border);
  border-top: 3px solid var(--sdk-text-muted);
  border-radius: var(--sdk-radius-md);
  min-width: 0;
}
.compare__col--fastapi { border-top-color: var(--g-fastapi); }
.compare__col--flutter { border-top-color: var(--g-flutter); }
.compare__col--malo { border-top-color: var(--g-danger); }
.compare__col--bueno { border-top-color: var(--g-ok); }
.compare__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.45rem;
  margin-bottom: var(--sdk-spacing-sm);
}
.compare__icon { font-size: 1.1rem; }
.compare__head small { color: var(--sdk-text-secondary); font-size: 0.74rem; }
.compare__note { margin: 0.5rem 0 0; font-size: 0.84rem; color: var(--sdk-text-secondary); }

/* ---------- Contrato visual endpoint ⇄ pantalla ---------- */

.contract {
  padding: var(--sdk-spacing-md);
  background: var(--sdk-bg-card);
  border: 1px solid var(--sdk-glass-border);
  border-radius: var(--sdk-radius-lg);
}
.contract__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sdk-spacing-sm);
  margin-bottom: var(--sdk-spacing-md);
}
.contract__method {
  padding: 0.15rem 0.55rem;
  font-family: var(--sdk-font-code);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--g-on-accent);
  border-radius: var(--sdk-radius-sm);
  background: var(--sdk-text-muted);
}
.contract__method--get { background: var(--g-info); }
.contract__method--post { background: var(--g-ok); }
.contract__method--put, .contract__method--patch { background: var(--g-warn); }
.contract__method--delete { background: var(--g-danger); }
.contract__path {
  font-family: var(--sdk-font-code);
  font-size: 0.85rem;
  color: var(--sdk-text-primary);
  min-width: 0;
}
.contract__body { display: grid; gap: var(--sdk-spacing-md); }
.contract__body > * { min-width: 0; }
.contract__side { min-width: 0; }
.contract__kicker {
  display: block;
  margin-bottom: 0.4rem;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sdk-text-secondary);
}
.contract__side--app .contract__kicker { color: var(--g-flutter); }
.contract__note { margin: var(--sdk-spacing-md) 0 0; font-size: 0.84rem; color: var(--sdk-text-secondary); }

/* Teléfono simulado: marco sobrio, sin imágenes externas. */
.phone {
  max-width: 17rem;
  margin: 0 auto;
  padding: 0.55rem 0.5rem 0.9rem;
  background: var(--g-phone-frame);
  border: 2px solid var(--g-flutter);
  border-radius: 1.4rem;
  box-shadow: var(--g-shadow);
}
.phone::before {
  content: '';
  display: block;
  width: 3.2rem;
  height: 0.28rem;
  margin: 0 auto 0.5rem;
  background: var(--g-phone-notch);
  border-radius: 1rem;
}
.phone__screen {
  padding: 0.6rem;
  background: var(--g-phone-screen);
  border-radius: 0.9rem;
  min-height: 9rem;
}
.phone__title {
  padding-bottom: 0.4rem;
  margin-bottom: 0.5rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--g-phone-accent);
  border-bottom: 1px solid var(--g-flutter-line);
}
.phone__row {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.35rem 0.4rem;
  margin-bottom: 0.35rem;
  background: var(--g-tint-soft);
  border-radius: var(--sdk-radius-sm);
}
.phone__widget { font-family: var(--sdk-font-code); font-size: 0.7rem; color: var(--g-phone-accent); }
.phone__desc { font-size: 0.74rem; color: var(--g-phone-muted); line-height: 1.3; }

/* ---------- Ejercicio guiado ---------- *
 *
 * No es una variante de `callout`. Un ejercicio se distingue de una nota
 * porque el aprendiz tiene que hacer algo con él: lleva enunciado, pistas
 * plegadas y criterios de aceptación verificables. La pista va en <details>
 * a propósito —abrirla es una decisión, no un accidente de scroll—.
 */

.exercise {
  padding: var(--sdk-spacing-md);
  background: var(--sdk-bg-card);
  border: 1px solid var(--sdk-glass-border);
  border-inline-start: 4px solid var(--g-fastapi);
  border-radius: var(--sdk-radius-md);
}
.exercise__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  margin-bottom: var(--sdk-spacing-sm);
}
.exercise__badge {
  padding: 0.12rem 0.5rem;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--g-on-accent);
  background: var(--g-fastapi);
  border-radius: var(--sdk-radius-sm);
}
.exercise__title { margin: 0; font-size: 1rem; }
.exercise__time { font-size: 0.74rem; color: var(--sdk-text-secondary); }
.exercise__goal { margin: 0 0 var(--sdk-spacing-sm); }
.exercise__section {
  margin-top: var(--sdk-spacing-sm);
  font-size: 0.7rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--sdk-text-secondary);
}
.exercise { min-width: 0; }
.exercise ol, .exercise ul { margin: 0.35rem 0 0; padding-inline-start: 1.15rem; }
.exercise li { overflow-wrap: anywhere; }
.exercise li { margin-bottom: 0.3rem; }
.exercise__hint {
  margin-top: var(--sdk-spacing-sm);
  padding: 0.5rem 0.65rem;
  background: var(--g-tint-soft);
  border-radius: var(--sdk-radius-sm);
}
.exercise__hint summary {
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--g-fastapi);
}
.exercise__hint[open] summary { margin-bottom: 0.4rem; }
.exercise__hint p { margin: 0.3rem 0; font-size: 0.86rem; }

/* ---------- Tarjeta de descarga ---------- */

.download {
  display: grid;
  gap: var(--sdk-spacing-sm);
  padding: var(--sdk-spacing-md);
  background: var(--g-fastapi-soft);
  border: 1px solid var(--g-fastapi);
  border-radius: var(--sdk-radius-md);
}
.download__head { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.download__icon { font-size: 1.2rem; }
.download__title { margin: 0; font-size: 1rem; }
.download__desc { margin: 0; font-size: 0.88rem; color: var(--sdk-text-secondary); }
.download__files {
  margin: 0;
  padding-inline-start: 1.15rem;
  font-family: var(--sdk-font-code);
  font-size: 0.78rem;
  color: var(--sdk-text-secondary);
}
.download__actions { display: flex; flex-wrap: wrap; gap: var(--sdk-spacing-sm); }
.download__status { font-size: 0.8rem; color: var(--sdk-text-secondary); }
