/**
 * Switch Control (/switch-control).
 *
 * Estilos propios, sin depender de ninguna otra hoja del sitio: este
 * panel lo usa alguien conduciendo una transmisión, muchas veces desde un
 * celular y con poca luz, así que va en oscuro, con texto grande y botones
 * cómodos de tocar.
 *
 * Todo sale de la tabla de valores de abajo. Antes cada regla inventaba su
 * radio, su sombra y su duración, y doce piezas que hacían lo mismo se veían
 * distintas: en una mesa que se mira seis horas seguidas eso cansa mucho más
 * que un color feo.
 */

:root {
    /* Alturas. Tres y no más: el hueco donde se apoya todo, el panel, y la
       pieza dentro del panel. Cada altura nueva es una raya más que el ojo
       tiene que ignorar mientras busca lo que está al aire. */
    --cb-bg:       #0d1017;
    --cb-hueco:    #10141c;   /* rebajado: rails y cajas de registro */
    --cb-panel:    #161b25;
    --cb-panel-2:  #1d2432;
    --cb-panel-3:  #253044;   /* solo cursor encima; no es una altura nueva */
    --cb-border:   #2a3342;
    --cb-border-2: #3b4759;   /* lo que tiene el cursor o el foco */
    --cb-text:     #e8edf5;
    --cb-dim:      #97a5ba;
    --cb-dim-2:    #74829a;   /* notas y letra chica: presentes, no leídas */

    --cb-accent:   #6366f1;
    --cb-accent-2: #8b5cf6;
    --cb-danger:   #ef4444;
    --cb-ok:       #22c55e;

    /* Los dos colores que mandan en una mesa de realización. Rojo lo que
       sale, ámbar lo que está listo para salir. Nada más de la pantalla
       puede pesar tanto como estos dos, o dejan de significar algo. */
    --cb-aire:     #f04747;
    --cb-prev:     #f59e0b;

    /* Escala de espacio, en saltos de 4. Se usa el nombre, no el número:
       así una fila de botones y otra de tarjetas respiran igual. */
    --cb-e1: 4px;
    --cb-e2: 6px;
    --cb-e3: 8px;
    --cb-e4: 12px;
    --cb-e5: 16px;
    --cb-e6: 20px;
    --cb-e7: 28px;

    /* Radios. Cuanto más grande la caja, más redondo el borde: una caja
       chica con el radio de una grande parece una pastilla deshinchada. */
    --cb-r1: 6px;    /* sellos, celdas del esquema */
    --cb-r2: 9px;    /* botones chicos, campos apretados */
    --cb-r3: 11px;   /* botón normal, campo normal */
    --cb-r4: 14px;   /* tarjeta */
    --cb-r5: 18px;   /* panel, rail, escenario */

    /* Alto de la cabecera del cajón. Vive aquí y no dentro de su regla
       porque lo usan DOS piezas que tienen que empezar a la misma altura: la
       cabecera y el rail que va a su izquierda. Cuando el rail no lo sabía,
       sus botones arrancaban pegados al borde de la ventana mientras el
       título del módulo empezaba 65 px más abajo, y las dos columnas se veían
       desalineadas. */
    --cb-cajon-cab: 65px;
    --cb-rp: 999px;  /* pastilla */

    /* Tipografía. Siete tamaños; si hace falta un octavo es que la pieza
       está mal pensada. */
    --cb-t0: 10px;
    --cb-t1: 11px;
    --cb-t2: 12px;
    --cb-t3: 13px;
    --cb-t4: 14px;
    --cb-t5: 16px;
    --cb-t6: 21px;
    --cb-t7: 30px;

    /* Sombras. En oscuro la sombra casi no se ve, así que cada altura lleva
       además un filo de luz arriba: es lo que hace que una tarjeta parezca
       levantada y no un rectángulo pintado. */
    --cb-som-1: 0 1px 2px rgba(0, 0, 0, .35);
    --cb-som-2: 0 2px 4px rgba(0, 0, 0, .25), 0 10px 26px rgba(0, 0, 0, .3);
    --cb-som-3: 0 24px 60px rgba(0, 0, 0, .55);
    --cb-som-cajon: -30px 0 80px rgba(0, 0, 0, .55);
    --cb-filo: inset 0 1px 0 rgba(255, 255, 255, .045);

    /* Tiempos. Lo chico se mueve rápido o parece lento; lo grande se mueve
       despacio o parece un salto. */
    --cb-mov-1: 130ms;   /* un color, un borde, un punto */
    --cb-mov-2: 190ms;   /* un botón, una tarjeta */
    --cb-mov-3: 300ms;   /* el contenido de un módulo */
    --cb-mov-4: 320ms;   /* el cajón entero */

    /* Curvas. Ninguna es lineal: nada de lo que existe se mueve a velocidad
       constante, y el ojo lo nota aunque no sepa decir por qué. */
    --cb-sal:     cubic-bezier(.33, 1, .68, 1);      /* llega y frena */
    --cb-amb:     cubic-bezier(.4, 0, .2, 1);        /* ida y vuelta */
    --cb-firme:   cubic-bezier(.16, 1, .3, 1);       /* mucho recorrido */
    --cb-resorte: cubic-bezier(.34, 1.48, .58, 1);   /* pasa de largo y vuelve */

    /* El compás de lo que está saliendo al aire.
       Un solo tempo para las seis piezas que dicen lo mismo —el punto de
       emisión, el sello del invitado, el estado de Emitir, el botón de la
       fuente al aire, la píldora de la web y el tally del teléfono—, que
       corrían a cinco velocidades distintas. Dos rojos parpadeando a
       destiempo se leen como una avería, no como una emisión; y el
       comentario de .cb-em-on decía «como el punto de emisión» mientras
       latía más lento que él.
       NO lo usan los otros dos latidos del panel, que significan otra cosa:
       .cb-gv-ap-espera va más rápido porque es impaciencia, no emisión. */
    --cb-latido: 1.7s;

    --cb-foco: #818cf8;
    --cb-anillo: 0 0 0 3px rgba(99, 102, 241, .32);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* Que «hidden» siga escondiendo pase lo que pase. Media docena de piezas de
   Switch Control llevan display propio —el vúmetro es flex, el video del
   invitado es absolute— y eso le ganaba a la regla del navegador: el guion
   las escondía y seguían ahí. */
[hidden] { display: none !important; }

/* El rótulo que no se ve. Media botonera son dibujos sin palabra al lado
   —así se reconocen de un vistazo—, pero un dibujo sin nombre no lo puede
   pulsar quien no ve, y tampoco hay forma de buscarlo desde una prueba.
   Se queda en la página, ocupando un píxel, para los dos. */
.cb-vh {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

body {
    background: var(--cb-bg);
    color: var(--cb-text);
    font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    min-height: 100vh;
    -webkit-text-size-adjust: 100%;
    /* A media luz el texto grueso se emborrona; con suavizado de escala de
       grises la letra chica de los rótulos se sigue leyendo de lejos. */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* El foco tiene que verse SIEMPRE, y verse igual en todas partes: es la
   única pista que le queda a quien opera Switch Control con el teclado porque
   tiene las dos manos ocupadas. Solo con teclado, para no ensuciar el clic. */
:focus-visible {
    outline: 2px solid var(--cb-foco);
    outline-offset: 2px;
}

/* ── Login ───────────────────────────────────────────────────────────── */

.cb-login-page {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background:
        radial-gradient(circle at 50% 0%, rgba(99, 102, 241, 0.18), transparent 60%),
        var(--cb-bg);
}

.cb-login {
    width: 100%;
    max-width: 380px;
    background: var(--cb-panel);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r5);
    padding: 34px var(--cb-e7);
    text-align: center;
    box-shadow: var(--cb-som-3), var(--cb-filo);
}

.cb-login-logo { height: 54px; width: auto; margin-bottom: var(--cb-e5); }
.cb-login-title { font-size: var(--cb-t6); font-weight: 800; letter-spacing: -.01em; }
.cb-login-sub { font-size: var(--cb-t3); color: var(--cb-dim); margin-bottom: var(--cb-e7); }

/* Rótulo de campo. Va en versalitas y apagado a propósito: dice qué se
   escribe ahí, no compite con lo que ya está escrito. */
.cb-lbl {
    display: block;
    text-align: left;
    font-size: var(--cb-t1);
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--cb-dim-2);
    margin: var(--cb-e5) 0 var(--cb-e2);
}

.cb-input {
    width: 100%;
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r3);
    color: var(--cb-text);
    font-family: inherit;
    padding: 12px 14px;
    /* 16px como mínimo: por debajo, iOS hace zoom al enfocar. */
    font-size: max(15px, 16px);
    transition: border-color var(--cb-mov-1) var(--cb-amb),
                box-shadow var(--cb-mov-1) var(--cb-amb),
                background-color var(--cb-mov-1) var(--cb-amb);
}

.cb-input::placeholder { color: var(--cb-dim-2); }
.cb-input:hover:not(:focus) { border-color: var(--cb-border-2); }

/* El anillo hace de foco por sí solo, así que aquí no hace falta además el
   contorno del navegador: serían dos marcas para lo mismo. */
.cb-input:focus {
    outline: none;
    border-color: var(--cb-accent);
    box-shadow: var(--cb-anillo);
    background: var(--cb-bg);
}

.cb-login-error {
    color: var(--cb-danger);
    font-size: var(--cb-t3);
    font-weight: 600;
    margin-top: 12px;
    min-height: 1em;
}

.cb-login-foot { font-size: var(--cb-t2); color: var(--cb-dim); margin-top: 20px; }
.cb-login-foot a { color: var(--cb-accent); }

/* ── Botones ─────────────────────────────────────────────────────────── */

.cb-btn {
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    color: var(--cb-text);
    font-family: inherit;
    font-size: var(--cb-t4);
    font-weight: 600;
    padding: 10px var(--cb-e5);
    border-radius: var(--cb-r3);
    cursor: pointer;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--cb-e2);
    /* 40px de alto mínimo: se usa con el dedo, muchas veces de pie. */
    min-height: 40px;
    box-shadow: var(--cb-filo);
    /* Al soltar vuelve más despacio de lo que se hundió: así el botón
       parece tener masa en vez de parpadear. */
    transition: background-color var(--cb-mov-2) var(--cb-amb),
                border-color var(--cb-mov-2) var(--cb-amb),
                color var(--cb-mov-1) var(--cb-amb),
                box-shadow var(--cb-mov-2) var(--cb-amb),
                transform var(--cb-mov-2) var(--cb-sal);
}

.cb-btn:hover:not(:disabled)  { background-color: var(--cb-panel-3); border-color: var(--cb-border-2); }
.cb-btn:active:not(:disabled) { transform: scale(0.975); transition-duration: 60ms; }
.cb-btn:disabled { opacity: 0.42; cursor: default; box-shadow: none; }

.cb-btn-primary {
    background: linear-gradient(135deg, var(--cb-accent), var(--cb-accent-2));
    border-color: transparent;
    color: #fff;
    box-shadow: var(--cb-som-1), inset 0 1px 0 rgba(255, 255, 255, .18);
}

.cb-btn-primary:hover:not(:disabled) {
    background: linear-gradient(135deg, #7679f4, #9a6bf8);
    box-shadow: 0 4px 14px rgba(99, 102, 241, .34), inset 0 1px 0 rgba(255, 255, 255, .22);
}

.cb-btn-block { width: 100%; margin-top: var(--cb-e6); }
.cb-btn-ghost { background: transparent; box-shadow: none; font-size: var(--cb-t3); padding: var(--cb-e3) var(--cb-e4); min-height: 36px; }
.cb-btn-xs    { font-size: var(--cb-t2); padding: 5px 11px; min-height: 32px; border-radius: var(--cb-r2); }

/* Rojo lleno = esto sale al aire o corta la emisión. Es la acción de la que
   se arrepiente uno, y va sola en su fila. */
.cb-btn-danger {
    color: #fff;
    background: var(--cb-danger);
    border-color: transparent;
    box-shadow: 0 2px 10px rgba(239, 68, 68, .28), inset 0 1px 0 rgba(255, 255, 255, .16);
}

.cb-btn-danger:hover:not(:disabled) {
    background: #f25757;
    box-shadow: 0 4px 16px rgba(239, 68, 68, .4), inset 0 1px 0 rgba(255, 255, 255, .2);
}

/* Un botón apagado no es «el mismo color más flojo». Un morado al 40 % se
   sigue leyendo como morado y hace creer que se puede pulsar; en gris se ve
   de una que todavía no toca. */
.cb-btn-primary:disabled {
    opacity: 1;
    background: var(--cb-panel-2);
    color: var(--cb-dim-2);
    border-color: var(--cb-border);
    box-shadow: none;
}

/* Pero el rojo chico —borrar una escena, quitar un destino, silenciar a un
   invitado— no es lo mismo, y llenar la pantalla de botones rojos le quita
   el significado justo al único rojo que importa: el del aire. Se queda en
   rojo, pero apenas dibujado. */
.cb-btn-xs.cb-btn-danger,
.cb-btn-ghost.cb-btn-danger {
    color: #f8a5a5;
    background: rgba(239, 68, 68, .12);
    border-color: rgba(239, 68, 68, .34);
    box-shadow: none;
}

.cb-btn-xs.cb-btn-danger:hover:not(:disabled),
.cb-btn-ghost.cb-btn-danger:hover:not(:disabled) {
    color: #fff;
    background: rgba(239, 68, 68, .28);
    border-color: rgba(239, 68, 68, .72);
    box-shadow: none;
}

/* ── Cabecera ────────────────────────────────────────────────────────── */

.cb-top {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cb-e4);
    padding: var(--cb-e4) var(--cb-e6);
    background: rgba(13, 16, 23, 0.86);
    backdrop-filter: blur(14px) saturate(1.2);
    border-bottom: 1px solid var(--cb-border);
    box-shadow: 0 1px 0 rgba(255, 255, 255, .03), 0 10px 30px -18px rgba(0, 0, 0, .9);
}

.cb-top-brand { display: flex; align-items: center; gap: 11px; }
.cb-top-logo  { height: 34px; width: auto; }
.cb-top-title { font-size: var(--cb-t5); font-weight: 800; letter-spacing: 0.02em; }

.cb-top-right { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }

.cb-quien {
    font-size: var(--cb-t3);
    color: var(--cb-dim);
    font-weight: 600;
    max-width: 140px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── Contenido ───────────────────────────────────────────────────────── */

.cb-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(135px, 1fr));
    gap: 10px;
    margin-bottom: 18px;
}

.cb-card {
    background: var(--cb-panel);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    padding: var(--cb-e4) var(--cb-e5);
    box-shadow: var(--cb-filo);
}

.cb-card-l {
    font-size: var(--cb-t1);
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--cb-dim-2);
    margin-bottom: 5px;
}

/* La cifra manda sobre su rótulo: se mira el número y solo si sorprende se
   lee de qué era. */
.cb-card-v { font-size: var(--cb-t5); font-weight: 800; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }

.cb-panel {
    background: var(--cb-panel);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r5);
    padding: var(--cb-e6);
    box-shadow: var(--cb-filo);
}

.cb-h2 {
    font-size: var(--cb-t1);
    font-weight: 800;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--cb-dim-2);
    margin-bottom: 10px;
}

.cb-h2:not(:first-child) { margin-top: var(--cb-e6); }

.cb-mini { font-weight: 600; opacity: 0.7; letter-spacing: 0; }

/* Dentro de un titular hereda su tamaño, pero suelto —el aviso de «pon la
   fuente del encoder a 1920 × 1080»— salía a tamaño de cuerpo: era la letra
   más grande de Aspecto y solo es una nota al pie. */
.cb-estilo > .cb-mini { font-size: var(--cb-t2); color: var(--cb-dim-2); opacity: 1; }

/* Lo que está sonando en la radio. Era texto suelto encima del panel: el
   nombre de una canción flotando sin nada que dijera qué era eso. Ahora va
   en una placa —el mismo hueco hundido que usan los rails—, que es lo que
   la convierte en un dato de la mesa y no en un renglón perdido. */
.cb-now {
    font-size: var(--cb-t3);
    line-height: 1.45;
    padding: var(--cb-e4) var(--cb-e5);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    background: var(--cb-hueco);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, .35);
}

/* En línea a propósito: el guion escribe artista, un <br> y canción, y
   volver el nombre en bloque metería un renglón vacío por medio. */
.cb-now b { font-size: var(--cb-t5); font-weight: 800; letter-spacing: -.01em; }
.cb-now span { color: var(--cb-dim); }

.cb-actions { display: flex; gap: var(--cb-e3); flex-wrap: wrap; }

.cb-say { display: flex; gap: var(--cb-e3); }
.cb-say .cb-input { flex: 1; min-width: 0; }

/* La letra de ayuda. Se lee una vez, el primer día, y después estorba: por
   eso baja de tamaño y de brillo en vez de irse.
   Los 11,5px de antes no estaban en la escala y además se leían mal a media
   luz: 12 es el escalón que existe y el que aguanta una cabina en penumbra. */
.cb-note {
    font-size: var(--cb-t2);
    line-height: 1.5;
    color: var(--cb-dim-2);
    margin-top: var(--cb-e3);
    min-height: 1em;
    /* Medida de columna de lectura. Sin ella la ayuda se estira a lo ancho
       del panel y salen renglones de noventa caracteres en letra chica:
       eso ya no es una nota, es un cartel, y no lo lee nadie que esté
       conduciendo un programa. */
    max-width: 64ch;
}

/* ── Chat ────────────────────────────────────────────────────────────── */

.cb-chat {
    max-height: 62vh;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
    /* Al llegar al final del chat no debe arrastrarse la página entera. */
    overscroll-behavior: contain;
}

.cb-msg {
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    padding: 10px var(--cb-e4);
    transition: border-color var(--cb-mov-1) var(--cb-amb);
}

.cb-msg:hover { border-color: var(--cb-border-2); }

/* Lo dicho desde el estudio no es un mensaje más del público: lleva el borde
   del panel entero, por el lado, para reconocerlo sin leer el nombre. */
.cb-msg-staff {
    border-color: rgba(99, 102, 241, .45);
    background: rgba(99, 102, 241, 0.11);
    box-shadow: inset 3px 0 0 var(--cb-accent);
}

.cb-msg-head {
    font-size: var(--cb-t1);
    color: var(--cb-dim);
    margin-bottom: 4px;
}

.cb-msg-head b { text-transform: uppercase; letter-spacing: 0.04em; }
.cb-msg-head i { color: var(--cb-accent); font-style: normal; font-weight: 700; }

.cb-msg-txt {
    font-size: var(--cb-t4);
    line-height: 1.4;
    overflow-wrap: break-word;
    margin-bottom: 8px;
}

.cb-msg-act { display: flex; gap: 6px; }

/* ── Celular ─────────────────────────────────────────────────────────── */

@media (max-width: 820px) {
    .cb-chat { max-height: 55vh; }
    .cb-quien { display: none; }
    .cb-stats { grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); }
    .cb-card-v { font-size: var(--cb-t4); }
}

/* ── Emisión ─────────────────────────────────────────────────────────── */

.cb-broadcast {
    background: var(--cb-panel);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r5);
    padding: var(--cb-e5) var(--cb-e6);
    margin-bottom: var(--cb-e5);
    box-shadow: var(--cb-filo);
    transition: border-color var(--cb-mov-3) var(--cb-amb),
                box-shadow var(--cb-mov-3) var(--cb-amb);
}

/* Al aire: borde rojo para que se distinga de un vistazo desde lejos. Y un
   filo rojo arriba del todo, que es la primera línea de la página: si algo
   está saliendo, se sabe antes de mirar nada. */
.cb-broadcast-on {
    border-color: rgba(240, 71, 71, 0.5);
    background:
        linear-gradient(180deg, rgba(240, 71, 71, .5), transparent 3px),
        linear-gradient(100deg, rgba(240, 71, 71, 0.11), var(--cb-panel) 62%);
    box-shadow: 0 0 0 1px rgba(240, 71, 71, .1), 0 10px 34px -14px rgba(240, 71, 71, .5);
}

/* Dentro, pero sin emitir. Un filo del color de la casa arriba del todo, en
   el mismo sitio donde el aire pone el suyo rojo: la primera línea de la
   página dice siempre en qué estado se está, y son dos estados distintos.
   Nada de rojo aquí — el rojo es de lo que está saliendo, y gastarlo en una
   sesión que se está preparando enseña a no mirarlo. */
.cb-broadcast-prep {
    border-color: var(--cb-border-2);
    background:
        linear-gradient(180deg, var(--cb-accent), transparent 3px),
        var(--cb-panel);
}

/* Emisión abierta que NO está saliendo: se le quita el rojo.
   El rojo de esta barra significa una sola cosa —hay programa en la calle— y
   dejarlo puesto para una emisión que no sale a ninguna parte lo convierte en
   un adorno. El ámbar dice lo que es: anotada, preparada, y sin señal. */
.cb-broadcast-mudo {
    border-color: rgba(245, 158, 11, .5);
    background:
        linear-gradient(180deg, rgba(245, 158, 11, .55), transparent 3px),
        linear-gradient(100deg, rgba(245, 158, 11, .10), var(--cb-panel) 62%);
    box-shadow: none;
}

/* Y el punto deja de latir: el latido es el pulso de lo que sale. */
.cb-broadcast-mudo .cb-bc-dot {
    background: #f59e0b;
    animation: none;
}

.cb-bc-mudo {
    margin-top: 2px;
    font-size: var(--cb-t1);
    font-weight: 700;
    letter-spacing: .02em;
    color: #f59e0b;
    /* Que no empuje la botonera a otra línea: la barra tiene que medir lo
       mismo con aviso y sin él. */
    max-width: 46ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── Modo DJ ─────────────────────────────────────────────────────────────
   Va arriba del módulo de cámaras porque decide la forma de todo lo de
   abajo. No es un ajuste escondido: es la primera decisión de la sesión. */
.cb-dj {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    margin-bottom: 10px;
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    background: var(--cb-hueco);
}
.cb-dj-txt { min-width: 0; }
.cb-dj-tit {
    margin: 0;
    font-size: var(--cb-t3);
    font-weight: 800;
    letter-spacing: -.01em;
    color: var(--cb-text);
}
.cb-dj-estado { margin: 2px 0 0; font-size: var(--cb-t1); color: var(--cb-dim); }
/* Encendido en el color de la casa, no en rojo: el rojo es del aire.
   Modo DJ con la orden abierta es exactamente eso: se te oye, pero no sale
   a ninguna parte. */
.cb-dj-on { color: var(--cb-accent-2); }
/* Y esto sí es el aire: el mismo rojo que la barra de arriba. Se gasta solo
   cuando la voz está saliendo de verdad. */
.cb-dj-aire { color: var(--cb-aire); font-weight: 700; }
.cb-dj-mal { color: #fca5a5; }
/* Los dos mandos se van al extremo: son las acciones del bloque, y el rótulo
   de al lado es lo que se lee antes de pulsarlos. En pantalla estrecha se
   apilan en vez de encogerse hasta no poder leerse. */
.cb-dj-mandos {
    margin-left: auto;
    flex: 0 0 auto;
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: flex-end;
}
/* El aviso del bucle. En ámbar y no en rojo: no está saliendo nada mal al
   aire, es una advertencia de sala. Lleva su arreglo dentro, a un clic, en
   vez de mandar a buscarlo a Ajustes con el programa empezado. */
.cb-dj-eco {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin: 0 0 12px;
    padding: 10px 12px;
    border: 1px solid var(--cb-prev);
    border-radius: var(--cb-r4);
    background: rgba(245, 158, 11, .09);
    font-size: var(--cb-t1);
    color: var(--cb-text);
}
.cb-dj-eco > span { flex: 1 1 260px; min-width: 0; }

/* La orden abierta: el color de la casa y un latido, como el sello. No es el
   rojo del aire —esto no sale a ninguna parte— pero un micrófono abierto
   tiene que verse desde el otro lado del estudio. */
.cb-dj-orden-on {
    background: var(--cb-accent-2);
    border-color: var(--cb-accent-2);
    color: #0b0713;
    animation: cb-pulse var(--cb-latido) var(--cb-amb) infinite;
}

/* ── El encoder de radio ─────────────────────────────────────────────────
   Vive en el módulo «La radio». Es un formulario, no una mesa: se abre dos
   veces en la vida de una emisora —el día que se contrata el streaming y el
   día que cambia— así que lo que importa es que se entienda, no que se opere
   rápido. Por eso cada campo lleva su pista debajo en vez de un tooltip. */
/* ── La cabecera de estado ────────────────────────────────────────────
   Un equipo de rack: el piloto grande a la izquierda, el rótulo del canal a
   la derecha, y los conectores debajo. Lo primero que se mira al abrir esto
   no es un campo, es si la radio suena. */
.cb-rd-cab {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 18px;
    border-radius: var(--cb-r4, 14px);
    border: 1px solid var(--cb-border);
    background:
        linear-gradient(180deg, var(--cb-rd-filo, transparent), transparent 3px),
        linear-gradient(100deg, var(--cb-rd-vel, transparent), var(--cb-panel-2) 68%);
    margin-bottom: 12px;
    transition: border-color var(--cb-mov-3) var(--cb-amb);
}

/* La luz. Un anillo con el punto dentro: se lee de lejos y no depende del
   texto, que es de lo que se trata cuando hay prisa. */
.cb-rd-luz {
    width: 42px; height: 42px;
    flex: 0 0 auto;
    border-radius: 50%;
    display: grid;
    place-items: center;
    border: 2px solid var(--cb-rd-color, var(--cb-border-2));
    background: var(--cb-rd-vel, transparent);
}
.cb-rd-luz span {
    width: 14px; height: 14px;
    border-radius: 50%;
    background: var(--cb-rd-color, var(--cb-dim-2));
}

.cb-rd-cab-txt { min-width: 0; flex: 1; }

.cb-rd-titulo {
    font-size: var(--cb-t5);
    font-weight: 800;
    letter-spacing: .06em;
    color: var(--cb-rd-color, var(--cb-dim));
    line-height: 1.2;
}
.cb-rd-sub {
    font-size: var(--cb-t1);
    color: var(--cb-dim);
    margin-top: 3px;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cb-rd-sub2 {
    font-size: var(--cb-t0);
    color: var(--cb-dim-2);
    letter-spacing: .06em;
    text-transform: uppercase;
    font-weight: 700;
    margin-top: 2px;
}
.cb-rd-sub2:empty { display: none; }

/* El rótulo del canal, como el serigrafiado de un equipo. */
.cb-rd-marca {
    flex: 0 0 auto;
    max-width: 34%;
    font-size: var(--cb-t0);
    font-weight: 800;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--cb-dim-2);
    text-align: right;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Los cinco estados. Cada uno sólo cambia tres fichas y el resto de las
   reglas de arriba se pinta sola: así no hay forma de que un estado se
   quede a medio vestir. */
.cb-rd-aire    { --cb-rd-color: var(--cb-ok); --cb-rd-vel: rgba(34,197,94,.10);  --cb-rd-filo: rgba(34,197,94,.55);  border-color: rgba(34,197,94,.45); }
.cb-rd-fuera,
.cb-rd-caida   { --cb-rd-color: #ef4444;      --cb-rd-vel: rgba(239,68,68,.10);  --cb-rd-filo: rgba(239,68,68,.55);  border-color: rgba(239,68,68,.45); }
.cb-rd-yendo,
.cb-rd-sin     { --cb-rd-color: #f59e0b;      --cb-rd-vel: rgba(245,158,11,.09); --cb-rd-filo: rgba(245,158,11,.5);  border-color: rgba(245,158,11,.4); }
.cb-rd-apagada,
.cb-rd-lista   { --cb-rd-color: var(--cb-dim-2); }

/* Sólo late lo que está sonando. Es el mismo latido del punto de aire de la
   barra de arriba, a propósito: el ojo ya sabe lo que significa. */
.cb-rd-aire .cb-rd-luz span { animation: cb-pulse var(--cb-latido) var(--cb-amb) infinite; }
.cb-rd-yendo .cb-rd-luz span { animation: cb-sal-late 1.1s var(--cb-amb) infinite; }
@media (prefers-reduced-motion: reduce) {
    .cb-rd-aire .cb-rd-luz span,
    .cb-rd-yendo .cb-rd-luz span { animation: none; }
}

/* Qué suena ahora mismo, si el servidor de streaming lo cuenta. */
/* El mando de la radio. Grande y antes que el formulario: es lo que se pulsa
   todos los días, mientras que el servidor se configura dos veces en la vida
   de una emisora. */
.cb-rd-mando {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    padding: 14px 0 4px;
    margin-bottom: 10px;
    border-bottom: 1px solid var(--cb-border);
}
.cb-rd-mando .cb-note { flex: 1; min-width: 200px; }
.cb-rd-btn {
    font-size: var(--cb-t3);
    font-weight: 800;
    letter-spacing: .06em;
    padding: 12px 20px;
    flex: 0 0 auto;
}
.cb-rd-btn:disabled { opacity: .45; cursor: not-allowed; }

/* El vúmetro del canal, justo debajo del piloto: la luz dice si hay conexión
   y esto dice si por esa conexión va algo. Son las dos preguntas de una radio
   y se responden sin leer. */
/* El selector de fuente: un desplegable ancho y el botón de rebuscar al lado.
   Las tarjetas se enchufan y se desenchufan con el estudio encendido. */
/* El acceso a la configuración. Un renglón, con el destino escrito al lado:
   así se comprueba a dónde va la radio sin abrir nada. */
/* El renglón de avisos del módulo. Vacío no deja hueco: una línea en blanco
   permanente empuja todo lo de abajo y se lee como que falta algo. */
.cb-rd-aviso { margin: 10px 0 0; min-height: 0; }
.cb-rd-aviso:empty { display: none; }

.cb-rd-config {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px solid var(--cb-border);
}
.cb-rd-config .cb-note { margin: 0; font-variant-numeric: tabular-nums; }

.cb-rd-fuente {
    display: flex;
    gap: 8px;
    align-items: center;
}
.cb-rd-fuente .cb-input { flex: 1; min-width: 0; }
.cb-rd-fuente .cb-btn   { flex: 0 0 auto; }

.cb-rd-vufila {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 12px;
}
.cb-rd-vufila .cb-vu { flex: 1; min-width: 0; }

.cb-rd-vutxt {
    flex: 0 0 auto;
    font-size: var(--cb-t1);
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--cb-dim-2);
    min-width: 11ch;
    text-align: right;
}
.cb-rd-vu-on   { color: var(--cb-ok); }
/* Al aire y callado no es un error —hay silencios— pero sí lo que hay que
   poder ver de un vistazo. Ámbar: mira esto, no corras. */
.cb-rd-vu-mudo { color: #f59e0b; }

/* ── El canal de streaming, para quien no lo tiene ────────────────────────
   EstudioLive pone el estudio; el canal que reparte la radio a los oyentes es
   otro servicio. Quien abre esta pantalla sin canal se queda mirando cinco
   campos que no sabe de dónde sacar, y eso no se arregla con un tooltip. */
.cb-rd-oferta {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    margin-top: 18px;
    padding: 16px 18px;
    border: 1px dashed var(--cb-border-2);
    border-radius: var(--cb-r4);
    background: var(--cb-hueco);
}
.cb-rd-oferta-txt { flex: 1; min-width: 220px; }
.cb-rd-oferta-tit {
    margin: 0 0 6px;
    font-size: var(--cb-t3);
    font-weight: 800;
    letter-spacing: -.01em;
    color: var(--cb-text);
}
.cb-rd-oferta-btn { flex: 0 0 auto; text-decoration: none; }

/* Ya tiene canal: la oferta se encoge a un renglón. No se quita —se cambia de
   proveedor y se sube de plan— pero deja de ocupar media pantalla. */
.cb-rd-oferta-mini {
    padding: 9px 14px;
    gap: 10px;
}
.cb-rd-oferta-mini .cb-rd-oferta-tit { display: none; }
.cb-rd-oferta-mini .cb-note {
    font-size: var(--cb-t1);
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
}
.cb-rd-oferta-mini .cb-rd-oferta-btn { padding: 6px 12px; font-size: var(--cb-t1); }

.cb-rd-suena {
    margin: 0 0 14px;
    padding: 7px 12px;
    border-left: 2px solid var(--cb-border-2);
    font-size: var(--cb-t2);
    color: var(--cb-dim);
}

.cb-rd-panel .cb-h2 { margin-top: 4px; }

.cb-rd-pista { margin: 4px 0 12px; }

.cb-rd-fila {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    margin-bottom: 4px;
}
@media (max-width: 520px) { .cb-rd-fila { grid-template-columns: 1fr; } }

.cb-rd-sw {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 10px 0;
}
.cb-rd-sw label { font-size: var(--cb-t2); color: var(--cb-dim); cursor: default; }

.cb-rd-mal { color: #fca5a5; }

/* ── La tira de salidas de la barra de emisión ───────────────────────────
   A dónde va a salir esto, PEGADO al botón que lo saca. Antes había que
   abrir el módulo «Destinos de transmisión» para verlo, y es lo que uno
   quiere saber con el dedo ya sobre TRANSMITIR.

   Son iconos y no rótulos. Con fichas de texto de hasta 22 caracteres, seis
   destinos partían la barra en tres líneas y el botón bajaba de sitio justo
   cuando hay prisa; y para saber si YouTube estaba en pie había que LEER.
   Un dibujo se reconoce sin leer, y las cinco salidas caben en el hueco que
   antes ocupaban dos.

   El verde significa UNA cosa y sólo una: el relay confirma que ese destino
   está recibiendo señal ahora mismo. No «está activo», no «está configurado».
   Esa confusión es justo la que hacía perder tardes buscando por qué no
   llegaba nada, y por eso el gris de al lado tiene su propio significado. */
.cb-bc-salidas {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    margin-top: 6px;
}
.cb-bc-salidas:empty { display: none; }   /* sin destinos no deja hueco */

/* Dentro del grupo del botón —modo preparando— la tira ya está en su fila:
   el margen de arriba la despegaría de TRANSMITIR, que es justo lo que hay
   que evitar. Y no crece: el botón manda, la tira acompaña. */
.cb-bc-start .cb-bc-salidas { margin-top: 0; flex: 0 1 auto; }

.cb-sal {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 9px 3px 7px;
    border-radius: 999px;
    border: 1px solid var(--cb-border);
    background: transparent;
    color: var(--cb-dim);
    font: inherit;
    font-size: var(--cb-t1);
    font-weight: 700;
    letter-spacing: .01em;
    line-height: 1.7;
    cursor: pointer;
    max-width: 22ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    transition: border-color var(--cb-mov-3) var(--cb-amb),
                color var(--cb-mov-3) var(--cb-amb);
}
.cb-sal:hover { border-color: var(--cb-border-2); }
.cb-sal:focus-visible { outline: 2px solid var(--cb-accent); outline-offset: 2px; }

/* El dibujo hereda el color del estado: es el mismo piloto que la luz de al
   lado, pero en grande. Aquí sí se tiñe el icono entero —al revés que en el
   rail de módulos— porque la forma de estas cuatro marcas se reconoce por
   silueta, y de eso el color no quita nada. */
.cb-sal-ic { font-size: 15px; }

/* Las cuatro redes y la radio van SIN rótulo: el dibujo ya dice cuál es, y
   así la tira entera cabe al lado del botón. El nombre no se pierde, sigue
   en el title y en el aria-label. */
.cb-sal-red { max-width: none; padding: 4px 9px; }

/* Lo que no es ninguna de las cuatro lleva un dibujo genérico, y a ése no se
   le distingue de otro: ahí el nombre sí hace falta. */
.cb-sal-nom { overflow: hidden; text-overflow: ellipsis; }

/* La luz de cada ficha. Es el mismo lenguaje que el punto de la barra: un
   círculo que se enciende. */
.cb-sal-luz {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex: 0 0 auto;
    background: currentColor;
    opacity: .55;
}

/* Apagado: se ve que existe, pero no participa. */
.cb-sal-off { opacity: .5; }

/* Ni siquiera está dada de alta. Se pulsa y se crea, de ahí el borde
   discontinuo: es un hueco, no una ficha.

   NO es rojo, y eso no es un descuido. El rojo de esta tira dice «esto
   debería estar saliendo y no sale»; gastarlo en una red que nadie ha dado
   de alta enseña a no mirarlo, que es exactamente lo que no puede pasar con
   el único sitio donde se comprueba si hay señal. Es la misma regla que el
   piloto de la radio. */
.cb-sal-sin {
    color: var(--cb-dim-2);
    border-style: dashed;
}
.cb-sal-sin .cb-sal-luz { opacity: .28; }
.cb-sal-sin:hover { color: var(--cb-dim); }

/* Aquí vivía `.cb-sal-vacia`, la ficha «Sin destinos · añade dónde
   publicar». Se fue con su HTML: la tira ya no puede estar vacía porque las
   cuatro redes se pintan aunque no tengan ficha, y cada una apagada dice lo
   mismo que decía aquella, pero señalando a cuál le falta. */

/* Preparado y completo: cuenta, pero todavía no sale nada por él. */
.cb-sal-lista { color: var(--cb-dim); }

/* Le falta la clave: se usará al emitir y NO va a publicar. Ámbar, el mismo
   que usa la barra para «anotada pero sin señal». */
.cb-sal-falta {
    color: #f59e0b;
    border-color: rgba(245, 158, 11, .45);
}

/* Yendo hacia la plataforma. */
.cb-sal-yendo {
    color: #f59e0b;
    border-color: rgba(245, 158, 11, .45);
}
.cb-sal-yendo .cb-sal-luz { opacity: 1; animation: cb-sal-late 1.1s var(--cb-amb) infinite; }

/* VIVO. Lo enciende el relay y nadie más.

   Late, y al compás del aire —la misma variable que el punto de emisión y
   que el piloto de la radio—. Quieto se confundía con el ámbar de «lista» de
   un vistazo rápido; latiendo se ve desde el otro lado de la mesa, que es
   desde donde se mira. */
.cb-sal-viva {
    color: var(--cb-ok);
    border-color: rgba(34, 197, 94, .55);
    background: rgba(34, 197, 94, .10);
}
.cb-sal-viva .cb-sal-luz {
    opacity: 1;
    box-shadow: 0 0 0 3px rgba(34, 197, 94, .18);
    animation: cb-pulse var(--cb-latido) var(--cb-amb) infinite;
}

/* ROJO: estamos empujando y el relay NO da esta salida por en pie. Es el
   estado que faltaba: hasta ahora una plataforma que se quedaba fuera al
   arrancar se pintaba gris igual que una en reposo, y gris se lee como
   «todavía no», no como «no está saliendo». */
.cb-sal-fuera {
    color: #fca5a5;
    border-color: rgba(239, 68, 68, .5);
    background: rgba(239, 68, 68, .08);
}
.cb-sal-fuera .cb-sal-luz { opacity: 1; background: #ef4444; }

/* Se cayó a mitad de emisión. Rojo, porque es una pérdida de aire. */
.cb-sal-caida {
    color: #fca5a5;
    border-color: rgba(239, 68, 68, .45);
    background: rgba(239, 68, 68, .08);
}
.cb-sal-caida .cb-sal-luz { opacity: 1; }

@keyframes cb-sal-late { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }

@media (prefers-reduced-motion: reduce) {
    .cb-sal-yendo .cb-sal-luz,
    .cb-sal-viva .cb-sal-luz { animation: none; }
}

/* Por qué no hay ningún verde cuando no puede haberlo. */
.cb-sal-nota {
    font-size: var(--cb-t1);
    color: var(--cb-dim-2);
    font-style: italic;
}

.cb-bc-off {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
}

/* La tira de salidas, TRANSMITIR y el guardado, en una sola fila y
   alineados por el centro. Sin `align-items` la tira se estiraba a la altura
   del botón y sus iconos quedaban colgando del borde de arriba. */
.cb-bc-start {
    display: flex;
    gap: 9px;
    flex: 1;
    min-width: 260px;
    align-items: center;
    flex-wrap: wrap;
    justify-content: flex-end;
}
.cb-bc-start .cb-input { max-width: 260px; }

.cb-bc-live {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}

.cb-bc-dot {
    width: 13px;
    height: 13px;
    border-radius: 50%;
    background: var(--cb-danger);
    flex: 0 0 auto;
    animation: cb-pulse var(--cb-latido) var(--cb-amb) infinite;
}

/* El latido del punto de aire. Sale despacio y vuelve deprisa, como un
   pulso de verdad: un parpadeo simétrico se lee como un aviso de error. */
@keyframes cb-pulse {
    0%       { opacity: 1;   box-shadow: 0 0 0 0 rgba(240, 71, 71, 0.55); }
    55%      { opacity: .48; box-shadow: 0 0 0 8px rgba(240, 71, 71, 0); }
    100%     { opacity: 1;   box-shadow: 0 0 0 0 rgba(240, 71, 71, 0); }
}

@media (prefers-reduced-motion: reduce) {
    .cb-bc-dot { animation: none; }
}

.cb-bc-info { min-width: 0; }
.cb-bc-title { font-size: var(--cb-t5); font-weight: 800; letter-spacing: -.01em; }

.cb-bc-time {
    font-size: var(--cb-t6);
    font-weight: 800;
    font-variant-numeric: tabular-nums;   /* el reloj no debe bailar */
    letter-spacing: .02em;
}

/* Al aire la tira sale del bloque del título y se pone a su lado: es un
   tally, y un tally no se busca dentro de un párrafo. El `margin-left:auto`
   de las cifras sigue empujándolas al extremo, así que la tira se queda en
   medio sin pelearse con nadie. */
.cb-bc-live .cb-bc-salidas { margin-top: 0; }

.cb-bc-metrics {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
    margin-left: auto;
    font-size: var(--cb-t2);
    color: var(--cb-dim);
}

.cb-bc-metrics b { font-size: var(--cb-t5); color: var(--cb-text); display: block; font-weight: 800; font-variant-numeric: tabular-nums; }

/* ── Historial ───────────────────────────────────────────────────────────
   Siete columnas —programa, fecha, duración, pico, promedio, mensajes,
   personas— dentro de un cajón de 480 px. Como tabla no cabía: se deslizaba
   por el lado, los rótulos se quedaban arriba fuera de vista y para saber si
   ese «1» era el pico o el promedio había que arrastrar de vuelta.

   Así que deja de ser una tabla y pasa a ser una lista de fichas: cada
   emisión, una ficha; el nombre arriba con peso de titular, la fecha debajo
   apagada, y las cifras en una tira con su rótulo encima de cada una. Sigue
   siendo un <table> en el marcado —lo escribe el guion y no se toca—, pero
   deja de comportarse como tal.

   Los rótulos van en ::before y por posición de columna: el guion siempre
   escribe las siete celdas en el mismo orden, y si algún día cambia, cambia
   también esta lista de cinco líneas. */

.cb-tabla {
    display: block;   /* ya no es una rejilla: es una lista de fichas */
    width: 100%;
    font-size: var(--cb-t3);
}

/* La cabecera se va: con cada cifra rotulada en su sitio, repetir los
   rótulos arriba es decir dos veces lo mismo. */
.cb-tabla thead { display: none; }

.cb-tabla tbody { display: flex; flex-direction: column; gap: var(--cb-e3); }

/* Cada emisión, una ficha. Hundida sobre el panel, como el resto de las
   listas de Switch Control. */
.cb-tabla tr {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    column-gap: var(--cb-e2);
    row-gap: var(--cb-e3);
    padding: var(--cb-e4);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    background: var(--cb-panel-2);
    box-shadow: var(--cb-filo);
    transition: border-color var(--cb-mov-2) var(--cb-amb);
}

.cb-tabla tr:hover { border-color: var(--cb-border-2); }

.cb-tabla td {
    padding: 0;
    border: 0;
    min-width: 0;
}

/* El programa y la fecha ocupan la ficha entera: son la identidad, no un
   dato más de la tira. */
.cb-tabla td:nth-child(1) { grid-column: 1 / -1; }

.cb-tabla td:nth-child(1) b {
    display: block;
    font-size: var(--cb-t4);
    font-weight: 800;
    letter-spacing: -.01em;
    overflow-wrap: anywhere;
}

/* Fecha y hora en un solo renglón: son un dato, no dos. */
.cb-tabla td:nth-child(2) {
    grid-column: 1 / -1;
    display: flex;
    align-items: baseline;
    gap: var(--cb-e2);
    color: var(--cb-dim);
    margin-bottom: var(--cb-e1);
}

.cb-tabla td:nth-child(2) .cb-note { margin: 0; min-height: 0; }

/* La tira de cifras. La cifra manda y el rótulo la explica en chico encima,
   igual que en las tarjetas de arriba: se recorre la columna de números y
   solo se lee el rótulo cuando alguno sorprende. */
.cb-tabla td:nth-child(n+3) {
    font-size: var(--cb-t4);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}

.cb-tabla td:nth-child(n+3)::before {
    display: block;
    font-size: var(--cb-t0);
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--cb-dim-2);
    margin-bottom: 2px;
}

.cb-tabla td:nth-child(3)::before { content: 'Duración'; }
.cb-tabla td:nth-child(4)::before { content: 'Pico'; }
.cb-tabla td:nth-child(5)::before { content: 'Prom.'; }
.cb-tabla td:nth-child(6)::before { content: 'Mensajes'; }
.cb-tabla td:nth-child(7)::before { content: 'Personas'; }

/* Duración y pico son las dos cifras por las que se abre el historial: se
   quedan en blanco vivo y las otras tres bajan un punto. Tres columnas de
   ceros en blanco pesan igual que el dato que sí importa. */
.cb-tabla td:nth-child(n+5) { color: var(--cb-dim); }

@media (max-width: 820px) {
    .cb-bc-metrics { gap: 12px; margin-left: 0; width: 100%; }
    .cb-bc-start { justify-content: stretch; }
    /* Ya no hace falta deslizarla: la ficha se apila sola. Se deja el hueco
       previsto por si alguna cifra creciera de más. */
    #cbHistory { overflow-x: auto; }
}

/* ── Mesa de aire ────────────────────────────────────────────────────── */

.cb-mesa { margin-bottom: var(--cb-e5); }

.cb-mesa-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cb-e4);
    margin-bottom: var(--cb-e4);
}

.cb-toggles {
    display: flex;
    gap: var(--cb-e3);
    flex-wrap: wrap;
    margin-bottom: var(--cb-e5);
}

/* Interruptor de cada gráfica. Grande y con un punto de color: al aire hay
   que poder ver de un vistazo qué está en pantalla, sin leer. */
.cb-tog {
    display: inline-flex;
    align-items: center;
    gap: var(--cb-e3);
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    color: var(--cb-dim);
    font-family: inherit;
    font-size: var(--cb-t3);
    font-weight: 600;
    padding: 10px 15px;
    border-radius: var(--cb-r3);
    cursor: pointer;
    min-height: 42px;
    box-shadow: var(--cb-filo);
    transition: background-color var(--cb-mov-2) var(--cb-amb),
                border-color var(--cb-mov-2) var(--cb-amb),
                color var(--cb-mov-1) var(--cb-amb),
                transform var(--cb-mov-2) var(--cb-sal);
}

.cb-tog:hover  { background-color: var(--cb-panel-3); border-color: var(--cb-border-2); color: var(--cb-text); }
.cb-tog:active { transform: scale(.975); transition-duration: 60ms; }

.cb-tog-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #3f4a5c;
    flex: 0 0 auto;
    /* El punto se enciende con un resorte cortito: es la única pieza que
       cambia al pulsar, así que tiene que confirmar el gesto. */
    transition: background-color var(--cb-mov-1) var(--cb-amb),
                box-shadow var(--cb-mov-3) var(--cb-resorte);
}

.cb-tog-on {
    background-color: rgba(34, 197, 94, .13);
    border-color: rgba(34, 197, 94, .45);
    color: var(--cb-text);
}

.cb-tog-on .cb-tog-dot {
    background: var(--cb-ok);
    box-shadow: 0 0 0 3px rgba(34, 197, 94, .2), 0 0 10px rgba(34, 197, 94, .55);
}

/* ── Generador de caracteres ─────────────────────────────────────────── */

.cb-gc {
    display: grid;
    grid-template-columns: 1.3fr 1fr;
    gap: var(--cb-e6);
    padding-top: var(--cb-e5);
    border-top: 1px solid var(--cb-border);
}

.cb-gc-col { min-width: 0; }
.cb-gc-col .cb-lbl:first-child { margin-top: 0; }
.cb-gc-col .cb-input { margin-bottom: 2px; }

.cb-gc-btns {
    display: flex;
    gap: var(--cb-e3);
    margin-top: var(--cb-e4);
    flex-wrap: wrap;
}

@media (max-width: 820px) {
    .cb-gc { grid-template-columns: 1fr; gap: 14px; }
    .cb-toggles { gap: 6px; }
    .cb-tog { flex: 1 1 calc(50% - 3px); justify-content: center; }
}

/* ── Zócalos preparados ──────────────────────────────────────────────── */

.cb-presets {
    display: flex;
    flex-direction: column;
    gap: var(--cb-e2);
    margin-bottom: var(--cb-e4);
    max-height: 190px;
    overflow-y: auto;
}

.cb-preset { display: flex; gap: 6px; }

/* El botón ocupa todo el ancho: al aire hay que poder darle sin apuntar. */
.cb-preset-fire {
    flex: 1;
    min-width: 0;
    text-align: left;
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    border-left: 3px solid var(--cb-accent);
    border-radius: var(--cb-r2);
    color: var(--cb-text);
    font-family: inherit;
    padding: var(--cb-e3) 11px;
    cursor: pointer;
    transition: background-color var(--cb-mov-2) var(--cb-amb),
                border-color var(--cb-mov-2) var(--cb-amb),
                transform var(--cb-mov-2) var(--cb-sal);
}

.cb-preset-fire:hover  { background-color: var(--cb-panel-3); border-left-color: var(--cb-accent-2); }
.cb-preset-fire:active { transform: scale(.99); transition-duration: 60ms; }

.cb-preset-fire b {
    display: block;
    font-size: var(--cb-t3);
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cb-preset-fire span {
    display: block;
    font-size: var(--cb-t1);
    color: var(--cb-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cb-preset-del {
    flex: 0 0 auto;
    width: 34px;
    background: transparent;
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r2);
    color: var(--cb-dim-2);
    cursor: pointer;
    font-size: var(--cb-t3);
    transition: color var(--cb-mov-1) var(--cb-amb),
                border-color var(--cb-mov-1) var(--cb-amb),
                background-color var(--cb-mov-1) var(--cb-amb);
}

.cb-preset-del:hover { color: #f8a5a5; border-color: rgba(239, 68, 68, .55); background: rgba(239, 68, 68, .1); }

/* ── Invitados ───────────────────────────────────────────────────────── */

/* ── Invitados ───────────────────────────────────────────────────────────
   Tarjeta con la imagen delante. Lo primero que se quiere saber de alguien
   que espera turno es qué cara trae y si se le ve bien; el nombre y los
   botones vienen después. Antes la imagen aparecía y desaparecía según
   hubiera cámara, y la lista daba saltos mientras se intentaba pulsar. */

.cb-gv {
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    overflow: hidden;
    margin-bottom: 10px;
    box-shadow: var(--cb-filo);
    transition: border-color var(--cb-mov-3) var(--cb-amb),
                box-shadow var(--cb-mov-3) var(--cb-amb);
}

/* Rojo si sale, ámbar si está preparado: los mismos colores de la mesa. El
   halo cuenta lo mismo que el borde pero se ve de más lejos, que es a la
   distancia a la que se mira una lista de cuatro invitados. */
.cb-gv-aire {
    border-color: rgba(240, 71, 71, .6);
    box-shadow: 0 0 0 1px rgba(240, 71, 71, .18), 0 8px 26px -12px rgba(240, 71, 71, .6);
}

.cb-gv-pvw  {
    border-color: rgba(245, 158, 11, .55);
    box-shadow: 0 0 0 1px rgba(245, 158, 11, .14), 0 8px 26px -14px rgba(245, 158, 11, .5);
}

.cb-gv-cuadro {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: #05070b;
}

.cb-gv-video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    /* Sin espejo: aquí se comprueba cómo va a salir al aire, y al aire no
       va invertido. En su propia pantalla el invitado sí se ve en espejo. */
}

/* ── El estudio sin cámara ────────────────────────────────────────────────
   En modo DJ no hay pista de vídeo y este marco salía en negro: un 16:9
   entero para no enseñar nada. Se colapsa a una tira que sólo lleva el
   sello —AL AIRE / SOLO INVITADOS— y deja al vúmetro de abajo el trabajo de
   ser la imagen, que en una radio es exactamente lo que es. */
.cb-gv-cuadro.cb-camest-voz {
    aspect-ratio: auto;
    background: transparent;
    min-height: 0;
    display: flex;
    align-items: center;
    padding: 0 0 8px;
}
.cb-camest-voz .cb-gv-video { display: none; }
/* El sello deja de flotar sobre la imagen porque ya no hay imagen debajo. */
.cb-camest-voz .cb-gv-sello {
    position: static;
    box-shadow: none;
}

/* Mientras no hay imagen, el hueco dice por qué no la hay. */
.cb-gv-espera {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: 14px;
    text-align: center;
}

.cb-gv-ini {
    width: 54px;
    height: 54px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    font-size: var(--cb-t6);
    font-weight: 800;
    color: var(--cb-dim);
}

.cb-gv-espera-txt { font-size: var(--cb-t2); color: var(--cb-dim); line-height: 1.4; max-width: 30ch; }

/* El estado, encima de la imagen: se mira de reojo mientras se opera. */
.cb-gv-sello {
    position: absolute;
    top: var(--cb-e3);
    left: var(--cb-e3);
    padding: 3px 9px;
    border-radius: var(--cb-rp);
    font-size: var(--cb-t0);
    font-weight: 800;
    letter-spacing: .08em;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .45);
}

.cb-gv-sello-aire   { background: var(--cb-aire); color: #fff; animation: cb-pulse var(--cb-latido) var(--cb-amb) infinite; }
.cb-gv-sello-pvw    { background: var(--cb-prev); color: #1a1206; }
.cb-gv-sello-espera { background: rgba(34, 197, 94, .9); color: #05210f; }
/* La orden: se te oye, pero solo dentro. En el color de la casa y sin latido
   —el latido es del aire y no se presta— pero encendido, porque un micrófono
   abierto tiene que verse desde el otro lado del estudio. */
.cb-gv-sello-int    { background: var(--cb-accent-2); color: #0b0713; }
.cb-gv-sello-no     { background: rgba(8, 10, 16, .8); border: 1px solid var(--cb-border); color: var(--cb-dim); }

/* Se le está mirando pero su conexión se cayó: lo que se ve es el último
   cuadro, congelado. Apagado y sin color no se confunde con alguien que
   está ahí callado, que es como se veía hasta ahora. */
.cb-gv-video-mal { opacity: .4; filter: grayscale(.85); }

/* Apagar la imagen: discreto, en la esquina. Cada pantalla abierta le cuesta
   subida al invitado, pero no es la acción principal. */
.cb-gv-ojo {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background: rgba(8, 10, 16, .72);
    border: 1px solid rgba(255, 255, 255, .14);
    color: #e8edf5;
    font-size: var(--cb-t3);
    cursor: pointer;
    line-height: 1;
}

.cb-gv-ojo {
    transition: background-color var(--cb-mov-1) var(--cb-amb),
                border-color var(--cb-mov-1) var(--cb-amb),
                opacity var(--cb-mov-2) var(--cb-amb);
    /* Está encima de la cara del invitado: se aparta hasta que hace falta. */
    opacity: .55;
}

.cb-gv-cuadro:hover .cb-gv-ojo,
.cb-gv-ojo:focus-visible { opacity: 1; }

.cb-gv-ojo:hover { background: rgba(8, 10, 16, .92); border-color: rgba(255, 255, 255, .3); }

/* La mesa del invitado: sus aparatos y cuánto se le oye. Va entre la imagen
   y el nombre porque es lo que se toca mientras se le mira. */
.cb-gv-mesa {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 11px 0;
}

.cb-gv-ap { padding: 6px 9px; line-height: 1; }

/* Orden mandada y todavía sin cumplir: la orden viaja en el latido del
   invitado, así que tarda unos segundos. Sin marcarlo, el operador cree que
   no funcionó y vuelve a pulsar. */
.cb-gv-ap-espera {
    opacity: .55;
    /* Más rápido que --cb-latido a propósito, y no es un descuido: esto no
       dice «está saliendo», dice «te estoy esperando». Igualarlo al compás
       del aire le quitaría la prisa, que es justo lo que comunica. */
    animation: cb-pulse 1.1s var(--cb-amb) infinite;
}

.cb-gv-vol {
    display: flex;
    align-items: center;
    gap: 7px;
    flex: 1;
    min-width: 0;
    padding-left: 4px;
}

.cb-gv-vol span {
    font-size: var(--cb-t0);
    font-weight: 700;
    color: var(--cb-dim);
    min-width: 24px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.cb-gv-vol input {
    flex: 1;
    min-width: 0;
    accent-color: var(--cb-accent);
    cursor: pointer;
}

/* Cuando el monitor SÍ suena, el aviso cambia de tono: en un estudio, algo
   sonando sin que nadie lo sepa es un pitido esperando a ocurrir. */
.cb-mon-suena {
    background: rgba(34, 197, 94, .9);
    border-color: rgba(34, 197, 94, .5);
    color: #05210f;
}

/* ── La cámara del estudio ───────────────────────────────────────────────
   La cámara de este equipo como una fuente más. Va arriba de los invitados
   porque es la que casi siempre está: la del conductor. */

.cb-camest {
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    border-radius: 13px;
    padding: 12px 13px;
    margin-bottom: 14px;
}

.cb-camest-cab {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 10px;
}

.cb-camest-tit {
    font-size: var(--cb-t3);
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--cb-dim);
    margin: 0;
}

.cb-camest-sel { margin-bottom: 10px; }
.cb-camest-sel .cb-input { margin-bottom: 8px; font-size: var(--cb-t2); }
.cb-camest-sel .cb-lbl { margin-top: 0; }

.cb-camest .cb-gv-cuadro { border-radius: 10px; overflow: hidden; }

.cb-camest-pie {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 8px;
}

/* ── El vúmetro ──────────────────────────────────────────────────────────
   Doce luces con lo que entra por el micrófono del invitado. Dice lo que no
   dice ningún botón: si se le oye, si se le oye de más, o si está hablando y
   no llega nada. */

.cb-vu {
    display: flex;
    gap: 2px;
    padding: 7px 11px 9px;
}

.cb-vu i {
    flex: 1;
    height: 7px;
    border-radius: 2px;
    background: var(--cb-border);
    /* Sube al instante y baja con calma: así se ve el pico, que es lo que
       hay que ver. Con la misma duración en los dos sentidos el vúmetro
       parpadea y no se lee nada. */
    transition: background-color 260ms var(--cb-sal);
}

.cb-vu i.cb-vu-on { transition-duration: 40ms; }

/* Verde hasta las ocho, ámbar hasta las diez, rojo las dos últimas: el rojo
   es "te estás pasando", no "va bien y fuerte". */
.cb-vu i.cb-vu-on                      { background: var(--cb-ok); }
.cb-vu i:nth-child(n+9).cb-vu-on       { background: #f59e0b; }
.cb-vu i:nth-child(n+11).cb-vu-on      { background: var(--cb-danger); }

/* Sin medir: apagado y sin llamar la atención. */
.cb-vu-off { opacity: .35; }

/* Midiendo pero en silencio: se distingue de "no estoy midiendo". */
.cb-vu-mudo i:first-child { background: #3f4a5c; }

.cb-gv-pie {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 11px;
}

.cb-gv-name {
    flex: 1;
    min-width: 0;
    font-size: var(--cb-t4);
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cb-gv-btns { display: flex; gap: 5px; flex: 0 0 auto; }

/* El enlace solo mientras haga falta mandarlo. */
.cb-gv-url {
    padding: 0 11px 10px;
    font-size: var(--cb-t0);
    color: var(--cb-dim);
    font-family: ui-monospace, monospace;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Con sitio de sobra, dos por fila. En el cajón hay una sola columna. */
#gvList { display: grid; grid-template-columns: 1fr; gap: 10px; }
#gvList .cb-gv { margin-bottom: 0; }

@media (min-width: 1400px) {
    .cb-cajon-cuerpo #gvList { grid-template-columns: 1fr; }
}

/* ── Selector de fuente ──────────────────────────────────────────────────
   Lo más importante de la pantalla: qué se está viendo al aire. Botones
   grandes y la que está al aire marcada en rojo, que es el color que en
   televisión significa "esto sale". */

/* Los dos sellos que se pegan sobre una miniatura: rojo lo que sale, ámbar
   lo preparado. Son lo único que quedó vivo del módulo «Fuentes», una lista
   de tarjetas que el rediseño sustituyó por la botonera. El resto de la
   familia .cb-src —unas 130 líneas— se retiró; estos dos siguen porque
   pintarImagenes() los cuelga de .cb-img-sello, que es quien los coloca. */
.cb-src-pvw {
    font-size: var(--cb-t0);
    font-weight: 800;
    letter-spacing: .09em;
    color: #1a1206;
    background: var(--cb-prev);
    padding: 3px 7px;
    border-radius: var(--cb-r1);
    flex: 0 0 auto;
}

.cb-src-live {
    font-size: var(--cb-t0);
    font-weight: 800;
    letter-spacing: .09em;
    color: #fff;
    background: var(--cb-aire);
    padding: 3px 7px;
    border-radius: var(--cb-r1);
    flex: 0 0 auto;
    box-shadow: 0 0 14px rgba(240, 71, 71, .45);
}

/* Qué mira el monitor: previo o aire. */
.cb-mon-sel { opacity: .6; transition: opacity var(--cb-mov-2) var(--cb-amb), background-color var(--cb-mov-2) var(--cb-amb), border-color var(--cb-mov-2) var(--cb-amb); }
.cb-mon-sel:hover { opacity: .9; }
.cb-mon-sel-on {
    opacity: 1;
    background-color: rgba(99, 102, 241, .2);
    border-color: rgba(99, 102, 241, .5);
    color: #fff;
    box-shadow: 0 0 0 1px rgba(99, 102, 241, .16);
}

/* Una fuente en escena lleva al lado el botón de hacerla principal, así que
   la celda de la cuadrícula es la fila, no el botón. */
.cb-src-row {
    display: flex;
    align-items: stretch;
    gap: 6px;
}

.cb-src-row .cb-src { flex: 1; min-width: 0; }
.cb-src-row .cb-btn { flex: 0 0 auto; }

/* Al aire pero sin señal: sigue en la lista para poder sacarla, y el punto
   deja de latir porque ya no está llegando nada. */
.cb-src-mal .cb-src-dot {
    background: var(--cb-prev);
    box-shadow: none;
    animation: none;
}

/* Cómo se reparten la pantalla las fuentes. Reusa el interruptor de las
   gráficas: es el mismo gesto y conviene que se vea igual. */
.cb-lays {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 12px;
}

/* Aspecto de la escena: la tira de estilos ocupa su renglón entero y el
   rótulo baja pegado a su muestra de color. Cuando lo dejaba al azar del
   ajuste de línea, «Color de la casa» se quedaba arriba con los botones y
   el cuadradito de color aparecía solo debajo, huérfano y sin nombre. */
.cb-estilo {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: var(--cb-e5);
}

.cb-estilo > .cb-lays { flex: 1 1 100%; }

.cb-color {
    width: 46px;
    height: 34px;
    padding: 2px;
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r2);
    cursor: pointer;
    transition: border-color var(--cb-mov-1) var(--cb-amb), transform var(--cb-mov-2) var(--cb-sal);
}

.cb-color:hover { border-color: var(--cb-border-2); }
.cb-color:active { transform: scale(.97); }

@media (max-width: 820px) {
    .cb-fuentes { grid-template-columns: 1fr; }
    .cb-lays .cb-tog { flex: 1 1 calc(50% - 4px); justify-content: center; }
}

/* ── Emitir desde el navegador ───────────────────────────────────────────
   Salir al aire sin OBS. Va arriba del todo porque es la primera acción del
   programa y la última: encender y cortar. */

.cb-emitir { margin-bottom: var(--cb-e5); }

.cb-em-main {
    display: grid;
    grid-template-columns: 1.1fr 1fr;
    gap: var(--cb-e5);
    align-items: start;
}

.cb-em-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: #000;
}

.cb-em-ctl { display: flex; flex-direction: column; }

.cb-em-estado {
    font-size: var(--cb-t4);
    font-weight: 700;
    color: var(--cb-dim);
    padding: var(--cb-e4) var(--cb-e5);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r3);
    background: var(--cb-panel-2);
    transition: color var(--cb-mov-3) var(--cb-amb),
                background-color var(--cb-mov-3) var(--cb-amb),
                border-color var(--cb-mov-3) var(--cb-amb);
}

/* Al aire: rojo y latiendo, como el punto de emisión. No hay forma de
   confundirlo con "preparado". */
.cb-em-on {
    color: #fff;
    background: rgba(240, 71, 71, .18);
    border-color: rgba(240, 71, 71, .6);
    animation: cb-pulse var(--cb-latido) var(--cb-amb) infinite;
}

/* Conectando: ámbar y quieto. Es el estado que ANTES no existía —el panel
   saltaba de "preparado" a "AL AIRE" en cuanto se lanzaba ffmpeg, sin esperar
   a que hablara con ningún destino—, y tiene que distinguirse a un metro del
   rojo del aire: aquí todavía no está saliendo nada. Sin latido a propósito;
   el latido es del aire. */
.cb-em-mid {
    color: #fcd34d;
    background: rgba(245, 158, 11, .14);
    border-color: rgba(245, 158, 11, .5);
}

.cb-em-mal { color: #fca5a5; border-color: rgba(239, 68, 68, .4); }

.cb-em-reloj {
    font-size: var(--cb-t7);
    font-weight: 800;
    letter-spacing: .02em;
    margin: var(--cb-e4) 0 var(--cb-e1);
    font-variant-numeric: tabular-nums;
}

/* Los dos pasos de salir al aire son lo único que se hace en este módulo, y
   se hacen con prisa. Van en columna, a todo lo ancho y con cuerpo de mando
   de verdad: aquí no se apunta, se golpea. */
.cb-em-btns {
    display: flex;
    flex-direction: column;
    gap: var(--cb-e3);
    margin-top: var(--cb-e5);
}

.cb-em-btns .cb-btn { justify-content: center; min-height: 46px; }

/* El registro del relay: lo que dice ffmpeg mientras se emite. Feo a
   propósito —monoespaciado y pequeño— porque es diagnóstico, no interfaz. */
.cb-em-log {
    margin-top: var(--cb-e4);
    max-height: 120px;
    overflow-y: auto;
    background: var(--cb-hueco);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r2);
    padding: 8px 10px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: var(--cb-t1);
    line-height: 1.5;
    color: var(--cb-dim);
    word-break: break-word;
}

/* La fila de kbps y cuadros por segundo. Vivía dentro del desplegable
   «Configurar relay» del módulo de Emitir, que ya no existe: la
   configuración entera se mudó a Ajustes › Emitir. El marco de aquel
   desplegable (.cb-em-cfg) se fue con él; la fila sigue haciendo falta. */
.cb-em-cfg-row {
    display: flex;
    gap: var(--cb-e4);
    align-items: flex-end;
    margin-top: var(--cb-e4);
    flex-wrap: wrap;
}

.cb-em-cfg-row .cb-input { max-width: 130px; }

@media (max-width: 900px) {
    .cb-em-main { grid-template-columns: 1fr; }
}

/* ── Destinos de transmisión ─────────────────────────────────────────────
   Aquí se manejan credenciales: cada tarjeta es una plataforma con su
   dirección y su clave. */

.cb-dest {
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    padding: var(--cb-e5);
    margin-bottom: var(--cb-e4);
    box-shadow: var(--cb-filo);
    transition: border-color var(--cb-mov-2) var(--cb-amb);
}

/* Destinos es el módulo más cargado de Switch Control: veintitrés mandos en un
   cajón de 480 px. Aquí la densidad no es cuestión de gusto.

   El rótulo pertenece al campo que tiene debajo, no al que tiene encima:
   con los 14 px de aire que traía de fábrica quedaba a medio camino entre
   los dos y el módulo medía dos pantallas y media. Se pega al suyo y el
   aire se reparte entre grupos, que es donde hace falta. */
.cb-dest .cb-lbl { margin: var(--cb-e4) 0 var(--cb-e1); }
.cb-dest .cb-lbl:first-of-type { margin-top: var(--cb-e3); }

.cb-dest:hover { border-color: var(--cb-border-2); }

.cb-dest-head {
    display: flex;
    align-items: center;
    gap: var(--cb-e4);
    margin-bottom: var(--cb-e2);
}

.cb-dest-head b { font-size: var(--cb-t4); letter-spacing: -.01em; }

/* El dibujo de la red, el mismo que lleva en la tira de la barra. Va pegado
   al nombre —no separado por el hueco de la fila— porque los dos son la
   misma cosa dicha dos veces: quién es este destino. */
.cb-dest-head .cb-sal-ic { font-size: 18px; margin-right: calc(var(--cb-e4) * -1 + var(--cb-e3)); }

.cb-dest-st {
    font-size: var(--cb-t0);
    font-weight: 800;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--cb-dim-2);
    border: 1px solid var(--cb-border);
    padding: 3px var(--cb-e3);
    border-radius: var(--cb-rp);
    transition: color var(--cb-mov-2) var(--cb-amb),
                border-color var(--cb-mov-2) var(--cb-amb),
                background-color var(--cb-mov-2) var(--cb-amb);
}

/* Activo = va a salir por ahí. Verde, como el resto de lo que está en marcha. */
.cb-dest-on {
    color: var(--cb-ok);
    border-color: rgba(34, 197, 94, .5);
    background: rgba(34, 197, 94, .12);
}

.cb-dest-row {
    display: flex;
    gap: var(--cb-e2);
    align-items: center;
    margin-bottom: 0;
}

.cb-dest-row .cb-input { flex: 1; min-width: 0; }
.cb-dest-row .cb-btn   { flex: 0 0 auto; }

/* La dirección es larga y no cabe entera: en letra más chica se ve más de
   una vez. Solo con ratón — en un móvil, por debajo de 16 px iOS hace zoom
   al enfocar el campo y te saca de Switch Control a mitad de programa. */
@media (pointer: fine) {
    .cb-dest-row .cb-input { font-size: var(--cb-t3); }
}

/* Los cuatro botones del pie no son cuatro botones iguales: tres tocan este
   destino y el cuarto lo borra. Una raya arriba los separa de los campos y
   el rojo se va al otro extremo de la fila: es la distancia lo que evita el
   clic de más. */
.cb-dest-acts {
    display: flex;
    gap: var(--cb-e2);
    align-items: center;
    flex-wrap: wrap;
    margin-top: var(--cb-e5);
    padding-top: var(--cb-e4);
    border-top: 1px solid var(--cb-border);
}

.cb-dest-acts .cb-btn-danger { margin-left: auto; }

/* El acuse de «guardado» o «responde» va en su propio renglón, debajo de
   los botones. Y sin alto reservado: cuatro tarjetas guardando doce píxeles
   por si acaso son cincuenta píxeles de nada. */
.cb-dest-nota { flex: 1 1 100%; margin: var(--cb-e2) 0 0; min-height: 0; }

@media (max-width: 640px) {
    .cb-dest-row { flex-wrap: wrap; }
    .cb-dest-row .cb-input { flex: 1 1 100%; }
}

/* ── Imágenes del estudio ────────────────────────────────────────────────
   Una cuadrícula de miniaturas: se reconocen por la imagen, no por el
   nombre del archivo, que además es generado y no dice nada. */

.cb-imgs {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: var(--cb-e3);
}

.cb-img {
    position: relative;
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    overflow: hidden;
    background: #05070b;
    transition: border-color var(--cb-mov-2) var(--cb-amb),
                box-shadow var(--cb-mov-3) var(--cb-amb),
                transform var(--cb-mov-2) var(--cb-sal);
}

.cb-img:hover { border-color: var(--cb-border-2); }

/* Los mismos colores que la mesa: rojo lo que sale, ámbar lo preparado. */
.cb-img-aire {
    border-color: rgba(240, 71, 71, .6);
    box-shadow: 0 0 0 1px rgba(240, 71, 71, .18), 0 10px 28px -14px rgba(240, 71, 71, .7);
}

.cb-img-pvw  {
    border-color: rgba(245, 158, 11, .6);
    box-shadow: 0 0 0 1px rgba(245, 158, 11, .14), 0 10px 28px -16px rgba(245, 158, 11, .55);
}

.cb-img-mini {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: contain;
    background: #05070b;
}

.cb-img-sello {
    position: absolute;
    top: 7px;
    left: 7px;
}

.cb-img-btns {
    display: flex;
    gap: 4px;
    padding: 7px;
    border-top: 1px solid var(--cb-border);
    background: var(--cb-panel-2);
}

.cb-img-btns .cb-btn { flex: 1; justify-content: center; padding: 7px 6px; }
.cb-img-btns .cb-btn-danger { flex: 0 0 auto; }

/* ── El banco de escenas ─────────────────────────────────────────────────
   Mesas guardadas con nombre. La miniatura es un esquema dibujado aquí, no
   video en vivo: lo que hace falta mirando el banco es reconocer la forma
   —uno grande, dos al lado, un mosaico—, y mantener cuatro previsualizaciones
   reales por escena dejaría Switch Control de rodillas.

   Mismos colores que la mesa: ámbar lo preparado, rojo lo que sale. */

.cb-escenas {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: var(--cb-e3);
}

/* ── Las pestañas del rail izquierdo ─────────────────────────────────────
   Escenas y Cortinas comparten sitio: las dos son «cosas preparadas de
   antemano», y tenerlas a la vez en pantalla partiría en dos una columna que
   ya es estrecha. */
.cb-pest {
    display: flex;
    gap: 4px;
    margin: 0 0 14px;
    padding: 3px;
    border-radius: var(--cb-r3);
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
}

.cb-pest-b {
    flex: 1;
    padding: 7px 4px;
    border: 0;
    border-radius: calc(var(--cb-r3) - 3px);
    background: transparent;
    color: var(--cb-dim-2);
    font: inherit;
    font-size: var(--cb-t2);
    font-weight: 700;
    cursor: pointer;
    transition: background-color var(--cb-mov-2) var(--cb-amb),
                color var(--cb-mov-2) var(--cb-amb);
}

.cb-pest-b:hover { color: var(--cb-text); background: var(--cb-panel-3); }

.cb-pest-on, .cb-pest-on:hover {
    color: #fff;
    background: rgba(99, 102, 241, .28);
    box-shadow: inset 0 0 0 1px rgba(99, 102, 241, .45);
}

/* La primera casilla de Switch Control. Se marca con el dedo tanto como con el
   ratón, así que el área que responde es la etiqueta entera y no el cuadrito. */
.cb-casilla {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--cb-t2);
    font-weight: 600;
    color: var(--cb-dim);
    cursor: pointer;
    user-select: none;
}

.cb-casilla input {
    width: 15px;
    height: 15px;
    accent-color: var(--cb-accent);
    cursor: pointer;
}

/* ── La cola de continuidad ──────────────────────────────────────────────
   En marcha no se dice qué clip suena, y es a propósito: quien encadena es
   el overlay, en local, y esta página no tiene forma de saberlo sin
   inventárselo. Un panel que adivina es peor que uno que calla. */
.cb-con-mando { margin: 0 0 12px; display: flex; flex-wrap: wrap; gap: 6px; }

.cb-con-marcha {
    flex: 1 1 100%;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border-radius: var(--cb-r3);
    border: 1px solid rgba(240, 71, 71, .5);
    background: rgba(240, 71, 71, .1);
    font-size: var(--cb-t2);
    font-weight: 700;
}

.cb-con-cola { display: grid; gap: 6px; margin: 0 0 12px; }

.cb-con-fila {
    display: grid;
    grid-template-columns: 22px 1fr auto;
    gap: 6px;
    align-items: center;
    padding: 5px 6px;
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    background: var(--cb-panel-2);
}

.cb-con-num {
    font-size: var(--cb-t1);
    font-weight: 800;
    color: var(--cb-dim-2);
    text-align: center;
}

.cb-con-nom {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--cb-t2);
    font-weight: 600;
}

.cb-con-nom span { color: var(--cb-dim-2); font-weight: 500; }

.cb-con-acc { display: flex; gap: 3px; }

.cb-con-add { display: flex; gap: 6px; }
.cb-con-add select { flex: 1; min-width: 0; }

/* ── El almacén de cortinas ──────────────────────────────────────────────
   El medidor va arriba y siempre visible. La cuota del hosting está al 89%:
   enterarse de que no cabe justo cuando hace falta subir la careta es
   enterarse tarde. */
.cb-cor-subir { position: relative; cursor: pointer; }

.cb-cor-medidor { margin: 0 0 12px; }

.cb-cor-barra {
    height: 5px;
    border-radius: 999px;
    background: var(--cb-panel-3);
    overflow: hidden;
}

.cb-cor-barra i {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: rgba(99, 102, 241, .8);
    transition: width var(--cb-mov-3) var(--cb-amb);
}

/* Casi lleno no es «un poco más rojo»: es rojo. Es el aviso de que la
   próxima cortina puede no entrar. */
.cb-cor-barra-full { background: var(--cb-aire); }

.cb-cor-med-txt { margin: 5px 0 0; font-size: var(--cb-t1); }

.cb-cortinas { display: grid; gap: 8px; }

.cb-cor {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 6px;
    align-items: center;
    padding: 6px;
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    background: var(--cb-panel-2);
    box-shadow: var(--cb-filo);
    transition: border-color var(--cb-mov-2) var(--cb-amb),
                background-color var(--cb-mov-2) var(--cb-amb);
}

/* Preparada: ámbar, el mismo color que el previo en todo Switch Control. Está
   cargada y esperando, que es exactamente lo que significa el ámbar aquí. */
.cb-cor-armada {
    border-color: rgba(245, 158, 11, .5);
    background-color: rgba(245, 158, 11, .08);
}

.cb-cor-aire {
    border-color: rgba(240, 71, 71, .55);
    background-color: rgba(240, 71, 71, .1);
}

.cb-cor-b {
    display: flex;
    align-items: center;
    gap: 9px;
    min-width: 0;
    padding: 4px;
    border: 0;
    border-radius: var(--cb-r4);
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.cb-cor-b:hover { background: var(--cb-panel-3); }

.cb-cor-mini {
    flex: 0 0 auto;
    width: 60px;
    height: 34px;
    object-fit: cover;
    border-radius: calc(var(--cb-r4) - 5px);
    background: #000;
    border: 1px solid var(--cb-border);
}

/* Sin miniatura no se deja un hueco: se deja una caja del mismo tamaño, para
   que la lista no baile según qué vídeo pudo leer el navegador. */
.cb-cor-mini-no { display: block; }

.cb-cor-txt { flex: 1; min-width: 0; }

.cb-cor-txt b {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--cb-t3);
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cb-cor-txt span {
    display: block;
    font-size: var(--cb-t1);
    color: var(--cb-dim-2);
}

.cb-cor-sello {
    flex: 0 0 auto;
    font-size: var(--cb-t0);
    font-weight: 800;
    letter-spacing: .09em;
    color: #1a1206;
    background: var(--cb-prev);
    padding: 1px 6px;
    border-radius: 999px;
}

.cb-cor-sello-aire { color: #fff; background: var(--cb-aire); box-shadow: 0 0 12px rgba(240, 71, 71, .5); }

/* Lo que hace el próximo pulso, escrito. Un botón que cambia de significado
   entre un clic y el siguiente tiene que decir en cuál está. */
.cb-cor-acc-b {
    flex: 0 0 auto;
    font-size: var(--cb-t1);
    font-weight: 800;
    letter-spacing: .04em;
    color: var(--cb-dim-2);
}

.cb-cor-armada .cb-cor-acc-b { color: var(--cb-prev); }
.cb-cor-aire   .cb-cor-acc-b { color: var(--cb-aire); }

.cb-cor-acc { display: flex; flex-direction: column; gap: 4px; }

.cb-esc {
    display: grid;
    grid-template-columns: 72px 1fr;
    grid-template-areas: "mini txt" "acc acc";
    gap: 10px;
    padding: 10px;
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    background: var(--cb-panel-2);
    box-shadow: var(--cb-filo);
    transition: border-color var(--cb-mov-2) var(--cb-amb),
                background-color var(--cb-mov-2) var(--cb-amb),
                box-shadow var(--cb-mov-3) var(--cb-amb);
}

.cb-esc:hover { border-color: var(--cb-border-2); }

/* La que está cargada en el previo, para no perderla de vista entre doce. */
.cb-esc-on {
    border-color: rgba(245, 158, 11, .55);
    background-color: rgba(245, 158, 11, .07);
    box-shadow: var(--cb-filo), 0 0 0 1px rgba(245, 158, 11, .1);
}

.cb-esc-txt { grid-area: txt; min-width: 0; }

.cb-esc-nom {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--cb-t3);
    font-weight: 700;
}

.cb-esc-res {
    margin-top: 3px;
    font-size: var(--cb-t1);
    color: var(--cb-dim);
    /* Cuatro rótulos de invitado no caben: se cortan y no rompen la tarjeta. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cb-esc-sello {
    flex: 0 0 auto;
    font-size: var(--cb-t0);
    font-weight: 800;
    letter-spacing: .09em;
    color: #1a1206;
    background: var(--cb-prev);
    padding: 3px 7px;
    border-radius: var(--cb-r1);
}

.cb-esc-sello-aire { color: #fff; background: var(--cb-aire); box-shadow: 0 0 12px rgba(240, 71, 71, .5); }

.cb-esc-acc {
    grid-area: acc;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}

.cb-esc-acc .cb-btn { flex: 1; justify-content: center; padding: 7px 6px; }
.cb-esc-acc .cb-btn-danger { flex: 0 0 auto; }

/* ── El esquema ──────────────────────────────────────────────────────────
   Un cuadro 16:9 con una celda por fuente, repartidas como lo hará el
   overlay. No es exacto al píxel y no debe serlo: es un icono. */

.cb-esc-mini {
    grid-area: mini;
    display: grid;
    gap: 2px;
    width: 72px;
    aspect-ratio: 16 / 9;
    padding: 2px;
    border-radius: 6px;
    background: #05070b;
    border: 1px solid var(--cb-border);
}

.cb-esc-mini i {
    display: block;
    border-radius: 2px;
    background: linear-gradient(135deg, var(--cb-accent), var(--cb-accent-2));
}

/* Sin fuentes: el cuadro en negro, que es lo que se vería. */
.cb-esc-mini-negro { background: #05070b; }

.cb-esc-mini-solo { grid-template-columns: 1fr; }

/* Todos en una fila, sea cual sea el número. */
.cb-esc-mini-lado { grid-auto-flow: column; grid-auto-columns: 1fr; }

/* Cuadrícula: dos por fila, y con tres el último ocupa el ancho. */
.cb-esc-mini-mosaico { grid-template-columns: 1fr 1fr; }
/* La celda ancha del mosaico de tres es la PRINCIPAL y va arriba, que es lo
   que hace overlay.css. La miniatura la ponía abajo: justo la forma
   contraria a la que iba a salir al aire. */
.cb-esc-mini-mosaico.cb-esc-n3 i:first-child { grid-column: 1 / -1; }

/* La principal grande a la izquierda, el resto apilados a la derecha. */
.cb-esc-mini-destacado { grid-template-columns: 2fr 1fr; }
.cb-esc-mini-destacado i:first-child { grid-row: 1 / -1; }
.cb-esc-mini-destacado.cb-esc-n3 { grid-template-rows: 1fr 1fr; }
.cb-esc-mini-destacado.cb-esc-n4 { grid-template-rows: 1fr 1fr 1fr; }

/* La principal a pantalla completa y las demás encima, en recuadros. */
.cb-esc-mini-ventana { position: relative; grid-template-columns: 1fr; }
.cb-esc-mini-ventana i:first-child { grid-column: 1 / -1; grid-row: 1 / -1; }
.cb-esc-mini-ventana i:not(:first-child) {
    position: absolute;
    bottom: 3px;
    width: 30%;
    height: 34%;
    border: 1px solid rgba(255, 255, 255, .35);
}
.cb-esc-mini-ventana i:nth-child(2) { right: 3px; }
.cb-esc-mini-ventana i:nth-child(3) { right: 36%; }
.cb-esc-mini-ventana i:nth-child(4) { right: 69%; }

/* Libre. El sitio de cada cuadro lo decide el operador arrastrándolo, así que
   la miniatura no puede reproducirlo: lo que sí puede es no mentir. Se dibuja
   como cuadros sueltos y desalineados, que es lo que significa «los coloco
   yo». Sin esta regla la escena caía en `.cb-esc-mini` a secas —un grid sin
   columnas— y los cuadros salían apilados en una sola tira dentro de un
   recuadro de 72 px: la única de las seis escenas que no se reconocía de un
   vistazo. */
.cb-esc-mini-libre { position: relative; grid-template-columns: 1fr; }
.cb-esc-mini-libre i {
    position: absolute;
    width: 46%;
    height: 46%;
    border: 1px solid rgba(255, 255, 255, .35);
}
.cb-esc-mini-libre i:nth-child(1) { left: 4%;  top: 8%; }
.cb-esc-mini-libre i:nth-child(2) { right: 5%; top: 20%; }
.cb-esc-mini-libre i:nth-child(3) { left: 18%; bottom: 6%; }
.cb-esc-mini-libre i:nth-child(4) { right: 3%; bottom: 12%; }

/* Un botón que además dice que eso está saliendo AHORA. Rojo, como todo lo
   que emite en Switch Control. */
.cb-btn-al-aire {
    background: var(--cb-aire) !important;
    border-color: transparent !important;
    color: #fff !important;
    box-shadow: 0 3px 14px rgba(240, 71, 71, .4), inset 0 1px 0 rgba(255, 255, 255, .2) !important;
    animation: cb-pulse var(--cb-latido) var(--cb-amb) infinite;
}

/* Sesión caducada. Va fijo abajo y no como alert() porque un alert bloquea
   la página entera, y aquí lo importante es que se pueda seguir mirando lo
   que hay mientras se vuelve a entrar. */
.cb-caida {
    position: fixed;
    left: 50%;
    bottom: var(--cb-e6);
    z-index: 999;
    display: flex;
    align-items: center;
    gap: var(--cb-e4);
    max-width: min(560px, calc(100vw - 24px));
    padding: 13px var(--cb-e6);
    border-radius: var(--cb-r4);
    background: rgba(239, 68, 68, .16);
    border: 1px solid rgba(239, 68, 68, .6);
    backdrop-filter: blur(10px);
    color: var(--cb-text);
    font-size: var(--cb-t4);
    line-height: 1.45;
    box-shadow: var(--cb-som-3);
    /* Sube desde abajo en vez de aparecer: una caja que se materializa
       encima de la mesa da un susto que la noticia no merece. */
    transform: translateX(-50%);
    animation: cb-caida-entra var(--cb-mov-4) var(--cb-firme) both;
}

@keyframes cb-caida-entra {
    from { opacity: 0; transform: translate(-50%, 18px) scale(.97); }
    to   { opacity: 1; transform: translateX(-50%); }
}

/* ── Chat interno ────────────────────────────────────────────────────────
   La orden del estudio. Se parece al chat del público a propósito —es la
   misma lectura rápida— pero se distingue: aquí lo propio va a la derecha,
   como en cualquier mensajería, porque es conversación y no moderación. */

.cb-ic-tabs {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}

.cb-ic-tab {
    position: relative;
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    color: var(--cb-dim);
    font-family: inherit;
    font-size: var(--cb-t2);
    font-weight: 600;
    padding: var(--cb-e3) 13px;
    border-radius: var(--cb-rp);
    cursor: pointer;
    transition: background-color var(--cb-mov-2) var(--cb-amb),
                border-color var(--cb-mov-2) var(--cb-amb),
                color var(--cb-mov-1) var(--cb-amb);
}

.cb-ic-tab:hover { background-color: var(--cb-panel-3); border-color: var(--cb-border-2); color: var(--cb-text); }

.cb-ic-tab-on {
    background-color: rgba(99, 102, 241, .17);
    border-color: rgba(99, 102, 241, .55);
    color: var(--cb-text);
    box-shadow: 0 0 0 1px rgba(99, 102, 241, .14);
}

/* Sin leer. Va en el propio botón: el operador mira la pestaña, no una
   lista aparte. */
.cb-ic-pin {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 17px;
    height: 17px;
    margin-left: 6px;
    padding: 0 4px;
    border-radius: var(--cb-rp);
    background: var(--cb-danger);
    color: #fff;
    font-size: var(--cb-t0);
    font-style: normal;
    font-weight: 800;
}

.cb-ic-log {
    height: 190px;
    overflow-y: auto;
    background: var(--cb-hueco);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    padding: 12px;
    margin-bottom: 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.cb-ic-msg {
    max-width: 78%;
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    border-bottom-left-radius: var(--cb-r1);
    padding: var(--cb-e3) 11px;
}

/* Lo dicho desde Switch Control, a la derecha. La esquina en pico cambia de lado
   con quien habla: se distingue el turno sin leer el nombre. */
.cb-ic-mio {
    align-self: flex-end;
    background: rgba(99, 102, 241, .15);
    border-color: rgba(99, 102, 241, .4);
    border-bottom-left-radius: var(--cb-r4);
    border-bottom-right-radius: var(--cb-r1);
}

.cb-ic-quien {
    font-size: var(--cb-t1);
    font-weight: 700;
    color: var(--cb-dim);
    margin-bottom: 2px;
}

.cb-ic-quien span { font-weight: 500; opacity: .75; }
.cb-ic-para { color: var(--cb-accent); font-weight: 700; }

.cb-ic-txt { font-size: var(--cb-t4); line-height: 1.45; word-break: break-word; }

/* El acuse. Deliberadamente pequeño y apagado: es un dato de control, no
   parte de la conversación, y si pesara lo mismo que el mensaje competiría
   con él justo cuando hay prisa por leer. */
.cb-ic-visto {
    display: block;
    margin-top: 3px;
    font-size: var(--cb-t0);
    letter-spacing: .04em;
    color: var(--cb-dim-2);
}

/* «Visto» sí se enciende: es la única de las dos que cambia una decisión —si
   no repetir la orden por otro camino— y por eso se lee de un vistazo. */
.cb-ic-visto-si { color: var(--cb-ok); }

/* ── Las órdenes de un toque ─────────────────────────────────────────────
   Envuelven en varias filas y ocupan lo que dicen: son texto, no iconos, y
   un botón de ancho fijo obligaría a abreviar «No te oímos: revisa el
   micrófono» hasta dejarlo en algo que hay que descifrar con prisa. */
.cb-ic-rapidas {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cb-e2);
    margin-bottom: 10px;
}

.cb-ic-rapida {
    padding: 7px 11px;
    border: 1px solid var(--cb-border-2);
    border-radius: var(--cb-rp);
    background: var(--cb-panel-2);
    color: var(--cb-text);
    font: inherit;
    font-size: var(--cb-t2);
    line-height: 1.2;
    cursor: pointer;
    transition: background-color var(--cb-mov-1) var(--cb-amb),
                border-color var(--cb-mov-1) var(--cb-amb),
                transform var(--cb-mov-1) var(--cb-amb);
}

.cb-ic-rapida:hover:not(:disabled) { background: var(--cb-panel-3); border-color: var(--cb-foco); }

/* Al pulsar cede, y queda apagado un momento. Sin eso, el dedo nervioso
   manda «Sales ahora» tres veces y el invitado recibe tres avisos idénticos
   justo cuando menos puede pararse a leerlos. */
.cb-ic-rapida:active:not(:disabled) { transform: scale(.97); }
.cb-ic-rapida:disabled { opacity: .45; cursor: default; }

/* La única que no puede esperar dos segundos va en rojo de aire. Es el mismo
   rojo que lo que sale en pantalla, y significa lo mismo: esto es ahora. */
.cb-ic-rapida-urge {
    border-color: var(--cb-aire);
    color: #ff9b9b;
    font-weight: 700;
}
.cb-ic-rapida-urge:hover:not(:disabled) {
    background: rgba(240, 71, 71, .14);
    border-color: var(--cb-aire);
}

/* ── Monitor de programa ─────────────────────────────────────────────────
   El overlay real embebido y reducido. Se ve lo mismo que sale al aire. */

/* Aviso de que la pantalla va en silencio. Va encima del propio monitor y no
   en una nota al pie: quien mira una pantalla muda tiene que enterarse
   mirándola, no leyendo debajo. */
.cb-mon-mudo {
    position: absolute;
    top: 9px;
    right: 9px;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 9px;
    border-radius: var(--cb-rp);
    background: rgba(8, 10, 16, .8);
    border: 1px solid rgba(255, 255, 255, .16);
    color: #e8edf5;
    font-size: var(--cb-t1);
    font-weight: 700;
    pointer-events: none;
}

/* La pantalla. Es el objeto de la página, así que va hundida en el panel y
   con un filo claro por dentro: el cuadro se lee como un cristal y no como
   otro rectángulo más de la pila. */
.cb-monitor {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: #05070b;
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    overflow: hidden;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .04),
                inset 0 18px 40px -30px rgba(255, 255, 255, .18),
                0 12px 32px -20px rgba(0, 0, 0, .9);
}

/* El overlay se dibuja a 1920x1080 y se reduce al tamaño del cuadro: así se
   ve con las proporciones exactas del aire, no un diseño distinto. */
.cb-monitor-frame {
    position: absolute;
    z-index: 1;
    top: 0;
    left: 0;
    width: 1920px;
    height: 1080px;
    border: 0;
    transform-origin: top left;
    transform: scale(0.3);
    background: #05070b;
}

/* El reproductor de la plataforma se adapta al hueco por su cuenta. */
.cb-monitor-embed {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

/* Reserva para el primer pintado: el guion recalcula la escala con el ancho
   real del hueco, que cambia con el diseño y con la ventana. */
@media (min-width: 1400px) { .cb-monitor-frame { transform: scale(0.36); } }
@media (max-width: 1100px) { .cb-monitor-frame { transform: scale(0.24); } }
@media (max-width: 820px)  { .cb-monitor-frame { transform: scale(0.19); } }

/* ── La pantalla apagada ─────────────────────────────────────────────────
   Es la pieza más grande de Switch Control y pasa apagada la mayor parte del
   programa. Un rectángulo negro enorme con dos renglones flotando en medio
   no se lee como «apagado»: se lee como «se rompió».

   Un monitor de verdad apagado no es un agujero: es un cristal oscuro con
   su textura, en el que se adivina que hay un aparato. Eso es lo que se
   dibuja aquí —una trama fina de líneas de barrido y un halo suave en el
   centro—, y el mensaje deja de flotar suelto para meterse en una placa
   con un piloto en espera al lado. Cuesta cero: son dos degradados.

   Ojo: NO se toca el tamaño del cuadro según esté encendido o apagado. El
   guion mide el ancho del hueco para escalar el overlay ANTES de esconder
   esta capa, y un cuadro que crece después de medirlo deja el aire dibujado
   a media escala. */
.cb-monitor-off {
    position: absolute;
    inset: 0;
    /* Por encima del iframe. Los dos son `absolute` sin capa, y el iframe se
       cuelga DESPUÉS en el árbol, así que pintaba encima y el cartel no se
       veía nunca con el monitor encendido — justo el caso para el que se
       escribió: la vista vacía mientras el operador escucha el programa.
       Salía un rectángulo negro y ni una palabra. */
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--cb-e1);
    color: var(--cb-dim);
    text-align: center;
    padding: var(--cb-e4);
    background:
        radial-gradient(115% 85% at 50% 42%, rgba(148, 163, 184, .1), transparent 64%),
        repeating-linear-gradient(180deg,
            rgba(255, 255, 255, .035) 0 1px,
            transparent 1px 3px),
        linear-gradient(180deg, #0b0f16, #06080d);
}

/* La placa del mensaje. Es lo que convierte «no hay nada» en «está en
   espera»: el texto se apoya en algo, y lo que se apoya en algo parece
   puesto ahí a propósito. */
.cb-monitor-off p {
    display: flex;
    align-items: center;
    gap: var(--cb-e3);
    font-size: var(--cb-t4);
    font-weight: 700;
    letter-spacing: .01em;
    color: var(--cb-text);
    padding: var(--cb-e3) var(--cb-e5);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-rp);
    background: rgba(13, 16, 23, .66);
    box-shadow: var(--cb-som-1), var(--cb-filo);
}

/* El piloto de espera. Ámbar apagadito y respirando muy despacio: dice
   «alimentado y esperando», que es justo lo que pasa. Rojo sería aire y
   verde sería en marcha; ninguno de los dos es verdad aquí. */
.cb-monitor-off p::before {
    content: '';
    width: 7px;
    height: 7px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: var(--cb-prev);
    opacity: .55;
    box-shadow: 0 0 8px rgba(245, 158, 11, .45);
    /* Nombre propio y no uno generico: dos @keyframes con el mismo nombre
       no conviven —gana el ultimo y el otro deja de existir sin que nada
       avise—. */
    animation: cb-standby 3.2s var(--cb-amb) infinite;
}

@keyframes cb-standby {
    0%, 100% { opacity: .28; }
    50%      { opacity: .8; }
}

.cb-monitor-off span {
    font-size: var(--cb-t2);
    color: var(--cb-dim-2);
    margin-top: var(--cb-e2);
    max-width: 46ch;
    line-height: 1.45;
}

@media (prefers-reduced-motion: reduce) {
    .cb-monitor-off p::before { animation: none; opacity: .55; }
}

/* La fila del tema cuando no pinta nada: a sangre no hay fondo donde verlo,
   y con una imagen puesta manda la imagen. Se apaga en vez de esconderse,
   para que se entienda que existe y por qué ahora no hace nada. */
.cb-estilo-off { opacity: .45; }

/* Monitor en vertical: los recuadros que enseñan el overlay siguen al
   formato del programa. Verlo apaisado mientras sale en 9:16 haría creer
   que hay franjas negras donde no las hay. */
/* En vertical se limita el ANCHO, no el alto: con el width:100% heredado y
   aspect-ratio 9/16, la caja pedía casi el doble de alto que la columna y el
   monitor enseñaba solo el tercio superior del cuadro. */
.cb-monitor-vert {
    aspect-ratio: 9 / 16;
    width: 100%;
    max-width: calc(62vh * 9 / 16);
    margin: 0 auto;
}

/* ═══════════════════════════════════════════════════════════════════════
   EL ESTUDIO
   ═══════════════════════════════════════════════════════════════════════

   Switch Control dejó de ser una columna de tarjetas y pasó a ser un estudio:
   rail de escenas a la izquierda, el programa en el centro, rail de módulos
   a la derecha y un dock abajo con el panel del módulo elegido.

   Las clases de componente de más arriba (.cb-panel, .cb-btn, .cb-tog,
   .cb-esc*, .cb-src*, .cb-monitor*) se conservan tal cual: son las que el
   guion escribe al generar marcado, y tocarlas rompería paneles enteros.

   A 820px esto deja de ser un estudio de tres columnas y vuelve a ser una
   pila. No es una concesión: Switch Control se conduce desde el celular. */

.cb-studio {
    max-width: 1600px;
    margin: 0 auto;
    padding: 16px;
}

.cb-work {
    display: grid;
    grid-template-columns: 220px minmax(0, 1fr) 96px;
    gap: 14px;
    align-items: start;
    margin-top: 14px;
}

/* ── Los rails ───────────────────────────────────────────────────────── */

/* Los rails van HUNDIDOS y el escenario LEVANTADO. Es la única jerarquía
   que hace falta explicar de lejos: en el centro está el programa, a los
   lados están las herramientas. Antes los tres eran el mismo rectángulo y
   la pantalla se leía como una lista de tres columnas iguales. */
.cb-rail {
    background: var(--cb-hueco);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r5);
    padding: var(--cb-e4);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, .35);
}

.cb-rail-esc {
    /* El banco puede tener doce escenas: se desliza solo él, no la página. */
    max-height: 76vh;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.cb-rail-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cb-e3);
    margin-bottom: var(--cb-e4);
}

.cb-rail-head .cb-btn { padding: 5px 9px; }

/* En 220 px de rail, «+ Guardar el previo» al lado del título parte en dos
   renglones y queda como un botón roto. Debajo y a todo lo ancho se lee de
   una vez y además se acierta con el dedo. */
.cb-rail-esc .cb-rail-head { flex-wrap: wrap; }
.cb-rail-esc .cb-rail-head .cb-btn { flex: 1 1 100%; }

/* El rail de módulos: iconos en columna, como una barra de herramientas. */
.cb-rail-mod {
    display: flex;
    flex-direction: column;
    gap: 4px;
    position: sticky;
    top: 74px;   /* debajo de la cabecera, que va pegada arriba */
}

/* El botón de módulo.
   La marca de «este es el que está abierto» es una barra de luz al costado,
   dibujada con el fondo y no con un borde: un borde de 3px empujaría el
   icono cada vez que se cambia de módulo, y once botones dando un tirón de
   tres píxeles cada clic es exactamente lo que hace que una mesa parezca
   barata. El fondo se puede animar de alto sin mover nada. */
.cb-mod {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    padding: 9px var(--cb-e1);
    border: 1px solid transparent;
    border-radius: var(--cb-r3);
    background-color: transparent;
    background-image: linear-gradient(180deg, var(--cb-accent-2), var(--cb-accent));
    background-repeat: no-repeat;
    background-position: 0 50%;
    background-size: 3px 0%;
    color: var(--cb-dim);
    font-family: inherit;
    font-size: var(--cb-t0);
    font-weight: 700;
    cursor: pointer;
    transition: background-color var(--cb-mov-2) var(--cb-amb),
                color var(--cb-mov-2) var(--cb-amb),
                border-color var(--cb-mov-2) var(--cb-amb);
}

.cb-mod:hover { background-color: var(--cb-panel-2); color: var(--cb-text); }

/* Aquí va animación y no transición a propósito: el guion MUEVE el rail
   entero al cajón cada vez que se abre un módulo, y un elemento que se
   reinserta en la página pierde el estado anterior —la transición no llega
   a arrancar—. Una animación, en cambio, se ejecuta desde el principio cada
   vez que el botón vuelve a pintarse ya marcado. Es lo que hace que la
   barra CREZCA en lugar de aparecer. */
.cb-mod-on {
    color: #fff;
    background-color: rgba(99, 102, 241, .2);
    background-size: 3px 58%;
    border-color: rgba(99, 102, 241, .42);
    animation: cb-mod-marca var(--cb-mov-4) var(--cb-resorte) both,
               cb-mod-fondo var(--cb-mov-2) var(--cb-sal) both;
}

/* La barra se pasa un poco de largo y vuelve: es lo que hace un interruptor
   con muelle, y es la diferencia entre marcar algo y encenderlo. */
@keyframes cb-mod-marca {
    from { background-size: 3px 0%; }
    to   { background-size: 3px 58%; }
}

@keyframes cb-mod-fondo {
    from { background-color: rgba(99, 102, 241, 0); }
    to   { background-color: rgba(99, 102, 241, .2); }
}

/* ── El piloto de la radio en el rail ────────────────────────────────────
   El único botón del rail que dice algo por sí solo, y es a propósito: la
   radio es lo único que puede estar sonando —o dejar de sonar— sin que nadie
   tenga el módulo abierto. Un punto en la esquina del icono, como el led de
   un equipo, y no el icono entero de color: teñir el dibujo lo vuelve difícil
   de reconocer justo cuando se busca deprisa. */
.cb-mod-rd-aire  .cb-mod-ico,
.cb-mod-rd-mal   .cb-mod-ico,
.cb-mod-rd-yendo .cb-mod-ico { position: relative; }

.cb-mod-rd-aire  .cb-mod-ico::after,
.cb-mod-rd-mal   .cb-mod-ico::after,
.cb-mod-rd-yendo .cb-mod-ico::after {
    content: "";
    position: absolute;
    top: -2px; right: -3px;
    width: 8px; height: 8px;
    border-radius: 50%;
    /* El aro del color del rail: sin él, el punto se pierde encima del
       dibujo del icono cuando los dos se cruzan. */
    box-shadow: 0 0 0 2px var(--cb-panel);
}
.cb-mod-rd-aire  .cb-mod-ico::after { background: var(--cb-ok); animation: cb-pulse var(--cb-latido) var(--cb-amb) infinite; }
.cb-mod-rd-mal   .cb-mod-ico::after { background: #ef4444; }
.cb-mod-rd-yendo .cb-mod-ico::after { background: #f59e0b; animation: cb-sal-late 1.1s var(--cb-amb) infinite; }

/* Y el rótulo acompaña, apagado pero del mismo color: el punto solo es
   pequeño en una barra que se mira de reojo. */
.cb-mod-rd-aire  .cb-mod-txt { color: var(--cb-ok); }
.cb-mod-rd-mal   .cb-mod-txt { color: #f87171; }

@media (prefers-reduced-motion: reduce) {
    .cb-mod-rd-aire .cb-mod-ico::after,
    .cb-mod-rd-yendo .cb-mod-ico::after { animation: none; }
}

.cb-mod-ico { font-size: 17px; line-height: 1; }
.cb-mod-txt { letter-spacing: .02em; }

/* ── El programa ─────────────────────────────────────────────────────── */

.cb-stage {
    background: var(--cb-panel);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r5);
    padding: var(--cb-e5);
    box-shadow: var(--cb-som-2), var(--cb-filo);
}

/* Dentro del escenario los paneles heredados pierden su caja: ya están
   dentro de una. Dos bordes redondeados uno dentro de otro se ven mal.
   Y sin caja tampoco les toca el filo de luz de arriba: sin borde donde
   apoyarse queda una raya blanca suelta cruzando el panel. */
.cb-stage > .cb-panel {
    background: transparent;
    border: 0;
    border-radius: 0;
    padding: 0;
    box-shadow: none;
}

/* Aquí estaba .cb-ctlbar, la barra de Audio · Invitar · Imagen · Gráficas
   al pie del escenario. Sus cuatro mandos viven ahora en la botonera del
   monitor y no quedó nadie con esta clase. */

/* ── El dock ─────────────────────────────────────────────────────────── */

/* ── El cajón de módulos ─────────────────────────────────────────────────
   Se abre pegado al borde derecho y el programa se ENCOGE, no se tapa: hay
   que poder tocar un zócalo o cambiar el aspecto mirando el monitor. Una
   ventana centrada obligaba a trabajar a ciegas y a cerrarla para comprobar
   lo que acababas de hacer. */

/* Los paneles cerrados viven aquí, fuera de la vista pero DENTRO de la
   página: el chat, los invitados y los destinos se repintan solos cada pocos
   segundos y tienen que poder encontrar sus elementos. */
.cb-guardados { display: none; }

.cb-cajon {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 800;
    display: flex;
}

.cb-cajon[hidden] { display: none; }

.cb-cajon-caja {
    display: flex;
    width: min(var(--cb-cajon-ancho), 100vw);
    background: var(--cb-panel);
    border-left: 1px solid var(--cb-border);
    box-shadow: var(--cb-som-cajon);
    overflow: hidden;
    /* Entra deslizándose del todo, no asomando 24px: media pantalla de
       recorrido con una curva que frena al final es lo que hace que un
       cajón parezca pesado. Los 0,16s de antes eran un parpadeo. */
    animation: cb-cajon-entra var(--cb-mov-4) var(--cb-firme) both;
}

:root { --cb-cajon-ancho: 480px; }

@keyframes cb-cajon-entra {
    from { transform: translateX(100%); opacity: .4; }
    to   { transform: none; opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .cb-cajon-caja { animation: none; }
}

/* El programa se aparta para dejarle sitio. Es lo que hace que no tape.
   Y deja de ir centrado mientras el cajón está abierto: centrado en la
   pantalla entera acabaría metiéndose debajo. */
body.cb-con-cajon .cb-studio {
    max-width: none;
    margin-right: calc(var(--cb-cajon-ancho) + 14px);
}

/* El programa se encoge acompañando al cajón en vez de saltar. Se queda
   corto a propósito: el guion vuelve a calcular la escala del monitor a los
   220 ms, y si el hueco siguiera moviéndose lo mediría a medias y el
   monitor saldría del cuadro. */
.cb-studio { transition: margin-right 180ms var(--cb-firme); }
.cb-top    { transition: padding-right 180ms var(--cb-firme); }

body.cb-con-cajon .cb-top { padding-right: calc(var(--cb-cajon-ancho) + 22px); }

/* El rail vive aquí mientras el cajón está abierto. */
.cb-cajon-rail {
    flex: 0 0 auto;
    border-right: 1px solid var(--cb-border);
    background: var(--cb-hueco);
    overflow-y: auto;
    /* Arriba, el hueco de la cabecera: así el primer módulo del rail queda a
       la misma altura que el primer renglón del cuerpo, y las dos columnas
       leen como una sola pieza. Abajo y a los lados, aire: sin esto los
       botones tocaban el borde de la ventana. */
    padding: var(--cb-cajon-cab) var(--cb-e2) var(--cb-e5);
    box-sizing: border-box;
}

.cb-cajon-rail .cb-rail-mod {
    position: static;
    border: 0;
    border-radius: 0;
    background: transparent;
    /* Y sin relleno propio: el aire lo pone ya la columna de fuera. Con los
       12 px de `.cb-rail` puestos, el primer módulo caía 12 px por debajo del
       primer renglón del cuerpo — el desajuste se veía y no se sabía de dónde
       venía, porque el relleno era de otra regla. */
    padding: 0;
}

.cb-cajon-col {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.cb-cajon-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cb-e4);
    min-height: var(--cb-cajon-cab);
    box-sizing: border-box;
    padding: var(--cb-e5);
    border-bottom: 1px solid var(--cb-border);
    background: var(--cb-panel-2);
    box-shadow: var(--cb-filo);
}

/* El nombre del módulo es lo único del cajón que no se puede animar —el
   guion cambia el texto y ya—, así que se le da el peso de un titular para
   que el cambio se note por tamaño y no por movimiento. */
.cb-cajon-top .cb-h2 {
    font-size: var(--cb-t2);
    color: var(--cb-text);
    letter-spacing: .14em;
}

/* Solo se desliza el contenido: el nombre y la ✕ se quedan a la vista, que
   es de donde se sale. */
.cb-cajon-cuerpo {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--cb-e6) var(--cb-e5) var(--cb-e7);
}

/* Dentro del cajón los paneles ya no necesitan su propio marco: el marco es
   el cajón. Tampoco el filo de luz, por lo mismo que en el escenario. */
.cb-cajon-cuerpo .cb-panel {
    border: 0;
    border-radius: 0;
    padding: 0;
    background: transparent;
    box-shadow: none;
}

/* El historial ya no empuja el cajón por el lado: sus siete columnas se
   apilan en fichas (ver «Historial»). Se le deja el hueco de desbordamiento
   por si alguna cifra creciera de más, pero sin ancho mínimo: era el ancho
   mínimo lo que obligaba a arrastrar. */
.cb-cajon-cuerpo #cbHistory { overflow-x: auto; }
.cb-cajon-cuerpo .cb-tabla { min-width: 0; }

/* El historial es el único módulo que empieza por sus tarjetas de resumen,
   así que su titular no es el primer hijo y la regla de abajo no lo pillaba:
   se leía «EMISIONES ANTERIORES» en la cabecera del cajón y otra vez seis
   centímetros más abajo. */
.cb-cajon-cuerpo > .cb-dockpane > .cb-stats + .cb-panel > .cb-h2:first-child { display: none; }

.cb-cajon-cuerpo .cb-panel + .cb-panel {
    margin-top: var(--cb-e7);
    padding-top: var(--cb-e7);
    border-top: 1px solid var(--cb-border);
}

/* El nombre del módulo ya está en la cabecera del cajón: repetirlo justo
   debajo es ruido. Solo se quita el del primer panel; un módulo con varios
   —la radio tiene tres— conserva los demás para poder distinguirlos.

   Con tres excepciones, abajo. */
.cb-cajon-cuerpo > .cb-dockpane > .cb-panel:first-child > .cb-h2:first-child,
.cb-cajon-cuerpo > .cb-dockpane > .cb-panel:first-child > .cb-mesa-head > .cb-h2:first-child { display: none; }

.cb-cajon-cuerpo > .cb-dockpane > .cb-panel:first-child > .cb-mesa-head { justify-content: flex-end; }

/* La nota que abre un módulo es material de consulta, no una instrucción
   que haya que leer antes de tocar nada. En Destinos son siete renglones, y
   son lo primero que se lee cada vez que se abre el módulo más cargado de
   Switch Control. Con una raya al costado y el fondo hundido el ojo la reconoce
   de lejos como letra pequeña y salta directo a los mandos, sin que haya
   que quitarle una palabra al texto. */
.cb-cajon-cuerpo .cb-mesa-head + .cb-note {
    max-width: none;
    padding: var(--cb-e3) var(--cb-e4);
    border-left: 2px solid var(--cb-border);
    border-radius: 0 var(--cb-r2) var(--cb-r2) 0;
    background: rgba(148, 163, 184, .04);
}

/* Las tres excepciones: titulares que NO repiten el nombre del módulo.
   «Al aire», en la radio, dice qué está sonando. «Chat en vivo (14)» y
   «Chat interno — 3 sin leer» llevan colgado un dato vivo que se consulta
   con el programa en marcha. Escondiéndolos se iba también el dato: se
   abría el chat sin saber si había algo que leer. */
.cb-cajon-cuerpo > #pane-radio > .cb-panel > .cb-h2:first-child,
.cb-cajon-cuerpo > #pane-chat > .cb-panel > .cb-h2:first-child,
.cb-cajon-cuerpo > #pane-estudio > .cb-panel > .cb-mesa-head > .cb-h2:first-child { display: block; }

/* Y con el titular de vuelta, su fila vuelve a repartirse: la nota del chat
   interno no cabe al lado y baja a su propio renglón. */
.cb-cajon-cuerpo > #pane-estudio > .cb-panel > .cb-mesa-head {
    justify-content: space-between;
    flex-wrap: wrap;
}

.cb-cajon-cuerpo > #pane-estudio > .cb-panel > .cb-mesa-head > .cb-note { flex: 1 1 100%; }

/* Sin titular a la izquierda, el único mando del módulo se queda de tamaño
   accesorio y arrinconado en un rincón: el botón que enciende la señal
   pública tenía el cuerpo de una «x» de cerrar. Se le devuelve el cuerpo de
   un botón normal, que es lo que es. */
.cb-cajon-cuerpo > .cb-dockpane > .cb-panel:first-child > .cb-mesa-head > .cb-h2 + .cb-btn:last-child {
    font-size: var(--cb-t3);
    padding: var(--cb-e3) var(--cb-e5);
    min-height: 38px;
}

/* En un cajón estrecho, lo que se reparte en dos columnas se apila. */
.cb-cajon-cuerpo .cb-gc,
.cb-cajon-cuerpo .cb-em-main { grid-template-columns: 1fr; }

.cb-cajon-cuerpo .cb-imgs { grid-template-columns: 1fr; }

/* Estrecho de verdad: el cajón pasa a ocupar la pantalla y el programa ya no
   puede quedarse a la vista. En un móvil no hay sitio para las dos cosas. */
@media (max-width: 1100px) {
    :root { --cb-cajon-ancho: 100vw; }

    body.cb-con-cajon .cb-studio { margin-right: 0; }
    body.cb-con-cajon .cb-top { padding-right: 0; }

    body.cb-con-cajon { overflow: hidden; }

    .cb-cajon-caja { border-left: 0; flex-direction: column; }

    .cb-cajon-rail { border-right: 0; border-bottom: 1px solid var(--cb-border); }

    /* Se reparten en filas en vez de salirse por el lado. Con desplazamiento
       horizontal solo se veían seis de los once, y nada indicaba que hubiera
       más: pulsar un módulo parecía abrir solo ese y no llevar a ningún
       sitio. */
    .cb-cajon-rail .cb-rail-mod {
        flex-direction: row;
        flex-wrap: wrap;
        justify-content: center;
        padding: 8px;
        gap: 3px;
    }

    .cb-cajon-rail .cb-mod {
        flex: 1 1 auto;
        min-width: 58px;
        max-width: 90px;
        padding: 7px 4px;
    }

    .cb-cajon-rail .cb-mod-ico { font-size: 15px; }
    .cb-cajon-rail .cb-mod-txt { font-size: var(--cb-t0); }
}

/* Aquí vivía un segundo bloque a 900px que repetía palabra por palabra el de
   1100px de arriba. Era vestigio de cuando el cajón era una ventana centrada
   —de ahí el `padding: 0` y el `border-radius: 0`— y no llegaba a aplicarse
   nunca, porque el de 1100px ya lo había hecho todo. Se quitó al añadir la
   ventana de Ajustes: ahora sí hay una ventana centrada de verdad y un bloque
   suelto hablando de una que no existe es una trampa esperando. */

/* Un panel del dock puede traer varias secciones (Historial trae dos). */
.cb-dockpane > .cb-panel + .cb-panel,
.cb-dockpane > .cb-panel + .cb-stats { margin-top: 14px; }

.cb-dockpane > .cb-stats { margin-bottom: 14px; }

/* ── Las escenas, ahora en un rail estrecho ──────────────────────────── */

.cb-rail-esc .cb-escenas { grid-template-columns: 1fr; }

/* ── La ayuda del banco ──────────────────────────────────────────────────
   El párrafo de «arma la mesa en el previo y guárdala con un nombre» se lee
   el primer día y ya. Ocupaba un tercio del rail —la pieza que más se mira
   de todo Switch Control— para siempre. No se puede quitar del marcado, pero sí
   se puede hacer que se comporte como lo que es: un estado vacío.

   Vacío el banco, ES el estado vacío y se dibuja como tal. Con escenas
   guardadas se retira: quien ya guardó una no necesita que le expliquen
   cómo se guarda. Sin :has() el navegador se queda con el texto puesto,
   que es exactamente lo que hay hoy: nadie pierde nada. */
.cb-rail-esc:has(.cb-esc) > .cb-note { display: none; }

/* El recuadro punteado dice «aquí va a haber algo y todavía no lo hay».
   Un párrafo suelto encima de la nada solo dice «hay texto». */
.cb-rail-esc > .cb-note {
    border: 1px dashed var(--cb-border-2);
    border-radius: var(--cb-r4);
    background: rgba(148, 163, 184, .04);
    padding: var(--cb-e4);
    max-width: none;   /* en 220px la medida de lectura no pinta nada */
}

/* Y el «todavía no hay escenas guardadas» que escribe el guion dice lo
   mismo que el párrafo de arriba, palabra por palabra. Con dos avisos
   iguales seguidos no se lee ninguno: se queda el de arriba, que además
   explica el porqué y no solo el qué. */
.cb-rail-esc .cb-escenas > .cb-note { display: none; }

/* En 220px no caben miniatura y texto uno al lado del otro. */
.cb-rail-esc .cb-esc {
    grid-template-columns: 1fr;
    grid-template-areas: "mini" "txt" "acc";
    gap: 7px;
}

.cb-rail-esc .cb-esc-mini { width: 100%; }
.cb-rail-esc .cb-esc-acc .cb-btn { font-size: var(--cb-t1); padding: 5px 4px; }

/* ── Celular: el estudio vuelve a ser una pila ───────────────────────── */

@media (max-width: 820px) {
    .cb-studio { padding: 12px; }

    /* A todo lo ancho el botón vuelve a caber junto al título. */
    .cb-rail-esc .cb-rail-head .cb-btn { flex: 0 0 auto; }

    .cb-work { grid-template-columns: 1fr; gap: 12px; }

    /* Las escenas pasan a una tira que se desliza en horizontal. */
    .cb-rail-esc { max-height: none; overflow: visible; }
    .cb-rail-esc .cb-escenas {
        display: flex;
        gap: 10px;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        padding-bottom: 6px;
    }
    .cb-rail-esc .cb-esc { flex: 0 0 190px; }

    /* Y los módulos, a una fila de pestañas que también se desliza. */
    .cb-rail-mod {
        position: static;
        flex-direction: row;
        overflow-x: auto;
        overscroll-behavior-x: contain;
    }
    .cb-mod { flex: 0 0 auto; min-width: 62px; }

    /* Que se deslice la tira y no la página entera.
       Una casilla de rejilla mide por defecto lo que mida su contenido:
       con once módulos en fila, la tira empujaba el ancho del documento a
       615 px y Switch Control se movía de lado en el móvil, con la barra de
       transición saliéndose por la derecha. */
    .cb-work > * { min-width: 0; }
    .cb-rail-mod, .cb-stage { min-width: 0; max-width: 100%; }
}

/* ── Deshacer la moderación del chat ─────────────────────────────────
   Ocultar y bloquear son de un clic; poder volver atrás tenía que estar
   igual de a mano, sin sacar al operador del módulo de chat.            */
.cb-modact {
    display: flex;
    gap: 6px;
    margin-top: 8px;
}
.cb-oculto {
    margin-top: 8px;
    max-height: 300px;
    overflow-y: auto;
    border-top: 1px solid var(--cb-border);
    padding-top: 8px;
}
.cb-oculto-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 8px;
    font-size: var(--cb-t2);
    color: var(--cb-dim);
}
.cb-msg-oculto {
    opacity: .72;
}
.cb-msg-oculto .cb-msg-txt {
    text-decoration: line-through;
    text-decoration-color: rgba(148, 163, 184, .5);
}

/* ── Destinos: dónde va a salir esto ─────────────────────────────────── */
.cb-dest-resumen {
    margin: 0 0 10px;
    padding: 9px 11px;
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r2);
    background: rgba(148, 163, 184, .06);
    font-size: var(--cb-t3);
    line-height: 1.5;
}
.cb-dest-resumen-mal {
    border-color: rgba(251, 191, 36, .55);
    background: rgba(251, 191, 36, .09);
}
.cb-dest-aviso { color: #fbbf24; }
.cb-dest-mal { border-color: rgba(251, 191, 36, .4); }

/* Las redes que aún no están, para darlas de alta de un clic. Va lo primero
   del módulo: dar de alta YouTube es lo que viene a hacer aquí quien abre
   esto por primera vez, y estaba escondido detrás de un «+ Añadir destino»
   que pedía inventarse un nombre y pegar una dirección a mano. */
.cb-dest-redes {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cb-e3);
    margin: 0 0 var(--cb-e4);
}
.cb-dest-redes .cb-note { flex: 0 0 auto; }

/* De dónde sale la clave de esta plataforma. Es letra pequeña porque se lee
   una vez —la primera— y después estorba. */
.cb-dest-ayuda {
    margin: var(--cb-e3) 0 0;
    padding-left: var(--cb-e3);
    border-left: 2px solid var(--cb-border-2);
}
.cb-dest-falta {
    background: rgba(251, 191, 36, .16);
    color: #fbbf24;
    border: 1px solid rgba(251, 191, 36, .4);
}

/* ═══════════════════════════════════════════════════════════════════════
   EL CAMBIO DE MÓDULO
   ═══════════════════════════════════════════════════════════════════════

   Esta es la costura que más se nota de todo Switch Control: el operador salta de
   Gráficas a Imágenes a Invitados decenas de veces por programa, y el cajón
   cambiaba de contenido de un fotograma al siguiente, en seco. No parecía
   rápido: parecía roto.

   El guion no avisa de nada —mueve el panel del módulo dentro del cajón y ya
   está—, así que no hay ningún evento del que colgarse. Pero no hace falta:
   un elemento que pasa de no estar pintado a estarlo ARRANCA sus animaciones
   solo, y eso es exactamente lo que le ocurre a cada panel al entrar en el
   cajón. Basta con dejar la animación escrita aquí para que se ejecute en
   cada cambio, sin tocar una línea de guion.

   La coreografía es la de siempre en un aparato bien hecho: primero se mueve
   el bloque —que es la forma, y el ojo la lee antes que nada—, y detrás
   entran sus piezas con un retraso mínimo y decreciente, como una cinta que
   se estira y se asienta. */

.cb-cajon-cuerpo > .cb-dockpane {
    animation: cb-mod-desliza var(--cb-mov-4) var(--cb-firme) both,
               cb-mod-aparece 170ms var(--cb-sal) both;
}

@keyframes cb-mod-desliza {
    from { transform: translate3d(26px, 0, 0); }
    to   { transform: none; }
}

@keyframes cb-mod-aparece {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Las piezas de dentro suben, no entran de lado: dos ejes distintos hacen
   que el módulo se lea como una cosa que se abre y no como una diapositiva
   que se desliza. */
.cb-cajon-cuerpo .cb-dockpane > .cb-panel > *,
.cb-cajon-cuerpo .cb-dockpane > *:not(.cb-panel) {
    animation: cb-mod-hijo 280ms var(--cb-firme) both;
}

@keyframes cb-mod-hijo {
    from { opacity: 0; transform: translate3d(0, 10px, 0); }
    to   { opacity: 1; transform: none; }
}

/* El retraso crece cada vez menos. Repartido a partes iguales el escalonado
   se lee como lentitud; frenando, se lee como peso. Del séptimo en adelante
   ya no se escalona: eso está debajo del pliegue y esperar por nada es lo
   único que en una mesa en vivo no se perdona. */
.cb-cajon-cuerpo .cb-dockpane > .cb-panel > *:nth-child(1),
.cb-cajon-cuerpo .cb-dockpane > *:not(.cb-panel):nth-child(1) { animation-delay: 40ms; }
.cb-cajon-cuerpo .cb-dockpane > .cb-panel > *:nth-child(2),
.cb-cajon-cuerpo .cb-dockpane > *:not(.cb-panel):nth-child(2) { animation-delay: 75ms; }
.cb-cajon-cuerpo .cb-dockpane > .cb-panel > *:nth-child(3),
.cb-cajon-cuerpo .cb-dockpane > *:not(.cb-panel):nth-child(3) { animation-delay: 105ms; }
.cb-cajon-cuerpo .cb-dockpane > .cb-panel > *:nth-child(4),
.cb-cajon-cuerpo .cb-dockpane > *:not(.cb-panel):nth-child(4) { animation-delay: 128ms; }
.cb-cajon-cuerpo .cb-dockpane > .cb-panel > *:nth-child(5),
.cb-cajon-cuerpo .cb-dockpane > *:not(.cb-panel):nth-child(5) { animation-delay: 146ms; }
.cb-cajon-cuerpo .cb-dockpane > .cb-panel > *:nth-child(n+6),
.cb-cajon-cuerpo .cb-dockpane > *:not(.cb-panel):nth-child(n+6) { animation-delay: 160ms; }

/* ── El rail cuando va en fila ────────────────────────────────────────────
   En pantalla estrecha los once módulos pasan a ser una fila de pestañas, y
   una barra vertical al costado de una pestaña no significa nada: se pone
   debajo, que es donde el ojo la espera. */

@media (max-width: 1100px) {
    .cb-cajon-rail .cb-mod {
        background-position: 50% 100%;
        background-size: 0% 3px;
    }

    .cb-cajon-rail .cb-mod-on {
        background-size: 62% 3px;
        animation: cb-mod-marca-fila var(--cb-mov-4) var(--cb-resorte) both,
                   cb-mod-fondo var(--cb-mov-2) var(--cb-sal) both;
    }
}

@media (max-width: 820px) {
    .cb-rail-mod .cb-mod {
        background-position: 50% 100%;
        background-size: 0% 3px;
    }

    .cb-rail-mod .cb-mod-on {
        background-size: 62% 3px;
        animation: cb-mod-marca-fila var(--cb-mov-4) var(--cb-resorte) both,
                   cb-mod-fondo var(--cb-mov-2) var(--cb-sal) both;
    }
}

@keyframes cb-mod-marca-fila {
    from { background-size: 0% 3px; }
    to   { background-size: 62% 3px; }
}

/* ── Lo que se toca ──────────────────────────────────────────────────────
   Cuatro estados y los cuatro tienen que verse: encima, con el foco puesto,
   hundido y apagado. Antes solo existía «encima», y quien opera con teclado
   —porque tiene las dos manos en la mesa de sonido— no sabía dónde estaba
   parado. */

.cb-mod:focus-visible,
.cb-tog:focus-visible,
.cb-preset-fire:focus-visible,
.cb-preset-del:focus-visible,
.cb-ic-tab:focus-visible,
.cb-gv-ojo:focus-visible,
.cb-color:focus-visible,
.cb-esc:focus-visible {
    outline: 2px solid var(--cb-foco);
    outline-offset: 2px;
}

/* El botón rojo del aire lleva el anillo en blanco: sobre rojo, el índigo
   del foco no se ve, y ese es justo el botón en el que hay que estar seguro
   de dónde se tiene el dedo. */
.cb-btn-danger:focus-visible,
.cb-btn-al-aire:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* Los deslizadores de volumen también se manejan con el teclado. */
.cb-gv-vol input:focus-visible {
    outline: 2px solid var(--cb-foco);
    outline-offset: 3px;
    border-radius: var(--cb-rp);
}

/* Nada de quitar el contorno al hacer clic con el ratón, pero tampoco
   dejarlo pegado en un botón que ya se soltó. */
:focus:not(:focus-visible) { outline: none; }

/* ── Las barras de desplazamiento ────────────────────────────────────────
   Media pantalla se desliza por dentro —el chat, el banco de escenas, el
   cajón, el registro del relay—. La barra gris de fábrica es una franja
   clara en una pantalla oscura, y a media luz se ve más que su contenido. */

.cb-chat, .cb-ic-log, .cb-em-log, .cb-presets, .cb-oculto,
.cb-rail-esc, .cb-cajon-cuerpo, .cb-cajon-rail, #cbHistory {
    scrollbar-width: thin;
    scrollbar-color: #38445a transparent;
}

.cb-chat::-webkit-scrollbar,
.cb-ic-log::-webkit-scrollbar,
.cb-em-log::-webkit-scrollbar,
.cb-presets::-webkit-scrollbar,
.cb-oculto::-webkit-scrollbar,
.cb-rail-esc::-webkit-scrollbar,
.cb-cajon-cuerpo::-webkit-scrollbar,
.cb-cajon-rail::-webkit-scrollbar,
#cbHistory::-webkit-scrollbar { width: 9px; height: 9px; }

.cb-chat::-webkit-scrollbar-thumb,
.cb-ic-log::-webkit-scrollbar-thumb,
.cb-em-log::-webkit-scrollbar-thumb,
.cb-presets::-webkit-scrollbar-thumb,
.cb-oculto::-webkit-scrollbar-thumb,
.cb-rail-esc::-webkit-scrollbar-thumb,
.cb-cajon-cuerpo::-webkit-scrollbar-thumb,
.cb-cajon-rail::-webkit-scrollbar-thumb,
#cbHistory::-webkit-scrollbar-thumb {
    background: #303c4f;
    border-radius: var(--cb-rp);
    border: 2px solid transparent;
    background-clip: padding-box;
}

.cb-chat::-webkit-scrollbar-thumb:hover,
.cb-ic-log::-webkit-scrollbar-thumb:hover,
.cb-rail-esc::-webkit-scrollbar-thumb:hover,
.cb-cajon-cuerpo::-webkit-scrollbar-thumb:hover { background: #47566f; background-clip: padding-box; }

.cb-chat::-webkit-scrollbar-track,
.cb-ic-log::-webkit-scrollbar-track,
.cb-em-log::-webkit-scrollbar-track,
.cb-presets::-webkit-scrollbar-track,
.cb-oculto::-webkit-scrollbar-track,
.cb-rail-esc::-webkit-scrollbar-track,
.cb-cajon-cuerpo::-webkit-scrollbar-track,
.cb-cajon-rail::-webkit-scrollbar-track,
#cbHistory::-webkit-scrollbar-track { background: transparent; }

/* ── Sin movimiento ──────────────────────────────────────────────────────
   Quien pide al sistema que no le muevan la pantalla lo pide por algo, y
   aquí hay latidos, barras que crecen y un cajón que entra deslizándose.
   Se apaga TODO de una vez, incluido lo que se añada mañana: dejando las
   animaciones en una duración inapreciable en vez de quitarlas, el estado
   final se sigue aplicando y nada se queda invisible a medio camino. */

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 1ms !important;
        animation-delay: 0ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 1ms !important;
        transition-delay: 0ms !important;
        scroll-behavior: auto !important;
    }
}

/* ── La botonera del monitor ─────────────────────────────────────────────
   Dos filas debajo de la pantalla: arriba CÓMO se reparte la pantalla,
   abajo QUÉ entra y por dónde se oye. Antes esos mandos estaban repartidos
   por media pantalla: unos en el titular del panel, los repartos sueltos
   debajo de la mesa, la salida de sonido en ninguna parte —porque no
   existía— y cuatro más en una barra aparte al pie del escenario.

   Es la forma de una mesa de verdad: los repartos se miran, los mandos se
   tocan. Por eso arriba van dibujos y abajo van botones redondos, todos
   del mismo tamaño y a la misma altura: la mano los encuentra sin mirar,
   que es como se opera con la vista puesta en el monitor.                */
.cb-monbar {
    display: flex;
    flex-direction: column;
    gap: var(--cb-e4);
    margin-top: var(--cb-e3);
    padding: var(--cb-e4);
    background: var(--cb-hueco);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r3);
    box-shadow: var(--cb-filo);
}

.cb-monbar-fila {
    display: flex;
    align-items: center;
    /* Centradas: es donde cae la mano al soltar el ratón mirando la
       pantalla, y donde el ojo vuelve después de mirar el monitor. */
    justify-content: center;
    gap: var(--cb-e3);
}

/* Los repartos se deslizan si no caben; nunca se parten en dos renglones,
   porque media tira de esquemas no se lee como una tira. */
.cb-monbar-repartos {
    /* Centrados si caben, pegados a la izquierda si no.
       `center` a secas y desbordando deja el primer esquema fuera y sin
       forma de llegar a el: el deslizador no puede ir a negativo. Los
       navegadores que no entiendan `safe` se quedan con flex-start, que es
       feo pero alcanzable. */
    justify-content: flex-start;
    justify-content: safe center;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
    /* Sitio para el aro del reparto puesto y para el anillo de foco: sin
       esto el deslizador los recorta por arriba y por abajo. */
    padding: 4px;
    margin: -4px;
}

/* Los mandos se reparten en dos renglones si no caben, y NO se deslizan:
   sus menús se abren por encima, y un contenedor que se desliza los
   recortaría justo cuando hay que elegir el micrófono. */
.cb-monbar-mandos {
    flex-wrap: wrap;
    gap: var(--cb-e4);
}

/* La raya que separa los repartos de la forma del cuadro. Son dos cosas
   distintas: una decide cómo se colocan las cámaras dentro del cuadro, la
   otra qué forma tiene el cuadro. */
.cb-monbar-raya {
    flex: 0 0 auto;
    width: 1px;
    height: 26px;
    background: var(--cb-border);
    margin: 0 var(--cb-e1);
}

/* ── Los mandos redondos ──────────────────────────────────────────────── */

/* La pastilla que junta el círculo con su flecha. Van dentro de la misma
   pieza a propósito: abrir el micrófono y elegir cuál es el mismo mando
   visto de dos maneras, no dos mandos. */
.cb-rb-par {
    position: relative;
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    background: var(--cb-panel);
    border-radius: var(--cb-rp);
}

/* Los que no llevan flecha no necesitan pastilla: el círculo se basta. */
.cb-rb-par-solo { background: transparent; }

.cb-rb {
    position: relative;   /* ancla su rótulo escondido; ver .cb-lays-mon .cb-tog */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 46px;
    height: 46px;
    padding: 0;
    background: var(--cb-panel-2);
    border: 1px solid transparent;
    border-radius: 50%;
    color: var(--cb-text);
    font-family: inherit;
    cursor: pointer;
    box-shadow: var(--cb-filo);
    transition: background-color var(--cb-mov-2) var(--cb-amb),
                border-color var(--cb-mov-2) var(--cb-amb),
                color var(--cb-mov-1) var(--cb-amb),
                transform var(--cb-mov-2) var(--cb-sal);
}

.cb-rb-ic { font-size: 21px; }

.cb-rb:hover:not(:disabled)  { background-color: var(--cb-panel-3); }
.cb-rb:active:not(:disabled) { transform: scale(.94); transition-duration: 60ms; }
.cb-rb:disabled { opacity: .45; cursor: default; }

/* Los ajustes, un paso apartados del resto: no se tocan en directo y no
   deben estar donde está la mano. */
.cb-rb-fin { margin-left: var(--cb-e4); }

/* Grabando: un punto rojo en la tuerca.
   El reloj y el estado de la grabación viven dentro de la ventana de
   Ajustes, así que cerrarla dejaba la mesa sin ninguna señal de que se
   estaba grabando. Esto es lo único que se ve con la ventana cerrada. */
.cb-rb-grabando::after {
    content: '';
    position: absolute;
    top: 2px;
    right: 2px;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--cb-aire);
    border: 2px solid var(--cb-panel);
    animation: cb-grabando 1.6s var(--cb-amb) infinite;
}

@keyframes cb-grabando {
    0%, 100% { opacity: 1; }
    50%      { opacity: .35; }
}

/* ── AL AIRE ─────────────────────────────────────────────────────────────
   Lo único irreversible de la mesa, y el botón más grande y más luminoso de
   la botonera. Tiene que seguir siéndolo aunque la fila se llene: por eso no
   es redondo como los demás, va separado del último y no se encoge.

   Vive aquí desde que se quitó la barra de transición: sin él, sacar algo al
   aire dependía de un atajo de teclado que viene apagado de fábrica. */
.cb-alaire {
    flex: 0 0 auto;
    margin-left: auto;          /* al extremo, lejos del resto de la mano */
    min-height: 44px;
    padding: 0 22px;
    border-radius: var(--cb-r3);
    border: 1px solid transparent;
    font: inherit;
    font-size: var(--cb-t3);
    font-weight: 800;
    letter-spacing: .05em;
    cursor: pointer;
    color: var(--cb-dim-2);
    background: var(--cb-panel-2);
    border-color: var(--cb-border);
    transition: background-color var(--cb-mov-2) var(--cb-amb),
                color var(--cb-mov-2) var(--cb-amb),
                box-shadow var(--cb-mov-3) var(--cb-amb);
}

/* Hay algo preparado que todavía no sale. */
.cb-alaire-listo {
    color: #fff;
    background: var(--cb-aire);
    border-color: transparent;
    box-shadow: 0 3px 14px rgba(240, 71, 71, .38), inset 0 1px 0 rgba(255, 255, 255, .2);
}

.cb-alaire-listo:hover {
    background: #f45c5c;
    box-shadow: 0 6px 22px rgba(240, 71, 71, .55), inset 0 1px 0 rgba(255, 255, 255, .26);
}

/* Apagado es GRIS, no rojo pálido: un rojo al 40% se sigue leyendo como rojo
   desde el otro lado del estudio y haría creer que hay algo listo. */
.cb-alaire:disabled {
    cursor: default;
    opacity: 1;
    color: var(--cb-dim-2);
    background: var(--cb-panel-2);
    border-color: var(--cb-border);
    box-shadow: none;
}

/* Sobre rojo, el anillo índigo del foco no se ve, y este es justo el botón
   en el que hay que estar seguro de dónde se tiene el dedo. */
.cb-alaire:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* La flecha, pegada al círculo dentro de la pastilla. */
.cb-rb-fl {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 30px;
    height: 46px;
    padding: 0 4px 0 0;
    background: transparent;
    border: 0;
    border-radius: 0 var(--cb-rp) var(--cb-rp) 0;
    color: var(--cb-dim);
    cursor: pointer;
    transition: background-color var(--cb-mov-2) var(--cb-amb),
                color var(--cb-mov-1) var(--cb-amb);
}

.cb-rb-fl:hover { background-color: var(--cb-panel-2); color: var(--cb-text); }
.cb-rb-ch { font-size: 15px; }

/* Cerrado: el mismo dibujo con una barra encima. La barra no sobra al lado
   del rojo: de lejos una barra se ve, y un tono de fondo hay quien no lo
   distingue. */
.cb-rb-tacha { opacity: 0; transition: opacity var(--cb-mov-1) var(--cb-amb); }
.cb-rb-off .cb-rb-tacha { opacity: 1; }

.cb-rb-off {
    background-color: rgba(239, 68, 68, .16);
    border-color: rgba(239, 68, 68, .42);
    color: #fca5a5;
}

.cb-rb-off:hover:not(:disabled) { background-color: rgba(239, 68, 68, .24); }

/* Apagada del todo no es lo mismo que cerrada: todavía no hay nada que
   cortar, así que no grita en rojo. Aquí el círculo invita a encenderla.
   Va DESPUÉS de cb-rb-off a propósito: los dos estados conviven en el
   botón y este es el que manda. */
.cb-rb-apagado {
    background-color: var(--cb-panel-2);
    border-color: var(--cb-border);
    color: var(--cb-dim);
}

.cb-rb-apagado:hover:not(:disabled) {
    background-color: var(--cb-panel-3);
    color: var(--cb-text);
}

/* Un mando que vive dentro de un menú no se puede llevar su estado dentro
   con él. El punto rojo dice que ahí abajo hay algo cortado; el porqué lo
   cuenta con palabras la línea de la botonera. */
.cb-rb-par-alerta::after {
    content: '';
    position: absolute;
    top: 1px;
    right: 3px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--cb-aire);
    box-shadow: 0 0 0 2px var(--cb-hueco);
    pointer-events: none;
}

/* Encendido y haciendo algo: compartiendo pantalla, o sonando. */
.cb-rb-on {
    background-color: rgba(99, 102, 241, .24);
    border-color: rgba(99, 102, 241, .55);
    color: #fff;
}

.cb-rb-on:hover:not(:disabled) { background-color: rgba(99, 102, 241, .32); }

/* ── Los menús de la botonera ─────────────────────────────────────────────
   Se abren hacia ARRIBA, encima de la pantalla: debajo de la botonera está
   la transición, y un menú tapando el botón de AL AIRE es una forma
   estupenda de sacar algo sin querer.                                    */
.cb-menu {
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%);
    z-index: 40;
    width: max-content;
    min-width: 208px;
    /* Nunca más ancho que la pantalla: en un teléfono de 320 px un menú de
       300 px con sus márgenes ya no cabía. */
    max-width: min(300px, calc(100vw - 24px));
    padding: var(--cb-e3);
    text-align: left;
    background: var(--cb-panel);
    border: 1px solid var(--cb-border-2);
    border-radius: var(--cb-r3);
    box-shadow: var(--cb-som-2);
}

.cb-menu-ancho { min-width: 248px; }

.cb-menu-tit {
    margin: 2px 8px 6px;
    font-size: var(--cb-t0);
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--cb-dim-2);
}

.cb-menu-tit-2 {
    margin-top: var(--cb-e4);
    padding-top: var(--cb-e3);
    border-top: 1px solid var(--cb-border);
}

/* Con seis micrófonos enchufados la lista no puede empujar el menú fuera
   de la pantalla. */
.cb-menu-lista {
    display: flex;
    flex-direction: column;
    max-height: 240px;
    overflow-y: auto;
    scrollbar-width: thin;
}

.cb-menu-op {
    display: flex;
    align-items: center;
    gap: var(--cb-e3);
    width: 100%;
    padding: 9px 10px;
    background: transparent;
    border: 0;
    border-radius: var(--cb-r2);
    color: var(--cb-dim);
    font-family: inherit;
    font-size: var(--cb-t3);
    text-align: left;
    cursor: pointer;
    transition: background-color var(--cb-mov-1) var(--cb-amb),
                color var(--cb-mov-1) var(--cb-amb);
}

.cb-menu-op:hover { background: var(--cb-panel-2); color: var(--cb-text); }
.cb-menu-op-on { color: var(--cb-text); font-weight: 600; }
.cb-menu-op > .ic { font-size: 1.3em; }

/* El aparato puesto lleva su punto; los demás dejan el hueco, o la lista
   entera se movería de sitio cada vez que se cambia de micrófono. */
.cb-menu-tic {
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #3f4a5c;
    transition: background-color var(--cb-mov-1) var(--cb-amb),
                box-shadow var(--cb-mov-3) var(--cb-resorte);
}

.cb-menu-op-on .cb-menu-tic {
    background: var(--cb-ok);
    box-shadow: 0 0 0 3px rgba(34, 197, 94, .2);
}

.cb-menu-nota {
    margin: 0;
    padding: 4px 10px 6px;
    font-size: var(--cb-t2);
    line-height: 1.5;
    color: var(--cb-dim-2);
}

/* Dentro del menú los campos ocupan el ancho: el menú ya decidió lo ancho
   que es, y un desplegable a medias parece roto. */
.cb-menu-sel,
.cb-menu-btn {
    width: 100%;
    max-width: none;
}

.cb-menu-btn { justify-content: center; }

/* El pie del menú: lo que no es elegir un aparato sino hacer algo con él. */
.cb-menu-pie {
    display: flex;
    flex-direction: column;
    gap: var(--cb-e2);
    margin-top: var(--cb-e3);
    padding-top: var(--cb-e3);
    border-top: 1px solid var(--cb-border);
}

.cb-input-xs {
    padding: 5px 8px;
    font-size: var(--cb-t2);
    max-width: 168px;
    border-radius: var(--cb-r1);
}

/* Lo que dice la botonera cuando algo sale bien o sale mal. Va dentro de
   ella y no en la nota de abajo: quien acaba de pulsar un redondo mira el
   redondo, no el pie del panel. */
.cb-monbar-aviso {
    margin: 0;
    padding-top: var(--cb-e1);
    font-size: var(--cb-t2);
    line-height: 1.45;
    text-align: center;
    color: var(--cb-dim);
}

.cb-monbar-aviso-mal   { color: #fca5a5; font-weight: 600; }
.cb-monbar-aviso-medio { color: #fcd34d; font-weight: 600; }

/* Vacío no ocupa: sin esto la botonera crecería un renglón para no decir
   nada, y el monitor de encima se encogería con él. */
.cb-monbar-aviso:empty { display: none; }

/* ── Los repartos, dibujados ───────────────────────────────────────────── */

.cb-lays-mon {
    display: flex;
    flex-wrap: nowrap;
    gap: var(--cb-e2);
    margin: 0;
    flex: 0 0 auto;
}

/* Aquí el interruptor de las gráficas se queda sin caja: lo que se ve es el
   esquema, y una caja alrededor de un esquema son dos rectángulos
   discutiendo por el mismo sitio. */
.cb-lays-mon .cb-tog {
    /* Posicionado para que su rótulo escondido —que va absoluto— se ancle
       AQUÍ. Sin esto se anclaba fuera de la fila que se desliza, escapaba
       del recorte y ensanchaba la página entera en un móvil: un píxel
       invisible empujando la barra de desplazamiento horizontal. */
    position: relative;
    gap: 0;
    min-height: 0;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: var(--cb-r1);
    box-shadow: none;
}

.cb-lays-mon .cb-tog:hover,
.cb-lays-mon .cb-tog-on { background: transparent; border-color: transparent; }

/* Con una sola fuente el reparto no decide nada. Se siguen viendo, apagados
   y en su sitio: esconderlos encogería la barra entera cada vez que entra o
   sale alguien del previo. */
.cb-lays-mon .cb-tog:disabled { opacity: .38; cursor: default; }
.cb-lays-mon .cb-tog:disabled:active { transform: none; }

/* El esquema: la pantalla en pequeño, con los cuadros donde irían. */
.cb-esq {
    position: relative;
    display: block;
    width: 46px;
    height: 27px;
    border-radius: 5px;
    background: var(--cb-panel-2);
    transition: background-color var(--cb-mov-2) var(--cb-amb),
                box-shadow var(--cb-mov-2) var(--cb-amb);
}

.cb-tog:hover .cb-esq { background: var(--cb-panel-3); }

.cb-esq i {
    position: absolute;
    background: #4b586d;
    border-radius: 2px;
    transition: background-color var(--cb-mov-1) var(--cb-amb);
}

/* El puesto lleva un aro, no un color de fondo: el fondo es la pantalla, y
   teñirla haría creer que el reparto pinta algo encima. */
.cb-tog-on .cb-esq {
    background: var(--cb-panel-3);
    box-shadow: 0 0 0 2px var(--cb-hueco), 0 0 0 4px var(--cb-accent);
}

.cb-tog-on .cb-esq i { background: #aeb9cc; }

/* Cuadro de 46×27 con 3 px de margen: 40×21 de pantalla útil. Las medidas
   son las mismas que usa el overlay, en pequeño. */
.cb-esq-mosaico i:nth-child(1) { left: 3px;    top: 3px;  width: 18.5px; height: 9px; }
.cb-esq-mosaico i:nth-child(2) { left: 24.5px; top: 3px;  width: 18.5px; height: 9px; }
.cb-esq-mosaico i:nth-child(3) { left: 3px;    top: 15px; width: 18.5px; height: 9px; }
.cb-esq-mosaico i:nth-child(4) { left: 24.5px; top: 15px; width: 18.5px; height: 9px; }

.cb-esq-lado i:nth-child(1) { left: 3px;     top: 5px; width: 11.3px; height: 17px; }
.cb-esq-lado i:nth-child(2) { left: 17.3px;  top: 5px; width: 11.3px; height: 17px; }
.cb-esq-lado i:nth-child(3) { left: 31.7px;  top: 5px; width: 11.3px; height: 17px; }

.cb-esq-destacado i:nth-child(1) { left: 3px;  top: 5px;  width: 23px; height: 17px; }
.cb-esq-destacado i:nth-child(2) { left: 29px; top: 5px;  width: 14px; height: 8px; }
.cb-esq-destacado i:nth-child(3) { left: 29px; top: 14px; width: 14px; height: 8px; }

.cb-esq-ventana i:nth-child(1) { left: 3px;  top: 3px;  width: 40px; height: 21px; }
.cb-esq-ventana i:nth-child(2) {
    left: 27px;
    top: 13px;
    width: 14px;
    height: 9px;
    background: var(--cb-panel-2);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, .28);
}

.cb-tog-on .cb-esq-ventana i:nth-child(2) { background: var(--cb-panel-3); }

/* Libre: los dos cuadros a su aire y con el borde de puntos que llevan las
   asas dentro del monitor. Es el mismo dibujo, en pequeño. */
.cb-esq-libre i:nth-child(1) { left: 4px;  top: 4px;  width: 22px; height: 12px; }
.cb-esq-libre i:nth-child(2) {
    left: 21px;
    top: 12px;
    width: 21px;
    height: 11px;
    background: var(--cb-panel-2);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, .34);
}

.cb-tog-on .cb-esq-libre i:nth-child(2) { background: var(--cb-panel-3); }

/* La forma del cuadro: aquí el esquema es el cuadro mismo. */
.cb-esq-apaisado i { left: 5px;  top: 5.5px; width: 36px; height: 16px; }
.cb-esq-vertical i { left: 17px; top: 2px;   width: 12px; height: 23px; }

/* ── Qué mira el monitor, en su cabecera ──────────────────────────────────
   No está en la botonera a propósito: la botonera decide lo que SALE, y
   esto solo decide lo que se mira. Mezclarlos hacía dudar de si «Aire» era
   un botón de emitir.

   Separarlos no bastó: el botón se llamaba «Aire» y enseñaba el bus de
   programa, que puede estar lleno sin que salga nada. Ahora se llama
   «Programa» y a su lado va el piloto, que es quien contesta lo otro.      */
.cb-monhead {
    display: flex;
    align-items: center;
    gap: var(--cb-e3);
    flex: 0 0 auto;
}

.cb-monhead-seg { display: flex; gap: var(--cb-e1); }

/* El piloto de emisión, a la izquierda de los dos botones.
   Va en la cabecera y no en la botonera por la misma razón que ellos: no es
   un mando, no se pulsa. Es el único sitio de la pantalla que responde a
   «¿esto está saliendo?», y tiene que estar donde se mira, que es el
   monitor.
   Píldora y no punto suelto: el punto solo obliga a recordar de qué color
   era el bueno, y el rótulo lo dice con palabras. */
.cb-monlive {
    display: inline-flex;
    align-items: center;
    gap: var(--cb-e2);
    padding: 3px var(--cb-e3);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-rp);
    font-size: var(--cb-t1);
    font-weight: 800;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--cb-dim-2);
    white-space: nowrap;
    transition: color var(--cb-mov-2) var(--cb-amb),
                border-color var(--cb-mov-2) var(--cb-amb),
                background-color var(--cb-mov-2) var(--cb-amb);
}

.cb-monlive-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: currentColor;
    flex: 0 0 auto;
}

/* Saliendo. El rojo del aire y el mismo latido que el piloto de la emisión
   registrada: en una mesa, «al aire» tiene un solo color y un solo pulso, o
   deja de significar algo. */
.cb-monlive[data-est="on"] {
    color: var(--cb-aire);
    border-color: rgba(240, 71, 71, .45);
    background: rgba(240, 71, 71, .1);
}

.cb-monlive[data-est="on"] .cb-monlive-dot {
    animation: cb-pulse var(--cb-latido) var(--cb-amb) infinite;
}

/* Comprobado y no sale. Ámbar y no rojo: es el color de «listo para salir»,
   que es exactamente el estado —la mesa está compuesta, sólo falta emitir—.
   En rojo se leería como avería. */
.cb-monlive[data-est="off"] {
    color: var(--cb-prev);
    border-color: rgba(245, 158, 11, .35);
}

/* Sin comprobar se queda en gris apagado a propósito: no afirma nada, y
   nada de la pantalla debe pesar como los otros dos. */

@media (prefers-reduced-motion: reduce) {
    .cb-monlive[data-est="on"] .cb-monlive-dot { animation: none; }
}

/* ── En pantallas estrechas ─────────────────────────────────────────────── */

@media (max-width: 820px) {
    .cb-monbar { padding: var(--cb-e3); gap: var(--cb-e3); }
    .cb-monbar-mandos { gap: var(--cb-e3); }
    .cb-rb    { width: 42px; height: 42px; }
    .cb-rb-fl { width: 26px; height: 42px; }
    .cb-rb-fin { margin-left: 0; }
}

/* Un menú anclado a su botón puede salirse de la pantalla por un lado: el
   primer mando y el último quedan cerca del borde en una columna estrecha.
   Quien lo corre lo justo para que quepa es `menuColocar()` en el guion, y
   lo hace en TODOS los anchos, no solo por debajo de un número: entre una
   cosa y la otra siempre hay una ventana donde el apaño no llegaba. */

/* ── Colocar los cuadros a mano dentro del monitor ───────────────────────
   Solo existe en el reparto libre y mirando el previo. Va ENCIMA del
   monitor y no dentro: el monitor es el mismo overlay que captura el
   encoder, y meterle asas dentro seria meterlas en lo que sale al aire.  */
.cb-moncapa {
    position: absolute;
    /* El hueco exacto lo mide el guion contra el overlay: no es todo el
       monitor, porque el aire deja su margen de seguridad. Esto es solo el
       punto de partida hasta que hay algo que medir. */
    inset: 0;
    z-index: 3;
    /* La capa no estorba: solo atrapan el dedo los cuadros. */
    pointer-events: none;
}

.cb-mov {
    position: absolute;
    aspect-ratio: 16 / 9;
    pointer-events: auto;
    cursor: grab;
    border: 1.5px dashed rgba(255, 255, 255, .32);
    border-radius: var(--cb-r1);
    background: rgba(129, 140, 248, .05);
    transition: border-color var(--cb-mov-1) var(--cb-sal),
                background var(--cb-mov-1) var(--cb-sal),
                box-shadow var(--cb-mov-1) var(--cb-sal);
    /* Que no se seleccione el nombre al arrastrar, ni salte el menú del
       teléfono al dejar el dedo puesto. */
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
}

.cb-monitor-vert .cb-mov { aspect-ratio: 16 / 9; }

.cb-mov:hover {
    border-color: var(--cb-foco);
    background: rgba(129, 140, 248, .12);
}

.cb-mov-cogido {
    cursor: grabbing;
    border-style: solid;
    border-color: var(--cb-foco);
    background: rgba(129, 140, 248, .18);
    box-shadow: 0 10px 30px -12px rgba(0, 0, 0, .8);
}

/* El asa de mover, arriba a la izquierda: es el icono que se pincha. */
.cb-mov-asa,
.cb-mov-quitar,
.cb-mov-tam {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    padding: 0;
    font-size: 15px;
    color: var(--cb-text);
    background: rgba(8, 11, 18, .82);
    border: 1px solid rgba(255, 255, 255, .18);
    border-radius: var(--cb-r1);
    cursor: inherit;
    backdrop-filter: blur(6px);
}

.cb-mov-asa { top: 5px; left: 5px; }
.cb-mov-tam { right: 3px; bottom: 3px; cursor: nwse-resize; }

/* Quitar va arriba a la DERECHA y en rojo al pasar por encima: es la esquina
   donde todo el mundo busca una cruz, y la lejanía con el asa de mover —la
   otra esquina— es lo que evita quitar un cuadro creyendo que se agarraba.
   El puntero vuelve a ser flecha: dentro del cuadro todo dice «arrástrame», y
   esto es lo único que no se arrastra. */
.cb-mov-quitar { top: 5px; right: 5px; cursor: pointer; }

.cb-mov-asa:hover,
.cb-mov-tam:hover { border-color: var(--cb-foco); }

.cb-mov-quitar:hover {
    border-color: var(--cb-danger);
    background: rgba(240, 71, 71, .85);
}

/* De quién es el cuadro. Sin esto, con tres cámaras iguales en negro no hay
   forma de saber cuál se está moviendo. */
.cb-mov-nom {
    position: absolute;
    top: 7px;
    left: 37px;
    /* Deja sitio a las dos esquinas de arriba: el asa a la izquierda y la
       cruz a la derecha. Con el hueco de antes el nombre se metía debajo de
       la cruz en cuanto el cuadro se hacía pequeño. */
    max-width: calc(100% - 80px);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--cb-t1);
    font-weight: 700;
    color: var(--cb-text);
    text-shadow: 0 1px 3px rgba(0, 0, 0, .9);
}

/* En cuadros pequeños no cabe el nombre y estorba más que ayuda. */
@container (max-width: 180px) {
    .cb-mov-nom { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    .cb-mov { transition: none; }
}

/* ── ¿Te oyen los invitados? ─────────────────────────────────────────────
   Un aviso que solo aparece cuando tiene algo que decir. Tres colores, y
   el orden importa: rojo es "no te oye nadie", ámbar es "alguno sí y
   alguno no", verde es "te oyen". El verde es el único que se puede
   ignorar de reojo, y por eso es el más callado.                        */
.cb-retorno {
    margin: var(--cb-e3) 0 0;
    padding: 8px 11px;
    border: 1px solid var(--cb-border);
    border-left-width: 3px;
    border-radius: var(--cb-r1);
    font-size: var(--cb-t2);
    line-height: 1.45;
    color: var(--cb-text);
    background: rgba(148, 163, 184, .06);
}

.cb-retorno-bien {
    border-left-color: #22c55e;
    color: var(--cb-dim);
    background: rgba(34, 197, 94, .07);
}

.cb-retorno-medio {
    border-left-color: #fbbf24;
    background: rgba(251, 191, 36, .09);
}

.cb-retorno-mal {
    border-left-color: var(--cb-aire, #ef4444);
    background: rgba(239, 68, 68, .1);
    font-weight: 600;
}


/* ══ La ventana de Ajustes ═══════════════════════════════════════════════
   La tuerca de la botonera abre esto. Es una ventana CENTRADA y con el
   fondo oscurecido, al revés que el cajón de módulos: los módulos se tocan
   mientras se conduce y por eso el cajón deja la mesa a la vista, pero los
   ajustes se tocan ANTES de empezar. Aquí sí conviene que nada más pida
   atención, y por eso el clic fuera cierra.

   Vive siempre en el árbol, aunque esté escondida: media pantalla se repinta
   sola cada cuatro segundos buscando sus elementos por id, y el panel de
   Aspecto se mudó aquí dentro.                                          */

.cb-ajustes {
    position: fixed;
    inset: 0;
    /* Por encima del cajón (800) y por debajo del aviso de sesión caducada
       (999), que tiene que verse aunque esto esté abierto: si la sesión se
       cayó, seguir tocando ajustes no lleva a ninguna parte. */
    z-index: 850;
    display: grid;
    place-items: center;
    padding: var(--cb-e5);
}

.cb-ajustes[hidden] { display: none; }

.cb-ajustes-fondo {
    position: absolute;
    inset: 0;
    background: rgba(6, 9, 14, .62);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}

.cb-ajustes-caja {
    position: relative;
    display: flex;
    flex-direction: column;
    width: min(880px, calc(100vw - 2 * var(--cb-e5)));
    height: min(620px, calc(100vh - 2 * var(--cb-e5)));
    overflow: hidden;
    background: var(--cb-panel);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r5);
    box-shadow: var(--cb-som-3), var(--cb-filo);
    animation: cb-ajustes-entra var(--cb-mov-4) var(--cb-firme) both;
}

@keyframes cb-ajustes-entra {
    from { transform: translateY(14px) scale(.985); opacity: 0; }
    to   { transform: none; opacity: 1; }
}

.cb-ajustes-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cb-e4);
    flex: 0 0 auto;
    padding: var(--cb-e5);
    background: var(--cb-panel-2);
    border-bottom: 1px solid var(--cb-border);
    box-shadow: var(--cb-filo);
}

.cb-ajustes-top .cb-h2 {
    margin: 0;
    font-size: var(--cb-t2);
    letter-spacing: .14em;
    color: var(--cb-text);
}

.cb-ajustes-cuerpo {
    display: grid;
    grid-template-columns: 232px 1fr;
    flex: 1;
    min-height: 0;
}

/* ── La lista de secciones ─────────────────────────────────────────────── */

.cb-ajnav {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-height: 0;
    padding: var(--cb-e4) var(--cb-e3);
    overflow-y: auto;
    background: var(--cb-hueco);
    border-right: 1px solid var(--cb-border);
}

.cb-ajnav-op {
    display: flex;
    align-items: center;
    gap: var(--cb-e3);
    width: 100%;
    padding: 10px 11px;
    font: inherit;
    font-size: var(--cb-t3);
    font-weight: 600;
    color: var(--cb-dim);
    text-align: left;
    background: transparent;
    border: 0;
    border-radius: var(--cb-r2);
    cursor: pointer;
    transition: background var(--cb-mov-1), color var(--cb-mov-1);
}

.cb-ajnav-op:hover { background: var(--cb-panel-2); color: var(--cb-text); }

.cb-ajnav-op .ic { font-size: 17px; opacity: .85; }

/* El nombre empuja al chevron hasta el borde. */
.cb-ajnav-nom { flex: 1; min-width: 0; }

.cb-ajnav-fl {
    flex: 0 0 auto;
    font-size: 15px;
    opacity: .5;
    transition: transform var(--cb-mov-1), opacity var(--cb-mov-1);
}

.cb-ajnav-on {
    color: var(--cb-text);
    background: rgba(99, 102, 241, .14);
    box-shadow: inset 2px 0 0 var(--cb-accent);
}

.cb-ajnav-on .ic { opacity: 1; }
.cb-ajnav-on .cb-ajnav-fl { opacity: .9; transform: translateX(2px); }

/* ── El panel de la derecha ────────────────────────────────────────────── */

.cb-ajcuerpo {
    min-height: 0;
    padding: var(--cb-e6) var(--cb-e6) var(--cb-e7);
    overflow-y: auto;
    overscroll-behavior: contain;
}

.cb-ajpane[hidden] { display: none; }

/* Una fila de ajuste: lo que se ajusta a la izquierda, el mando a la
   derecha. Es la gramática de la captura y la que la gente ya conoce. */
.cb-ajfila {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cb-e5);
    padding: var(--cb-e4) 0;
    border-bottom: 1px solid var(--cb-border);
}

.cb-ajfila:last-child { border-bottom: 0; }

.cb-ajfila-txt { flex: 1; min-width: 0; }

.cb-ajfila-tit {
    margin: 0;
    font-size: var(--cb-t4);
    font-weight: 600;
    color: var(--cb-text);
}

/* La explicación va debajo del rótulo, no en un title: en una mesa de
   control nadie deja el ratón quieto encima esperando a que salga. */
.cb-ajfila-sub {
    margin: 3px 0 0;
    max-width: 52ch;
    font-size: var(--cb-t2);
    line-height: 1.45;
    color: var(--cb-dim-2);
}

.cb-ajfila-mando { flex: 0 0 auto; }
.cb-ajfila-mando .cb-input { max-width: 260px; }

/* Una fila cuyo mando es demasiado ancho para caber al lado. */
.cb-ajfila-ancha { flex-direction: column; align-items: stretch; }
.cb-ajfila-ancha .cb-ajfila-mando { width: 100%; }

.cb-ajaviso {
    margin: var(--cb-e4) 0 0;
    padding: 9px 12px;
    font-size: var(--cb-t2);
    line-height: 1.5;
    color: var(--cb-dim);
    background: rgba(148, 163, 184, .06);
    border: 1px solid var(--cb-border);
    border-left: 3px solid var(--cb-border-2);
    border-radius: var(--cb-r1);
}

.cb-ajaviso-mal { border-left-color: var(--cb-aire); background: rgba(239, 68, 68, .09); color: var(--cb-text); }
.cb-ajaviso:empty { display: none; }

/* ── El interruptor deslizante ──────────────────────────────────────────
   Nuevo en Switch Control. El punto verde de .cb-tog se queda para «esto está
   al aire»; mezclar los dos idiomas haría que una preferencia puesta se
   leyera de reojo como una fuente en antena.                            */

.cb-sw {
    position: relative;
    display: block;
    width: 46px;
    height: 26px;
    padding: 0;
    background: var(--cb-border-2);
    border: 0;
    border-radius: var(--cb-rp);
    cursor: pointer;
    transition: background var(--cb-mov-1);
}

.cb-sw::after {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: 20px;
    height: 20px;
    background: #fff;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .45);
    transition: transform var(--cb-mov-1) var(--cb-amb);
}

.cb-sw[aria-checked="true"] { background: var(--cb-accent); }
.cb-sw[aria-checked="true"]::after { transform: translateX(20px); }
.cb-sw:disabled { opacity: .42; cursor: default; }

/* ── Piezas de dentro de las secciones ─────────────────────────────────── */

/* La lista de cámaras y micrófonos. Es la misma que la de los menús de la
   botonera y escribe en el mismo <select>: aquí solo cambia el tamaño. */
.cb-ajlista {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 210px;
    overflow-y: auto;
}

.cb-ajlista .cb-menu-op { font-size: var(--cb-t3); }

/* Las cuatro opciones de fondo virtual y la tira de imágenes. */
.cb-ajops { display: flex; flex-wrap: wrap; gap: var(--cb-e3); margin-top: var(--cb-e3); }

.cb-ajimgs {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: var(--cb-e3);
    margin-top: var(--cb-e4);
}

.cb-ajimg {
    position: relative;
    aspect-ratio: 16 / 9;
    padding: 0;
    overflow: hidden;
    background: var(--cb-panel-2);
    border: 2px solid transparent;
    border-radius: var(--cb-r2);
    cursor: pointer;
}

.cb-ajimg img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cb-ajimg-on { border-color: var(--cb-accent); }

/* El previo del fondo virtual. Va en 16:9 y con fondo negro: un hueco
   vacío del color del panel parece un fallo de carga. */
.cb-ajprev {
    width: 100%;
    max-width: 340px;
    aspect-ratio: 16 / 9;
    margin-top: var(--cb-e4);
    object-fit: cover;
    background: #000;
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r3);
}

/* Verse como en un espejo es SOLO de esta pantalla: no viaja al aire. */
.cb-espejo { transform: scaleX(-1); }

/* La tubería del fondo virtual: el <video> de origen y el lienzo donde se
   compone. Nadie los mira, pero el <video> tiene que estar reproduciéndose
   de verdad o la tubería se congela, así que no puede ir con display:none
   ni con hidden. Se saca de la pantalla y ya está. */
.cb-fuera {
    position: absolute;
    width: 1px;
    height: 1px;
    left: -9999px;
    top: 0;
    opacity: 0;
    pointer-events: none;
}

/* El cronómetro de la grabación, con cifras que no bailan. */
.cb-ajreloj {
    font-size: var(--cb-t6);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    letter-spacing: .02em;
    color: var(--cb-text);
}

.cb-ajreloj[hidden] { display: none; }

.cb-ajgrabs { display: flex; flex-direction: column; gap: var(--cb-e2); margin-top: var(--cb-e4); }

.cb-ajgrab {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--cb-e4);
    padding: 8px 11px;
    font-size: var(--cb-t2);
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r2);
}

/* La tabla de atajos. Una tecla por fila y nada más: es la documentación
   del interruptor de arriba, no un editor. */
.cb-ajteclas { display: flex; flex-direction: column; gap: 2px; margin-top: var(--cb-e4); }

.cb-ajtecla {
    display: flex;
    align-items: center;
    gap: var(--cb-e4);
    padding: 7px 2px;
    font-size: var(--cb-t3);
    color: var(--cb-dim);
    border-bottom: 1px solid var(--cb-border);
}

.cb-ajtecla:last-child { border-bottom: 0; }

.cb-ajtecla kbd {
    flex: 0 0 auto;
    min-width: 58px;
    padding: 4px 8px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: var(--cb-t2);
    text-align: center;
    color: var(--cb-text);
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border-2);
    border-bottom-width: 2px;
    border-radius: var(--cb-r1);
}

/* Las barras finas no se heredan: la lista de la línea ~2820 es
   enumerativa y un contenedor nuevo con scroll se queda con la barra
   gorda del sistema. */
.cb-ajnav,
.cb-ajcuerpo,
.cb-ajlista {
    scrollbar-width: thin;
    scrollbar-color: #303c4f transparent;
}

.cb-ajnav::-webkit-scrollbar,
.cb-ajcuerpo::-webkit-scrollbar,
.cb-ajlista::-webkit-scrollbar { width: 9px; }

.cb-ajnav::-webkit-scrollbar-thumb,
.cb-ajcuerpo::-webkit-scrollbar-thumb,
.cb-ajlista::-webkit-scrollbar-thumb {
    background: #303c4f;
    border-radius: var(--cb-rp);
}

/* En estrecho la ventana ocupa la pantalla y la lista de secciones pasa a
   ser una tira que se desliza, como los rails. Con `safe center`: una fila
   deslizable centrada deja el primer elemento inalcanzable, y esa trampa ya
   costó un rato una vez. */
@media (max-width: 820px) {
    .cb-ajustes { padding: 0; }

    .cb-ajustes-caja {
        width: 100%;
        height: 100%;
        border: 0;
        border-radius: 0;
    }

    .cb-ajustes-cuerpo { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }

    .cb-ajnav {
        flex-direction: row;
        gap: var(--cb-e2);
        padding: var(--cb-e3);
        overflow-x: auto;
        overflow-y: hidden;
        justify-content: safe center;
        border-right: 0;
        border-bottom: 1px solid var(--cb-border);
    }

    .cb-ajnav-op { flex: 0 0 auto; padding: 8px 10px; }

    /* En la tira solo caben el icono y el nombre: el chevron apuntaba a una
       columna que ya no está a la derecha. */
    .cb-ajnav-fl { display: none; }
    .cb-ajnav-on { box-shadow: inset 0 -2px 0 var(--cb-accent); }

    .cb-ajcuerpo { padding: var(--cb-e5) var(--cb-e4) var(--cb-e6); }

    /* El mando debajo del rótulo: al lado no queda ancho para ninguno de
       los dos. El interruptor es la excepción, que es estrecho y se lee
       mejor enfrente de su rótulo. */
    .cb-ajfila { flex-wrap: wrap; }
    .cb-ajfila-mando { width: 100%; }
    .cb-ajfila-mando .cb-input { max-width: none; }
    .cb-ajfila-sw { flex-wrap: nowrap; }
    .cb-ajfila-sw .cb-ajfila-mando { width: auto; }
}

.cb-gn {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: var(--cb-e3);
    padding: var(--cb-e4);
    margin-bottom: var(--cb-e2);
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    border-left: 3px solid transparent;
    border-radius: var(--cb-r3);
    transition: background var(--cb-mov-2) var(--cb-amb),
                border-color var(--cb-mov-2) var(--cb-amb);
}

.cb-gn:hover { border-color: var(--cb-border-2); }

@media (max-width: 820px) {
}

/* La otra puerta de la pantalla de entrada: crear un estudio propio.
   Separada del renglón de recuperar el acceso por una línea, porque son dos
   cosas distintas y pegadas se leen como una sola frase larga. */
.cb-login-alta {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--cb-borde, #232c3a);
    font-size: var(--cb-t2);
    color: var(--cb-dim);
}
.cb-login-alta a { color: var(--cb-accent); font-weight: 600; }

/* Dos botones que son UNA elección: micrófono o línea. Pegados y con un solo
   borde entre ambos, para que se lean como un interruptor de dos posiciones y
   no como dos acciones sueltas que se pudieran pulsar las dos. */
.cb-toggrupo {
    display: inline-flex;
    gap: 0;
}

.cb-toggrupo .cb-tog {
    border-radius: 0;
    box-shadow: none;
}

.cb-toggrupo .cb-tog:first-child {
    border-radius: var(--cb-r3) 0 0 var(--cb-r3);
}

.cb-toggrupo .cb-tog:last-child {
    border-radius: 0 var(--cb-r3) var(--cb-r3) 0;
    /* Sin este ajuste, el borde compartido se dibuja dos veces y se ve una
       línea el doble de gruesa justo en medio. */
    margin-left: -1px;
}

/* Un interruptor que la línea no admite: se queda a la vista, apagado y
   explicado. Esconderlo haría creer que se lo llevó un error; dejarlo vivo,
   que sirve de algo con una mezcla enchufada. */
.cb-sw:disabled {
    opacity: .4;
    cursor: not-allowed;
}

/* ══ En un teléfono, el dedo manda ═══════════════════════════════════════
   El panel YA se reordena solo a una columna: ninguna vista desborda a lo
   ancho, medido a 375 px en los doce módulos. Lo que faltaba no era el
   reparto, era el TAMAÑO: mandos de 27 px de alto —media yema de dedo— y
   rótulos de 10 px que no se leen en la calle, con el sol de lado.

   Va todo en un bloque y sólo por debajo de 820 px, que es donde el panel ya
   cambia de forma. En el escritorio no cambia nada: la densidad de una mesa
   que se mira seis horas seguidas es una virtud, y ensancharla ahí sería
   pagar con espacio un problema que allí no existe.

   36 px no es el ideal —Apple y Google piden 44— pero un switcher tiene
   cuarenta mandos a la vista: a 44 px cada uno, no cabe ninguno. 36 es lo
   que se puede pulsar sin que la mesa deje de ser una mesa. */
@media (max-width: 820px) {

    /* El rail de módulos ES la navegación del panel. A 10 px se adivina. */
    .cb-mod-txt { font-size: var(--cb-t2); }
    .cb-mod     { min-height: 54px; padding: 9px var(--cb-e2); }

    /* Los interruptores de gráficas: se pulsan al aire y a menudo con prisa. */
    .cb-tog { min-height: 38px; padding-left: 12px; padding-right: 12px; }

    /* Las pestañas del escenario: escenas, cortinas, continuidad. */
    .cb-pest-b { min-height: 38px; }

    /* «xs» sigue siendo pequeño, pero deja de ser inalcanzable. */
    .cb-btn-xs { min-height: 36px; font-size: var(--cb-t2); padding-left: 12px; padding-right: 12px; }

    /* Las frases rápidas del intercom: se mandan mientras se opera. */
    .cb-ic-rapida { min-height: 38px; }

    /* Las fichas de destino de la barra de emisión. */
    .cb-sal { min-height: 34px; }

    /* Ningún titular de sección por debajo de 12 px en un teléfono. */
    .cb-h2 { font-size: var(--cb-t3); }

    /* Las flechas que despliegan el rail lateral. */
    .cb-rb-fl { min-width: 38px; }

    /* Y el resumen de la escena, que es información y no adorno. */
    .cb-esc-res { font-size: var(--cb-t2); }

    /* ── Los que hacían falta con más puntería ────────────────────────────
       Estos tres los pisaban reglas más específicas de más arriba, y una
       regla de una clase no gana a una de dos. Se repiten con la misma
       especificidad en vez de recurrir a !important: `!important` gana la
       discusión de hoy y deja al siguiente sin forma de ganar la suya. */

    /* El rail se MUEVE dentro del cajón al abrir un módulo, y allí tenía su
       propio tamaño de 10 px. Es la navegación: no puede encogerse justo
       cuando estás navegando. */
    .cb-cajon-rail .cb-mod-txt { font-size: var(--cb-t2); }
    .cb-cajon-rail .cb-mod     { min-height: 54px; }

    /* Los repartos del monitor son esquemas, no botones con caja: por eso
       renuncian al alto mínimo. En un dedo siguen necesitándolo. */
    .cb-lays-mon .cb-tog { min-height: 34px; min-width: 34px; }

    /* Las frases del intercom y los rótulos sueltos de 11 px. */
    .cb-ic-para,
    .cb-btn.cb-btn-xs,
    .cb-btn.cb-btn-danger { font-size: var(--cb-t2); }

    /* Los mandos del banco de escenas —Cargar, Actualizar, Renombrar,
       Borrar— llevan una regla de tres clases para caber en el rail
       estrecho del escritorio. Aquí no hay rail estrecho: hay un dedo. */
    .cb-rail-esc .cb-esc-acc .cb-btn { font-size: var(--cb-t2); padding: 7px 10px; }

    /* El piloto del monitor —«Sin emitir» / «En vivo»— es de las tres cosas
       que se miran de reojo mientras se opera. No puede ser lo más pequeño
       de la pantalla.
       Lo que SÍ se queda en 11 px son las horas del chat: son metadato al
       lado de un mensaje de 13, y subirlas rompería esa jerarquía para
       hacer legible algo que nadie lee de lejos. */
    #monLiveTxt { font-size: var(--cb-t2); }

    /* ── La puerta de entrada ─────────────────────────────────────────────
       Los campos y el botón ya estaban bien (46 px de alto y letra de 16, que
       es lo que evita que iOS haga zoom al enfocar). Los dos enlaces del pie
       —«¿Olvidaste tu contraseña?» y «Regístrate aquí»— medían 15 px de alto:
       en el teléfono se falla más de lo que se acierta, y son justo los dos
       que pulsa quien ya está teniendo un problema. */
    .cb-login-foot a,
    .cb-login-alta a { display: inline-block; padding: 9px 0; }
}

/* ═══════════════════════════════════════════════════════════════════════
   COMPACTO: el estudio cabe en UNA pantalla (2026-10-23)
   ═══════════════════════════════════════════════════════════════════════

   A 1366×768 —el portátil más común— el panel medía 918 px de alto y la
   botonera, con AL AIRE dentro, quedaba debajo del borde: para salir al
   aire había que desplazar la página, y al desplazarla se perdía de vista
   el monitor. Una mesa de control que no se ve entera no es una mesa.

   Dos cosas, y en este orden:

   1. Se aprieta lo que rodea al monitor: cabecera, barra de emisión,
      márgenes y la botonera. Sólo el relleno; ningún mando se encoge.
   2. El monitor deja de mandar en el alto. Antes era `width: 100%` y su
      alto salía del ancho, así que en una pantalla ancha y baja empujaba
      todo lo demás fuera. Ahora su ancho es el MENOR entre la columna y
      lo que cabe a lo alto: `--cb-resto` es todo lo que no es monitor.
      monEscala() ya lee el ancho real del cuadro, así que el overlay de
      dentro se reescala solo.

   Sólo de 821 px para arriba: por debajo el estudio es una pila que se
   desliza a propósito (ver «Celular» más arriba). */
@media (min-width: 821px) {
    :root { --cb-resto: 316px; }

    .cb-top { padding: 7px var(--cb-e5); }
    .cb-top-logo { height: 28px; }

    .cb-studio { padding: 10px 14px; }

    .cb-broadcast { padding: 9px var(--cb-e5); margin-bottom: 0; }
    .cb-work { margin-top: 10px; gap: 12px; }

    .cb-stage { padding: 12px; }
    .cb-stage .cb-mesa-head { margin-bottom: var(--cb-e3); }

    .cb-monitor:not(.cb-monitor-vert) {
        width: min(100%, calc((100dvh - var(--cb-resto)) * 16 / 9));
        margin-inline: auto;
    }

    .cb-monbar { gap: var(--cb-e3); padding: var(--cb-e3) var(--cb-e4); margin-top: var(--cb-e3); }

    /* Los rails no deben ser más altos que la ventana: se deslizan ellos. */
    .cb-rail-esc { max-height: calc(100dvh - 140px); }
}

/* En pantallas bajas (720 px) el que sobresale es el rail de módulos: diez
   botones de 56 px. Se les quita relleno, no letra ni icono. */
@media (min-width: 821px) and (max-height: 760px) {
    .cb-rail-mod .cb-mod { padding-block: 5px; }
}

/* ── La transición, pegada a AL AIRE ─────────────────────────────────────
   Una pastilla de cuatro palabras y no cuatro dibujos: «fundido» y «barrido»
   no tienen un esquema que se reconozca sin leerlo, y un mando que hay que
   adivinar en directo es un mando que no se usa. Empuja ella al extremo, y
   AL AIRE queda pegado a su derecha. */
.cb-trans {
    display: inline-flex;
    flex: 0 0 auto;
    margin-left: auto;
    padding: 3px;
    gap: 2px;
    background: var(--cb-panel);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r3);
}

.cb-trans + .cb-alaire { margin-left: var(--cb-e3); }

.cb-trans-b {
    min-height: 34px;
    padding: 0 10px;
    border: 0;
    border-radius: var(--cb-r2);
    background: transparent;
    color: var(--cb-dim);
    font: inherit;
    font-size: var(--cb-t1);
    font-weight: 700;
    cursor: pointer;
    transition: background-color var(--cb-mov-2) var(--cb-amb), color var(--cb-mov-2) var(--cb-amb);
}

.cb-trans-b:hover { color: var(--cb-text); background: var(--cb-panel-2); }

.cb-trans-on,
.cb-trans-on:hover { color: #fff; background: var(--cb-accent); }

@media (max-width: 820px) {
    .cb-trans { margin-left: 0; }
    .cb-trans-b { min-height: 36px; font-size: var(--cb-t2); }
}

/* ── Soltar archivos sobre el panel ──────────────────────────────────────
   Aparece sólo mientras se arrastran archivos desde fuera. Tapa el panel
   entero porque el panel entero acepta: un hueco concreto donde «hay que
   acertar» es lo que hace fallar un arrastre con prisa. */
.cb-soltar {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba(8, 10, 16, .72);
    backdrop-filter: blur(3px);
    pointer-events: none;     /* el drop lo recoge window */
}

.cb-soltar-caja {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    width: min(640px, 100%);
    padding: 42px 28px;
    border: 2px dashed var(--cb-accent);
    border-radius: var(--cb-r5);
    background: rgba(99, 102, 241, .12);
    text-align: center;
}

.cb-soltar-caja b    { font-size: 22px; color: #fff; }
.cb-soltar-caja span { font-size: var(--cb-t2); color: var(--cb-dim); }

/* ── El menú de una red en la tira de salidas ────────────────────────────
   Flota debajo de su icono (lo coloca salMenu()). Lo justo: qué le pasa,
   si se usa en la próxima transmisión, y la puerta a configurarla. */
.cb-salpop {
    position: fixed;
    z-index: 120;
    width: 260px;
    max-width: calc(100vw - 20px);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
    padding: 14px;
    background: var(--cb-panel);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r4);
    box-shadow: 0 18px 40px -12px rgba(0, 0, 0, .8), var(--cb-filo);
}

.cb-salpop-cab { display: flex; align-items: center; gap: 8px; font-size: var(--cb-t3); }
.cb-salpop-cab .ic { width: 20px; height: 20px; }

.cb-salpop-est,
.cb-salpop-nota { margin: 0; font-size: var(--cb-t2); line-height: 1.4; color: var(--cb-dim); }
.cb-salpop-viva   { color: #86efac; }
.cb-salpop-caida,
.cb-salpop-fuera  { color: #fca5a5; }
.cb-salpop-falta,
.cb-salpop-yendo  { color: #fcd34d; }

.cb-salpop-sw {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    min-height: 36px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--cb-text);
    font: inherit;
    font-size: var(--cb-t3);
    font-weight: 700;
    cursor: pointer;
    text-align: left;
}

.cb-salpop-sw-pista {
    position: relative;
    flex: 0 0 auto;
    width: 38px;
    height: 22px;
    border-radius: 999px;
    background: var(--cb-panel-2);
    border: 1px solid var(--cb-border);
    transition: background-color var(--cb-mov-2) var(--cb-amb);
}

.cb-salpop-sw-pista i {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--cb-dim);
    transition: transform var(--cb-mov-2) var(--cb-amb), background-color var(--cb-mov-2) var(--cb-amb);
}

.cb-salpop-sw-on .cb-salpop-sw-pista   { background: var(--cb-accent); border-color: transparent; }
.cb-salpop-sw-on .cb-salpop-sw-pista i { transform: translateX(16px); background: #fff; }

/* En el celular la cabecera del monitor —título, piloto y Previo/Programa—
   no cabe en 375 px y «Programa» se salía del panel, cortado por el borde.
   Se deja partir en dos renglones: los mandos bajan enteros. */
@media (max-width: 820px) {
    .cb-stage .cb-mesa-head { flex-wrap: wrap; row-gap: var(--cb-e3); }
    .cb-monhead { flex-wrap: wrap; }
}

/* ── Continuidad: pegar un enlace para retransmitir ───────────────────── */
.cb-con-enl {
    display: flex;
    gap: var(--cb-e2);
    margin-top: var(--cb-e4);
}
.cb-con-enl .cb-input { flex: 1 1 auto; min-width: 0; }
.cb-con-enl .cb-btn   { flex: 0 0 auto; }

.cb-con-enl-nota { margin: var(--cb-e2) 0 0; font-size: var(--cb-t1); }
.cb-con-enl-mal  { color: #fca5a5; }

.cb-con-enls { margin-top: var(--cb-e3); }
.cb-con-enls-tit {
    margin: 0 0 var(--cb-e2);
    font-size: var(--cb-t0);
    font-weight: 800;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--cb-dim);
}
.cb-con-enls:empty { display: none; }

/* Las filas de la continuidad, en dos renglones: el nombre arriba y los
   mandos debajo. En los 220 px del rail, con tres botones al lado, el nombre
   se quedaba en tres letras —«Señ…», «You…»— y con enlaces, cuyos títulos
   son largos, la cola dejaba de decir qué había en ella. */
.cb-con-fila {
    grid-template-columns: 22px 1fr;
    grid-template-areas: "num nom" "num acc";
    row-gap: 4px;
}
.cb-con-num { grid-area: num; align-self: start; padding-top: 1px; }
.cb-con-nom {
    grid-area: nom;
    white-space: normal;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    line-height: 1.3;
}
.cb-con-acc { grid-area: acc; justify-content: flex-end; }
/* La fila de enlaces guardados no lleva número. */
.cb-con-enls .cb-con-fila { grid-template-columns: 1fr; grid-template-areas: "nom" "acc"; }

/* ── Con la continuidad sonando: sacar una cámara encima ─────────────────
   Una fila más en la botonera, sólo mientras la cola rueda. */
.cb-monbar-cont {
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: var(--cb-e2);
    padding: var(--cb-e2) var(--cb-e3);
    border-radius: var(--cb-r3);
    background: rgba(99, 102, 241, .1);
    border: 1px solid rgba(99, 102, 241, .35);
}
.cb-cont-tit  { font-size: var(--cb-t1); font-weight: 800; color: var(--cb-text); margin-right: var(--cb-e2); }
.cb-cont-modo {
    display: inline-flex;
    gap: 2px;
    padding: 2px;
    background: var(--cb-panel);
    border: 1px solid var(--cb-border);
    border-radius: var(--cb-r3);
}
.cb-cont-modo .cb-trans-b { min-height: 30px; }
.cb-cont-nota { font-size: var(--cb-t1); color: var(--cb-dim); }

/* Mientras está la fila, el monitor cede su alto para que todo siga
   cabiendo en una pantalla (ver «COMPACTO»). */
@media (min-width: 821px) {
    :root:has(#monCont:not([hidden])) { --cb-resto: 362px; }
}

/* ── Más cámaras: USB del equipo y móviles por QR (2026-10-23) ───────── */
.cb-camsx { display: grid; gap: var(--cb-e3); margin-top: var(--cb-e3); }
.cb-camsx:empty { display: none; }
.cb-camsx-add { margin: var(--cb-e3) 0 var(--cb-e4); }
.cb-camsx-c .cb-camest-cab { gap: var(--cb-e2); }
.cb-camsx-nom { flex: 1 1 auto; min-width: 0; font-weight: 700; padding: 5px 8px; }
.cb-camsx-sel { margin: var(--cb-e2) 0; font-size: var(--cb-t2); }
.cb-camsx-c .cb-camest-pie { display: flex; align-items: center; gap: var(--cb-e3); margin-top: var(--cb-e2); }

/* El QR de una cámara móvil, en el hueco de la imagen mientras no conecta.
   Blanco detrás: un lector necesita contraste, y el panel es oscuro. */
.cb-gv-qr { gap: 6px; }
.cb-gv-qr svg {
    width: min(150px, 70%);
    height: auto;
    aspect-ratio: 1;
    background: #fff;
    border-radius: 8px;
    padding: 4px;
}

/* ── Multiview (2026-10-23) ──────────────────────────────────────────────
   Las entradas en miniatura bajo el programa. Tally como en vMix: borde
   ROJO = al aire. Se desliza en horizontal si no caben. */
.cb-mv {
    display: flex;
    gap: var(--cb-e2);
    margin-top: var(--cb-e3);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
    padding-bottom: 2px;
}
.cb-mv-t {
    position: relative;
    flex: 0 0 auto;
    width: 136px;
    aspect-ratio: 16 / 9;
    border-radius: var(--cb-r2);
    background: #05070b;
    border: 2px solid var(--cb-border);
    overflow: hidden;
    cursor: pointer;
    transition: border-color var(--cb-mov-2) var(--cb-amb);
}
.cb-mv-t:hover { border-color: var(--cb-accent); }
.cb-mv-t.cb-mv-aire { border-color: #ef4444; box-shadow: 0 0 0 1px #ef4444; }
.cb-mv-v { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cb-mv-ini {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    font-size: 26px; font-weight: 800; color: var(--cb-dim);
}
.cb-mv-ver {
    position: absolute; left: 50%; bottom: 20px; transform: translateX(-50%);
    font: inherit; font-size: 11px; padding: 2px 8px; border-radius: 999px;
    border: 1px solid var(--cb-border); background: var(--cb-panel-2); color: var(--cb-text); cursor: pointer;
}
.cb-mv-num {
    position: absolute; top: 3px; left: 4px; min-width: 16px; padding: 0 4px;
    font-size: 11px; font-weight: 800; color: #fff; background: rgba(0, 0, 0, .6); border-radius: 4px; text-align: center;
}
.cb-mv-num:empty { display: none; }
.cb-mv-aire .cb-mv-num { background: #ef4444; }
.cb-mv-nom {
    position: absolute; left: 0; right: 0; bottom: 0; padding: 2px 6px;
    font-size: 11px; font-weight: 700; color: #fff; background: linear-gradient(transparent, rgba(0, 0, 0, .8));
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cb-mv-mas {
    position: absolute; top: 3px; right: 3px; width: 22px; height: 22px; padding: 0;
    font: inherit; font-weight: 800; line-height: 1; border: 0; border-radius: 6px;
    background: rgba(0, 0, 0, .6); color: #fff; cursor: pointer;
}
.cb-mv-mas:hover { background: var(--cb-accent); }

@media (min-width: 821px) {
    :root:has(#cbMv:not([hidden])) { --cb-resto: 404px; }
    :root:has(#cbMv:not([hidden])):has(#monCont:not([hidden])) { --cb-resto: 450px; }
}

/* ── Ajustes → Control remoto ────────────────────────────────────────── */
.cb-ctl code { font-size: 11px; word-break: break-all; color: var(--cb-text); }
.cb-ctl-tok { display: flex; align-items: center; gap: 8px; margin: 4px 0 12px; }
.cb-ctl-tok code { padding: 6px 8px; border-radius: 6px; background: var(--cb-hueco); border: 1px solid var(--cb-border); }
.cb-ctl-ej { display: grid; grid-template-columns: 1fr auto; gap: 2px 8px; align-items: center; padding: 6px 0; border-bottom: 1px solid var(--cb-border); }
.cb-ctl-ej span { font-size: var(--cb-t2); font-weight: 700; grid-column: 1 / -1; }
.cb-ctl-ej code { color: var(--cb-dim); }

/* La pestaña del aire con el sonido bloqueado: se ve sí o sí, encima del
   monitor, en rojo. Es el único aviso del panel que dice «el público no te
   oye» y no puede quedarse en una línea de texto pequeña. */
.cb-aviso-sonido {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    margin: 0 0 var(--cb-e3);
    padding: 8px 12px;
    border-radius: var(--cb-r3);
    background: rgba(239, 68, 68, .16);
    border: 1px solid rgba(239, 68, 68, .6);
    color: #fecaca;
    font-size: var(--cb-t2);
}
.cb-aviso-sonido b { color: #fff; }

/* La radio con el audio de la pestaña AIRE (para YouTube). */
.cb-rd-pestana { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin: 8px 0 4px; }

/* ── El mezclador de audio (2026-10-23) ────────────────────────────────── */
.cb-mix-master { padding: 12px; border-radius: var(--cb-r4); background: var(--cb-hueco); border: 1px solid var(--cb-border); }
.cb-mix-mh { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 8px; }
.cb-mix-tit { font-size: var(--cb-t1); font-weight: 800; letter-spacing: .12em; color: var(--cb-dim); margin-right: auto; }
.cb-mix-txt { font-size: var(--cb-t2); font-weight: 700; color: var(--cb-dim); }
.cb-mix-ok  { color: #86efac; }
.cb-mix-mal { color: #fca5a5; }
.cb-mix-nota { margin: 6px 0 0; font-size: var(--cb-t1); }
.cb-mix-acc { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 10px; }
.cb-mix-ok-chip { font-size: var(--cb-t1); font-weight: 700; color: #86efac; }
.cb-mix-radio { font-size: var(--cb-t1); color: var(--cb-dim); margin-left: auto; }

.cb-mix-dx { margin: 10px 0 14px; padding: 9px 12px; border-radius: var(--cb-r3); font-size: var(--cb-t2); font-weight: 600; border: 1px solid var(--cb-border); color: var(--cb-text); }
.cb-mix-dx-ok    { background: rgba(34, 197, 94, .1);  border-color: rgba(34, 197, 94, .45); color: #bbf7d0; }
.cb-mix-dx-medio { background: rgba(245, 158, 11, .1); border-color: rgba(245, 158, 11, .45); color: #fde68a; }
.cb-mix-dx-mal   { background: rgba(239, 68, 68, .14); border-color: rgba(239, 68, 68, .6);  color: #fecaca; }

.cb-mix-filas, .cb-mix-cont { display: grid; gap: 6px; margin-bottom: 14px; }
.cb-mix-fila { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 7px 10px; border-radius: var(--cb-r3); background: var(--cb-panel-2); border: 1px solid var(--cb-border); }
.cb-mix-muted { opacity: .7; }
.cb-mix-tally { font-size: 10px; font-weight: 800; letter-spacing: .08em; padding: 2px 6px; border-radius: 4px; background: #ef4444; color: #fff; }
.cb-mix-nom { font-weight: 700; font-size: var(--cb-t2); min-width: 120px; }
.cb-mix-nom small { font-weight: 500; color: var(--cb-dim); }
.cb-mix-vu { flex: 0 0 auto; }
.cb-mix-fader { flex: 1 1 120px; min-width: 90px; }
.cb-mix-vol { min-width: 28px; text-align: right; font-size: var(--cb-t1); color: var(--cb-dim); font-variant-numeric: tabular-nums; }

/* El monitor enseñando la CAPTURA de la pestaña AIRE: lo que sale de verdad. */
.cb-monitor-cap {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: #05070b;
    z-index: 1;
}
.cb-monitor-encap::after {
    content: 'SALIDA REAL';
    position: absolute;
    left: 10px;
    bottom: 10px;
    z-index: 3;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(239, 68, 68, .9);
    color: #fff;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: .08em;
}

/* El rótulo de sonido del monitor se pulsa: es el mismo mando que «Aquí». */
.cb-mon-mudo-clic { cursor: pointer; pointer-events: auto; }
.cb-mon-mudo-clic:hover { filter: brightness(1.25); }

/* ── El logo: subirlo y ponerlo donde se quiera (2026-10-23) ─────────── */
.cb-logo { display: grid; grid-template-columns: 1fr auto; gap: 10px 14px; align-items: center; margin: 4px 0 16px; padding: 12px; border-radius: var(--cb-r4); background: var(--cb-hueco); border: 1px solid var(--cb-border); }
.cb-logo-cab { display: flex; align-items: center; gap: 12px; min-width: 0; }
.cb-logo-prev { width: 64px; height: 64px; object-fit: contain; border-radius: 10px; background: repeating-conic-gradient(#2a2f3a 0 25%, #1c2029 0 50%) 0 0 / 14px 14px; padding: 4px; flex: 0 0 auto; }
.cb-logo-acc { display: flex; flex-wrap: wrap; gap: 6px; }
.cb-logo-pos { display: grid; grid-template-columns: repeat(3, 30px); gap: 3px; grid-row: span 2; }
.cb-logo-pos button { width: 30px; height: 30px; padding: 0; border-radius: 6px; border: 1px solid var(--cb-border); background: var(--cb-panel-2); color: var(--cb-text); font: inherit; font-size: 13px; cursor: pointer; }
.cb-logo-pos button:hover { border-color: var(--cb-accent); color: #fff; }
.cb-logo-tam { display: flex; align-items: center; gap: 10px; font-size: var(--cb-t2); font-weight: 700; color: var(--cb-dim); }
.cb-logo-tam input { flex: 1 1 auto; }
.cb-logo #logoNota { grid-column: 1 / -1; }

/* El recuadro que se arrastra sobre el monitor. */
.cb-logo-asa {
    position: absolute;
    z-index: 20;
    min-width: 28px;
    min-height: 18px;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 4px;
    padding: 2px;
    border: 2px dashed #fff;
    border-radius: 6px;
    background: rgba(99, 102, 241, .28);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, .5);
    cursor: move;
    touch-action: none;
    user-select: none;
}
.cb-logo-asa span { font-size: 9px; font-weight: 800; letter-spacing: .08em; color: #fff; padding: 1px 4px; background: rgba(0, 0, 0, .55); border-radius: 3px; }
.cb-logo-asa button { font: inherit; font-size: 9px; font-weight: 800; padding: 1px 5px; border: 0; border-radius: 3px; background: #22c55e; color: #04130a; cursor: pointer; }
@media (max-width: 820px) { .cb-logo { grid-template-columns: 1fr; } .cb-logo-pos { grid-row: auto; } }
.cb-logo-guardar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; grid-column: 1 / -1; }
.cb-logo-guardar .cb-logo-sin { color: #fcd34d; font-weight: 700; }

/* ── El marco, en Gráficas (2026-10-23) ────────────────────────────────── */
.cb-marco { display: grid; gap: 8px; margin: 4px 0 14px; padding: 12px; border-radius: var(--cb-r4); background: var(--cb-hueco); border: 1px solid var(--cb-border); }
.cb-mk-fila { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.cb-mk-tit { width: 52px; font-size: var(--cb-t1); font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--cb-dim); }
.cb-mk-b { display: inline-flex; align-items: center; gap: 6px; min-height: 32px; padding: 0 10px; border-radius: var(--cb-r2); border: 1px solid var(--cb-border); background: var(--cb-panel-2); color: var(--cb-text); font: inherit; font-size: var(--cb-t2); font-weight: 600; cursor: pointer; }
.cb-mk-b:hover { border-color: var(--cb-accent); }
.cb-mk-on { background: var(--cb-accent); border-color: transparent; color: #fff; }
.cb-mk-apagado { opacity: .5; }
.cb-mk-mas { font-size: var(--cb-t1); color: var(--cb-dim); margin-left: 4px; }
.cb-mk-sw { font-size: var(--cb-t2); font-weight: 600; cursor: pointer; }
.cb-mk-sw small { color: var(--cb-dim); font-weight: 500; }
/* El dibujito de cada marco: un cuadro con el filo de ese diseño. */
.cb-mk-ico { display: inline-flex; width: 26px; height: 18px; padding: 3px; border-radius: 4px; background: linear-gradient(145deg, #8e2de2, #4a00e0); }
.cb-mk-ico i { flex: 1; background: #0b0f17; }
.cb-mk-ico-clasico  i { border-radius: 3px; }
.cb-mk-ico-tv       i { border-radius: 5px; box-shadow: inset 0 0 0 1px rgba(255,255,255,.4); }
.cb-mk-ico-neon     i { border-radius: 3px; box-shadow: 0 0 0 1px #fff, 0 0 5px 1px #c084fc; }
.cb-mk-ico-cine     i { border-radius: 0; box-shadow: 0 0 0 1px #fff; }
.cb-mk-ico-tarjeta  i { border-radius: 1px; box-shadow: 0 0 0 2px #f8fafc; }
.cb-mk-ico-esquinas i { border-radius: 0; background:
    linear-gradient(#fff,#fff) top left / 5px 1px no-repeat, linear-gradient(#fff,#fff) top left / 1px 5px no-repeat,
    linear-gradient(#fff,#fff) bottom right / 5px 1px no-repeat, linear-gradient(#fff,#fff) bottom right / 1px 5px no-repeat, #0b0f17; }

/* ── Los nombres de las pantallas (2026-10-23) ─────────────────────────── */
.cb-nombres { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; margin: 0 0 var(--cb-e3); padding: 8px 12px; border-radius: var(--cb-r3); background: var(--cb-hueco); border: 1px solid var(--cb-border); }
.cb-nom-tit { font-size: var(--cb-t1); font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--cb-dim); }
.cb-nom-fila { display: inline-flex; align-items: center; gap: 6px; }
.cb-nom-num { min-width: 18px; height: 18px; border-radius: 4px; background: #ef4444; color: #fff; font-size: 11px; font-weight: 800; display: inline-flex; align-items: center; justify-content: center; }
.cb-nom-in { width: 170px; padding: 5px 8px; font-size: var(--cb-t2); }
.cb-nom-fila small { color: var(--cb-dim); font-size: 11px; }
.cb-nom-nota { margin: 0; font-size: var(--cb-t1); color: var(--cb-dim); width: 100%; }

/* ── Gráficas, ordenadas en pestañas (2026-10-23) ──────────────────────── */
.cb-gtabs { display: flex; align-items: center; gap: 4px; margin: 0 0 12px; padding: 3px; border-radius: var(--cb-r3); background: var(--cb-hueco); border: 1px solid var(--cb-border); }
.cb-gtab { min-height: 32px; padding: 0 14px; border: 0; border-radius: var(--cb-r2); background: transparent; color: var(--cb-dim); font: inherit; font-size: var(--cb-t2); font-weight: 700; cursor: pointer; }
.cb-gtab:hover { color: var(--cb-text); }
.cb-gtab-on { background: var(--cb-accent); color: #fff; }
.cb-gtab-bajar { margin-left: auto; }
.cb-gpane[hidden] { display: none; }

/* Las gráficas encendidas, en una fila de chips. */
.cb-toggles-comp { gap: 6px; margin-bottom: 12px; }
.cb-toggles-comp .cb-tog { min-height: 32px; padding: 0 10px; font-size: var(--cb-t2); }

.cb-gbloque { display: grid; gap: 6px; padding: 10px 0; border-top: 1px solid var(--cb-border); }
.cb-gtit { font-size: var(--cb-t1); font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--cb-dim); }
.cb-gfila { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.cb-gfila .cb-input { flex: 1 1 160px; min-width: 0; padding: 8px 10px; font-size: var(--cb-t2); }
.cb-gfila-fin { margin-left: auto; }
.cb-gbloque .cb-presets { margin: 0; }
.cb-gpane .cb-marco, .cb-gpane .cb-logo { margin-top: 0; }

/* ── El monitor no se mueve con los avisos (2026-10-23) ────────────────────
   El alto del monitor se MIDE (cbAjustarAlto): todo lo que entra o sale del
   flujo a su alrededor lo encoge o lo agranda. Los avisos van y vienen solos
   —«Conectando…», que se borra a los 6 s; «¿te oyen?»; el sonido bloqueado—
   y el monitor hacía zoom con cada uno. Ahora FLOTAN sobre el monitor, como
   los rótulos de un monitor de estudio, y no ocupan sitio. */
#cbMonitor > .cb-aviso-sonido {
    position: absolute; top: 10px; left: 10px; right: 10px; z-index: 7;
    margin: 0; background: rgba(60, 10, 12, .92);
}
#cbMonitor > .cb-aviso-sonido[hidden] { display: none; }
@media (min-width: 821px) {
    .cb-monbar { position: relative; }
    .cb-monbar .cb-monbar-aviso {
        position: absolute; left: 50%; bottom: calc(100% + 10px); transform: translateX(-50%);
        z-index: 6; width: max-content; max-width: min(92%, 640px);
        padding: 5px 12px; border-radius: var(--cb-r3);
        background: rgba(5, 7, 11, .9); border: 1px solid var(--cb-border);
        box-shadow: 0 6px 18px -8px rgba(0, 0, 0, .9);
        pointer-events: none;
    }
    /* Los dos a la vez: «¿te oyen?» se sube un renglón para no taparse. */
    .cb-monbar:not(:has(#monAviso:empty)) #monRetorno { bottom: calc(100% + 46px); }
}

/* ── Multiview: cambiar el orden (2026-10-23) ───────────────────────────── */
.cb-mv-t[draggable="true"] { cursor: grab; }
.cb-mv-t.cb-mv-mueve { opacity: .45; }
.cb-mv-t.cb-mv-antes   { box-shadow: -4px 0 0 0 var(--cb-accent); }
.cb-mv-t.cb-mv-despues { box-shadow:  4px 0 0 0 var(--cb-accent); }
.cb-mv-ord {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    display: flex; gap: 3px; opacity: 0; transition: opacity var(--cb-mov-2) var(--cb-amb);
}
.cb-mv-t:hover .cb-mv-ord, .cb-mv-t:focus-within .cb-mv-ord { opacity: 1; }
.cb-mv-ord button {
    min-width: 26px; height: 24px; padding: 0 5px; border: 0; border-radius: 6px;
    font: inherit; font-size: 11px; font-weight: 800; line-height: 1;
    background: rgba(0, 0, 0, .72); color: #fff; cursor: pointer;
}
.cb-mv-ord button:hover:not(:disabled) { background: var(--cb-accent); }
.cb-mv-ord button:disabled { opacity: .3; cursor: default; }
/* La que va primera al aire: «1º» encendido, siempre a la vista. */
.cb-mv-primera .cb-mv-1o { background: #ef4444; }
.cb-mv-primera::after {
    content: "1º"; position: absolute; top: 3px; left: 26px; padding: 0 4px;
    font-size: 10px; font-weight: 800; color: #fff; background: #ef4444; border-radius: 4px;
}
@media (hover: none) { .cb-mv-ord { opacity: 1; top: 40%; } }

/* ── El zócalo donde se quiera (2026-10-23) ────────────────────────────── */
.cb-zc-pos { gap: 6px 8px; }
.cb-zc-tam { display: inline-flex; align-items: center; gap: 6px; font-size: var(--cb-t1); font-weight: 700; color: var(--cb-dim); }
.cb-zc-tam input { width: 96px; accent-color: var(--cb-accent); }
.cb-zc-txt { font-size: var(--cb-t1); color: var(--cb-dim); }
.cb-zc-txt.cb-zc-sin { color: #fcd34d; font-weight: 700; }
.cb-zc-asa { background: rgba(14, 165, 233, .22); align-items: flex-start; }
.cb-zc-asa-sin { border-style: dotted; }
.cb-zc-asa-acc { display: inline-flex; gap: 3px; }
.cb-zc-asa .cb-zc-asa-g { background: #fff; color: #0b1220; }

/* La audiencia en un renglón bajo el reloj (2026-10-23). */
.cb-bc-cifras { font-size: var(--cb-t1); color: var(--cb-dim); white-space: nowrap; }
.cb-bc-cifras b { color: var(--cb-text); font-variant-numeric: tabular-nums; }
.cb-bc-fila1 { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }

/* Multiview: eliminar un invitado (2026-10-23). Junto al «+», en rojo al
   pasar por encima; pide confirmación (gvRemove). */
.cb-mv-quitar {
    position: absolute; top: 3px; right: 28px; width: 22px; height: 22px; padding: 0;
    font: inherit; font-size: 12px; font-weight: 800; line-height: 1; border: 0; border-radius: 6px;
    background: rgba(0, 0, 0, .6); color: #fff; cursor: pointer;
}
.cb-mv-quitar:hover { background: #ef4444; }

/* ── Multiview: invitados que aún no entran (2026-10-23) ───────────────────
   Salen desde que se les manda la invitación, en blanco y negro, con su
   estado. Se pueden sacar al aire igual: su cuadro espera. Al conectarse
   recuperan el color y un punto verde. */
.cb-mv-t.cb-mv-espera .cb-mv-v,
.cb-mv-t.cb-mv-espera .cb-mv-ini { filter: grayscale(1); opacity: .55; }
.cb-mv-t.cb-mv-espera { border-style: dashed; }
.cb-mv-estado {
    position: absolute; left: 4px; bottom: 19px; padding: 1px 6px;
    font-size: 10px; font-weight: 800; border-radius: 4px;
    background: rgba(0, 0, 0, .7); color: #cbd5e1; white-space: nowrap;
}
.cb-mv-est-conectado .cb-mv-estado { color: #4ade80; }
.cb-mv-est-abrio .cb-mv-estado { color: #fcd34d; }
.cb-mv-est-se-fue .cb-mv-estado { color: #fca5a5; }

/* ── Continuidad sin achicar el monitor (2026-10-23) ───────────────────────
   Con la cola rodando aparecía una FILA más en la botonera (50 px) y, con el
   Multiview abierto, el monitor bajaba de 804 a 583 px de ancho: «el monitor
   se está minimizando». En escritorio, los repartos y los mandos de la
   continuidad comparten línea —sobra sitio a los lados de los repartos—;
   sólo si no caben, bajan. Los mandos redondos siguen en su fila. */
@media (min-width: 821px) {
    .cb-monbar { flex-direction: row; flex-wrap: wrap; align-items: center; column-gap: var(--cb-e3); }
    .cb-monbar > .cb-monbar-repartos { order: 1; flex: 1 1 auto; justify-content: center; }
    .cb-monbar > #monCont:not([hidden]) { order: 2; flex: 0 1 auto; margin: 0; padding: 4px 8px; }
    .cb-monbar > #monCont:not([hidden]) ~ .cb-monbar-repartos { justify-content: flex-start; }
    .cb-monbar > .cb-monbar-mandos { order: 3; flex: 1 1 100%; }
    .cb-monbar > .cb-monbar-aviso { order: 4; }
    .cb-monbar > #monCont .cb-cont-tit { margin-right: 4px; }
}

/* La columna de escenas/cortinas/continuidad nunca más alta que la del
   monitor (2026-10-23): si lo era, alargaba el estudio y el ajuste de alto
   achicaba el monitor sin fin. --cb-alto-stage lo mide cbAjustarAlto(). */
@media (min-width: 821px) {
    .cb-rail-esc { max-height: min(calc(100dvh - 140px), var(--cb-alto-stage, 100dvh)); }
}

/* ── Pantalla completa: sin márgenes muertos (2026-10-23) ──────────────────
   El estudio tenía 1600 px de tope: en 1920 quedaban 174 px vacíos a cada
   lado. Y la columna de escenas acababa a media altura. Ahora el estudio
   usa todo el ancho, y la columna de la izquierda llega abajo —al alto de
   la del monitor, --cb-alto-stage— con las hojas deslizándose dentro y los
   INVITADOS siempre a la vista debajo. */
@media (min-width: 821px) {
    .cb-studio { max-width: none; }
    .cb-work { grid-template-columns: 250px minmax(0, 1fr) 96px; }
    .cb-rail-esc {
        display: flex; flex-direction: column;
        height: var(--cb-alto-stage, auto);
        max-height: var(--cb-alto-stage, calc(100dvh - 140px));
        overflow: hidden;
    }
    .cb-rail-esc > .cb-pest { flex: 0 0 auto; }
    .cb-rail-esc > .cb-hoja { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
    .cb-rail-esc > .cb-hoja[hidden] { display: none; }
    .cb-rail-esc > .cb-rail-inv { flex: 0 1 auto; max-height: 48%; }
}

.cb-rail-inv {
    display: flex; flex-direction: column; min-height: 0;
    margin-top: 10px; padding-top: 10px;
    border-top: 1px solid var(--cb-border);
}
.cb-rinv-head { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.cb-rinv-tit { font-size: var(--cb-t1); font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--cb-dim); }
.cb-rinv-n { font-size: 11px; color: var(--cb-dim); margin-right: auto; }
.cb-rinv-lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; overflow-y: auto; overscroll-behavior: contain; min-height: 0; }
.cb-rinv-f {
    display: flex; align-items: center; gap: 4px;
    padding: 5px 6px; border-radius: var(--cb-r2);
    background: var(--cb-hueco); border: 1px solid var(--cb-border);
}
.cb-rinv-f.cb-rinv-aire { border-color: #ef4444; }
.cb-rinv-dot { flex: 0 0 8px; height: 8px; border-radius: 50%; background: #64748b; }
.cb-rinv-conectado .cb-rinv-dot { background: #22c55e; box-shadow: 0 0 6px #22c55e; }
.cb-rinv-abrio .cb-rinv-dot { background: #f59e0b; }
.cb-rinv-se-fue .cb-rinv-dot { background: #ef4444; }
.cb-rinv-nom { flex: 1 1 auto; min-width: 0; display: grid; line-height: 1.2; }
.cb-rinv-nom b { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cb-rinv-nom small { font-size: 10px; color: var(--cb-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cb-rinv-aire .cb-rinv-nom small { color: #fca5a5; font-weight: 700; }
.cb-rinv-f .cb-btn-xs { padding: 3px 6px; min-height: 24px; font-size: 11px; }
.cb-rinv-vacio { margin: 0; font-size: 11px; color: var(--cb-dim); }
.cb-rinv-n, .cb-rinv-head .cb-btn { white-space: nowrap; }
.cb-rinv-head .cb-btn { padding: 4px 8px; }

/* Multiview: la continuidad, primera ventana (2026-10-23). */
.cb-mv-t.cb-mv-cont { background: linear-gradient(135deg, #1e1b4b, #312e81); cursor: pointer; }
.cb-mv-cont .cb-mv-v { opacity: .75; }
.cb-mv-cont-ico {
    position: absolute; left: 50%; top: 44%; transform: translate(-50%, -50%);
    width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
    background: rgba(0, 0, 0, .55); color: #fff; font-size: 13px; pointer-events: none;
}
.cb-mv-cont .cb-mv-estado { color: #c4b5fd; }
.cb-mv-cont.cb-mv-aire .cb-mv-estado { color: #fca5a5; }

/* Facebook con la cuenta, en Destinos (2026-10-23). */
.cb-meta { display: grid; gap: 8px; margin: 0 0 14px; padding: 12px; border-radius: var(--cb-r4); background: var(--cb-hueco); border: 1px solid rgba(24, 119, 242, .45); }
.cb-meta-tit { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cb-meta-ok { font-size: var(--cb-t1); font-weight: 700; color: #4ade80; }
.cb-meta-fila { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.cb-meta-fila .cb-input { flex: 1 1 160px; min-width: 0; }
.cb-meta .cb-note { margin: 0; }
.cb-meta-auto { display: flex; align-items: center; gap: 6px; font-size: var(--cb-t2); }
.cb-meta:empty { display: none; }
.cb-meta-err { margin: 0; padding: 6px 10px; border-radius: var(--cb-r2); background: rgba(239, 68, 68, .14); border: 1px solid rgba(239, 68, 68, .5); color: #fecaca; font-size: var(--cb-t2); }

/* ── ¿Por dónde transmitimos? (2026-10-24) ─────────────────────────────── */
.cb-tx-fondo { position: fixed; inset: 0; z-index: 9000; display: grid; place-items: center; padding: 16px; background: rgba(3, 6, 12, .72); }
.cb-tx { width: min(440px, 100%); max-height: calc(100dvh - 32px); overflow: auto; display: grid; gap: 12px; padding: 18px; border-radius: var(--cb-r4); background: var(--cb-panel, #111827); border: 1px solid var(--cb-border); box-shadow: 0 24px 60px rgba(0, 0, 0, .6); }
.cb-tx-tit { margin: 0; font-size: 18px; }
.cb-tx-lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.cb-tx-f label { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: var(--cb-r3); background: var(--cb-hueco); border: 1px solid var(--cb-border); cursor: pointer; }
.cb-tx-f input { width: 18px; height: 18px; accent-color: var(--cb-accent); flex: 0 0 auto; }
.cb-tx-f:has(input:checked) label { border-color: var(--cb-accent); }
.cb-tx-nom { display: grid; line-height: 1.25; min-width: 0; }
.cb-tx-nom b { font-size: 14px; }
.cb-tx-nom small { font-size: 12px; color: var(--cb-dim); }
.cb-tx-no label { opacity: .5; cursor: default; }
.cb-tx-err { margin: 0; color: #fca5a5; font-weight: 700; font-size: 13px; }
.cb-tx-acc { display: flex; justify-content: flex-end; gap: 8px; }
.cb-tx-f:has(.cb-tx-pag) { display: grid; gap: 6px; }
.cb-tx-pag { margin: -2px 12px 4px 40px; width: auto; }
