/**
 * cpdisenador — El visor 3D del editor (V1b, D38–D43).
 *
 * Dos capas en este fichero:
 *   · LA VENTANA (`.cpd-vis`) — la del visor común (views/js/visor.js): la
 *     cabecera, el escenario con su perspectiva, el pie con los controles, la
 *     asa de redimensionar y la pista «Arrastra para girar».
 *   · EL MOTOR HOJA (`.cpd-hoja`) — lo que construye views/js/visor-hoja.js: los
 *     paneles encadenados, sus dos caras, el oscurecido junto al pliegue y la
 *     sombra del suelo.
 *   · EL MOTOR SOBRE (`.cpd-sobre`, S3) — lo que construye
 *     views/js/visor-sobre.js: un panel, las tapas, la ventana y la solapa.
 *
 * Los colores son tokens de `.cpd-body` (editor.css), también los del visor
 * (`--cpd-visor-*`): esta hoja se carga detrás de la del editor y no declara
 * ninguno. Las medidas que dependen del objeto (el tamaño de cada panel, la
 * posición de cada cara dentro de la imagen) las pone el JS en línea: son
 * datos del formato, no estilo.
 *
 * ⚠ EL LIENZO NO SE ENTERA DEL VISOR (regla de F3-UI). La ventana cuelga de
 * `.cpd-ed__cuerpo` como los paneles, fuera del flujo: abrirla, moverla o
 * ampliarla no cambia el hueco del área, y el ResizeObserver del lienzo no
 * salta.
 *
 * @author    Gráficas Campoamor
 * @copyright Gráficas Campoamor
 * @license   Propietario
 */

/* ==========================================================================
 * EL BOTÓN DEL CARRIL
 *
 * Anclado ABAJO: no es una herramienta de edición como las de arriba, es una
 * forma de mirar lo que se ha hecho. En móvil el carril es una fila y el botón
 * es el último por orden del DOM; ahí el `margin-top: auto` empujaría el botón
 * hacia abajo DENTRO de la fila (el eje cruzado), así que se anula.
 * ========================================================================== */

.cpd-ed__carril-bt--abajo {
    margin-top: auto;
}

/* ==========================================================================
 * LA VENTANA
 * ========================================================================== */

.cpd-vis {
    position: absolute;
    /* Arriba a la derecha DEL ÁREA: por debajo de la barra de propiedades, que
     * es la primera fila del área y no debe quedar tapada al abrir. */
    top: calc(var(--cpd-props-h) + 12px);
    right: 16px;
    z-index: 35;
    width: 420px;
    height: 320px;
    min-width: 280px;
    min-height: 220px;
    display: flex;
    flex-direction: column;
    background: var(--cpd-panel);
    border: 1px solid var(--cpd-linea);
    border-radius: 12px;
    box-shadow: var(--cpd-visor-sombra);
    overflow: hidden;
}

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

/* Ampliada: todo el área de trabajo bajo la barra superior —el cuerpo menos el
 * carril—. `!important` porque arrastrar y redimensionar escriben `left`,
 * `top`, `width` y `height` en línea, y ampliar tiene que ganarles sin
 * borrarlos: al reducir, la ventana vuelve a donde estaba.
 *
 * ⚠ `--cpd-vis-izq` y no `--cpd-carril-w` a secas: el carril mide su ancho MÁS
 * su relleno (89 px con el token a 76), y con el token la ventana taparía 13 px
 * del carril —a los paneles no les pasa porque van por debajo, en el 20—. Lo
 * mide visor.js al ampliar; el token queda de respaldo. */
.cpd-vis.is-ampliada {
    top: 0 !important;
    left: var(--cpd-vis-izq, var(--cpd-carril-w)) !important;
    right: 0 !important;
    bottom: 0 !important;
    width: auto !important;
    height: auto !important;
    border-radius: 0;
    border-width: 0 0 0 1px;
}

.cpd-vis__cab {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    height: 40px;
    padding: 0 6px 0 12px;
    border-bottom: 1px solid var(--cpd-linea);
    color: var(--cpd-tinta);
    cursor: move;
    user-select: none;
    touch-action: none;
}

.cpd-vis.is-ampliada .cpd-vis__cab {
    cursor: default;
}

.cpd-vis__tit {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cpd-vis__bt {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-width: 32px;
    height: 32px;
    padding: 0 8px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--cpd-tinta-sec);
    font: inherit;
    font-size: 12px;
    cursor: pointer;
}

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

.cpd-vis__bt .cpd-ico {
    width: 16px;
    height: 16px;
}

/* ── EL ESCENARIO ───────────────────────────────────────────────────────────
 * `touch-action: none`: el arrastre gira el objeto, y sin esto en móvil el
 * dedo desplazaría la página (o haría zoom) en vez de girar. La perspectiva la
 * pone el JS en línea, proporcional al escenario. */
.cpd-vis__escena {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    background: radial-gradient(ellipse at 50% 45%, var(--cpd-visor-escena-centro) 0%, var(--cpd-visor-escena-borde) 100%);
    touch-action: none;
    cursor: grab;
}

.cpd-vis__escena.is-arrastrando {
    cursor: grabbing;
}

/* El mundo: un punto en el centro del escenario del que cuelga el objeto. Lo
 * gira el arrastre (rotateX · rotateY en línea). Sin transición mientras se
 * arrastra —seguiría al dedo con retraso—; con ella al recolocar o girar. */
.cpd-vis__mundo {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 0;
    height: 0;
    transform-style: preserve-3d;
}

.cpd-vis__mundo.is-animada {
    transition: transform var(--cpd-visor-duracion) ease;
}

/* La pista, ABAJO del escenario y centrada, justo encima de la barra de
 * controles: no tapa el objeto. La enseña visor.js solo la primera vez que se
 * abre el visor en la carga, y se va con el fundido de abajo al primer
 * arrastre o a los 4 s. */
.cpd-vis__pista {
    position: absolute;
    left: 50%;
    bottom: 12px;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border-radius: 999px;
    background: var(--cpd-panel);
    box-shadow: var(--cpd-visor-sombra);
    color: var(--cpd-tinta-sec);
    font-size: 12px;
    white-space: nowrap;
    transform: translateX(-50%);
    pointer-events: none;
    transition: opacity 300ms ease;
}

.cpd-vis__pista.is-oculta {
    opacity: 0;
}

/* ── EL PIE: LOS CONTROLES ──────────────────────────────────────────────── */
.cpd-vis__pie {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 6px 8px;
    border-top: 1px solid var(--cpd-linea);
}

.cpd-vis__seg {
    display: inline-flex;
    padding: 2px;
    border-radius: 9px;
    background: var(--cpd-fondo);
}

.cpd-vis__seg-bt {
    height: 28px;
    padding: 0 12px;
    border: 0;
    border-radius: 7px;
    background: transparent;
    color: var(--cpd-tinta-sec);
    font: inherit;
    font-size: 12px;
    cursor: pointer;
}

.cpd-vis__seg-bt[aria-pressed="true"] {
    background: var(--cpd-panel);
    color: var(--cpd-azul);
    box-shadow: 0 1px 2px rgba(17, 24, 39, 0.12);
}

/* La asa de redimensionar, en la esquina inferior derecha. Tres trazos en
 * diagonal pintados con un degradado: no es un icono de Lucide, es la marca
 * convencional de «estira de aquí». */
.cpd-vis__asa {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 16px;
    height: 16px;
    cursor: nwse-resize;
    touch-action: none;
    background: linear-gradient(135deg, transparent 55%, var(--cpd-tinta-ter) 55%, var(--cpd-tinta-ter) 62%, transparent 62%, transparent 72%, var(--cpd-tinta-ter) 72%, var(--cpd-tinta-ter) 79%, transparent 79%);
}

.cpd-vis.is-ampliada .cpd-vis__asa {
    display: none;
}

/* ==========================================================================
 * EL MOTOR HOJA
 *
 * `.cpd-hoja` es un ancla sin tamaño en el centro del mundo; de ella cuelga el
 * panel raíz, y de cada panel el siguiente de la cadena. Todos con
 * `preserve-3d`: sin él, un panel hijo se aplanaría contra el plano de su padre
 * y el pliegue no existiría.
 *
 * Las caras llevan `backface-visibility: hidden` y el dorso va girado 180°: así
 * cada lado de la hoja enseña solo su página, y el cambio de una a otra al
 * girar el objeto es el de un papel de verdad, sin parpadeos.
 * ========================================================================== */

.cpd-hoja {
    position: absolute;
    left: 0;
    top: 0;
    transform-style: preserve-3d;
}

.cpd-hoja__panel {
    position: absolute;
    transform-style: preserve-3d;
}

.cpd-hoja.is-animada,
.cpd-hoja.is-animada .cpd-hoja__panel,
.cpd-hoja.is-animada .cpd-hoja__suelo {
    transition: transform var(--cpd-visor-duracion) ease;
}

.cpd-hoja__cara {
    position: absolute;
    inset: 0;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    background-repeat: no-repeat;
}

/* El oscurecido junto al pliegue (D43): una capa encima de la cara con un
 * degradado desde el borde del pliegue (lo compone el JS: qué bordes y en qué
 * sentido). Casi invisible con la hoja abierta; se nota plegada, que es cuando
 * el papel de verdad hace sombra en el lomo. */
.cpd-hoja__oscuro {
    position: absolute;
    inset: 0;
    opacity: 0.12;
    pointer-events: none;
    transition: opacity var(--cpd-visor-duracion) ease;
}

.cpd-hoja.is-plegada .cpd-hoja__oscuro {
    opacity: 1;
}

/* La sombra del suelo: un plano tumbado bajo el objeto con un degradado radial
 * difuminado. Va dentro del mundo, así que gira con el objeto. */
.cpd-hoja__suelo {
    position: absolute;
    background: radial-gradient(ellipse at 50% 50%, var(--cpd-visor-suelo) 0%, transparent 70%);
    pointer-events: none;
}

/* ==========================================================================
 * EL MOTOR SOBRE (S3, D81–D83)
 *
 * Lo que construye views/js/visor-sobre.js: un panel plano con dos caras de
 * espaldas, como una hoja sin pliegues, y encima del frontal las tapas del
 * color del papel (la franja no imprimible y la zona de la ventana), la
 * ventana y su brillo; en la trasera, la solapa. Clases propias (`cpd-sobre`):
 * no comparte ninguna con Hoja, para que tocar uno no mueva el otro.
 *
 * Los tamaños y las posiciones los pone el JS en línea —son datos del formato—
 * y los colores del papel, también. Aquí queda lo que es estilo.
 * ========================================================================== */

.cpd-sobre {
    position: absolute;
    left: 0;
    top: 0;
    transform-style: preserve-3d;
}

.cpd-sobre__panel {
    position: absolute;
    transform-style: preserve-3d;
}

.cpd-sobre__cara {
    position: absolute;
    inset: 0;
    overflow: hidden;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    background-repeat: no-repeat;
}

.cpd-sobre__cara--detras {
    transform: rotateY(180deg);
}

/* Las dos tapas (D81). La franja es un marco de cuatro bandas —no un borde:
 * el navegador redondea el ancho de un borde a píxeles enteros y dejaba asomar
 * la tinta—. La zona de la ventana, un rectángulo redondeado. El color lo pone
 * el JS: el del papel. */
.cpd-sobre__franja,
.cpd-sobre__zona {
    position: absolute;
    pointer-events: none;
}

/* La ventana (D82): el interior del sobre. `overflow: hidden` recorta el
 * brillo a su forma redondeada. */
.cpd-sobre__ventana {
    position: absolute;
    overflow: hidden;
    pointer-events: none;
}

/* El brillo: tres bandas diagonales en una capa el triple de ancha que la
 * ventana, que se desplaza con el giro. `--cpd-vis-ry` y `--cpd-vis-rx` los
 * publica visor.js en el mundo, en grados y sin unidad (D84); un número por un
 * porcentaje es un porcentaje, y en `translate` el porcentaje es del tamaño de
 * la propia capa. Los tres números de la capa los pone visor-sobre.js.
 *
 * Las bandas están a un tercio de la capa una de otra —el ancho de la
 * ventana—: cuando una sale por un lado, la siguiente entra por el otro. */
.cpd-sobre__brillo {
    position: absolute;
    top: -40%;
    bottom: -40%;
    left: -100%;
    width: 300%;
    background-image:
        linear-gradient(115deg,
            transparent 10%, rgba(255, 255, 255, var(--cpd-sobre-brillo, 0.5)) 16.5%, transparent 23%,
            transparent 43.3%, rgba(255, 255, 255, var(--cpd-sobre-brillo, 0.5)) 49.8%, transparent 56.3%,
            transparent 76.6%, rgba(255, 255, 255, var(--cpd-sobre-brillo, 0.5)) 83.1%, transparent 89.6%);
    transform: translate(
        calc(var(--cpd-vis-ry, 0) * var(--cpd-sobre-brillo-ry, 0.6) * 1%),
        calc(var(--cpd-vis-rx, 0) * var(--cpd-sobre-brillo-rx, 0.35) * -1%));
}

/* Con «Girar» y «Recolocar» el mundo gira con transición; el brillo, que salta
 * con la variable, la acompaña con la misma. Arrastrando no hay transición. */
.cpd-vis__mundo.is-animada .cpd-sobre__brillo {
    transition: transform var(--cpd-visor-duracion) ease;
}

/* La solapa (D83): un SVG en mm sobre la trasera. El tono la distingue apenas
 * del cuerpo; la sombra y el filo, en la tinta del editor. Las opacidades y
 * los gruesos los pone visor-sobre.js. */
.cpd-sobre__solapa {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

.cpd-sobre__solapa-tono {
    fill: #ffffff;
}

.cpd-sobre__solapa-sombra,
.cpd-sobre__solapa-filo {
    stroke: #111827;
}

.cpd-sobre__suelo {
    position: absolute;
    background: radial-gradient(ellipse at 50% 50%, var(--cpd-visor-suelo) 0%, transparent 70%);
    transform: rotateX(90deg);
    pointer-events: none;
}

/* ==========================================================================
 * MÓVIL — a pantalla completa, siempre (D40)
 *
 * `fixed` e `inset: 0` sobre la ventana: tapa el lienzo, la hoja inferior y el
 * carril. Nivel 70 (ver la escalera de editor.css). Sin ampliar —ya lo está—
 * ni asa, y la cabecera no arrastra.
 * ========================================================================== */

@media (max-width: 720px) {
    .cpd-ed__carril-bt--abajo {
        margin-top: 0;
    }

    .cpd-vis,
    .cpd-vis.is-ampliada {
        position: fixed;
        inset: 0 !important;
        z-index: 70;
        width: auto !important;
        height: auto !important;
        border: 0;
        border-radius: 0;
    }

    .cpd-vis__cab {
        height: 52px;
        cursor: default;
    }

    .cpd-vis__ampliar,
    .cpd-vis__asa {
        display: none;
    }

    .cpd-vis__pie {
        padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
    }
}

@media (prefers-reduced-motion: reduce) {
    .cpd-vis__mundo.is-animada,
    .cpd-hoja.is-animada,
    .cpd-hoja.is-animada .cpd-hoja__panel,
    .cpd-hoja.is-animada .cpd-hoja__suelo,
    .cpd-hoja__oscuro,
    .cpd-vis__pista,
    .cpd-vis__mundo.is-animada .cpd-sobre__brillo {
        transition: none;
    }

    /* S3 (D82) — el brillo de la ventana del sobre queda FIJO: no sigue al
     * giro. Se ve el plástico, sin nada que se mueva solo. */
    .cpd-sobre__brillo {
        transform: none;
    }
}
