/* ============================================================== */
/* InfoVis! — La Casita Tiembla — Stylesheet                      */
/* ============================================================== */

:root {
  --cream:  #f4ece0;
  --paper:  #ebe2d2;
  --ink:    #1a1a1a;
  --brick:  #c8442a;
  --wood:   #a86a3d;
  --ochre:  #d9a441;
  --ink10:  rgba(26,26,26,0.1);
  --ink20:  rgba(26,26,26,0.2);
  --ink50:  rgba(26,26,26,0.5);
  /* Aprueba / reprueba — azul y naranja quemado. Par azul-naranja:
     el estándar legible con daltonismo rojo-verde, y ambos con buen
     contraste como texto (el naranja oscuro, no un amarillo claro). */
  --ok:  #4059AD;
  --bad: #c75e1e;

  --ff-disp: 'Fraunces', serif;
  --ff-body: 'Archivo', sans-serif;
  --ff-mono: 'JetBrains Mono', monospace;

  --sidebar-w: 272px;
  --header-h:  52px;   /* alto del header fixed → offset de scroll-padding y anclas */
  --max-content: 840px;
  /* Light-orange accent for dark slide backgrounds (hero / moraleja /
     quote / audio / video). The main `--brick` (#c8442a) is too dark
     against #1a1a1a and degrades reading legibility — this peachy
     variant matches the audio label colour already in use. */
  --slide-accent: #ffb38a;
  /* Reading area scale (driven by the AAA toggle in the tool-rail):
     step 1 = current, step 2 = +8 %, step 3 = +18 %. Affects body
     text font-size and the max-width of the capsule column (which in
     turn lets images grow because they're sized at 100 % of column).
     Persisted to localStorage by site.js. */
  --reading-fs: 1rem;
}
body.text-size-2 {
  --max-content: 960px;
  --reading-fs: 1.08rem;
}
body.text-size-3 {
  --max-content: 1080px;
  --reading-fs: 1.18rem;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-padding-top: var(--header-h); }
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--ff-body);
  font-size: 15px;
  line-height: 1.65;
}
a { color: var(--brick); text-decoration: underline; text-underline-offset: 3px; }
a:hover { opacity: 0.8; }

/* ── HEADER ──────────────────────────────────────────────────── */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 300;
  height: 52px;
  background: var(--ink);
  color: var(--cream);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 1.5rem;
  border-bottom: 2px solid var(--brick);
  transition: transform 0.32s cubic-bezier(0.4, 0, 0.2, 1),
              box-shadow 0.28s ease;
  will-change: transform;
}
/* Auto-hide (driven by site.js): the bar tucks away while reading down
   and slides back on scroll-up. The soft shadow only appears once it's
   detached from the very top, so at rest it sits flush against the page. */
.site-header--hidden {
  transform: translateY(-100%);
}
.site-header--floating {
  box-shadow: 0 8px 22px -12px rgba(0, 0, 0, 0.5);
}
.brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
  color: var(--cream);
}
.brand:hover { opacity: 1; }
.brand-icon {
  display: inline-flex;
  width: 26px; height: 26px;
  color: var(--cream); /* drives the roof's currentColor */
  flex-shrink: 0;
}
.casita-icon { width: 100%; height: 100%; display: block; overflow: visible; }
.casita-icon-body {
  transform-origin: 16px 22px;
  animation: tremor-icon 1.6s ease-in-out infinite;
}
/* The roof rattles loose: hops up off the wall twice per tremor cycle,
   so the two pieces of the flat single-colour silhouette stay legible. */
.casita-icon .ci-roof {
  animation: casita-roof-hop 1.6s ease-in-out infinite;
}
@keyframes tremor-icon {
  0%, 100% { transform: rotate(-2.5deg); }
  50%      { transform: rotate(3deg); }
}
@keyframes casita-roof-hop {
  0%, 50%, 100% { transform: translateY(0); }
  25%, 75%      { transform: translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) {
  .casita-icon-body,
  .casita-icon .ci-roof { animation: none; }
  .site-header,
  .mnav, .mbar { transition: none; }
}
.brand-name {
  font-family: var(--ff-disp);
  font-weight: 900;
  font-size: 1.45rem;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--cream);
}
.brand-bang { color: var(--slide-accent); }
.brand-tagline {
  font-family: var(--ff-mono);
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(244,236,224,0.55);
  border-left: 1px solid rgba(244,236,224,0.25);
  padding-left: 0.7rem;
  margin-left: 0.3rem;
  white-space: nowrap;
}
@media (max-width: 980px) {
  .brand-tagline { display: none; }
}
.site-nav { display: flex; align-items: center; gap: 0.25rem; }
.nav-link {
  font-family: var(--ff-mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--cream);
  text-decoration: none;
  padding: 6px 10px;
  opacity: 0.65;
  transition: opacity 0.15s, border-color 0.15s;
  border-bottom: 2px solid transparent;
}
.nav-link:hover { opacity: 1; color: var(--cream); }
.nav-link.active { opacity: 1; border-bottom-color: var(--slide-accent); }

.page-body { padding-top: var(--header-h); }
/* Bare pages (e.g. programa.html when opened as standalone) have no
   fixed site-header, so the header-offset becomes wasted dead space.
   Use a small, calm top padding instead. */
.page-body.page-bare { padding-top: 1.5rem; padding-bottom: 2rem; }

/* ============================================================== */
/* HOME HERO — storytelling intro                                 */
/* ============================================================== */

/* The hero is now an editorial longform: a stack of independent
   blocks (intro, scenes, quote band, closing). */
.home-hero {
  background:
    radial-gradient(ellipse at 50% -10%, rgba(200,68,42,0.08), transparent 55%),
    var(--paper);
  border-bottom: 1px solid var(--ink20);
  position: relative;
  overflow: hidden;
}

/* ── Hero intro ──────────────────────────────────────────────── */
.hero-intro {
  max-width: 980px;
  margin: 0 auto;
  padding: 5.5rem 3rem 2.5rem;
  text-align: center;
}
.hero-tag {
  font-family: var(--ff-mono);
  font-size: 0.68rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brick);
  margin-bottom: 1.5rem;
}
.hero-title {
  font-family: var(--ff-disp);
  font-weight: 900;
  font-size: clamp(3.5rem, 10vw, 7.5rem);
  line-height: 0.84;
  letter-spacing: -0.045em;
  margin-bottom: 1.5rem;
}
.hero-title em { font-style: italic; color: var(--brick); }
.hero-lead {
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: clamp(1.1rem, 1.8vw, 1.4rem);
  line-height: 1.45;
  color: var(--ink50);
  max-width: 580px;
  margin: 0 auto;
}

/* ── Hero scene (two-column alternating) ─────────────────────── */
.hero-scene {
  max-width: 1080px;
  margin: 0 auto;
  padding: 4rem 3rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 3.5rem;
  align-items: center;
}
.hero-scene.scene-textleft  { grid-template-areas: "text art"; }
.hero-scene.scene-textright { grid-template-areas: "art text"; }
.hero-scene .scene-text { grid-area: text; }
.hero-scene .scene-art  { grid-area: art; display: flex; justify-content: center; }

.scene-label {
  font-family: var(--ff-mono);
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brick);
  margin-bottom: 1rem;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
}
.scene-label::before {
  content: "";
  display: inline-block;
  width: 28px; height: 1px;
  background: var(--brick);
}
.scene-text p {
  font-family: var(--ff-disp);
  font-size: 1.18rem;
  line-height: 1.55;
  margin-bottom: 0.9rem;
}
.scene-text p strong { font-weight: 700; color: var(--brick); }
.scene-text .scene-tail {
  font-style: italic;
  color: var(--ink50);
  font-size: 1.05rem;
}

/* The "still" casita art (calm scene) */
.casita-still {
  width: 100%;
  max-width: 320px;
  height: auto;
  overflow: visible;
  opacity: 0.9;
}

/* ── Quote band ──────────────────────────────────────────────── */
.hero-quote {
  margin: 2rem 0 0;
  padding: 4rem 2rem 4.5rem;
  text-align: center;
  border-top: 1px solid var(--ink20);
  border-bottom: 1px solid var(--ink20);
  background:
    repeating-linear-gradient(135deg,
      transparent 0, transparent 14px,
      rgba(200,68,42,0.025) 14px, rgba(200,68,42,0.025) 15px),
    var(--paper);
  position: relative;
}
.hero-quote::before,
.hero-quote::after {
  position: absolute;
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: 8rem;
  line-height: 1;
  color: var(--brick);
  opacity: 0.18;
  pointer-events: none;
}
.hero-quote::before { content: "“"; top: 1rem;    left: 1.5rem; }
.hero-quote::after  { content: "”"; bottom: -1rem; right: 1.5rem; }
.quote-text {
  font-family: var(--ff-disp);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.7rem, 4vw, 3rem);
  line-height: 1.18;
  letter-spacing: -0.015em;
  color: var(--brick);
  max-width: 880px;
  margin: 0 auto 1.3rem;
}
.quote-attr {
  font-family: var(--ff-mono);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink50);
}

/* ── Hero closing ────────────────────────────────────────────── */
.hero-closing {
  max-width: 820px;
  margin: 0 auto;
  padding: 4rem 3rem 5.5rem;
  text-align: center;
}
.closing-kicker {
  font-family: var(--ff-mono);
  font-size: 0.68rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brick);
  margin-bottom: 1.2rem;
}
.closing-line {
  font-family: var(--ff-disp);
  font-weight: 700;
  font-size: clamp(1.35rem, 2.6vw, 2rem);
  line-height: 1.28;
  letter-spacing: -0.015em;
  color: var(--ink);
  margin-bottom: 2.2rem;
}
.closing-line .cl-ve,
.closing-line .cl-oye,
.closing-line .cl-siente {
  font-style: italic;
  color: var(--brick);
  position: relative;
  white-space: nowrap;
}
.closing-line .cl-ve::after,
.closing-line .cl-oye::after,
.closing-line .cl-siente::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 2px;
  background: var(--brick);
  opacity: 0.4;
}

.hero-ctas { display: flex; gap: 0.75rem; flex-wrap: wrap; justify-content: center; }
.btn-primary {
  font-family: var(--ff-mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: var(--ink);
  color: var(--cream);
  padding: 11px 22px;
  text-decoration: none;
  border: none;
  cursor: pointer;
  transition: background 0.12s, transform 0.12s;
  display: inline-block;
}
.btn-primary:hover { background: var(--brick); color: var(--cream); transform: translateY(-1px); }
.btn-secondary {
  font-family: var(--ff-mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: transparent;
  color: var(--ink);
  padding: 10px 22px;
  text-decoration: none;
  border: 1px solid var(--ink);
  cursor: pointer;
  transition: all 0.12s;
  display: inline-block;
}
.btn-secondary:hover { background: var(--ink); color: var(--cream); }

/* ── Casita illustration ─────────────────────────────────────── */
.casita-large {
  width: 100%;
  max-width: 460px;
  height: auto;
  overflow: visible;
}
/* Subtle continuous tremor */
.casita-large .casita-body {
  transform-origin: 100px 160px;
  animation: tremor 1.8s ease-in-out infinite;
}
.casita-large .shake-waves {
  animation: pulse 3s ease-in-out infinite;
  transform-origin: 100px 100px;
}
@keyframes tremor {
  0%, 100% { transform: rotate(-3.2deg) translate(0,0); }
  20%      { transform: rotate(-2.6deg) translate(1px,0); }
  40%      { transform: rotate(-3.4deg) translate(-1px,1px); }
  60%      { transform: rotate(-2.8deg) translate(0px,-1px); }
  80%      { transform: rotate(-3.2deg) translate(1px,1px); }
}
@keyframes pulse {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: 0.55; transform: scale(1.04); }
}

/* Reduce motion preference */
@media (prefers-reduced-motion: reduce) {
  .casita-large .casita-body,
  .casita-large .shake-waves { animation: none; }
}

/* ============================================================== */
/* CAPSULES INTRO — separator between hero and capsule grid       */
/* ============================================================== */

.capsulas-intro,
.curso-intro {
  background: var(--ink);
  color: var(--cream);
  padding: 4rem 3rem;
  border-bottom: 2px solid var(--brick);
  /* No scroll-margin-top: `html { scroll-padding-top }` already offsets
     anchor jumps by the header height — adding it here doubled the gap,
     leaving a strip of the previous section above the black band. */
  text-align: center;
}
.ci-inner { max-width: 760px; margin: 0 auto; }
.ci-kicker {
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--slide-accent);
  margin-bottom: 1.1rem;
}
.ci-title {
  font-family: var(--ff-disp);
  font-weight: 900;
  font-size: clamp(2rem, 4vw, 3.1rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: var(--cream);
  margin-bottom: 1rem;
}
.ci-subtitle {
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: 1.1rem;
  color: rgba(244,236,224,0.72);
  max-width: 580px;
  margin: 0 auto;
}
/* El TOC dentro de la banda oscura "El curso" — texto claro sobre fondo ink. */
/* "el curso" en el título de la banda oscura — acento melocotón claro. */
.curso-intro .ci-title em { font-style: italic; color: var(--slide-accent); }
.curso-intro .cu-hero-toc { margin: 1.5rem 0 0; }
.curso-intro .cu-hero-toc a { color: var(--cream); }
.curso-intro .cu-hero-toc a:hover { color: var(--slide-accent); }
.curso-intro .cu-hero-toc b { color: var(--slide-accent); }

/* ============================================================== */
/* CAPSULES LAYOUT — sticky sidebar + page-flow main column       */
/* ============================================================== */

.capsulas-layout {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  align-items: start;
}

/* Sidebar — sticks once we scroll past hero */
.sidebar {
  position: sticky;
  top: var(--header-h);
  align-self: start;
  height: calc(100vh - var(--header-h));
  background: var(--cream);
  border-right: 1px solid var(--ink20);
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: var(--ink20) transparent;
  transition: top 0.32s cubic-bezier(0.4, 0, 0.2, 1),
              height 0.32s cubic-bezier(0.4, 0, 0.2, 1);
}
.sidebar-inner { padding: 0 0 2rem; }
/* When the smart header tucks away on scroll-down, the sidebar reclaims
   the freed strip and grows to the full viewport height. */
body.chrome-hidden .sidebar {
  top: 0;
  height: 100vh;
}

/* ── Resizable sidebar handle (drag logic in site.js) ──────────────── */
.sidebar-resizer {
  position: fixed;
  top: var(--header-h);
  left: calc(var(--sidebar-w) - 3px);
  width: 8px;
  height: calc(100vh - var(--header-h));
  z-index: 30;
  cursor: col-resize;
  display: none;
  transition: top 0.32s cubic-bezier(0.4, 0, 0.2, 1),
              height 0.32s cubic-bezier(0.4, 0, 0.2, 1);
}
body.chrome-hidden .sidebar-resizer {
  top: 0;
  height: 100vh;
}
body.in-capsules .sidebar-resizer { display: block; }
body.activities-mode .sidebar-resizer,
.sidebar-resizer.is-off { display: none !important; }
.sidebar-resizer::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0; left: 2px;
  width: 3px;
  background: var(--brick);
  opacity: 0;
  transition: opacity 0.12s ease;
}
.sidebar-resizer:hover::before,
.sidebar-resizer.dragging::before { opacity: 1; }
body.sidebar-resizing { user-select: none; }
body.sidebar-resizing * { cursor: col-resize !important; }
@media (max-width: 560px) {
  .sidebar-resizer { display: none !important; }
}
.sidebar-section-label {
  font-family: var(--ff-mono);
  font-size: 0.58rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink50);
  padding: 1rem 1.25rem 0.4rem;
}

/* ── Filter bar above the sidebar list ───────────────────────────── */
/* Pinned to the top of the sidebar's scroll area so it stays reachable
   while the capsule list scrolls underneath it. */
.sidebar-filter {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 1rem 1rem 0.55rem 1.25rem;
  border-bottom: 1px solid rgba(26,26,26,0.08);
  margin-bottom: 0.25rem;
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--cream);
}
.sidebar-filter .sidebar-section-label {
  padding: 0;
  flex: 0 0 auto;
}
.sidebar-filter-select {
  flex: 1 1 auto;
  font-family: inherit;
  font-size: 0.78rem;
  padding: 0.3rem 1.6rem 0.3rem 0.55rem;
  border: 1px solid rgba(26,26,26,0.18);
  border-radius: 4px;
  background-color: #ffffff;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%231a1a1a' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 0.5rem center;
  background-size: 10px;
  color: var(--ink);
  cursor: pointer;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.sidebar-filter-select:hover  { border-color: var(--brick); }
.sidebar-filter-select:focus  { outline: none; border-color: var(--brick); box-shadow: 0 0 0 2px rgba(200,68,42,0.15); }

/* When filter active, hide BOTH the sidebar items AND the capsule sections
   in the reading area that don't match the current type. Scoped via a
   data-filter attribute on the body. */
body[data-filter="teorica"] .sidebar-item.tecnica,
body[data-filter="teorica"] .sidebar-subitem.tecnica,
body[data-filter="teorica"] .cap-section.tecnica { display: none; }
body[data-filter="tecnica"] .sidebar-item.teorica,
body[data-filter="tecnica"] .sidebar-subitem.teorica,
body[data-filter="tecnica"] .cap-section.teorica { display: none; }
/* Evaluation milestones belong to the full sequence — show only in "Todas". */
body[data-filter="teorica"] .sidebar-eval,
body[data-filter="tecnica"] .sidebar-eval { display: none; }

/* ── Sidebar indent ladder ───────────────────────────────────────────
   Capsule items sit at the OUTERMOST level (closest to the left edge);
   h2 sub-items are indented further in; h3 sub-items deeper still.
   This visually reads as: cápsula (lowest level) → sección (h2) → sub-sección (h3).
   All entries reserve a 5 px border-left strip; that strip stays
   transparent normally and turns orange (brick / wood) when active.
   ─────────────────────────────────────────────────────────────────── */
.sidebar-item {
  display: flex;
  align-items: flex-start;          /* títulos largos pueden tener 2-3 líneas */
  gap: 0.3rem;
  padding: 0.55rem 0.85rem 0.55rem 0.4rem;
  cursor: pointer;
  text-decoration: none;
  color: var(--ink);
  /* NOTE: transitioning color OR border-left-color caused the active orange
     accent to get "stuck" at the inactive value in chromium / webkit —
     getComputedStyle would keep returning the start value even after the
     duration had elapsed.  Keep the transition only on `background`. */
  transition: background 0.12s;
  line-height: 1.3;
  border-left: 5px solid transparent;
}
.sidebar-item:hover { background: rgba(26,26,26,0.05); color: var(--ink); }

/* ── ACTIVE state — orange left accent + orange bold text, no dark bg ── */
.sidebar-item.active {
  background: transparent;
  border-left-color: var(--brick);
}
.sidebar-item.active:hover { background: rgba(200,68,42,0.06); }
.sidebar-item.active .si-num,
.sidebar-item.active .si-title { color: var(--brick); font-weight: 700; }
.sidebar-item.active .si-icon  { color: var(--brick); opacity: 1; }

/* ── Technical capsules — subtle wood tint, never dark when active ── */
.sidebar-item.tecnica {
  background: rgba(168,106,61,0.10);
}
.sidebar-item.tecnica:hover { background: rgba(168,106,61,0.18); }
.sidebar-item.tecnica.active {
  background: rgba(168,106,61,0.10);
  border-left-color: var(--wood);
}
.sidebar-item.tecnica.active .si-num,
.sidebar-item.tecnica.active .si-title { color: var(--wood); font-weight: 700; }

.si-num {
  font-family: var(--ff-mono);
  font-size: 0.6rem;
  letter-spacing: 0.02em;             /* tighter to take less horizontal room */
  color: var(--brick);
  min-width: 16px;                    /* was 24 — leaves more space for the title */
  flex-shrink: 0;
  padding-top: 3px;
}
.sidebar-item.tecnica .si-num { color: var(--wood); font-weight: 700; }
.sidebar-item.tecnica .si-title { color: #6f4524; }

/* ── Evaluation milestones — interrogaciones + project entregas woven
   into the sidebar at their point in the course sequence. Not capsules:
   no special fill, just the label in bold brick red — visible because of
   colour and weight contrast against the regular capsule rows. The link
   opens the pauta in a new tab. */
.sidebar-eval {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.55rem 0 0.3rem;
  padding: 0.45rem 0.85rem 0.35rem;
  text-decoration: none;
  background: transparent;
  color: var(--brick);
  transition: background 0.12s;
}
.sidebar-eval:hover {
  background: rgba(200, 68, 42, 0.07);
}
.se-ico { flex-shrink: 0; font-size: 0.95rem; line-height: 1; color: var(--brick); }
.se-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.se-label {
  font-family: var(--ff-mono);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 900;
  line-height: 1.2;
  color: var(--brick);
}
.se-date {
  font-family: var(--ff-mono);
  font-size: 0.6rem;
  letter-spacing: 0.05em;
  color: var(--wood);
  opacity: 0.8;
}
.se-ext { flex-shrink: 0; font-size: 0.9rem; color: var(--brick); opacity: 0.55; }
.sidebar-eval:hover .se-ext { opacity: 1; }

/* ── Sub-section anchors (one per <h2>/<h3>) ────────────────────────── */
.sidebar-subitem {
  display: block;
  padding: 0.28rem 0.9rem 0.28rem 1.95rem;   /* indented further than capsule title */
  font-size: 0.78rem;
  line-height: 1.3;
  color: var(--ink70, #555);
  text-decoration: none;
  border-left: 5px solid transparent;
  /* Same lesson as above — transitioning color / border-left-color silently
     breaks the orange-accent active state. */
  transition: background 0.12s;
}
/* Section number prefix shown in the sidebar (matches the CSS counter in
   the body, e.g. "1.1") — small monospace orange tag. */
.sidebar-subitem .si-num {
  display: inline-block;
  min-width: auto;
  margin-right: 0.4em;
  font-family: var(--ff-mono);
  font-size: 0.66rem;
  color: var(--brick);
  font-weight: 600;
  letter-spacing: 0;
  padding-top: 0;
}
.sidebar-subitem.tecnica .si-num { color: var(--wood); }
.sidebar-subitem.active .si-num  { color: var(--brick); }
.sidebar-subitem.tecnica.active .si-num { color: var(--wood); }
.sidebar-subitem .ss-title {
  /* Title text follows the number; allowed to wrap below. */
}
.sidebar-subitem.level-3 {
  padding-left: 3.0rem;             /* deeper indent for h3's */
  font-size: 0.74rem;
  color: var(--ink50, #777);
}
.sidebar-subitem:hover {
  background: rgba(26,26,26,0.04);
  color: var(--ink);
}
.sidebar-subitem.active {
  background: transparent;
  color: var(--brick);
  font-weight: 700;
  border-left-color: var(--brick);
}
.sidebar-subitem.tecnica.active {
  color: var(--wood);
  border-left-color: var(--wood);
}

/* ── CAP-ACTIVE — extend the orange left border to every item belonging
   to the capsule that the user is currently reading. This makes the
   "you are inside capsule N" context visible at a glance: a tall
   orange ribbon spans the capsule header AND all its h2/h3 subitems,
   while the .active state (bold orange text) still pinpoints the exact
   reading position. ──────────────────────────────────────────────── */
.sidebar-item.cap-active,
.sidebar-subitem.cap-active { border-left-color: var(--brick); }
.sidebar-item.tecnica.cap-active,
.sidebar-subitem.tecnica.cap-active { border-left-color: var(--wood); }

/* ── Titles: wrap freely, no truncation, no ellipsis ── */
.si-title {
  font-size: 0.82rem;
  line-height: 1.32;
  flex: 1;                         /* prende tutta la larghezza disponibile */
  min-width: 0;                    /* abilita il wrap dentro flex */
  word-break: break-word;
  hyphens: auto;
}

.si-icon { font-size: 0.65rem; margin-left: auto; opacity: 0.5; flex-shrink: 0; padding-top: 3px; }
.si-tag {
  margin-left: auto;
  flex-shrink: 0;
  font-family: var(--ff-mono);
  font-size: 0.5rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  background: var(--wood);
  color: var(--cream);
  padding: 2px 6px;
  border-radius: 2px;
  line-height: 1.3;
  align-self: center;
}

/* Main scroll area — flows in the page now (no internal scroll) */
.capsulas-main { min-width: 0; }

/* Individual capsule section — centered inside the main column.
   Capsules are separated by whitespace alone (no divider rule): a big
   padding-bottom here + the next hero's generous padding-top open a
   clear, calm gap between one cápsula and the next. */
.cap-section {
  max-width: var(--max-content);
  margin: 0 auto;
  padding-bottom: 10rem;
}
.cap-section.tecnica { background: rgba(168,106,61,0.04); }

/* ── Capsule HERO ───────────────────────────────────────────────────
   The first thing you see when arriving at a capsule.  Lots of top
   air, a small "CÁPSULA NN" kicker label, the big title, the optional
   subtitle, and the audio player.  scroll-margin-top makes anchor
   clicks (#cap-{slug}) land the kicker just below the sticky header. */
.cap-hero {
  padding: 11rem 3rem 2.5rem;
  margin-bottom: 2rem;
  background: linear-gradient(180deg, rgba(245,233,208,0.35), transparent);
  /* html has `scroll-padding-top: var(--header-h)`, so the browser will
     already park the hero just below the sticky header on anchor clicks.
     Adding scroll-margin-top here would double the gap. */
}
.cap-section.tecnica .cap-hero {
  background: linear-gradient(180deg, rgba(168,106,61,0.10), transparent);
}
/* Hero head: capsule-number badge on the left, title block on the right. */
.hero-head {
  display: flex;
  align-items: flex-start;
  gap: 1.4rem;
}
.hero-head-main { flex: 1; min-width: 0; }
.cap-numbadge {
  flex: 0 0 auto;
  margin-top: 0.35rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: var(--brick);
  color: var(--cream);
  border-radius: 9px;
  padding: 0.5rem 0.8rem 0.62rem;
  line-height: 1;
}
.cap-numbadge-tec { background: var(--wood); }
.cnb-label {
  font-family: var(--ff-mono);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  opacity: 0.85;
}
.cnb-num {
  font-family: var(--ff-disp);
  font-weight: 900;
  font-size: 2rem;
  letter-spacing: -0.02em;
  margin-top: 0.15rem;
}

/* Body wrapper: keeps reading content centered without the hero's
   over-generous top padding. The end-of-capsule space lives on
   .cap-section's padding-bottom, so no bottom padding here. */
.cap-body { padding: 0 3rem; }

/* Anchor-click targets for h2/h3 inside a capsule — small ADDITIONAL
   breathing room on top of the global scroll-padding so the heading
   sits just below the sticky header with a visible gap.  (12 px of
   margin + the 52 px scroll-padding-top → heading appears ~12 px down
   from the bottom edge of the header.) */
.cap-section :is(h2, h3)[id^="sec-"] {
  scroll-margin-top: 12px;
}

/* Capsule header bar (technical tag pills row) */
.cap-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}
.cap-badge {
  font-family: var(--ff-mono);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: rgba(200,68,42,0.1);
  color: var(--brick);
  border: 1px solid rgba(200,68,42,0.25);
  padding: 3px 8px;
}
.cap-badge.tecnica {
  background: rgba(168,106,61,0.1);
  color: var(--wood);
  border-color: rgba(168,106,61,0.25);
}
.cap-tags { display: flex; gap: 4px; flex-wrap: wrap; }
.cap-tag {
  font-family: var(--ff-mono);
  font-size: 0.58rem;
  letter-spacing: 0.06em;
  background: var(--ink);
  color: var(--cream);
  padding: 2px 7px;
}
.present-btn {
  margin-left: auto;
  font-family: var(--ff-mono);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--ink20);
  padding: 4px 10px;
  cursor: pointer;
  transition: all 0.12s;
  white-space: nowrap;
}
.present-btn:hover, .present-btn.on { background: var(--ink); color: var(--cream); border-color: var(--ink); }

/* Capsule title */
.cap-title-row { margin-bottom: 1.25rem; }
.cap-h1 {
  font-family: var(--ff-disp);
  font-weight: 900;
  font-size: clamp(1.9rem, 3.5vw, 2.75rem);
  line-height: 0.95;
  letter-spacing: -0.025em;
}
/* Bigger, more "hero" feeling when sitting inside .cap-hero. */
.cap-hero .cap-h1 {
  font-size: clamp(2.3rem, 4.5vw, 3.4rem);
  line-height: 1.0;
}
.cap-subtitle {
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: 1.1rem;
  color: var(--wood);
  margin-top: 0.4rem;
}
.cap-hero .cap-subtitle { font-size: 1.25rem; }

/* Capsule song row — the rich .pl-row used to sit here; it's now the
   .cap-video-wrap (16:9 iframe + compact info subrow). The hero gives
   it a top margin so it doesn't touch the title row. */
.cap-hero .cap-video-wrap {
  margin-top: 1.75rem;
  margin-bottom: 0;
}

/* ── Capsule music-video block ──────────────────────────────────────
   Each teorica cápsula hero embeds an iframe of the song's videoclip
   (see capsules.render_video_row + canciones/video.html). The
   iframe owns the audio; the site shell mirrors playback state into
   the sticky mini-player via postMessage.

   Layout: full hero width (≤ 920px content column), 16:9 letterbox
   via aspect-ratio, dark frame so the orange/red interior reads as a
   "screen". Compact meta strip below: number badge + title + author +
   external-link icon to open the video standalone in a new tab. */
.cap-video-wrap {
  width: 100%;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
}
.cap-video-wrap.is-placeholder { opacity: 0.85; }

.cap-video-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--ink);
  border: 2px solid var(--ink);
  box-shadow:
    0 10px 30px rgba(26,26,26,0.30),
    0 3px 6px rgba(26,26,26,0.18);
  overflow: hidden;
}
.cap-video-frame.is-empty {
  display: grid;
  place-items: center;
}
.cv-empty {
  font-family: var(--ff-mono);
  font-size: 0.78rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--cream);
  opacity: 0.55;
}
iframe.cap-video {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: var(--ink);
}

/* ── Video slot + placeholder ────────────────────────────────────────
   Each capsule hero (and the playlist central player) has a SLOT —
   a positioned container that hosts the single #main-video iframe
   when it lands here. While the iframe is parked elsewhere the slot
   shows a placeholder (cover thumbnail + big play button); CSS
   :has() detects iframe presence and hides the placeholder. */
.cap-video-slot {
  position: relative;
  width: 100%;
  height: 100%;
  background: var(--ink);
  overflow: hidden;
}
.cap-video-slot > iframe.cap-video {
  position: absolute;
  inset: 0;
}
/* Hide placeholder only when the slot's iframe has been promoted
   (data-src → src happens on first play) AND it's not currently
   lifted out as the playlist overlay. While the iframe is overlayed
   the placeholder stays visible to fill the slot's normal spot. */
.cap-video-slot:has(> iframe.cap-video[src]:not(.floats-over))
  .cv-placeholder {
  display: none;
}

/* Floating-over class — set in playlist mode to lift the playing
   iframe out of its capsule slot visually. position:fixed with inline
   top/left/width/height set by JS measureAndApplyOverlay. */
iframe.cap-video.floats-over {
  position: fixed;
  z-index: 50;
  pointer-events: auto;
  background: var(--ink);
}
.cv-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: var(--ink);
  overflow: hidden;
}
.cv-cover {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.55;
  transition: opacity 0.2s;
}
.cv-placeholder:hover .cv-cover { opacity: 0.78; }

.cv-play-btn {
  position: relative;
  z-index: 2;
  all: unset;
  cursor: pointer;
  width: 88px;
  height: 88px;
  border-radius: 50%;
  background: var(--slide-accent, #ffb38a);
  color: var(--ink);
  display: grid;
  place-items: center;
  box-shadow: 0 10px 30px rgba(0,0,0,0.50);
  transition: transform 0.2s, background 0.2s;
  padding-left: 6px;     /* visual centre for the triangle */
}
.cv-placeholder:hover .cv-play-btn,
.cv-play-btn:hover {
  transform: scale(1.08);
  background: var(--ochre, #d9a441);
}
@media (max-width: 720px) {
  .cv-play-btn { width: 64px; height: 64px; }
  .cv-play-btn svg { width: 30px; height: 30px; }
}
.cv-empty-hint {
  position: relative;
  z-index: 2;
  font-family: var(--ff-mono);
  font-size: 0.78rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--cream);
  opacity: 0.7;
  padding: 0.6em 1em;
  background: rgba(0,0,0,0.45);
  border-radius: 4px;
}

/* The hidden parking spot for #main-video when no song is loaded. */
#video-stash {
  position: fixed;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  pointer-events: none;
}
#video-stash[hidden] { display: none; }

.cap-video-meta {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0 0.25rem;
}
.cvm-num {
  font-family: var(--ff-mono);
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--brick);
  min-width: 2.6ch;
  text-align: right;
  padding-top: 2px;
}
.cvm-text {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}
.cvm-kicker {
  font-family: var(--ff-mono);
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink70);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cvm-title {
  font-family: var(--ff-disp);
  font-style: italic;
  font-weight: 900;
  font-size: 1.4rem;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0;
}
.cvm-author {
  font-family: var(--ff-body);
  font-size: 0.78rem;
  color: var(--ink70);
  font-style: italic;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
/* Avatar generico dell'autore (silhouette di una persona). L'autore è un
   personaggio inventato — il pittogramma rinforza il fatto che la canzone
   "ha un autore". 20×20, colore esplicito (no var, non era definito). */
.cvm-avatar {
  width: 20px; height: 20px;
  flex: 0 0 auto;
  fill: none;
  stroke: #555;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.85;
}
.cvm-badge-ph {
  display: inline-block;
  font-family: var(--ff-mono);
  font-size: 0.55rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 2px 7px;
  margin-left: 0.6rem;
  vertical-align: middle;
  background: var(--ink20);
  color: var(--ink);
  border-radius: 999px;
}
.cvm-standalone {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  color: var(--ink);
  background: transparent;
  border: 1.5px solid var(--ink20);
  transition: background 0.12s, color 0.12s, border-color 0.12s;
  text-decoration: none;
}
.cvm-standalone:hover {
  background: var(--brick);
  color: var(--cream);
  border-color: var(--brick);
}

@media (max-width: 720px) {
  .cap-video-wrap { gap: 0.55rem; }
  .cvm-title { font-size: 1.15rem; }
  .cvm-kicker { font-size: 0.58rem; letter-spacing: 0.14em; }
  .cvm-author { font-size: 0.72rem; }
  .cvm-standalone { width: 28px; height: 28px; }
}

/* Tech links */
.cap-tech-links {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-top: 3.5rem;
  padding: 0 3rem;
}
.cap-link-btn {
  font-family: var(--ff-mono);
  font-size: 0.65rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--cream);
  background: var(--wood);
  padding: 7px 14px;
  text-decoration: none;
  transition: opacity 0.12s;
}
.cap-link-btn:hover { opacity: 0.82; color: var(--cream); }

/* ── DEMO NOTE (inline, sits right under each demo image) ────── */
/* Used inside .cap-body markdown via <div class="demo-note didactica|esperada">…</div> */
.cap-body .demo-note {
  display: block;
  width: fit-content;
  max-width: 100%;
  margin: -0.85rem auto 1.5rem;          /* slight negative top — sticks to image bottom */
  padding: 0.45rem 0.85rem;
  font-family: var(--ff-mono);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.45;
  text-align: center;
}
.cap-body .demo-note.didactica {
  background: rgba(26,26,26,0.06);
  color: var(--ink50);
  border-left: 3px solid var(--ink20);
  border-right: 3px solid var(--ink20);
}
.cap-body .demo-note.esperada {
  background: rgba(200,68,42,0.1);
  color: var(--brick);
  border-left: 3px solid var(--brick);
  border-right: 3px solid var(--brick);
  font-weight: 600;
}
.cap-body .demo-note b { font-weight: 700; }

/* ── DEMO RESOURCE (secondary code link under physical-demo videos) ───── */
/* Used inside .cap-body markdown via <div class="demo-resource">💻 …</div>
   Pattern: under a {{YTV::}} block of a student physical project, this
   row holds the link to the source code + sensor metadata. */
.cap-body .demo-resource {
  display: block;
  margin: -0.85rem auto 1.6rem;
  padding: 0.5rem 0.9rem;
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  line-height: 1.55;
  color: var(--ink50);
  background: rgba(26,26,26,0.035);
  border-left: 2px dashed var(--ink20);
  max-width: 100%;
}
.cap-body .demo-resource a {
  color: var(--brick);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.cap-body .demo-resource a:hover { opacity: 0.78; }
.cap-body .demo-resource code {
  font-size: 0.92em;
  padding: 1px 5px;
  background: rgba(168,106,61,0.08);
  border-radius: 3px;
  color: var(--wood);
}

/* ── LEVELS CALLOUT (deprecated — kept for backwards compat) ─── */
.cap-levels-callout {
  margin: 0 0 1.75rem;
  padding: 0.85rem 1rem;
  background: rgba(168,106,61,0.05);
  border-left: 3px solid var(--wood);
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.cap-levels-callout .lc-row {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  flex-wrap: wrap;
}
.cap-levels-callout .lc-tag {
  font-family: var(--ff-mono);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 3px 8px;
  white-space: nowrap;
  flex-shrink: 0;
}
.cap-levels-callout .lc-tag.didactica {
  background: rgba(26,26,26,0.08);
  color: var(--ink50);
  border: 1px solid var(--ink20);
}
.cap-levels-callout .lc-tag.esperada {
  background: var(--brick);
  color: var(--cream);
}
.cap-levels-callout .lc-text {
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--ink);
  flex: 1;
  min-width: 200px;
}

/* ── DEMO CARDS (didactic vs expected groups) ─────────────────── */
.cap-demos {
  margin-top: 3rem;
}
.cap-demos:first-of-type { margin-top: 3.5rem; }
.cap-demos-head {
  display: flex;
  align-items: baseline;
  gap: 0.85rem;
  flex-wrap: wrap;
  margin-bottom: 0.85rem;
}
.cd-kicker {
  font-family: var(--ff-mono);
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brick);
  font-weight: 700;
}
.cd-desc {
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: 0.92rem;
  color: var(--ink50);
  flex: 1;
  min-width: 200px;
}
.cap-demos-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 0.6rem;
}
.demo-card {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.7rem 0.95rem;
  text-decoration: none;
  transition: transform 0.12s, box-shadow 0.12s;
  border-left: 3px solid transparent;
}
.demo-card:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(0,0,0,0.08);
  opacity: 1;
}
.demo-card.didactica {
  background: rgba(26,26,26,0.04);
  border-left-color: var(--ink20);
  color: var(--ink);
}
.demo-card.didactica:hover { background: rgba(26,26,26,0.08); }
.demo-card.esperada {
  background: rgba(200,68,42,0.07);
  border-left-color: var(--brick);
  color: var(--ink);
}
.demo-card.esperada:hover { background: rgba(200,68,42,0.13); }
.dc-kind {
  font-family: var(--ff-mono);
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.demo-card.didactica .dc-kind { color: var(--ink50); }
.demo-card.esperada  .dc-kind { color: var(--brick); font-weight: 700; }
.dc-label {
  font-size: 0.92rem;
  line-height: 1.35;
  color: var(--ink);
}

/* ── Aprendizaje activo — capsule footer section ────────────────────
   Material per clase: links to Google Slides + Docs. Compact card
   grid with the official-looking Slides (yellow) and Docs (blue)
   icons rendered as inline SVG. Hover lifts the card slightly. */
/* Materials block — same 3rem horizontal inset as .cap-body so it lines
   up with the reading column; separated by whitespace, no divider rule. */
.cap-activities {
  margin: 4.5rem 0 0;
  padding: 0 3rem;
}
.cap-act-head { margin-bottom: 1.25rem; }
/* Header on a single line: "Material para clase" (ink) · "CÁPSULA 04"
   (brick) — title and capsule tag, hierarchised by colour and font. */
.cap-act-title {
  font-family: var(--ff-disp);
  font-weight: 800;
  font-size: 1.4rem;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0;
}
.cap-act-title .cap-act-sep {
  color: var(--ink20);
  font-weight: 400;
  margin: 0 0.12em;
}
.cap-act-title .cap-act-cap {
  font-family: var(--ff-mono);
  font-weight: 700;
  font-size: 0.72em;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brick);
}
.cap-section.tecnica .cap-act-title .cap-act-cap { color: var(--wood); }
.cap-act-sub {
  margin: 0.5rem 0 0;
  font-size: 0.88rem;
  color: var(--ink50);
  font-style: italic;
}
.cap-act-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 0.85rem;
}
.act-card {
  display: grid;
  grid-template-columns: 38px 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 14px 16px;
  background: #ffffff;
  border: 1px solid var(--ink10);
  border-radius: 6px;
  text-decoration: none;
  color: inherit;
  transition: transform 0.12s, border-color 0.12s, box-shadow 0.12s;
}
.act-card:hover {
  transform: translateY(-1px);
  border-color: rgba(26,26,26,0.22);
  box-shadow: 0 6px 16px rgba(0,0,0,0.06);
}
.act-icon {
  display: flex;
  align-items: center;
  justify-content: center;
}
.act-svg {
  width: 30px;
  height: 38px;
  display: block;
}
.act-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.act-kind {
  font-family: var(--ff-mono);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink50);
  font-weight: 600;
}
.act-title {
  font-family: var(--ff-disp);
  font-weight: 700;
  font-size: 0.98rem;
  color: var(--ink);
  line-height: 1.25;
}
.act-purpose {
  margin-top: 2px;
  font-size: 0.82rem;
  color: var(--ink70, #555);
  font-style: italic;
  line-height: 1.4;
}
.act-arrow {
  font-family: var(--ff-mono);
  font-size: 1rem;
  color: var(--ink50);
  align-self: start;
  margin-top: 4px;
  transition: transform 0.12s, color 0.12s;
}
.act-card:hover .act-arrow {
  color: var(--brick);
  transform: translate(2px, -2px);
}
.act-card.legacy {
  background: rgba(168,106,61,0.06);
  border-color: rgba(168,106,61,0.18);
}

/* ── ACTIVITIES VIEW — full-width tile grid toggled by the Activ.
   button in the tool rail. Body class `activities-mode` switches:
     - hides sidebar, the regular capsules column, the home hero
       and the capsules-intro band
     - hides the Presentar + Texto buttons (only the Activ. button
       stays so the user can toggle the view off)
     - shows the activities-view section (a tile per capsule with
       Aprendizaje activo material). ─────────────────────────────── */
.activities-view {
  display: none;
  max-width: 1400px;
  margin: 0 auto;
  padding: 3rem 2rem 5rem;
}
body.activities-mode .activities-view { display: block; }

body.activities-mode .home-hero,
body.activities-mode .curso-hero,
body.activities-mode .capsulas-intro,
body.activities-mode .capsulas-layout,
body.ejemplos-mode .home-hero,
body.ejemplos-mode .curso-hero,
body.ejemplos-mode .capsulas-intro,
body.ejemplos-mode .capsulas-layout { display: none; }
/* In activities-mode tanto «Presentar» como «Texto» se quedan visibles
   pero deshabilitados —no aplican sobre la vista de actividades—.
   Se rehabilitan al salir del modo actividades. */
body.activities-mode .tools-rail #mode-toggle,
body.activities-mode .tools-rail #text-size-toggle,
body.ejemplos-mode .tools-rail #mode-toggle,
body.ejemplos-mode .tools-rail #text-size-toggle {
  opacity: 0.32;
  pointer-events: none;
}

/* Activ. button active state: brick fill so it reads as ON. */
body.activities-mode #activities-toggle {
  background: var(--brick);
  border-color: var(--brick);
}
body.activities-mode #activities-toggle:hover { background: #b53a23; }

/* View header — kicker + big title + sub-paragraph. */
.aview-header {
  margin-bottom: 2.5rem;
  max-width: 800px;
}
.aview-kicker {
  display: inline-block;
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brick);
  font-weight: 700;
  margin-bottom: 0.6rem;
}
.aview-title {
  font-family: var(--ff-disp);
  font-weight: 900;
  font-size: clamp(2rem, 4vw, 3.4rem);
  line-height: 0.98;
  letter-spacing: -0.025em;
  color: var(--ink);
  margin: 0 0 0.8rem;
}
.aview-sub {
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: 1.05rem;
  color: var(--ink70, #555);
  line-height: 1.5;
}

/* Tile grid — one tile per capsule, auto-fill responsive columns. */
.aview-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
  gap: 1.5rem;
}
.aview-tile {
  background: rgba(255,255,255,0.55);
  border: 1px solid var(--ink10);
  border-radius: 6px;
  padding: 1.25rem 1.25rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
/* Flash applied (via JS) when the user opens the activities view from
   inside a cápsula: the tile of the NEXT cápsula with material pulses
   for ~2.4 s so the eye knows where the view jumped. */
.aview-tile.tile-highlight {
  animation: tile-pulse 0.7s ease-in-out 3 alternate;
}
@keyframes tile-pulse {
  from {
    border-color: var(--brick);
    background: rgba(199, 68, 42, 0.10);
    box-shadow: 0 0 0 0 rgba(199, 68, 42, 0);
  }
  to {
    border-color: var(--brick);
    background: rgba(199, 68, 42, 0.22);
    box-shadow: 0 0 0 6px rgba(199, 68, 42, 0.18);
  }
}
.atile-head {
  border-bottom: 1px solid var(--ink10);
  padding-bottom: 0.85rem;
}
.atile-cap-link {
  display: block;
  text-decoration: none;
  color: inherit;
}
.atile-cap-link:hover .atile-cap-title { color: var(--brick); }
.atile-num {
  display: inline-block;
  font-family: var(--ff-mono);
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brick);
  font-weight: 700;
  margin-bottom: 0.35rem;
}
.atile-cap-title {
  font-family: var(--ff-disp);
  font-weight: 800;
  font-size: 1.1rem;
  line-height: 1.2;
  color: var(--ink);
  letter-spacing: -0.01em;
  margin: 0;
  transition: color 0.15s;
}
.atile-acts {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
/* Smaller, denser act-cards inside the tile. */
.atile-acts .act-card {
  padding: 10px 12px;
  grid-template-columns: 28px 1fr auto;
  gap: 10px;
}
.atile-acts .act-svg { width: 22px; height: 28px; }
.atile-acts .act-title { font-size: 0.92rem; }
.atile-acts .act-purpose { font-size: 0.78rem; margin-top: 1px; }
.atile-acts .act-kind { font-size: 0.58rem; }
.atile-acts .act-arrow { font-size: 0.85rem; }

/* ── EJEMPLOS VIEW — example gallery, toggled by the "Ejemplos" nav link
   (body.ejemplos-mode). One bare video per row, in capsule order — a true
   filter over every {{EJEMPLO}} tagged across the course's capsules. */
.ejemplos-view {
  display: none;
  max-width: 760px;
  margin: 0 auto;
  padding: 3rem 2rem 5rem;
}
body.ejemplos-mode .ejemplos-view { display: block; }
.ev-header { margin-bottom: 2.5rem; }
.ev-kicker {
  display: inline-block;
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brick);
  font-weight: 700;
  margin-bottom: 0.6rem;
}
.ev-title {
  font-family: var(--ff-disp);
  font-weight: 900;
  font-size: clamp(2rem, 4vw, 3.4rem);
  line-height: 0.98;
  letter-spacing: -0.025em;
  color: var(--ink);
  margin: 0 0 0.8rem;
}
.ev-sub {
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: 1.05rem;
  color: var(--ink70, #555);
  line-height: 1.5;
}
.ev-list {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
/* Each card reuses the .demo-embed.video chrome (dark bar + frame), so it
   looks identical to the inline {{EJEMPLO}} block in the capsules. */
.ej-card { margin: 0; }
.ej-card .video-embed {
  position: relative;
  width: 100%;
  padding-top: 56.25%;
}
.ej-card .video-embed iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: none;
}
.ej-code {
  padding: 0.5rem 0.85rem;
  background: #f3efe8;
  border-top: 1px solid var(--ink15, rgba(0, 0, 0, 0.08));
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  color: var(--ink50);
}
.ej-code a {
  color: var(--brick);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.ej-code a:hover { opacity: 0.78; }
/* Student credits — shown inside the card, both in the inline {{EJEMPLO}}
   block and the Ejemplos view. */
.ej-credits {
  padding: 0.7rem 0.9rem;
  font-family: var(--ff-disp);
  font-size: 0.84rem;
  line-height: 1.55;
  color: var(--ink70, #555);
}
.ej-credits b { color: var(--ink); font-weight: 700; }
/* ── PLAYLIST VIEW — full-width song list toggled by the Playlist tool
   button (body.playlist-mode). Same hide-everything-else trick as the
   activities view; the row layout below is an attempt at "music-app"
   ergonomics: number + spinning vinyl + meta + controls, with an
   expandable lyrics panel per row.                              */
.playlist-view {
  display: none;
  max-width: 1400px;
  margin: 0 auto;
  padding: 2.5rem 1.5rem 5rem;
}
body.playlist-mode .playlist-view { display: block; }
body.playlist-mode .home-hero,
body.playlist-mode .curso-hero,
body.playlist-mode .capsulas-intro,
body.playlist-mode .activities-view,
body.playlist-mode .ejemplos-view { display: none; }

/* Capsulas-layout in playlist mode: park it off-screen but KEEP it
   rendering so the iframes inside each capsule (with .floats-over
   position:fixed) remain visible. We can NOT use display:none here
   (it cascades to position:fixed children too) and we can NOT use
   z-index:-1 (it creates a stacking context that traps the iframe
   even when the iframe has z-index:50 itself).

   Solution: position:absolute moves the layout off-flow without
   creating a stacking context, left:-200vw moves it visually off-
   screen, visibility:hidden hides every descendant. We then bring
   back the active iframe explicitly with visibility:visible. */
body.playlist-mode .capsulas-layout {
  position: absolute;
  left: -200vw;
  top: 0;
  width: 100vw;
  visibility: hidden;
  pointer-events: none;
}
body.playlist-mode iframe.cap-video.floats-over {
  visibility: visible;
  pointer-events: auto;
}

/* In playlist mode the slideshow + text-size buttons dim (they don't
   apply here). Activ. stays clickable so the user can jump straight to
   activities mode without first closing the playlist. */
body.playlist-mode .tools-rail #mode-toggle,
body.playlist-mode .tools-rail #text-size-toggle {
  opacity: 0.32;
  pointer-events: none;
}
/* When the playlist toggle is on, fill it brick so it reads as ACTIVE. */
body.playlist-mode #playlist-toggle {
  background: var(--brick);
  border-color: var(--brick);
}
body.playlist-mode #playlist-toggle:hover { background: #b53a23; }

/* ── Playlist body — 2-col grid: central iframe + scrollable side list.
   Mobile: stacks vertically (iframe on top, list below). The side-list
   is a flex column with overflow-y auto so it scrolls independently of
   the iframe on desktop. */
.plv-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(260px, 28vw, 360px);
  gap: 1.5rem;
  margin-top: 1.5rem;
  align-items: start;
}
.plv-player-col {
  /* Wrapper della colonna sinistra: player video + intro testuale sotto.
     L'intro cambia automaticamente quando si seleziona un'altra canzone
     (vedi site.js, promoteToCurrentSong). */
  display: flex;
  flex-direction: column;
  gap: 1.4rem;
  min-width: 0;
}
.plv-player {
  /* Inherits .cap-video-wrap layout (16:9 frame). The wrap class adds
     the gap+meta below, but in playlist mode we hide the meta — the
     side list already shows the title. */
  width: 100%;
}
.plv-player .cap-video-meta { display: none; }
/* Intro testuale della cápsula, sotto al video. Stesso contenuto del
   blockquote di apertura della pagina della cápsula. Solo l'articolo
   .is-active è visibile (gli altri 26 sono display:none — toggle via
   site.js quando cambia la canzone). */
.plv-intros {
  width: 100%;
  font-family: var(--ff-disp), Georgia, serif;
  font-size: 1.05rem;
  line-height: 1.55;
  color: var(--ink, #1a1a1a);
  border-left: 3px solid var(--brick, #c8442a);
  padding: 0.4rem 0 0.4rem 1rem;
}
.plv-intro { display: none; }
.plv-intro.is-active { display: block; }
.plv-intro p { margin: 0; }
.plv-intro strong { color: var(--brick, #c8442a); font-weight: 700; }
.plv-intro em { color: var(--wood, #a86a3d); font-style: italic; }
.plv-player .cap-video-frame {
  /* Slightly thicker frame to feel like a "main screen". */
  box-shadow:
    0 18px 50px rgba(26,26,26,0.32),
    0 6px 12px rgba(26,26,26,0.20);
}

.plv-sidelist {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  /* On desktop the list scrolls independently of the iframe so the
     player stays put. Height roughly matches the iframe (16:9 of a
     960px column ≈ 540px) + a bit more breathing room. */
  max-height: min(78vh, 720px);
  overflow-y: auto;
  padding-right: 6px;
  /* Custom scrollbar — narrow, brick on hover. */
  scrollbar-width: thin;
  scrollbar-color: var(--ink20) transparent;
}
.plv-sidelist::-webkit-scrollbar { width: 8px; }
.plv-sidelist::-webkit-scrollbar-track { background: transparent; }
.plv-sidelist::-webkit-scrollbar-thumb {
  background: var(--ink20);
  border-radius: 4px;
}
.plv-sidelist::-webkit-scrollbar-thumb:hover { background: var(--brick); }

.plv-side-row {
  all: unset;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: 0.7rem;
  padding: 0.5rem;
  background: rgba(255,255,255,0.45);
  border: 1px solid var(--ink10);
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, transform 0.08s;
  font-family: var(--ff-body);
}
.plv-side-row:hover {
  background: rgba(255,255,255,0.85);
  border-color: var(--ink20);
}
.plv-side-row:active { transform: scale(0.995); }
.plv-side-row.is-selected {
  background: rgba(199, 68, 42, 0.10);
  border-color: var(--brick);
  box-shadow: inset 3px 0 0 var(--brick);
}
.plv-side-row.is-placeholder { opacity: 0.55; }

.plv-thumb-wrap {
  position: relative;
  width: 96px;
  height: 54px;             /* 16:9 */
  border-radius: 4px;
  overflow: hidden;
  background: var(--ink);
  display: grid;
  place-items: center;
  flex-shrink: 0;
}
.plv-thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.plv-thumb-play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--cream);
  font-size: 1.5rem;
  background: rgba(0, 0, 0, 0.30);
  opacity: 0;
  transition: opacity 0.15s;
}
.plv-thumb-empty .plv-thumb-play {
  opacity: 1;
  background: var(--ink);
  color: var(--ink40);
}
.plv-side-row:hover .plv-thumb-play { opacity: 1; }
.plv-side-row.is-selected .plv-thumb-play {
  opacity: 1;
  background: rgba(199, 68, 42, 0.55);
}

.plv-side-meta {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  gap: 0.1rem;
}
.plv-side-num {
  font-family: var(--ff-mono);
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brick);
  font-weight: 700;
}
.plv-side-title {
  font-family: var(--ff-disp);
  font-style: italic;
  font-weight: 800;
  font-size: 0.98rem;
  line-height: 1.15;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.plv-side-cap {
  font-family: var(--ff-mono);
  font-size: 0.58rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink70);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Mobile: stack iframe over sidelist; sidelist no longer scrolls
   independently (gets the page scroll). */
@media (max-width: 900px) {
  .plv-body {
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
  }
  .plv-sidelist {
    max-height: none;
    overflow-y: visible;
    padding-right: 0;
  }
}

/* ── Hide every legacy lyrics affordance ──────────────────────────────
   The lyrics modal and its toggle button are gone now — subtitles live
   inside the video. If any markup straggles in from older HTML cache,
   suppress it visually instead of breaking layout. */
.pl-lyrics, .pl-lyrics-toggle, .pl-lyr-ico, .pl-lyr-label { display: none !important; }

/* Header — kicker + big title + sub-paragraph + author + stats. */
.plv-header { margin-bottom: 0.75rem; max-width: 720px; }
.plv-kicker {
  display: inline-block;
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brick);
  font-weight: 700;
  margin-bottom: 0.6rem;
}
.plv-title {
  font-family: var(--ff-disp);
  font-weight: 900;
  font-size: clamp(2rem, 4vw, 3.4rem);
  line-height: 0.98;
  letter-spacing: -0.025em;
  color: var(--ink);
  margin: 0 0 0.8rem;
}
.plv-sub {
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: 1.05rem;
  color: var(--ink70, #555);
  line-height: 1.5;
  margin: 0 0 0.85rem;
}
.plv-sub strong { color: var(--brick); font-style: normal; font-weight: 700; }
.plv-sub em { color: var(--wood); font-style: italic; }
.plv-author-line {
  font-family: var(--ff-mono);
  font-size: 0.78rem;
  color: var(--ink70, #555);
  margin: 0 0 0.6rem;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}
.plv-author-avatar {
  width: 22px; height: 22px;
  flex: 0 0 auto;
  fill: none;
  stroke: var(--brick, #c8442a);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.plv-author-label {
  text-transform: uppercase;
  letter-spacing: 0.15em;
  color: var(--ink50);
  font-size: 0.66rem;
  margin-right: 0.35rem;
}
.plv-author-name {
  color: var(--brick);
  font-weight: 700;
  letter-spacing: 0.01em;
}
.plv-stats {
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  color: var(--ink50);
  margin: 0;
  display: inline-flex;
  gap: 0.55rem;
  align-items: baseline;
  flex-wrap: wrap;
}
.plv-stat b {
  color: var(--ink);
  font-weight: 700;
  margin-right: 0.2rem;
}
.plv-stat-sep { opacity: 0.45; }

/* List = stack of rows. The vinyl decoration + spin animation make the
   currently-playing row obvious without screaming for attention. */
.pl-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  border-top: 1px solid var(--ink10);
}
.pl-row {
  position: relative;
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid var(--ink10);
  border-radius: 6px;
  padding: 0;
  transition: background 0.15s, border-color 0.15s;
  overflow: hidden;
}
.pl-row:hover { background: rgba(255, 255, 255, 0.85); }
.pl-row.is-playing {
  background: rgba(199, 68, 42, 0.06);
  border-color: var(--brick);
}
.pl-row.is-disabled {
  opacity: 0.55;
}
.pl-row.is-disabled:hover { background: rgba(255, 255, 255, 0.55); }

.pl-row-main {
  display: grid;
  /* num | meta | controls — vinyl column was removed (visual noise that
     looked like a clickable button). The number badge keeps the cápsula
     position front and centre. */
  grid-template-columns: auto 1fr auto;
  gap: 0.85rem;
  align-items: center;
  padding: 0.85rem 1rem;
}
.pl-num {
  font-family: var(--ff-mono);
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--ink50);
  width: 2ch;
  text-align: right;
}
.pl-row.is-playing .pl-num { color: var(--brick); }

/* Vinyl decoration removed entirely from the rows + mini-player —
   visual noise that read as an unrelated clickable button. */

/* Meta block — capsule kicker + song title + author */
.pl-meta { min-width: 0; }
.pl-cap-link {
  display: block;             /* fill .pl-meta so ellipsis has a width */
  max-width: 100%;
  min-width: 0;
  text-decoration: none;
  color: inherit;
  margin-bottom: 0.18rem;
}
.pl-cap-kicker {
  display: block;
  max-width: 100%;
  white-space: nowrap;        /* never wrap the kicker */
  overflow: hidden;
  text-overflow: ellipsis;    /* … when the capsule title doesn't fit */
  font-family: var(--ff-mono);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink50);
  font-weight: 700;
  transition: color 0.15s;
}
.pl-cap-link:hover .pl-cap-kicker { color: var(--brick); }
.pl-song-title {
  font-family: var(--ff-disp);
  font-weight: 800;
  font-size: 1.05rem;
  line-height: 1.18;
  color: var(--ink);
  letter-spacing: -0.01em;
  margin: 0 0 0.1rem;
  /* Truncate when very long so the row stays single-line on desktop. */
  overflow: hidden;
  text-overflow: ellipsis;
}
.pl-row.is-playing .pl-song-title { color: var(--brick); }
/* "placeholder" badge appended inline to the song title for rows whose
   audio is a temporary stand-in (real recording not yet uploaded). */
.pl-badge-ph {
  display: inline-block;
  margin-left: 0.45rem;
  padding: 1px 6px 2px;
  font-family: var(--ff-mono);
  font-size: 0.55rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  vertical-align: middle;
  background: rgba(168, 106, 61, 0.18);
  color: var(--wood);
  border: 1px solid rgba(168, 106, 61, 0.42);
  border-radius: 3px;
  font-weight: 700;
}
/* Placeholder badge: dim number + brick outline so the badge alone
   carries the "not yet recorded" signal (vinyl was the previous tell). */
.pl-row.is-placeholder .pl-num { opacity: 0.6; }
.pl-author {
  display: inline-block;
  font-family: var(--ff-mono);
  font-size: 0.66rem;
  color: var(--wood);
  letter-spacing: 0.02em;
  font-style: italic;
  opacity: 0.85;
}

/* Controls (right side) — time + lyrics-toggle + play */
.pl-controls {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  flex-shrink: 0;
}
.pl-time {
  font-family: var(--ff-mono);
  font-size: 0.7rem;
  color: var(--ink50);
  font-variant-numeric: tabular-nums;
  min-width: 4.2ch;
  text-align: right;
}
.pl-row.is-playing .pl-time { color: var(--brick); }

.pl-lyrics-toggle {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: transparent;
  border: 1px solid rgba(168, 106, 61, 0.35);
  color: var(--wood);
  font-family: var(--ff-mono);
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 5px 9px 5px 7px;
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.pl-lyrics-toggle:hover {
  background: rgba(168, 106, 61, 0.1);
  color: var(--brick);
  border-color: var(--brick);
}
.pl-lyrics-toggle.is-open {
  background: var(--wood);
  color: var(--cream);
  border-color: var(--wood);
}
.pl-lyrics-toggle.is-off {
  border-color: var(--ink15, rgba(0, 0, 0, 0.1));
  color: var(--ink50);
  cursor: not-allowed;
}
.pl-lyr-ico { width: 14px; height: 14px; display: block; flex-shrink: 0; }
.pl-lyr-label { line-height: 1; }

.pl-play {
  width: 42px;
  height: 42px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--brick);
  color: var(--cream);
  border: none;
  border-radius: 50%;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(199, 68, 42, 0.3);
  transition: background 0.15s, transform 0.12s;
}
.pl-play:hover { background: #b53a23; transform: scale(1.05); }
.pl-play:active { transform: scale(0.97); }
.pl-play.is-off {
  background: transparent;
  color: var(--ink50);
  box-shadow: none;
  border: 1px dashed var(--ink15, rgba(0, 0, 0, 0.18));
  cursor: not-allowed;
}
.pl-play.is-off:hover { transform: none; }
/* While fetching the mp3 as a Blob (so seek works on servers without
   Range support), spin the play button instead of showing play/pause. */
.pl-row.is-loading .pl-play {
  background: var(--wood);
  cursor: progress;
}
.pl-row.is-loading .pl-play .pl-play-ico {
  animation: pl-spin 0.8s linear infinite;
  border: 2px solid var(--cream);
  border-top-color: transparent;
  border-radius: 50%;
}
.pl-row.is-loading .pl-play .pl-ico-play,
.pl-row.is-loading .pl-play .pl-ico-pause { display: none; }
@keyframes pl-spin {
  to { transform: rotate(360deg); }
}
.pl-play-ico { width: 18px; height: 18px; display: block; }
.pl-play-ico .pl-ico-pause { display: none; fill: currentColor; }
.pl-play-ico .pl-ico-play  { display: block; fill: currentColor; }
.pl-row.is-playing .pl-play .pl-ico-play  { display: none; }
.pl-row.is-playing .pl-play .pl-ico-pause { display: block; }

/* Progress bar — runs across the bottom edge of the row.
   Click or drag to seek inside the currently-playing song. Grows taller
   on hover so the click target feels obvious without being intrusive
   when idle. */
.pl-progress {
  position: relative;
  height: 6px;
  background: rgba(0, 0, 0, 0.06);
  cursor: pointer;
  transition: height 0.12s, background 0.12s;
  outline: none;
  /* Senza questo, su touch il browser intercetta il drag verticale come
     scroll della pagina e il pointermove non arriva mai → la barra del
     mini-player non si trascina su mobile. */
  touch-action: none;
}
.pl-progress:hover,
.pl-progress:focus-visible,
.pl-row.is-playing .pl-progress {
  height: 9px;
  background: rgba(0, 0, 0, 0.10);
}
.pl-progress:focus-visible {
  box-shadow: inset 0 0 0 1px var(--brick);
}
.pl-progress-fill {
  display: block;
  height: 100%;
  width: 0%;
  background: var(--brick);
  transition: width 0.18s linear;
  pointer-events: none;
}
/* Thumb — small circle that sits at the end of the fill while playing,
   reinforcing that the bar is draggable. Hidden when no song is loaded. */
.pl-progress-thumb {
  position: absolute;
  top: 50%;
  left: 0%;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  background: var(--brick);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
  opacity: 0;
  transition: opacity 0.12s, transform 0.12s;
  pointer-events: none;
}
.pl-row.is-playing .pl-progress-thumb,
.pl-progress:hover .pl-progress-thumb {
  opacity: 1;
}
.pl-progress:hover .pl-progress-thumb {
  transform: scale(1.15);
}

/* Lyrics panel — collapsed by default, expands inline below the row. */
.pl-lyrics {
  background: var(--paper);
  border-top: 1px solid var(--ink10);
}
.pl-lyrics-body {
  padding: 1.2rem 1.4rem 1.4rem;
  max-height: 360px;
  overflow-y: auto;
  font-family: var(--ff-disp);
  font-size: 0.94rem;
  line-height: 1.55;
  color: var(--ink);
}
.pl-lyrics-body h1 { display: none; }   /* title shown above already */
.pl-lyrics-body p { margin: 0 0 0.7rem; }
.pl-lyrics-body strong { color: var(--brick); font-weight: 700; }
.pl-lyrics-body em { color: var(--wood); font-style: italic; }
.pl-lyrics-loading {
  font-family: var(--ff-mono);
  font-size: 0.78rem;
  color: var(--ink50);
  text-align: center;
  padding: 0.6rem 0;
}
.pl-lyrics-error {
  font-family: var(--ff-mono);
  font-size: 0.78rem;
  color: var(--brick);
  text-align: center;
  padding: 0.6rem 0;
}

/* Mobile bar — Playlist pill mirrors the Activ. pill behaviour. */
.mbar-playlist { /* inherits .mbar-btn */ }
body.playlist-mode .mbar-playlist {
  background: var(--brick);
  color: var(--cream);
}

/* ── Mini-player (sticky bottom band) ─────────────────────────────────
   A persistent SoundCloud-style player surface that mirrors the audio
   engine state. Always at the bottom of the viewport regardless of
   which mode is active. It IS a .pl-row (so the engine drives play /
   pause / scrub for free) but with mini-player-specific tweaks: dark
   background, no row borders, compact spacing, slide-up entrance.

   ⚠ Specificity matters here: .pl-row.is-playing has bg
   rgba(199, 68, 42, 0.06) at specificity (0,0,2,0). All the mini-player
   rules below use .mini-player.pl-row (also 0,0,2,0) so they win in
   source order, and .mini-player.pl-row.is-playing (0,0,3,0) for the
   playing state — otherwise the bottom band turns transparent the
   second a song actually starts playing. */
.mini-player.pl-row {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  /* Above EVERYTHING (mbar at 350, fullscreen overlays, etc.). The
     seek bar at the bottom of the band must always be tappable — if
     the mbar covers it, the user can't drag to seek. */
  z-index: 9999;
  margin: 0;
  border: none;
  border-top: 1px solid rgba(244, 236, 224, 0.12);
  border-radius: 0;
  background: var(--ink);
  color: var(--cream);
  box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.28);
  overflow: hidden;
  transform: translateY(0);
  transition: transform 0.22s ease-out;
}
.mini-player.pl-row:hover {
  /* The base .pl-row:hover lightens the bg — kill that here, the band
     stays solid dark whether you're hovering it or not. */
  background: var(--ink);
}
.mini-player.pl-row.is-playing {
  background: var(--ink);
  border-color: rgba(244, 236, 224, 0.12);
}
.mini-player[hidden] {
  display: none;
}
.mini-player .pl-row-main {
  /* prev | play | next | meta | controls — transport on the left, then
     song info, then time + close on the right. */
  grid-template-columns: auto auto auto 1fr auto;
  padding: 0.55rem 1rem;
  gap: 0.55rem;
}
/* Prev / Next transport buttons (mini-player only). Subtle, mute on the
   dark band, glow brick on hover so they read as live controls. */
.mp-prev, .mp-next {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: transparent;
  color: rgba(244, 236, 224, 0.7);
  border: none;
  border-radius: 50%;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.mp-prev:hover, .mp-next:hover {
  background: rgba(244, 236, 224, 0.08);
  color: var(--cream);
}
/* Play button in the mini-player is a bit smaller than in the rows so
   the transport trio sits comfortably. */
.mini-player .pl-play {
  width: 38px;
  height: 38px;
  box-shadow: 0 1px 4px rgba(199, 68, 42, 0.45);
}
.mini-player .pl-play-ico { width: 16px; height: 16px; }
/* Light-on-dark colour shifts for all sub-elements. */
.mini-player .pl-cap-kicker {
  color: rgba(244, 236, 224, 0.55);
  font-size: 0.58rem;
  letter-spacing: 0.16em;
}
.mini-player .pl-cap-link:hover .pl-cap-kicker { color: var(--brick); }
.mini-player .pl-song-title {
  color: var(--cream);
  font-size: 0.95rem;
  margin: 0.05rem 0 0;
}
.mini-player.is-playing .pl-song-title { color: var(--cream); }
.mini-player.is-playing .pl-num,
.mini-player.is-playing .pl-time { color: var(--brick); }
.mini-player .pl-time {
  color: rgba(244, 236, 224, 0.6);
  font-size: 0.7rem;
}
.mini-player .pl-progress {
  background: rgba(244, 236, 224, 0.08);
}
.mini-player .pl-progress:hover,
.mini-player.is-playing .pl-progress {
  background: rgba(244, 236, 224, 0.14);
}
/* Close button (X) at the right end of the controls. */
.mp-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  background: transparent;
  color: rgba(244, 236, 224, 0.55);
  border: none;
  border-radius: 50%;
  cursor: pointer;
  margin-left: 0.35rem;
  transition: background 0.12s, color 0.12s;
}
.mp-close:hover {
  background: rgba(244, 236, 224, 0.1);
  color: var(--cream);
}
/* Push everything up so the fixed band never covers the last line of
   page content. Only when the mini-player is actually visible. */
body.has-mini-player {
  padding-bottom: 76px;
}
/* On mobile both the mini-player AND the bottom .mbar are pinned to
   the screen. The mini-player sits at bottom: 0, the mbar lifts ABOVE
   it (bottom: <mini-player-height>) so they stack cleanly. */
@media (max-width: 720px) {
  body.has-mini-player {
    padding-bottom: 116px;            /* mini ~60 + mbar ~52 + air */
  }
  /* Lift the mbar a few px ABOVE the mini-player's top edge so the two
     surfaces aren't glued together — gives the eye some breathing room
     and the seek bar room to be tapped. */
  body.has-mini-player .mbar { bottom: 66px; }
  /* Single-row flex layout on mobile — much cleaner than the previous
     2-row grid. Transport on the left, song title takes the remaining
     space, time + close pinned right. The "Reproduciendo · …" kicker
     is hidden on phones — the song title alone carries the message. */
  .mini-player .pl-row-main {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.45rem 0.6rem;
  }
  .mini-player .mp-prev,
  .mini-player .mp-next { width: 28px; height: 28px; }
  .mini-player .mp-prev svg,
  .mini-player .mp-next svg { width: 16px; height: 16px; }
  .mini-player .pl-play { width: 36px; height: 36px; flex-shrink: 0; }
  .mini-player .pl-play-ico { width: 14px; height: 14px; }
  .mini-player .pl-meta { flex: 1; min-width: 0; }
  .mini-player .pl-cap-kicker { display: none; }
  .mini-player .pl-song-title { font-size: 0.85rem; line-height: 1.15; }
  .mini-player .pl-controls { gap: 0.3rem; flex-shrink: 0; }
  .mini-player .pl-time { font-size: 0.65rem; min-width: 0; }
  .mini-player .mp-close { width: 26px; height: 26px; margin-left: 0; }
}

@media (max-width: 720px) {
  .playlist-view { padding: 1.75rem 0.9rem 0.9rem; }
  .pl-row-main {
    grid-template-columns: auto 1fr;
    grid-template-areas:
      "num  meta"
      "time controls";
    row-gap: 0.5rem;
  }
  .pl-num     { grid-area: num; }
  .pl-meta    { grid-area: meta; }
  .pl-time    { grid-area: time; text-align: left; }
  .pl-controls {
    grid-area: controls;
    justify-content: flex-end;
  }
  .pl-author { font-size: 0.6rem; }
  .pl-song-title { font-size: 0.98rem; }
}

/* "Ejemplos" is a toggle, not a scroll destination — so it reads as a
   pill button: outlined when off, solid orange when the mode is on. */
.nav-link[href$="#ejemplos"] {
  border: 1px solid rgba(244, 236, 224, 0.32);
  border-radius: 999px;
  padding: 5px 13px;
  opacity: 0.85;
  transition: opacity 0.15s, border-color 0.15s, background-color 0.15s;
}
.nav-link[href$="#ejemplos"]:hover {
  opacity: 1;
  border-color: rgba(244, 236, 224, 0.6);
}
body.ejemplos-mode .nav-link[href$="#ejemplos"] {
  background: var(--brick);
  border-color: var(--brick);
  color: var(--cream);
  opacity: 1;
}

/* ── BODY CONTENT (markdown rendered) ────────────────────────── */
/* Auto-numbering: every .cap-body counts its own h2/h3/h4 (CSS counters)
   so headings render as "1. Title", "1.1 Sub-title", "1.1.1 Sub-sub" —
   the same numbering scheme is computed Python-side and injected into the
   sidebar sub-items so the two views stay in sync. */
.cap-body {
  line-height: 1.7;
  counter-reset: h2-cnt 0;
  /* Drives text size for paragraph-level reading content. Inherits to
     <p>, <li>, captions, blockquotes via natural CSS cascade. Heading
     sizes stay in rem (capsule titles shouldn't grow with reading-fs
     since they're already large). */
  font-size: var(--reading-fs);
}
.cap-body h2 { counter-reset: h3-cnt 0; counter-increment: h2-cnt; }
.cap-body h3 { counter-reset: h4-cnt 0; counter-increment: h3-cnt; }
.cap-body h4 { counter-increment: h4-cnt; }
/* Gallery titles (<h4 class="gal-title">) are NOT auto-numbered: they
   appear in the sidebar but without the "X.Y.Z" prefix. We also opt them
   out of the h4-cnt counter so they don't shift the numbering of any
   subsequent real h4 sections. */
.cap-body h4.gal-title { counter-increment: none; }
.cap-body h2[id^="sec-"]:not(.gal-title)::before {
  content: counter(h2-cnt) ". ";
  color: var(--brick); font-weight: 700;
  margin-right: 0.25em;
}
.cap-body h3[id^="sec-"]:not(.gal-title)::before {
  content: counter(h2-cnt) "." counter(h3-cnt) "\00a0 ";
  color: var(--brick); font-weight: 700;
  margin-right: 0.25em;
}
.cap-body h4[id^="sec-"]:not(.gal-title)::before {
  content: counter(h2-cnt) "." counter(h3-cnt) "." counter(h4-cnt) "\00a0 ";
  color: var(--brick); font-weight: 700;
  margin-right: 0.25em;
}
.cap-body h1 {
  font-family: var(--ff-disp); font-weight: 900;
  font-size: 1.7rem; margin: 2.5rem 0 0.6rem;
  letter-spacing: -0.02em;
}
.cap-body h2 {
  font-family: var(--ff-disp); font-weight: 700;
  font-size: 1.35rem; margin: 2.75rem 0 0.7rem;
  letter-spacing: -0.015em;
}
.cap-body h3 {
  font-family: var(--ff-disp); font-weight: 700;
  font-size: 1.05rem; margin: 1.75rem 0 0.45rem;
  color: var(--wood);
}
.cap-body h4 {
  font-family: var(--ff-mono);
  font-size: 0.72rem; letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 1.5rem 0 0.4rem;
  color: var(--ink50);
}
.cap-body p { margin-bottom: 0.9rem; }
.cap-body ul, .cap-body ol { margin: 0.4rem 0 1rem 1.6rem; }
.cap-body li { margin-bottom: 0.3rem; }

.cap-body blockquote {
  border-left: 3px solid var(--brick);
  margin: 1.5rem 0;
  padding: 0.75rem 1.25rem;
  background: rgba(200,68,42,0.05);
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: 1.05rem;
}
.cap-body blockquote p { margin-bottom: 0; }
.cap-body blockquote strong { font-style: normal; }

/* First blockquote of a capsule = its editorial premise. Louder than the
   ordinary pull-quotes: big icon, kicker label, larger italic body. */
.cap-body blockquote.cap-tagline {
  display: grid;
  grid-template-columns: 56px 1fr;
  column-gap: 20px;
  align-items: center;
  margin: 1.25rem 0 2.75rem;
  padding: 22px 26px;
  background: linear-gradient(to right,
    rgba(200,68,42,0.14) 0%, rgba(200,68,42,0.04) 100%);
  border-left: 5px solid var(--brick);
  border-radius: 4px;
  font-size: 1rem;
  font-style: normal;
}
.cap-body blockquote.cap-tagline::before {
  content: "💡";
  grid-column: 1;
  grid-row: 1 / -1;
  align-self: center;
  font-size: 44px;
  line-height: 1;
  text-align: center;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.15));
}
.cap-body blockquote.cap-tagline > p {
  grid-column: 2;
  margin: 0;
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: 1.3rem;
  line-height: 1.5;
  color: var(--ink);
}
.cap-body blockquote.cap-tagline > p:first-of-type::before {
  content: "En pocas palabras";
  display: block;
  font-family: var(--ff-mono);
  font-size: 0.74rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 700;
  font-style: normal;
  color: var(--brick);
  margin-bottom: 0.5rem;
}
.cap-body blockquote.cap-tagline strong {
  font-style: normal;
  color: var(--brick);
}

/* Horizontal rules in capsule content: whitespace only, never a line. */
.cap-body hr {
  border: 0;
  height: 0;
  margin: 2.5rem 0;
}

.cap-body img {
  max-width: 100%;
  max-height: 460px;
  width: auto;
  height: auto;
  display: block;
  margin: 1.5rem auto;
  border: 1px solid var(--ink10);
  object-fit: contain;
}

.cap-body .caption {
  font-size: 0.82rem;
  color: var(--ink50);
  text-align: center;
  margin-top: -1rem;
  margin-bottom: 1.5rem;
  font-family: var(--ff-disp);
  font-style: italic;
}

.table-scroll { overflow-x: auto; }
.cap-body table {
  width: 100%; border-collapse: separate; border-spacing: 0;
  margin: 1.5rem 0; font-size: 0.92rem;
  table-layout: fixed;
}
.cap-body th {
  background: rgba(200, 68, 42, 0.10); color: var(--brick);
  font-family: var(--ff-disp); font-size: 0.86rem;
  letter-spacing: 0.02em; text-transform: none;
  padding: 12px 14px; text-align: left;
  font-weight: 700;
  border-bottom: 2px solid var(--brick);
}
.cap-body th:not(:last-child) { border-right: 1px solid rgba(200, 68, 42, 0.20); }
.cap-body td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--ink10);
  vertical-align: top;
  line-height: 1.55;
}
.cap-body td:not(:last-child) { border-right: 1px solid var(--ink10); }
.cap-body tr:nth-child(even) td { background: rgba(26,26,26,0.025); }
.cap-body td strong { color: var(--brick); }
/* When a table has no header row content (legacy "|  |  |"), hide the
   thead so we don't show a bare black/empty stripe at the top. */
.cap-body thead:empty,
.cap-body thead tr:empty,
.cap-body thead th:empty:first-child:last-child { display: none; }

.cap-body pre {
  background: var(--ink); color: #e8dcc8;
  padding: 1.25rem; overflow-x: auto;
  font-family: var(--ff-mono); font-size: 0.8rem;
  line-height: 1.6; margin: 1.25rem 0;
}
.cap-body code {
  font-family: var(--ff-mono); font-size: 0.82em;
  background: rgba(26,26,26,0.08); padding: 2px 5px;
}
.cap-body pre code { background: none; padding: 0; font-size: 0.8rem; }

.cap-body .video-embed {
  position: relative; width: 100%; padding-top: 56.25%; margin: 1.5rem 0;
}
.cap-body .video-embed iframe {
  position: absolute; inset: 0; width: 100%; height: 100%;
  border: none;
}

.cap-body .audio-inline {
  display: flex; align-items: center; gap: 0.75rem;
  padding: 0.75rem 1rem;
  background: rgba(26,26,26,0.06);
  margin: 0.75rem 0;
}
.cap-body .audio-inline audio { flex: 1; height: 30px; }
.cap-body .audio-inline span {
  font-family: var(--ff-mono); font-size: 0.65rem;
  color: var(--ink50); letter-spacing: 0.06em;
}

/* ── GALLERY (3-column grid + click-to-zoom modal with prev/next) ───── */
.cap-body .gallery {
  margin: 1.5rem 0;
  background: rgba(168,106,61,0.04);
  border-left: 3px solid var(--wood);
  padding: 0.6rem 0 0.6rem;
}
.cap-body .gallery-head {
  display: flex; align-items: baseline; justify-content: space-between;
  padding: 0 1rem 0.7rem;
}
.cap-body .gallery-head h4 {
  margin: 0; font-size: 0.9rem; font-weight: 700;
  color: var(--wood); font-family: var(--ff-mono);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.cap-body .gallery-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  padding: 0 1rem;
}
@media (max-width: 800px) {
  .cap-body .gallery-strip { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 500px) {
  .cap-body .gallery-strip { grid-template-columns: 1fr; }
}
.cap-body .gal-item {
  margin: 0;
  display: flex; flex-direction: column;
  cursor: zoom-in;
  background: #fff;
  border: 1px solid rgba(168,106,61,0.2);
  transition: transform 0.12s, box-shadow 0.12s;
}
.cap-body .gal-item:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 10px rgba(0,0,0,0.12);
}
.cap-body .gal-item img {
  width: 100%; height: 180px;
  object-fit: contain;
  background: #fff;
  display: block;
  padding: 8px;
  box-sizing: border-box;
}
.cap-body .gal-item figcaption {
  font-family: var(--ff-mono);
  font-size: 0.7rem;
  color: var(--ink50);
  padding: 0.5rem 0.7rem 0.6rem;
  line-height: 1.4;
  border-top: 1px solid rgba(168,106,61,0.12);
}

/* Click-to-zoom modal (handled by site.js) — with prev/next nav */
.gallery-modal {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.9);
  z-index: 9999;
  display: none;
  flex-direction: column;
  align-items: center; justify-content: center;
  padding: 2rem 4rem;
}
.gallery-modal.open { display: flex; }
.gm-stage {
  position: relative;
  flex: 1; min-height: 0;
  display: flex; align-items: center; justify-content: center;
  width: 100%;
}
.gm-stage img {
  max-width: 100%; max-height: 100%;
  object-fit: contain;
  background: #fff;
  cursor: zoom-out;
}
.gm-cap {
  margin-top: 1rem;
  color: #fff; font-family: var(--ff-mono);
  font-size: 0.85rem; max-width: 80%;
  text-align: center; line-height: 1.4;
}
.gm-counter {
  position: absolute; top: 1rem; right: 1.5rem;
  color: rgba(255,255,255,0.65);
  font-family: var(--ff-mono); font-size: 0.75rem;
}
.gm-close {
  position: absolute; top: 1rem; left: 1.5rem;
  background: none; border: none;
  color: rgba(255,255,255,0.7);
  font-size: 1.4rem; cursor: pointer;
  padding: 0.3rem 0.6rem;
}
.gm-close:hover { color: #fff; }
.gm-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  background: rgba(255,255,255,0.1);
  border: none;
  color: #fff;
  width: 48px; height: 80px;
  font-size: 2rem;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.12s;
}
.gm-nav:hover { background: rgba(255,255,255,0.25); }
.gm-nav:disabled { opacity: 0.2; cursor: default; background: none; }
.gm-prev { left: 0.5rem; }
.gm-next { right: 0.5rem; }

/* ── AUDIO / VIDEO BLOCK (nuovo: figure + figcaption + media) ───────── */
.cap-body .audio-block,
.cap-body .video-block {
  margin: 1.1rem 0;
  padding: 0;
  background: rgba(168,106,61,0.06);
  border: 1px solid rgba(168,106,61,0.25);
  border-left: 3px solid var(--wood);
  border-radius: 4px;
}
.cap-body .audio-block figcaption,
.cap-body .video-block figcaption {
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  color: var(--ink50);
  padding: 0.5rem 0.85rem 0.35rem;
  text-transform: none;
  letter-spacing: 0.02em;
  line-height: 1.4;
}
.cap-body .audio-block audio {
  display: block;
  width: calc(100% - 1.7rem);
  margin: 0 0.85rem 0.6rem;
  height: 32px;
}
.cap-body .video-block video {
  display: block;
  width: calc(100% - 1.7rem);
  margin: 0 0.85rem 0.6rem;
  max-height: 480px;
  background: #000;
}

/* ── TOOL RAIL (floating buttons, fixed top-right) ───────────── */
/* Designed to grow: stack more .tool-btn vertically as needed. */
.tools-rail {
  position: fixed;
  top: calc(52px + 0.85rem);
  right: 0.85rem;
  z-index: 250;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  opacity: 1;
  pointer-events: auto;
  transform: translateX(0);
  transition: opacity 0.25s, transform 0.25s,
              top 0.32s cubic-bezier(0.4, 0, 0.2, 1);
}
/* When the smart header tucks away on scroll-down, the rail rises with
   it so the gap above stays constant whether the bar is there or not. */
body.chrome-hidden .tools-rail { top: 0.85rem; }
/* Hide the text-size cycler at the very top — only the Presentar
   button needs to be reachable from the hero (where the intro
   slideshow lives). The AAA toggle reveals itself when the user
   enters the capsules reading area. */
.tools-rail #text-size-toggle { display: none; }
body.in-capsules .tools-rail #text-size-toggle { display: flex; }

.tool-btn {
  width: 64px;
  height: 64px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 6px 4px 7px;
  background: var(--ink);
  color: var(--cream);
  border: 1px solid rgba(244,236,224,0.10);
  border-radius: 6px;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(0,0,0,0.18);
  transition: background 0.15s, transform 0.12s, border-color 0.15s;
  font-family: var(--ff-mono);
}
.tool-btn:hover {
  background: var(--brick);
  border-color: var(--brick);
  transform: translateY(-1px);
}
.tool-btn:active { transform: translateY(0); }
.tool-icon-wrap {
  display: inline-flex;
  width: 26px; height: 26px;
}
.tool-icon { width: 100%; height: 100%; display: block; }
.tool-label {
  font-size: 0.52rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1;
}

/* ── AAA text-size toggle inside the tool rail.
   Three As stacked from large → small. Only the one matching the
   current `body.text-size-N` is brick-orange; the other two are
   cream so the active state is obvious at a glance. */
.tool-btn.text-size-toggle .ts-icon {
  display: inline-flex;
  align-items: baseline;
  justify-content: center;
  gap: 1px;
  width: 26px;
  height: 26px;
}
.tool-btn.text-size-toggle .ts-a {
  font-family: var(--ff-disp);
  font-weight: 900;
  color: var(--cream);
  line-height: 1;
  display: inline-block;
}
.tool-btn.text-size-toggle .ts-a3 { font-size: 20px; }
.tool-btn.text-size-toggle .ts-a2 { font-size: 14px; }
.tool-btn.text-size-toggle .ts-a1 { font-size: 9px;  }
/* Highlight the A that corresponds to the current size. */
body.text-size-2 .tool-btn.text-size-toggle .ts-a1,
body.text-size-2 .tool-btn.text-size-toggle .ts-a3 { color: var(--cream); }
body.text-size-2 .tool-btn.text-size-toggle .ts-a2 { color: #ffb38a; }

body.text-size-3 .tool-btn.text-size-toggle .ts-a1,
body.text-size-3 .tool-btn.text-size-toggle .ts-a2 { color: var(--cream); }
body.text-size-3 .tool-btn.text-size-toggle .ts-a3 { color: #ffb38a; }

/* Default state (no `text-size-N` class on body, or `text-size-1`) →
   smallest A glows. */
.tool-btn.text-size-toggle .ts-a1 { color: #ffb38a; }
body.text-size-2 .tool-btn.text-size-toggle .ts-a1,
body.text-size-3 .tool-btn.text-size-toggle .ts-a1 { color: var(--cream); }

/* ── Sidebar SECTIONS toggle (icon-only, inside the filter row) ───────
   Two states, controlled by `body.sections-hidden`:
     • default (sections visible)  → expanded icon shown (three bullets),
                                     tooltip "Ocultar secciones"
     • toggled (sections hidden)   → collapsed icon shown (one bullet),
                                     tooltip "Mostrar secciones"
   When `sections-hidden`, every `.sidebar-subitem` is hidden via CSS.
   ───────────────────────────────────────────────────────────────────── */
.sections-toggle {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  background: transparent;
  border: 1px solid rgba(26,26,26,0.18);
  border-radius: 4px;
  color: var(--ink50);
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.sections-toggle:hover {
  color: var(--brick);
  border-color: var(--brick);
  background: rgba(200,68,42,0.06);
}
.sections-toggle .st-icon {
  width: 16px;
  height: 16px;
  display: block;
}
/* Hide collapsed-icon by default; swap when body has .sections-hidden. */
.sections-toggle .st-icon-collapsed { display: none; }
body.sections-hidden .sections-toggle .st-icon-expanded { display: none; }
body.sections-hidden .sections-toggle .st-icon-collapsed { display: block; }
body.sections-hidden .sections-toggle {
  color: var(--brick);
  border-color: var(--brick);
  background: rgba(200,68,42,0.06);
}
/* The actual section-hiding rule */
body.sections-hidden .sidebar-subitem { display: none !important; }

/* ── PRESENTATION MODE (slideshow overlay) ───────────────────────────
   Activated by clicking the Presentar tool-btn. A full-viewport overlay
   takes over: top breadcrumb (capsule + section), large stage with the
   current slide content cloned from the page, prev/next arrows, counter
   and a bottom hint strip. ESC / ← / → all work; clicking the close X
   exits and scrolls the page back to wherever the slide came from. */
.present-overlay {
  position: fixed;
  inset: 0;
  z-index: 9000;
  background: #1a1a1a;
  color: #f4ecdf;
  display: none;
  flex-direction: column;
  font-family: var(--ff-body);
  /* Hide the mouse cursor when idle (same trigger as the side arrows:
     `.mouse-active` is added on mousemove and stripped after 1.8s).
     This gives a clean "cinema" feel during presentations where the
     pointer doesn't sit on top of the slide. */
  cursor: none;
}
.present-overlay.mouse-active { cursor: auto; }
.present-overlay.open { display: flex; }
body.presenting { overflow: hidden; }

/* TOP bar — small, fixed height; capsule name + section + counter + close */
.present-top {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 0.8rem;
  align-items: center;
  padding: 12px 18px;
  background: #0e0e0e;
  border-bottom: 1px solid rgba(244,236,224,0.10);
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
}
.po-breadcrumb {
  min-width: 0;             /* allow ellipsis */
  display: flex;
  align-items: center;
  gap: 0.6rem;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.po-cap {
  text-transform: uppercase;
  color: var(--brick);
  font-weight: 700;
  letter-spacing: 0.18em;
  flex: 0 0 auto;
}
.po-cap-title {
  color: #f4ecdf;
  font-family: var(--ff-disp);
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0;
  text-transform: none;
  overflow: hidden;
  text-overflow: ellipsis;
}
.po-sep {
  color: rgba(244,236,224,0.30);
  flex: 0 0 auto;
}
.po-section {
  color: rgba(244,236,224,0.65);
  text-transform: none;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
}
.po-counter {
  flex: 0 0 auto;
  color: rgba(244,236,224,0.55);
  font-variant-numeric: tabular-nums;
  font-size: 0.72rem;
}
.po-close {
  flex: 0 0 auto;
  background: transparent;
  border: none;
  color: rgba(244,236,224,0.55);
  padding: 0 4px;
  margin-left: 6px;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: color 0.15s, transform 0.12s;
}
.po-close:hover  { color: #f4ecdf; transform: scale(1.15); }
.po-close:active { transform: scale(0.96); }

/* On hero / intro slides the breadcrumb (chip + capsule title +
   section) would be redundant — the slide IS the capsule splash, the
   title is already rendered huge below. Hide the breadcrumb chunks
   and make the top bar TRANSPARENT (no dark strip across the top)
   so the splash extends edge-to-edge. Counter and close button stay
   visible — they're floating text on the slide bg, contrast is fine. */
.present-overlay[data-slide-kind="hero"]  .po-breadcrumb,
.present-overlay[data-slide-kind="intro"] .po-breadcrumb { visibility: hidden; }
.present-overlay[data-slide-kind="hero"]  .present-top,
.present-overlay[data-slide-kind="intro"] .present-top {
  background: transparent;
  border-bottom: none;
}

/* STAGE — center area where the current slide is rendered.
   No horizontal padding: the image uses the FULL viewport width
   (capped only by its own aspect ratio via object-fit:contain).
   Side arrows live as absolute overlays on top of the image — they
   only appear on mousemove anyway, so they never interfere.
   Background is driven by `data-slide-kind` on the overlay so that
   fig/video slides get pure WHITE while hero/moraleja stay DARK.
   The transition is synchronised with the slide fade-in (same 0.25s
   ease-in-out) so the image doesn't pop in before the bg changes. */
.present-stage {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
  padding: 8px 0;
  min-height: 0;
  background: #1a1a1a;
  /* Phase 1 of the slide change: bg colour fades over the FIRST 0.15s
     of the transition. The slide content (see .po-slide animation) stays
     invisible during this phase, then fades in over the next 0.1s. */
  transition: background 0.15s ease-out;
}
.present-overlay[data-slide-kind="fig"]   .present-stage { background: #ffffff; }
/* Videos (YouTube / Vimeo / <video>) get a pure-black "cinema" backdrop
   — videos themselves typically have black bars, so this avoids the
   visible seam between video content and slide canvas. */
.present-overlay[data-slide-kind="video"] .present-stage { background: #000000; }
/* Intro slides reproduce the home-page hero look: paper-cream bg with
   dark ink text. Lets the audience recognise the page they just left. */
.present-overlay[data-slide-kind="intro"] .present-stage { background: var(--paper); }
.present-overlay[data-slide-kind="intro"] .po-slide { color: var(--ink); }
.po-slide-wrap {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.po-slide {
  width: 100%;
  height: 100%;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  text-align: center;
  /* Two-phase choreography (matches the stage bg transition above):
       Phase 1 (0 → 0.15s): slide stays at opacity 0 — bg is morphing
                            black ↔ white, no content should be visible
                            on the "wrong" colour during the swap.
       Phase 2 (0.15 → 0.25s): bg has settled; slide fades in cleanly.
     `both` fill-mode keeps the keyframe `from { opacity: 0 }` state in
     effect during the 0.15s delay (without it, the element would sit
     at its default opacity 1 during the wait). */
  animation: po-fade 0.1s ease-out 0.15s both;
}
@keyframes po-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
/* Visual area — auto-sizes to its child (image / iframe / video),
   capped at viewport-aware dims so it never spills under the bottom bar.
   The shrink-to-fit math: viewport height minus top bar (~50),
   bottom bar (~36), stage paddings (48) and caption space (~120). */
.po-visual {
  /* No cap on width — fills the FULL stage width on wide monitors.
     `flex: 1 1 auto + min-height:0` lets the visual claim every
     vertical pixel the slide column hasn't reserved for the caption.
     The image/iframe/video then scales via object-fit:contain so
     whichever dimension is the limiting one (W or H) becomes the
     bound, and the picture is as big as physically possible. */
  display: block;
  width: 100%;
  flex: 1 1 auto;
  min-height: 0;
  background: transparent;
  overflow: hidden;
}
.po-visual img,
.po-visual svg,
.po-visual video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: transparent;
}
.po-visual video { background: #000; }
.po-visual iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: none;
  background: #fff;
  transition: opacity 0.18s ease-out;
}

/* ── Three-dot loader shown while a live-demo iframe is loading and the
   auto-fit calculation hasn't run yet. The iframe is hidden behind it
   (opacity:0) until the fit completes — avoids the user seeing the
   demo "snap" from its full-size first paint to the scaled position. */
.po-loader {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  gap: 12px;
  pointer-events: none;
}
.po-visual.iframe-loading .po-loader { display: flex; }
.po-visual.iframe-loading iframe   { opacity: 0; }
.po-loader span {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #888;
  display: inline-block;
  animation: po-loader-pulse 1.2s ease-in-out infinite;
}
.po-loader span:nth-child(2) { animation-delay: 0.15s; }
.po-loader span:nth-child(3) { animation-delay: 0.30s; }
@keyframes po-loader-pulse {
  0%, 100% { opacity: 0.25; transform: scale(0.7); }
  50%      { opacity: 1;    transform: scale(1.0); }
}
/* Caption underneath the visual — large and readable.
   Color depends on slide background (driven by data-slide-kind):
     fig (white stage) → black text, brick highlights
     hero/moraleja (dark stage) → cream text, light-orange highlights */
.po-caption {
  flex: 0 0 auto;
  max-width: min(960px, 78vw);
  max-height: 22vh;
  overflow-y: auto;
  color: #f4ecdf;
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: 1.05rem;
  line-height: 1.45;
  padding: 0 4px;
}
.po-caption b      { font-style: normal; font-weight: 700; color: #ffb38a; }
.po-caption a      { color: #ffd0a8; }
.present-overlay[data-slide-kind="fig"] .po-caption    { color: #1a1a1a; }
.present-overlay[data-slide-kind="fig"] .po-caption b  { color: var(--brick); }
.present-overlay[data-slide-kind="fig"] .po-caption a  { color: var(--brick); }
/* ── HERO slide redesign (capsule entry splash) ────────────────────
   Editorial left-anchored layout: kicker with brick rule, big title,
   and the tagline as a side pull-quote. Two columns above ~1100 px
   viewport (title left, tagline right) so the whole slide breathes
   horizontally instead of stacking awkwardly. Below 1100 px → single
   left-aligned column. Minimalist palette (cream + brick + ink). */
.po-slide.kind-hero {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  grid-template-rows: auto auto auto;
  grid-template-areas:
    "kicker    kicker"
    "title     tagline"
    "subtitle  tagline";
  column-gap: 4vw;
  row-gap: 1.4rem;
  padding: 0 6vw;
  width: 100%;
  max-width: 1600px;
  margin: 0 auto;
  text-align: left;
  align-items: start;
  align-content: center;       /* pack rows and centre vertically */
  justify-content: center;
}
/* Kicker top, full width, with a brick "—" rule preceding it */
.po-slide.kind-hero .po-hero-kicker {
  grid-area: kicker;
  font-family: var(--ff-mono);
  font-size: clamp(0.78rem, 1.1vw, 1.15rem);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--slide-accent);
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 1rem;
}
.po-slide.kind-hero .po-hero-kicker::before {
  content: "";
  display: inline-block;
  width: clamp(40px, 4vw, 80px);
  height: 2px;
  background: var(--slide-accent);
  flex: 0 0 auto;
}
/* Title — anchored left, comfortable wrap (2-3 lines target). We don't
   constrain max-width at all (the column already constrains it via the
   1.6fr / 1fr grid). Font-size scaled to keep long titles like
   "Qué significa visualizar: visión, oído, tacto…" wrapping cleanly
   into 3 lines instead of 5. */
.po-slide.kind-hero .po-hero-title {
  grid-area: title;
  font-family: var(--ff-disp);
  font-weight: 900;
  font-size: clamp(2.2rem, 4.2vw, 4.6rem);
  line-height: 1.04;
  letter-spacing: -0.025em;
  color: var(--cream);
  align-self: center;
}
.po-slide.kind-hero .po-hero-subtitle {
  grid-area: subtitle;
  align-self: start;
  margin-top: 0;
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: clamp(1.05rem, 1.6vw, 1.4rem);
  color: rgba(244,236,224,0.65);
  max-width: 38ch;
  line-height: 1.4;
}
/* Tagline — the opening blockquote, sits in the right column as a
   pull-quote with thick brick rule. Vertically centred against the
   title block; aligned to the title's baseline visually. */
.po-slide.kind-hero .po-hero-tagline {
  grid-area: tagline;
  align-self: center;
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: clamp(1.05rem, 1.6vw, 1.55rem);
  color: rgba(244,236,224,0.88);
  line-height: 1.55;
  padding-left: 1.5rem;
  border-left: 3px solid var(--slide-accent);
  max-width: 36ch;
}
.po-slide.kind-hero .po-hero-tagline p { margin: 0 0 0.5em; }
.po-slide.kind-hero .po-hero-tagline p:last-child { margin-bottom: 0; }
.po-slide.kind-hero .po-hero-tagline strong {
  font-style: normal;
  font-weight: 700;
  color: var(--cream);
}
/* Technical capsules carry no pull-quote in the deck — the hero drops the
   2-column split for a single full-width centred column (no right-hand gap)
   and a larger title that commands the whole slide. */
.po-slide.kind-hero.hero-solo {
  grid-template-columns: 1fr;
  grid-template-areas:
    "kicker"
    "title"
    "subtitle";
  text-align: center;
}
.po-slide.kind-hero.hero-solo .po-hero-kicker { justify-content: center; }
.po-slide.kind-hero.hero-solo .po-hero-title {
  font-size: clamp(2.4rem, 5vw, 5.4rem);
}
.po-slide.kind-hero.hero-solo .po-hero-subtitle {
  max-width: 72ch;
  margin-left: auto;
  margin-right: auto;
}
/* Single column on smaller viewports — tagline stacks under title. */
@media (max-width: 1100px) {
  .po-slide.kind-hero {
    grid-template-columns: 1fr;
    grid-template-areas:
      "kicker"
      "title"
      "subtitle"
      "tagline";
    row-gap: 1.6rem;
    padding: 0 6vw;
  }
  .po-slide.kind-hero .po-hero-title {
    align-self: start;
    max-width: 100%;
  }
  .po-slide.kind-hero .po-hero-tagline {
    align-self: start;
    max-width: 100%;
  }
}

/* ── Standalone pull-quote slide: every blockquote past the opening
   tagline gets its own dark slide. Large italic body, brick rule on
   the left, attribution line in small caps if present. */
.po-slide.kind-quote {
  padding: 0 8vw;
  gap: 18px;
}
.po-slide.kind-quote .po-quote-body {
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: clamp(1.3rem, 2.6vw, 2.6rem);
  line-height: 1.5;
  color: var(--cream);
  max-width: 50ch;
  padding-left: 2rem;
  border-left: 4px solid var(--slide-accent);
  text-align: left;
}
.po-slide.kind-quote .po-quote-body p { margin: 0 0 0.7em; }
.po-slide.kind-quote .po-quote-body p:last-child { margin-bottom: 0; }
.po-slide.kind-quote .po-quote-body strong {
  font-style: normal;
  font-weight: 700;
  color: #ffb38a;
}

/* ── Aprendizaje activo — final slide of each capsule with material.
   Dark slide; the same card markup as the in-page block but with
   text colours flipped (cream + light orange). ────────────────── */
.po-slide.kind-activities {
  padding: 0 4vw;
  gap: 18px;
  align-items: center;
  justify-content: center;
}
/* One-line header: "Material para clase" (cream) · "CÁPSULA 01"
   (light accent) — hierarchised by colour, font and size. */
.po-slide.kind-activities .po-acts-title {
  font-family: var(--ff-disp);
  font-weight: 800;
  font-size: clamp(1.8rem, 3.5vw, 3.2rem);
  line-height: 1.15;
  color: var(--cream);
  text-align: center;
  margin-bottom: 1.4rem;
}
.po-slide.kind-activities .po-acts-sep {
  color: rgba(244, 236, 224, 0.35);
  font-weight: 400;
}
.po-slide.kind-activities .po-acts-cap {
  font-family: var(--ff-mono);
  font-weight: 700;
  font-size: 0.5em;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--slide-accent);
  vertical-align: 0.12em;
}
/* Flex (not grid) so the last partial row stays centered when the slide
   shows 4 or 5 cards (3 + 2 layout): the orphan row sits centered under
   the full first row instead of left-aligned to columns 1 and 2. */
.po-slide.kind-activities .po-acts-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: flex-start;
  gap: 0.85rem;
  width: min(1280px, 88vw);
  max-height: 60vh;
  overflow-y: auto;
}
/* Override the in-page .act-card colours for the dark slide context.
   Fixed flex basis so cards keep a consistent width and the row math
   stays predictable (≈ 3 cards × 380px + gaps ≈ 1180px ≈ 88vw cap). */
.po-slide.kind-activities .act-card {
  flex: 0 0 360px;
  max-width: 380px;
  background: rgba(244,236,224,0.05);
  border: 1px solid rgba(244,236,224,0.15);
  padding: 16px 18px;
}
.po-slide.kind-activities .act-card:hover {
  background: rgba(244,236,224,0.10);
  border-color: var(--slide-accent);
  box-shadow: none;
  /* No lift here: inside the overflow-y:auto grid a −1px translate would
     push the card's top border above the clip edge and hide it. */
  transform: none;
}
.po-slide.kind-activities .act-kind {
  color: rgba(244,236,224,0.55);
}
.po-slide.kind-activities .act-title { color: var(--cream); }
.po-slide.kind-activities .act-purpose { color: rgba(244,236,224,0.72); }
.po-slide.kind-activities .act-arrow { color: rgba(244,236,224,0.45); }
.po-slide.kind-activities .act-card:hover .act-arrow {
  color: var(--slide-accent);
}

/* ── INTRO SLIDES — the prologue that retells the home-hero earthquake
   story BEFORE the capsules start. Five narrative slides + 2 payoff
   media slides. All share dark bg (kind: 'hero' from JS, so the
   present-stage uses the default dark background); layouts mirror the
   home-hero rendering so content reads identically. ──────────────── */
.po-slide[class*="kind-intro"] {
  padding: 0 6vw;
  text-align: center;
  gap: 22px;
}

/* Big-title intro: "La casita tiembla." + lead sentence underneath.
   Colours mirror the home-hero (dark ink on cream paper, italic em
   in brick). Sizes use generous clamp() caps so on a 1600 px wide
   screen the title fills with confidence — small viewports still
   get readable minima. */
.po-slide.kind-intro-title .hero-title {
  font-family: var(--ff-disp);
  font-weight: 900;
  font-size: clamp(3.2rem, 11vw, 13rem);
  line-height: 0.92;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 0;
}
.po-slide.kind-intro-title .hero-title em {
  font-style: italic;
  color: var(--brick);
}
.po-slide.kind-intro-title .hero-lead {
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: clamp(1.1rem, 2.2vw, 2.4rem);
  color: var(--ink50);
  max-width: 38ch;
  line-height: 1.5;
  margin: 1.5rem auto 0;
}

/* Scene slides: text + casita illustration side-by-side. innerHTML of
   .hero-scene is cloned directly so the children's document order is
   preserved (Scene 1 = text-left/art-right; Scene 2 = art-left/text-
   right). The .po-slide.kind-intro-scene container is a flex ROW with
   equal-split 50/50 so the two sides feel balanced regardless of how
   wide the screen is. */
.po-slide.kind-intro-scene {
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 4vw;
  padding: 0 4vw;
}
.po-slide.kind-intro-scene .scene-text {
  flex: 1 1 50%;
  max-width: 50%;
  min-width: 0;
  text-align: left;
}
.po-slide.kind-intro-scene .scene-art {
  flex: 1 1 50%;
  max-width: 50%;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.po-slide.kind-intro-scene .scene-art svg {
  width: 100%;
  max-width: clamp(380px, 42vw, 900px);
  height: auto;
  display: block;
}
.po-slide.kind-intro-scene .scene-label {
  font-family: var(--ff-mono);
  font-size: clamp(0.78rem, 1.4vw, 1.5rem);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brick);
  font-weight: 700;
  margin-bottom: 1rem;
}
.po-slide.kind-intro-scene .scene-text p {
  font-family: var(--ff-disp);
  font-size: clamp(1.1rem, 2.1vw, 2.4rem);
  line-height: 1.5;
  color: var(--ink);
  margin-bottom: 0.7rem;
}
.po-slide.kind-intro-scene .scene-text p strong {
  color: var(--brick);
  font-weight: 700;
}
.po-slide.kind-intro-scene .scene-tail {
  font-style: italic;
  color: var(--ink50) !important;
  font-size: clamp(0.95rem, 1.6vw, 1.8rem) !important;
}

/* Quote slide: big italic pull-quote, attribution underneath. */
.po-slide.kind-intro-quote .quote-text {
  font-family: var(--ff-disp);
  font-style: italic;
  font-weight: 700;
  font-size: clamp(2.2rem, 6.5vw, 6.5rem);
  line-height: 1.18;
  color: var(--brick);
  max-width: 22ch;
}
.po-slide.kind-intro-quote .quote-attr {
  margin-top: 2rem;
  font-family: var(--ff-mono);
  font-size: clamp(0.85rem, 1.3vw, 1.5rem);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink50);
}

/* Closing slide: "Visualización multisensorial · No es solo un gráfico,
   es información que se VE, se ESCUCHA y se SIENTE." */
.po-slide.kind-intro-closing .closing-kicker {
  font-family: var(--ff-mono);
  font-size: clamp(0.9rem, 1.5vw, 1.6rem);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brick);
  font-weight: 700;
  margin-bottom: 2rem;
}
.po-slide.kind-intro-closing .closing-line {
  font-family: var(--ff-disp);
  font-weight: 800;
  font-size: clamp(1.8rem, 5.2vw, 5.5rem);
  line-height: 1.18;
  color: var(--ink);
  max-width: 22ch;
}
.po-slide.kind-intro-closing .closing-line .cl-ve,
.po-slide.kind-intro-closing .closing-line .cl-oye,
.po-slide.kind-intro-closing .closing-line .cl-siente {
  color: var(--brick);
  font-style: italic;
}

/* "El curso" presentation slides — each slide is a chunk of the live page
   (cloned, exact same content), wrapped in .cs-fit and uniformly scaled
   with transform:scale() by scaleFitSlide() so it fills the screen at
   any resolution (~80 px margin). The page CSS (.cu-*, .hero-quote,
   .meto-bar, .pru-line, .calc-*) renders the content as-is — here we
   only neutralise the page-flow padding/margins that would otherwise
   eat into the scale budget. */
.po-slide.cs-slide { padding: 0; gap: 0; }
.cs-fit { transform-origin: center center; }
/* The .po-slide forces text-align:center; restore the page's left
   alignment inside cloned beats (the kicker/heading stay centred — they
   set text-align:center explicitly). */
.cs-fit .cu-beat { padding-top: 0.6rem; padding-bottom: 0.6rem; text-align: left; }
.cs-fit .hero-quote { margin: 0; border-top: none; border-bottom: none; }
.cs-fit .hero-closing { padding-top: 1.4rem; padding-bottom: 1.4rem; }
.cs-fit .curso-intro { border-bottom: none; }
.cs-calc-mount { display: flex; justify-content: center; }
.cs-calc-mount .calc { margin: 0; }
/* En modalidad presentación los títulos de cada promedio NUNCA se parten:
   "Promedio proyecto • E1 · E2 · E3" y "Nota final • teoría + proyecto"
   deben quedar en una sola línea. En lectura normal (mobile / pantalla
   angosta) se permite el wrap. */
.cs-fit .calc-check-head { white-space: nowrap; }

.po-slide.kind-moraleja {
  gap: 24px;
  padding: 0 6vw;
}
.po-slide.kind-moraleja .po-mor-icon {
  font-size: 4rem;
  line-height: 1;
  filter: drop-shadow(0 2px 6px rgba(0,0,0,0.4));
}
.po-slide.kind-moraleja .po-mor-label {
  font-family: var(--ff-mono);
  font-size: 0.85rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--slide-accent);
  font-weight: 700;
}
.po-slide.kind-moraleja .po-mor-body {
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: clamp(1.3rem, 2.6vw, 2.2rem);
  line-height: 1.4;
  color: #f4ecdf;
  max-width: 22ch;
}
.po-slide.kind-moraleja .po-mor-body strong {
  font-style: normal;
  color: #ffb38a;
}

/* ── Audio slide redesign: editorial hierarchy with a custom
   waveform SVG icon, kicker, big italic title, and audio controls.
   Replaces the old 🔊 emoji + flat mono label layout. ─────────── */
.po-slide.kind-audio {
  gap: 24px;
  padding: 0 6vw;
  align-items: center;
}
.po-slide.kind-audio .po-audio-kicker {
  font-family: var(--ff-mono);
  font-size: clamp(0.78rem, 1.1vw, 1.15rem);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--slide-accent);
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 1rem;
}
.po-slide.kind-audio .po-audio-kicker::before {
  content: "";
  display: inline-block;
  width: clamp(40px, 4vw, 80px);
  height: 2px;
  background: var(--slide-accent);
}
.po-slide.kind-audio .po-audio-wave {
  width: clamp(180px, 22vw, 320px);
  height: auto;
  fill: var(--slide-accent);
  filter: drop-shadow(0 2px 12px rgba(255,179,138,0.25));
  margin: 0.5rem 0;
}
.po-slide.kind-audio .po-audio-title {
  font-family: var(--ff-disp);
  font-style: italic;
  font-weight: 700;
  font-size: clamp(1.5rem, 3vw, 2.8rem);
  line-height: 1.3;
  color: var(--cream);
  max-width: 28ch;
  text-align: center;
}
.po-slide.kind-audio audio {
  width: min(520px, 80vw);
  margin-top: 0.5rem;
}

/* SIDE arrows — hidden by default; fade in only when the user moves the
   mouse (overlay gets `.mouse-active` for ~1.8 s after any mousemove).
   Keyboard navigation (←/→) is the primary path; the arrows are an
   on-demand visual affordance. */
.po-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(244,236,224,0.08);
  color: #f4ecdf;
  border: 1px solid rgba(244,236,224,0.18);
  width: 56px;
  height: 56px;
  border-radius: 50%;
  font-size: 2rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.12s, opacity 0.25s;
  z-index: 2;
}
.present-overlay.mouse-active .po-nav {
  opacity: 1;
  pointer-events: auto;
}
.po-nav:hover {
  background: rgba(200,68,42,0.30);
  border-color: var(--brick);
}
.po-nav:active { transform: translateY(-50%) scale(0.96); }
.po-nav:disabled { opacity: 0.18; cursor: default; }
.po-nav:disabled:hover {
  background: rgba(244,236,224,0.08);
  border-color: rgba(244,236,224,0.18);
}
/* On white stage (fig slides), arrows go dark so they're visible. */
.present-overlay[data-slide-kind="fig"] .po-nav {
  background: rgba(26,26,26,0.06);
  color: #1a1a1a;
  border-color: rgba(26,26,26,0.20);
}
.present-overlay[data-slide-kind="fig"] .po-nav:hover {
  background: rgba(200,68,42,0.20);
  border-color: var(--brick);
  color: var(--brick);
}
.po-prev { left: 18px; }
.po-next { right: 18px; }

@media (max-width: 720px) {
  .present-stage { padding: 6px 0 8px; }
  .po-nav {
    width: 44px;
    height: 44px;
    top: auto;
    bottom: 60px;
    transform: none;
  }
  .po-nav:active { transform: scale(0.96); }
  .po-prev { left: 12px; }
  .po-next { right: 12px; }
  .present-top { font-size: 0.65rem; }
  .po-cap-title { font-size: 0.85rem; }
}

/* ============================================================== */
/* STATIC PAGES (programa, ejemplos, herramientas, pruebas, ayuda)*/
/* ============================================================== */

.static-page {
  max-width: 1080px;
  margin: 0 auto;
  padding: 3rem 2rem 5rem;
}
/* The formal syllabus prose stays at a comfortable reading width even
   though the page itself (infographics) is now wide. */
.programa-formal { max-width: 760px; margin: 0 auto; scroll-margin-top: var(--header-h); }
.static-page h1 {
  font-family: var(--ff-disp); font-weight: 900;
  font-size: clamp(2rem, 5vw, 3.2rem);
  letter-spacing: -0.03em;
  margin-bottom: 0.5rem;
}
.static-page .page-intro {
  font-size: 1.05rem; color: var(--ink50);
  line-height: 1.65; margin-bottom: 2.5rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid var(--ink10);
}
.static-page h2 {
  font-family: var(--ff-disp); font-weight: 700;
  font-size: 1.45rem; margin: 2.6rem 0 0.8rem;
}
.static-page h3 {
  font-family: var(--ff-disp); font-weight: 700;
  font-size: 1.1rem; margin: 1.75rem 0 0.5rem;
  color: var(--wood);
}
.static-page p { margin-bottom: 0.9rem; line-height: 1.7; }
.static-page ul, .static-page ol { margin: 0.4rem 0 1rem 1.5rem; }
.static-page li { margin-bottom: 0.4rem; line-height: 1.6; }
.static-page strong { font-weight: 600; }
.static-page em { font-style: italic; }
.static-page table {
  width: 100%; border-collapse: collapse; margin: 1.5rem 0; font-size: 0.9rem;
}
.static-page th {
  background: var(--ink); color: var(--cream);
  font-family: var(--ff-mono); font-size: 0.66rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  padding: 8px 12px; text-align: left;
}
.static-page td { padding: 8px 12px; border-bottom: 1px solid var(--ink10); }

/* Proyecto cards */
.proyecto-card {
  background: var(--cream);
  border: 1px solid var(--ink10);
  padding: 1.25rem 1.5rem;
  margin: 1.25rem 0;
}
.proyecto-year {
  font-family: var(--ff-mono); font-size: 0.62rem;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--brick); margin-bottom: 0.6rem;
}
.proyecto-title {
  font-family: var(--ff-disp); font-weight: 700;
  font-size: 1.05rem; margin-bottom: 0.4rem;
}
.proyecto-credits { font-size: 0.85rem; color: var(--ink50); margin-bottom: 0.75rem; }
.proyecto-btns { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.75rem; }
.proyecto-btn {
  font-family: var(--ff-mono); font-size: 0.62rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  padding: 5px 12px; text-decoration: none; transition: opacity 0.12s;
}
.proyecto-btn.primary { background: var(--ink); color: var(--cream); }
.proyecto-btn.secondary { border: 1px solid var(--ink); color: var(--ink); }
.proyecto-btn:hover { opacity: 0.75; color: inherit; }
.video-container {
  position: relative; width: 100%; padding-top: 56.25%; margin: 1rem 0;
}
.video-container iframe {
  position: absolute; inset: 0; width: 100%; height: 100%; border: none;
}

/* Entrega cards */
.entrega-card {
  border-left: 3px solid var(--brick);
  background: var(--cream);
  padding: 1rem 1.25rem;
  margin: 1rem 0;
}
.entrega-num {
  font-family: var(--ff-mono); font-size: 0.62rem;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--brick); margin-bottom: 0.2rem;
}
.entrega-title {
  font-family: var(--ff-disp); font-weight: 700;
  font-size: 1.05rem; margin-bottom: 0.2rem;
}
.entrega-fecha {
  font-family: var(--ff-mono); font-size: 0.68rem;
  color: var(--wood); margin-bottom: 0.5rem;
}

/* ── FOOTER ──────────────────────────────────────────────────── */
.site-footer {
  border-top: 1px solid var(--ink10);
  padding: 1.25rem 2rem;
  display: flex;
  justify-content: space-between;
  font-family: var(--ff-mono);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.45;
  margin-top: 3rem;
}

/* ── RESPONSIVE ──────────────────────────────────────────────── */
@media (max-width: 980px) {
  .hero-intro    { padding: 4rem 1.5rem 2rem; }
  .hero-scene    { padding: 2.5rem 1.5rem; gap: 2rem; grid-template-columns: 1fr; }
  .hero-scene.scene-textleft,
  .hero-scene.scene-textright { grid-template-areas: "art" "text"; }
  .hero-scene .scene-art { max-width: 280px; margin: 0 auto; }
  .hero-quote    { padding: 3rem 1.5rem 3.5rem; }
  .hero-closing  { padding: 3rem 1.5rem 4rem; }
  .casita-large  { max-width: 280px; }
  .casita-still  { max-width: 240px; }
}
/* ─────────────────────────────────────────────────────────────────
   Demo embeds (iframe live, iframe static, video)
   ───────────────────────────────────────────────────────────────── */
.demo-embed {
  margin: 1.25rem 0 1.75rem;
  border: 1px solid var(--ink20);
  border-radius: 6px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 1px 0 rgba(0,0,0,0.02);
}
.demo-embed-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0.85rem;
  background: #f3efe8;
  border-bottom: 1px solid var(--ink15, rgba(0,0,0,0.08));
  font-size: 13px;
  font-family: var(--mono, ui-monospace, monospace);
}
.demo-embed-bar .dee-kind {
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: 11px;
  color: #6a5d4a;
}
.demo-embed-bar .dee-label {
  flex: 1;
  color: #444;
}
.demo-embed-bar .dee-fullscreen,
.demo-embed-bar .dee-open {
  background: transparent;
  border: 1px solid var(--ink20);
  padding: 0.15rem 0.5rem;
  border-radius: 3px;
  font: inherit;
  color: var(--accent, #b3502a);
  text-decoration: none;
  cursor: pointer;
  line-height: 1;
}
.demo-embed-bar .dee-fullscreen:hover,
.demo-embed-bar .dee-open:hover {
  background: var(--accent, #b3502a);
  color: #fff;
}

.demo-embed iframe {
  width: 100%;
  border: 0;
  display: block;
  background: #fff;
}
/* A .video-embed nested inside a demo-embed card fills it edge-to-edge —
   the standalone .cap-body .video-embed margin would otherwise leave white
   strips above and below the video inside the card. */
.demo-embed .video-embed { margin: 0; }

/* STATIC variant — overlay covers iframe so user can't interact */
.demo-embed.static .demo-embed-frame {
  position: relative;
}
.demo-embed.static .demo-embed-frame .dee-overlay {
  position: absolute;
  inset: 0;
  background: transparent;
  cursor: pointer;
  z-index: 2;
}
.demo-embed.static .demo-embed-bar { background: #ece6db; }
.demo-embed.static .demo-embed-bar .dee-kind { color: #5a5042; }

/* LIVE variant — accent the bar to signal "really interactive" */
.demo-embed.live .demo-embed-bar {
  background: #efe1d6;
  border-bottom-color: #d8c4b1;
}
.demo-embed.live .demo-embed-bar .dee-kind { color: #8a4a2a; }

/* VIDEO variant — for physical prototypes */
.demo-embed.video .demo-embed-bar {
  background: #1a1a1a;
  color: #eee;
  border-bottom-color: #333;
}
.demo-embed.video .demo-embed-bar .dee-kind { color: #ffaa55; }
.demo-embed.video .demo-embed-bar .dee-label { color: #eee; }

/* Fullscreen modal */
.demo-fullscreen-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.85);
  z-index: 9999;
  display: flex;
  flex-direction: column;
  padding: 2rem;
  box-sizing: border-box;
}
.demo-fullscreen-overlay .dfo-bar {
  display: flex;
  align-items: center;
  gap: 1rem;
  color: #fff;
  padding-bottom: 0.75rem;
}
.demo-fullscreen-overlay .dfo-bar .dfo-label {
  flex: 1;
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 14px;
}
.demo-fullscreen-overlay .dfo-close {
  background: #fff; color: #1a1a1a;
  border: 0; border-radius: 3px;
  padding: 0.4rem 0.85rem;
  font: inherit; cursor: pointer;
  font-size: 14px;
}
.demo-fullscreen-overlay iframe {
  flex: 1;
  width: 100%;
  border: 0;
  background: #fff;
  border-radius: 4px;
}
body.has-fullscreen-demo { overflow: hidden; }

@media (max-width: 768px) {
  :root { --sidebar-w: 220px; }
  .cap-hero { padding: 2.5rem 1.25rem 1.75rem; }
  .cap-body { padding: 0 1.25rem 3rem; }
  .static-page { padding: 2rem 1.25rem 4rem; }
  .capsulas-intro { padding: 2.5rem 1.5rem; }
  .hero-quote::before,
  .hero-quote::after { font-size: 5rem; }
}
@media (max-width: 560px) {
  .cap-section { padding: 1.25rem 1rem 2.5rem; }
  .hero-intro  { padding: 2.5rem 1.25rem 1.5rem; }
  .scene-text p { font-size: 1.05rem; }
}

/* ============================================================== */
/* MOBILE NAVIGATION — bottom-bar trigger + full-screen panel      */
/* The .mnav / .mbar elements exist on every page but stay off     */
/* until the viewport drops to phone width.                        */
/* ============================================================== */
.mnav, .mbar { display: none; }

@media (max-width: 720px) {
  /* The top bar drops to a centered logo — its links move into the panel. */
  .site-header { justify-content: center; }
  .site-header .site-nav { display: none; }
  /* The desktop tool rail is replaced by the bottom bar; Presentar
     and the text-size cycler are intentionally dropped on phones. */
  .tools-rail { display: none; }
  /* Capsule layout collapses to a single column — site.js lifts the
     index into the panel, so the in-flow column + resizer are gone. */
  .capsulas-layout { display: block; }
  .sidebar-resizer { display: none !important; }
  .capsulas-layout > .sidebar { display: none; }   /* pre-move: no flash */
  /* Leave room so the fixed bottom bar never covers the footer. */
  .page-body { padding-bottom: 4.5rem; }
  body.mnav-open { overflow: hidden; }

  /* ── Bottom bar — thumb-zone pills (Activ/Playlist/Menu) ──────
     Sized so all three buttons fit at 360 px viewport width without
     horizontal overflow. */
  .mbar {
    display: flex;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 350;
    align-items: center;
    gap: 0.4rem;
    padding: 0.55rem 0.55rem;
    pointer-events: none;
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  }
  .mbar--hidden { transform: translateY(165%); }
  .mbar-btn {
    pointer-events: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.32rem;
    height: 40px;
    padding: 0 0.7rem;
    background: var(--ink);
    color: var(--cream);
    border: none;
    border-radius: 10px;
    font-family: var(--ff-mono);
    font-size: 0.6rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    cursor: pointer;
    box-shadow: 0 7px 20px -7px rgba(0, 0, 0, 0.6);
    transition: background 0.15s ease, transform 0.1s ease;
    white-space: nowrap;
    min-width: 0;
  }
  .mbar-btn:active { transform: translateY(1px); }
  .mbar-ico { width: 16px; height: 16px; flex-shrink: 0; }
  .mbar-menu { margin-left: auto; }              /* always pinned right */
  .mbar-menu .mbar-ico { color: var(--slide-accent); }
  .mbar-label--index { display: none; }
  body.in-capsules .mbar-menu .mbar-label--menu  { display: none; }
  body.in-capsules .mbar-menu .mbar-label--index { display: inline; }
  body.activities-mode .mbar-activ { background: var(--brick); }

  /* ── Full-screen panel ───────────────────────────────────────── */
  .mnav {
    display: flex;
    flex-direction: column;
    position: fixed;
    inset: 0;
    z-index: 850;
    background: var(--ink);
    visibility: hidden;
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.28s ease, transform 0.28s ease,
                visibility 0s linear 0.28s;
  }
  .mnav.is-open {
    visibility: visible;
    opacity: 1;
    transform: none;
    transition: opacity 0.28s ease, transform 0.28s ease;
  }
  /* Close button floats bottom-right — near the menu trigger it
     replaces, on the panel's own dark ground. */
  .mnav-close {
    position: absolute;
    right: 0.85rem;
    bottom: 0.7rem;
    z-index: 10;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--ink);
    color: var(--cream);
    border: 1.5px solid rgba(244, 236, 224, 0.4);
    box-shadow: 0 6px 22px -4px rgba(0, 0, 0, 0.8);
    cursor: pointer;
  }
  .mnav-close svg { width: 22px; height: 22px; }
  .mnav-links {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    padding: 1.3rem 0 0.6rem;
  }
  .mnav-link {
    font-family: var(--ff-mono);
    font-size: 0.82rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--cream);
    text-decoration: none;
    padding: 0.92rem 1.35rem;
    opacity: 0.62;
    border-left: 3px solid transparent;
    transition: opacity 0.12s ease;
  }
  .mnav-link:hover { opacity: 1; color: var(--cream); }
  .mnav-link.active {
    opacity: 1;
    color: var(--slide-accent);
    border-left-color: var(--slide-accent);
  }
  body.ejemplos-mode .mnav-link[href$="#ejemplos"] {
    opacity: 1;
    color: var(--slide-accent);
    border-left-color: var(--slide-accent);
  }
  /* The capsule index — the SAME .sidebar element, moved in by site.js,
     filling the rest of the panel as its own scroll area. */
  .mnav .sidebar {
    position: static;
    flex: 1 1 auto;
    width: 100%;
    height: auto;
    min-height: 0;
    border-right: none;
    border-top: 2px solid var(--brick);
  }
  /* Extra room at the end of the index so the last capsules clear the
     floating close button when scrolled all the way down. */
  .mnav .sidebar-inner { padding-bottom: 5.5rem; }
}

/* ── Mobile content reflow — keep capsule content within the screen ── */
@media (max-width: 720px) {
  /* Capsule hero titles: smaller, with long words breaking instead of
     pushing the whole page wider than the viewport. */
  .cap-hero .cap-h1 {
    font-size: clamp(1.6rem, 5.5vw, 2.5rem);
    line-height: 1.1;
  }
  .cap-h1,
  .cap-act-title,
  .act-title { overflow-wrap: break-word; }
  /* (cap-pl-row variant removed — cápsulas now use the same .pl-row as
     the playlist, so the base mobile rules above cover both contexts.) */
  /* "Material para clase" cards drop to one column so the 320px-min
     grid track never overflows a narrow screen. */
  .cap-act-grid { grid-template-columns: 1fr; }

  /* Gallery title wraps cleanly even on the narrowest phones. */
  .cap-body .gallery-head h4 { overflow-wrap: break-word; }

  /* Live / static demos: the iframe is dropped on phones — these
     visualizations are built for a desktop screen. Each demo collapses
     into one tappable card that opens the real thing in a new tab. */
  .demo-embed.live,
  .demo-embed.static { position: relative; }
  .demo-embed.live iframe,
  .demo-embed.static .demo-embed-frame,
  .demo-embed.live .dee-fullscreen,
  .demo-embed.static .dee-fullscreen { display: none; }
  .demo-embed.live .demo-embed-bar,
  .demo-embed.static .demo-embed-bar {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.3rem;
    padding: 0.85rem 1rem 0.95rem;
    border-bottom: none;
  }
  .demo-embed.live .dee-label,
  .demo-embed.static .dee-label {
    font-family: var(--ff-disp);
    font-size: 1rem;
    line-height: 1.3;
    color: var(--ink);
  }
  /* The "open in new tab" link expands to cover the whole card. */
  .demo-embed.live .dee-open,
  .demo-embed.static .dee-open {
    position: absolute;
    inset: 0;
    border: 0;
    padding: 0;
    font-size: 0;
    background: transparent;
  }
  /* Disclaimer + call to action, shown under the title. */
  .demo-embed.live .demo-embed-bar::after,
  .demo-embed.static .demo-embed-bar::after {
    content: "Hecha para verse en computador — tocá para abrir ↗";
    font-family: var(--ff-mono);
    font-size: 0.66rem;
    letter-spacing: 0.03em;
    line-height: 1.4;
    color: var(--brick);
    margin-top: 0.1rem;
  }

  /* Video demos keep their player, but the bar stacks too — kind
     label on top, title below. */
  .demo-embed.video .demo-embed-bar {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.3rem;
    padding: 0.7rem 0.9rem;
  }
  .demo-embed.video .dee-label {
    font-family: var(--ff-disp);
    font-size: 1rem;
    line-height: 1.3;
  }

  /* Activities view ("Activ." mode): single-column tiles + tighter
     padding so nothing runs past a phone screen. */
  .activities-view { padding: 1.75rem 1rem 3.5rem; }
  .aview-grid { grid-template-columns: 1fr; gap: 1rem; }
  .aview-title { font-size: clamp(1.7rem, 7vw, 2.6rem); }
  .atile-cap-title { overflow-wrap: break-word; }

  /* Ejemplos view — tighter padding on phones. */
  .ejemplos-view { padding: 1.75rem 1rem 3.5rem; }
  .ev-title { font-size: clamp(1.7rem, 7vw, 2.6rem); }

  /* Minimal lateral margins — capsule text runs out to the bottom-bar
     buttons (0.85rem inset) instead of a narrow centered column. */
  .cap-section { padding-left: 0; padding-right: 0; }
  .cap-hero,
  .cap-body,
  .cap-tech-links,
  .cap-demos,
  .cap-activities {
    padding-left: 0.85rem;
    padding-right: 0.85rem;
  }

  /* "En pocas palabras" premise block: lightbulb on its own line at the
     top, text full-width below for comfortable reading. */
  .cap-body blockquote.cap-tagline {
    display: block;
    padding: 1.05rem 1rem 1.2rem;
  }
  .cap-body blockquote.cap-tagline::before {
    display: block;
    text-align: left;
    margin-bottom: 0.35rem;
  }
  .cap-body blockquote.cap-tagline > p {
    font-size: 1.15rem;
  }

  /* Footer: drop the long course-code line — keep just the tagline
     (left) and the year (right). */
  .site-footer span:first-child { display: none; }

  /* "El curso" section: minimal lateral margins, like the capsule text. */
  .cu-beat { padding-left: 0.85rem; padding-right: 0.85rem; }

  /* Tables size to their content and scroll horizontally inside their
     wrapper instead of crushing columns into an unreadable grid. */
  .cap-body .table-scroll table {
    table-layout: auto;
    width: auto;
    min-width: 100%;
  }
  .cap-body .table-scroll th,
  .cap-body .table-scroll td { min-width: 9rem; }
}

/* ── NEW: Self-contained figure block + clickable [fig:] / [gal:] refs ── */
.cap-body .cap-fig {
  margin: 1.5rem 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.cap-body .cap-fig img {
  /* Default sizing: respect natural dimensions, cap both axes.
     The orientation-specific rules below add WIDTH:100% only for
     LANDSCAPE images (aspect ≥ 1.1) so they fill the column and
     grow with the AAA text-size toggle. Portrait / square images
     stay at intrinsic size constrained by max-height — making them
     stretch column-wide would force their height beyond what fits
     comfortably on a screen. */
  max-width: 100%;
  max-height: 66vh;     /* never taller than 2/3 of the viewport */
  height: auto;
  width: auto;
  background: #fff;
  display: block;
  box-sizing: border-box;
  /* Lift the image off the cream page: a thin warm border crisply
     finishes the edge (white charts otherwise bleed into the page),
     a soft warm-tinted shadow gives depth — that is what actually
     stops them looking flat — and a small radius softens the corners. */
  border: 1px solid var(--wood);
  border-radius: 4px;
  box-shadow: 0 1px 3px rgba(60, 40, 22, 0.14),
              0 10px 26px rgba(60, 40, 22, 0.15);
}
/* JS tags each img with .landscape or .portrait once intrinsic size is
   known (on load). Landscape images fill the column width (grow with
   the AAA text-size cycler); portrait images stay constrained by
   max-height + intrinsic width. */
.cap-body .cap-fig img.landscape {
  width: 100%;
}

/* YouTube / video figure — column-wide, scaling with the AAA text-size
   toggle that widens --max-content. (Was previously capped at 760 px.) */
.cap-body .cap-fig-video {
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
  display: block;
}
.cap-body .cap-fig-video iframe {
  width: 100%;
  height: 100%;
  border: none;
  display: block;
}
/* Live interactive demo figure: reuses the .demo-embed.live chrome from
   the technical capsules, but must fill the text column — the .cap-fig
   flex column (align-items:center) would otherwise shrink it to the
   iframe's intrinsic ~300px width. */
.cap-body .cap-fig .demo-embed { width: 100%; }
.cap-body .cap-fig figcaption {
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: 0.95rem;
  color: var(--ink);
  margin-top: 0.6rem;
  line-height: 1.5;
  max-width: 70ch;
}
.cap-body .cap-fig figcaption b {
  font-style: normal;
  font-weight: 700;
  color: var(--brick);
}
.cap-body .cap-fig-source {
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  color: var(--ink50);
  font-style: normal;
  letter-spacing: 0.04em;
}
.cap-body .cap-fig.missing,
.cap-body .gallery.missing {
  border: 2px dashed var(--brick);
  padding: 1rem;
  background: rgba(200, 68, 42, 0.05);
}

/* ── Cross-capsule figure: small thumbnail + click-to-fullscreen ────── */
.cap-body .cap-fig.cross-cap {
  margin: 1.2rem auto;
  max-width: 360px;
  padding: 0;
  display: block;
}
.cap-body .cap-fig.cross-cap .cross-cap-trigger {
  display: block;
  width: 100%;
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 6px;
  background: #fafafa;
  padding: 8px;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
  font: inherit;
  color: inherit;
  text-align: left;
}
.cap-body .cap-fig.cross-cap .cross-cap-trigger:hover,
.cap-body .cap-fig.cross-cap .cross-cap-trigger:focus-visible {
  border-color: var(--brick);
  background: #fff;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  outline: none;
}
.cap-body .cap-fig.cross-cap .cross-cap-thumb {
  display: block;
  max-height: 140px;
  overflow: hidden;
  border-radius: 4px;
  background: #fff;
  text-align: center;
}
.cap-body .cap-fig.cross-cap .cross-cap-thumb img {
  max-height: 140px;
  width: auto;
  max-width: 100%;
  margin: 0 auto;
}
.cap-body .cap-fig.cross-cap .cross-cap-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 6px 4px 0;
  font-family: var(--ff-mono);
  font-size: 0.68rem;
  letter-spacing: 0.04em;
}
.cap-body .cap-fig.cross-cap .cross-cap-num {
  color: var(--brick);
  font-weight: 700;
}
.cap-body .cap-fig.cross-cap .cross-cap-owner {
  color: var(--ink50);
  flex: 1;
}
.cap-body .cap-fig.cross-cap .cross-cap-action {
  color: var(--brick);
  font-weight: 600;
}
/* The full caption is hidden inline (only the small bar above is visible);
   it's still in the DOM so the modal can render it on click. */
.cap-body .cap-fig.cross-cap > figcaption {
  display: none;
}
/* Text link to a cross-capsule figure (dashed underline = "opens modal") */
.cap-body a.fig-ref.cross {
  border-bottom: 1px dashed currentColor;
  text-decoration: none;
}
.cap-body a.fig-ref.cross::after {
  content: " ⛶";
  font-size: 0.75em;
  opacity: 0.6;
}

/* ── Fullscreen modal for any figure (cross-cap or text-link) ────────── */
.fig-modal {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(15, 15, 18, 0.92);
  align-items: center;
  justify-content: center;
  padding: 40px;
  overflow: auto;
}
.fig-modal.open {
  display: flex;
}
.fig-modal-content {
  max-width: 95vw;
  max-height: 92vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}
.fig-modal-content img {
  max-width: 95vw;
  max-height: 80vh;
  width: auto;
  height: auto;
  background: #fff;
  border-radius: 4px;
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.5);
}
.fig-modal-caption {
  color: #f0f0f0;
  font-family: var(--ff-disp);
  font-style: italic;
  font-size: 0.95rem;
  max-width: 80ch;
  text-align: center;
  line-height: 1.5;
}
.fig-modal-caption b {
  color: #ffaa88;
  font-style: normal;
  font-weight: 700;
}
.fig-modal-close {
  position: absolute;
  top: 16px;
  right: 20px;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 0;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.12s;
}
.fig-modal-close:hover { background: rgba(255, 255, 255, 0.25); }
body.fig-modal-open { overflow: hidden; }

/* ── Créditos — popup triggered by the "Créditos" nav link ──────────── */
/* Backdrop fills the viewport; the card is a centered, paper-like sheet
   with the same warm palette as the rest of the site. */
.credits-modal {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: rgba(20, 18, 16, 0.78);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 32px 20px;
  overflow: auto;
}
.credits-modal.open { display: flex; }
.credits-modal[hidden] { display: none; }
.credits-modal.open[hidden] { display: flex; }   /* override [hidden] when open */

.credits-card {
  position: relative;
  background: var(--cream, #f7f1e7);
  color: var(--ink, #2b2520);
  max-width: 640px;
  width: 100%;
  border-radius: 6px;
  padding: 38px 40px 30px;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.45);
  border-top: 4px solid var(--brick, #c7442a);
  font-family: var(--ff-text, sans-serif);
}

.credits-close {
  position: absolute;
  top: 12px;
  right: 14px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 0;
  background: transparent;
  color: var(--ink50, #6c615a);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.12s, color 0.12s;
}
.credits-close:hover { background: rgba(0,0,0,0.06); color: var(--brick, #c7442a); }

.credits-head { margin-bottom: 14px; }
.credits-kicker {
  display: block;
  font-family: var(--ff-disp, sans-serif);
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brick, #c7442a);
  margin-bottom: 4px;
}
.credits-title {
  font-family: var(--ff-disp, serif);
  font-size: 1.9rem;
  font-weight: 700;
  margin: 0;
  line-height: 1.1;
}

.credits-body p {
  font-size: 0.96rem;
  line-height: 1.6;
  margin: 0 0 0.85rem;
}
.credits-body p:last-child { margin-bottom: 0; }
.credits-body strong { font-weight: 600; }
.credits-body em { font-style: italic; }

.credits-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid rgba(0,0,0,0.08);
}
.credits-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 10px 18px;
  border-radius: 4px;
  font-family: var(--ff-disp, sans-serif);
  font-size: 0.92rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  border: 0;
  transition: background 0.12s, color 0.12s, transform 0.05s;
}
.credits-btn:active { transform: translateY(1px); }
.credits-btn.primary {
  background: var(--brick, #c7442a);
  color: #fff;
}
.credits-btn.primary:hover { background: var(--brick-dk, #9a3320); }
.credits-btn.secondary {
  background: transparent;
  color: var(--ink, #2b2520);
  border: 1.5px solid var(--ink20, #c8bfb6);
}
.credits-btn.secondary:hover {
  background: rgba(0,0,0,0.04);
  border-color: var(--ink40, #8a7f76);
}

body.credits-modal-open { overflow: hidden; }

@media (max-width: 520px) {
  .credits-card { padding: 28px 22px 22px; }
  .credits-title { font-size: 1.5rem; }
  .credits-actions { flex-direction: column; }
  .credits-btn { justify-content: center; }
}

/* ── "La moraleja del profesor" — closing block of each capsule ──────── */
.cap-body .profe-moraleja {
  margin: 2.4rem 0 1rem;
  display: grid;
  grid-template-columns: 56px 1fr;
  gap: 18px;
  align-items: start;
  padding: 18px 22px 18px 18px;
  background: linear-gradient(
    to right,
    rgba(200, 68, 42, 0.07) 0%,
    rgba(200, 68, 42, 0.02) 100%);
  border-left: 4px solid var(--brick);
  border-radius: 4px;
  position: relative;
}
.cap-body .profe-moraleja .pm-icon {
  font-size: 38px;
  line-height: 1;
  text-align: center;
  align-self: center;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.15));
}
.cap-body .profe-moraleja .pm-meta {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.cap-body .profe-moraleja .pm-label {
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brick);
  font-weight: 700;
}
.cap-body .profe-moraleja .pm-body {
  font-family: var(--ff-disp);
  font-size: 1.15rem;
  line-height: 1.45;
  color: var(--ink);
  margin: 0;
  font-style: italic;
}
.cap-body .profe-moraleja .pm-body strong {
  font-style: normal;
  color: var(--brick);
}
@media (max-width: 520px) {
  .cap-body .profe-moraleja {
    grid-template-columns: 1fr;
    padding: 14px 16px;
  }
  .cap-body .profe-moraleja .pm-icon {
    font-size: 28px;
    text-align: left;
  }
}
.cap-body .missing-marker {
  font-family: var(--ff-mono);
  color: var(--brick);
  font-size: 0.85rem;
}

/* Clickable references inside paragraphs */
.cap-body .fig-ref,
.cap-body .gal-ref {
  font-family: var(--ff-mono);
  font-size: 0.85em;
  color: var(--brick);
  text-decoration: none;
  font-weight: 600;
  border-bottom: 1px dotted var(--brick);
  padding: 0 0.15em;
  transition: background 0.12s;
}
.cap-body .fig-ref:hover,
.cap-body .gal-ref:hover {
  background: rgba(200, 68, 42, 0.12);
  border-bottom-style: solid;
}

/* Auto-numbered gallery title (Fig. X.Y / Galería X.Y) — same chip style */
.cap-body .gallery .gallery-head h4 b {
  color: var(--brick);
  font-weight: 700;
}
.cap-body .gallery-desc {
  padding: 0 1rem 0.6rem;
  font-family: var(--ff-body);
  font-size: 0.9rem;
  color: var(--ink);
  line-height: 1.5;
  font-style: italic;
}

/* (Removed .audio-tagline — unified into .audio-song-label above) */

/* ── EL CURSO — narrativa editorial (programa.html) ──────────── */
.curso-hero {
  background:
    radial-gradient(ellipse at 50% -10%, rgba(200,68,42,0.08), transparent 55%),
    var(--paper);
  border-bottom: 1px solid var(--ink20);
  position: relative;
  overflow: hidden;
}

/* Cada beat: una columna centrada sobre el fondo papel. */
.cu-beat {
  max-width: 900px;
  margin: 0 auto;
  padding: 4rem 3rem;
  scroll-margin-top: var(--header-h);
}
.cu-beat--wide { max-width: 1080px; }

/* Cabecera del beat — kicker + título, centrados. */
.cu-kicker {
  font-family: var(--ff-mono);
  font-size: 0.68rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brick);
  text-align: center;
  margin-bottom: 0.9rem;
}
.cu-h {
  font-family: var(--ff-disp);
  font-weight: 700;
  font-size: clamp(1.7rem, 3.4vw, 2.5rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-align: center;
  margin: 0 0 1.7rem;
}
.cu-h em { font-style: italic; color: var(--brick); }

/* Prosa narrativa — alineada a la izquierda, en columna centrada. */
.cu-prose { max-width: 680px; margin: 0 auto; }
.cu-prose p {
  font-family: var(--ff-disp);
  font-size: 1.18rem;
  line-height: 1.6;
  color: var(--ink);
  margin: 0 0 1rem;
}
.cu-prose p:last-child { margin-bottom: 0; }
.cu-prose strong { font-weight: 700; color: var(--brick); }

/* Bajada corta de una línea (intro de la calculadora) — centrada. */
.cu-lead {
  font-family: var(--ff-disp);
  font-size: 1.18rem;
  line-height: 1.5;
  color: var(--ink);
  text-align: center;
  max-width: 580px;
  margin: 0 auto 1.9rem;
}
.cu-lead strong { font-weight: 700; color: var(--brick); }

/* Trío de cifras — el dato del curso, grande y desnudo. */
.cu-stats {
  display: flex;
  justify-content: center;
  max-width: 640px;
  margin: 2.4rem auto 0;
}
.cu-stat { flex: 1; padding: 0 0.6rem; text-align: center; }
.cu-stat + .cu-stat { border-left: 1px solid var(--ink20); }
.cu-stat-n {
  display: block;
  font-family: var(--ff-disp);
  font-weight: 900;
  font-size: clamp(2.4rem, 5vw, 3.3rem);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--brick);
}
.cu-stat-l {
  display: block;
  margin-top: 0.55rem;
  font-family: var(--ff-mono);
  font-size: 0.64rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink50);
  line-height: 1.35;
}
/* Operador de una ecuación de cifras (ej. 2 + 3 = 5): conecta los
   .cu-stat para que se lean como una suma, no como datos sueltos. */
.cu-stat-op {
  flex: 0 0 auto;
  align-self: flex-start;
  display: flex;
  align-items: center;
  justify-content: center;
  height: clamp(2.4rem, 5vw, 3.3rem);
  padding: 0 0.5rem;
  font-family: var(--ff-disp);
  font-weight: 400;
  font-size: 2rem;
  color: var(--ink50);
}

/* Lista de definiciones — término + cuerpo, sin tarjetas, con filete. */
/* The def-list shrinks to its content and is centred (margin:auto) — so
   a list with short right-column text stays balanced, not left-heavy. */
.cu-defs { width: fit-content; max-width: 100%; margin: 2.5rem auto 0; }
.cu-def {
  display: grid;
  grid-template-columns: 190px 460px;
  gap: 1.7rem;
  padding: 1.35rem 0;
  border-top: 1px solid var(--ink10);
}
/* No outer frame lines — only the separators between items. */
.cu-def:first-child { border-top: none; }
.cu-def:last-child { border-bottom: none; }
.cu-def-term {
  font-family: var(--ff-disp);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--ink);
  line-height: 1.25;
}
.cu-def-term a { color: var(--ink); text-decoration: none; }
.cu-def-term a:hover { color: var(--brick); opacity: 1; }
.cu-tag {
  display: block;
  margin-top: 0.3rem;
  font-family: var(--ff-mono);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink50);
}
.cu-tag--key { color: var(--brick); }
.cu-def-body p {
  font-family: var(--ff-disp);
  font-size: 1.04rem;
  line-height: 1.55;
  color: var(--ink);
  margin: 0;
}
.cu-def-body p strong { font-weight: 700; color: var(--brick); }
.cu-chan {
  display: block;
  margin-top: 0.6rem;
  font-family: var(--ff-mono);
  font-size: 0.76rem;
  color: var(--ink50);
}
a.cu-chan { color: var(--brick); text-decoration: none; }
a.cu-chan:hover { opacity: 1; text-decoration: underline; }

/* Nota al pie de un beat — aclaración secundaria, atenuada. */
.cu-note {
  max-width: 680px;
  margin: 1.7rem auto 0;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--ink50);
}
.cu-note strong { font-weight: 700; color: var(--ink); }

/* El <em> dentro del cierre reutilizado (.closing-line). */
.curso-hero .closing-line em { font-style: italic; color: var(--brick); }

/* El curso — quotes & closing line: ink base with brick bold/italic
   emphasis (applies both on the page and in the presentation slides). */
.curso-hero .quote-text,
.cs-fit .quote-text { color: var(--ink); }
.quote-text strong { color: var(--brick); font-weight: 700; }
.curso-hero .closing-line,
.cs-fit .closing-line { font-weight: 400; }
.curso-hero .closing-line strong,
.cs-fit .closing-line strong { color: var(--brick); font-weight: 700; }
.cs-fit .closing-line em { font-style: italic; color: var(--brick); }

/* Título del programa formal — compacto, aunque caiga en dos líneas. */
.programa-formal h1 {
  font-size: clamp(1.9rem, 4vw, 2.7rem);
  line-height: 1.06;
}

/* Línea-índice del hero — los temas del curso, con viñetas. */
.cu-hero-toc {
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.9;
  margin: 0 0 1.1rem;
}
.cu-hero-toc a {
  color: var(--ink);
  text-decoration: none;
  transition: color 0.12s ease;
}
.cu-hero-toc a:hover { color: var(--brick); opacity: 1; }
.cu-hero-toc b { color: var(--brick); font-weight: 400; margin: 0 0.15rem; }
.hero-intro .hero-ctas { margin-top: 1.9rem; }

/* Sub-encabezado dentro de un beat — ícono + etiqueta. */
.cu-sub {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  margin: 2.9rem 0 0;
}
.cu-sub-ico {
  flex: 0 0 auto;
  width: 25px;
  height: 25px;
  color: var(--brick);
}
.cu-sub-ico svg { display: block; width: 100%; height: 100%; }
.cu-sub-label {
  font-family: var(--ff-disp);
  font-weight: 700;
  font-size: 1.3rem;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.cu-sub + .cu-defs { margin-top: 0.5rem; }

/* Trío de herramientas en fila — comparación lado a lado. */
.cu-trio {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.8rem;
  max-width: 780px;
  margin: 2.3rem auto 0;
}
.cu-trio-item {
  border-top: 2px solid var(--ink20);
  padding-top: 0.9rem;
}
.cu-trio-item--free { border-top-color: var(--brick); }
.cu-trio-name {
  font-family: var(--ff-disp);
  font-weight: 700;
  font-size: 1.16rem;
  line-height: 1.2;
  color: var(--ink);
}
.cu-trio-name a { color: var(--ink); text-decoration: none; }
.cu-trio-name a:hover { color: var(--brick); opacity: 1; }
.cu-trio-tag {
  margin-top: 0.4rem;
  font-family: var(--ff-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink50);
}
.cu-trio-tag--free { color: var(--brick); }
.cu-trio-desc {
  font-family: var(--ff-disp);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--ink);
  margin: 0.55rem 0 0;
}

.meto-bar { max-width: 720px; margin: 2.4rem auto 0; }
.meto-bar-title {
  font-family: var(--ff-mono); font-size: 0.74rem; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--ink50); margin-bottom: 0.5rem;
  text-align: center;
}
.meto-bar-row { display: flex; gap: 3px; height: 66px; border-radius: 8px; overflow: hidden; }
.meto-seg {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  color: var(--ink); text-align: center; padding: 0;
  flex-basis: 0; min-width: 0; box-sizing: border-box;
  overflow: hidden;
}
.meto-seg span { font-size: 0.75rem; opacity: 0.9; }
.meto-seg strong { font-size: 1.15rem; font-weight: 800; }
/* Barras = tonos cálidos neutros (la nota es dato, no juicio). Claros para
   que la línea de aprobación oscura se vea siempre encima. I más claro, E más oscuro. */
.seg-i1 { background: #e8d7b9; }
.seg-i2 { background: #e8d7b9; }
.seg-e1 { background: #d2c3a9; }
.seg-e2 { background: #d2c3a9; }
.seg-e3 { background: #d2c3a9; }
.meto-bar-brackets { display: flex; margin-top: 5px; }
.meto-brk {
  border-top: 3px solid var(--ink20); padding-top: 0.32rem;
  font-size: 0.77rem; font-weight: 600; color: var(--ink50); text-align: center;
  flex-basis: 0; min-width: 0;
}
.meto-brk-proj { border-top-color: rgba(26, 26, 26, 0.4); color: rgba(26, 26, 26, 0.7); }

@media (max-width: 640px) {
  .cu-beat { padding: 3rem 0.85rem; }
  .cu-def { grid-template-columns: 1fr; gap: 0.4rem; }
  .cu-def-body p { font-size: 1rem; }
  .cu-trio { grid-template-columns: 1fr; gap: 1.5rem; }
  .cu-sub-label { font-size: 1.15rem; }
  .cu-hero-toc { font-size: 0.63rem; letter-spacing: 0.09em; }
}
@media (max-width: 560px) {
  .meto-seg span { display: none; }
  .meto-brk { font-size: 0.68rem; }
}

/* ── CALCULADORA DE NOTA INTERACTIVA (sección 4) ─────────────── */
.calc { margin: 0.4rem 0 0; }
.calc-chart { display: flex; gap: 0.5rem; margin-top: 0.4rem; margin-bottom: 3.4rem; }
.calc-yaxis {
  flex: 0 0 30px; height: 230px; position: relative;
  font-family: var(--ff-mono); font-size: 0.62rem; color: var(--ink50);
}
.calc-yaxis span { position: absolute; left: 0; line-height: 1; }
.calc-yaxis span:nth-child(1) { top: -0.35em; }
.calc-yaxis span:nth-child(2) { top: calc(42.86% - 0.35em); }
.calc-yaxis span:nth-child(3) { top: calc(85.71% - 0.35em); }
.calc-plot { flex: 1; position: relative; height: 230px; }
.calc-cols {
  position: relative; display: flex; gap: 5px; height: 230px;
}
.calc-aprob {
  position: absolute; left: 0; right: 0; bottom: 57.14%;
  border-top: 2px dashed var(--ink); z-index: 3; pointer-events: none;
}
.calc-aprob span {
  position: absolute; right: 0; bottom: 3px;
  font-family: var(--ff-mono); font-size: 0.6rem; font-weight: 700;
  color: var(--ink);
}
.calc-col { position: relative; display: flex; }
.calc-track {
  position: relative; width: 100%; height: 100%;
  background: rgba(26, 26, 26, 0.06);
  border-radius: 4px 4px 0 0; overflow: hidden;
  cursor: ns-resize; touch-action: none;
}
.calc-fill {
  position: absolute; left: 0; right: 0; bottom: 0; height: 0%;
  border-radius: 4px 4px 0 0;
  transition: height 0.4s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.calc-grade {
  position: absolute; bottom: 3px; left: 50%;
  transform: translateX(-50%);
  width: 2.7rem; height: 22px; z-index: 4;
  border: none; outline: none;
  text-align: center; color: var(--ink);
  font-family: var(--ff-mono); font-weight: 800; font-size: 0.8rem;
  cursor: text;
  transition: bottom 0.4s cubic-bezier(0.22, 0.61, 0.36, 1);
  /* En mobile: sin esto, arrastrar verticalmente desde el número scrollea la
     página (el browser interpreta el touch como pan-y). Con touch-action:none
     el browser no se mete y nuestros pointermove handlers reciben el drag
     normalmente — mismo comportamiento que la barra. El tap (touch + release
     sin moverse) sigue disparando click → focus, así que tocar el número
     para tipear sigue funcionando. */
  touch-action: none;
  /* En mobile la columna se vuelve angosta y el fondo del input queda más
     ancho que la barra (y la línea "Aprobación · 4,0" se cruza por debajo).
     Mantenemos el fondo de color (lo aporta .seg-* y ES necesario para tapar
     la línea cuando el número se posa encima), pero lo desvanecemos en los
     bordes con un mask cruzado: gradiente horizontal × gradiente vertical
     compuestos en "intersect" → solo el centro 25-75% queda 100% opaco, el
     resto se atenúa hasta transparente. El número (texto, centrado) cae en
     la zona sólida del mask, así que se ve nítido. */
  -webkit-mask-image:
    linear-gradient(to right,  transparent 0%, #000 25%, #000 75%, transparent 100%),
    linear-gradient(to bottom, transparent 0%, #000 25%, #000 75%, transparent 100%);
  -webkit-mask-composite: source-in;
          mask-image:
    linear-gradient(to right,  transparent 0%, #000 25%, #000 75%, transparent 100%),
    linear-gradient(to bottom, transparent 0%, #000 25%, #000 75%, transparent 100%);
          mask-composite: intersect;
}
.calc-col.dragging .calc-fill,
.calc-col.dragging .calc-grade { transition: none; }
.calc-code {
  position: absolute; top: 100%; left: 0; right: 0; text-align: center;
  font-family: var(--ff-mono); font-size: 0.72rem; font-weight: 700;
  color: var(--ink50); padding-top: 5px;
}
.calc-result { margin-top: 0; }
/* Resultado en una fila: teoría · proyecto · nota final (un poco más ancha). */
.calc-row { display: flex; gap: 2rem; align-items: flex-start; }
.calc-check { flex: 35 1 0; }
.calc-verdict { flex: 31 1 0; }
.calc-num {
  flex: 0 0 4rem; text-align: right;
  font-family: var(--ff-disp); font-weight: 900; font-size: 1.25rem;
  color: var(--ink50);
}
.calc-badge { display: flex; transform: translateY(-4px); }
.thumb { display: none; width: 1.9rem; height: 1.9rem; }
.thumb-up { fill: var(--ok); }
.thumb-down { fill: var(--bad); }
.calc-verdict.is-pass .thumb-up { display: block; }
.calc-verdict.is-fail .thumb-down { display: block; }
.calc-verdict.is-pass .calc-num { color: var(--ok); }
.calc-verdict.is-fail .calc-num { color: var(--bad); }
.calc-verdict.is-pass .calc-check-fill { background: var(--ok); }
.calc-verdict.is-fail .calc-check-fill { background: var(--bad); }
/* En móvil se apila: primero la nota final, luego los dos promedios. */
@media (max-width: 820px) {
  .calc-row { flex-direction: column; align-items: stretch; gap: 1.4rem; }
  .calc-row > * { flex: none; }
  .calc-verdict { order: -1; }
}
.calc-check-head {
  font-size: 0.9rem; color: var(--ink); margin-bottom: 0.5rem;
}
.calc-check .calc-check-head { font-style: italic; }
.calc-verdict .calc-check-head { font-weight: 700; }
/* Sub en línea con el nombre. white-space:nowrap = si falta sitio,
   baja entero a la línea de abajo, nunca se parte a media frase. */
.calc-check-sub {
  white-space: nowrap; font-style: normal;
  font-family: var(--ff-mono); font-size: 0.7rem; font-weight: 600;
  color: var(--ink50);
}
.calc-check-meter { display: flex; align-items: center; gap: 0.7rem; min-height: 2rem; }
.calc-check-bar {
  flex: 1; height: 10px; border-radius: 5px;
  background: rgba(26, 26, 26, 0.08); overflow: hidden;
}
.calc-check-fill {
  height: 100%; width: 0%; border-radius: 5px;
  background: var(--ink20);
  transition: width 0.4s cubic-bezier(0.22, 0.61, 0.36, 1), background 0.2s ease;
}
.calc-check-val {
  flex: 0 0 4rem; text-align: right;
  font-family: var(--ff-disp); font-weight: 600; font-size: 1.25rem;
  color: var(--ink50);
}
.calc-check.is-ok .calc-check-fill { background: var(--ok); }
.calc-check.is-ok .calc-check-val { color: var(--ok); }
.calc-check.is-bad .calc-check-fill { background: var(--bad); }
.calc-check.is-bad .calc-check-val { color: var(--bad); }
.calc-msg { font-size: 0.84rem; color: var(--ink50); line-height: 1.5; margin: 1.4rem 0 0; text-align: center; }

/* ── EVALUACIONES — línea de tiempo editorial (en programa.html) ── */
.pru-line {
  list-style: none;
  max-width: 780px;
  margin: 2.4rem auto 0;
  padding: 0;
}
.pru-step {
  position: relative;
  display: grid;
  grid-template-columns: 62px 1fr;
  gap: 2.3rem;
  padding: 1.6rem 0;
}
/* nodo del hito, sobre la línea */
.pru-step::before {
  content: "";
  position: absolute;
  left: 75px; top: 2.15rem;
  width: 13px; height: 13px;
  border-radius: 50%;
  background: var(--ink50);
  z-index: 2;
}
.pru-step--teoria::before   { background: var(--wood); }
.pru-step--proyecto::before { background: var(--brick); }
/* conector entre nodos consecutivos */
.pru-step:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 80.5px;
  top: calc(2.15rem + 6.5px);
  bottom: calc(-2.15rem - 6.5px);
  width: 2px;
  background: var(--ink10);
  z-index: 1;
}
.pru-date { text-align: center; }
.pru-date-d {
  display: block;
  font-family: var(--ff-disp);
  font-weight: 900;
  font-size: 2.3rem;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.pru-date-m {
  display: block;
  margin-top: 0.28rem;
  font-family: var(--ff-mono);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink50);
}
.pru-head {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  flex-wrap: wrap;
  margin-bottom: 0.35rem;
}
.pru-code {
  font-family: var(--ff-mono);
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.06em;
}
.pru-step--teoria   .pru-code { color: var(--wood); }
.pru-step--proyecto .pru-code { color: var(--brick); }
.pru-tipo {
  font-family: var(--ff-mono);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink50);
}
.pru-peso {
  margin-left: auto;
  font-family: var(--ff-mono);
  font-size: 0.64rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink50);
}
.pru-title {
  font-family: var(--ff-disp);
  font-weight: 700;
  font-size: 1.3rem;
  line-height: 1.2;
  color: var(--ink);
  margin: 0 0 0.35rem;
}
.pru-desc {
  font-family: var(--ff-disp);
  font-size: 1.04rem;
  line-height: 1.55;
  color: var(--ink);
  margin: 0 0 0.5rem;
}
.pru-fecha {
  font-family: var(--ff-mono);
  font-size: 0.73rem;
  color: var(--ink50);
}
/* Link to the evaluation's pauta (Google Docs) — one per timeline step. */
.pru-link {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin-top: 0.55rem;
  font-family: var(--ff-mono);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--brick);
  text-decoration: none;
}
.pru-link:hover { text-decoration: underline; }
@media (max-width: 560px) {
  .pru-step { grid-template-columns: 1fr; gap: 0.5rem; }
  .pru-step::before,
  .pru-step:not(:last-child)::after { display: none; }
  .pru-date { display: flex; align-items: baseline; gap: 0.5rem; }
  .pru-date-d { font-size: 1.9rem; }
  .pru-date-m { margin-top: 0; }
}
