/* =========================================================================
   custom.css — DenunciaSegura
   REGLA DEL PROYECTO: utility-first de Bootstrap 5.3.
   Aquí SOLO va lo que Bootstrap no cubre:
     1) Paleta de marca (tonos en :root + utilidades text-/bg-/border-)
     2) Variantes de botón (vía variables --bs-btn-*)
     3) Los pocos componentes que no se pueden expresar con utilidades
   Tipografía, espaciado, alineación, grid, sombras… se hacen en el HTML con
   utilidades (fw-bold, fs-*, display-*, text-center, mb-*, py-*, g-*, ratio…).
   ========================================================================= */

/* ---------------------------------------------------------------------------
   1. PALETA DE MARCA
   Para cambiar un tono del sitio entero se toca SOLO aquí.
   Blanco, negro y grises los aporta Bootstrap (text-white, bg-light, text-secondary…).
   --------------------------------------------------------------------------- */
:root {
    /* Contraste verificado con blanco (WCAG AA exige 4.5:1 en texto normal):
       teal 5.47 · ambar-700 5.02 · teal-dark 12.06. El ámbar puro (#D97706) da
       3.19 sobre blanco, así que NO se usa como fondo de botón ni como color de
       texto: solo como fondo de badge/acento, siempre con texto oscuro (5.48). */
    --cd-teal:        #0F766E;  /* primario */
    --cd-teal-700:    #0C5F59;  /* hover/active del primario */
    --cd-teal-dark:   #0B3D39;  /* fondos oscuros y texto de marca */
    --cd-ambar:       #D97706;  /* acento: SOLO fondo con texto oscuro */
    --cd-ambar-700:   #B45309;  /* ámbar accesible: botones y texto */
    --cd-ambar-800:   #92400E;  /* hover del botón ámbar */
    --cd-soft:        #E8F2F1;  /* fondo suave de sección */
    --cd-ink:         #0F1C1B;  /* color de texto base */

    /* Curvas de easing. Las integradas de CSS son flojas: estas tienen más
       intención. Nunca ease-in en UI (arranca lento y se percibe pesado). */
    --cd-ease-out:    cubic-bezier(.23, 1, .32, 1);

    /* Overrides globales de Bootstrap */
    --bs-body-font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    --bs-body-color: var(--cd-ink);
    --bs-link-color-rgb: 15, 118, 110;        /* --cd-teal */
    --bs-link-hover-color-rgb: 12, 95, 89;    /* --cd-teal-700 */
    --bs-focus-ring-color: rgba(15, 118, 110, .25);
}

a { text-decoration: none; }

/* ---- Tipografía ----
   El tracking es específico del tamaño: cuanto más grande es el texto, más
   separadas se perciben las letras, así que el titular pide tracking negativo
   y el cuerpo se queda cerca de 0. Un letter-spacing único para todo siempre
   está mal en algún tamaño. El interlineado va al revés: ajustado en titulares
   grandes, holgado en el cuerpo (Bootstrap no tiene utilidades para esto). */
.display-1, .display-2, .display-3,
.display-4, .display-5, .display-6 { letter-spacing: -.03em; line-height: 1.06; }
h1, .h1 { letter-spacing: -.025em; }
h2, .h2 { letter-spacing: -.02em; }
h3, .h3, h4, .h4 { letter-spacing: -.01em; }

/* ---- Utilidades de color (mismo patrón que Bootstrap) ---- */
.text-teal        { color: var(--cd-teal) !important; }
.text-teal-dark   { color: var(--cd-teal-dark) !important; }
.text-ambar       { color: var(--cd-ambar-700) !important; } /* el tono accesible */

.bg-teal          { background-color: var(--cd-teal) !important; }
.bg-teal-dark     { background-color: var(--cd-teal-dark) !important; }
.bg-ambar         { background-color: var(--cd-ambar) !important; }

/* Texto encima del acento. Con el ámbar de fábrica es la tinta oscura, que es
   lo que está medido (5,48 sobre el ámbar); si la empresa pone su propio
   acento (6.3), `marca_colores` calcula cuál de los dos se lee mejor y pisa
   esta variable. ⚠️ Sin esto, un acento oscuro dejaría las pastillas con texto
   oscuro sobre fondo oscuro. */
.text-sobre-ambar { color: var(--cd-sobre-ambar, var(--cd-teal-dark)) !important; }
.bg-soft          { background-color: var(--cd-soft) !important; }

.border-teal      { border-color: var(--cd-teal) !important; }
.border-teal-dark { border-color: var(--cd-teal-dark) !important; }
.border-ambar     { border-color: var(--cd-ambar) !important; }

/* ---------------------------------------------------------------------------
   2. VARIANTES DE BOTÓN
   Solo se redefinen las variables --bs-btn-*: el resto (tamaños, focus,
   disabled, .btn-lg, .rounded-pill…) lo sigue gestionando Bootstrap.
   --------------------------------------------------------------------------- */
.btn-teal {
    --bs-btn-bg: var(--cd-teal);            --bs-btn-border-color: var(--cd-teal);            --bs-btn-color: #fff;
    --bs-btn-hover-bg: var(--cd-teal-700);  --bs-btn-hover-border-color: var(--cd-teal-700);  --bs-btn-hover-color: #fff;
    --bs-btn-active-bg: var(--cd-teal-700); --bs-btn-active-border-color: var(--cd-teal-700); --bs-btn-active-color: #fff;
    --bs-btn-disabled-bg: var(--cd-teal);   --bs-btn-disabled-border-color: var(--cd-teal);   --bs-btn-disabled-color: #fff;
}
.btn-teal-dark {
    --bs-btn-bg: var(--cd-teal-dark);       --bs-btn-border-color: var(--cd-teal-dark);       --bs-btn-color: #fff;
    --bs-btn-hover-bg: #072A27;             --bs-btn-hover-border-color: #072A27;             --bs-btn-hover-color: #fff;
    --bs-btn-active-bg: #072A27;            --bs-btn-active-border-color: #072A27;            --bs-btn-active-color: #fff;
}
/* Ámbar accesible: el tono puro no llega a AA con texto blanco (3.19).
   ⚠️ El texto sale de `--cd-sobre-ambar` (15/09), que `marca_colores` calcula con el
   acento de cada marca: con uno claro —el verde de DenunciaSegura— el texto blanco
   daba 1,32:1. Sin acento propio no hay variable y vale el blanco de siempre, que es
   lo medido sobre el ámbar-700 (5,02). ⚠️ Distinto del respaldo de `.text-sobre-ambar`,
   que va sobre el ámbar claro de las pastillas. */
.btn-ambar {
    --bs-btn-bg: var(--cd-ambar-700);        --bs-btn-border-color: var(--cd-ambar-700);        --bs-btn-color: var(--cd-sobre-ambar, #fff);
    --bs-btn-hover-bg: var(--cd-ambar-800);  --bs-btn-hover-border-color: var(--cd-ambar-800);  --bs-btn-hover-color: var(--cd-sobre-ambar, #fff);
    --bs-btn-active-bg: var(--cd-ambar-800); --bs-btn-active-border-color: var(--cd-ambar-800); --bs-btn-active-color: var(--cd-sobre-ambar, #fff);
    --bs-btn-disabled-bg: var(--cd-ambar-700); --bs-btn-disabled-border-color: var(--cd-ambar-700); --bs-btn-disabled-color: var(--cd-sobre-ambar, #fff);
}
.btn-outline-teal {
    --bs-btn-color: var(--cd-teal);          --bs-btn-border-color: var(--cd-teal);
    --bs-btn-hover-bg: var(--cd-teal);       --bs-btn-hover-border-color: var(--cd-teal);       --bs-btn-hover-color: #fff;
    --bs-btn-active-bg: var(--cd-teal);      --bs-btn-active-border-color: var(--cd-teal);      --bs-btn-active-color: #fff;
}
/* Botón sobre fondo oscuro (menú/hero): borde claro que no se pierde */
.btn-outline-light-teal {
    --bs-btn-color: #fff;                    --bs-btn-border-color: rgba(255, 255, 255, .5);
    --bs-btn-hover-bg: #fff;                 --bs-btn-hover-border-color: #fff;                 --bs-btn-hover-color: var(--cd-teal-dark);
    --bs-btn-active-bg: #fff;                --bs-btn-active-border-color: #fff;                --bs-btn-active-color: var(--cd-teal-dark);
}

/* ---------------------------------------------------------------------------
   3. COMPONENTES PROPIOS (lo que NO se puede hacer con utilidades)
   --------------------------------------------------------------------------- */

/* Respuesta al pulsar: Bootstrap cambia el color pero no da sensación táctil.
   Un 3% de escala confirma al instante que la interfaz ha registrado el clic.
   Se redeclara la transición completa porque CSS no permite añadir una
   propiedad a la de Bootstrap (color/fondo/borde/sombra en .15s). */
.btn {
    transition-property: color, background-color, border-color, box-shadow, transform;
    transition-duration: .15s;
    transition-timing-function: var(--cd-ease-out);
}
.btn:active { transform: scale(.97); }

/* ⚠️ Menos en un botón que estira su enlace a toda la caja (15/09, lo vio Juan en
   la caja «Comunicar una denuncia» de la portada de un canal). Un `transform`
   convierte al botón en el bloque contenedor de su propio `::after`, así que al
   pulsar en la caja —fuera del botón— el área clicable **se encogía de golpe al
   tamaño del botón**, el ratón se soltaba ya fuera del enlace y el navegador no
   daba el clic por hecho: solo funcionaba pulsando el botón. Las cajas con un
   enlace de texto no lo sufrían porque no llevan este efecto. */
.btn.stretched-link:active { transform: none; }

/* Elevación al pasar el puntero (Bootstrap no trae hover de transform).
   Se limita a punteros finos: en táctil el :hover se queda "pegado" tras el tap. */
.cd-hover-lift { transition: transform .15s var(--cd-ease-out), box-shadow .15s var(--cd-ease-out); }
@media (hover: hover) and (pointer: fine) {
    .cd-hover-lift:hover { transform: translateY(-3px); box-shadow: 0 .5rem 1.25rem rgba(0, 0, 0, .12) !important; }
}

/* Hero: la imagen se inyecta por variable (--cd-hero-img) desde la vista */
.cd-hero {
    background-color: var(--cd-teal-dark);
    background-image: linear-gradient(rgba(11, 61, 57, .82), rgba(11, 61, 57, .82)), var(--cd-hero-img, none);
    background-size: cover;
    background-position: center;
}

/* Círculo para icono o número de paso (medida fija: no es una utilidad de BS) */
.cd-icon-circle {
    width: 3rem;
    height: 3rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    flex: 0 0 auto;
}

/* Altura fija del logo (mantiene la proporción del SVG) */
.cd-logo { height: 30px; width: auto; }

/* Medida de línea legible. Bootstrap no tiene utilidades en `ch` y el óptimo
   de lectura son 55-75 caracteres: evita párrafos de línea larga en pantallas
   anchas. Sustituye a los style="max-width: __ch" en línea. */
.cd-measure { max-width: 60ch; }

/* Un desplegable que además de opciones lleva un aviso escrito necesita ancho
   de lectura; Bootstrap solo trae anchos en porcentaje. Lo usa el botón de
   exportar el expediente, cuyo aviso es la mitad del control. */
.cd-menu-con-aviso { min-width: 20rem; max-width: 20rem; }

/* ⚠⚠ El hilo del buzón se desplaza POR DENTRO (10/09). Con veinte mensajes
   había que bajar toda la página para llegar al cuadro de responder, y volver a
   subir para releer. Acotado, el cuadro está siempre a la vista y el recorrido
   por la conversación no arrastra al resto de la ficha.
   ⚠ Sin JavaScript se ve desde el principio —la denuncia— en vez de desde el
   final; se pierde la comodidad, no el contenido. */
/* ⚠⚠ La altura va en `vh` y no en `rem` (10/09): con 34rem fijas, en una
   pantalla de portátil **el cuadro de escribir se quedaba fuera** y había que bajar
   para responder — justo lo que este recorte venía a evitar. Lo vio Juan.
   El `clamp` pone suelo y techo: ni una rendija en una pantalla baja ni un hilo
   intransitable en un monitor grande. */
/* ⚠⚠ **Alto fijo: el máximo, siempre** (11/09, Juan —y lo había pedido antes: se
   entendió al revés y se bajó el suelo en vez de subirlo—). Con un solo mensaje la caja mide
   lo mismo que con cuarenta, así que la pantalla no cambia de forma según lo que haya
   dentro y el botón de escribir está siempre en el mismo sitio. */
.cd-hilo { height: clamp(20rem, 58vh, 44rem); overflow-y: auto; }

/* ⚠⚠ El botón de escribir se pega al borde inferior de la pantalla mientras su
   tarjeta lo cruza (10/09). La ficha es más alta que el viewport y un botón quieto
   siempre cae en el lado malo del corte: debajo del hilo se salía, y encima del hilo
   empujaba la conversación. Pegajoso va **donde le toca** —al final del hilo— y
   **flota sobre él** cuando hace falta. Es lo «flotante» que pedía Juan, pero dentro
   de su tarjeta: nunca encima de la columna derecha.
   ⚠ Sin soporte de `sticky` queda quieto, que es lo que había: no se pierde nada. */
.cd-escribir-pegajoso { position: sticky; bottom: 1rem; z-index: 3; }

/* ⚠⚠ Pestañas **sin una línea de JavaScript** (10/09, decisión de Juan: los
   archivos del expediente junto a sus datos). Son radios: el navegador cambia de
   panel él solo, como en las tres vías del formulario público. Las de Bootstrap
   necesitan su script, y sin él dejarían una sola pestaña alcanzable.
   ⚠⚠ Y el fallo se cae del lado bueno: si el navegador no entiende `:has()`, la
   regla entera no se aplica y **se ven los dos paneles**, uno debajo del otro. Nunca
   al revés — que es la regla de siempre: esconder es lo excepcional. */
.cd-pestanas:has(> .card-body > .cd-pestanas-barra > #panel-datos:checked) .cd-panel:not(.cd-panel-datos),
.cd-pestanas:has(> .card-body > .cd-pestanas-barra > #panel-archivos:checked) .cd-panel:not(.cd-panel-archivos),
.cd-pestanas:has(> .card-body > .cd-pestanas-barra > #panel-seguimiento:checked) .cd-panel:not(.cd-panel-seguimiento) {
    display: none;
}

/* Cronologia del expediente (11/09): una linea vertical une los hitos. */
.cd-cronologia li { position: relative; }
.cd-cronologia-punto { width: 1.25rem; flex-shrink: 0; text-align: center; }
.cd-cronologia li:not(:last-child)::before {
    content: ""; position: absolute; left: .6rem; top: 1.5rem; bottom: .25rem;
    border-left: 2px solid var(--bs-border-color);
}

/* ⚠⚠ **El editor de un mensaje NO es el de un texto legal** (10/09). Quill
   traía 18rem de alto mínimo —bien para redactar una página de condiciones— y en
   el buzón eso son 288px solo de caja de texto: con la barra, los adjuntos y el
   botón, media pantalla para escribir dos líneas. Es la causa de fondo de que no
   se viera el formulario entero, no el hilo de encima. */
.cd-caja-mensaje .cd-wysiwyg-editor .ql-editor { min-height: 7rem; }


/* Un `<summary>` con la forma del título de una tarjeta: sin el marcador de lista
   por defecto, que dentro de un `card-body` se sale del sitio. ⚠ La flecha es un
   icono del HTML y no un `::before` con la fuente de iconos: así se dibuja igual que
   las demás del panel y no depende de acertar con el nombre de la familia. */
.cd-summary { cursor: pointer; list-style: none; }
.cd-summary::-webkit-details-marker { display: none; }
.cd-summary .cd-flecha { transition: transform .15s ease; }
details[open] > .cd-summary .cd-flecha { transform: rotate(90deg); }

/* Respeta los saltos de línea del texto que escribió el usuario, sin permitir
   HTML. Bootstrap no tiene utilidad de white-space. */
.cd-pre-line { white-space: pre-line; }

/* Burbuja de mensaje del buzón: ancho máximo para que la línea sea legible. */
.cd-bubble { max-width: 42rem; }

/* ---- Prosa de los textos legales ----
   Es el único HTML que escribe el cliente, y Bootstrap no trae estilos para
   contenido libre (no usamos Reboot para esto porque los h2/h3 dentro de un
   aviso legal necesitan menos peso que un titular de página). */
.cd-prose > *:first-child { margin-top: 0; }
.cd-prose > *:last-child  { margin-bottom: 0; }
.cd-prose p,
.cd-prose ul,
.cd-prose ol,
.cd-prose blockquote { margin-bottom: 1rem; line-height: 1.7; }
.cd-prose h2 { font-size: 1.5rem; font-weight: 700; margin: 2rem 0 .75rem; }
.cd-prose h3 { font-size: 1.25rem; font-weight: 700; margin: 1.75rem 0 .5rem; }
.cd-prose h4 { font-size: 1.05rem; font-weight: 600; margin: 1.5rem 0 .5rem; }
.cd-prose ul,
.cd-prose ol { padding-left: 1.5rem; }
.cd-prose li { margin-bottom: .35rem; }
.cd-prose a { color: var(--cd-teal); text-decoration: underline; }
.cd-prose blockquote {
    border-left: 3px solid var(--cd-soft);
    padding-left: 1rem;
    color: #4B5563;
}

/* Editor visual del admin: Quill trae sus propios estilos, aquí solo se le da
   una altura de trabajo y se integra el botón propio de "ver el código". */
.cd-wysiwyg-editor .ql-editor { min-height: 18rem; }
.cd-ql-active { color: var(--cd-teal) !important; }

/* Código de seguimiento de la denuncia: monoespaciado y legible */
.cd-code {
    font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
    letter-spacing: .12em;
}

/* ---- Panel de administración ----
   Bootstrap no trae componente de barra lateral. Con offcanvas-lg la barra es
   desplegable en móvil y estática a partir de lg: aquí solo se fija su ancho.

   300px y no 264: con el ancho anterior, cuatro entradas del menú partían en dos
   líneas («Plantillas de investigación», «Biblioteca de respuestas», «Estado de
   la plataforma», «Campos del formulario») y la lista se leía a saltos. Ensanchar
   además ACORTA el menú, porque cada salto de línea costaba una línea entera. */
.cd-admin-sidebar { width: 300px; }
@media (min-width: 992px) { .cd-admin-sidebar { flex: 0 0 300px; } }

/* Un hijo flexible no se encoge por debajo de su contenido salvo con
   min-width:0. Bootstrap no tiene utilidad para esto y sin ella una tabla
   ancha desborda el panel. */
.cd-min-w-0 { min-width: 0; }

/* Listas reordenables (ver initSortables en custom.js). */
.cd-grab { cursor: grab; }
.cd-grab:active { cursor: grabbing; }
.cd-dragging { opacity: .45; }

/* Columna del tablero de tareas: alto mínimo para poder soltar una tarjeta en
   una columna vacía, que si no no tendría superficie donde caer. */
.cd-kanban-col { min-height: 4rem; }

/* Ítem activo del menú: subrayado que no desplaza el layout */
@media (min-width: 992px) {
    .navbar-nav .nav-link { border-bottom: 3px solid transparent; margin-bottom: -3px; }
    .navbar-nav .nav-link.active { border-bottom-color: var(--cd-ambar); }
}

/* Accesibilidad: movimiento reducido.
   No se desactiva todo: se conservan los cambios de color (ayudan a comprender
   el estado) y se elimina solo el desplazamiento y la escala. */
@media (prefers-reduced-motion: reduce) {
    .cd-hover-lift { transition: box-shadow .15s var(--cd-ease-out); }
    .cd-hover-lift:hover { transform: none; }
    .btn { transition-property: color, background-color, border-color, box-shadow; }
    .btn:active { transform: none; }
}

/* Ojo para ver la contraseña (ver initPasswordToggles en custom.js).

   Va DENTRO del campo, no como botón pegado al lado: con un `input-group` de
   Bootstrap el botón dibuja su propio borde y se lee como dos controles
   distintos. Aquí el borde es el del input y el ojo flota encima.

   El envoltorio y el botón los crea el JavaScript: si el ojo estuviera en el
   HTML, un navegador sin JS enseñaría un botón que no hace nada — y en un campo
   de contraseña eso es peor que no tenerlo. */
.cd-ojo-campo { position: relative; }

/* Sitio para el icono: sin esto, un texto largo pasa por debajo. */
.cd-ojo-campo .form-control { padding-right: 2.75rem; }

.cd-ojo {
    position: absolute;
    top: 0;
    right: 0;
    height: 100%;
    width: 2.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: none;
    color: var(--bs-secondary-color);
    border-radius: 0 var(--bs-border-radius) var(--bs-border-radius) 0;
}

.cd-ojo:hover { color: var(--cd-teal); }

/* El foco tiene que verse: es un control operable con teclado. */
.cd-ojo:focus-visible {
    outline: 0;
    color: var(--cd-teal);
    box-shadow: var(--bs-focus-ring-x, 0) var(--bs-focus-ring-y, 0)
                var(--bs-focus-ring-blur, 0) .2rem rgba(15, 118, 110, .35);
}

/* ---------------------------------------------------------------------------
   GRÁFICAS DEL PANEL DE INICIO (27/08) — Chart.js 4.5.1, vendorizado

   El lienzo lo dibuja Chart.js; aquí solo va la caja que lo contiene y la
   **lista de respaldo**, que es lo que se ve si no hay JavaScript.

   ⚠️ El respaldo NO es decorativo: sin él, un navegador sin JS enseñaría una
   caja vacía donde debería estar el estado del canal. Por eso el estado por
   defecto es «lista visible, lienzo oculto», y es el propio JavaScript el que
   le da la vuelta cuando ha comprobado que Chart existe. Al revés —ocultar la
   lista de entrada— una carga fallida del script dejaría la tarjeta en blanco.
   --------------------------------------------------------------------------- */

/* Paleta de las series. Va aquí y no en el JavaScript por lo mismo que el resto
   de la paleta: para cambiar un tono se toca un sitio. Las dos primeras son las
   de marca, así que una empresa con color propio (6.3) tiñe también sus
   gráficas. Contraste verificado sobre blanco: todas por encima de 4.5:1. */
:root {
    /* ⚠️ El orden importa: los dos verdes de la marca NO van seguidos. Puestos
       1º y 2º, en un anillo con cuatro porciones el teal y el teal oscuro
       quedaban pegados y no se distinguían — comprobado en pantalla. */
    --cd-serie-1: var(--cd-teal);
    --cd-serie-2: var(--cd-ambar-700);
    --cd-serie-3: #1D4E89;
    --cd-serie-4: #7C3AED;
    --cd-serie-5: var(--cd-teal-dark);
    --cd-serie-6: #6B7280;
}

.cd-grafica-lienzo {
    position: relative;
    height: 16rem;
}

/* El anillo pide menos alto: al lado lleva su cifra, no una serie larga. */
.cd-grafica-anillo .cd-grafica-lienzo { height: 11rem; }

/* Sin JavaScript el lienzo no existe y manda la lista. La clase la pone
   `initGraficas()` DESPUÉS de comprobar que Chart.js ha cargado. */
.cd-grafica:not(.cd-pintada) .cd-grafica-lienzo { display: none; }
.cd-grafica.cd-pintada .cd-grafica-respaldo { display: none; }

/* Una barra clicable tiene que parecerlo. */
.cd-grafica-clicable canvas { cursor: pointer; }

/* ---------------------------------------------------------------------------
   INTERRUPTOR DE ESTADO (listado de Empresas, 27/08)

   Un botón de formulario con pinta de interruptor: enseña si el canal público
   está abierto y lo cambia al pulsarlo. No es la casilla `.form-switch` de
   Bootstrap porque una casilla necesitaría JavaScript para enviarse sola, y
   esto abre o cierra un canal de denuncias.

   ⚠️ El color NO es lo único que dice el estado: al lado va la palabra
   («Abierto» / «Cerrado») y el botón lleva `role="switch"` con `aria-checked`.
   --------------------------------------------------------------------------- */
.cd-interruptor {
    width: 2.75rem;
    height: 1.5rem;
    flex: 0 0 auto;
    padding: 0;
    border: 0;
    border-radius: var(--bs-border-radius-pill);
    background-color: var(--bs-secondary-bg);
    position: relative;
    transition: background-color .15s var(--cd-ease-out);
}

.cd-interruptor::after {
    content: "";
    position: absolute;
    top: .1875rem;
    left: .1875rem;
    width: 1.125rem;
    height: 1.125rem;
    border-radius: 50%;
    background-color: #fff;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .3);
    transition: transform .15s var(--cd-ease-out);
}

.cd-interruptor[aria-checked="true"] { background-color: var(--bs-success); }
.cd-interruptor[aria-checked="true"]::after { transform: translateX(1.25rem); }

/* Se opera con teclado: el foco tiene que verse. */
.cd-interruptor:focus-visible {
    outline: 0;
    box-shadow: 0 0 0 .25rem var(--bs-focus-ring-color);
}

/* La cuenta en sesión no puede desactivarse a sí misma: su interruptor se ve,
   pero no se toca. Ausente se leería como «esta cuenta no tiene estado». */
.cd-interruptor:disabled { opacity: .45; cursor: not-allowed; }

/* El HEX junto al cuadradito de color (27/08). Ancho justo para `#RRGGBB`, y
   en monoespaciada porque se lee y se compara carácter a carácter. */
.cd-hex {
    width: 8.5rem;
    flex: 0 0 auto;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    text-transform: uppercase;
}

/* Selector de iconos del editor de bloques (27/08). El elegido se marca con el
   color de marca; `.active` lo pone el JavaScript. */
.cd-icono { width: 2.25rem; }
.cd-icono.active {
    background-color: var(--cd-teal);
    border-color: var(--cd-teal) !important;
    color: #fff;
}

/* Botón flotante de «volver arriba» (ver element/footer.php, 01/09).
   ⚠️ Nace visible y lo esconde el JavaScript; el CSS solo define el estado
   oculto. Al revés, un script que no cargue dejaría un botón invisible. */
.cd-subir {
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    z-index: 1030;            /* sobre el contenido, por debajo de modales (1055) */
    width: 2.75rem;
    height: 2.75rem;
    display: flex;            /* centra el icono sin pelearse con el line-height */
    align-items: center;
    justify-content: center;
    padding: 0;
    border-radius: 50%;
    box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .18);
    transition: opacity .2s var(--cd-ease-out), transform .2s var(--cd-ease-out),
                visibility .2s var(--cd-ease-out);
}
/* Oculto: además de no verse, no se puede pulsar NI alcanzar con el tabulador.
   Solo con opacity seguiría estando en el orden de foco, y quien navega con
   teclado se encontraría un botón que no ve. */
.cd-subir-oculto {
    opacity: 0;
    visibility: hidden;
    transform: translateY(.5rem);
    pointer-events: none;
}
@media (min-width: 992px) {
    .cd-subir { right: 1.5rem; bottom: 1.5rem; }
}
@media (prefers-reduced-motion: reduce) {
    .cd-subir { transition: opacity .2s var(--cd-ease-out), visibility .2s var(--cd-ease-out); }
    .cd-subir-oculto { transform: none; }
}

/*
 * Vista previa de un adjunto en la ficha (07/09).
 *
 * ⚠️ Con tope de altura: una foto de móvil son 4000px de alto y empujaría el
 * resto del expediente fuera de la pantalla. Se ve entera pulsándola.
 */
.cd-adjunto-previo {
    max-width: 100%;
    max-height: 22rem;
    height: auto;
}
