/* ===========================================================================
   oriol colomer — hoja de estilo unica.

     1. variables            6. velo
     2. base                 7. ficha tecnica
     3. la hoja que gira     8. linea del tiempo
     4. topbar               9. about (cara B)
     5. stage / tunel       10. movil y accesibilidad
   =========================================================================== */

/* ---------- 1. variables ---------- */
:root{
  --bg:#fff;
  --ink:#111;
  --muted:#8a8a8a;
  --line:#ececec;
  --card-w:min(420px, 46dvw);

  /* Fuerza de la sombra. Ya no es un numero fijo para todas las cartas: el
     pintor escribe --halo en cada una segun lo cerca que este del foco, asi que
     la sombra es lo que te dice cual estas mirando. Esto de aqui es solo el
     valor de reserva por si el js no llega a arrancar. */
  --halo:.5;

  /* Cuanto desborda la sombra a los lados y por arriba/abajo, en % de la carta.
     Este es el tamano del commit "sombra mas marcada": grande, con presencia,
     un hueco de verdad en el blanco. Lo que fogueaba la pantalla era el paso
     siguiente (85%/130%, casi tres anchos y casi cuatro altos, mas que la
     ventana): ahi las nubes de las tres cartas visibles se fundian en una sola
     niebla centrada que ya no separaba nada.

     Lo que evita ahora esa fusion no es encoger la sombra sino la curva de
     profundidad (HALO_* en config.js): la carta que ya has pasado —que es la
     enorme, la que aportaba la mitad de la niebla— no pinta sombra ninguna.

     Si los pies de foto se te pierden sobre la nube, el valor de abajo
     (46%/70%) los devuelve sin perder mucho hueco. */
  --halo-x:62%;
  --halo-y:95%;

  --safe-b:env(safe-area-inset-bottom, 0px);
  --flip:1.15s cubic-bezier(.62,.02,.2,1);
  --swing:cubic-bezier(.2,.7,.2,1);
}

/* ---------- 2. base ---------- */
*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0;
  background:var(--bg);
  color:var(--ink);
  font:400 13px/1.45 -apple-system,BlinkMacSystemFont,"Helvetica Neue",Arial,sans-serif;
  overflow:hidden;
  overscroll-behavior:none;
  -webkit-font-smoothing:antialiased;
}

/* sonda invisible para leer 1dvw/1dvh en js sin heuristicas */
.unit{
  position:fixed; top:0; left:0;
  width:100dvw; height:100dvh;
  visibility:hidden; pointer-events:none;
}

/* ---------- 3. la hoja que gira ---------- */
.scene{
  position:fixed; inset:0;
  perspective:2400px;
  perspective-origin:50% 50%;
}
.book{
  position:absolute; inset:0;
  transform-style:preserve-3d;
  transition:transform var(--flip);
}
/* hacia la izquierda: el canto derecho se te viene encima y la cara se va */
body.flipped .book{transform:rotateY(-180deg)}

.face{
  position:absolute; inset:0;
  background:var(--bg);
  backface-visibility:hidden; -webkit-backface-visibility:hidden;
  /* Imprescindible para el mix-blend-mode de los textos. Al colgar de un
     contenedor con preserve-3d, la cara entra en un contexto de render 3d y el
     blend se queda sin fondo contra el que mezclar: el texto blanco salia
     blanco sobre blanco, o sea invisible. `isolate` la convierte en grupo de
     mezcla propio y ya cuenta su fondo. */
  isolation:isolate;
}
.face.back{transform:rotateY(180deg)}
/* la cara que no miras no recibe clicks aunque el navegador la pinte */
body.flipped .face.front,
body:not(.flipped) .face.back{pointer-events:none}

/* ---------- 4. topbar ---------- */
.topbar{
  position:absolute; top:0; left:0; right:0; z-index:40;
  display:flex; justify-content:space-between; align-items:center;
  gap:16px;
  padding:18px 22px;
  pointer-events:none;
  /* difference con el texto en blanco: sobre el blanco del fondo sale negro, y
     segun se le pone debajo una nube oscura o una foto se va aclarando solo. Se
     lee siempre y no hace falta ni caja ni halo blanco por detras. */
  mix-blend-mode:difference;
  color:#fff;
}
.name{
  pointer-events:auto;
  appearance:none; border:0; background:none; padding:0;
  font:inherit; color:inherit; letter-spacing:.01em;
  cursor:pointer;
  border-bottom:1px solid transparent;
  transition:border-color .25s ease;
}
.name:hover,.name:focus-visible{border-bottom-color:currentColor}

/* En difference, el gris de la pista sale de restarle este valor al blanco: con
   #757575 se pintaba un #8a8a8a de 3,4:1 sobre el fondo, por debajo del minimo
   para un texto de 11px. #8a8a8a se pinta como #757575 y sube a 4,6:1. */
.hint{color:#8a8a8a; font-size:11px; letter-spacing:.04em}
.hint-m{display:none}

/* el "volver" de la cara B es un boton de verdad: parecia uno y no lo era */
.hint-btn{
  pointer-events:auto;
  appearance:none; border:0; background:none; padding:0;
  font:inherit; cursor:pointer;
  border-bottom:1px solid transparent;
  transition:border-color .25s ease;
}
.hint-btn:hover,.hint-btn:focus-visible{border-bottom-color:currentColor}

/* ---------- 5. stage / tunel ---------- */
.stage{
  position:absolute; inset:0;
  perspective:900px;
  perspective-origin:50% 46%;
  cursor:grab;
  touch-action:none;
  user-select:none; -webkit-user-select:none;
  z-index:10;
}
/* con un proyecto abierto la carta tiene que quedar por delante del velo */
body.open .stage{z-index:25}
.stage.dragging{cursor:grabbing}

.tunnel{
  position:absolute; inset:0;
  transform-style:preserve-3d;
}

.card{
  position:absolute;
  top:46%; left:50%;
  width:var(--card-w);
  margin:0;
  will-change:transform,opacity,filter;
  cursor:pointer;
}

/* El hueco: un degradado radial que hunde la carta en el blanco del fondo. Lo
   escribe el pintor en --halo, carta a carta y frame a frame, asi que la de
   delante lleva sombra fuerte, las del fondo apenas, y la que acabas de pasar
   ninguna. */
.card::before{
  content:'';
  position:absolute;
  inset:calc(-1 * var(--halo-y)) calc(-1 * var(--halo-x));
  z-index:0;
  border-radius:50%;
  /* la sombra desborda la carta: si fuese clicable, abririas proyectos
     apuntando al vacio y las sombras se robarian los clicks */
  pointer-events:none;
  opacity:var(--halo);
  transition:opacity .18s linear;
  /* Nunca a negro: todas las paradas son grises dentro de la banda .30–.70
     (0 = blanco, 1 = negro). El gris va aclarando hacia fuera a la vez que baja
     el alfa, asi que la nube se apaga sin llegar a tinta en ningun punto. Al
     lado de cada parada, su gris en esa escala. */
  background:radial-gradient(50% 50% at 50% 50%,
    rgba(77,77,77,1)      0%,    /* .70 */
    rgba(89,89,89,.95)    36%,   /* .65 */
    rgba(107,107,107,.82) 52%,   /* .58 */
    rgba(128,128,128,.62) 66%,   /* .50 */
    rgba(153,153,153,.38) 79%,   /* .40 */
    rgba(173,173,173,.16) 90%,   /* .32 */
    rgba(179,179,179,0)   100%); /* .30 */
}

/* ---------- stickers ----------
   Decorado que se cuela entre proyecto y proyecto. Ni pie de foto ni click:
   solo forma y sombra, y la sombra un poco mas cerrada que la de las cartas
   (el multiplicador vive en config.js, HALO_STICK). */
.sticker{cursor:default}
.sticker::before{--halo-x:76%; --halo-y:76%}

.card img{
  position:relative; z-index:1;
  display:block; width:100%; height:auto;
  /* sin borde ni sombra: los thumbs flotan sobre el blanco */
  transition:transform .28s var(--swing);
}
/* Acuse de recibo del raton. Antes lo unico que decia que una carta del fondo
   era clicable era el cursor; ahora se levanta un poco y su sombra sube (eso
   ultimo lo hace el pintor, que es quien manda en --halo). */
@media (hover:hover) and (pointer:fine){
  .card.hot img{transform:scale(1.03)}
}

.card .cap{
  position:absolute; z-index:2;
  left:0; top:calc(100% + 8px);
  white-space:nowrap;
  font-size:12px; letter-spacing:.02em;
}
.card .cap .yr{margin-left:8px}

/* Los pies de foto y la nota de la barra van a dos capas (twinLabel en js):
   debajo la copia en difference —el mismo truco que el nombre de arriba— y
   encima la misma en tinta al 40%. Difference se anula sobre gris medio, que es
   justo la banda de la sombra: la tinta pone ahi el suelo de contraste, y sobre
   blanco o sobre foto apenas se nota. */
.cap .diff,.current .diff{mix-blend-mode:difference; color:#fff}
.cap .diff .yr,.current .diff .cd{color:#8a8a8a}
.cap .ink,.current .ink{
  position:absolute; left:0; top:0;
  color:var(--ink); opacity:.4;
}
.cap .ink .yr,.current .ink .cd{color:var(--muted)}

/* ---------- 6. velo ---------- */
.veil{
  position:absolute; inset:0; z-index:20;
  background:rgba(255,255,255,.62);
  backdrop-filter:blur(14px);
  -webkit-backdrop-filter:blur(14px);
  opacity:0; pointer-events:none;
  transition:opacity .4s ease;
}
.veil.on{opacity:1; pointer-events:auto}

/* ---------- 7. ficha tecnica ----------
   La ficha no tiene transiciones css: la mueve el pintor en el mismo frame que
   la carta. Tiene que ser asi porque lo que la esconde "detras" de la carta no
   es el z-index —la carta esta en otro contexto 3d y no se puede intercalar—
   sino un recorte contra su canto derecho, y ese recorte hay que recalcularlo a
   la vez que se mueven las dos cosas o se despega. */
.sheet{
  position:absolute; z-index:30;
  top:46%; left:50%;
  width:300px;
  padding:0 0 0 26px;
  transform:translate(0,-50%);
  opacity:0; pointer-events:none;
}
.sheet.on{pointer-events:auto}
.sheet h1{margin:0 0 2px; font-size:18px; font-weight:500; letter-spacing:.01em}
.sheet-date{margin:0 0 18px; color:var(--muted); font-size:12px}
.sheet-text{margin:0; font-size:12px; color:#444; max-width:34ch}
.close{
  position:absolute; top:-4px; right:0;
  border:0; background:none; font-size:20px; line-height:1;
  color:var(--muted); cursor:pointer; padding:4px;
}

.credits{margin:0 0 18px; display:grid; grid-template-columns:80px 1fr; gap:4px 10px; font-size:12px}
.credits dt{color:var(--muted)}
.credits dd{margin:0}

/* ---------- 8. linea del tiempo ---------- */
.scrubber{
  position:absolute; z-index:40; left:0; right:0; bottom:0;
  display:flex; align-items:flex-end; gap:12px;
  padding:34px 22px calc(22px + var(--safe-b));
  user-select:none;
  transition:opacity .35s ease, transform .45s var(--swing);
}
/* las fechas de los extremos, en vertical: la izquierda girada 90º a la
   izquierda (se lee de abajo arriba) y la derecha 90º a la derecha */
.end{
  flex:0 0 auto;
  writing-mode:vertical-rl;
  font-size:10px; letter-spacing:.06em; color:var(--muted);
  white-space:nowrap;
}
.end-a{transform:rotate(180deg)}

.track{
  position:relative; flex:1 1 auto; height:26px;
  background:var(--line);
  cursor:pointer;
  touch-action:none;
}
/* Area tactil. La barra que se ve mide 22–26px de alto, que es la mitad del
   objetivo minimo recomendado y ademas vive pegada al borde de abajo, justo
   donde el telefono tiene sus propios gestos. Esto la estira a 50px sin
   engordar ni un pixel de lo que se pinta; los eventos siguen cayendo en
   .track, que es quien los atiende. */
.track::before{content:''; position:absolute; inset:-12px 0}

.fill{
  position:absolute; left:0; top:0; bottom:0; width:0;
  background:#c9c9c9;
}
.marks{position:absolute; inset:0}
.mark{
  position:absolute; top:0; bottom:0; width:1px;
  padding:0; border:0; appearance:none;
  background:#fff;
  transform:translateX(-.5px);
  cursor:pointer;
}
/* Zona de hover, no de toque: los toques los resuelve el track entero (gana el
   marcador mas cercano al soltar), asi que esto solo sirve para que el raton
   encuentre el tooltip y el puntito sin apuntar a una linea de 1px. Que dos
   zonas se solapen ya da igual. */
.mark::after{
  content:''; position:absolute;
  top:-16px; bottom:-16px;
  left:-8px; right:-8px;
}
/* Cabeza del marcador, encima de la barra. #949494 sobre blanco da 3:1, que es
   el minimo para un control; el #c9c9c9 de antes se quedaba en 1,7:1 y en una
   pantalla al sol no estaba. */
.mark::before{
  content:''; position:absolute;
  left:-2px; top:-9px; width:5px; height:5px;
  border-radius:50%; background:#949494;
  transition:background .2s ease, transform .2s ease;
}
.mark:hover::before,.mark:focus-visible::before{background:var(--ink)}
.mark.now::before{background:var(--ink); transform:scale(1.45)}
.mark:focus{outline:none}
.mark:focus-visible::before{box-shadow:0 0 0 3px rgba(17,17,17,.14)}

/* marquita de sticker: se ve que hay algo ahi, pero no se toca */
.stick{
  position:absolute; top:6px; bottom:6px; width:1px;
  background:#cfcfcf;
  transform:translateX(-.5px);
  pointer-events:none;
}

.knob{
  position:absolute; top:-3px; bottom:-3px; width:2px;
  background:var(--ink);
  transform:translateX(-1px);
}

/* nota al pie: cuelga centrada encima del marcador en el que estas. El left lo
   pone el pintor en px, ya recortado para que no se salga de la barra. */
.current{
  position:absolute; bottom:100%; left:0;
  margin-bottom:11px;
  transform:translateX(-50%);
  white-space:nowrap;
  font-size:11px; letter-spacing:.02em;
  transition:left .35s var(--swing);
}
.current .cd{margin-left:8px}

/* ---------- 9. about (cara B) ---------- */
.about-scroll{
  position:absolute; inset:0;
  overflow-y:auto; -webkit-overflow-scrolling:touch;
  overscroll-behavior:contain;
}
.about{
  max-width:560px;
  margin:0 auto;
  padding:calc(18vh + 40px) 22px calc(80px + var(--safe-b));
}
.about h1{margin:0 0 4px; font-size:20px; font-weight:500; letter-spacing:.01em}
.about .lead{margin:0 0 26px; color:var(--muted); font-size:12px; letter-spacing:.04em}
.about p{margin:0 0 14px; font-size:13px; line-height:1.62; color:#333; max-width:52ch}
.about .credits{margin:26px 0 0; grid-template-columns:96px 1fr; font-size:12px}
.about .links{
  list-style:none; display:flex; flex-wrap:wrap; gap:18px;
  margin:26px 0 0; padding:0; font-size:12px;
}
.about .links a{color:var(--ink); text-decoration:none; border-bottom:1px solid #d8d8d8}
.about .links a:hover,.about .links a:focus-visible{border-bottom-color:var(--ink)}
.about .note{margin-top:30px; font-size:11px; color:var(--muted)}

/* ---------- 10. movil ---------- */
@media (max-width:760px){
  :root{--card-w:min(300px, 66dvw)}
  .hint{font-size:10px}
  .hint-d{display:none}
  .hint-m{display:inline}
  .topbar{padding:14px 16px}
  .scrubber{padding:32px 16px calc(16px + var(--safe-b)); gap:10px}
  .track{height:22px}

  /* con un proyecto abierto la barra sobra: el gesto pasa a ser del panel */
  body.open .scrubber{opacity:0; pointer-events:none; transform:translateY(118%)}

  /* la ficha deja de salir por el lado y sube desde abajo */
  .sheet{
    top:auto; bottom:0; left:0;
    width:100%; max-height:64dvh; overflow-y:auto;
    overscroll-behavior:contain;
    padding:20px 20px calc(26px + var(--safe-b));
    background:rgba(255,255,255,.94);
    backdrop-filter:blur(12px); -webkit-backdrop-filter:blur(12px);
    /* aqui no hay nada detras de lo que salir: sube desde abajo, sin recorte.
       La `y` tambien la pone el pintor */
    transform:translateY(100%);
  }
  .sheet-text{max-width:none}
  .close{top:14px; right:14px; font-size:24px}
  .credits{grid-template-columns:74px 1fr}

  .about{padding-top:calc(12dvh + 40px)}
  .about .credits{grid-template-columns:88px 1fr}
}

/* Pantallas estrechas: las dos fechas verticales se comian ~50px de barra —un
   septimo del ancho util en un telefono— y dejaban la nota al pie a nueve
   pixeles de la de la izquierda. Fuera las dos; la nota pasa a decir siempre la
   fecha, tambien en el primer y el ultimo proyecto (lo decide labelCurrent()
   en render.js leyendo esta misma media query). */
@media (max-width:479px){
  .end{display:none}
  .scrubber{gap:0}
}

/* Pantallas muy bajas (movil en horizontal): la barra se come el escenario. Las
   cartas se encogen con el alto (58dvh) para no pisarla, y el pie de foto sobra:
   la nota de la barra ya dice titulo y fecha justo debajo. */
@media (max-height:480px){
  :root{--card-w:min(280px, 58dvh)}
  .card .cap{display:none}
  .scrubber{padding-top:12px; padding-bottom:calc(10px + var(--safe-b))}
  .sheet{max-height:76dvh}
  .about{padding-top:70px}
}

/* ---------- accesibilidad ----------
   Los interpoladores del pintor tambien saltan al destino con reduce: ver la
   constante REDUCED en util.js. */
@media (prefers-reduced-motion:reduce){
  .book{transition-duration:.01ms}
  .veil,.sheet,.scrubber,.current,.mark::before,
  .card img,.card::before{transition-duration:.01ms}
}
