/* La configuración es una columna de alto de viewport que NO scrollea: el
   cabezal y la barra de inicio son filas fijas, y el único nodo que scrollea
   es .setup-scroll. Antes era scroll de página con el botón de iniciar en
   position: sticky.

   Esa regla vieja traía un gotcha que ya no aplica y conviene no "restaurar":
   el botón no podía envolverse en un <div>, porque ese wrapper habría pasado a
   ser su bloque contenedor con el alto exacto del botón y nunca se habría
   despegado. Ahora el wrapper .start-bar es obligatorio —lleva el padding y el
   degradado— y no hay nada que despegar.

   El invariante que SÍ sobrevive: la barra de inicio nunca puede terminar
   dentro de .setup-scroll. Hay aserción, que es mejor que este comentario.

   Y sigue vigente la prohibición de transform/filter/contain/will-change en
   cualquier ancestro de una hoja modal, de la franja de edición o del editor a
   pantalla completa: son position:fixed y un bloque contenedor nuevo los
   reanclaría. Tentación concreta: animar el cambio de paso con un transform
   sobre .setup-scroll. */
#view-setup {
  /* LOS ANCHOS DE LAS COLUMNAS LATERALES del escritorio, declarados acá y no
     dentro de la media query que los usa, que es donde estuvieron en la 2.12.0.
     Son custom properties y no literales porque hay CUATRO sitios que tienen
     que coincidir con ellos: la grilla de la vista, la del cabezal (que alinea
     el campo del nombre con la columna del medio), la aserción del test y,
     desde la 2.13.0, el divisor arrastrable.
     Y SE DECLARAN FUERA DE LA MEDIA QUERY por ese cuarto: js/setup-splitter.js
     lee acá el ancho por defecto —con getComputedStyle— cuando el dispositivo
     todavía no tiene preferencia, y monta una sola vez, al construirse la
     vista, sin mirar el ancho de la ventana. Declaradas adentro, esa lectura
     devolvería la cadena vacía en un teléfono y el default habría que
     reescribirlo en js/state.js: el mismo 400 en dos archivos. Lo que sigue
     siendo de escritorio es su USO, que está en la media query del final. */
  --setup-rail-w: 240px;
  --setup-aside-w: 400px;

  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  max-width: 640px;
  margin: 0 auto;
}


/* En teléfono no hay wordmark en la configuración: el cabezal es «‹ nombre de
   la charla ⋯». Sigue en el DOM porque es la izquierda de la barra superior de
   escritorio, y porque lleva el pill de versión que marca la línea v2. */
.app-title {
  display: none;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
}

.app-title__link {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: inherit;
  text-decoration: none;
}

.app-title__icon {
  width: 28px;
  height: 28px;
  border-radius: 6px;
}

.app-title__version {
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--color-edition);
  border: 1px solid var(--color-edition);
  border-radius: 999px;
  padding: 1px 8px;
}

.field-hint {
  font-size: 0.8rem;
  margin: var(--space-1) 0 var(--space-3);
}

/* Los marcadores se citan literales en la ayuda del editor de slides. */
.field-hint code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.95em;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: 3px;
  padding: 0 0.25em;
  white-space: nowrap;
}

.btn {
  font-family: inherit;
  font-size: 1rem;
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-3);
  background: none;
  color: var(--color-text);
  border: 1px solid var(--color-border);
}

.btn--primary {
  width: 100%;
  padding: var(--space-3);
  font-size: 1.1rem;
  font-weight: 600;
  background: var(--color-accent);
  color: #06231f;
  border: none;
  margin-top: var(--space-4);
}

.btn--primary:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.btn--dashed {
  width: 100%;
  border-style: dashed;
}

/* 2.75rem, not the old 2rem: below Apple's 44pt touch target these are
   genuinely hard to hit on the iPad this app is built for. */
.icon-btn {
  background: none;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  color: var(--color-text-muted);
  min-width: 2.75rem;
  min-height: 2.75rem;
  font-size: 1rem;
}

textarea {
  width: 100%;
  background: var(--color-bg-elevated);
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-2);
  font-family: inherit;
  font-size: 1rem;
  resize: vertical;
}

/* ---- Lo que queda de la barra de biblioteca: pegar texto y transferir ----- */

/* El único panel plegable que queda: pegar texto. La biblioteca y la ayuda de
   marcadores se fueron a hojas modales. (`.talk-name-input` también vivía en
   esta sección y se fue con el campo «Nombre» de la hoja del «⋯» en la 2.11.0;
   el campo del renombrado en el sitio es otro —`.talk-card__name-input` y
   `.setup-head__name-input`— porque tiene que medir exactamente igual que el
   rótulo que reemplaza.) */
.paste-panel {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: var(--space-3);
  background: var(--color-bg-elevated);
}

.paste-panel summary {
  cursor: pointer;
  color: var(--color-text);
  font-weight: 600;
}

.paste-panel__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

.paste-panel__actions .btn { flex: 1; }

.transfer-box {
  margin-top: var(--space-3);
}

.transfer-box[hidden] {
  display: none;
}

.transfer-box textarea {
  font-family: ui-monospace, "SF Mono", monospace;
  font-size: 0.85rem;
  margin-bottom: var(--space-2);
}

.transfer-status {
  font-size: 0.9rem;
  margin: var(--space-2) 0 0;
  color: var(--color-accent);
}

.transfer-status:empty {
  margin: 0;
}

.transfer-status--error {
  color: var(--color-danger);
}

/* ---- Slide editor (editor and preview merged into one list) -------------- */

/* Resumen y control maestro en la misma línea: el botón es la contraparte
   global de los disclosures de cada fila. */
.slide-summary-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.btn--ghost {
  flex-shrink: 0;
  padding: var(--space-1) var(--space-2);
  font-size: 0.9rem;
  background: none;
  color: var(--color-accent);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.slide-summary {
  font-size: 0.9rem;
  color: var(--color-text-muted);
  margin-bottom: var(--space-2);
}

.slide-list {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-2);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* ATENCIÓN: ESTE BLOQUE ESTÁ DUPLICADO EN css/slide-editor.css, que es su dueño
   desde que la lista de slides se mudó a su propio módulo. Parece muerto y NO LO
   ESTÁ: setup.css se carga ANTES, así que slide-editor.css gana en todo lo que
   las dos declaran, pero lo que sólo declara ésta sigue aplicando.

   Medido en el navegador borrando sólo estas reglas del CSSOM, sobre la app de
   verdad: `padding` 8px → 0, `background` #14171c → transparente,
   `.slide-row__index` min-width 24px → auto (o sea 22px) y `.slide-row__badge`
   white-space nowrap → normal. Cuatro regresiones visibles y NINGÚN test en
   rojo, que es por qué esto no se barrió en la 2.11.0 junto con las reglas
   realmente huérfanas de al lado.

   Unificarlas es una tarea propia: hay que decidir en qué hoja viven —la lista
   de slides es del editor, así que slide-editor.css— y mudar esas cuatro
   propiedades con una aserción por cada una. Hasta entonces, las dos hojas
   describen la misma fila y el orden de los <link> es load-bearing. */
.slide-row {
  padding: var(--space-2);
  border-radius: var(--radius);
  background: var(--color-bg-elevated);
  border-left: 4px solid var(--color-border);
}

.slide-row--comfortable {
  border-left-color: var(--color-slide-ok);
}

.slide-row--tight {
  border-left-color: var(--color-slide-tight);
}

.slide-row--too-long {
  border-left-color: var(--color-danger);
}

.slide-row--empty {
  opacity: 0.7;
}

/* Independent of the timing-status colors above (border-left-color) — a
   slide can be "comfortable" in duration and still fall outside the
   Pechakucha 20-slide format by position. `outline` doesn't share a box
   model with `border`, so both can be visible on the same row at once. */
.slide-row--over-limit {
  outline: 2px solid var(--color-slide-over);
  outline-offset: -2px;
}

/* Acá vivían .slide-row__toggle, .slide-row__preview y .slide-row__head, de
   cuando la fila era un disclosure con cabecera y vista previa plegada. La
   edición se fue a su propia pantalla en la 2.7.0 y la fila pasó a ser un
   <button> de una línea: ningún elemento lleva esas clases desde entonces, así
   que se retiran en la 2.11.0. Es la diferencia con el bloque de arriba —aquél
   PARECE muerto y aplica; éstos no matchean nada— y por eso se barren éstos y
   aquél se anota. */
.slide-row__index {
  color: var(--color-text-muted);
  min-width: 1.5rem;
  font-variant-numeric: tabular-nums;
}

/* .slide-row__words se fue con la cabecera de la fila: el recuento de palabras
   vive hoy en el badge. */
.slide-row__badge {
  font-size: 0.8rem;
  color: var(--color-text-muted);
  white-space: nowrap;
}

.font-preview-wrap {
  background: #000;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-3);
  margin-bottom: var(--space-4);
  overflow-x: auto;
}

/* Sin `white-space: nowrap`: que envuelva como envuelve de verdad en el
   teleprompter, en vez de scrollear en horizontal. Con la misma line-height. */
.font-preview {
  margin: 0;
  color: #fff;
  line-height: 1.4;
}

/* .voice-enable-row se retiró en la 2.11.0: era la fila del checkbox de voz de
   antes del rediseño, y hoy eso es .switch-row, en #ajustes. */

.voice-row {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.voice-row select {
  /* min-width: 0 no es opcional. El ancho mínimo intrínseco de un <select> es
     el de su opción más larga —un nombre de voz como «Google UK English Male»
     pasa los 300px— y el default de un ítem flex es min-width: auto, que
     respeta ese mínimo y empuja al botón «Probar» fuera de la pantalla. A
     402px la página scrolleaba de costado; se veía solo a ancho de teléfono,
     y hasta la 2.7.0 los tests corrían a 1280. */
  flex: 1;
  min-width: 0;
  background: var(--color-bg-elevated);
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-2);
  font-family: inherit;
}

/* El de idioma no crece: toma el ancho de su opción más larga y el de voz se
   queda con el resto, que es donde el nombre largo hace falta. min-width: 0
   igual que su hermano, para que pueda encogerse en vez de empujar. */
.voice-row #voice-lang-select {
  flex: 0 1 auto;
}
.voice-row .btn {
  white-space: nowrap;
}

.voice-row .btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Toast de "nueva versión disponible" (ver renderUpdateToast en ui-setup.js). */
/* Una fila más de la columna, justo encima de la barra de inicio. Antes era
   position:fixed con un `bottom` calculado a partir de --setup-footer-h, que
   era un espejo a mano del alto real del botón: cambiarle el padding al botón
   y olvidarse de la variable dejaba el aviso debajo del pie. Ahora el orden
   del DOM lo resuelve y la variable se retiró. */
.update-toast {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: 0 var(--space-3) var(--space-2);
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-edition);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  font-size: 0.9rem;
}


/* Modo libre: la fila no tiene estado cómoda/ajustada, solo la estimación. */
.slide-row--free {
  border-left-color: var(--color-text-muted);
}

/* `.help-panel #slide-help` se retiró en la 2.11.0: el <details class="help-panel">
   con la ayuda adentro dejó de existir en la 2.7.0, cuando la referencia de
   marcadores pasó a ser una hoja con una fila que la abre. */

/* Encabezado de sección plegable. El <h2> sigue siendo el encabezado real
   (importa para la navegación por landmarks); el botón vive adentro. */
/* Fila que abre la hoja de marcadores. Reemplaza al <details class="help-panel">
   cerrado, donde la referencia de sintaxis no la encontraba nadie. Las tres
   muestras adelantan de qué se trata sin abrir nada, y son los colores
   vigentes: leen las mismas custom properties que escribe fmt-colors.js. */
.markers-row-open {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  margin-bottom: var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-row);
  background: var(--color-bg-elevated);
  color: inherit;
  font: inherit;
  text-align: left;
}

.markers-row-open:hover { border-color: var(--color-accent); }

.markers-row-open__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.markers-row-open__title {
  font-size: var(--fs-body);
  font-weight: 600;
}

.markers-row-open__sub {
  font-size: var(--fs-hint);
}

.markers-row-open__swatches {
  flex: none;
  display: flex;
  gap: var(--space-1);
}

.markers-row-open__dot {
  width: 16px;
  height: 16px;
  border-radius: 5px;
}

.markers-row-open__dot--mark { background: var(--color-fmt-mark); }
.markers-row-open__dot--dim { background: var(--color-fmt-dim); }
.markers-row-open__dot--stress { background: var(--color-fmt-stress); }

.markers-row-open__chevron {
  flex: none;
  color: var(--color-text-muted);
}

/* ---- Cabezal, cuerpo y barra de inicio ------------------------------------ */

.setup-head {
  flex: none;
  /* La franja de edición son 4px fijos bajo el safe-area; el cabezal empieza
     debajo de las dos cosas. En landscape los insets laterales también
     cuentan, o el botón «‹» queda bajo el notch. */
  padding: calc(env(safe-area-inset-top, 0px) + 4px + var(--space-3))
           calc(var(--space-3) + env(safe-area-inset-right, 0px))
           0
           calc(var(--space-3) + env(safe-area-inset-left, 0px));
}

.setup-head__row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2.75rem;
}

/* Agrupa el ⚙ y el ⋯. Con el mismo gap que la fila y `flex: none`, en teléfono
   es indistinguible de tenerlos sueltos; existe para que en escritorio haya UN
   solo elemento que mandar a la tercera columna. */
.setup-head__tools {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* El conmutador ES/EN se MONTA a los dos anchos y acá se esconde: en teléfono el
   cabezal ya lleva «‹ Charlas», el nombre, el ⚙ y el ⋯ en 402px, y un quinto
   control obliga a que alguno pierda su etiqueta. Esconderlo con CSS y no montar
   según el ancho deja un solo camino de montaje — si dependiera del breakpoint,
   rotar el teléfono lo dejaría sin existir, porque ui-lang-toggle.js no escucha
   el cambio de ancho. En #talks y en la bienvenida sigue estando a todo ancho. */
.setup-head .lang-toggle { display: none; }

/* Es un <a href="#talks">, no un <button>: volver a la biblioteca es una
   navegación de verdad, así que tiene que poder abrirse en otra pestaña y
   funcionar aunque el JS todavía no haya montado.

   Lleva la palabra «Charlas» y no sólo el «‹»: como icono suelto era un glifo
   fino en --color-text-muted dentro de un cuadrado sin relleno, al lado del
   nombre de la charla en 16px/600 — se perdía. Con la etiqueta gana ancho de
   blanco tocable y dice a dónde va, que es la mitad que le faltaba. */
.setup-head__back {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  min-height: 2.75rem;
  padding: 0 var(--space-3) 0 var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, 0.04);
  color: var(--color-text);
  font-size: var(--fs-row);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

/* COLUMNA FLEX y no un bloque, desde que el nombre es un <button>: un botón es
   inline-block, así que se encogería al ancho de su TEXTO y la tríada del
   recorte de abajo no recortaría nada — un nombre largo empujaría al ⚙ y al «⋯»
   fuera de la pantalla, que es justo lo que esa tríada existe para impedir.
   Medido a 402 px sobre el marcado que ui-setup.js produce: 173 px de botón con
   la columna; 213 con un nombre corto sin ella y 1886 con uno de 200
   caracteres.
   Quien estira a los dos hijos al ancho del contenedor son estas DOS
   declaraciones y nada más: el `align-items` por defecto ya es un estiramiento
   (`normal` se comporta como `stretch` en flex), así que declararlo no cambiaba
   ningún píxel — medido: 173 px con y sin. Es el mismo mecanismo que en la
   tarjeta de #talks, donde sale gratis porque la tarjeta YA es una columna flex.
   El min-width:0 es lo que deja que la columna ceda ancho de verdad dentro de
   la fila; sin él, el ancho mínimo intrínseco del contenido la vuelve a inflar. */
.setup-head__talk {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.setup-head__name {
  /* Los resets del <button>: el agente de usuario le pone fondo gris, texto
     negro y centrado, que sobre el cabezal oscuro deja el nombre ilegible. Que
     sea un control no puede notarse — el cabezal se lee como el título de la
     charla, no como un botón—. Son los mismos TRES que .talk-card__name, y son
     tres y no cuatro: la tipografía no hace falta declararla acá ni allá,
     porque css/main.css ya trae un `button { font-family: inherit }` global.
     Medido: quitando un `font-family: inherit` de esta regla, el font-family
     computado del botón no se mueve. */
  background: none;
  color: inherit;
  text-align: left;
  font-size: var(--fs-name);
  font-weight: 600;
  /* Un nombre largo se acorta: lo que no puede es empujar al «⋯» fuera de la
     pantalla. Misma razón que el min-width:0 del <select> de voz. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* CAJA COMPARTIDA entre el rótulo y el campo, segunda de las dos instancias. El
   porqué —por qué la caja del campo tiene que ser la del rótulo, y por qué eso
   no es cosmética— está escrito UNA sola vez, en js/rename-inline.js, que es el
   módulo que hace el reemplazo; la gemela es `.talks--cards .talk-card__name,
   .talk-card__name-input` en css/screens.css.
   POR QUÉ DOS BLOQUES Y NO UNO: el invariante es que DENTRO de una pantalla el
   rótulo y el campo midan igual, no que las dos pantallas midan igual entre sí.
   Hasta la 2.13.0 la tarjeta y el cabezal medían casi lo mismo por coincidencia
   —17px y 16px— y acá se avisaba de que una regla común los ataría a medir
   siempre igual. La 2.14.0 lo COMPROBÓ: se pidió el nombre del cabezal «un poco
   más grande» y sólo el del cabezal, así que hoy son --fs-title (17px) en la
   tarjeta y --fs-name (19px) acá. Con un bloque común, agrandar el cabezal
   habría agrandado la tarjeta sin que nadie lo pidiera.
   Lo que sí se duplicaba era el ARGUMENTO, y eso es lo que se unificó: acá queda
   sólo lo que es de esta pantalla.
   DE ESTA PANTALLA: el padding es sólo vertical porque uno lateral indentaría el
   nombre respecto del formato de abajo, que empieza en el borde. Y lo que se ve
   saltar debajo del dedo es esa línea del formato — la fila del cabezal está
   clavada en 44px por «‹ Charlas» y los dos botones de icono, así que absorbe
   sola cualquier diferencia de alto.
   MEDIDO a 402px sobre el marcado que ui-setup.js produce: 28px de botón con
   esta regla, 24 sin ella. No 18: los resets de arriba pisan background, color,
   text-align y font-size, así que el <button> CONSERVA el padding y el borde del
   agente de usuario y nunca cae al alto de su contenido pelado. O sea que el
   24×24 de WCAG 2.2 SC 2.5.8 lo cumple con esta regla y sin ella, y la aserción
   de altura de tests/ui-setup.test.html es un piso absoluto, no la defensa de
   este bloque: lo que defiende este bloque son las tres comparaciones
   botón↔campo de ahí mismo. */
.setup-head__name,
.setup-head__name-input {
  padding: var(--space-1) 0;
  border: 1px solid transparent;
  border-radius: var(--radius-xs);
}

/* Sobre un <input> la tríada del recorte NO vale y no tiene que valer:
   text-overflow no pone puntos suspensivos en un campo con foco, y no debería
   —hay que poder ver lo que se escribe—. El invariante que sí vale mientras se
   edita es que LA CAJA NO CREZCA: 200 caracteres tienen que desbordar el campo
   en lugar de ensanchar el cabezal y empujar al ⚙ y al «⋯» fuera de la
   pantalla. Eso lo hace el stretch de la columna contra el box-sizing:
   border-box global de main.css; el min-width:0 es lo que impide que el ancho
   mínimo intrínseco del <input> (su atributo `size`) gane igual. */
.setup-head__name-input {
  min-width: 0;
  border-color: var(--color-accent);
  background: var(--color-bg);
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--fs-name);
  font-weight: 600;
}

/* El formato del cabezal: dos controles en una línea (js/ui-setup.js).
   Un <select> nativo y no una lista dibujada acá: son cuatro opciones, y el
   control del sistema ya trae su apertura, su teclado y su anuncio.

   SIN el `min-width: 0` que sí lleva el <select> de la fila de voz, y no por
   olvido: allá las opciones son los nombres de voz del sistema, cadenas de
   largo desconocido cuyo ancho mínimo intrínseco empujaba al botón de al lado
   fuera de la pantalla. Acá son cuatro rótulos fijos y cortos —el más largo es
   «Personalizado», y su traducción al inglés es más corta—, y que la línea
   entre a 402 px lo mide tests/ui-setup.test.html. */
.setup-head__format {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--fs-hint);
  font-variant-numeric: tabular-nums;
}

/* Los dos, desvestidos hasta parecer el texto que eran antes: esto es un
   cabezal, no una barra de herramientas, y el nombre de la charla tiene que
   seguir siendo lo primero que se lee. Se distinguen al tocarlos, no al
   mirarlos.

   `font: inherit` y no las tres longhands sueltas, que es lo que parece
   equivalente y no lo es: el agente de usuario le pone a los controles su
   propia fuente, y con ella se lleva puesto el `font-variant-numeric` de la
   regla de arriba. MEDIDO en Chromium sobre este mismo marcado: con
   `font: inherit` los dos computan `tabular-nums`; heredando font-family,
   font-size y font-weight una por una, los dos computan `normal` — y ahí los
   números dejan de ser de ancho fijo y el cabezal se mueve al pasar de
   20 × 20 s a 20 × 15 s. */
.setup-head__preset,
.setup-head__nums {
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  /* El subrayado punteado es la única marca de que se pueden tocar. Un borde
     completo alrededor de dos controles de 11,5px llena el cabezal de cajas. */
  text-decoration: underline dotted;
  text-underline-offset: 2px;
}

/* El <select> nativo se dibuja con flecha propia y con blanco propio a los
   lados: MEDIDO en Chromium, 20px de ancho de más sobre el mismo contenido y
   el mismo padding. appearance:none se los saca, y en su lugar NO se dibuja
   ninguna flecha, a propósito: así la única marca que queda es el subrayado
   punteado de arriba, que es la misma que lleva el botón de al lado. Los dos
   abren algo, así que tienen que parecer lo mismo. */
.setup-head__preset {
  appearance: none;
  -webkit-appearance: none;
}

.setup-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--space-1)
           calc(var(--space-3) + env(safe-area-inset-right, 0px))
           var(--space-4)
           calc(var(--space-3) + env(safe-area-inset-left, 0px));
}

/* El cuerpo de la pantalla. Era `.step-pane`, el panel del paso «Texto», y
   hereda sus dos separaciones porque son las mismas y NINGUNA aserción las
   medía antes de la 2.11.0 — así que perderlas al demoler el riel habría dejado
   las tarjetas pegadas una a otra y la primera tocando el cabezal, sin un solo
   test en rojo. Ahora hay dos, en tests/ui-setup.test.html.

   · El `gap` es el de `.step-pane`, tal cual.
   · El `margin-top` reemplaza al `margin: var(--space-3) 0 var(--space-2)` del
     `.step-rail`, que era lo único que separaba el contenido del cabezal: el
     riel se llevaba ese aire consigo al desaparecer, y el padding de
     `.setup-scroll` es de 4px, que no alcanza. No son los 24px de la suma de
     aquellos dos márgenes sino 16px, porque no hay una barra de botones en el
     medio de la que despegarse: es el aire de un cabezal a su contenido. */
.setup-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.start-bar {
  flex: none;
  padding: var(--space-2)
           calc(var(--space-3) + env(safe-area-inset-right, 0px))
           calc(var(--space-3) + env(safe-area-inset-bottom, 0px))
           calc(var(--space-3) + env(safe-area-inset-left, 0px));
  /* Decorativo: la barra no se superpone al área scrolleable, así que el
     degradado se funde con el fondo de la página y no se ve. Está para que, si
     algún día la barra flota sobre el contenido, el corte no sea seco. */
  background: linear-gradient(to top, var(--color-bg) 70%, transparent);
}

/* Dice SIEMPRE qué se va a correr: la acción a la izquierda, qué implica a la
   derecha. Vive fuera de .setup-scroll, así que se ve entera sin importar dónde
   esté el scroll — que es lo que la hace el sitio del recuento. El argumento
   anterior («es lo único que no cambia al cambiar de paso») se fue con el riel
   en la 2.11.0: con un solo paso no distinguía nada. */
.start-btn {
  width: 100%;
  min-height: 3.375rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: 0 var(--space-3);
  border: none;
  border-radius: var(--radius-btn);
  background: var(--color-accent);
  color: #06231f;
  font: inherit;
}

.start-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.start-btn__label {
  font-size: 1.0625rem;
  font-weight: 700;
}

.start-btn__meta {
  font-size: var(--fs-row);
  font-weight: 600;
  opacity: 0.75;
  font-variant-numeric: tabular-nums;
}

/* ---- Vocabulario de controles ---------------------------------------------
   ESTE VOCABULARIO YA NO LO DIBUJA ESTA PANTALLA. Es una afirmación de
   PERTENENCIA y no de posición: no dice «de acá para abajo» —debajo siguen la
   sección de Importar / Exportar y el @media de escritorio, que son de acá— ni
   «todo está acá» —.field-hint, .btn, .btn--ghost, .font-preview y .voice-row
   viven más arriba en este mismo archivo—. Dice quién las usa.

   .card, .step-label, .slider-row, .font-picker, .font-pick, .font-preview,
   .switch-row, .switch, .voice-row, .btn y .field-hint las dibuja
   js/ui-ajustes.js, que se llevó los pasos 1 y 2. Lo único que las sigue usando
   desde esta pantalla es la tarjeta de transferencia (.card + .step-label) y el
   atajo de teclado del pie (.field-hint). `.font-preview` era además de la
   columna derecha, y dejó de serlo en la 2.11.0: esa columna ya no tiene vista
   previa propia —es el hueco de #ajustes, que trae la suya al tamaño real—. La
   lista completa y el porqué están en la cabecera de css/ajustes.css.

   El riel se demolió y se llevó .step-rail, .step, .step__label, .step__name y
   .step-pane —y el @media de 380px que hacía entrar «Letra y voz» en un tercio
   de pantalla, que sin tercios no describe nada—. Estas reglas se quedaron, y
   el mutante `ajustes-sin-tarjetas` de scripts/recuento.sh existe para eso: si
   alguien las borra creyendo que también eran de los pasos, tests/ajustes.test.html
   se pone en rojo en vez de medir una pantalla sin estilo. */

.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-bg-elevated);
}

.step-label {
  margin: 0;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: var(--ls-label, 0.8px);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* ---- Importar / Exportar -------------------------------------------------- */

/* La tarjeta de la pantalla del texto —era «el paso «Texto»» hasta que la
   2.11.0 demolió el riel—. Sus dos botones NO son .btn--ghost como el resto:
   llevan borde de acento y 46px de alto porque son la única forma de mover una
   charla entre dispositivos, y hasta la 2.7.0 estaban a dos toques de
   profundidad dentro de la hoja del «⋯» —«los botones de importar/exportar
   quedan ocultos»—. El resto de la transferencia (exportar todo, pegar texto)
   sigue en la hoja, detrás de «Más…»: es lo que se usa una vez cada tanto. */
.transfer-card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.transfer-card__more {
  flex: none;
  padding: 0;
  border: none;
  background: none;
  color: var(--color-accent);
  font: inherit;
  font-size: var(--fs-meta);
}

.transfer-card__actions {
  display: flex;
  gap: var(--space-2);
}

.transfer-card__btn {
  flex: 1;
  min-width: 0;
  min-height: 46px;
  border: 1px solid var(--color-accent);
  border-radius: 11px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--color-text);
  font: inherit;
  font-size: var(--fs-body);
  font-weight: 600;
}

/* El .field-hint de siempre trae un margin-bottom de --space-3 pensado para un
   flujo de párrafos; acá el gap de .card ya separa, y el margen dejaba la
   tarjeta con un colchón vacío abajo. */
.transfer-card__note {
  margin-bottom: 0;
}

/* ---- Formato -------------------------------------------------------------- */

/* Cuatro tarjetas en vez de un <select>: el formato decide cuánto dura todo, y
   un desplegable lo esconde detrás de un toque y no deja comparar. Cada una
   dice sus números, así que elegir no exige abrir nada.

   Donde el argumento no aplica es en el cabezal de la pantalla del texto, que
   desde la 2.15.0 sí ofrece un <select> (.setup-head__format, más arriba): ahí
   hay UNA charla, la abierta, así que no hay con qué compararla y esconder la
   lista no cuesta nada. */
.format-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
}

.format-card {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 2.75rem;
  padding: 13px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-row);
  background: var(--color-bg-elevated);
  color: var(--color-text-muted);
  font: inherit;
  text-align: left;
}

.format-card[aria-pressed="true"] {
  border-color: var(--color-accent);
  background: rgba(255, 255, 255, 0.05);
  color: var(--color-text);
}

.format-card__title {
  font-size: var(--fs-body);
  font-weight: 600;
}

.format-card__line {
  font-size: var(--fs-meta);
  opacity: 0.7;
  font-variant-numeric: tabular-nums;
}

/* La fila de «N × M s» y su total. Su único consumidor VIVO EN LA APP es la
   hoja de js/ui-format-sheet.js, que edita esos dos números desde la tarjeta de
   una charla; la grilla de js/ui-format.js —el paso «Formato» del riel, que la
   2.11.0 demolió— las sigue usando pero sólo se monta en su página de test.

   Por eso los selectores están SUELTOS y no acotados a #view-setup, y ahora el
   argumento es más fuerte que antes y no más débil: la hoja vive en
   #layer-root, o sea FUERA de esta vista, así que acotarlos la dejaría con los
   campos del agente de usuario y sin un solo test en rojo. Que las reglas vivan
   en esta sección es historia, no pertenencia. El gemelo de este párrafo está
   en js/ui-format-sheet.js, junto al marcado que las consume. */
.format-custom {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.format-custom input[type="number"] {
  min-width: 58px;
  width: 4.5rem;
  padding: var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: rgba(0, 0, 0, 0.35);
  color: var(--color-text);
  font: inherit;
  font-variant-numeric: tabular-nums;
}

.format-total {
  margin-left: auto;
  color: var(--color-accent);
  font-size: var(--fs-meta);
  font-variant-numeric: tabular-nums;
}

/* ---- Sliders -------------------------------------------------------------- */

.slider-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.slider-row__label {
  font-size: var(--fs-body);
}

.slider-row__value {
  flex: none;
  color: var(--color-accent);
  font-size: var(--fs-row);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

input[type="range"] {
  width: 100%;
  accent-color: var(--color-accent);
}

/* ---- Tipografía ----------------------------------------------------------- */

.font-picker {
  display: flex;
  gap: var(--space-2);
}

/* Cada botón se dibuja EN SU PROPIA fuente (el style inline lo pone el JS):
   es la forma más corta de elegir una tipografía sin probarlas una por una. */
.font-pick {
  flex: 1;
  min-height: 2.75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-bg-elevated);
  color: var(--color-text-muted);
  font-size: var(--fs-body);
}

.font-pick[aria-pressed="true"] {
  border-color: var(--color-accent);
  color: var(--color-text);
  background: rgba(255, 255, 255, 0.05);
}

/* ---- Interruptor de voz --------------------------------------------------- */

.switch-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.switch-row__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.switch-row__title { font-size: var(--fs-body); font-weight: 600; }
.switch-row__sub { font-size: var(--fs-hint); line-height: 1.35; }

.switch { flex: none; position: relative; display: inline-flex; }

/* El checkbox real sigue existiendo y sigue siendo el que se toca: se lo tapa
   con la pista pero NO se lo saca del árbol, así que el teclado, el lector de
   pantalla y el <label> siguen funcionando sin una sola línea de JS. */
.switch input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  z-index: 1;
}

.switch__track {
  width: 52px;
  height: 31px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  padding: 2px;
  transition: background 0.15s ease;
}

.switch__knob {
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background: var(--color-text-muted);
  transition: transform 0.15s ease, background 0.15s ease;
}

.switch input:checked + .switch__track { background: var(--color-accent); border-color: var(--color-accent); }
.switch input:checked + .switch__track .switch__knob { transform: translateX(21px); background: #06231f; }
.switch input:focus-visible + .switch__track { outline: 2px solid var(--color-accent); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  .switch__track, .switch__knob { transition: none; }
}

/* ---- Escritorio ----------------------------------------------------------
   El breakpoint es 1024px, el mismo que declara js/responsive.js. Si alguien
   mueve uno, tiene que mover el otro: con dos media queries sueltas basta
   tocar una para que el DOM y el layout discrepen en una franja de anchos. */

/* Las cuatro cosas que sólo existen a partir de 1024px. `.setup-aside` se llamó
   `.preview-col` hasta la 2.11.0, cuando dejó de alojar una vista previa: hoy es
   el hueco donde aterriza el nodo de #ajustes, y el nombre dice el ÁREA de la
   grilla (aside) en vez de un contenido que ya no tiene.
   `.setup-splitter` es la cuarta, y se esconde por CSS y no desmontando el
   módulo: vive DENTRO de #view-setup y no se oculta por su cuenta, que es la
   condición exacta con la que js/responsive.js separa los dos caminos. Con
   `display: none` no recibe punteros ni parada de tabulación, así que sus
   listeners quedan inertes solos —lo mismo que ya hace el panel de marcadores,
   y el contraejemplo de la mudanza de #ajustes, que sí necesita JS. */
.talks-rail,
.setup-keys,
.setup-aside,
.setup-splitter { display: none; }

.setup-main {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.setup-foot { flex: none; }

@media (min-width: 1024px) {
  /* Mismo DOM, otra disposición: las tres columnas salen de las áreas, no de
     mover un solo nodo con JS. La barra de inicio aterriza abajo a la derecha
     porque el área la manda ahí, sin tocar su marcado. */
  #view-setup {
    /* --setup-rail-w y --setup-aside-w se declaran ARRIBA, fuera de esta media
       query, y ahí está el porqué. Acá sólo se usan: el divisor arrastrable
       pisa la segunda con un `style` en línea sobre este mismo elemento
       (js/setup-splitter.js), así que la grilla sigue el arrastre sin que nadie
       toque grid-template-columns. */
    display: grid;
    max-width: none;
    grid-template-columns: var(--setup-rail-w) minmax(0, 1fr) var(--setup-aside-w);
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "head head  head"
      "rail main  aside"
      "rail main  start";
    gap: 0 var(--space-4);
    padding-inline: var(--space-3);
  }

  .setup-head { grid-area: head; padding-inline: 0; }
  .talks-rail { grid-area: rail; display: flex; flex-direction: column; min-height: 0; overflow-y: auto; }
  .setup-main { grid-area: main; }
  /* El hueco de #ajustes. Sin padding ni gap propios: el aire de esa pantalla
     vive en `.ajustes` —el nodo— justamente para que se mude con él
     (css/ajustes.css). Lo único que pone esta hoja es que la columna scrollee
     sola: son cuatro tarjetas y no entran en el alto del viewport. */
  .setup-aside { grid-area: aside; display: block; min-height: 0; overflow-y: auto; scrollbar-gutter: stable; }
  .setup-foot { grid-area: start; }

  /* ---- El divisor arrastrable (2.13.0) ----------------------------------
     NO ES UNA COLUMNA DE LA GRILLA, y ésa es toda la decisión: vive dentro del
     `gap` que ya separaba el texto de los ajustes, como ítem de la columna 3
     corrido hacia la izquierda su ancho entero. Una columna propia habría
     obligado a rehacer grid-template-columns Y las tres áreas —layout nuevo, en
     las dos grillas, porque el cabezal copia las columnas de ésta— para dibujar
     una línea que ya estaba ahí. Del gap sale además el ancho de la zona de
     agarre sin elegir un número: `var(--space-4)` son 24px, muy por encima de
     los 8 que pide un tirador.

     CRUZA LAS DOS FILAS DE ABAJO (`2 / -1`: la de los ajustes y la de la barra
     de inicio) porque el borde que mueve es el de las dos. Parar en la primera
     dejaría media frontera con el cursor de texto y sin agarre, justo la clase
     de zona muerta que la franja de la tarjeta de charla vino a sacar en la
     2.12.0.

     Y NADA DE `transform`: la prohibición de la cabecera de esta hoja vale
     también para el arrastre. Lo que se mueve es el ancho de la columna
     —`--setup-aside-w`, que js/setup-splitter.js escribe en línea sobre
     #view-setup—, nunca el grid ni este nodo. Un transform acá reanclaría las
     hojas modales, la franja de edición y el editor a pantalla completa. */
  .setup-splitter {
    display: block;
    grid-column: 3;
    grid-row: 2 / -1;
    justify-self: start;
    width: var(--space-4);
    margin-inline-start: calc(-1 * var(--space-4));
    position: relative;
    cursor: col-resize;
    /* Sin esto el navegador se queda el gesto para desplazar y el pointermove
       deja de llegar en cuanto el puntero es un dedo o un trackpad con inercia. */
    touch-action: none;
  }
  /* La línea se dibuja con un pseudo-elemento y no con un `border` del nodo:
     el nodo mide 24px porque es la zona de agarre, y lo que se ve tiene que ser
     1px en el medio de esos 24. */
  .setup-splitter::before {
    content: "";
    position: absolute;
    inset-block: 0;
    left: calc(50% - 0.5px);
    width: 1px;
    background: var(--color-border);
  }
  /* El realce al apuntar, al enfocar y mientras se arrastra es el MISMO, y sale
     del idioma que ya usa el repo para una superficie un punto más clara: el
     overlay blanco con alfa (el chip de formato pulsado, la pista de la barra).
     Un token de color nuevo para tres estados de una línea de 1px sería un
     nombre más en la paleta para algo que no se reusa. */
  .setup-splitter:hover::before,
  .setup-splitter:focus-visible::before,
  #view-setup.is-splitting .setup-splitter::before {
    width: 2px;
    left: calc(50% - 1px);
    background: rgba(255, 255, 255, 0.24);
  }
  /* El anillo de foco es el de la app (.switch, más arriba), no un `outline:
     none` compensado con la línea: la línea también se enciende al apuntar con
     el ratón, así que sola no distingue «enfocado» de «encima». */
  .setup-splitter:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }
  /* Mientras se arrastra, el puntero cruza el texto de las dos columnas: sin
     esto el gesto selecciona media charla de paso. Va en la vista y no en el
     <body> porque es esta pantalla la que está partiéndose. */
  #view-setup.is-splitting { user-select: none; }
  /* El aire del final NO es decorativo: es el hueco entre la última palabra de
     una línea y la barra de scroll de esta misma columna, que en escritorio está
     siempre a la vista. Sin él el texto termina tocándola. El del principio sí
     sobra —lo pone `padding-inline` de la grilla—, y por eso son distintos.
     `scrollbar-gutter: stable` reserva ese carril aunque la barra no esté, para
     que aparecer y desaparecer no le cambie el ancho al texto. */
  .setup-scroll { padding-inline: 0 var(--space-3); scrollbar-gutter: stable; }
  .start-bar { padding-inline: 0; }

  /* En escritorio el cabezal es una barra: wordmark a la izquierda, charla al
     medio. El «‹» sobra —el riel de charlas está siempre a la vista— y el
     nombre deja de necesitar su propia fila. */
  /* LA MISMA GRILLA QUE #view-setup, y por eso lee las mismas propiedades. El
     cabezal sigue cruzando las tres columnas como área de la grilla de afuera,
     pero por dentro se alinea con ellas: el wordmark sobre el riel, el nombre de
     la charla sobre las slides y el ⚙/⋯ sobre los ajustes.

     Lo que esto arregla es el ancho del campo del nombre. Como fila flex, el
     nombre era `flex: 1` y se comía TODO el sobrante hasta el ⋯ — o sea el ancho
     de la ventana entera menos el wordmark: un campo de texto de más de 900 px
     para un nombre de charla. Ahora mide exactamente la columna del medio.

     Que el ancho salga de la custom property y no de un número repetido es lo
     que impide que las dos grillas se desalineen cuando una cambie. El `gap`
     también tiene que ser el mismo, por la misma razón. */
  .setup-head {
    display: grid;
    grid-template-columns: var(--setup-rail-w) minmax(0, 1fr) var(--setup-aside-w);
    grid-auto-rows: minmax(2.75rem, auto);
    align-items: center;
    gap: 0 var(--space-4);
    padding-block: var(--space-2);
    border-bottom: 1px solid var(--color-border);
  }
  /* El <h1> por defecto es 2em: en una barra superior de 48px de alto eso es
     un titular, no una marca. */
  .setup-head .app-title { display: flex; font-size: var(--fs-title); }
  /* La fila deja de ser una caja: sus hijos pasan a ser ítems de la grilla de
     arriba y se reparten las columnas 2 y 3 por sí mismos. `display: contents`
     y no un re-marcado en JS porque el DOM del cabezal es UNO solo para los dos
     anchos — el mismo criterio con el que #ajustes se muda de nodo en vez de
     duplicarse. Sólo corre a partir de 1024px, así que el soporte irregular de
     `display: contents` en iOS 15.0-15.3 no lo alcanza.
     Los que están en `display: none` acá (el «‹ Charlas» y el ⚙) NO cuentan como
     ítems, así que no ocupan columna: quedan tres hijos visibles para tres
     columnas, en el orden del marcado. */
  .setup-head__row { display: contents; }
  .setup-head__tools { justify-self: end; }
  .setup-head__back { display: none; }
  /* Acá sí hay sitio: el «‹ Charlas» y el ⚙ están ocultos, así que la tercera
     columna tiene 400px para el ⋯ y el idioma. */
  .setup-head .lang-toggle { display: flex; }

  /* Y EL ⚙ TAMBIÉN, que es la puerta a #ajustes: en escritorio esa pantalla es
     la columna de al lado, así que abrir lo que ya está abierto es el sobrante
     clásico de una mudanza. Con CSS y no con JS —vive dentro de #view-setup y no
     se oculta por su cuenta, que es la condición que hace transferible el
     precedente del panel de marcadores—; lo que sí es JS es la redirección de la
     ruta #ajustes, porque un hash tipeado a mano mostraría una .view vacía
     (desktopRedirect en js/router.js).
     Acotado a la fila del cabezal y no suelto: `[data-action]` es un atributo de
     toda la app y el ⋯ es su vecino inmediato. */
  .setup-head__row [data-action="open-ajustes"] { display: none; }

  /* El «‹ Texto» del nodo huésped: acá no hay a dónde volver, porque el texto
     está a la izquierda y siempre a la vista. La regla es de esta hoja y no de
     css/ajustes.css a propósito —es lo que ESTA pantalla le hace a su huésped, y
     el módulo de ajustes no sabe ni tiene por qué saber si lo montaron en una
     ruta o en una columna—. Su gemelo de arriba, `.setup-head__back`, se esconde
     por lo mismo: el riel de charlas está siempre a la vista. */
  #setup-ajustes-slot .ajustes__back { display: none; }

  /* El atajo de teclado, al pie: sólo tiene sentido donde hay teclado. */
  .setup-keys { display: block; margin-bottom: var(--space-2); }

  /* Y la fila que abría la hoja no tiene nada que abrir. */
  .markers-row-open { display: none; }

  /* Acá vivía `.summary-card`, el <dl> read-only de la columna derecha: cinco
     filas repitiendo en texto el formato, el margen, el ritmo, la letra y la
     voz. Se retiró con la columna en la 2.11.0 —ningún elemento lleva esa clase
     desde entonces— porque los controles de esas cinco cosas SON ahora esta
     misma columna, y un resumen al lado de su propio control es un segundo
     lector que se queda rancio. El porqué completo, fila por fila, está en el
     marcado de js/ui-setup.js. */
}
