/* specimen.css — andamio del espécimen Stella Nova.
   Sólo lo necesario para presentar los componentes en grilla y para la
   barra de control superior. NO redefine tokens — los usa. */

html, body { margin: 0; padding: 0; background: var(--sn-field); color: var(--sn-ink);
             font-family: var(--sn-font-text); font-size: var(--sn-fs-base);
             line-height: var(--sn-leading); }

body.spec { display: flex; flex-direction: column; min-height: 100vh; }

.vh { position: absolute; clip: rect(0 0 0 0); width: 1px; height: 1px;
      overflow: hidden; white-space: nowrap; border: 0; padding: 0; margin: -1px; }

/* — Barra superior del espécimen — sticky, no es el header del skin. */
.spec-top {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: var(--sn-s-5);
  padding: var(--sn-s-3) var(--sn-s-5);
  background: color-mix(in oklab, var(--sn-field) 90%, transparent);
  -webkit-backdrop-filter: saturate(1.4) blur(10px);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--sn-hairline-soft);
}
.spec-brand { display: inline-flex; align-items: baseline; gap: var(--sn-s-2);
              text-decoration: none; color: var(--sn-ink); }
.spec-brand-icon { align-self: center; flex: none;
                   /* Sigue el tema: el <rect> es currentColor (tinta) y la
                      constelación var(--sn-paper) — al inlinear el SVG estos
                      tokens cambian con data-sn-theme. */ }
.spec-brand-name { font-family: var(--sn-font-display); font-size: var(--sn-fs-md);
                   font-weight: 500; letter-spacing: -0.01em; }
.spec-brand-ver { color: var(--sn-ink-faint); font-size: var(--sn-fs-xs);
                  font-family: var(--sn-font-mono); }

.spec-nav { display: flex; gap: var(--sn-s-1); margin-inline-start: var(--sn-s-4); }
.spec-nav a { padding: var(--sn-s-1) var(--sn-s-3); border-radius: var(--sn-radius);
              text-decoration: none; color: var(--sn-ink-soft); font-size: var(--sn-fs-sm);
              transition: background var(--sn-dur-1), color var(--sn-dur-1); }
.spec-nav a:hover { background: var(--sn-sunk); color: var(--sn-ink); }
.spec-nav a[aria-current="page"] { color: var(--sn-ink); background: var(--sn-paper);
                                   box-shadow: var(--sn-lift-paper); }

.spec-controls { margin-inline-start: auto; display: flex; gap: var(--sn-s-3); }
.spec-seg { border: 0; padding: 0; margin: 0; display: inline-flex;
            background: var(--sn-sunk); border-radius: var(--sn-radius-pill);
            padding: 2px; }
.spec-seg button { border: 0; background: transparent; padding: var(--sn-s-1) var(--sn-s-3);
                   font: inherit; color: var(--sn-ink-soft); font-size: var(--sn-fs-xs);
                   border-radius: var(--sn-radius-pill); cursor: pointer;
                   transition: background var(--sn-dur-1), color var(--sn-dur-1); }
.spec-seg button[aria-pressed="true"] { background: var(--sn-paper); color: var(--sn-ink);
                                        box-shadow: var(--sn-lift-paper); }

/* — Layout general — */
.spec-main { flex: 1; max-width: 76rem; margin-inline: auto;
             padding: var(--sn-s-6) var(--sn-s-5); width: 100%; box-sizing: border-box; }
.spec-foot { padding: var(--sn-s-5); text-align: center; color: var(--sn-ink-soft);
             font-size: var(--sn-fs-xs); border-top: var(--sn-hair); }
.spec-foot a { color: var(--sn-ink-soft); }

.intro, .comp, .tokgrp { margin-bottom: var(--sn-s-7); }
.intro h1, .comp h1 { font-family: var(--sn-font-display); font-size: var(--sn-fs-display);
                      font-weight: 400; letter-spacing: -0.02em; margin: 0 0 var(--sn-s-3); }
.intro .lede, .comp .lede { max-width: 38rem; font-size: var(--sn-fs-md);
                            color: var(--sn-ink-soft); }
.intro .lede-sub { max-width: 38rem; color: var(--sn-ink-soft); font-size: var(--sn-fs-sm);
                   margin-top: var(--sn-s-3); }
.comp h2 { font-family: var(--sn-font-display); font-size: var(--sn-fs-lg);
           font-weight: 400; margin: 0 0 var(--sn-s-2); }
.comp .meta { color: var(--sn-ink-soft); font-size: var(--sn-fs-sm);
              max-width: 42rem; margin: 0 0 var(--sn-s-4); }

/* — Bloques demo: la "hoja" donde se monta cada componente — */
.demo {
  background: var(--sn-paper); color: var(--sn-ink);
  border-radius: var(--sn-radius-paper); box-shadow: var(--sn-lift-paper);
  padding: var(--sn-s-5); margin-top: var(--sn-s-3);
}
.demo-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
             gap: var(--sn-s-5); }
.demo-stack > * + * { margin-top: var(--sn-s-3); }
.demo-inline { display: flex; flex-wrap: wrap; gap: var(--sn-s-2); align-items: center; }
/* Demo de .full-width: el padding lateral del contenedor se iguala a
   --sn-paper-px (lo normal de .demo es --sn-s-5), para que el margin negativo
   de .full-width sangre EXACTO hasta el borde del demo. */
.demo--bleed { padding-inline: var(--sn-paper-px); }
.spec-bleed { background: var(--sn-sunk); color: var(--sn-ink-soft);
  padding: var(--sn-s-3); text-align: center; font-size: var(--sn-fs-sm); }

/* — Token grids — */
.tokgrp-h { font-family: var(--sn-font-display); font-size: var(--sn-fs-lg);
            font-weight: 400; margin: 0 0 var(--sn-s-4);
            padding-bottom: var(--sn-s-2); border-bottom: var(--sn-hair); }
.tokgrp-body { display: grid; gap: var(--sn-s-4); }
.grid-color { grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); }
.grid-size  { grid-template-columns: 1fr; }
.grid-other { grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr)); }

/* Swatch */
.sw { margin: 0; display: flex; gap: var(--sn-s-3); align-items: center;
      background: var(--sn-paper); padding: var(--sn-s-2);
      border-radius: var(--sn-radius); box-shadow: var(--sn-lift-paper); }
.sw-chip { width: 3rem; height: 3rem; flex: none; border-radius: var(--sn-radius);
           background: var(--sw-c); border: 1px solid var(--sn-hairline); }
.sw figcaption { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sw-var { font-family: var(--sn-font-mono); font-size: var(--sn-fs-xs);
          color: var(--sn-ink); overflow-wrap: anywhere; }
.sw-val { font-family: var(--sn-font-mono); font-size: var(--sn-fs-xs);
          color: var(--sn-ink-soft); }
.sw-note { font-size: var(--sn-fs-xs); color: var(--sn-ink-faint); margin-top: 2px; }

/* Comparador de tema — el MISMO swatch semántico resuelto en claro y oscuro.
   Cada lado fuerza `color-scheme`; como los roles de color usan light-dark(),
   cada columna resuelve su rama sola, sobre su propio fondo `--sn-field`. El
   lado oscuro replica además los 4 tokens de geometría (grain/lifts) y el GRAD
   de la serif, que NO usan light-dark() (se redefinen por tema en tokens.css),
   para que sombras y textura calcen con el modo oscuro real. */
.theme-duo { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sn-s-3);
             align-items: start; }
.theme-side { padding: var(--sn-s-3); border-radius: var(--sn-radius);
              background: var(--sn-field); color: var(--sn-ink);
              border: 1px solid var(--sn-hairline); }
.theme-side[data-demo-theme="light"] { color-scheme: light; }
.theme-side[data-demo-theme="dark"] {
	color-scheme: dark;
	--sn-field-grain: .05;
	--sn-lift-paper: 0 1px 1px rgba(0,0,0,.25), 0 3px 10px rgba(0,0,0,.35);
	--sn-lift:       0 1px 2px rgba(0,0,0,.35), 0 8px 22px rgba(0,0,0,.45), 0 24px 60px rgba(0,0,0,.4);
	--sn-lift-soft:  0 2px 12px rgba(0,0,0,.4);
	--sn-serif-grade: 30;
}
.theme-side-tag { display: inline-block; font-family: var(--sn-font-mono);
                  font-size: var(--sn-fs-xs); text-transform: uppercase;
                  letter-spacing: .08ex; color: var(--sn-ink-faint);
                  margin-bottom: var(--sn-s-3); }
.theme-side .grid-color { display: grid; grid-template-columns: 1fr;
                          gap: var(--sn-s-3); }
@media (max-width: 40rem) { .theme-duo { grid-template-columns: 1fr; } }

/* Size */
.sz { margin: 0; padding: var(--sn-s-3); background: var(--sn-paper);
      border-radius: var(--sn-radius); box-shadow: var(--sn-lift-paper);
      display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sn-s-4);
      align-items: center; }
.sz-bar { display: block; height: 1.25rem; width: var(--sz-w);
          background: var(--sn-ink); border-radius: 2px; max-width: 100%; }
.sz figcaption { display: flex; flex-direction: column; gap: 2px; text-align: end; }
.sz-var { font-family: var(--sn-font-mono); font-size: var(--sn-fs-xs);
          color: var(--sn-ink); }
.sz-val { font-family: var(--sn-font-mono); font-size: var(--sn-fs-xs);
          color: var(--sn-ink-soft); }
.sz-note { font-size: var(--sn-fs-xs); color: var(--sn-ink-faint); }

/* Type scale */
.ts { margin: 0; padding: var(--sn-s-3); background: var(--sn-paper);
      border-radius: var(--sn-radius); box-shadow: var(--sn-lift-paper);
      display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sn-s-4);
      align-items: baseline; line-height: 1.2; }
.ts-sample { font-family: var(--sn-font-display); color: var(--sn-ink); }
.ts figcaption { display: flex; flex-direction: column; gap: 2px; text-align: end;
                 font-size: var(--sn-fs-xs); line-height: 1.4; }
.ts-var { font-family: var(--sn-font-mono); color: var(--sn-ink); }
.ts-val { font-family: var(--sn-font-mono); color: var(--sn-ink-soft); }
.ts-note { color: var(--sn-ink-faint); }

/* Shadow */
.sh { margin: 0; padding: var(--sn-s-4); background: var(--sn-field);
      border-radius: var(--sn-radius); display: flex; gap: var(--sn-s-4);
      align-items: center; border: var(--sn-hair); }
.sh-box { width: 4rem; height: 4rem; flex: none; background: var(--sn-paper);
          border-radius: var(--sn-radius); }
.sh figcaption { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sh-var { font-family: var(--sn-font-mono); font-size: var(--sn-fs-xs); color: var(--sn-ink); }
.sh-val { font-family: var(--sn-font-mono); font-size: var(--sn-fs-xs); color: var(--sn-ink-soft);
          overflow-wrap: anywhere; }
.sh-note { font-size: var(--sn-fs-xs); color: var(--sn-ink-faint); }

/* KV genérico */
.kv { display: flex; flex-direction: column; gap: 2px; padding: var(--sn-s-3);
      background: var(--sn-paper); border-radius: var(--sn-radius);
      box-shadow: var(--sn-lift-paper); }
.kv-var { font-family: var(--sn-font-mono); font-size: var(--sn-fs-xs); color: var(--sn-ink); }
.kv-val { font-family: var(--sn-font-mono); font-size: var(--sn-fs-xs); color: var(--sn-ink-soft);
          overflow-wrap: anywhere; }
.kv-note { font-size: var(--sn-fs-xs); color: var(--sn-ink-faint); margin-top: 2px; }

/* — Colofón tipográfico — */
.colophon { display: grid; gap: var(--sn-s-5); }
.colophon-row {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr);
  gap: var(--sn-s-5); align-items: center;
  padding-bottom: var(--sn-s-4); border-bottom: var(--sn-hair);
}
.colophon-row:last-child { border-bottom: 0; padding-bottom: 0; }
.colophon-name {
  font-size: clamp(2.2rem, 1.6rem + 2vw, 3.2rem);
  line-height: 1.05; letter-spacing: -0.01em; color: var(--sn-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.colophon-meta {
  font-size: var(--sn-fs-sm); color: var(--sn-ink-soft);
  line-height: 1.6;
}
.colophon-meta strong { color: var(--sn-ink); font-weight: 500; }
.colophon-meta code { font-size: 0.95em; }

/* — Componentes propios del espécimen que el skin aún no cubre. — */
/* Botón base (refleja la capa semántica --sn-btn-*) */
.sn-btn {
  display: inline-flex; align-items: center; justify-content: center;
  height: var(--sn-ctl); padding: 0 var(--sn-s-4);
  font: inherit; font-size: var(--sn-fs-sm); font-weight: 500;
  background: var(--sn-btn-bg); color: var(--sn-btn-fg);
  border: 1px solid var(--sn-btn-border); border-radius: var(--sn-radius);
  cursor: pointer; transition: background var(--sn-dur-1), border-color var(--sn-dur-1);
}
.sn-btn:hover, .sn-btn[data-state="hover"] {
  background: var(--sn-btn-bg-hover); border-color: var(--sn-btn-border-hover);
}
.sn-btn:focus-visible { outline: none; border-color: var(--sn-focus-border);
                        box-shadow: var(--sn-focus-ring); }
.sn-btn[disabled] { color: var(--sn-ink-faint); cursor: not-allowed;
                    background: var(--sn-field-bg-disabled); }
.sn-btn-primary {
  background: var(--sn-btn-primary-bg); color: var(--sn-btn-primary-fg);
  border-color: var(--sn-btn-primary-bg);
}
.sn-btn-primary:hover, .sn-btn-primary[data-state="hover"] {
  background: var(--sn-btn-primary-bg-hover); border-color: var(--sn-btn-primary-bg-hover);
}
.sn-btn-danger {
  background: var(--sn-btn-danger-bg); color: var(--sn-btn-danger-fg);
  border-color: var(--sn-btn-danger-bg);
}
.sn-btn-danger:hover, .sn-btn-danger[data-state="hover"] { filter: brightness(.92); }
.sn-btn-ghost { background: transparent; border-color: transparent; color: var(--sn-ink-soft); }
.sn-btn-ghost:hover { background: var(--sn-sunk); color: var(--sn-ink); }

.btn-row { display: flex; align-items: center; gap: var(--sn-s-3); flex-wrap: wrap;
           padding: var(--sn-s-3) 0; border-bottom: var(--sn-hair); }
.btn-row:last-child { border-bottom: 0; }
.btn-row-label { font-size: var(--sn-fs-xs); color: var(--sn-ink-faint);
                 text-transform: uppercase; letter-spacing: 0.05em;
                 width: 6rem; flex: none; font-family: var(--sn-font-mono); }

/* Formularios */
.sn-form p { display: flex; flex-direction: column; gap: var(--sn-s-1); margin: 0 0 var(--sn-s-4); }
.sn-form label { font-size: var(--sn-fs-sm); color: var(--sn-ink-soft); }
.sn-form :is(input[type="text"], input[type="search"], textarea, select) {
  font: inherit; font-size: var(--sn-fs-base);
  background: var(--sn-field-bg); color: var(--sn-field-fg);
  border: 1px solid var(--sn-field-border); border-radius: var(--sn-radius);
  padding: var(--sn-s-2) var(--sn-s-3); width: 100%; box-sizing: border-box;
  transition: border-color var(--sn-dur-1), box-shadow var(--sn-dur-1);
}
.sn-form :is(input, textarea, select):focus {
  outline: none; border-color: var(--sn-focus-border); box-shadow: var(--sn-focus-ring);
}
.sn-form ::placeholder { color: var(--sn-field-placeholder); }
.sn-form :is(input[type="checkbox"], input[type="radio"]) {
  accent-color: var(--sn-ink); margin-inline-end: var(--sn-s-2);
}
.sn-form-actions { display: flex; flex-direction: row !important; gap: var(--sn-s-2); }

/* Tabs de página */
.sn-tabs { background: var(--sn-paper); border-radius: var(--sn-radius-paper);
           box-shadow: var(--sn-lift-paper); padding: 0 var(--sn-s-3); }
.sn-tabs ul { display: flex; gap: 0; list-style: none; margin: 0; padding: 0; }
.sn-tabs li a { display: inline-block; padding: var(--sn-s-3) var(--sn-s-4);
                color: var(--sn-ink-soft); text-decoration: none;
                font-size: var(--sn-fs-sm); border-bottom: 2px solid transparent;
                transition: color var(--sn-dur-1), border-color var(--sn-dur-1); }
.sn-tabs li a:hover { color: var(--sn-ink); }
.sn-tabs li.selected a { color: var(--sn-ink); border-bottom-color: var(--sn-nova); }
.sn-tabs li.new a { color: var(--sn-link); }

/* (Los "washes" .sn-wash-* eran clases INVENTADAS por el espécimen: no existen
   en el skin. Se retiraron. El patrón real de banda con lavado semántico es la
   familia .fondo-* del skin, documentada en "Bandas de fondo".) */

/* Badges: .sn-badge (+ variantes -nova/-ok/-warn/-danger) ahora es componente
   REAL del skin (resources/stella-nova.css), no specimen-only. El especimen
   carga stella-nova.css → los ejemplos se pintan con el componente shippeado;
   no se redefine aquí para no duplicar/divergir. */
.sn-pill { display: inline-flex; align-items: center; padding: 2px var(--sn-s-3);
           font-size: var(--sn-fs-xs); background: var(--sn-sunk);
           color: var(--sn-ink-soft); border-radius: var(--sn-radius-pill);
           font-family: var(--sn-font-mono); }

/* TOC */
.sn-toc { background: var(--sn-paper); border-radius: var(--sn-radius);
          padding: var(--sn-s-4); box-shadow: var(--sn-lift-paper); }
.sn-toc-h { font-family: var(--sn-font-display); font-size: var(--sn-fs-md);
            font-weight: 400; margin: 0 0 var(--sn-s-3); }
.sn-toc ol { list-style: none; margin: 0; padding: 0; }
.sn-toc ol ol { padding-inline-start: var(--sn-s-5); margin-top: var(--sn-s-1); }
.sn-toc li { margin: var(--sn-s-1) 0; }
.sn-toc a { display: inline-flex; align-items: baseline; gap: var(--sn-s-2);
            text-decoration: none; color: var(--sn-ink-soft);
            font-size: var(--sn-fs-sm); padding: 2px 0;
            border-inline-start: 2px solid transparent; padding-inline-start: var(--sn-s-2); }
.sn-toc a:hover { color: var(--sn-ink); }
.sn-toc a.active { color: var(--sn-ink); border-inline-start-color: var(--sn-nova); }
.sn-toc .num { font-family: var(--sn-font-mono); font-size: var(--sn-fs-xs);
               color: var(--sn-ink-faint); min-width: 1.5em; }

/* Tablas: SIN andamio propio del espécimen. El estilo real de
   `.wikitable` / `.smwtable` / `.broadtable` y de las fichas
   `table.plantilla` vive en stella-nova.css (que el espécimen carga) y se
   aplica dentro de `.sn-body`. Una regla `.wikitable` local aquí solo
   introduciría inexactitudes (p.ej. filas alternadas, que el skin NO usa:
   su diseño son filetes horizontales uniformes, cabecera transparente). */

/* Footer del simulacro de layout */
.demo-app .sn-footer { padding: var(--sn-s-6) 0; border-top: var(--sn-hair);
                       margin-top: var(--sn-s-6); }
.demo-app .sn-footer-inner { max-width: var(--sn-shell); margin-inline: auto;
                             padding-inline: var(--sn-s-5); display: flex;
                             justify-content: space-between; gap: var(--sn-s-5);
                             flex-wrap: wrap; }
.demo-app .sn-footer-col p { margin: 0; font-size: var(--sn-fs-sm);
                              color: var(--sn-ink-soft); }
.demo-app .sn-footer-tools ul { list-style: none; margin: 0; padding: 0;
                                 display: flex; gap: var(--sn-s-4);
                                 font-size: var(--sn-fs-sm); }
.demo-app .sn-footer-tools a { color: var(--sn-ink-soft); text-decoration: none; }
.demo-app .sn-footer-tools a:hover { color: var(--sn-ink); }

/* Demo del layout completo: dejarlo respirar contra el chrome del espécimen */
.demo-app { background: var(--sn-field); margin: calc(-1 * var(--sn-s-6))
                                           calc(-1 * var(--sn-s-5)); }
.demo-app .sn-shell { max-width: var(--sn-shell); margin-inline: auto;
                       padding: var(--sn-s-6) var(--sn-s-5); }
.demo-app .sn-paper { background: var(--sn-paper); border-radius: var(--sn-radius-paper);
                       box-shadow: var(--sn-lift-paper); padding: var(--sn-s-6); }
/* El CONTENIDO del paper (h1/h2/párrafos/enlaces/cita/aviso .sn-notice) NO se
   re-estila aquí: lo pinta la CSS REAL del skin (stella-nova.css, que el
   espécimen carga). El contenido del layout vive dentro de `.sn-body`, así que
   hereda tipografía, jerarquía de cabeceras, enlaces, blockquote y el aviso
   `.sn-notice` tal cual el skin — sin CSS custom que diverja. Antes esta zona
   forzaba cabeceras a la familia display (el skin ya usa --sn-font-text) y
   falseaba `.sn-notice` como caja simple (el real es la banda superior del
   paper con su token --sn-notice-bg): ambas cosas se retiraron. */

pre, code { font-family: var(--sn-font-mono); }
pre { background: var(--sn-sunk); padding: var(--sn-s-3) var(--sn-s-4);
      border-radius: var(--sn-radius); overflow-x: auto; font-size: var(--sn-fs-sm); }
code { background: var(--sn-sunk); padding: 1px 4px; border-radius: 2px;
       font-size: 0.9em; }
pre code { background: transparent; padding: 0; }

/* `.poem` ya está estilada por stella-nova.css (familia display,
   white-space: pre-wrap, `.poem br { display: none }`). No redefinir aquí. */

/* — Bloque "uso": código wikitexto a la izquierda, render a la derecha
   ── el editor lee la sintaxis y el efecto al mismo tiempo. Usa la
   misma `grilla cols-2` que el skin expone para wikitexto: el
   especímen demuestra el patrón usándolo. Bajo 56 rem colapsa a una
   sola columna (código arriba, render abajo). */
.spec-usage.grilla.cols-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sn-s-4);
  margin-top: var(--sn-s-3);
  margin-bottom: 0;
  align-items: stretch;
}
@media (max-width: 56rem) {
  .spec-usage.grilla.cols-2 { grid-template-columns: 1fr; }
}
.spec-usage > pre.howto-code {
  margin: 0;
  padding: var(--sn-s-4);
  background: var(--sn-sunk);
  border: 1px solid var(--sn-hairline-soft);
  border-radius: var(--sn-radius);
  font-family: var(--sn-font-mono);
  font-size: var(--sn-fs-xs);
  color: var(--sn-ink);
  line-height: 1.55;
  overflow-x: auto;
  white-space: pre;
}
.spec-usage > .demo { margin-top: 0; }

/* — Notas explicativas debajo del bloque de uso ── prosa secundaria
   sobre fondo sunk, para distinguirla del cuerpo editorial del demo. */
.spec-notes {
  margin-top: var(--sn-s-4);
  padding: var(--sn-s-3) var(--sn-s-4);
  background: var(--sn-sunk);
  border-radius: var(--sn-radius);
  font-size: var(--sn-fs-sm);
  color: var(--sn-ink-soft);
}
.spec-notes p { margin: 0 0 var(--sn-s-2); line-height: 1.55; }
.spec-notes p:last-child { margin-bottom: 0; }
.spec-notes p code { font-size: 0.92em; }

/* — Subtítulos dentro de un componente (p. ej. variantes de grilla) — */
.spec-subh {
  font-family: var(--sn-font-mono);
  font-size: var(--sn-fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 500;
  color: var(--sn-ink-soft);
  margin: var(--sn-s-5) 0 var(--sn-s-2);
}

/* — Celda neutra para demostrar grillas: contorno sobrio, contenido
   pequeño centrado — no compite con el contenido editorial real. */
.spec-cell {
  padding: var(--sn-s-4);
  background: var(--sn-sunk);
  border-radius: var(--sn-radius);
  text-align: center;
  font-family: var(--sn-font-mono);
  font-size: var(--sn-fs-sm);
  color: var(--sn-ink-soft);
}

/* Iconbutton mínimo (el stella-nova.css real lo cubre, pero el demo aislado
   no siempre está dentro de los selectores anclados al chrome) */
.sn-iconbtn { display: inline-grid; place-items: center;
              width: var(--sn-ctl); height: var(--sn-ctl);
              background: transparent; color: var(--sn-icon);
              border: 1px solid transparent; border-radius: var(--sn-radius);
              cursor: pointer; transition: background var(--sn-dur-1),
              color var(--sn-dur-1), border-color var(--sn-dur-1); }
.sn-iconbtn:hover { background: var(--sn-sunk); color: var(--sn-icon-active);
                    border-color: var(--sn-hairline); }

/* === Helpers tipográficos de contenido (espejo de MediaWiki:Common.css) ===
   Clases utilitarias que el editor teclea en el wikitexto (<span>, <div> o el
   atributo class= de una plantilla). Referencian los tokens de Stella Nova con
   fallback → se ven igual bajo Stella Nova y degradan a stacks/valores
   equivalentes en otros skins. Son ORTOGONALES: se combinan libremente
   (class="lg serif center nova"). Alcance .mw-parser-output .clase para
   ganarle a las reglas de cuerpo del skin.

   Pensadas para envolver el <p> que genera la wiki: una clase en el <div>
   contenedor (tamaño, familia, énfasis, color) se HEREDA al párrafo interno;
   la ALINEACIÓN se propaga explícitamente al <p> porque `.sn-body p` fija
   text-align: justify y, sin esto, ganaría por especificidad. */

/* — Tamaño — escala tipográfica; respeta la preferencia S/M/L del lector
     (--sn-font-scale). `jumbo` es el titular; lg/sm/xs afinan alrededor del
     cuerpo (que es el tamaño por defecto, sin clase). */
.mw-parser-output .jumbo {
	font-size: calc(clamp(2rem, 1.5rem + 2.2vw, 3.25rem) * var(--sn-font-scale, 1));
	line-height: 1.12;
}
.mw-parser-output .lg { font-size: var(--sn-fs-lg, 1.35rem); }
.mw-parser-output .sm { font-size: var(--sn-fs-sm, .88rem); }
.mw-parser-output .xs { font-size: var(--sn-fs-xs, .76rem); }

/* — Familia — fuerzan la familia (heredan a los hijos). */
.mw-parser-output .serif {
	font-family: var(--sn-font-serif, 'Roboto Serif','Iowan Old Style',Palatino,'Times New Roman',Georgia,serif);
}
.mw-parser-output .sans {
	font-family: var(--sn-font-sans, 'IBM Plex Sans',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif);
}
.mw-parser-output .mono {
	font-family: var(--sn-font-mono, 'IBM Plex Mono',ui-monospace,'SFMono-Regular','Cascadia Code',Menlo,Consolas,monospace);
}

/* — Énfasis — transformaciones que heredan al texto interno. */
.mw-parser-output .uppercase { text-transform: uppercase; letter-spacing: .04ex; }
.mw-parser-output .italic    { font-style: italic; }
.mw-parser-output .bold      { font-weight: 700; }

/* — Alineación — aplica al elemento Y a los <p>/<li>/leyendas que genera la
     wiki dentro (gana a `.sn-body p { text-align: justify }`). Las
     alineaciones no justificadas apagan la división de palabras. */
.mw-parser-output :is(.left, .center, .right) :is(p, li, figcaption) { hyphens: none; }
.mw-parser-output .left,    .mw-parser-output .left    :is(p, li) { text-align: left; }
.mw-parser-output .center,  .mw-parser-output .center  :is(p, li) { text-align: center; }
.mw-parser-output .right,   .mw-parser-output .right   :is(p, li) { text-align: right; }
.mw-parser-output .justify, .mw-parser-output .justify :is(p, li) { text-align: justify; }

/* — Color semántico — color de texto por rol (hereda al texto interno; voltea
     claro/oscuro porque los tokens usan light-dark). Para fondos y avisos en
     bloque, ver las cajas .wash del skin, no estas clases. */
.mw-parser-output .nova   { color: var(--sn-nova,   #c4361f); }
.mw-parser-output .ok     { color: var(--sn-ok,     #2e7d32); }
.mw-parser-output .warn   { color: var(--sn-warn,   #b26a00); }
.mw-parser-output .danger { color: var(--sn-danger, #b21e3e); }

/* === Galería nativa <gallery> (layout base) ============================
   El módulo del core `mediawiki.page.gallery.styles` aporta el LAYOUT de
   `ul.gallery.mw-gallery-traditional`; carga on-demand sólo en páginas con
   <gallery>, así que el espécimen estático lo replica. El COLOR/recuadro de
   cada caja y el tamaño de la leyenda ya los viste el skin
   (`.sn-body li.gallerybox div.thumb`, `.sn-body .gallerytext`). */
.mw-parser-output ul.gallery {
	list-style: none; margin: var(--sn-s-3) 0; padding: 0;
	display: flex; flex-wrap: wrap; gap: var(--sn-s-3);
}
.mw-parser-output li.gallerybox { display: flex; flex-direction: column; }
.mw-parser-output li.gallerybox div.thumb {
	display: flex; align-items: center; justify-content: center; margin: 0;
}
.mw-parser-output li.gallerybox div.thumb img { display: block; max-width: 100%; height: auto; }
.mw-parser-output .gallerytext { padding: var(--sn-s-1) .25rem 0; text-align: center; }

/* === Tarjeta .portafolio (espejo de Plantilla:Portafolio/style.css) =====
   Miniatura + título + alumnos + palabras clave. Suelta (p.ej. #ask inline)
   se auto-acomoda en filas con ancho base 16rem; dentro de una grilla pasa a
   celda (width:auto) y la separación la da el gap. */
.mw-parser-output .portafolio {
	display: inline-block; vertical-align: top; width: 16rem;
	margin: 0 var(--sn-s-3) var(--sn-s-3) 0; padding: var(--sn-s-2);
	background: var(--sn-paper-edge); border-radius: var(--sn-radius);
	position: relative;
}
/* Toda la tarjeta enlaza a su página (patrón "stretched link"). */
.mw-parser-output .portafolio .title a::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.mw-parser-output :is(.grilla, .grid) .portafolio { width: auto; margin: 0; }
.mw-parser-output .portafolio .thumb img { width: 100%; height: auto; }
.mw-parser-output .portafolio .text { font-size: var(--sn-fs-sm); line-height: 1em; margin: 0; text-align: left !important; }
.mw-parser-output .portafolio .text .title { display: block; margin: var(--sn-s-4) 0; font-weight: bold !important; }

/* === Ficha Personal (espejo de Plantilla:Ficha Personal/style.css) ======
   Foto circular + bio en dos columnas; típica de los #ask format=template
   que listan profesores (Categoría:Persona). */
.mw-parser-output .ficha-personal {
	display: grid; align-items: center; min-height: 10rem;
	grid-template-columns: 1fr 2fr; gap: 1rem; column-gap: 1rem;
	font-size: var(--sn-fs-sm); line-height: 120%; max-width: 24rem;
}
.mw-parser-output .ficha-personal > .foto > img { border-radius: 50%; }
.mw-parser-output .ficha-personal > .bio > h3.name {
	font-size: var(--sn-fs-xs) !important; line-height: 110%;
	text-transform: uppercase; font-weight: 500; letter-spacing: .08ex; margin: 0;
}
.mw-parser-output .ficha-personal > .bio > span.text { font-size: var(--sn-fs-xs); }

/* === Documento miniatura .dm (espejo de Plantilla:Documento miniatura/styles.css)
   Tarjeta de una fila: título enlazado + pie (autor · año) + guía. Se apila en
   columna larga desde un #ask que lista documentos/proyectos. Cada texto corre a
   `line-height: var(--sn-baseline)` (una línea base), y el relleno vertical usa
   `--sn-baseline-half` a cada lado → suma UNA línea base, así la tarjeta cierra en
   un número entero de baselines y una columna no acumula desfase. Es el consumidor
   canónico del token. NOTA DE SINCRONÍA: la plantilla viva aún usa
   `padding: var(--sn-s-3)` (la aproximación); el espécimen muestra el estado
   objetivo tras migrar a `--sn-baseline-half` (ver docs/tokens.css regla 4). */
.mw-parser-output .dm {
	position: relative;
	padding: var(--sn-baseline-half) var(--sn-s-3);
	box-shadow: inset 0 .5px 0 var(--sn-ink-faint);
	background-color: transparent;
	transition: background-color .6s ease;
}
.mw-parser-output .dm:hover { background-color: var(--sn-nova-wash); }
.mw-parser-output .dm-titulo { line-height: var(--sn-baseline); }
.mw-parser-output .dm-titulo a { color: var(--sn-ink); text-decoration: none; }
/* Stretched link: toda la tarjeta enlaza a su página. */
.mw-parser-output .dm-titulo a::after { content: ""; position: absolute; inset: 0; }
.mw-parser-output .dm:hover .dm-titulo a { color: var(--sn-nova); }
.mw-parser-output .dm-pie {
	display: flex; justify-content: space-between; align-items: baseline;
	gap: var(--sn-s-2); line-height: var(--sn-baseline);
	font-size: .82em; color: var(--sn-ink-faint);
}
.mw-parser-output .dm-autor { min-width: 0; font-size: var(--sn-fs-xs); }
.mw-parser-output .dm-autor a { color: inherit; text-decoration: none; }
.mw-parser-output .dm-anio { white-space: nowrap; font-variant-numeric: tabular-nums; align-self: end; }
.mw-parser-output .dm-guia { line-height: var(--sn-baseline); font-size: var(--sn-fs-xs); color: var(--sn-ink-faint); }
.mw-parser-output .dm-guia-etq { text-transform: uppercase; letter-spacing: .04em; font-size: .85em; opacity: .75; }
.mw-parser-output .dm-guia a { color: inherit; text-decoration: none; }

/* === Listado de Cursos .curso-listado (espejo de Plantilla:Listado de Cursos/style.css)
   Hermana de .dm para cursos: h4 enlazado + profesores (itálica) + alumnos. Mismo
   contrato de retícula: textos a `--sn-baseline` y relleno vertical
   `--sn-baseline-half` para cerrar en baselines enteras. Misma nota de sincronía
   que .dm (la plantilla viva aún usa `--sn-s-3`). */
.mw-parser-output .curso-listado {
	position: relative; margin: 0;
	padding: var(--sn-baseline-half) var(--sn-s-3);
	line-height: var(--sn-baseline);
	background-color: transparent;
	transition: background-color .6s ease;
}
.mw-parser-output .curso-listado:hover { background-color: var(--sn-nova-wash); }
.mw-parser-output .curso-listado h4 {
	margin: 0; font-family: var(--sn-font-text); font-weight: 500;
	font-size: var(--sn-fs-base); line-height: var(--sn-baseline);
}
.mw-parser-output .curso-listado h4 a { color: var(--sn-ink); text-decoration: none; }
.mw-parser-output .curso-listado h4 a::after { content: ""; position: absolute; inset: 0; }
.mw-parser-output .curso-listado:hover h4 a { color: var(--sn-nova); }
.mw-parser-output .curso-listado .profesores {
	font-family: var(--sn-font-text); font-style: italic;
	font-size: var(--sn-fs-sm); line-height: var(--sn-baseline); color: var(--sn-ink-faint);
}
.mw-parser-output .curso-listado .alumnos {
	font-family: var(--sn-font-text);
	font-size: var(--sn-fs-xs); line-height: var(--sn-baseline); color: var(--sn-ink-faint);
}
.mw-parser-output .curso-listado :is(.profesores, .alumnos) a { color: inherit; text-decoration: none; }
