﻿/* ============================================================
   crayon.css — sistema base "lápiz de palo"
   Tokens, papel, texturas, tipografía y primitivas reutilizables
   ============================================================ */

/* ---------- 1. Tokens ---------- */
:root {
    /* Papel.
       --paper es EL PAPEL DEL ARTE DEL BANNER, copiado tal cual: así la
       ilustración no se lee como un rectángulo pegado encima de otro papel, sino
       como parte de la misma hoja. Si cambia el arte, el número sale de correr
       `node e2e/comprimir.mjs`, que lo imprime. */
    --paper: #f6f4f4;
    --paper-outer: #ffffff; /* escritorio: blanco liso alrededor del marco */
    --paper-warm: #fff3cd;
    --paper-deep: #ffe9a3;

    /* Mina.
       --ink es el TEXTO. --trazo es la LÍNEA: las cajas, los marcos, los rótulos
       y los dibujos del sitio. Es el gris exacto de las líneas del arte del
       banner, medido sobre el original: con negro puro, cualquier recuadro pesaba
       más que la propia ilustración. El texto no se toca, que ahí manda leer. */
    --ink: #17130f;
    --trazo: #414040;
    --ink-soft: #4a4038;
    --ink-faint: #8b8177;

    /* Caja de 12 colores */
    --blue: #2f5fd0;
    --blue-deep: #1c3d94;
    --red: #e03b2e;
    --red-deep: #b3241a;
    --yellow: #ffd230;
    --yellow-deep: #f0ac00;
    --green: #4fa860;
    --pink: #f49ab6;
    --purple: #6e4ba8;
    --orange: #f5842c;

    /* Medidas */
    /* El arte del banner es de trazo fino, y con 3/2 todo lo de abajo competía
       con él: se veía más pesado que la propia ilustración. 1.5 y no 1 en el
       fino porque el filtro #wobble desplaza ±2px y a 1px empieza a quebrar la
       línea en las cajas grandes —se probó—. */
    --stroke: 2px;
    --stroke-thin: 1.5px;
    --radius: 0px; /* 2006: esquinas cuadradas; el redondeo llega con Web2.0 */
    --radius-lg: 0px;
    --frame: 950px; /* ancho fijo japonés de la era 1024×768, no el 960 de 960.gs */
    --shell: var(--frame); /* contenido = marco menos gutters (~894px en desktop) */
    --gutter: 12px; /* px fijos: en 2006 nada escalaba con el viewport */

    /* Ritmo vertical de 2006: los bloques casi se tocan */
    --section-gap: 24px;

    /* Tipografía */
    --font-display: "Shantell Sans", "Comic Sans MS", cursive;
    --font-body: "Nunito", system-ui, -apple-system, "Segoe UI", sans-serif;
    /* Japonés: fuentes del sistema. Ninguna webfont del sitio trae kana, y una
       gótica del sistema es justo lo que usaban esos sitios (MS Pゴシック). */
    --font-jp: "Yu Gothic", "Hiragino Kaku Gothic ProN", "MS PGothic", "Meiryo", sans-serif;

    /* Grano de papel reutilizable */
    --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- 2. Reset corto ---------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    /* Reserva el hueco de la barra SIEMPRE. Al bloquear el scroll con el modal
       abierto la barra desaparece, y sin esto la página saltaría hacia la derecha
       justo al abrir y al cerrar. */
    scrollbar-gutter: stable;
}

/* Con el modal abierto la página de atrás no se mueve */
html.modal-abierto { overflow: hidden; }

body {
    margin: 0;
    /* Ancho fijo de verdad: si la ventana es menor, se scrollea. No se adapta. */
    min-width: var(--frame);
    background-color: var(--paper-outer);
    font-family: var(--font-body);
    font-size: 12px; /* el cuerpo canónico de la época */
    line-height: 1.55;
    color: var(--ink);
}

img, svg { max-width: 100%; display: block; }

h1, h2, h3, h4 {
    font-family: var(--font-display);
    font-weight: 700;
    line-height: 1.15;
    margin: 0;
    letter-spacing: -0.01em;
}

p { margin: 0 0 1em; }

a { color: inherit; text-decoration: none; }

ul { list-style: none; margin: 0; padding: 0; }

time { font-variant-numeric: tabular-nums; }

/* ---------- 3. Layout ----------
   Marco angosto centrado, al modo de los sitios japoneses de antes:
   el papel es una columna fija y el resto del escritorio queda a la vista. */
/* El grano vive dentro del marco: fuera queda papel blanco limpio */
.page::before {
    content: "";
    position: absolute;
    inset: 0;
    /* Sobre todo lo de la hoja (que no pasa de 6) y DEBAJO del modal (200) y el
       visor (300). Era 9999, y como .page no arma contexto de apilamiento ese
       número competía con todo el sitio: el grano velaba las fotos del visor y,
       en el PC, sus bordes cruzaban la foto y el fondo oscuro como dos franjas
       verticales. El modal y el visor llevan su propio grano, bajo su contenido. */
    z-index: 100;
    pointer-events: none;
    background-image: var(--grain);
    background-size: 240px 240px;
    opacity: 0.16;
    /* El grano se apaga junto con el papel: si siguiera entero hasta el final,
       la franja disuelta quedaría con ruido flotando sobre el escritorio. */
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - var(--disuelto)), transparent);
    mask-image: linear-gradient(to bottom, #000 calc(100% - var(--disuelto)), transparent);
    /* SIN mix-blend-mode a propósito: un blend aquí obliga a Chromium a componer
       TODA la página en un buffer aparte y eso apaga el antialiasing subpíxel del
       texto del sitio entero. El grano se nota igual y el texto queda nítido. */
}

.page {
    /* La hoja termina donde termina el contenido y sus últimos --disuelto px se
       apagan hasta el blanco del escritorio. Antes llevaba min-height: 100vh y en
       un monitor alto el marco se estiraba vacío hasta abajo: parecía un pie de
       página infinito con dos líneas de tinta cortadas en seco.

       El tramo arranca JUSTO BAJO LA FIRMA, no antes: la firma va sobre papel
       entero. Se probó haciéndolo empezar arriba del pie —para no agregar alto— y
       el pie completo quedaba lavado; se veía como si el desvanecido empezara con
       el pie. El tramo son los 22px de aire que ya trae el pie más los 30 de cola.

       Y la cola es CORTA a propósito. Con 120px colgando bajo la firma la hoja
       crecía tanto que en una ventana de ~1200 el degradado caía justo en el filo,
       con scroll nuevo incluido: el final quedaba fuera de la pantalla, que es
       exactamente lo que había que evitar. */
    --disuelto: 52px; /* 22 de aire del pie + los 30 de cola */
    --linea: rgba(65, 64, 64, 0.85); /* el gris de --trazo: las dos líneas del marco */

    position: relative;
    width: var(--frame);
    margin-inline: auto;
    padding-bottom: 30px; /* la cola de papel que se disuelve bajo la firma */

    /* Papel y líneas del marco van los tres de degradado, no de color plano ni de
       border: un borde sólido llegaría a tope y se cortaría en seco. El borde
       queda transparente sólo para conservar la medida (950 con box-sizing:
       border-box) y background-origin: border-box pone la línea donde iba. */
    border-inline: 2px solid transparent;
    background-color: transparent;
    background-image:
        linear-gradient(to bottom, var(--linea) calc(100% - var(--disuelto)), transparent),
        linear-gradient(to bottom, var(--linea) calc(100% - var(--disuelto)), transparent),
        linear-gradient(to bottom, var(--paper) calc(100% - var(--disuelto)), transparent);
    background-size: 2px 100%, 2px 100%, 100% 100%;
    background-position: left top, right top, center top;
    background-repeat: no-repeat;
    background-origin: border-box;
    overflow-x: clip;
    /* Deja que la sombra del ::after asome fuera del marco sin soltar el recorte
       horizontal, que es lo que evita la barra de scroll por los adornos. */
    overflow-clip-margin: 30px;
}

/* La sombra que la hoja tira sobre el escritorio. Iba de box-shadow en .page,
   pero un box-shadow llega entero hasta el final y dibujaba dos esquinas grises
   justo donde el papel ya era blanco: se veía el canto de una hoja que en
   realidad se está desvaneciendo. Pintada a mano y con máscara se apaga con el
   papel. Va detrás del papel (z-index: -1): sólo asoman los 30px de fuera. */
.page::after {
    content: "";
    position: absolute;
    inset: 0 -32px; /* -32 y no -30: el 0 de un absoluto es la caja de padding */
    z-index: -1;
    pointer-events: none;
    background-image:
        linear-gradient(to right, rgba(23, 19, 15, 0) 0, rgba(23, 19, 15, 0.09) 30px),
        linear-gradient(to left, rgba(23, 19, 15, 0) 0, rgba(23, 19, 15, 0.09) 30px);
    background-size: 30px 100%;
    background-position: left top, right top;
    background-repeat: no-repeat;
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - var(--disuelto)), transparent);
    mask-image: linear-gradient(to bottom, #000 calc(100% - var(--disuelto)), transparent);
}

.shell {
    width: calc(var(--shell) - var(--gutter) * 2);
    margin-inline: auto;
}

.shell--narrow { width: 700px; }

/* ---------- 4. Primitiva: caja dibujada a mano ----------
   El borde vive en un pseudo-elemento para que nunca se toque el texto de
   adentro. Quién tuerce ese borde cambió: lo dibuja site.js con el temblor en
   la propia línea (ver «EL TRAZO A MANO» allá). Este ::before quedó de dos
   cosas: es la MEDIDA de la que sale el grosor del trazo, y es lo que se ve si
   el JS no corre. */
.hand-box {
    position: relative;
    isolation: isolate;
}

.hand-box::before {
    content: "";
    position: absolute;
    inset: 0;
    border: var(--stroke) solid var(--trazo);
    border-radius: var(--radius);
    pointer-events: none;
    z-index: 2;
}

.hand-box--thin::before { border-width: var(--stroke-thin); }

/* Sin JS no hay quien dibuje nada, así que ahí el borde se tuerce con el filtro
   como toda la vida: la clase `js` la pone el script del <head> antes del primer
   pintado, o sea que no hay parpadeo de uno a otro. NO devolver este filtro al
   caso con JS: a 1x desplaza el borde a escalones y se regenera en cada
   repintado. Ver el comentario largo de site.js. */
html:not(.js) .hand-box::before { filter: url(#wobble); }
html:not(.js) .hand-box--soft::before { filter: url(#wobble-soft); }

/* ---------- 4b. El trazo dibujado ----------
   El <svg> que site.js le cuelga a cada caja y a cada separador. Va por encima
   del contenido —el mismo z-index que tenía el borde que reemplaza— y no recibe
   clics. overflow visible porque el temblor se sale un par de px del elemento,
   que es justo la gracia. */
.trazo {
    position: absolute;
    inset: 0;
    z-index: 2;
    width: 100%;
    height: 100%;
    overflow: visible;
    pointer-events: none;
}

.trazo path {
    fill: none;
    stroke: var(--trazo);
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* Dibujado el trazo, el borde recto sobra. Se apaga acá y no desde el JS para
   que el grosor siga viviendo en la CSS, en --stroke y --stroke-thin. */
.hand-box.trazado::before { display: none; }
[data-trazo].trazado { border-color: transparent; }

/* Sombra de lápiz: segundo trazo corrido, como al calcar dos veces */
.hand-shadow { box-shadow: 6px 7px 0 rgba(23, 19, 15, 0.9); }
.hand-shadow--sm { box-shadow: 4px 4px 0 rgba(23, 19, 15, 0.85); }

/* ---------- 5. Relleno de color con veta de lápiz ----------
   Rayas diagonales muy suaves + grano: el color nunca es plano. */
.crayon-fill {
    position: relative;
    /* Confina el mix-blend-mode del ::after a este elemento. Sin esto, el blend
       arrastra a todo el grupo padre (la ficha entera) a un buffer y le apaga el
       antialiasing subpíxel al texto. */
    isolation: isolate;
    background-color: var(--fill, var(--yellow));
}

.crayon-fill::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image:
        repeating-linear-gradient(58deg,
            rgba(255, 255, 255, 0.32) 0 2px,
            rgba(255, 255, 255, 0) 2px 7px),
        var(--grain);
    background-size: auto, 200px 200px;
    opacity: 0.55;
    mix-blend-mode: overlay;
    border-radius: inherit;
}

/* ---------- 6. Etiquetas / píldoras ---------- */
.tag {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.15em 0.95em;
    min-width: 68px;
    font-family: var(--font-display);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--paper);
    background: var(--tag-bg, var(--ink)); /* el color de marca llega por style inline */
    /* Píldora, y SIN filtro. Llevaba #wobble-soft y era la peor combinación
       posible: un filtro SOBRE TEXTO —lo que el sistema prohíbe en todas partes
       menos aquí— y encima dentro de una ficha que se anima al aparecer, así
       que en el móvil se regeneraba al frenar el movimiento. Queda la píldora
       limpia y el texto nítido; lo dibujado a mano lo ponen la letra y el color.

       Y con 999px, no con porcentajes: un radio en % sobre una caja ancha y
       baja da una ELIPSE, no una píldora. Se probó y quedaba un óvalo. */
    border-radius: 999px;
}

.tag--blue { background: var(--blue); }
.tag--red { background: var(--red); }
.tag--purple { background: var(--purple); }
.tag--green { background: var(--green); }

/* ---------- 7. Rótulo de sección colgado del borde ---------- */
/* Rótulo colgado del borde de una sección. Cuadrado y del mismo tamaño en todas:
   antes uno era círculo y el otro una píldora ancha, y no se leían como la misma
   pieza. Las esquinas rectas son las del canon 2006. */
.section-badge {
    position: absolute;
    top: 0;
    left: 50%;
    translate: -50% -50%;
    z-index: 5;
    display: grid;
    place-items: center;
    /* align-content: sin esto las filas se estiran para llenar el cuadrado y el
       ícono queda separado del texto. El gap declarado no basta. */
    align-content: center;
    gap: 4px;
    /* El alto lo da el contenido (ícono + texto) más el padding, no un número fijo:
       con un cuadrado de 78 quedaban ~19px de aire muerto arriba y abajo.
       min-width para que «Blog» y «Música» midan igual pese al largo distinto. */
    min-width: 84px;
    padding: 10px 18px;
    background: var(--paper);
    font-family: var(--font-display);
    font-weight: 700;
}

.section-badge__icon { font-size: 15px; line-height: 1; }
.section-badge__text { font-size: 11px; letter-spacing: 0.03em; }

/* ---------- 8. Flecha de enlace ---------- */
.arrow {
    flex: none;
    width: 18px;
    height: 18px;
    display: grid;
    place-items: center;
    font-size: 12px;
    transition: translate 0.18s ease;
}

a:hover .arrow,
.arrow:hover { translate: 5px 0; }

/* ---------- 9. Utilidades ---------- */
/* Rótulo en katakana sobre el nombre: el tracking ancho es marca de la casa japonesa */
.kicker {
    font-family: var(--font-jp);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.34em;
    text-indent: 0.34em; /* compensa el tracking del último carácter, si no se descentra */
    color: var(--ink-soft);
    margin: 0 0 2px;
}

.visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.sr-filters {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
}

/* Reduced-motion, con criterio en vez de escopeta.
   El `*` con !important mataba TODA animación del sitio, incluido el crayón que
   dibuja el modal, y además no tocaba los `animation-delay`: dejaba animaciones
   sin duración pero con retardo, o sea un pop desfasado, que es peor que nada.

   Lo que se apaga es lo que la guía WCAG realmente señala: movimiento continuo y
   desplazamientos grandes disparados por el scroll. Un trazo chico que el usuario
   pide con un clic no entra en esa categoría y se conserva. */
@media (prefers-reduced-motion: reduce) {
    /* flotar infinito */
    .hero__spark { animation: none; }

    /* el salto de posición al navegar por anclas */
    html { scroll-behavior: auto; }
}

/* ---------- 10. Responsive ----------
   El escritorio NO se toca: todo lo de acá vive dentro de media queries, así que
   de --frame para arriba manda el canon de 2006 igual que antes —950 de marco,
   px fijos, cero fluido—. Lo de abajo es una capa que se suma, no una reescritura:
   así el canon no se puede romper por accidente al tocar el móvil.

   Abajo del marco, 950px en un teléfono son una postal ilegible. Ahí el papel
   pasa a ser la pantalla entera, pero el mood se queda: mismo papel crema, las
   dos líneas de tinta ahora al filo, los trazos a pulso, el grano y la densidad.

   Dos cortes:
     1024  se acaba el escritorio → el papel se vuelve elástico
      620  teléfono → se apila lo que en fila ya no entra

   Y 1024 y no 950, aunque el marco quepa: el diseño de escritorio no es sólo la
   columna de 950, es la columna MÁS el escritorio alrededor —la sombra que la
   hoja tira necesita sus 30px a cada lado—. Con 20px de blanco al canto no se
   lee como una hoja sobre una mesa, se lee como un sitio mal centrado. Y da la
   casualidad de que 1024 es justo la pantalla de la que salió el 950.

   Regla al agregar cosas: si el escritorio necesita una excepción, va FUERA de
   estas media queries; acá adentro sólo lo que cambia al angostarse. */

@media (max-width: 1024px) {
    /* El ancho fijo era justamente lo que impedía adaptarse */
    body { min-width: 0; }

    /* La sombra sobre el escritorio se apaga, y con ella el margen de recorte
       que la dejaba asomar. No es cosmético: con el papel ocupando la pantalla
       ya no hay escritorio donde caer, y ese overflow-clip-margin es la causa
       del SCROLL LATERAL EN FIREFOX. Firefox cuenta la zona ampliada del
       recorte como desbordamiento scrolleable —Chromium no—, así que salían 28px
       de scroll fijos, iguales a cualquier ancho de ventana. En escritorio nunca
       se notó porque los 30px caían sobre el blanco de los costados.
       Si vuelve a aparecer scroll lateral, mirar acá primero. */
    .page {
        overflow-clip-margin: 0;
    }

    .page::after { display: none; }

    /* El papel toma la pantalla. El aire lateral lo pone la hoja y no cada
       .shell: hay una (.hero__scene) que es a la vez shell y hand-box, y con
       padding ahí el borde dibujado se separaría de su contenido. */
    .page {
        width: 100%;
        padding-inline: var(--gutter);
    }

    /* El grano se mide contra la caja de padding, así que con el aire nuevo
       dejaba los dos bordes sin textura. Se estira hasta el filo. */
    .page::before { inset: 0 calc(var(--gutter) * -1); }

    .shell { width: 100%; }
    .shell--narrow { max-width: 100%; }

    /* La hoja ocupa la pantalla, así que el velo va del color del papel y no
       del escritorio, que acá ya no se ve. Si no, al levantarse cambia el tono. */
    .velo { background: var(--paper); }
}

@media (max-width: 620px) {
    /* 13 y no los 12 canónicos: esa densidad es de monitor a un brazo de
       distancia. En la mano, 12px se lee con lupa. Un punto y nada más —el
       resto de la escala se queda donde está. */
    body { font-size: 13px; }

    /* El rótulo colgado se achica con todo lo demás, o se come el ancho */
    .section-badge {
        min-width: 76px;
        padding: 8px 14px;
    }
}

/* ---------- 11. Velo de carga ----------
   Un backdrop de papel que tapa el armado de la página. La página se estaba
   armando a la vista y se notaba en dos cosas:

   - las webfonts llegan DESPUÉS del primer pintado (con red lenta, la hoja de
     Google a +7,6s y los archivos a +10s), así que todo se dibuja en la de
     respaldo y después salta a Shantell Sans;
   - y lo que aparece al scroll arrancaba escondido desde el JS, o sea que el
     navegador alcanzaba a pintarlo entero antes de que se apagara. Eso está
     arreglado más abajo, en su propia regla.

   El velo sólo existe si el JS corre: la clase `js` la pone un script en línea
   del <head>, antes del primer pintado. Sin JS no hay velo que nadie destape.

   No bloquea el clic (`pointer-events: none`) a propósito: dura un suspiro, y
   un velo invisible que secuestre la página es peor que ver el armado. */
.velo {
    position: fixed;
    inset: 0;
    z-index: 500;
    display: grid;
    place-items: center;
    pointer-events: none;
    background: var(--paper-outer);
    /* Sin JS: nunca se ve */
    opacity: 0;
    visibility: hidden;
}

.js .velo {
    opacity: 1;
    visibility: visible;
}

/* `listo` la pone el script del <head> cuando ya no queda nada que salte. Se va
   TODO junto —papel y rótulo— en una sola disolvencia.

   NUNCA poner acá una `animation` sobre opacity «por si acaso». Hubo una, de
   rescate, con 2,5s de retardo, y en FIREFOX rompía el velo entero: se quedaba
   opaco desde los 35ms hasta los 2531 y ahí saltaba a 0 de golpe, sin disolver.
   Una animación y una transición sobre la MISMA propiedad se pelean, y Firefox
   le entrega la propiedad a la animación ya durante su retardo, así que esta
   regla no tenía ningún efecto. Chromium sí disolvía: el bug era invisible ahí.

   Y el rescate sobraba: el script del <head> agenda su setTimeout en la misma
   línea en que pone la clase `js`, así que si una corre, la otra también. */
.js.listo .velo {
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.35s ease, visibility 0s linear 0.35s;
}

/* El rótulo se ve DESDE EL PRIMER CUADRO y se desvanece con el velo.
   Se probó al revés —entraba a los 0,4s, para que en una carga rápida el velo
   se fuera antes y sólo se viera papel liso— y era horrible: en caché caliente
   el velo se levanta a los ~500ms, o sea que el rótulo aparecía justo cuando el
   velo se estaba yendo. Se veía la página, después el katakana, y otra vez la
   página. Un rótulo de carga entra con la carga y sale con ella; nunca al revés.

   Va en la gótica del sistema (--font-jp) y no en una webfont: sería absurdo que
   el velo esperara justo lo que está tapando. */
.velo__marca {
    margin: 0;
    font-family: var(--font-jp);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.34em;
    text-indent: 0.34em;
    color: var(--ink-faint);
}

/* Lo que site.js hace aparecer al entrar en pantalla arranca escondido DESDE
   LA CSS. Antes lo escondía el propio JS, con `el.style.opacity = 0`.

   Eso funcionaba, pero por una carrera: site.js va al final del <body> y sin
   defer, así que normalmente alcanza a correr antes del primer pintado —medido:
   +16ms contra +80ms—. «Normalmente» no es «siempre»: basta que el JS tarde un
   poco más que la CSS (caché caliente de estilos y fría de scripts, un defer
   futuro, una red rara) para que el navegador pinte el banner, el panel y las
   fichas ENTEROS y un instante después se apaguen. Desde la CSS no hay carrera
   que perder: nacen escondidos.

   El :not(.aparecido) no es adorno. Al terminar la transición, site.js pone esa
   clase y recién ahí borra los estilos en línea: si los borrara sin ella, la
   regla volvería a aplicarse y todo se apagaría de nuevo. Y hay que borrarlos,
   porque un `translate` pegado apaga el antialiasing subpíxel del texto. */
.revela .card:not(.aparecido),
.revela .links__panel:not(.aparecido),
.revela .nosotros__panel:not(.aparecido),
.revela .hero__scene:not(.aparecido) {
    opacity: 0;
    translate: 0 18px;
    transition: opacity 0.5s ease, translate 0.5s ease;
}
