/**
 * cpdisenador — Editor a página completa.
 *
 * ────────────────────────────────────────────────────────────────────────────
 * TODO CUELGA DE .cpd-body, Y NO ES ESTILO: ES AISLAMIENTO
 * ────────────────────────────────────────────────────────────────────────────
 * Esta hoja se registra en el setMedia() del controlador del editor, que NO
 * llama a parent — así que en la página del editor no hay ni una regla del
 * tema. Pero el 404 de ESE MISMO controlador se sirve con el layout del tema
 * (errors/404.tpl extiende layout-full-width con ruta fija) y esta hoja sigue
 * registrada en esa petición. Si aquí hubiera un `body { margin:0 }` a secas,
 * ese 404 saldría descuadrado.
 *
 * Por eso NO hay ni una regla sobre `body`, `html` o un selector de elemento
 * suelto: todo cuelga de `.cpd-body` —la clase que pone NUESTRO layout— o del
 * prefijo `.cpd-`. Ver noEncontrado() en el controlador.
 *
 * ────────────────────────────────────────────────────────────────────────────
 * ESCALA: px, Y AQUÍ SÍ
 * ────────────────────────────────────────────────────────────────────────────
 * cparchivos.css está en rem porque vive DENTRO del tema, que fija
 * html{font-size:62.5%} y hace que 1rem = 10px. Aquí no hay tema: la página es
 * nuestra desde el <!doctype>, el html conserva su 16px de fábrica y un rem
 * valdría 16px, no 10. Escribir rem aquí daría textos un 60 % más grandes de lo
 * que parecería al copiar una medida de la otra hoja. px, y sin ambigüedad.
 *
 * ────────────────────────────────────────────────────────────────────────────
 * TIPOGRAFÍA: Inter, DESDE LOS woff2 DEL TEMA
 * ────────────────────────────────────────────────────────────────────────────
 * Los ficheros son los mismos que usa la tienda
 * (themes/akira-campoprint/assets/fonts/), declarados aquí otra vez porque el
 * @font-face del tema vive en head.tpl:80-85 y esta página no incluye ese
 * parcial. Rutas ABSOLUTAS desde la raíz del sitio: una ruta relativa se
 * resolvería contra modules/cpdisenador/views/css/.
 *
 * ⚠ ESTOS woff2 NO SIRVEN PARA EL PDF. D7 lo dice: jsPDF necesita TTF
 * embebidos, que viven dentro del módulo (views/fonts/). Los de aquí son solo
 * para la interfaz.
 *
 * ────────────────────────────────────────────────────────────────────────────
 * LO QUE CAMBIÓ EN LA PASADA DE INTERFAZ (F3-UI)
 * ────────────────────────────────────────────────────────────────────────────
 * Tres cosas de ESTRUCTURA, no de aspecto, y las tres arreglan el mismo
 * síntoma: el lienzo se movía mientras se trabajaba.
 *
 *   1. Los paneles de herramienta pasaron de hermanos en el flex a
 *      `position:absolute` sobre el área. Antes le robaban 180-240 px de ancho
 *      al lienzo y el `ResizeObserver` lo reescalaba al abrirlos.
 *   2. La barra de propiedades tiene ALTO FIJO (`--cpd-props-h`), está siempre
 *      y ocupa el ancho entero del área. Antes llevaba `hidden` y se apilaba con
 *      `flex-wrap`, así que cambiaba de alto según el tipo de objeto; y en la
 *      primera versión de F3-UI iba encajada en el ancho del lienzo y con barra
 *      de scroll, que era un control más que estorbaba en una fila de 46 px.
 *   3. El aviso de CMYK se metió dentro de esa barra. Era un <p> propio y
 *      aparecía al seleccionar una foto, con el mismo efecto.
 *
 * Y una de aspecto: los iconos ya no son caracteres tipográficos sino un
 * sprite SVG (`views/img/iconos.svg`). Ver `.cpd-ico` más abajo.
 */

@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("/themes/akira-campoprint/assets/fonts/inter-400.woff2") format("woff2");
}
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("/themes/akira-campoprint/assets/fonts/inter-500.woff2") format("woff2");
}
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("/themes/akira-campoprint/assets/fonts/inter-600.woff2") format("woff2");
}
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("/themes/akira-campoprint/assets/fonts/inter-700.woff2") format("woff2");
}

/* ==========================================================================
 * TOKENS
 *
 * Los tres colores son los del proyecto: #1f4e8c (azul acero, el de PrintHub y
 * el de la tarjeta fiscal), #cf3d73 (rosa) y #ff003f (rojo Campoprint, el del
 * botón primario de la tienda). No se inventa ninguno.
 *
 * ⚠ EL REPARTO DE LOS TRES EN EL LIENZO NO ES DECORATIVO. Cada marca técnica
 * tiene ADEMÁS un trazo distinto, porque el color solo no basta —ni para quien
 * no lo distingue, ni en una captura en blanco y negro—:
 *   · CORTE      — #1f4e8c, línea CONTINUA. Es lo único de las tres que la
 *                  máquina hace de verdad, así que es la línea "real".
 *   · SEGURIDAD  — #cf3d73, DISCONTINUA. Es un consejo, no una operación.
 *   · GUÍA       — #1f4e8c a media opacidad, TRAZO Y PUNTO. Es el dibujo
 *                  convencional de un doblez en una prueba de imprenta, y su
 *                  opacidad lo separa del corte aunque compartan tono: los dos
 *                  son marcas de máquina, y se parecen a propósito.
 *   · SANGRE     — tinte de #ff003f al 8 %. Zona, no línea: es el área que se
 *                  va a la basura.
 *
 * ── LAS TRES MEDIDAS DE ESTRUCTURA ────────────────────────────────────────
 * `--cpd-carril-w`, `--cpd-panel-w` y `--cpd-props-h` no son gustos: las
 * consumen varias reglas que tienen que casar entre sí. El `left` del panel ES
 * el ancho del carril; si divergen, el panel tapa el carril o deja una franja
 * de fondo. Escribirlas dos veces es la forma de que eso pase.
 *
 * ── LA ESCALERA DE z-index ────────────────────────────────────────────────
 * De abajo arriba, y CADA SALTO TIENE UN MOTIVO:
 *
 *    2  marcas técnicas   sobre el diseño (D3: se ven SIEMPRE)
 *   20  paneles           sobre el lienzo y sus marcas
 *   35  visor 3D          (V1b, D40) ventana flotante: sobre los paneles y el
 *                         carril (30), bajo el selector de color
 *   60  selector de color sobre los paneles (se abre desde la barra, que está
 *                         por encima del área)
 *   70  visor 3D, móvil   (V1b) a pantalla completa: tapa la hoja inferior (40)
 *                         y la leyenda (50), y queda bajo velo, toast y diálogo
 *   80  velo de guardado  sobre el selector: si un guardado arranca con el
 *                         selector abierto, el velo tiene que tapar también eso
 *   90  toast             sobre el velo, porque el aviso de «guardado» aparece
 *                         justo cuando el velo se está quitando
 *  100  diálogo           sobre todo: es lo único modal de verdad
 *
 * ⚠ HASTA F3e EL SELECTOR ESTABA EN 100 Y EL VELO EN 80, contradiciendo el
 * comentario del propio velo (que decía «por encima del selector, que está en
 * 60»). O sea: un guardado lanzado con Ctrl+S teniendo el selector abierto
 * dejaba el selector DELANTE del velo y se podía seguir toqueteando el color
 * mientras el lienzo se serializaba. Corregido aquí.
 * ========================================================================== */

.cpd-body {
    --cpd-azul: #1f4e8c;
    --cpd-azul-osc: #173c6d;
    --cpd-rosa: #cf3d73;
    --cpd-rojo: #ff003f;

    --cpd-tinta: #1a1a1a;
    --cpd-tinta-sec: #6b7280;
    --cpd-tinta-ter: #9ca3af;
    --cpd-linea: #e5e7eb;
    --cpd-fondo: #f3f4f6;
    --cpd-panel: #ffffff;

    /* 0.13.0 (UI-7) — LAS MARCAS, UNA PALETA PARA TODOS LOS FORMATOS:
     *   corte     magenta, CONTINUO — el color del CutContour del PDF (D20),
     *             ahora también en guillotina y en forma libre (que hasta
     *             0.12.0 iba discontinua);
     *   sangre    rayado GRIS (patrón `cpd-rayas` del SVG);
     *   seguridad verde, DISCONTINUO;
     *   hendido   azul, trazo y punto.
     * La leyenda pinta sus muestras con estas mismas clases (editor.tpl). */
    --cpd-corte: #e6007e;
    --cpd-seguridad: #16a34a;
    --cpd-guia: #2563eb;
    --cpd-sangre-raya: #9ca3af;
    /* P2 (D59) — la sangre de un rectángulo: cuadrícula donde el diseño no
     * llega, velo donde sí, y rojo en los tramos que faltan al pulsar «Falta
     * sangre». Más el verde y el rojo del indicador. */
    --cpd-sangre-cuad-a: #ffffff;
    --cpd-sangre-cuad-b: #d5d8de;
    --cpd-sangre-velo: rgba(255, 255, 255, 0.22);
    --cpd-sangre-falta: rgba(220, 38, 38, 0.55);
    --cpd-sangre-ok-fondo: #dcfce7;
    --cpd-sangre-ok-tinta: #166534;
    --cpd-sangre-mal-fondo: #fee2e2;
    --cpd-sangre-mal-tinta: #991b1b;
    --cpd-corte-libre: var(--cpd-corte);
    /* S2 (D77) — la zona no imprimible de un sobre: la opacidad del velo de
     * papel (el color lo pone editor.tpl, que es el del papel del lienzo), el
     * rojo de su límite y el gris de la ventana. Y el ámbar del aviso del pie
     * (D79): avisa, no es un error. */
    --cpd-velo-zona: 0.9;
    --cpd-zona-limite: #dc2626;
    --cpd-ventana: #d1d5db;
    --cpd-ventana-tinta: #4b5563;
    --cpd-zona-aviso-fondo: #fef3c7;
    --cpd-zona-aviso-tinta: #92400e;
    /* Lo que queda fuera del sticker en forma libre: blanco al 65 %, para que
     * se vea la silueta que se va a cortar sin esconder la imagen. */
    --cpd-velo-libre: rgba(255, 255, 255, 0.65);

    /* V1b (D43) — EL VISOR 3D (views/css/visor.css). El escenario es un
     * degradado radial gris muy suave, claro en el centro: el objeto se lee
     * como una pieza sobre una mesa de estudio y no como un recorte sobre
     * blanco. La sombra del suelo y el oscurecido del pliegue son negro con
     * alfa, para que tiñan cualquier cartulina sin cambiarle el tono. */
    --cpd-visor-escena-centro: #fbfbfc;
    --cpd-visor-escena-borde: #dfe2e7;
    --cpd-visor-suelo: rgba(17, 24, 39, 0.32);
    --cpd-visor-pliegue: rgba(17, 24, 39, 0.34);
    --cpd-visor-sombra: 0 12px 32px rgba(17, 24, 39, 0.22);
    --cpd-visor-duracion: 600ms;

    --cpd-barra-h: 56px;
    /* El relleno lateral del área. ⚠ NO ES UN GUSTO: la barra de propiedades lo
     * devuelve con un margen negativo del mismo valor para llegar a los bordes
     * (ver `.cpd-ed__props`). Si los dos números divergen, la barra queda
     * descuadrada respecto al área por la diferencia. */
    --cpd-area-pad-x: 16px;
    --cpd-carril-w: 76px;
    --cpd-carril-h: 62px;   /* solo en móvil, donde el carril es una fila */
    --cpd-panel-w: 300px;
    --cpd-props-h: 46px;

    /* ── LA HOJA INFERIOR (solo móvil) ──────────────────────────────────────
     * Su alto, compartido por las TRES hojas —la ficha de propiedades y los dos
     * paneles de herramienta—, porque son el mismo componente y arrastrar una
     * tiene que dejar las otras igual de altas: si cada una recordara la suya, el
     * cliente tendría que reajustar tres veces.
     *
     * Lo reescribe hojaMovil() en el `style` de `.cpd-ed` como
     * `calc(<fracción> * 100dvh)` — una FRACCIÓN y no píxeles, para que girar el
     * móvil no deje una hoja de 340 px sobre una pantalla de 390. */
    --cpd-hoja-h: 40dvh;
    --cpd-hoja-min: 0.40;
    --cpd-hoja-max: 0.85;

    margin: 0;
    background: var(--cpd-fondo);
    color: var(--cpd-tinta);
    font-family: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
    font-size: 14px;
    line-height: 1.45;
    -webkit-font-smoothing: antialiased;
}

/* El editor ocupa el viewport y NO hace scroll de página: el scroll que haya
 * será del área del lienzo. `100dvh` y no `100vh` porque en móvil la barra del
 * navegador se retrae y 100vh deja un salto. */
.cpd-ed {
    display: flex;
    flex-direction: column;
    min-height: 100dvh;
}

/* ==========================================================================
 * ICONOS
 *
 * El anfitrión de cada `<use>`. Aquí SOLO se controla el TAMAÑO: el color sale
 * de `currentColor` (que el símbolo declara) y el grosor del trazo lo declara
 * también el símbolo. No es una elección de estilo, es lo único que puede
 * funcionar — ver la nota larga de views/img/iconos.svg: las reglas CSS de esta
 * hoja NO alcanzan al contenido de un `<use>` externo, que vive en un árbol en
 * la sombra. Lo que sí entra es la herencia, y `width`/`height` se aplican al
 * `<svg>` de esta página, que sí es un elemento nuestro.
 *
 * `flex: 0 0 auto` porque casi todos van dentro de un botón flex al lado de un
 * texto, y sin él un icono se encoge cuando la etiqueta no cabe: se vería un
 * dibujo aplastado en vez de una etiqueta recortada.
 * ========================================================================== */

.cpd-ico {
    display: block;
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
}

/* ==========================================================================
 * BARRA SUPERIOR
 * ========================================================================== */

/* 0.13.0 (UI-3) — TRES ZONAS EN REJILLA, con la central centrada de verdad:
 * `1fr auto 1fr` reparte el sobrante a partes iguales a los dos lados, así que
 * las herramientas quedan en el centro de la barra midan lo que midan el
 * nombre del diseño y los botones de la derecha. Con flex y un hueco
 * «empujador» el centro se movería cada vez que cambia el nombre. Los dos
 * lados llevan `minmax(0, …)` para poder encogerse: sin él, un nombre largo
 * ensancharía su columna y descentraría el grupo. */
.cpd-ed__barra {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
    gap: 16px;
    height: var(--cpd-barra-h);
    padding: 0 16px;
    background: var(--cpd-panel);
    border-bottom: 1px solid var(--cpd-linea);
    flex: 0 0 auto;
}

.cpd-ed__barra-izq,
.cpd-ed__barra-centro,
.cpd-ed__barra-der {
    display: flex;
    align-items: center;
    gap: 16px;
    min-width: 0;
}

.cpd-ed__barra-centro {
    justify-content: center;
}

.cpd-ed__barra-der {
    justify-content: flex-end;
    gap: 10px;
}

/* El estado del guardado, a la izquierda de «Guardar». Lo escribe
 * ponerSucio() en editor.js: «Guardado» en neutro, «Cambios sin guardar» con
 * `--sucio`, y vacío en un diseño nuevo sin tocar.
 *
 * ⚠ VACÍO NO LLEVA `hidden` NI `display:none`. Es una región `aria-live` (ver
 * la nota de editor.tpl): los dos la sacan del árbol de accesibilidad, y una
 * región que no está en el árbol cuando cambia su texto no anuncia ese primer
 * cambio — que aquí es justo «Cambios sin guardar». Vacío lleva el recorte de
 * 1 px de `.cpd-ed__sr`: sigue en el árbol, sale del flujo (`position:
 * absolute`, así que ni ocupa ni cuenta para el `gap` de la barra) y no deja
 * hueco a la izquierda de «Guardar». Es el mismo recorte que en móvil.
 *
 * `flex: 0 1 auto` + `min-width: 0`: es lo primero que se recorta si la
 * columna derecha se queda sin sitio, antes que empujar los botones. */
.cpd-ed__estado {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    font-size: 12px;
    color: var(--cpd-tinta-sec);
    white-space: nowrap;
    text-overflow: ellipsis;
}

.cpd-ed__estado:empty {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
}

.cpd-ed__estado--sucio {
    color: var(--cpd-zona-aviso-tinta);
}

/* 0.19.0 — EL AVISO DEL VISITANTE: «Estás diseñando sin cuenta…» y su enlace.
 * Una franja fina entre la barra y el cuerpo, fija y discreta: el mismo ámbar
 * del aviso de la zona no imprimible, que avisa sin ser un error. Hermana de
 * la barra en la columna de `.cpd-ed`, así que no le toca el alto.
 *
 * `--error` es para UN caso: el borrador no se ha podido escribir en el
 * navegador (editor.js, avisoVisitante()). Ahí sí es un error y va en rojo. */
.cpd-ed__visitante {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    gap: 12px;
    min-width: 0;
    padding: 6px 16px;
    background: var(--cpd-zona-aviso-fondo);
    color: var(--cpd-zona-aviso-tinta);
    font-size: 12px;
    line-height: 1.35;
}

.cpd-ed__visitante--error {
    background: var(--cpd-sangre-mal-fondo);
    color: var(--cpd-sangre-mal-tinta);
}

.cpd-ed__visitante-txt {
    min-width: 0;
}

.cpd-ed__visitante-ir {
    flex: 0 0 auto;
    color: inherit;
    font-weight: 600;
    text-decoration: underline;
    white-space: nowrap;
}

.cpd-ed__visitante-ir:hover,
.cpd-ed__visitante-ir:focus {
    color: inherit;
    text-decoration: none;
}

.cpd-ed__logo {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
}

.cpd-ed__logo img {
    display: block;
    max-height: 28px;
    width: auto;
}

/* min-width:0 en un hijo de flex NO es redundante: el valor inicial es `auto`,
 * que impide encoger por debajo del contenido, y sin él un nombre de producto
 * largo empuja el botón de volver fuera de la pantalla en vez de recortarse. */
.cpd-ed__titulo {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.cpd-ed__titulo-prod {
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cpd-ed__titulo-medida {
    font-size: 12px;
    color: var(--cpd-tinta-sec);
    /* Las cifras alineadas: es un dato numérico y cambia al conmutar de
     * tamaño. Sin esto, el ancho baila al cambiar de 440 a 320. */
    font-variant-numeric: tabular-nums;
}

.cpd-ed__volver {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    border: 1px solid var(--cpd-linea);
    border-radius: 6px;
    color: var(--cpd-tinta);
    text-decoration: none;
    font-size: 13px;
    font-weight: 500;
    white-space: nowrap;
}

.cpd-ed__volver:hover,
.cpd-ed__volver:focus-visible {
    border-color: var(--cpd-azul);
    color: var(--cpd-azul);
}

/* ==========================================================================
 * CUERPO: CARRIL + PANELES + ÁREA
 *
 * ⚠ `position: relative` AQUÍ ES LO QUE SOSTIENE LOS PANELES, y tiene que
 * estar en el cuerpo y no en el área. Los paneles son `position:absolute`, y su
 * marco de referencia es el ancestro posicionado más cercano:
 *
 *   · Si fuera `.cpd-ed__area`, que tiene `overflow:auto`, el panel sería un
 *     hijo del contenedor con scroll y SE DESPLAZARÍA CON ÉL: al bajar por un
 *     lienzo ampliado, el panel se iría hacia arriba y se saldría de la vista.
 *   · Siendo el cuerpo, que no hace scroll, el panel se queda quieto encima del
 *     área pase lo que pase con el lienzo.
 * ========================================================================== */

.cpd-ed__cuerpo {
    position: relative;
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
}

/* ── EL CARRIL DE HERRAMIENTAS ──────────────────────────────────────────────
 * Fijo, estrecho y siempre visible. Icono arriba y etiqueta debajo: el icono
 * solo no basta —«Formas» y «Subidas» no tienen un dibujo universal— y la
 * etiqueta sola sería una lista de enlaces. */

.cpd-ed__carril {
    flex: 0 0 var(--cpd-carril-w);
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 6px;
    background: var(--cpd-panel);
    border-right: 1px solid var(--cpd-linea);
    /* Por encima del panel: el panel se abre A SU DERECHA y el carril tiene que
     * seguir siendo pulsable para cerrarlo o cambiar de herramienta. */
    position: relative;
    z-index: 30;
}

.cpd-ed__carril-bt {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    padding: 10px 2px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--cpd-tinta-sec);
    font: inherit;
    font-size: 11px;
    line-height: 1.2;
    cursor: pointer;
}

.cpd-ed__carril-bt:hover,
.cpd-ed__carril-bt:focus-visible {
    background: var(--cpd-fondo);
    color: var(--cpd-azul);
}

/* La herramienta con su panel abierto. Se marca con fondo Y color, no solo con
 * el panel visible: en móvil el panel es una hoja inferior que puede taparlo
 * casi todo, y el botón tiene que decir por sí solo que está activo. */
.cpd-ed__carril-bt.is-activa {
    background: rgba(31, 78, 140, 0.1);
    color: var(--cpd-azul);
}

/* F7e — el botón «Borde» nace con `hidden` y lo enseña el JS: el `display:flex`
 * de arriba pisaría el atributo sin esta regla. */
.cpd-ed__carril-bt[hidden] {
    display: none;
}

.cpd-ed__carril-ico {
    width: 22px;
    height: 22px;
}

.cpd-ed__carril-et {
    white-space: nowrap;
}

/* ── LOS PANELES SUPERPUESTOS ───────────────────────────────────────────────
 * Fuera del flujo. El área mide lo mismo abiertos que cerrados, y por eso el
 * lienzo no se mueve ni se reescala al abrirlos — que era el síntoma que esta
 * pasada venía a arreglar.
 *
 * `top/bottom: 0` y no `height`: el panel llega de la barra superior al final
 * de la ventana sea cual sea el alto, sin calcular nada. */

.cpd-ed__panel {
    position: absolute;
    top: 0;
    bottom: 0;
    left: var(--cpd-carril-w);
    z-index: 20;
    width: var(--cpd-panel-w);
    display: flex;
    flex-direction: column;
    background: var(--cpd-panel);
    border-right: 1px solid var(--cpd-linea);
    /* La sombra es lo que dice que está ENCIMA y no al lado. Sin ella, un panel
     * blanco pegado a un carril blanco parece una columna más del layout, y
     * entonces no se entiende por qué tapa el lienzo. */
    box-shadow: 4px 0 16px rgba(17, 24, 39, 0.1);
}

/* `hidden` trae `display:none` de la hoja del navegador, que pierde contra
 * cualquier `display` de autor — y arriba hay un `display:flex`. Sin esta línea
 * los dos paneles se verían SIEMPRE, uno encima del otro. Es el gotcha clásico
 * de combinar [hidden] con flex, y en esta hoja aparece seis veces. */
.cpd-ed__panel[hidden] {
    display: none;
}

.cpd-ed__panel-cab {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 12px 10px 12px 14px;
    border-bottom: 1px solid var(--cpd-linea);
}

.cpd-ed__panel-tit {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
}

/* La × de cerrar, aquí y en los dos diálogos. Sin borde: es una salida, no una
 * acción, y un recuadro la pondría al mismo nivel que «Aplicar». */
.cpd-ed__panel-x {
    border-color: transparent;
    background: transparent;
    color: var(--cpd-tinta-sec);
}

.cpd-ed__panel-x:hover,
.cpd-ed__panel-x:focus-visible {
    border-color: var(--cpd-linea);
    background: var(--cpd-fondo);
    color: var(--cpd-tinta);
}

/* El scroll es DEL CUERPO del panel y no del panel: así la cabecera con el
 * título y la × se queda fija, que es justo lo que hace falta en una biblioteca
 * de veinte imágenes. */
.cpd-ed__panel-cuerpo {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 12px 14px 16px;
}

.cpd-ed__panel-pie {
    margin: 12px 0 0;
    font-size: 11px;
    line-height: 1.4;
    color: var(--cpd-tinta-sec);
}

/* ── EL ÁREA DEL LIENZO ──────────────────────────────────────────────────── */

.cpd-ed__area {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    padding: 14px var(--cpd-area-pad-x) 28px;
    overflow: auto;
}

/* ==========================================================================
 * PESTAÑAS DE PÁGINA
 * ========================================================================== */

.cpd-ed__pags {
    display: flex;
    gap: 4px;
    flex: 0 0 auto;
}

.cpd-ed__pag {
    padding: 6px 14px;
    border: 1px solid var(--cpd-linea);
    border-radius: 6px;
    background: var(--cpd-panel);
    color: var(--cpd-tinta-sec);
    font: inherit;
    font-size: 13px;
    cursor: pointer;
}

.cpd-ed__pag.is-activa {
    border-color: var(--cpd-azul);
    color: var(--cpd-azul);
    font-weight: 600;
}

.cpd-ed__pag[disabled] {
    cursor: not-allowed;
    opacity: 0.55;
}

/* ==========================================================================
 * BARRA DE PROPIEDADES DEL OBJETO
 *
 * ⚠ EL ALTO ES FIJO, Y ES EL PUNTO DE TODO ESTE BLOQUE. La barra existe
 * siempre —con selección y sin ella— y mide lo mismo con un rectángulo que con
 * un texto, que tiene el doble de controles. Las dos cosas están para que el
 * lienzo no se mueva: en F3d la barra llevaba `hidden` y se apilaba con
 * `flex-wrap`, así que seleccionar un texto en una ventana estrecha empujaba el
 * lienzo media pantalla hacia abajo.
 *
 * ⚠ Y LO QUE NO CABE SE RECORTA, NO SE DESPLAZA. Un `flex-wrap` reparte en más
 * filas y cambia el alto, que es justo lo que no puede pasar; una barra de
 * scroll mantiene el alto pero mete un control más en una fila de 46 px, y
 * además esconde a la derecha cosas que el cliente no sabe que existen. La
 * salida es tirar lo prescindible por orden —las unidades primero, ver
 * `is-apretada-1` y `is-apretada-2` más abajo— y dejar los controles a la vista.
 * En móvil no da para tanto y ahí sí vuelve el scroll, en su media query.
 * ========================================================================== */

.cpd-ed__props {
    flex: 0 0 auto;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    height: var(--cpd-props-h);
    /* ── A ANCHO COMPLETO DEL ÁREA, SANGRANDO EL RELLENO ──────────────────
     * `align-self: stretch` la saca del `align-items: center` del área y la
     * estira al ancho de contenido; el margen negativo le devuelve el relleno
     * lateral del área, así que llega a los dos bordes. Y el mismo valor vuelve
     * como `padding`, para que los controles no queden pegados al borde.
     *
     * ⚠ EL MARGEN NEGATIVO ES HORIZONTAL Y SOLO HORIZONTAL. Uno vertical
     * rompería huecoDelLienzo(), que suma `offsetHeight` de los hermanos — y
     * `offsetHeight` NO incluye los márgenes, así que el lienzo se calcularía
     * con más sitio del que hay y se saldría por abajo. */
    align-self: stretch;
    margin: 0 calc(-1 * var(--cpd-area-pad-x));
    padding: 0 var(--cpd-area-pad-x);
    /* Sin marco: es una fila de la interfaz, no una caja. Lo único que la
     * separa del lienzo es la línea de abajo, y los grupos se separan entre sí
     * con las suyas (el ::before de cada grupo). Un recuadro redondeado aquí
     * competía con el papel, que es la única caja que debe haber en pantalla. */
    border-bottom: 1px solid var(--cpd-linea);
    /* ⚠ `hidden` Y NO `auto`: EN ESCRITORIO NO HAY BARRA DE SCROLL. Lo que no
     * cabe se resuelve recortando por prioridad —`is-apretada-1` quita las
     * unidades, `is-apretada-2` también las etiquetas de las muestras; ver
     * apretar() en editor.js— y solo si después de eso sigue sin caber se
     * recorta en silencio. La barra horizontal vuelve, y solo ahí, en la media
     * query de móvil.
     *
     * `overflow-y: hidden` explícito: un `overflow-x` a solas convierte el eje Y
     * en `auto` también, y eso metería una barra vertical de 3 px en una caja de
     * 46 px de alto. */
    overflow-x: hidden;
    overflow-y: hidden;
}

/* La frase de «no hay nada seleccionado». En gris y sin icono: es un estado de
 * reposo, no un aviso — un triángulo amarillo aquí diría que algo va mal. */
.cpd-ed__props-vacio {
    margin: 0;
    font-size: 12.5px;
    color: var(--cpd-tinta-ter);
    white-space: nowrap;
}

.cpd-ed__props-ctl {
    display: flex;
    align-items: center;
    /* Sin `gap`: la separación entre grupos la pone el ::before de cada grupo,
     * que es también el separador visible. Un gap aquí se sumaría al margen de
     * ese separador y dejaría los grupos al doble de distancia. */
    /* ⚠ `flex: 1 1 auto` + `min-width: 0` + `overflow: hidden` SON LOS TRES QUE
     * HACEN MEDIBLE EL DESBORDE. apretar() compara `scrollWidth` con
     * `clientWidth` de este elemento, y esa comparación solo dice algo si el
     * elemento puede quedarse MÁS ESTRECHO que su contenido: sin `min-width: 0`
     * un hijo de flex no baja de su tamaño de contenido, así que los dos valores
     * serían iguales siempre y la barra nunca se apretaría. */
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
}

.cpd-ed__props-vacio[hidden],
.cpd-ed__props-ctl[hidden] {
    display: none;
}

.cpd-ed__props-grupo {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
}

/* El envoltorio de las medidas (X, Y, An, Al, Giro y el candado).
 *
 * ⚠ EN ESCRITORIO TIENE QUE SER INVISIBLE, y lo es porque repite exactamente el
 * `display` y el `gap` del grupo que lo contiene: envolver esos seis controles o
 * dejarlos sueltos se pinta igual. Es la condición que permite tener UN SOLO
 * marcado para la fila y para la hoja — si alguien le cambia el `gap`, la barra
 * de escritorio se descuadra y el motivo estará en un envoltorio que solo
 * importaba en móvil. En móvil pasa a ser la rejilla de dos columnas. */
.cpd-ed__medidas {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.cpd-ed__props-grupo[hidden] {
    display: none;
}

/* EL SEPARADOR ES UN ::before DEL GRUPO, no un elemento entre grupos.
 *
 * Es lo que hace que un separador no pueda quedarse huérfano: el grupo de texto
 * y el de imagen se conmutan con `hidden`, y un <span> separador suelto entre
 * ellos seguiría visible con los dos grupos ocultos —dos rayitas juntas en
 * medio de la nada—. Siendo parte del grupo, desaparece con él.
 *
 * Lo que no puede resolver el CSS es cuál es el PRIMER grupo VISIBLE, porque
 * `:first-child` es estructural y no mira el `hidden`: con el grupo de texto
 * oculto, el de color seguiría sin ser `:first-child` y sacaría una raya al
 * principio de la barra. Eso lo marca el JS con `is-primero` en cada
 * sincronización — ver marcarPrimerGrupo() en editor.js. */
.cpd-ed__props-grupo::before {
    content: "";
    flex: 0 0 auto;
    width: 1px;
    height: 20px;
    margin: 0 11px 0 5px;
    background: var(--cpd-linea);
}

.cpd-ed__props-grupo.is-primero::before {
    display: none;
}

/* El último grupo lleva un poco de aire a la derecha: sin él, al desplazar la
 * barra hasta el final el botón de borrar queda pegado al borde y parece
 * cortado. */
.cpd-ed__props-grupo--fin {
    padding-right: 2px;
}

/* 0.13.0 (UI-5) — «Posición»: el botón y, desplegados, X e Y a su derecha. El
 * botón se marca en azul mientras está abierto. */
.cpd-ed__pos-bt[aria-expanded="true"] {
    border-color: var(--cpd-azul);
    color: var(--cpd-azul);
    background: #eef3fa;
}

.cpd-ed__pos-campos[hidden] {
    display: none;
}

/* ── RECORTE POR PRIORIDAD ──────────────────────────────────────────────────
 * Las clases las pone apretar() midiendo el desborde de verdad, no un ancho de
 * ventana: la barra de un texto tiene el doble de controles que la de un
 * rectángulo, así que un umbral en píxeles acertaría con un tipo de objeto y
 * fallaría con el otro.
 *
 * NIVEL 1 · las UNIDADES («mm», «°», «pt»). Son lo primero que se va porque son
 * lo único redundante que hay en la barra: todo el editor mide en milímetros,
 * el campo de al lado de «Giro» no puede estar en otra cosa que en grados, y
 * quien tenga duda tiene el `title` de cada control.
 *
 * NIVEL 2 · además las PALABRAS de las muestras de color («Relleno», «Borde»).
 * El cuadradito de color se queda, y con él la información: qué color es y si
 * está vacío (la diagonal). Lo que se pierde es cuál de los dos es, y eso lo
 * dice el orden —relleno antes que borde, siempre— y el `title`.
 *
 * No hay nivel 3: lo que no quepa con las dos se recorta por la derecha. Antes
 * de llegar ahí hay que quitar controles de la barra, no seguir escondiendo
 * texto. */
.cpd-ed__props.is-apretada-1 .cpd-ed__campo em,
.cpd-ed__props.is-apretada-2 .cpd-ed__campo em,
.cpd-ed__props.is-apretada-2 .cpd-ed__muestra-et {
    display: none;
}

/* ==========================================================================
 * EL LIENZO
 * ========================================================================== */

.cpd-ed__lienzo-wrap {
    /* ⚠ SIN `max-width`. Lo tuvo (900px) hasta F3-UI, y era la mitad del
     * problema del «ajustar»: en una pantalla ancha el lienzo se quedaba clavado
     * a 900 px por mucho sitio que hubiera, y la otra mitad la ponía el 68 % del
     * alto de la ventana. Ahora el hueco es el área entera y quien decide el
     * tamaño es huecoDelLienzo(), que lo mide. */
    width: 100%;
    display: flex;
    /* ⚠ `safe center` Y NO `center` A SECAS. Al acercar el zoom el lienzo se
     * hace MÁS ANCHO que este contenedor, y un hijo centrado que desborda se
     * sale por los DOS lados a la vez: el navegador deja el desbordamiento de
     * la izquierda en coordenadas negativas, donde no llega ninguna barra de
     * scroll. El resultado es que se puede ver la mitad derecha del diseño y la
     * izquierda queda inalcanzable. `safe` dice "centra mientras quepa, y
     * cuando no quepa alinea al principio", que es exactamente lo que hace
     * falta. La declaración de arriba queda como reserva para quien no lo
     * soporte: se pierde el caso del zoom, no la página. */
    justify-content: center;
    justify-content: safe center;
}

/* EL HUECO DEL LIENZO, Y LAS DOS CAPAS QUE VIVEN DENTRO.
 *
 * `position: relative` es lo que sostiene la superposición: el canvas y el SVG
 * son los dos `position:absolute` con `inset:0`, así que ocupan exactamente
 * esta caja y ni uno solo de sus píxeles se desvía del otro.
 *
 * El `aspect-ratio` lo pone la plantilla en línea, porque depende del formato.
 * `max-height` en dvh para que un formato muy alto no obligue a hacer scroll, y
 * `width:100%` para que uno muy apaisado use todo el ancho. */
.cpd-ed__lienzo {
    position: relative;
    width: 100%;
    max-height: 68dvh;
    background: var(--cpd-panel);
    /* La sombra separa el papel del fondo gris. No es adorno: sin ella, un
     * lienzo blanco sobre gris claro no tiene borde donde el papel se acaba, y
     * la banda de sangre parece el final de la hoja. */
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 8px 24px rgba(0, 0, 0, 0.08);
}

/* ⚠ EN CUANTO EL JS ARRANCA, MANDA ÉL. La clase la pone editor.js nada más
 * construir el canvas, y suelta las tres medidas de arriba porque a partir de
 * ese momento el tamaño lo calcula `aplicarZoom()` en píxeles y lo escribe en
 * el `style` del elemento.
 *
 * Sin esto el zoom estaría roto y de una forma difícil de ver: `max-height`
 * recortaría la altura al acercar, `width:100%` pelearía con el ancho en px, y
 * el lienzo se quedaría clavado al tamaño de ajuste mientras los botones + y −
 * parecen no hacer nada. El `aspect-ratio` en línea de la plantilla también
 * sobra ya, porque las dos medidas son explícitas. */
.cpd-ed__lienzo.is-js {
    width: auto;
    max-height: none;
    aspect-ratio: auto;
}

/* CAPA 1 · EL DISEÑO.
 *
 * Fabric ENVUELVE el <canvas> en un <div class="canvas-container"> propio al
 * construirse, y le pone `position:relative` y un tamaño en línea. Ese div es
 * el que hay que posicionar: colocar solo el <canvas> no serviría de nada
 * porque quedaría dentro de un contenedor sin posicionar. `.canvas-container`
 * no lleva nuestro prefijo porque el nombre lo elige Fabric, no nosotros. */
.cpd-ed__lienzo .canvas-container {
    position: absolute !important;
    inset: 0;
}

/* F7e — CAPA 0 · EL FONDO DE UN TROQUELADO (material y fondo del sticker).
 *
 * Debajo del diseño: va antes que el `.canvas-container` en el marcado y los
 * dos son absolutos, así que el orden de pintado ya lo deja debajo; el
 * `z-index: 0` lo deja escrito. Sin eventos por lo mismo que el SVG de marcas:
 * los clics tienen que llegar a Fabric. El tamaño en px lo pone el JS
 * (pintarCapaFondo()), igual que el del canvas de Fabric. */
.cpd-ed__fondo {
    position: absolute;
    top: 0;
    left: 0;
    display: block;
    pointer-events: none;
    z-index: 0;
}

/* El cuentagotas activo: Fabric pone su cursor en el canvas superior; esto
 * cubre el resto de la caja (la sangre, en un lienzo con zoom). */
.cpd-ed__lienzo.is-cuentagotas {
    cursor: crosshair;
}

/* CAPA 2 · LAS MARCAS TÉCNICAS.
 *
 * ⚠ `pointer-events: none` NO ES OPCIONAL. Sin él este SVG se come todos los
 * clics del lienzo —está encima y cubre la superficie entera— y el editor
 * quedaría inerte: se vería todo bien y no se podría seleccionar ni arrastrar
 * nada. Con él, el ratón lo atraviesa como si no existiera y llega al canvas.
 *
 * `z-index` explícito para no depender del orden del marcado: que las marcas
 * técnicas se vean SIEMPRE por encima del diseño es un requisito (D3), no una
 * casualidad de dónde está el elemento en el HTML. */
.cpd-ed__svg {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 2;
}

.cpd-ed__sangre {
    fill: url(#cpd-rayas);
}

/* P2 (D59) — la sangre de un rectángulo. La cuadrícula se ve donde la
 * máscara no la tapa (lo que el diseño no cubre); el velo, solo dentro del
 * anillo, sobre lo cubierto. Ver pintarSangre() en editor.js. */
.cpd-ed__sangre-cuad {
    fill: url(#cpd-cuadricula);
}

.cpd-ed__cuad-a {
    fill: var(--cpd-sangre-cuad-a);
}

.cpd-ed__cuad-b {
    fill: var(--cpd-sangre-cuad-b);
}

.cpd-ed__sangre-velo {
    fill: var(--cpd-sangre-velo);
}

.cpd-ed__sangre-falta {
    fill: var(--cpd-sangre-falta);
}

/* En la muestra de la leyenda, «algo de diseño» bajo el velo. */
.cpd-ed__lg-diseno {
    fill: var(--cpd-azul);
}

/* Las rayas del patrón (lienzo y muestra de la leyenda). */
.cpd-ed__raya {
    fill: var(--cpd-sangre-raya);
}

/* P2 (D59) — EL HALO DE LAS MARCAS. Cada línea (corte, seguridad, guías, y
 * sus muestras de la leyenda) lleva debajo una copia blanca más gruesa
 * (editor.tpl la pinta justo antes). Sobre un fondo de su mismo color —un
 * diseño verde con la seguridad verde, un magenta con el corte— la línea se
 * sigue viendo por sus dos filos blancos; en las discontinuas, el blanco asoma
 * entre guiones y alterna con el color. Mismo `vector-effect` que la línea:
 * en px de pantalla, igual a cualquier zoom. */
.cpd-ed__halo {
    fill: none;
    stroke: #ffffff;
    stroke-width: 3.5;
    stroke-opacity: 0.9;
}

.cpd-ed__corte {
    fill: none;
    stroke: var(--cpd-corte);
    stroke-width: 1.5;
}

.cpd-ed__seguridad {
    fill: none;
    stroke: var(--cpd-seguridad);
    stroke-width: 1;
    /* En px de pantalla y no en mm, porque el trazo lleva
     * vector-effect="non-scaling-stroke": si el grosor no escala, el patrón de
     * guiones tampoco debe hacerlo, o se vería denso en un lienzo grande. */
    stroke-dasharray: 4 3;
}

/* S2 (D77) — LA ZONA NO IMPRIMIBLE Y LA VENTANA (editor.tpl las pinta en este
 * orden: velo, límites, ventana). El velo lleva su color en línea —el del
 * papel del lienzo—; aquí solo su opacidad, y el blanco por si faltara. */
.cpd-ed__zona-velo {
    fill: #ffffff;
    fill-opacity: var(--cpd-velo-zona);
}

.cpd-ed__zona-limite {
    fill: none;
    stroke: var(--cpd-zona-limite);
    stroke-width: 1;
}

.cpd-ed__ventana {
    fill: var(--cpd-ventana);
}

/* El rótulo va en mm de lienzo (font-size en el marcado): crece y encoge con
 * el zoom, como la ventana que nombra. */
.cpd-ed__ventana-txt {
    fill: var(--cpd-ventana-tinta);
    font-weight: 600;
    text-anchor: middle;
    dominant-baseline: central;
}

/* Desde 0.13.0 (UI-7) el corte de la forma libre es el de todos: continuo. */
.cpd-ed__corte--libre {
    stroke: var(--cpd-corte-libre);
}

/* F7c + 0.13.0 — la banda de sangre de la forma libre (entre el corte y la
 * forma de sangre), con su propio patrón: el overlay es otro <svg>. */
.cpd-ed__sangre--libre {
    fill: url(#cpd-rayas-libre);
}

/* F7c (D34) — el velo de la forma libre: el lienzo menos el contorno, con
 * fill-rule evenodd, como la banda de sangre de los demás formatos. */
.cpd-ed__velo-libre {
    fill: var(--cpd-velo-libre);
}

.cpd-ed__guia {
    stroke: var(--cpd-guia);
    stroke-width: 1.5;
    stroke-dasharray: 6 2 1 2;
}

/* ==========================================================================
 * BOTONES
 *
 * Un solo botón para la barra superior, la de propiedades y los diálogos. Son
 * el mismo gesto —una acción inmediata sobre lo que hay— y tenerlos con tres
 * clases distintas acabaría en tres tamaños distintos a la primera que alguien
 * tocara uno.
 * ========================================================================== */

.cpd-ed__grupo {
    display: flex;
    align-items: center;
    gap: 4px;
    flex: 0 0 auto;
}

.cpd-ed__bt {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    flex: 0 0 auto;
    min-width: 30px;
    height: 30px;
    padding: 0 7px;
    border: 1px solid var(--cpd-linea);
    border-radius: 6px;
    background: var(--cpd-panel);
    color: var(--cpd-tinta);
    font: inherit;
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
}

.cpd-ed__bt--txt {
    padding: 0 12px;
    font-size: 12px;
    font-weight: 500;
}

.cpd-ed__bt:hover:not([disabled]),
.cpd-ed__bt:focus-visible {
    border-color: var(--cpd-azul);
    color: var(--cpd-azul);
}

/* ⚠ Y AQUÍ TAMBIÉN, que es el sitio donde más se olvida. El `display:inline-flex`
 * de arriba pisa el `display:none` que trae el atributo `hidden` —viene de la
 * hoja del NAVEGADOR y pierde contra cualquier regla de autor, con cualquier
 * especificidad—, así que sin esta línea `boton.hidden = true` no esconde nada.
 *
 * Lo necesitan dos botones de verdad, y los dos fallarían en silencio:
 *   · `#cpd-modal-no`, que el diálogo esconde cuando no hay nada que decidir
 *     (un mensaje de error tiene un botón, no dos). Se vería un «Cancelar» al
 *     lado de «Entendido», los dos haciendo lo mismo.
 *   · `#cpd-selcolor-sin`, que se esconde con un texto seleccionado: «Sin
 *     relleno» en un texto es un texto invisible, y no tiene rescate posible.
 */
.cpd-ed__bt[hidden] {
    display: none;
}

/* Igual que en los botones del carril: el aspecto apagado sale del ATRIBUTO
 * `disabled`, nunca de una clase. Así es imposible que un botón parezca
 * apagado y sea pulsable, o al revés. Aquí importa más que en ningún sitio
 * porque deshacer y rehacer se habilitan y deshabilitan solos según el estado
 * real de las pilas, muchas veces por sesión. */
.cpd-ed__bt[disabled] {
    opacity: 0.35;
    cursor: not-allowed;
}

.cpd-ed__bt.is-activa {
    border-color: var(--cpd-azul);
    background: var(--cpd-azul);
    color: #ffffff;
}

.cpd-ed__bt--peligro:hover:not([disabled]),
.cpd-ed__bt--peligro:focus-visible {
    border-color: var(--cpd-rojo);
    color: var(--cpd-rojo);
}

/* El botón principal: el único relleno de la interfaz. En una barra con diez
 * controles del mismo peso visual, «Guardar» tiene que encontrarse sin leerla
 * entera. */
.cpd-ed__bt--pri {
    border-color: var(--cpd-azul);
    background: var(--cpd-azul);
    color: #ffffff;
    font-weight: 500;
}

.cpd-ed__bt--pri:hover:not([disabled]),
.cpd-ed__bt--pri:focus-visible {
    /* El hover del botón base aclara el borde y el texto, que sobre relleno
     * azul dejaría letras azules sobre azul. Aquí se oscurece el fondo y el
     * texto se queda blanco. */
    border-color: var(--cpd-azul-osc);
    background: var(--cpd-azul-osc);
    color: #ffffff;
}

/* El botón de recorte redondeado. Su icono es el MISMO `square` que el de
 * recorte rectangular —Lucide no trae un cuadrado de esquinas muy redondeadas—
 * y lo que los distingue es este radio sobre el propio botón: el de al lado
 * lleva el radio normal de 6 px y este 50 %, así que los dos botones puestos en
 * fila dicen «ángulo recto» y «esquina redonda» sin depender del dibujo. */
.cpd-ed__bt--redondo {
    border-radius: 50%;
}

.cpd-ed__zoom-val {
    min-width: 52px;
    text-align: center;
    font-size: 12px;
    color: var(--cpd-tinta-sec);
    /* El valor cambia constantemente al pulsar + y −. Sin cifras de ancho fijo,
     * los botones de los lados se mueven a cada pulsación. */
    font-variant-numeric: tabular-nums;
}

/* Agrupa controles que van juntos y se encienden o apagan como un bloque
 * (An+Al, ancho de caja, −/pt/+, las cuatro alineaciones, trazo+grosor). */
.cpd-ed__par {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
}

/* Mismo caso que el panel: el `display` de arriba pisa el `display:none` que
 * trae el atributo `hidden`. Sin esto, las dos ramas de la barra —la de forma y
 * la de texto— se verían A LA VEZ. */
.cpd-ed__par[hidden] {
    display: none;
}

/* El icono que rotula un grupo de botones en vez de una palabra (hoy solo la
 * tijera de recortar). En gris: es una etiqueta, no un control. */
.cpd-ed__par-ico {
    width: 15px;
    height: 15px;
    color: var(--cpd-tinta-sec);
}

/* ==========================================================================
 * CAMPOS
 * ========================================================================== */

.cpd-ed__campo {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex: 0 0 auto;
    font-size: 12px;
    color: var(--cpd-tinta-sec);
    white-space: nowrap;
}

.cpd-ed__campo input {
    width: 62px;
    height: 28px;
    padding: 0 4px;
    border: 1px solid var(--cpd-linea);
    border-radius: 5px;
    background: var(--cpd-panel);
    color: var(--cpd-tinta);
    font: inherit;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

.cpd-ed__campo input:focus-visible {
    border-color: var(--cpd-azul);
    outline: none;
}

/* Fuera las flechas del number: son diminutas, en un campo de 62 px se pulsan
 * sin querer, y aquí el paso fino ya lo dan las teclas de flecha sobre el
 * lienzo (1 mm, o 10 con Shift). */
.cpd-ed__campo input::-webkit-outer-spin-button,
.cpd-ed__campo input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.cpd-ed__campo input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

.cpd-ed__campo em {
    font-style: normal;
    opacity: 0.7;
}

.cpd-ed__select {
    height: 28px;
    max-width: 170px;
    padding: 0 4px;
    border: 1px solid var(--cpd-linea);
    border-radius: 5px;
    background: var(--cpd-panel);
    color: var(--cpd-tinta);
    font: inherit;
    font-size: 12px;
}

.cpd-ed__select:focus-visible {
    border-color: var(--cpd-azul);
    outline: none;
}

.cpd-ed__campo--familia {
    /* El nombre de la familia ya lo dice el propio <select>; la etiqueta solo
     * existe para quien no ve. */
    gap: 0;
}

/* Texto solo para lectores de pantalla. No `display:none` ni
 * `visibility:hidden`: los dos lo esconden TAMBIÉN de ellos, que es lo
 * contrario de lo que se busca. Este es el recorte de 1px de toda la vida. */
.cpd-ed__sr {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

/* ==========================================================================
 * LAS DOS MUESTRAS DE COLOR DE LA BARRA
 *
 * Relleno y borde. Cada una es un botón que abre el selector para SU destino.
 * El cuadradito lleva su color en línea (lo pone el JS: es un dato, no un
 * estilo) y la etiqueta dice cuál es, porque dos cuadraditos seguidos sin texto
 * no se distinguen.
 * ========================================================================== */

.cpd-ed__muestra {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
    height: 30px;
    padding: 0 8px 0 5px;
    border: 1px solid var(--cpd-linea);
    border-radius: 6px;
    background: var(--cpd-panel);
    color: var(--cpd-tinta-sec);
    font: inherit;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
}

.cpd-ed__muestra[hidden] {
    display: none;
}

.cpd-ed__muestra:hover,
.cpd-ed__muestra:focus-visible {
    border-color: var(--cpd-azul);
    color: var(--cpd-azul);
}

.cpd-ed__muestra-cuadro {
    width: 20px;
    height: 20px;
    border-radius: 4px;
    /* El borde gris NO es decorativo: un blanco 0/0/0/0 sobre el panel blanco
     * sería un cuadradito invisible. */
    border: 1px solid var(--cpd-linea);
    background: #ffffff;
}

/* SIN color: ni relleno ni borde. La barra diagonal es el convenio de
 * cualquier editor, y dice algo que un cuadradito blanco no puede decir —el
 * blanco es un color que se imprime; «sin borde» es que no hay tinta. */
.cpd-ed__muestra-cuadro.is-vacio {
    background:
        linear-gradient(to top right,
            transparent calc(50% - 1px), var(--cpd-rojo) calc(50% - 1px),
            var(--cpd-rojo) calc(50% + 1px), transparent calc(50% + 1px)),
        #ffffff;
}

.cpd-ed__muestra-et {
    white-space: nowrap;
}

/* ==========================================================================
 * PANEL DE SUBIDAS
 * ========================================================================== */

.cpd-ed__dropzone {
    border: 2px dashed var(--cpd-linea);
    border-radius: 8px;
    background: var(--cpd-fondo);
    transition: border-color 0.12s, background 0.12s;
}

/* Mientras se arrastra algo encima. La clase la pone el JS en dragenter y la
 * quita en dragleave y en drop. */
.cpd-ed__dropzone.is-encima {
    border-color: var(--cpd-azul);
    background: rgba(31, 78, 140, 0.06);
}

/* El <label> ocupa la zona entera: así el clic funciona en todo el recuadro y
 * no solo sobre el texto. */
.cpd-ed__dropzone-lbl {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 18px 12px;
    text-align: center;
    font-size: 12px;
    line-height: 1.35;
    color: var(--cpd-tinta-sec);
    cursor: pointer;
}

/* El foco del input recortado no se ve, así que se dibuja sobre la zona: sin
 * esto, quien navega con teclado no sabe cuándo está encima. */
.cpd-ed__dropzone:focus-within {
    border-color: var(--cpd-azul);
}

.cpd-ed__dropzone-ico {
    width: 24px;
    height: 24px;
    color: var(--cpd-azul);
}

.cpd-ed__dropzone-lbl em {
    font-style: normal;
    font-size: 11px;
    opacity: 0.8;
}

.cpd-ed__subidas-progreso,
.cpd-ed__subidas-aviso {
    margin: 10px 0 0;
    font-size: 11px;
    line-height: 1.4;
}

.cpd-ed__subidas-progreso {
    color: var(--cpd-tinta-sec);
}

.cpd-ed__subidas-aviso {
    padding: 8px 10px;
    border-left: 3px solid var(--cpd-rojo);
    background: #fff5f7;
    color: var(--cpd-tinta);
}

/* `hidden` frente a los display de arriba: mismo caso que los paneles. */
.cpd-ed__subidas-progreso[hidden],
.cpd-ed__subidas-aviso[hidden] {
    display: none;
}

/* ── ESTADO VACÍO ───────────────────────────────────────────────────────────
 * «Sube tu logo o una imagen», debajo de la zona de arrastre, que sigue
 * visible: el estado vacío de esta rejilla no tiene que ofrecer una salida
 * porque la salida ya está en pantalla, justo encima. Lo pinta pintarActivos(). */

.cpd-ed__activos-vacio {
    margin: 14px 0 0;
    font-size: 12px;
    line-height: 1.4;
    text-align: center;
    color: var(--cpd-tinta-ter);
}

/* ── REJILLA DE ACTIVOS ─────────────────────────────────────────────────── */

.cpd-ed__activos {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
    margin-top: 12px;
}

/* F5b — el rótulo «De Campoprint» antes de los activos globales. Ocupa la fila
 * entera de la rejilla (`1 / -1`): es un separador, no una ficha más. */
.cpd-ed__activos-sec {
    grid-column: 1 / -1;
    margin: 8px 0 0;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: var(--cpd-tinta-ter);
}

.cpd-ed__activo {
    position: relative;
}

.cpd-ed__activo-ins {
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 100%;
    padding: 6px;
    border: 1px solid var(--cpd-linea);
    border-radius: 6px;
    background: var(--cpd-panel);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.cpd-ed__activo-ins:hover,
.cpd-ed__activo-ins:focus-visible {
    border-color: var(--cpd-azul);
}

/* `contain` y no `cover`: la miniatura tiene que enseñar la imagen ENTERA. Con
 * `cover`, un logo apaisado se vería recortado por los lados y el cliente
 * elegiría a ciegas. El fondo a cuadros deja ver la transparencia, que en un
 * logo PNG es la diferencia entre servible e inservible. */
.cpd-ed__activo-ins img {
    display: block;
    width: 100%;
    height: 64px;
    object-fit: contain;
    background-color: var(--cpd-panel);
    background-image:
        linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%),
        linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%);
    background-size: 12px 12px;
    background-position: 0 0, 6px 6px;
}

.cpd-ed__activo-nom {
    font-size: 11px;
    line-height: 1.25;
    /* Un nombre largo no puede empujar la rejilla: se corta con puntos. El
     * nombre completo sigue disponible en el `alt` de la imagen. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cpd-ed__activo-px {
    font-size: 10px;
    color: var(--cpd-tinta-sec);
    font-variant-numeric: tabular-nums;
}

/* La × flota sobre la esquina de la ficha y no dentro del botón de insertar:
 * un <button> dentro de otro <button> es HTML inválido y los navegadores lo
 * reparan de formas distintas. */
.cpd-ed__activo-del {
    position: absolute;
    top: 3px;
    right: 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: 1px solid var(--cpd-linea);
    border-radius: 50%;
    background: var(--cpd-panel);
    color: var(--cpd-tinta-sec);
    cursor: pointer;
}

.cpd-ed__activo-del .cpd-ico {
    width: 13px;
    height: 13px;
}

.cpd-ed__activo-del:hover,
.cpd-ed__activo-del:focus-visible {
    border-color: var(--cpd-rojo);
    color: var(--cpd-rojo);
}

/* ── «TUS PDF» (P3b, 0.17.1 · D65) ──────────────────────────────────────────
 * Los PDF subidos por este panel, debajo de las imágenes y con la MISMA ficha
 * (`.cpd-ed__activo`): miniatura, nombre, una línea de pie y la × de quitar.
 * Lo único propio es el estado «preparándose»: una rueda donde irá la
 * miniatura y la frase de la espera en el pie, que ahí sí puede ocupar dos
 * líneas. Solo existe en los formatos que admiten PDF (editor.tpl). */

.cpd-ed__pdfs {
    margin-top: 16px;
}

.cpd-ed__pdfs[hidden] {
    display: none;
}

.cpd-ed__pdfs .cpd-ed__activos-sec {
    margin: 0;
}

.cpd-ed__pdfs .cpd-ed__activos {
    margin-top: 8px;
}

.cpd-ed__activo--pdf.is-preparando .cpd-ed__activo-ins {
    border-style: dashed;
    color: var(--cpd-tinta);
    cursor: default;
}

.cpd-ed__activo--pdf.is-preparando .cpd-ed__activo-ins:hover {
    border-color: var(--cpd-linea);
}

/* La rueda ocupa el hueco de la miniatura (64 px): la tarjeta no cambia de
 * alto al terminar de prepararse. La misma animación que el velo de guardar. */
.cpd-ed__pdf-rueda {
    display: block;
    box-sizing: border-box;
    width: 26px;
    height: 26px;
    margin: 19px auto;
    border: 3px solid var(--cpd-linea);
    border-top-color: var(--cpd-azul);
    border-radius: 50%;
    animation: cpd-gira 0.8s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
    .cpd-ed__pdf-rueda {
        animation: none;
    }
}

.cpd-ed__pdf-estado {
    white-space: normal;
    line-height: 1.3;
}

/* D67 — «Revisa tu PDF»: el aviso de fuentes o de PDF reparado, con la página
 * afectada tal como quedará. Dentro del cuerpo libre del diálogo. */
.cpd-ed__pdf-aviso-txt {
    margin: 0 0 10px;
    font-size: 13.5px;
    line-height: 1.5;
    color: var(--cpd-tinta);
}

.cpd-ed__pdf-aviso-nota {
    margin: 10px 0 0;
    font-size: 12px;
    line-height: 1.45;
    color: var(--cpd-tinta-sec);
}

.cpd-ed__pdf-vista {
    margin: 0;
    text-align: center;
}

.cpd-ed__pdf-vista img {
    display: block;
    max-width: 100%;
    max-height: 40dvh;
    margin: 0 auto;
    border: 1px solid var(--cpd-linea);
    background: #ffffff;
}

.cpd-ed__pdf-vista figcaption {
    margin-top: 6px;
    font-size: 11px;
    color: var(--cpd-tinta-sec);
}

/* D65 — «¿Qué página quieres colocar?»: las tarjetas de `.cpd-ed__encaje` con
 * la miniatura de cada página. A cuadros, como las de la rejilla: el elemento
 * es transparente donde el PDF no pinta. */
.cpd-ed__pdf-mini {
    display: block;
    width: 100%;
    height: 96px;
    margin-bottom: 4px;
    object-fit: contain;
    border: 1px solid var(--cpd-linea);
    background-color: var(--cpd-panel);
    background-image:
        linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%),
        linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%);
    background-size: 12px 12px;
    background-position: 0 0, 6px 6px;
}

/* ==========================================================================
 * GRUPO DE IMAGEN DE LA BARRA DE PROPIEDADES
 * ========================================================================== */

/* EL SEMÁFORO DE D5.
 *
 * ⚠ EL COLOR NO ES LA ÚNICA SEÑAL: la píldora lleva SIEMPRE el número de dpi
 * escrito. Un semáforo que solo fuera color no lo leería quien no distingue el
 * rojo del verde —que es una de cada doce personas— ni se vería en una captura
 * en blanco y negro. Es el mismo criterio que las marcas técnicas del lienzo,
 * donde cada una tiene además su propio trazo. */
.cpd-ed__dpi {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    height: 22px;
    padding: 0 9px;
    border-radius: 11px;
    font-size: 11px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.cpd-ed__dpi[hidden] {
    display: none;
}

.cpd-ed__dpi.is-verde {
    background: #dcfce7;
    color: #166534;
}

.cpd-ed__dpi.is-ambar {
    background: #fef3c7;
    color: #92400e;
}

.cpd-ed__dpi.is-rojo {
    background: #fee2e2;
    color: #991b1b;
}

.cpd-ed__dpi.is-vector {
    background: #e0e7ff;
    color: #3730a3;
}

/* 0.13.0 (UI-4) — el triángulo de aviso junto al semáforo, en el color de su
 * nivel. Un botón sin marco: se puede enfocar y tocar para leer el aviso. */
.cpd-ed__dpi-alerta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 0;
    border-radius: 12px;
    background: transparent;
    cursor: help;
}

.cpd-ed__dpi-alerta[hidden] {
    display: none;
}

.cpd-ed__dpi-alerta .cpd-ico {
    width: 17px;
    height: 17px;
}

.cpd-ed__dpi-alerta.is-ambar {
    color: #b45309;
}

.cpd-ed__dpi-alerta.is-rojo {
    color: #b91c1c;
}

.cpd-ed__dpi-alerta:focus-visible {
    outline: 2px solid var(--cpd-azul);
    outline-offset: 1px;
}

/* El globo del aviso: fijo a la ventana, lo coloca editor.js bajo el botón. */
.cpd-ed__tip {
    position: fixed;
    z-index: 95;
    max-width: 280px;
    padding: 8px 10px;
    border-radius: 6px;
    background: #111827;
    color: #fff;
    font-size: 12px;
    line-height: 1.4;
    box-shadow: 0 6px 18px rgba(17, 24, 39, 0.25);
    pointer-events: none;
}

.cpd-ed__tip[hidden] {
    display: none;
}

/* El aviso de CMYK (D6), ahora una píldora dentro de la barra y no un párrafo
 * debajo: ver la cabecera de esta hoja. En azul y con el icono de información
 * porque no es una alarma —no hay nada que corregir— sino cómo funciona la
 * impresión. La frase larga vive en el `title`. */
.cpd-ed__cmyk {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex: 0 0 auto;
    height: 22px;
    padding: 0 9px 0 7px;
    border-radius: 11px;
    background: #eef3fa;
    color: #1e3a5f;
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
    cursor: help;
}

.cpd-ed__cmyk[hidden] {
    display: none;
}

.cpd-ed__cmyk .cpd-ico {
    width: 13px;
    height: 13px;
}

/* ==========================================================================
 * PANEL DE FORMAS
 * ========================================================================== */

.cpd-ed__formas {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.cpd-ed__forma {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 10px;
    border: 1px solid transparent;
    border-radius: 6px;
    background: transparent;
    color: var(--cpd-tinta);
    font: inherit;
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}

.cpd-ed__forma:hover,
.cpd-ed__forma:focus-visible {
    border-color: var(--cpd-azul);
    color: var(--cpd-azul);
}

.cpd-ed__forma-ico {
    width: 20px;
    height: 20px;
}

/* ==========================================================================
 * PANEL DEL BORDE (F7e, D28 y D36)
 * ========================================================================== */

.cpd-ed__borde-grosor {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 0 0 14px;
}

.cpd-ed__borde-et {
    font-size: 13px;
    color: var(--cpd-tinta-sec);
}

.cpd-ed__borde-et output {
    font-weight: 600;
    color: var(--cpd-tinta);
}

.cpd-ed__borde-rango {
    width: 100%;
    accent-color: var(--cpd-azul);
}

.cpd-ed__borde-modos {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

/* El modo elegido, como la herramienta activa del carril. */
.cpd-ed__borde-modos .cpd-ed__forma.is-activa {
    border-color: var(--cpd-azul);
    background: rgba(31, 78, 140, 0.1);
    color: var(--cpd-azul);
}

.cpd-ed__borde-modos .cpd-ed__forma:disabled {
    color: var(--cpd-tinta-ter);
    border-color: transparent;
    cursor: not-allowed;
}

.cpd-ed__borde-color {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 12px;
}

.cpd-ed__borde-color[hidden] {
    display: none;
}

.cpd-ed__borde-muestra {
    width: 34px;
    height: 34px;
    padding: 0;
    border: 1px solid var(--cpd-linea);
    border-radius: 6px;
    cursor: pointer;
}

.cpd-ed__borde-cmyk {
    flex: 1 1 auto;
    font-size: 12px;
    color: var(--cpd-tinta-sec);
    font-variant-numeric: tabular-nums;
}

#cpd-borde-cuentagotas.is-activa {
    color: var(--cpd-azul);
    background: rgba(31, 78, 140, 0.1);
}

/* ==========================================================================
 * LEYENDA
 * ========================================================================== */

/* P2 (D59) — EL INDICADOR DE SANGRE, sobre la leyenda. El globo cuelga de
 * él (posición absoluta, hacia arriba) para no mover el lienzo al abrirse. */
.cpd-ed__sangre-pie {
    position: relative;
    display: flex;
    justify-content: center;
}

.cpd-ed__sangre-pie[hidden] {
    display: none;
}

.cpd-ed__sangre-estado {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 26px;
    padding: 0 12px;
    border: 0;
    border-radius: 13px;
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
}

.cpd-ed__sangre-estado::before {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: currentColor;
}

.cpd-ed__sangre-estado.is-ok {
    background: var(--cpd-sangre-ok-fondo);
    color: var(--cpd-sangre-ok-tinta);
}

.cpd-ed__sangre-estado.is-mal {
    background: var(--cpd-sangre-mal-fondo);
    color: var(--cpd-sangre-mal-tinta);
}

/* S2 (D79) — EL INDICADOR DE LA ZONA NO IMPRIMIBLE. La misma píldora que el
 * de sangre, pero informa y no se pulsa; en ámbar cuando algo toca la zona.
 * Su frase de aviso es larga: en un móvil parte en dos líneas en vez de
 * salirse. `cpd-ed__estados` es la fila que los junta cuando conviven. */
.cpd-ed__estados {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 6px 8px;
}

.cpd-ed__zona-estado {
    height: auto;
    min-height: 26px;
    margin: 0;
    padding-top: 4px;
    padding-bottom: 4px;
    cursor: default;
    line-height: 1.3;
}

.cpd-ed__zona-estado::before {
    flex: none;
}

.cpd-ed__zona-estado.is-aviso {
    background: var(--cpd-zona-aviso-fondo);
    color: var(--cpd-zona-aviso-tinta);
}

.cpd-ed__sangre-estado:focus-visible {
    outline: 2px solid var(--cpd-azul);
    outline-offset: 2px;
}

.cpd-ed__sangre-globo {
    position: absolute;
    bottom: calc(100% + 8px);
    left: 50%;
    z-index: 30;
    width: min(340px, calc(100vw - 32px));
    padding: 12px 14px;
    border: 1px solid var(--cpd-linea);
    border-radius: 10px;
    background: var(--cpd-panel);
    box-shadow: 0 8px 24px rgba(17, 24, 39, 0.18);
    transform: translateX(-50%);
    font-size: 13px;
    line-height: 1.45;
    color: var(--cpd-tinta);
}

.cpd-ed__sangre-globo[hidden] {
    display: none;
}

.cpd-ed__sangre-globo-txt {
    margin: 0 0 10px;
}

.cpd-ed__sangre-globo-bts {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

/* P2 (D59) — los ppp EN VIVO al escalar una imagen: junto al puntero (o
 * encima del objeto, con el dedo). Fija al viewport y sin eventos; mismos
 * colores que la pastilla del semáforo. */
.cpd-ed__ppp-vivo {
    position: fixed;
    z-index: 80;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 12px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    pointer-events: none;
    box-shadow: 0 2px 6px rgba(17, 24, 39, 0.18);
}

.cpd-ed__ppp-vivo[hidden] {
    display: none;
}

.cpd-ed__ppp-vivo.is-verde {
    background: #dcfce7;
    color: #166534;
}

.cpd-ed__ppp-vivo.is-ambar {
    background: #fef3c7;
    color: #92400e;
}

.cpd-ed__ppp-vivo.is-rojo {
    background: #fee2e2;
    color: #991b1b;
}

.cpd-ed__leyenda {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 20px;
    margin: 0;
    padding: 0;
    list-style: none;
    max-width: 900px;
    font-size: 12px;
    color: var(--cpd-tinta-sec);
}

.cpd-ed__leyenda li {
    display: flex;
    align-items: center;
    gap: 6px;
}

.cpd-ed__leyenda em {
    font-style: normal;
    opacity: 0.8;
}

/* F7b (D27) — «Sticker cortado: 80 × 50 mm», bajo el lienzo de un troquelado.
 * Mismo cuerpo y color que la leyenda: es un dato, no un aviso. */
.cpd-ed__real {
    margin: 0;
    font-size: 12px;
    font-weight: 600;
    color: var(--cpd-tinta-sec);
}

/* F7c — en forma libre la misma línea dice también el estado: sin imagen,
 * calculando o sin forma detectada. Este último en el rojo de los errores. */
.cpd-ed__real.is-aviso {
    color: var(--cpd-rojo);
}

/* 0.13.0 (UI-6) — «Sticker: 11,2 × 6,3 cm» destacado y «Documento con
 * sangre: 11,6 × 6,7 cm» en gris al lado (debajo si no cabe). */
.cpd-ed__real {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: center;
    gap: 2px 14px;
}

.cpd-ed__real-sticker {
    font-size: 14px;
    font-weight: 700;
    color: var(--cpd-tinta);
    font-variant-numeric: tabular-nums;
}

.cpd-ed__real-doc {
    font-weight: 400;
    color: var(--cpd-tinta-ter);
    font-variant-numeric: tabular-nums;
}

/* F7c (D35) — la barra de medida de la forma libre, encima del lienzo: el
 * ancho editable (o bloqueado en modo caja), el alto en grande y la calidad. */
.cpd-ed__medida-libre {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 16px;
    font-size: 13px;
    color: var(--cpd-tinta-sec);
}

.cpd-ed__medida-campo {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
}

.cpd-ed__medida-input {
    width: 80px;
    padding: 4px 6px;
    border: 1px solid var(--cpd-linea);
    border-radius: 4px;
    font: inherit;
    font-size: 15px;
    font-weight: 600;
    color: var(--cpd-tinta);
}

.cpd-ed__medida-input:disabled {
    background: var(--cpd-fondo);
    color: var(--cpd-tinta-sec);
    cursor: not-allowed;
}

.cpd-ed__medida-input[aria-invalid="true"] {
    border-color: var(--cpd-rojo);
}

.cpd-ed__medida-alto strong {
    font-size: 18px;
    color: var(--cpd-tinta);
}

.cpd-ed__medida-error {
    flex-basis: 100%;
    color: var(--cpd-rojo);
    font-size: 12px;
}

.cpd-ed__medida-error[hidden] {
    display: none;
}

.cpd-ed__pedir[hidden] {
    display: none;
}

/* 0.13.0 (UI-7) — las muestras de la leyenda son <svg> de 24 × 12 con un
 * trazo que lleva las MISMAS CLASES que las marcas del lienzo, así que color,
 * grosor y guiones no pueden divergir. Aquí solo el tamaño y, para la sangre,
 * su rectángulo rayado con un contorno gris que lo recorta. */
.cpd-ed__lg {
    display: inline-block;
    flex: 0 0 auto;
    width: 24px;
    height: 12px;
    overflow: visible;
}

.cpd-ed__sangre-lg {
    fill: url(#cpd-rayas-lg);
    stroke: var(--cpd-sangre-raya);
    stroke-width: 1;
}

/* ==========================================================================
 * SELECTOR DE COLOR (F3d)
 *
 * Diálogo centrado sobre un velo. Va en `position:fixed` respecto a la
 * VENTANA, y eso solo se cumple mientras ningún ancestro tenga `transform`,
 * `filter` ni `perspective`: cualquiera de los tres convierte a ese ancestro
 * en el marco de referencia y el diálogo se anclaría a él. Hoy no hay ninguno
 * en la cadena; si algún día se le pone una transición de escala a .cpd-ed o a
 * su cuerpo, este panel aparecerá descolocado y el motivo no saltará a la
 * vista.
 * ========================================================================== */

.cpd-ed__sel {
    position: fixed;
    inset: 0;
    z-index: 60;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}

/* El `display:flex` de arriba pisa el `display:none` del atributo `hidden`.
 * Sin esta línea el selector se vería siempre y taparía el editor entero. */
/* P2 (D58) — «Este color no se puede imprimir exacto: se verá así.» */
.cpd-ed__sel-aviso {
    margin: 4px 0 8px;
    padding: 6px 8px;
    border-radius: 6px;
    background: #fff7e6;
    color: #8a5300;
    font-size: 12px;
    line-height: 1.4;
}

.cpd-ed__sel-aviso[hidden] {
    display: none;
}

.cpd-ed__sel[hidden] {
    display: none;
}

/* El velo es un botón a pantalla completa: cerrar tocando fuera. Sin borde,
 * sin fondo propio más que el tinte, y fuera del orden de tabulación
 * (`tabindex="-1"` en el marcado) para que tabular dentro del diálogo no
 * empiece por «cerrar». */
.cpd-ed__sel-velo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: rgba(17, 24, 39, 0.45);
    cursor: pointer;
}

.cpd-ed__sel-panel {
    position: relative;
    width: 100%;
    max-width: 360px;
    /* Con el modo RGB abierto y los doce de la paleta, en una ventana baja no
     * cabe: el panel hace su propio scroll en vez de salirse por abajo. */
    max-height: calc(100dvh - 32px);
    overflow-y: auto;
    padding: 16px;
    border-radius: 10px;
    background: var(--cpd-panel);
    box-shadow: 0 12px 32px rgba(17, 24, 39, 0.25);
}

.cpd-ed__sel-cab {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 12px;
}

.cpd-ed__sel-tit {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
}

/* La muestra grande y sus cuatro valores. Es lo primero que se ve y lo que
 * responde a «¿qué va a salir impreso?». */
.cpd-ed__sel-actual {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 14px;
}

.cpd-ed__sel-muestra {
    flex: 0 0 auto;
    width: 64px;
    height: 48px;
    border: 1px solid var(--cpd-linea);
    border-radius: 6px;
    background: #ffffff;
}

.cpd-ed__sel-valores {
    font-size: 12px;
    color: var(--cpd-tinta-sec);
    /* Los cuatro números cambian a cada movimiento del deslizador; sin cifras
     * de ancho fijo la línea entera baila. */
    font-variant-numeric: tabular-nums;
}

.cpd-ed__sel-modos {
    display: flex;
    gap: 4px;
    margin-bottom: 12px;
}

.cpd-ed__sel-cmyk,
.cpd-ed__sel-rgb {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 14px;
}

/* Otra vez el atributo `hidden` contra un `display` propio: las dos ramas del
 * selector se conmutan, y sin esto se verían las dos a la vez. */
.cpd-ed__sel-cmyk[hidden],
.cpd-ed__sel-rgb[hidden],
.cpd-ed__sel-bloque[hidden] {
    display: none;
}

.cpd-ed__sel-fila {
    display: flex;
    align-items: center;
    gap: 8px;
}

.cpd-ed__sel-canal {
    flex: 0 0 auto;
    min-width: 22px;
    font-size: 12px;
    font-weight: 600;
    color: var(--cpd-tinta-sec);
}

.cpd-ed__sel-rango {
    flex: 1 1 auto;
    min-width: 0;
    height: 20px;
    /* El degradado del carril es del BLANCO A LA TINTA PURA de ese canal, y es
     * fijo: no simula la mezcla con los otros tres. Simularla exigiría
     * repintar cuatro degradados en cada movimiento para acabar enseñando una
     * aproximación RGB de una mezcla de tintas —justo lo que D6 dice que no se
     * hace—. Así el carril dice lo único que sí es cierto: hacia dónde sube
     * ESTE canal. */
    accent-color: var(--cpd-azul);
    cursor: pointer;
}

.cpd-ed__sel-rango--c { accent-color: #00aeef; }
.cpd-ed__sel-rango--m { accent-color: #ec008c; }
.cpd-ed__sel-rango--y { accent-color: #fff200; }
.cpd-ed__sel-rango--k { accent-color: #1a1a1a; }

.cpd-ed__sel-num,
.cpd-ed__sel-hex {
    flex: 0 0 auto;
    width: 62px;
    height: 28px;
    padding: 0 6px;
    border: 1px solid var(--cpd-linea);
    border-radius: 5px;
    background: var(--cpd-panel);
    color: var(--cpd-tinta);
    font: inherit;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

.cpd-ed__sel-num:focus-visible,
.cpd-ed__sel-hex:focus-visible {
    border-color: var(--cpd-azul);
    outline: none;
}

.cpd-ed__sel-hex {
    width: 110px;
    text-transform: lowercase;
}

.cpd-ed__sel-rgbtrio {
    display: flex;
    gap: 8px;
}

.cpd-ed__sel-fila--rgb {
    flex: 1 1 0;
}

.cpd-ed__sel-fila--rgb .cpd-ed__sel-num {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
}

.cpd-ed__sel-nota {
    margin: 0;
    font-size: 11px;
    line-height: 1.4;
    color: var(--cpd-tinta-sec);
}

.cpd-ed__sel-bloque {
    margin-bottom: 14px;
}

.cpd-ed__sel-sub {
    margin: 0 0 8px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--cpd-tinta-sec);
}

/* Seis por fila: los doce de la paleta caben en dos filas exactas y los ocho
 * recientes en dos. Rejilla y no flex para que las dos listas se alineen entre
 * sí aunque tengan distinto número de colores. */
.cpd-ed__sel-colores {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 6px;
}

.cpd-ed__sel-color {
    height: 28px;
    padding: 0;
    /* Igual que en las muestras: sin borde, el blanco de la paleta sobre el
     * panel blanco sería un botón invisible. */
    border: 1px solid var(--cpd-linea);
    border-radius: 5px;
    cursor: pointer;
}

.cpd-ed__sel-color:hover,
.cpd-ed__sel-color:focus-visible {
    border-color: var(--cpd-tinta);
}

/* El color que está cargado ahora mismo en los controles. El doble anillo
 * (borde oscuro + halo blanco por dentro) se ve sobre cualquier color, que es
 * lo que un borde de un solo tono no consigue: sobre negro o sobre blanco uno
 * de los dos desaparece. */
.cpd-ed__sel-color.is-activa {
    border-color: var(--cpd-tinta);
    box-shadow: inset 0 0 0 2px var(--cpd-panel);
}

/* «Sin relleno» a la izquierda y «Aplicar» a la derecha, separados por todo el
 * hueco: son las dos salidas del diálogo y ninguna es la otra. `space-between`
 * y no un `gap`, porque el de la izquierda no debe quedar al lado del primario
 * — un clic errado ahí borra el color de una forma. */
.cpd-ed__sel-pie {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

/* ==========================================================================
 * VELO DE GUARDADO
 *
 * `position: fixed` respecto a la VENTANA, y eso solo se cumple mientras
 * ningún ancestro tenga `transform`, `filter` ni `perspective`: cualquiera de
 * los tres convierte a ese ancestro en el marco de referencia. Es la misma
 * advertencia que lleva el selector de color, y por el mismo motivo — si algún
 * día se le pone una transición de escala a .cpd-ed, este velo tapará solo un
 * trozo de la pantalla y el motivo no saltará a la vista.
 * ========================================================================== */

.cpd-ed__velo {
    position: fixed;
    inset: 0;
    z-index: 80;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(26, 26, 26, 0.55);
}

.cpd-ed__velo[hidden] {
    /* `hidden` pierde contra `display: flex` en la cascada: el atributo trae
     * `display: none` de la hoja del navegador, que tiene menos peso que
     * cualquier regla de autor. Sin esta línea el velo se quedaría puesto para
     * siempre — y con él, el editor inservible. */
    display: none;
}

.cpd-ed__velo-caja {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 20px 26px;
    border-radius: 10px;
    background: var(--cpd-panel);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.25);
}

.cpd-ed__velo-spin {
    width: 22px;
    height: 22px;
    flex: 0 0 auto;
    border: 3px solid var(--cpd-linea);
    border-top-color: var(--cpd-azul);
    border-radius: 50%;
    animation: cpd-gira 0.8s linear infinite;
}

.cpd-ed__velo-txt {
    margin: 0;
    font-size: 15px;
    font-weight: 500;
    color: var(--cpd-tinta);
}

@keyframes cpd-gira {
    to { transform: rotate(360deg); }
}

/* Quien ha pedido menos movimiento no quiere una ruleta girando: se queda como
 * un anillo quieto, que sigue diciendo «aquí pasa algo» sin marear. El texto
 * del velo es lo que de verdad informa. */
@media (prefers-reduced-motion: reduce) {
    .cpd-ed__velo-spin {
        animation: none;
    }
}

/* ==========================================================================
 * EL AVISO EFÍMERO
 *
 * Abajo y centrado, no arriba: arriba está la barra, que es donde el cliente
 * acaba de pulsar, y un mensaje que aparece justo donde estaba el cursor tapa
 * lo que quería mirar después.
 *
 * Centrado y no en la esquina derecha (como en F3e) porque en móvil el carril
 * de herramientas está ahora ABAJO: un toast en la esquina taparía el botón de
 * «Formas» durante tres segundos.
 * ========================================================================== */

.cpd-ed__toast {
    position: fixed;
    left: 50%;
    bottom: 22px;
    z-index: 90;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 9px;
    max-width: calc(100vw - 32px);
    margin: 0;
    padding: 11px 16px;
    border-radius: 8px;
    background: var(--cpd-tinta);
    color: #ffffff;
    font-size: 13.5px;
    font-weight: 500;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.25);
}

.cpd-ed__toast[hidden] {
    display: none;
}

/* El icono lleva el TONO, y el fondo se queda oscuro en los tres casos: un
 * toast rojo a pantalla completa para «le hemos puesto un borde» sería una
 * alarma por algo que el editor acaba de arreglar solo. El color va en el
 * dibujo, que es lo que se mira. */
.cpd-ed__toast-ico {
    width: 17px;
    height: 17px;
    color: #4ade80;
}

.cpd-ed__toast.is-aviso .cpd-ed__toast-ico {
    color: #fbbf24;
}

.cpd-ed__toast.is-info .cpd-ed__toast-ico {
    color: #93c5fd;
}

.cpd-ed__toast-txt {
    /* Un mensaje largo se parte en dos líneas en vez de salirse: el toast no
     * tiene ancho fijo, tiene ancho máximo. */
    min-width: 0;
}

/* ==========================================================================
 * EL DIÁLOGO
 *
 * Uno para los cinco casos (nombre al guardar, borrar imagen, salir con
 * cambios, dpi en rojo, error de servidor). Lo compone dialogo() en editor.js.
 *
 * `z-index: 100`, el más alto de la escalera: es lo único modal de verdad y
 * tiene que poder salir POR ENCIMA del velo de guardado (que está en 80),
 * porque el error de un guardado que ha fallado se enseña con el velo todavía
 * puesto.
 * ========================================================================== */

.cpd-ed__modal {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}

.cpd-ed__modal[hidden] {
    display: none;
}

.cpd-ed__modal-velo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: rgba(17, 24, 39, 0.55);
    cursor: pointer;
}

.cpd-ed__modal-caja {
    position: relative;
    width: 100%;
    max-width: 420px;
    max-height: calc(100dvh - 32px);
    overflow-y: auto;
    padding: 20px;
    border-radius: 10px;
    background: var(--cpd-panel);
    box-shadow: 0 16px 48px rgba(17, 24, 39, 0.3);
}

.cpd-ed__modal-cab {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
    /* El hueco de la × (F6). */
    padding-right: 32px;
}

/* La × de la esquina (F6). La inyecta comun.js en todos los diálogos —ver su
 * `botonCerrar()`— con la clase de TIENDA, `cpd-modal__x`, porque el marcado
 * lo crea el JS y no sabe en qué página está. Aquí se pinta con la escala del
 * editor; en la tienda la pinta comun.css, que esta página no carga. Misma
 * forma que la × de los paneles (`.cpd-ed__panel-x`). */
.cpd-ed__modal .cpd-modal__x {
    position: absolute;
    top: 14px;
    right: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 6px;
    background: transparent;
    color: var(--cpd-tinta-sec);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
}

.cpd-ed__modal .cpd-modal__x:hover,
.cpd-ed__modal .cpd-modal__x:focus-visible {
    border-color: var(--cpd-linea);
    background: var(--cpd-fondo);
    color: var(--cpd-tinta);
}

.cpd-ed__modal-ico[hidden] {
    display: none;
}

/* El icono en su propio disco de color, que es lo que lleva el tono del
 * diálogo. El JS cambia las dos cosas a la vez (el símbolo y la clase del
 * disco): ver dialogo(). */
.cpd-ed__modal-ico {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: #eef3fa;
    color: var(--cpd-azul);
}

.cpd-ed__modal-ico.is-aviso {
    background: #fef3c7;
    color: #92400e;
}

.cpd-ed__modal-ico.is-peligro {
    background: #fee2e2;
    color: #991b1b;
}

.cpd-ed__modal-tit {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
}

.cpd-ed__modal-txt {
    margin: 0 0 10px;
    font-size: 13.5px;
    line-height: 1.5;
    color: var(--cpd-tinta-sec);
}

.cpd-ed__modal-txt[hidden],
.cpd-ed__modal-lista[hidden],
.cpd-ed__modal-campo[hidden],
.cpd-ed__modal-error[hidden] {
    display: none;
}

/* Una LISTA de verdad y no un párrafo con saltos de línea, que es lo que hacía
 * el `confirm` nativo: «estas imágenes se imprimirán mal» son tres cosas, y
 * quien no ve la pantalla necesita oír «lista de 3 elementos». */
/* 0.13.0 (D37) — el cuerpo libre del diálogo (pedir.js). Vacío no ocupa. */
.cpd-ed__modal-cuerpo {
    margin-bottom: 16px;
}

.cpd-ed__modal-cuerpo:empty {
    display: none;
}

/* P2 (0.16.0, D56) — «Tu PDF tiene otra proporción»: una tarjeta por opción
 * (Girar, Ajustar, Rellenar) con la vista previa de cómo quedaría. Rejilla
 * auto-fill: tres en fila en escritorio y una debajo de otra a 390 px. */
.cpd-ed__encaje {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 10px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.cpd-ed__encaje-op {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    width: 100%;
    padding: 10px;
    border: 1px solid var(--cpd-linea);
    border-radius: 8px;
    background: var(--cpd-panel);
    color: var(--cpd-tinta);
    font: inherit;
    font-size: 12px;
    text-align: center;
    cursor: pointer;
}

.cpd-ed__encaje-op:hover,
.cpd-ed__encaje-op:focus-visible {
    border-color: var(--cpd-azul);
    outline: none;
    box-shadow: inset 0 0 0 1px var(--cpd-azul);
}

.cpd-ed__encaje-op strong {
    font-size: 14px;
}

.cpd-ed__encaje-op span {
    color: var(--cpd-tinta-sec);
}

.cpd-ed__encaje-vista {
    display: block;
    max-width: 100%;
    margin-bottom: 4px;
    border: 1px solid var(--cpd-linea);
    background: var(--cpd-fondo);
}

.cpd-ed__modal-lista {
    margin: 0 0 12px;
    padding-left: 18px;
    font-size: 13px;
    line-height: 1.55;
    color: var(--cpd-tinta);
}

.cpd-ed__modal-campo {
    display: flex;
    flex-direction: column;
    gap: 5px;
    margin-bottom: 4px;
    font-size: 12px;
    color: var(--cpd-tinta-sec);
}

.cpd-ed__modal-campo input {
    width: 100%;
    height: 36px;
    padding: 0 10px;
    border: 1px solid var(--cpd-linea);
    border-radius: 6px;
    background: var(--cpd-panel);
    color: var(--cpd-tinta);
    font: inherit;
    font-size: 14px;
}

.cpd-ed__modal-campo input:focus-visible {
    border-color: var(--cpd-azul);
    outline: none;
}

.cpd-ed__modal-error {
    margin: 8px 0 0;
    font-size: 12px;
    color: #991b1b;
}

.cpd-ed__modal-pie {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 18px;
}

/* ==========================================================================
 * LO QUE SOLO EXISTE EN LA HOJA MÓVIL
 *
 * Seis piezas viven en el marcado siempre y solo se ven por debajo de 720 px:
 * las etiquetas de fila, el chrome de la hoja (asa y «Listo»), el asa de la
 * leyenda, los botones de paso −/+ y lo marcado como `--solo-movil` (hoy «Sin
 * relleno» y el botón de la leyenda de la barra superior).
 *
 * ⚠ ESTE BLOQUE VA AL FINAL DE LA HOJA BASE, Y NO ES COLOCACIÓN CASUAL. Casi
 * todas estas piezas llevan ADEMÁS una clase que les da un `display`:
 * «Sin relleno» es un `.cpd-ed__bt` (`inline-flex`) y el asa de la leyenda es un
 * `.cpd-ed__leyenda li` (`flex`). Con la misma especificidad —una clase— decide
 * el ORDEN, así que puesto más arriba perdía y los botones de paso y el «Sin
 * relleno» salían en la fila de escritorio. Se vio midiendo a 1440 px: doce
 * botones −/+ visibles donde no debía haber ninguno.
 *
 * `.cpd-ed__leyenda .cpd-ed__leyenda-asa` lleva dos clases a propósito: tiene
 * que ganarle a `.cpd-ed__leyenda li`, que son una clase y un tipo.
 *
 * ⚠ `display: none` Y NO la clase de recorte para lectores: en escritorio esto
 * no es información escondida, es información QUE NO EXISTE. La etiqueta «Capa»
 * la da el `aria-label` del grupo, y «Sin relleno» está dentro del selector de
 * color. Anunciar en escritorio una fila y un botón que no se pueden ver ni
 * pulsar sería peor que no anunciarlos.
 * ========================================================================== */

.cpd-ed__fila-et,
.cpd-ed__hoja-cab,
.cpd-ed__hoja-asa,
.cpd-ed__hoja-listo,
.cpd-ed__paso,
.cpd-ed__solo-movil,
.cpd-ed__leyenda .cpd-ed__leyenda-asa {
    display: none;
}

/* ==========================================================================
 * MÓVIL
 *
 * Tres cambios y los tres son de SITIO, no de aspecto:
 *
 *   1. El carril de herramientas baja al pie. En una pantalla de 360 px una
 *      columna de 76 px es el 21 % del ancho, y además el pulgar no llega a la
 *      esquina superior izquierda.
 *   2. El panel se abre como HOJA INFERIOR sobre el lienzo, no como columna.
 *      Sigue estando fuera del flujo, así que el lienzo tampoco se mueve aquí.
 *   3. El lienzo se queda arriba con lo que sobra.
 *
 * La barra de propiedades sí cambia, y es lo único que aquí gana un scroll: en
 * escritorio lo que no cabe se recorta por prioridad y en 360 px eso no alcanza.
 * Ver `.cpd-ed__props` en la media query.
 * ========================================================================== */

@media (max-width: 720px) {
    .cpd-ed__cuerpo {
        flex-direction: column;
    }

    /* `order` y no reordenar el marcado: el orden del DOM es el correcto para
     * el teclado y para un lector de pantalla —las herramientas antes del
     * lienzo—, y lo que cambia en móvil es solo dónde se pintan. */
    .cpd-ed__area {
        order: 1;
        padding: 12px 12px 20px;
        gap: 12px;
    }

    .cpd-ed__carril {
        order: 2;
        flex: 0 0 var(--cpd-carril-h);
        flex-direction: row;
        justify-content: space-around;
        gap: 4px;
        padding: 6px 8px;
        border-right: 0;
        border-top: 1px solid var(--cpd-linea);
    }

    .cpd-ed__carril-bt {
        flex: 1 1 0;
        gap: 3px;
        padding: 6px 2px;
    }

    .cpd-ed__carril-ico {
        width: 20px;
        height: 20px;
    }

    /* LA HOJA INFERIOR. `bottom` es el alto del carril, no 0: la hoja se para
     * justo encima de él y los tres botones siguen alcanzables — cerrar el
     * panel o cambiar de herramienta no puede exigir apuntar a una × de 22 px.
     *
     * `top: auto` es OBLIGATORIO y no sobra: la regla general fija `top: 0`, y
     * con `top` y `bottom` y `height` a la vez el navegador ignora la altura y
     * el panel volvería a ocupar la pantalla entera. */
    .cpd-ed__panel {
        top: auto;
        bottom: var(--cpd-carril-h);
        left: 0;
        right: 0;
        width: auto;
        height: 60%;
        border-right: 0;
        border-top: 1px solid var(--cpd-linea);
        border-radius: 12px 12px 0 0;
        box-shadow: 0 -6px 24px rgba(17, 24, 39, 0.16);
    }

    .cpd-ed__lienzo {
        max-height: 52dvh;
    }

    /* 0.13.0 (UI-3) — en móvil las tres zonas son TRES FILAS: logo y nombre;
     * las herramientas, centradas; y Guardar, Pedir y Salir. Hasta 0.12.0 la
     * barra era un flex que envolvía como caía y salían cuatro filas con los
     * botones sueltos. El alto deja de estar fijo por lo mismo. */
    .cpd-ed__barra {
        grid-template-columns: minmax(0, 1fr);
        height: auto;
        gap: 8px;
        padding: 8px 12px;
    }

    /* 0.19.0 — el aviso del visitante, en móvil: el texto parte en dos
     * líneas si hace falta y el enlace se queda entero a su derecha. No
     * desborda (`min-width: 0` en el texto) y no toca la barra. */
    .cpd-ed__visitante {
        justify-content: space-between;
        gap: 10px;
        padding: 6px 12px;
        font-size: 11px;
    }

    .cpd-ed__barra-izq {
        gap: 12px;
    }

    .cpd-ed__barra-centro {
        gap: 12px;
    }

    .cpd-ed__barra-der {
        justify-content: flex-start;
        gap: 8px;
    }

    .cpd-ed__logo img {
        max-height: 22px;
    }

    .cpd-ed__titulo {
        flex: 1 1 auto;
    }

    /* El estado del guardado no cabe como texto: se queda para los lectores
     * de pantalla (el mismo recorte que `.cpd-ed__sr`, no `display:none`, que
     * callaría la región `aria-live`) y lo que se ve es un punto sobre
     * «Guardar» cuando hay cambios. «Guardado» no pinta nada. */
    .cpd-ed__estado {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        padding: 0;
        border: 0;
        clip: rect(0 0 0 0);
        clip-path: inset(50%);
    }

    .cpd-ed__bt.is-sucio {
        position: relative;
    }

    .cpd-ed__bt.is-sucio::after {
        content: "";
        position: absolute;
        top: -4px;
        right: -4px;
        width: 10px;
        height: 10px;
        border: 2px solid var(--cpd-panel);
        border-radius: 50%;
        background: var(--cpd-zona-aviso-tinta);
        box-sizing: border-box;
    }

    /* «Salir» se queda en su icono y se va al final de la fila. */
    .cpd-ed__barra-der .cpd-ed__volver {
        margin-left: auto;
    }

    /* El texto del enlace de volver se va y queda el icono: en la segunda fila
     * de la barra compiten siete controles por 360 px. El `aria-label` y el
     * `title` siguen diciendo a dónde va. */
    .cpd-ed__volver {
        padding: 7px 9px;
    }

    .cpd-ed__volver-et {
        display: none;
    }

    /* Tres miniaturas por fila en vez de dos: en la hoja inferior el panel
     * ocupa el ancho completo, y dos columnas dejarían fichas enormes. */
    .cpd-ed__activos {
        grid-template-columns: repeat(3, 1fr);
    }

    .cpd-ed__formas {
        flex-direction: row;
        flex-wrap: wrap;
    }

    /* AQUÍ SÍ hay barra de scroll horizontal, y es el único sitio. En una
     * pantalla de 360 px la barra de un texto no cabe ni con los dos niveles de
     * recorte puestos, y recortarla en silencio dejaría controles inalcanzables.
     * En escritorio no hace falta y se quita: ver `.cpd-ed__props`. */
    .cpd-ed__props {
        overflow-x: auto;
        /* El desplazamiento lateral con el dedo tiene que parar donde acaba el
         * contenido, no arrastrar la página por detrás. */
        overscroll-behavior-x: contain;
    }

    .cpd-ed__props-ctl {
        /* Con scroll, el contenido manda: si se dejara encogible, el contenedor
         * se ajustaría al hueco y no habría nada que desplazar. Es lo contrario
         * de lo que hace falta en escritorio, donde `min-width: 0` es lo que
         * permite medir el desborde. */
        flex: 0 0 auto;
        overflow: visible;
    }

    /* Los campos numéricos se encogen para que quepan tres por pantallazo de
     * la barra en vez de dos. */
    .cpd-ed__campo input {
        width: 54px;
    }

    .cpd-ed__toast {
        bottom: calc(var(--cpd-carril-h) + 12px);
    }

    /* ══════════════════════════════════════════════════════════════════════
     * LA HOJA INFERIOR
     *
     * UN COMPONENTE, TRES CONSUMIDORES: la ficha de propiedades, el panel de
     * subidas y el panel de formas. Comparten esqueleto (posición, radio,
     * sombra, asa), comportamiento (se arrastran por el asa) y ALTO
     * (`--cpd-hoja-h`). Lo único que cambia entre ellos es de dónde cuelgan —la
     * ficha del viewport, los paneles del cuerpo— y eso lo resuelve cada uno.
     *
     * ⚠ AQUÍ EL LIENZO SÍ SE ENCOGE, al revés que en escritorio. En una pantalla
     * de 390×844 no hay sitio para el lienzo y la ficha a la vez, y superponer la
     * ficha sobre el diseño dejaría al cliente editando algo que no ve. El
     * mecanismo es un `padding-bottom` en el área: la hoja sigue fuera del flujo
     * —ni la ficha ni los paneles empujan nada— y lo que reserva el hueco es el
     * relleno, que huecoDelLienzo() ya resta. Ver `is-hoja` más abajo.
     * ══════════════════════════════════════════════════════════════════════ */

    .cpd-ed__hoja-cab {
        flex: 0 0 auto;
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        padding: 6px 12px 4px;
    }

    /* EL ASA. Es un <button> de verdad: se arrastra con el dedo y además se
     * enfoca y se pulsa con teclado (ver hojaMovil(), que trata Enter y las
     * flechas). El dibujo es el ::before; el botón en sí es una zona de toque de
     * 28 px de alto, que es lo que hace falta para acertarle con el pulgar.
     *
     * ⚠ `touch-action: none` NO ES OPCIONAL: sin él, el navegador interpreta el
     * arrastre vertical como un desplazamiento de la página y se queda con el
     * gesto a mitad de camino — el `pointermove` deja de llegar y la hoja se
     * atasca donde estuviera. */
    .cpd-ed__hoja-asa {
        display: block;
        flex: 1 1 auto;
        height: 28px;
        padding: 0;
        border: 0;
        background: transparent;
        cursor: grab;
        touch-action: none;
    }

    .cpd-ed__hoja-asa::before {
        content: "";
        display: block;
        width: 40px;
        height: 4px;
        margin: 12px auto 0;
        border-radius: 2px;
        background: var(--cpd-tinta-ter);
    }

    .cpd-ed__hoja-asa:active {
        cursor: grabbing;
    }

    .cpd-ed__hoja-listo,
    .cpd-ed__solo-movil {
        display: inline-flex;
        flex: 0 0 auto;
    }

    /* ── LA FICHA DE PROPIEDADES COMO HOJA ────────────────────────────────
     * `position: fixed` y no `absolute`: la ficha vive dentro de
     * `.cpd-ed__area`, que hace scroll, y un hijo absoluto de un contenedor con
     * scroll se desplaza con su contenido — se iría hacia arriba al bajar por un
     * lienzo ampliado. Fija al viewport se queda donde tiene que estar.
     *
     * Y al salir del flujo devuelve su hueco al área: `offsetParent` de un
     * elemento fijo es null, así que huecoDelLienzo() se la salta sola y el
     * lienzo recupera los 46 px de la fila. El sitio de la hoja lo reserva el
     * `padding-bottom` de `is-hoja`, que es otra cosa y se mide aparte. */
    .cpd-ed__props {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 40;
        /* SIN SELECCIÓN NO HAY FICHA. En móvil la ficha es una hoja que aparece
         * al seleccionar algo, no una barra permanente: el mensaje «Selecciona
         * un elemento para editarlo» sobra cuando lo que hay debajo es el carril
         * de herramientas, que ya dice qué se puede hacer. La enciende
         * `.is-hoja-props`, que pone el JS. */
        display: none;
        flex-direction: column;
        align-items: stretch;
        height: var(--cpd-hoja-h);
        margin: 0;
        padding: 0;
        background: var(--cpd-panel);
        border: 0;
        border-top: 1px solid var(--cpd-linea);
        border-radius: 14px 14px 0 0;
        box-shadow: 0 -6px 24px rgba(17, 24, 39, 0.16);
        overflow: hidden;
    }

    .cpd-ed__cuerpo.is-hoja-props .cpd-ed__props {
        display: flex;
    }

    /* Con la ficha abierta, el carril se va: es lo que dice el enunciado —la
     * ficha lo sustituye mientras hay selección— y además es lo que da los
     * 62 px que la hoja necesita para llegar al borde de abajo. Se vuelve a ver
     * en cuanto se deselecciona, que es lo que hace «Listo». */
    .cpd-ed__cuerpo.is-hoja-props .cpd-ed__carril {
        display: none;
    }

    /* EL CONTENIDO, APILADO. Aquí es donde la fila se convierte en hoja: la
     * misma cadena de nodos, en columna. */
    .cpd-ed__props-ctl {
        flex: 1 1 auto;
        flex-direction: column;
        align-items: stretch;
        min-height: 0;
        padding: 0 16px 16px;
        overflow-x: hidden;
        overflow-y: auto;
        /* El desplazamiento de la ficha no puede arrastrar la página de detrás
         * al llegar al final. */
        overscroll-behavior-y: contain;
    }

    .cpd-ed__props-grupo {
        flex-direction: column;
        align-items: stretch;
        gap: 0;
    }

    /* El separador vertical entre grupos pasa a ser la línea horizontal que
     * separa las secciones. Es el MISMO ::before: solo cambia de eje. */
    .cpd-ed__props-grupo::before {
        width: auto;
        height: 1px;
        margin: 4px 0;
    }

    /* ── LA FILA: ETIQUETA A LA IZQUIERDA, CONTROL A LA DERECHA ───────────
     * Cada `.cpd-ed__par` que sea hijo directo de un grupo es una fila. Los
     * `.cpd-ed__par` ANIDADOS dentro de ella son el grupo de controles de la
     * derecha y se quedan como estaban —en línea—: de ahí que la regla vaya con
     * `>` y no suelta. */
    .cpd-ed__props-grupo > .cpd-ed__par {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 12px;
        min-height: 46px;
        padding: 4px 0;
    }

    /* ⚠ Y OTRA VEZ EL `hidden`. La regla de arriba se lo pisa a las filas que van
     * con el atributo puesto —`#cpd-fila-relleno` y `#cpd-grupo-trazo`, que se
     * conmutan según lo que admita el objeto—, así que la fila «Borde» salía en
     * la hoja con un TEXTO seleccionado: un texto no tiene trazo y la fila no
     * hacía nada. Visto en la captura de 390 px.
     *
     * Es la tercera vez que aparece en esta hoja el mismo fallo, y siempre por lo
     * mismo: en cuanto una regla de autor le da un `display` a un elemento que el
     * JS esconde con `hidden`, hay que devolvérselo. La regla es: si escribes
     * `display` sobre algo que lleva `[hidden]` en el marcado, escribe la pareja. */
    .cpd-ed__props-grupo > .cpd-ed__par[hidden] {
        display: none;
    }

    /* Una línea fina entre filas de la MISMA sección (Relleno / Borde, Fuente /
     * Tamaño / Estilo…). La que separa SECCIONES es el `::before` del grupo, más
     * marcada por su margen. Sin esta, dos filas seguidas de la misma sección se
     * leen como una sola con cuatro controles. */
    .cpd-ed__props-grupo > .cpd-ed__par + .cpd-ed__par {
        border-top: 1px solid var(--cpd-linea);
    }

    .cpd-ed__fila-et {
        display: block;
        flex: 0 0 auto;
        font-size: 13px;
        font-weight: 500;
        color: var(--cpd-tinta);
        white-space: nowrap;
    }

    /* La palabra de dentro de la muestra sobra: la fila ya se llama «Relleno» o
     * «Borde» a dos centímetros. Lo que queda es el cuadradito, que es el dato
     * —qué color, y si está vacío— y un objetivo de dedo decente. */
    .cpd-ed__muestra-et {
        display: none;
    }

    /* La etiqueta del propio campo sobra cuando la fila ya la lleva: en
     * «Interlineado» se leería dos veces seguidas. */
    .cpd-ed__campo-et {
        display: none;
    }

    /* Las medidas: rejilla de dos columnas bajo su etiqueta, que ocupa la fila
     * entera. El candado va en la última celda, con los dos ejes que relaciona
     * justo encima. */
    .cpd-ed__props-grupo > .cpd-ed__fila-et {
        padding: 10px 0 2px;
    }

    .cpd-ed__medidas {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 8px;
        align-items: center;
        padding-bottom: 10px;
    }

    /* `#cpd-campos-forma` agrupa An y Al, y en la rejilla tiene que desaparecer
     * como caja para que sus dos campos sean dos celdas y no una. `contents` es
     * exactamente eso, y aquí es seguro: no lleva fondo, ni borde, ni posición
     * —solo agrupa—, que son las propiedades que `display: contents` tira. */
    .cpd-ed__medidas > #cpd-campos-forma {
        display: contents;
    }

    /* Y su `[hidden]`, por cuarta vez en esta hoja: con un texto seleccionado el
     * par de An/Al va oculto, pero `display: contents` se lo pisaba y en la
     * rejilla salían dos celdas «An» y «Al» vacías bajo un campo «Ancho» que sí
     * funcionaba. Visto en la captura de 390 px con un texto. */
    .cpd-ed__medidas > #cpd-campos-forma[hidden] {
        display: none;
    }

    .cpd-ed__medidas .cpd-ed__par {
        display: flex;
        align-items: center;
        gap: 4px;
        min-width: 0;
    }

    /* ⚠ Y LA DEVOLUCIÓN DEL `hidden`, QUE AQUÍ SE VEÍA. La regla de arriba le da
     * `display: flex` a TODOS los pares de la rejilla, incluido
     * `#cpd-campos-caja` —el «Ancho» del texto—, que va con el atributo `hidden`
     * puesto salvo con un Textbox seleccionado. El `display` de autor le gana al
     * `display:none` de la hoja del navegador, así que la celda «Ancho» salía en
     * la rejilla de un rectángulo, vacía y sin hacer nada. Es el mismo gotcha que
     * esta hoja documenta media docena de veces, y esta vez se vio en la captura
     * de 390 px antes de entregarlo. */
    .cpd-ed__medidas .cpd-ed__par[hidden] {
        display: none;
    }

    .cpd-ed__medidas .cpd-ed__campo {
        flex: 1 1 auto;
        min-width: 0;
    }

    .cpd-ed__medidas .cpd-ed__campo input {
        flex: 1 1 auto;
        width: 100%;
        min-width: 0;
        height: 36px;
    }

    /* El candado ocupa la fila entera de la rejilla y se va a la derecha. En una
     * celda suelta quedaba huérfano —un botón azul solo, bajo «Ancho», sin nada
     * al lado que dijera de qué es—; a lo ancho y alineado con los campos se lee
     * como lo que es: el interruptor de lo que hay encima. */
    .cpd-ed__candado {
        grid-column: 1 / -1;
        justify-self: end;
        width: 44px;
        height: 36px;
    }

    /* ── LOS BOTONES DE PASO (−/+) ────────────────────────────────────────
     * Los inyecta paso() en editor.js dentro de cada `[data-cpd-paso]`. En
     * escritorio no se ven: el campo se teclea, y para el ajuste fino están las
     * flechas del teclado sobre el lienzo. En un móvil no hay flechas y teclear
     * «12,5» en un campo de 60 px es una pelea, así que aquí son la vía
     * principal. */
    .cpd-ed__paso {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        flex: 0 0 auto;
        width: 34px;
        height: 36px;
        padding: 0;
        border: 1px solid var(--cpd-linea);
        border-radius: 6px;
        background: var(--cpd-panel);
        color: var(--cpd-tinta);
        cursor: pointer;
    }

    .cpd-ed__paso .cpd-ico {
        width: 15px;
        height: 15px;
    }

    /* Las píldoras de calidad se parten en dos líneas si hace falta: el aviso de
     * CMYK es más largo que el ancho que queda a la derecha de la etiqueta. */
    .cpd-ed__calidad {
        flex-wrap: wrap;
        justify-content: flex-end;
        gap: 6px;
    }

    .cpd-ed__cmyk {
        font-size: 10.5px;
    }

    /* La muestra de color, más grande: es un objetivo de dedo y además es lo
     * único que dice qué color tiene el objeto. */
    .cpd-ed__muestra {
        height: 36px;
    }

    .cpd-ed__muestra-cuadro {
        width: 24px;
        height: 24px;
    }

    /* 0.13.0 (UI-5) — en la hoja, «Posición» va ANTES del grupo de capa y
     * acciones, cuya última fila se pega al pie (ver abajo): detrás de ella
     * quedaría tapada. El orden del marcado es el de la barra de escritorio,
     * donde va al final. Plegada al abrir, como en escritorio. */
    #cpd-grupo-pos {
        order: 1;
    }

    #cpd-grupo-acciones {
        order: 2;
    }

    .cpd-ed__pos-bt {
        height: 36px;
    }

    /* La fila de acciones se pega al pie de la hoja. Ver la nota del marcado:
     * «Borrar» no puede depender de cuánto se haya desplazado la ficha. */
    .cpd-ed__fila-acciones {
        margin-top: auto;
        position: sticky;
        bottom: 0;
        background: var(--cpd-panel);
        box-shadow: 0 -8px 12px -8px rgba(17, 24, 39, 0.18);
    }

    /* El desplegable de fuentes, a lo ancho de lo que quede: su contenido son
     * nombres largos escritos cada uno en su tipografía. */
    .cpd-ed__select {
        max-width: none;
        width: 100%;
        height: 36px;
    }

    .cpd-ed__campo--familia {
        flex: 1 1 auto;
        min-width: 0;
    }

    /* ── LOS PANELES DE HERRAMIENTA, CON EL MISMO COMPONENTE ──────────────
     * Ya eran hoja inferior desde la primera pasada de F3-UI; lo que ganan aquí
     * es el asa y el alto compartido. Siguen por ENCIMA del carril (`bottom` es
     * su alto) y no a ras de suelo como la ficha: la ficha sustituye al carril
     * porque mientras editas un objeto no cambias de herramienta, pero un panel
     * abierto sí quiere poder saltar de «Subidas» a «Formas» de un toque. */
    .cpd-ed__panel {
        height: var(--cpd-hoja-h);
        border-radius: 14px 14px 0 0;
    }

    .cpd-ed__panel-cab {
        padding-top: 4px;
    }

    /* ── EL HUECO QUE LA HOJA LE QUITA AL LIENZO ──────────────────────────
     * Con cualquier hoja abierta, el área reserva su alto con relleno inferior.
     * El lienzo se reescala solo, porque huecoDelLienzo() resta el
     * `padding-bottom` del área — no hay una segunda fórmula para móvil.
     *
     * Los 12 px de más son el aire entre el borde del lienzo y el canto de la
     * hoja; sin ellos el papel parece salir de debajo de la ficha. */
    .cpd-ed__cuerpo.is-hoja .cpd-ed__area {
        padding-bottom: calc(var(--cpd-hoja-h) + 12px);
    }

    /* ── LA LEYENDA COMO HOJA ─────────────────────────────────────────────
     * La misma lista de escritorio, sacada del flujo y escondida hasta que se
     * pulsa el botón de información de la barra. Sin arrastre: mide lo que miden
     * sus cuatro líneas.
     *
     * `z-index` por encima de la ficha y de los paneles: es una consulta rápida
     * que se hace CON algo seleccionado, así que tiene que poder salir encima. */
    .cpd-ed__leyenda {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 50;
        display: none;
        flex-direction: column;
        gap: 12px;
        max-width: none;
        max-height: 70dvh;
        overflow-y: auto;
        padding: 0 16px 20px;
        background: var(--cpd-panel);
        border-top: 1px solid var(--cpd-linea);
        border-radius: 14px 14px 0 0;
        box-shadow: 0 -6px 24px rgba(17, 24, 39, 0.16);
        font-size: 13px;
    }

    .cpd-ed__leyenda.is-abierta {
        display: flex;
    }

    .cpd-ed__leyenda li {
        align-items: flex-start;
    }

    .cpd-ed__leyenda .cpd-ed__leyenda-asa {
        display: block;
        flex: 0 0 auto;
        width: 40px;
        height: 4px;
        margin: 10px auto 2px;
        border-radius: 2px;
        background: var(--cpd-tinta-ter);
    }

    /* ── EL SELECTOR DE COLOR, A PANTALLA COMPLETA ────────────────────────
     * Desde la ficha se abre ocupando la pantalla entera: el panel de 360 px
     * centrado sobre un velo deja los deslizadores a 300 px de ancho y el velo
     * a los lados no sirve de nada cuando no hay «fuera» que mirar. Al aplicar
     * se cierra y debajo sigue estando la hoja, tal y como se dejó. */
    .cpd-ed__sel {
        padding: 0;
    }

    .cpd-ed__sel-panel {
        width: 100%;
        max-width: none;
        height: 100dvh;
        max-height: none;
        border-radius: 0;
        padding: 16px 16px 24px;
    }

    .cpd-ed__sel-velo {
        display: none;
    }
}
