/* ============================================================
   Variables globales
   ============================================================ */
:root{
    /* Paleta: beis pastel calido (photoyoshi) + negro. --paper ya no es
       un blanco casi puro (#faf9f6) sino un beis perceptible real. */
    --paper:#e8dfd0;
    --ink:#171614;
    --mut:#8c8378;
    --line:#d9cdb8;
    --dark:#111110;
    --dark-line:#262622;

    /* --font-display: Playfair Display (serif Didone, alto contraste
       marcado entre trazos finos y gruesos) para el nombre/marca y
       titulos — referencia visual: logotipos editoriales/de galeria
       tipo "Royal Botanic Garden". --font-body: Archivo (sans-serif
       geometrica) para texto de lectura — el contraste serif/sans entre
       marca y cuerpo es deliberado, patron editorial. */
    --font-display:'Playfair Display', 'Georgia', serif;
    --font-body:'Archivo', system-ui, sans-serif;

    --space-1:8px;
    --space-2:16px;
    --space-3:24px;
    --space-4:40px;
    --space-5:64px;
    --space-6:96px;

    --ease-soft: cubic-bezier(.6,0,.2,1);

    /* Accesibilidad: color de foco unico para toda la app. Beis claro
       (visible tanto sobre --dark de las pantallas 2/3 como sobre
       --paper de la 1/4), nunca un azul de navegador que desentone. */
    --focus: #d9cdb8;
}

*{ box-sizing:border-box; }
html,body{ margin:0; padding:0; height:100%; }
body{
    background:var(--dark);
    color:var(--ink);
    font-family:var(--font-body);
    -webkit-font-smoothing:antialiased;
    overflow:hidden; /* cada pantalla gestiona su propio scroll interno */
}
a{ color:inherit; text-decoration:none; }
img{ max-width:100%; display:block; }
button{ font-family:inherit; }

/* Foco de teclado global: :focus-visible solo se activa con teclado
   (Tab), nunca con click de raton — no ensucia la UI para el uso normal
   pero garantiza que la navegacion por teclado siempre sea visible. Se
   resetea el outline por defecto del navegador (a menudo azul, rompe la
   paleta) y se sustituye por --focus en toda la app. */
:focus{ outline:none; }
:focus-visible{
    outline: 3px solid var(--focus);
    outline-offset: 3px;
    border-radius: 2px;
}

/* ============================================================
   PANTALLA 1 — Index / portada
   ============================================================ */
.screen1{
    position:fixed; inset:0; z-index:300;
    background:var(--paper);
    display:flex; align-items:center; justify-content:center;
    pointer-events:auto;
}
/* Transicion de color de fondo: en vez de saltar de golpe de beis
   (--paper) a negro (--dark) en el instante en que .screen1 se retira
   (is-inert, display:none) dejando ver el fondo negro de .screen2 ya
   opaco por debajo, el propio fondo de .screen1 se anima a negro EN
   PARALELO al reposicionamiento de la foto (el settle final hacia su
   hueco en la tira) — mismo timing exacto (950ms), asi el cambio de
   color se percibe fundido, no como un corte instantaneo. */
.screen1.is-color-shift{
    transition: background-color .95s var(--ease-soft);
    background-color: var(--dark);
}
/* No se usa opacity de golpe sobre toda la pantalla: solo
   .screen1-chrome (nombre, fecha, %) se desvanece en is-hidden. El
   fondo --paper de .screen1 se queda visible durante todo el proceso
   (la foto crece sin llegar a cubrirlo — ver .screen1-photo.is-expanded),
   asi que nunca hace falta un fondo solido aparte tapando la pantalla. */
.screen1.is-hidden{ pointer-events:none; }
.screen1.is-hidden .screen1-chrome{ opacity:0; transition: opacity .5s ease; }
.screen1.is-inert{ display:none; } /* se aplica solo cuando el zoom-out ya termino del todo */
/* Modo "arrastre desde About": .screen1 empieza fuera de la vista
   (translateY 100%, abajo del todo) y JS controla su posicion en
   tiempo real segun cuanto se sigue empujando el scroll en la Pantalla
   4 — sin transition aqui, para que responda al instante a cada
   evento de rueda (scroll-driven). Al soltar sin llegar al 100%,
   main.js SI anima el retroceso con una transition puntual. Al llegar
   al 100%, se retira esta clase y arranca la animacion normal de la
   intro (letras, doble zoom) desde su posicion final ya en su sitio. */
.screen1.is-scrub{ transform: translateY(100%); }

.screen1-chrome{ position:absolute; inset:0; z-index:5; pointer-events:none; }

.screen1-name{
    /* Maximalista, tipo editorial: mayusculas en redonda (no italica —
       la referencia solo usa cursiva en una palabra de apoyo pequeña,
       no en el nombre principal), alto contraste de trazos (Playfair
       Display, peso 900). Colocado en el tercio superior (no centrado en
       toda la pantalla) y con tamano mas contenido para dejar mas foto
       visible debajo. */
    position:absolute; top:14%; left:0; right:0;
    display:flex; justify-content:center;
    font-family:var(--font-display);
    font-weight:900;
    text-transform:uppercase;
    font-size:clamp(44px, 10vw, 160px);
    letter-spacing:0.01em;
    line-height:0.9;
    perspective: 600px;
}
.screen1-name .char{
    display:inline-block;
    transition: transform .22s ease;
    transform-origin: top center;
    backface-visibility: hidden;
}
/* Separacion real entre palabras (ej. "YERAY" / "GARRIDO"): min-width
   explicito en vez de depender solo del ancho natural del glifo espacio
   de la fuente, para que la separacion sea siempre notoria y ajustable
   directamente aqui, proporcional al tamano del nombre (clamp mas arriba). */
.screen1-name .char.char-space{ min-width:0.28em; }
/* Cascada tipo panel de aeropuerto (split-flap): cada letra es una
   "tarjeta" con bisagra arriba que cae girando sobre el eje X, como
   revelandose desde el reverso del panel, con un desfase respecto a la
   siguiente letra (delay inline via JS, ver ENTRANCE_STEP en
   Preloader.js), reproducida dos veces en cascada. */
.screen1-name .char.is-entering{
    animation: s1-char-flip 1.1s cubic-bezier(.3,.05,.15,1) both;
}
@keyframes s1-char-flip{
    0%{ transform: rotateX(-100deg); opacity:0; }
    60%{ opacity:1; }
    100%{ transform: rotateX(0deg); opacity:1; }
}

.screen1-frame{
    position:relative; z-index:2;
    display:flex; align-items:center; justify-content:center;
}
.screen1-photo{
    width:24vh; aspect-ratio:3/4;
    background:linear-gradient(165deg,#55524c,#0c0b09 78%);
    background-position:center;
    background-size:cover;
    background-repeat:no-repeat;
    box-shadow:0 0 0 1px rgba(0,0,0,0.04);
    /* Se escala/reposiciona SIEMPRE manteniendo su proporcion original
       (3/4); nunca se anima width/height por separado para evitar
       deformarla. Durante el zoom-out final se convierte en position:
       fixed (aplicado por JS) para poder viajar libremente desde su
       tamano expandido hasta el hueco real de su propia miniatura.
       background-size se anima en la misma transition: es el "zoom
       interno" del doble zoom (marco creciendo + contenido acercandose
       a la vez), controlado por JS junto al transform:scale. */
    transform: scale(1);
    transition: transform 1.1s var(--ease-soft), background-size 1.1s var(--ease-soft), opacity .5s ease;
    /* Antes de is-photo-ready se ve el gradiente placeholder de arriba a
       opacidad reducida (nunca 0 — sigue habiendo algo visible en el
       marco); al aplicarse backgroundImage con la foto ya completamente
       decodificada, sube a opacidad 1 con un fundido — evita el "pop"
       brusco de aparicion tras el fix de la carga escalonada. */
    opacity:.35;
}
.screen1-photo.is-photo-ready{ opacity:1; }
.screen1-photo.is-expanded{
    /* El factor de escala exacto (custom property --expand-scale) se
       calcula en JS segun el tamano real de la foto y del viewport,
       para crecer mucho SIN llegar a cubrir el 100% del viewport
       (ver Preloader._applyExpandScale) — queda como foto grande
       centrada, con margen/fondo visible alrededor. */
    transform: scale(var(--expand-scale, 12));
}
.screen1-photo.is-settling{
    /* Fase de encogimiento hacia el hueco de la tira: transicion mas
       larga y suave, sin corte respecto al estado anterior. Incluye
       background-size para que el zoom interno tambien vuelva a 100%
       en paralelo (mismo doble movimiento, en sentido inverso). */
    transition: transform .9s var(--ease-soft), top .9s var(--ease-soft), left .9s var(--ease-soft), width .9s var(--ease-soft), height .9s var(--ease-soft), background-size .9s var(--ease-soft);
}

.screen1-date{
    position:absolute; bottom:var(--space-3); left:var(--space-3);
    font-size:16px; letter-spacing:0.08em; color:var(--mut);
    transition: opacity .4s ease;
}
.screen1-loadwrap{
    position:absolute; bottom:var(--space-3); right:var(--space-3); z-index:5;
    transition: opacity .4s ease;
}
.screen1-percent{
    font-family:var(--font-display); font-size:34px;
    letter-spacing:0.03em; color:var(--mut);
    font-variant-numeric: tabular-nums;
}

/* ============================================================
   PANTALLA 2 — Biblioteca (tira horizontal continua)
   ============================================================ */
.screen2{
    position:fixed; inset:0; z-index:10;
    background:var(--dark); color:var(--paper);
    opacity:0; pointer-events:none;
    transition: opacity .3s ease;
}
.screen2.is-active{ opacity:1; pointer-events:auto; }
/* Mientras dura el recorrido lateral automatico de la intro (la tira se
   desplaza sola hasta que la foto random coincide con el ancla, ver
   runIntro() en main.js), la Pantalla 2 ya es visible/interactiva por
   .is-active de por si -- pero un click o scroll manual del usuario
   ahi ANTES de que ese recorrido automatico termine pisaba/interrumpia
   la animacion en curso. #screen2 (ID) + dos clases le gana en
   especificidad a .screen2.is-active sin depender del orden en la hoja. */
#screen2.is-active.is-intro-journey{ pointer-events:none; }

.s2-header{
    position:absolute; top:0; left:0; right:0; z-index:20;
    display:flex; justify-content:space-between; align-items:center;
    padding: var(--space-3) var(--space-4);
    /* Header algo mas visible: gradiente mas presente (75% en vez de
       55%, con un stop intermedio) para que no se pierda sobre fotos
       claras de la tira. */
    background:linear-gradient(var(--dark) 0%, rgba(17,17,16,0.85) 55%, transparent);
    opacity:0;
    transition: opacity .6s ease;
}
.s2-header.is-visible{ opacity:1; }
.s2-brand{ font-family:var(--font-display); font-size:19px; letter-spacing:0.02em; color:var(--paper); }
.s2-links{ display:flex; align-items:center; gap:22px; font-size:11px; letter-spacing:0.14em; text-transform:uppercase; color:#a8a397; }
.s2-links .is-active{ color:var(--paper); }
/* Subrayado que entra deslizando en hover -- scaleX(0)->1 con
   transform-origin invertido segun se entra/sale (derecha->izquierda al
   pasar el raton, izquierda->derecha al quitarlo) da la sensacion de
   "barrido" en una sola direccion en vez de un simple fade/crecimiento
   simetrico desde el centro. Mismo nav (.s2-links) en Pantalla 2 y
   Pantalla 4 (Sobre mi reutiliza la clase), asi que cubre Work/About en
   los dos sitios con esta unica regla. */
.s2-links a{ position:relative; padding-bottom:3px; }
.s2-links a::after{
    content:''; position:absolute; left:0; right:0; bottom:0; height:1px;
    background:currentColor;
    transform:scaleX(0); transform-origin:right;
    transition:transform .3s var(--ease-soft);
}
.s2-links a:hover::after{ transform:scaleX(1); transform-origin:left; }

/* Interruptor tira/mosaico -- abajo a la derecha, solo iconos (mismo
   lenguaje visual que .s3-icon-btn: circulo, borde var(--dark-line),
   relleno solido en el modo activo). */
.s2-view-switch{
    position:absolute; right:var(--space-4); bottom:var(--space-3); z-index:20;
    display:flex; align-items:center; gap:8px;
}
.s2-view-btn{
    cursor:pointer; background:none;
    border:1px solid rgba(232,223,208,.3); color:#a8a397;
    padding:0;
    display:flex; align-items:center; justify-content:center;
    transition: background .2s ease, color .2s ease, border-color .2s ease;
}
/* Formas distintas a proposito, cada una calcada del propio icono que
   lleva dentro -- antes ambas eran circulos de 44px con el SVG
   flotando en medio de mucho hueco vacio. Un primer intento con la tira
   como pildora bien ancha (60x36) quedaba demasiado estirado -- esta
   version es mas comedida, casi del mismo tamano que el mosaico, solo
   con las esquinas y proporcion ligeramente distintas para insinuar
   "franja" sin gritarlo. */
.s2-view-btn-tira{ width:46px; height:40px; border-radius:12px; }
.s2-view-btn-mosaico{ width:44px; height:44px; border-radius:12px; }
.s2-view-btn:hover{ color:var(--paper); border-color:rgba(232,223,208,.6); }
.s2-view-btn.is-active{ background:var(--paper); color:#111; border-color:var(--paper); }

.s2-meta{
    position:absolute; top:96px; left:var(--space-4); z-index:20;
    display:flex; align-items:baseline; gap:12px;
    opacity:0;
    transition: opacity .6s ease;
}
.s2-header.is-visible ~ .s2-meta{ opacity:1; }
/* Usa font-body (sans-serif) en mayusculas con tracking amplio — mismo
   caracter geometrico que el resto del texto de apoyo, sin recurrir a
   la serif de --font-display en un contexto tan pequeño. */
.s2-meta-cat{
    font-family:var(--font-body); font-weight:600; text-transform:uppercase;
    letter-spacing:0.04em; font-size:20px;
    display:inline-block;
    transition: opacity .16s ease, transform .16s ease;
}
/* Cambio de categoria: sale hacia arriba con fade-out, el texto se
   sustituye, y entra desde abajo con fade-in — se dispara solo cuando
   la categoria cambia de verdad (ver _paintHeader en Library.js). */
.s2-meta-cat.is-changing{ opacity:0; transform:translateY(-10px); }
.s2-meta-cat.is-entering-cat{ animation: s2-cat-enter .26s var(--ease-soft) both; }
@keyframes s2-cat-enter{
    from{ opacity:0; transform:translateY(10px); }
    to{ opacity:1; transform:translateY(0); }
}

/* Contador tipo fraccion: fotos de la categoria actual arriba, total
   de fotos de toda la galeria abajo, separados por una linea. */
.s2-meta-fraction{
    display:flex; flex-direction:column; align-items:center; line-height:1.15;
    font-size:11px; letter-spacing:0.04em; color:#7d7a72;
    font-variant-numeric: tabular-nums;
}
.s2-meta-num, .s2-meta-den{ display:block; }
.s2-meta-bar{ display:block; width:100%; height:1px; background:#7d7a72; margin:2px 0; }

.s2-track-wrap{
    position:absolute; inset:0;
    display:flex; align-items:center;
    overflow-x:auto; overflow-y:hidden;
    scrollbar-width:none;
    opacity:1; visibility:visible; transform:scale(1);
    /* FIX: 'visibility' NO estaba en la lista de propiedades animadas --
       sin transition propia, un valor discreto como visibility cambia
       de golpe en el mismo instante en que cambia la clase, ANTES de
       que la transition de opacity llegue a verse, asi que el fundido
       nunca se apreciaba (saltaba a invisible de inmediato). Con
       'visibility' en la lista Y un delay a juego (mas abajo, en cada
       estado "oculto"), el elemento sigue siendo visible MIENTRAS dura
       el fundido de salida, y solo se retira del todo (fuera del
       arbol de accesibilidad/tab) justo al terminar. Un ligero
       transform:scale acompaña el fundido -- sensacion de "zoom" en vez
       de un corte plano. */
    transition: opacity .65s ease .12s, transform .65s var(--ease-soft) .12s, visibility 0s linear 0s;
}
.s2-track-wrap::-webkit-scrollbar{ display:none; }
/* Modo mosaico: la tira se aleja/desvanece (scale ligeramente mayor,
   como si la camara retrocediera) y el contador de categoria de la
   tira no pinta nada aqui (el mosaico ensena todas las categorias a la
   vez). Sin delay: empieza a desvanecerse de inmediato al cambiar de
   modo (el que ENTRA, mas abajo, es el que lleva el pequeño retraso). */
#screen2.is-mosaic-mode .s2-track-wrap{
    opacity:0; visibility:hidden; pointer-events:none; transform:scale(1.05);
    transition: opacity .65s ease, transform .65s var(--ease-soft), visibility 0s linear .65s;
}
#screen2.is-mosaic-mode .s2-meta{ opacity:0; pointer-events:none; }

.s2-mosaic-wrap{
    position:absolute; inset:0; top:150px;
    overflow-y:auto; overflow-x:hidden;
    padding: 0 var(--space-4) var(--space-5);
    opacity:0; visibility:hidden; pointer-events:none; transform:scale(0.95) translateY(10px);
    transition: opacity .65s ease, transform .65s var(--ease-soft), visibility 0s linear .65s;
    /* Scrollbar fina a juego con la paleta oscura -- el gris/blanco por
       defecto del navegador desentonaba con el fondo --dark. Firefox usa
       scrollbar-width/scrollbar-color; Chrome/Safari/Edge, los
       pseudo-elementos ::-webkit-scrollbar de aqui abajo. */
    scrollbar-width: thin;
    scrollbar-color: rgba(232,223,208,.35) transparent;
}
.s2-mosaic-wrap::-webkit-scrollbar{ width:6px; }
.s2-mosaic-wrap::-webkit-scrollbar-track{ background:transparent; }
.s2-mosaic-wrap::-webkit-scrollbar-thumb{
    background:rgba(232,223,208,.35); border-radius:3px;
}
.s2-mosaic-wrap::-webkit-scrollbar-thumb:hover{ background:rgba(232,223,208,.55); }
#screen2.is-mosaic-mode .s2-mosaic-wrap{
    opacity:1; visibility:visible; pointer-events:auto; transform:scale(1) translateY(0);
    transition: opacity .65s ease .12s, transform .65s var(--ease-soft) .12s, visibility 0s linear 0s;
}

.s2-mosaic-section + .s2-mosaic-section{ margin-top:var(--space-4); }
.s2-mosaic-cat-label{
    display:flex; align-items:baseline; gap:10px;
    font-family:var(--font-body); font-weight:600; text-transform:uppercase;
    letter-spacing:0.08em; font-size:13px; color:var(--paper);
    padding-bottom:12px;
}
.s2-mosaic-count{ color:#7d7a72; font-weight:400; letter-spacing:0.02em; }
.s2-mosaic-grid{
    display:grid; grid-template-columns:repeat(auto-fill, minmax(150px, 1fr));
    gap:4px;
}
.s2-mosaic-item{
    aspect-ratio:3/4; cursor:pointer; position:relative;
    background:#1a1a18;
    /* SIN overflow:hidden a proposito (antes lo tenia): al foto crecer
       en hover (mas abajo) necesita poder "salir" del propio recuadro
       de la cuadricula, no quedarse recortada dentro -- el efecto
       pedido es que sobresalga sobre las fotos vecinas, no un simple
       zoom contenido. z-index sube en hover para que quede POR ENCIMA
       de esas vecinas (si no, el orden natural del grid tapa el trozo
       que sobresale con la celda siguiente). */
    z-index:1;
}
.s2-mosaic-item:hover{ z-index:5; }
.s2-mosaic-item:focus-visible{ outline:2px solid var(--focus); outline-offset:-2px; z-index:5; }
.s2-mosaic-item .ph{
    width:100%; height:100%; background-size:cover; background-position:center;
    opacity:0; filter:grayscale(1);
    transition: opacity .4s ease, filter .3s ease, transform .35s var(--ease-soft), box-shadow .35s ease;
}
.s2-mosaic-item .ph.is-loaded{ opacity:1; }
.s2-mosaic-item:hover .ph, .s2-mosaic-item:focus-visible .ph{
    filter:grayscale(0); transform:scale(1.15);
    box-shadow:0 14px 34px rgba(0,0,0,.55);
}
.s2-track{
    display:flex; gap:var(--space-3);
    padding: 0 var(--space-4);
}
.s2-cat-label{
    /* FIX: width fijo (220px) se desbordaba con nombres largos como
       "AUTOMOVILISMO", solapando la foto siguiente (Playfair Display en
       mayusculas es mas ancha que la sans-serif anterior a igual tamano).
       min-width en vez de width fijo: el contenedor crece con el texto,
       reservando su propio espacio real en el flex de la tira en vez de
       desbordarse por encima del siguiente elemento. */
    flex:0 0 auto; min-width:220px; padding-right:var(--space-2);
    display:flex; align-items:flex-end;
    font-family:var(--font-display); text-transform:uppercase; font-size:26px; color:#4a4844;
    white-space:nowrap;
}
.s2-item{
    flex:0 0 auto; width:280px; height:70vh; position:relative; cursor:pointer;
    /* Sin transition en transform/opacity: los actualiza Library.js en
       cada evento de scroll, y deben responder al instante (scroll-driven). */
}
.s2-item .ph{ width:100%; height:100%; }
/* El marco de foco NO sigue al outline nativo del navegador (que se
   moveria con cada .s2-item enfocado) — en su lugar se usa un marco fijo
   en el centro de pantalla (.s2-focus-frame, ver mas abajo) y la foto
   activa se centra bajo el via scroll (Library._focusAdjacentItem). Sin
   este reset, ademas del marco fijo se veria tambien el outline nativo
   viajando con cada foto, duplicando la señal visual. */
.s2-item:focus-visible{ outline:none; }
/* Marco fijo, centrado horizontalmente en la pantalla — nunca se mueve.
   Solo visible mientras la navegacion es por teclado (Library.js le
   anade/quita is-visible al entrar/salir del foco de la tira). */
.s2-focus-frame{
    position:fixed; top:50%; left:50%;
    width:280px; height:70vh;
    transform:translate(-50%, -50%);
    border:3px solid var(--focus);
    border-radius:2px;
    pointer-events:none;
    z-index:25;
    opacity:0;
    transition:opacity .15s ease;
}
.s2-focus-frame.is-visible{ opacity:1; }
/* Pulso "he sido esta foto": crece y encoge una vez al llegar al final
   de un recorrido (intro o vuelta del visor). Se anima .ph (la imagen
   interna), no .s2-item — .s2-item ya recibe su transform scroll-driven
   sin transition (responde al instante); una animacion por keyframes
   sobre un hijo distinto no interfiere con eso. */
@keyframes s2-item-pulse{
    0%{ transform:scale(1); }
    50%{ transform:scale(1.06); }
    100%{ transform:scale(1); }
}
.s2-item .ph.is-pulsing{ animation: s2-item-pulse .5s var(--ease-soft); }
.s2-item .s2-item-cap{
    position:absolute; left:0; right:0; bottom:0; padding:14px 16px;
    background:linear-gradient(0deg, rgba(0,0,0,.5), transparent 70%);
    color:var(--paper); font-size:11px; opacity:0; transition: opacity .3s ease;
}
.s2-item:hover .s2-item-cap{ opacity:1; }
.s2-item.is-dimmed{ filter: blur(4px) grayscale(0.4); opacity:0.45; transition: filter .35s ease, opacity .35s ease; }

/* Caida vertical scroll-driven (Library.js calcula transform/opacity
   inline en cada frame de scroll segun cuanto asoma la foto por el
   borde izquierdo o derecho de la tira — sin transition CSS aqui para
   que responda al instante y sea reversible en ambas direcciones). */

/* ============================================================
   PANTALLA 3 — Vista ampliada
   ============================================================ */
.screen3{
    position:fixed; inset:0; z-index:50;
    background:#0c0c0b; color:var(--paper);
    opacity:0; pointer-events:none;
    transition: opacity .7s ease;
}
.screen3.is-active{
    opacity:1; pointer-events:auto;
}
/* IMPORTANTE: .screen3 ya NO anima translateY. Ese movimiento era la
   causa raiz de un bug real: al "subir" arrastraba con el TODO su
   contenido, incluida la foto real ya pintada dentro del stage —
   mientras un clon aparte viajaba por su cuenta hacia el centro. Eran
   dos movimientos independientes de la misma foto (se veia duplicada).
   Ahora .screen3 solo hace fade de fondo; el UNICO movimiento con
   trayectoria (miniatura -> stage) lo hace la foto real via FLIP en
   main.js (transform invertido que se relaja a identidad). */

.s3-header{
    display:flex; justify-content:space-between; align-items:center;
    padding: var(--space-3) var(--space-4);
    border-bottom:1px solid var(--dark-line);
}
.s3-brand{ font-family:var(--font-display); font-size:15px; }
.s3-cat{ font-size:11px; letter-spacing:0.1em; text-transform:uppercase; color:#7d7a72; }
.s3-close{
    background:none; border:1px solid var(--dark-line); color:var(--paper);
    width:36px; height:36px; font-size:22px; line-height:1; cursor:pointer;
}
.s3-close:hover{ background:#1a1a18; }

.s3-body{
    display:flex; height:calc(100% - 140px);
}
.s3-stage{
    flex:1; display:flex; align-items:center; justify-content:center; padding:var(--space-4);
}
.s3-stage .ph{
    /* FIX: aspect-ratio:3/4 fijo forzaba SIEMPRE esa forma de caja,
       recortando la parte de abajo de cualquier foto con otra
       proporcion cuando la caja de 3/4 no cabia entera en el alto
       disponible. Sin aspect-ratio fijo: width/height se ajustan al
       espacio real (max-width/max-height:100%) y background-size:
       contain (puesto en JS) encaja la imagen completa sin recortar.
       El width real de la caja lo define el propio background-image
       mediante su proporcion natural via object-fit-like sizing. */
    width:100%; height:100%; max-width:100%; max-height:100%;
    box-shadow:0 0 0 1px #000, inset 0 0 0 10px #0c0c0b;
    border:10px solid #000;
    cursor:zoom-in;
    transition: transform .35s var(--ease-soft), opacity .3s ease;
}
/* Transicion de apertura: UN SOLO elemento (la foto real del stage,
   nunca un clon aparte) viaja desde la posicion de la miniatura hasta
   su sitio final. Como .screen3 entero sube con translateY, a la foto
   se le aplica un transform inicial IGUAL Y OPUESTO al desplazamiento
   restante del padre en cada instante — main.js lo anima en paralelo
   via requestAnimationFrame, sincronizado con la transicion CSS del
   padre — de forma que el movimiento NETO visible sea "desde la
   miniatura hasta el stage", nunca "pegada al fondo todo el rato". */
.s3-stage .ph.is-arriving-photo{
    transition: none;
}
/* El cambio de foto al navegar por RUEDA (scroll vertical) sigue siendo
   INSTANTANEO, sin fundido ni desplazamiento. Solo el click en una
   miniatura del rail anima la "llegada" de la nueva foto: fade-in +
   un ligero scale de acercamiento, como si centrara suavemente en el
   marco en vez de aparecer de golpe. */
@keyframes s3-photo-arrival{
    0%{ opacity:0; transform:scale(.96); }
    100%{ opacity:1; transform:scale(1); }
}
.s3-stage .ph.is-jump-arrival{
    animation: s3-photo-arrival .5s var(--ease-soft);
}

/* Zoom de foco: click en la foto la centra a pantalla completa con
   los laterales oscurecidos (unico foco visual); panel y rail se
   ocultan mientras dura. Un segundo click revierte, ambos sentidos
   animados via transition. */
.screen3.is-focused .s3-header,
.screen3.is-focused .s3-panel,
.screen3.is-focused .s3-rail{
    opacity:0; pointer-events:none; transition: opacity .35s ease;
}
.screen3.is-focused .s3-body{ height:100%; }
.screen3.is-focused .s3-stage{ padding:0; }
.screen3.is-focused .s3-stage .ph{
    /* Ocupa toda la pantalla como marco, pero la imagen respeta su
       propia proporcion SIN recortarse (contain, no cover) — se ve
       completa, con barras negras a los lados si no coincide con el
       aspect-ratio del viewport. */
    width:100vw; height:100vh; max-width:100vw; max-height:100vh;
    aspect-ratio:auto; border:0; box-shadow:none; cursor:zoom-out;
    background-size:contain !important; background-color:#000;
}
.s3-header, .s3-panel, .s3-rail{ transition: opacity .35s ease; }

/* RAIL LATERAL — "ventana de carrete": un MARCO fijo y VISIBLE (dibujado
   con border), CENTRADO verticalmente en el rail. La tira real
   (.s3-rail-track) vive detras y se desplaza por transform:translateY(),
   controlado por Viewer.js segun la rueda del raton — nunca hace scroll
   el navegador aqui. */
.s3-rail{
    width:180px; flex:0 0 auto; padding: 0 var(--space-2);
    overflow:hidden; position:relative;
}
.s3-rail-frame{
    /* Vuelto a CENTRADO vertical (posicion original) — no anclado al
       borde inferior. Marco FIJO — nunca se mueve; la tira interna
       (.s3-rail-track) es la que se desplaza por debajo al navegar
       (rueda o flechas arriba/abajo) — mismo --focus que el marco
       equivalente de la Pantalla 2 (.s2-focus-frame), coherencia visual
       entre ambos mecanismos de foco fijo. */
    position:absolute; left:var(--space-2); right:var(--space-2); top:50%;
    transform:translateY(-50%);
    aspect-ratio:3/4;
    border:2px solid var(--focus);
    pointer-events:none;
    z-index:2;
}
.s3-rail-track{
    display:flex; flex-direction:column; gap:26px;
    position:absolute; left:var(--space-2); right:var(--space-2); top:0;
    z-index:1;
    /* Separacion entre miniaturas: hace visible el hueco entre una
       foto y la siguiente mientras la tira se desliza. Viewer.js mide
       este gap real del DOM (no un valor fijo), asi el umbral de
       cambio de foto activa coincide exactamente con este espaciado.
       Sin transition por defecto: el arrastre por RUEDA mueve el
       transform en tiempo real segun el deltaY acumulado — debe
       responder al instante, sin animacion. */
}
/* Solo al hacer CLICK en una miniatura (nunca durante el arrastre por
   rueda, que sigue instantaneo): la tira SI anima su desplazamiento
   hasta centrar la miniatura elegida en el marco. */
.s3-rail-track.is-jumping{
    transition: transform .5s var(--ease-soft);
}
.s3-rail-item{
    flex:0 0 auto; aspect-ratio:3/4; cursor:pointer; opacity:.4;
    transition: opacity .2s ease;
}
.s3-rail-item:hover{ opacity:.65; }
.s3-rail-item.is-current{ opacity:1; }

/* Panel junto a la foto: titulo grande en blanco + ficha tecnica de
   camara pequena y difuminada (menor opacidad), tambien en blanco. */
.s3-panel{
    width:260px; flex:0 0 auto; display:flex; flex-direction:column; justify-content:center;
    padding: 0 var(--space-3);
}
.s3-panel h3{
    font-family:var(--font-display); font-size:26px; color:var(--paper);
    margin:0 0 18px; line-height:1.2;
}
.s3-description{
    font-size:12px; line-height:1.6; color:rgba(232,223,208,0.7);
    margin:0 0 18px;
}
.s3-description:empty{ display:none; }
.s3-exif{
    display:flex; flex-direction:column; gap:6px;
    font-size:10.5px; letter-spacing:0.04em; color:rgba(232,223,208,0.45);
}
.s3-exif .s3-exif-camera{ color:rgba(232,223,208,0.6); margin-bottom:4px; }
/* Me gusta / Compartir -- mismo par de acciones que los FABs icono-solo
   de Reels en movil (ver .m-fab en mobile.css), aqui en version
   escritorio: circulos pequenos con el mismo lenguaje visual que
   s3-download/s3-print (borde var(--dark-line), relleno solido al
   hover). Descargar y Pedir impresion siguen como enlaces de texto
   aparte (.s3-actions) -- son acciones distintas, con mas peso. */
.s3-icon-actions{ display:flex; gap:10px; margin-top:18px; }
.s3-icon-btn{
    cursor:pointer; background:none;
    border:1px solid var(--dark-line); color:var(--paper);
    width:38px; height:38px; border-radius:50%; padding:0;
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px;
    transition: background .25s ease, color .25s ease;
}
.s3-icon-btn:hover{ background:var(--paper); color:#111; }
.s3-icon-btn.is-liked, .s3-icon-btn.is-copied{ background:var(--paper); color:#111; }
.s3-icon-count{ font-size:9px; letter-spacing:0.02em; line-height:1; }
.s3-icon-count:empty{ display:none; }

.s3-actions{ display:flex; flex-direction:column; gap:10px; margin-top:20px; width:fit-content; }
.s3-download, .s3-print{
    display:inline-block; width:fit-content;
    font-size:10px; letter-spacing:0.14em; text-transform:uppercase;
    border:1px solid var(--dark-line); padding:9px 18px; color:var(--paper);
    transition: background .25s ease, color .25s ease;
}
.s3-download:hover, .s3-print:hover{ background:var(--paper); color:#111; }
/* "Pedir impresion" en un tono distinto (beis calido) para diferenciarlo
   del boton de descarga — es una accion de contacto/venta, no tecnica. */
.s3-print{ border-color:var(--focus); color:var(--focus); }
.s3-print:hover{ background:var(--focus); color:#111; }

/* Enlace "Contactar" en los headers de Pantalla 2 y 4 — mismo estilo que
   Work/About, sin destacar de mas (es un enlace mas del nav). */
.s2-contact-link{ opacity:.85; }
.s2-contact-link:hover{ opacity:1; }

/* ============================================================
   PANTALLA 4 — About
   Aparece encadenada tras la Pantalla 2 (click en "About"), sube desde
   abajo via transform:translateY. La foto ocupa TODO el lateral
   izquierdo a sangre completa (position:fixed, mitad del viewport),
   igual que la referencia — no un recuadro centrado con margenes.
   Header propio fijo arriba (Work/About siempre visibles). El texto
   de la derecha SI hace scroll vertical nativo dentro de .s4-scroll;
   al llegar al final, Library/main.js dispara la vuelta a la Pantalla 1.
   ============================================================ */
.screen4{
    position:fixed; inset:0; z-index:60;
    background:var(--paper); color:var(--ink);
    transform: translateY(100%);
    transition: transform .7s var(--ease-soft);
    pointer-events:none;
}
.screen4.is-active{
    transform: translateY(0);
    pointer-events:auto;
}
.s4-header{
    position:absolute; top:0; left:0; right:0; z-index:5;
    /* Sin nombre/marca en About (pedido explicito) — el nav queda solo,
       alineado a la derecha (mismo lado que en la Pantalla 2, donde el
       brand ocupa la izquierda) en vez de flotar centrado por el
       justify-content:space-between que asumia un segundo elemento. */
    display:flex; justify-content:flex-end; align-items:center;
    padding: var(--space-3) var(--space-4);
    /* El header cruza tanto la foto (izquierda) como el fondo --paper
       claro (derecha) — texto oscuro (legible sobre --paper) con una
       sombra de texto clara para que tambien se lea sobre la foto. */
    color: var(--ink);
    text-shadow: 0 1px 8px rgba(232,223,208,0.65);
}
.s4-header .s2-links{ color:#5a564e; }
.s4-header .s2-links .is-active{ color:var(--ink); }
/* Foto a sangre completa en TODO el lateral izquierdo (mitad del
   viewport) — antes era un recuadro 4:5 centrado con margenes, se veia
   pequeña y descentrada. Ahora cubre desde el borde hasta el borde. */
.s4-photo{
    position:fixed; top:0; left:0; bottom:0; width:50%;
    background:linear-gradient(170deg,#c9bda3,#8c8378 78%);
    /* FIX encuadre: con cover en un panel muy alto y estrecho, el ancho
       recortado es tan pequeño que "camara completa + fondo a los
       lados" a la vez es matematicamente imposible (cover siempre
       recorta el ancho hasta llenar el alto). Se prioriza que el
       OBJETIVO no se corte (baja el foco vertical, el objetivo llega
       casi hasta el final de la foto original) y centrar entre el
       sujeto y la camara en el eje horizontal. */
    background-size:cover; background-position:52% 55%;
}
.s4-scroll{
    position:absolute; top:0; right:0; bottom:0; left:50%;
    overflow-y:auto; overflow-x:hidden;
    -webkit-overflow-scrolling:touch;
    /* Scrollbar fina a juego -- aqui en tono OSCURO (fondo --paper,
       claro, a diferencia del scrollbar beige de la Pantalla 2/mosaico,
       que va sobre fondo oscuro). */
    scrollbar-width: thin;
    scrollbar-color: rgba(23,22,20,.25) transparent;
}
.s4-scroll::-webkit-scrollbar{ width:6px; }
.s4-scroll::-webkit-scrollbar-track{ background:transparent; }
.s4-scroll::-webkit-scrollbar-thumb{
    background:rgba(23,22,20,.25); border-radius:3px;
}
.s4-scroll::-webkit-scrollbar-thumb:hover{ background:rgba(23,22,20,.4); }
.s4-content{
    min-height:100%;
    display:flex; flex-direction:column; justify-content:center;
    padding: var(--space-6) var(--space-5);
}
.s4-text .s4-kicker{
    font-size:13px; letter-spacing:0.16em; text-transform:uppercase;
    color:var(--mut); margin-bottom:20px;
}
.s4-title{
    /* Italica confirmada por el usuario para este titulo — con Playfair
       Display es una italica real diseñada (no oblicua sintetica). */
    font-family:var(--font-display);
    font-style:italic;
    font-size:clamp(30px,3.8vw,46px); margin:0 0 26px; color:var(--ink);
    line-height:1.2;
}
.s4-text p{
    font-size:18px; line-height:1.85; color:#3a3733; font-weight:300;
    margin:0 0 22px; max-width:560px;
}
/* Boton fisico de contacto (no un link de texto suelto), mismo lenguaje
   visual que los botones de la Pantalla 3 (.s3-download/.s3-print) pero
   invertido porque aqui el fondo de la pagina es claro (--paper), no
   oscuro. FIX "los 3 botones que sean iguales": Email tenia un fondo
   solido (--mut) que Telegram/Instagram no llevaban (esos ya eran
   "ghost", solo borde) -- los tres unificados al mismo estilo ghost. */
.s4-contact-btn{
    display:inline-block; margin-top:6px;
    font-size:11px; letter-spacing:0.14em; text-transform:uppercase;
    background:none; color:var(--ink);
    padding:14px 28px; border:1px solid var(--ink);
    transition: background .25s ease, color .25s ease;
}
.s4-contact-btn:hover{ background:var(--ink); color:var(--paper); }
.s4-contact-row{ display:flex; flex-wrap:wrap; gap:10px; }
.s4-contact-lead{
    font-family:var(--font-display); font-weight:900; text-transform:uppercase;
    font-size:clamp(26px,3.4vw,40px); line-height:0.98; letter-spacing:0.01em;
    color:var(--ink); margin:48px 0 20px;
}
.s4-form-block{
    margin-top:44px; padding-top:28px; border-top:1px solid var(--line);
    display:flex; flex-direction:column; gap:10px; max-width:420px;
}
.s4-form-lead{
    margin:0 0 4px; font-size:12px; letter-spacing:0.1em; text-transform:uppercase; color:var(--mut);
}
.s4-form-input, .s4-form-textarea{
    padding:12px 14px; border:1px solid var(--line); background:#fff;
    font-family:var(--font-body); font-size:14px; color:var(--ink); resize:vertical;
}
.s4-form-status{ margin:0; font-size:12px; color:var(--mut); min-height:16px; }
/* Un unico "cuadradito" (mismo lenguaje visual que .s4-contact-btn,
   solo mas pequeno/discreto porque es informacion secundaria) en vez de
   un link de texto suelto con coma -- un solo destino (una pagina, con
   las 3 secciones dentro), asi que un solo boton, no tres. */
.s4-legal-row{ margin-top:18px; }
.s4-legal-btn{
    display:inline-block;
    font-size:10px; letter-spacing:0.08em; text-transform:uppercase;
    background:none; color:var(--mut);
    padding:9px 14px; border:1px solid var(--line);
    transition: background .25s ease, color .25s ease, border-color .25s ease;
}
.s4-legal-btn:hover{ background:var(--ink); color:var(--paper); border-color:var(--ink); }
@media (max-width: 720px){
    /* En movil, Sobre mi vive dentro del flujo de mobile-main.js/mobile.css
       -- la barra inferior propia (Home/Reels/Lupa/Sobre mi) ya cubre la
       navegacion de este header de escritorio (Work/About), asi que se
       oculta para no duplicarla ni verse fuera de sitio. */
    .s4-header{ display:none; }
    /* La foto ya no es un bloque fijo tapando el texto -- mobile-main.js
       la reubica dentro de .s4-text, justo antes de "Te gusta mi
       trabajo?" -- aqui solo hace falta que se comporte como un bloque
       normal en el flujo (nunca position:fixed/absolute como en
       escritorio), sin ningun hack de flex/order a nivel de pantalla. */
    #screen4{
        overflow-y:auto; -webkit-overflow-scrolling:touch;
        scrollbar-width: thin;
        scrollbar-color: rgba(23,22,20,.25) transparent;
    }
    #screen4::-webkit-scrollbar{ width:6px; }
    #screen4::-webkit-scrollbar-track{ background:transparent; }
    #screen4::-webkit-scrollbar-thumb{ background:rgba(23,22,20,.25); border-radius:3px; }
    .s4-scroll{ position:static; overflow:visible; height:auto; }
    .s4-content{ padding-bottom:84px; }
    .s4-photo{
        position:static; width:100%; height:44vh;
        margin:36px 0 8px;
    }
}

@media (prefers-reduced-motion: reduce){
    .screen1, .screen1-photo, .screen1-name .char, .screen2, .screen3, .screen4, .s2-item{
        transition-duration: .01ms !important;
    }
}
