#view-teleprompter {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  background: #000;
  color: #fff;
}

.tp-progress {
  height: 6px;
  background: #1a1a1a;
  flex-shrink: 0;
}

.tp-progress__bar {
  height: 100%;
  width: 0%;
  background: var(--color-accent);
  transition: width 0.1s linear;
}

.tp-main {
  display: flex;
  flex: 1;
  min-height: 0;
}

/* Viewport + capa fija encima (zonas táctiles, avisos). El viewport scrollea;
   la capa no, por eso las zonas viven en ella y no dentro del viewport. */
.tp-stage {
  position: relative;
  display: flex;
  flex: 1;
  min-width: 0;
  min-height: 0;
}

.tp-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.tp-viewport {
  position: relative;
  flex: 1;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  padding: var(--space-5) var(--space-4);
  line-height: 1.4;
}

.tp-runup,
.tp-rundown {
  pointer-events: none;
}

.tp-text {
  max-width: 900px;
  margin: 0 auto;
}

/* Una línea DURA (las que el autor separó con Enter o con [[br]]) por bloque.
   El aire va como margin-top de la línea SIGUIENTE, nunca como una línea
   vacía: un div sin contenido no genera line box y tendría altura 0.

   El selector `+` es también la garantía de que la PRIMERA línea de un
   segmento nunca lleva margin-top. Si lo llevara, ese margen colapsaría hacia
   afuera de .tp-slide-segment (que no tiene padding ni borde) y corrompería el
   seg.top que mide measureWordPositions. splitHardLines refuerza lo mismo del
   lado del JS: lines[0].breakLevel siempre es 0.

   Sin `white-space`: los saltos son bloques reales, no whitespace preservado,
   así que no hacen falta las sorpresas de pre-wrap. */
.tp-line + .tp-line {
  margin-top: 0.3em;
}

/* Después del anterior a propósito: misma especificidad (0,2,0), gana el que
   viene último. Una línea en blanco en el texto = separación de párrafo. */
.tp-line + .tp-line--para {
  margin-top: 0.8em;
}

.tp-word {
  transition: background-color 0.1s ease, color 0.1s ease, box-shadow 0.1s ease;
  border-radius: 4px;
}

/* Formato inline (**negrita**, *itálica*, ==resaltado==, ~atenuado~). Cuatro
   canales visuales deliberadamente distintos, porque .tp-word.active ya se
   apropió de "fondo + color de texto" para marcar la palabra que se está
   leyendo y el formato tiene que seguir viéndose por debajo de ese pill.

   Ninguna de estas clases puede declarar `font-size`: el box-shadow del pill
   mide su spread en `em` del .tp-word, así que cambiar el em de una palabra
   cambiaría el grosor de su halo.

   El subrayado de ==resaltado== se corta entre palabra y palabra a propósito:
   el nodo de texto separador vive FUERA del .tp-word, así que "==dos
   palabras==" muestra dos subrayados y no uno continuo. Unirlos exigiría spans
   de separador, complicación sin retorno. */
.tp-b {
  font-weight: 700;
}

.tp-i {
  font-style: italic;
}

.tp-mark {
  border-bottom: 0.12em solid var(--color-mark);
}

.tp-dim {
  color: var(--color-text-muted);
}

/* Los sub-spans solo existen cuando el formato cae a mitad de una palabra. */
.tp-fmt {
  transition: color 0.1s ease;
}

.tp-word.active {
  background: var(--color-accent);
  color: #06231f;
  /* box-shadow instead of padding: a visual "pill" without changing the
     word's box size, which would reflow neighboring words / push them to
     a different line every time the highlight moves. */
  box-shadow: 0 0 0 0.08em var(--color-accent);
}

/* Un sub-span atenuado tiene `color` DECLARADO, y un color declarado le gana a
   la herencia sin importar la especificidad del padre — quedaría gris #9aa0a8
   sobre el pill turquesa, ratio ~1.6:1, ilegible. Este selector (0,3,0) es lo
   que lo devuelve al color del pill mientras la palabra está activa.
   (Para las clases puestas en el propio .tp-word no hace falta nada: .tp-word.active
   es (0,2,0) y .tp-dim (0,1,0), así que el pill ya gana.) */
.tp-word.active .tp-fmt {
  color: inherit;
}

/* Subtle line between slides: the talk reads as one continuous text, the
   separator only hints at the slide boundary. Kept small on purpose — a big
   gap here is scroll distance that has to be crossed at the slide change. */
.tp-separator {
  height: 1px;
  margin: 0.6em auto;
  max-width: 200px;
  background: var(--color-border);
}

.tp-tapzone {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 30%;
  pointer-events: auto;
}

.tp-tapzone--prev {
  left: 0;
}

.tp-tapzone--next {
  right: 0;
}

.tp-sidebar {
  flex-shrink: 0;
  width: clamp(120px, 18vw, 220px);
  border-left: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-3);
  padding-right: calc(var(--space-3) + env(safe-area-inset-right, 0px));
  font-variant-numeric: tabular-nums;
}

.tp-sidebar__slide {
  font-size: clamp(1.75rem, 4.5vw, 2.75rem);
  font-weight: 700;
  color: #fff;
}

.tp-sidebar__timer {
  font-size: clamp(1.3rem, 3.5vw, 2rem);
  color: var(--color-accent);
  text-align: center;
  line-height: 1.3;
}

.tp-sidebar__timer-sep {
  display: block;
  color: var(--color-text-muted);
  font-size: 0.7em;
}

@media (max-width: 520px) {
  .tp-main {
    flex-direction: column;
  }

  .tp-sidebar {
    width: auto;
    flex-direction: row;
    border-left: none;
    border-top: 1px solid var(--color-border);
    gap: var(--space-4);
    padding: var(--space-2);
  }

  .tp-sidebar__timer-sep {
    display: inline;
  }
}

.tp-controls {
  display: flex;
  gap: var(--space-2);
  padding: var(--space-3) calc(var(--space-4) + env(safe-area-inset-right, 0px)) calc(var(--space-4) + env(safe-area-inset-bottom, 0px)) calc(var(--space-4) + env(safe-area-inset-left, 0px));
  flex-shrink: 0;
  opacity: 1;
  max-height: 120px;
  overflow: hidden;
  transition: opacity 0.4s ease, max-height 0.4s ease, padding-top 0.4s ease, padding-bottom 0.4s ease;
}

#view-teleprompter.kiosk-hidden .tp-controls {
  opacity: 0;
  pointer-events: none;
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
}

.tp-quick-pause {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + var(--space-3));
  right: calc(env(safe-area-inset-right, 0px) + var(--space-3));
  z-index: 10;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  background: var(--color-bg-elevated);
  color: #fff;
  border: 1px solid var(--color-border);
  opacity: 0.85;
}

.tp-controls button {
  flex: 1;
  padding: var(--space-3);
  font-size: 1.3rem;
  background: var(--color-bg-elevated);
  color: #fff;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.tp-controls #tp-playpause {
  background: var(--color-accent);
  color: #06231f;
  flex: 2;
}

.tp-empty {
  padding: var(--space-5) var(--space-4);
  text-align: center;
}

.tp-empty a {
  color: var(--color-accent);
}

.tp-end {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-2);
  padding: var(--space-4);
}

.tp-end__title {
  font-size: 1.8rem;
  margin: 0;
}

.tp-end__time {
  font-size: 4rem;
  font-weight: 700;
  color: var(--color-accent);
  margin: 0;
  font-variant-numeric: tabular-nums;
}

.tp-end__actions {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

.tp-end__actions button {
  padding: var(--space-3) var(--space-4);
  font-size: 1.1rem;
  background: var(--color-bg-elevated);
  color: #fff;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.tp-end__actions #tp-end-restart {
  background: var(--color-accent);
  color: #06231f;
  border: none;
}

/* Avisos (confirmación de fin, fin de slide en modo libre). Flotan sobre el
   texto, centrados abajo del área de lectura, y no capturan toques. */
.tp-hint {
  position: absolute;
  left: 50%;
  bottom: var(--space-3);
  transform: translateX(-50%);
  padding: var(--space-2) var(--space-3);
  border-radius: 999px;
  background: rgba(20, 23, 28, 0.92);
  border: 1px solid var(--color-border);
  color: var(--color-text);
  font-size: 0.95rem;
  white-space: nowrap;
  pointer-events: none;
  z-index: 3;
}

/* Pantalla de fin: tiempo por slide. */
.tp-end__slides {
  list-style: none;
  margin: var(--space-3) auto;
  padding: 0;
  width: min(100%, 320px);
  max-height: 40vh;
  overflow-y: auto;
  display: grid;
  gap: 4px;
  font-variant-numeric: tabular-nums;
}

.tp-end__slide {
  display: grid;
  grid-template-columns: 2.5em 1fr auto;
  gap: var(--space-2);
  padding: 2px var(--space-2);
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.04);
}

.tp-end__n {
  color: var(--color-text-muted);
  text-align: right;
}

.tp-end__delta {
  color: var(--color-text-muted);
}

.tp-end__delta.is-over {
  color: var(--color-danger);
}

.tp-end__delta.is-under {
  color: var(--color-accent);
}
