/* ═══════════════════════════════════════════════════════════════
   TIENDA.CSS · Cosas Agénticas · 30-jul-2026 · v2 mundo oscuro
   Catálogo, tarjeta y ficha. Se carga DESPUÉS de mundo.css y gana.
   No toca el hero ni el globo.

   El sistema sale de _proto-tienda-dark.html (prototipo de Julián).
   Cambios respecto a la v1 de esta mañana, y por qué:

   · Fuera los tres colores de ruta (verde/naranja/rojo). El prototipo
     lleva `route-tag{display:none}`: la ruta se dice en tipografía
     (R.01 ARRANQUE), no en semáforo. Tres colores compitiendo con el
     latón hacían que el latón dejara de significar "esto se compra".
   · Los datos van en mono, en versal y en --faint. Son ficha técnica,
     no reclamo: eso es Franchi y es Irma Boom.
   · Una sola curva, --e. Louis Paquet, Independent of the Year 2025,
     tiene UNA en todo su sitio. Nosotros teníamos veinte.
   ═══════════════════════════════════════════════════════════════ */

/* Los tokens vienen de mundo.css. Aquí solo lo propio del catálogo. */
:root{
  --stagger:70ms;
  --vel:0;                /* velocidad de scroll: la escribe tienda.js */
}

/* ═══ 1 · CATÁLOGO ═══════════════════════════════════════════ */

.tienda{
  padding:6rem clamp(1.2rem,5vw,4.5rem);
  max-width:1320px;margin:0 auto;
  background:var(--void);
}
.tienda__intro{max-width:52ch;margin-bottom:3.5rem}
.tienda__intro h2{color:var(--paper)}
.tienda__dek{color:var(--muted);font-size:1.02rem;max-width:46ch}

/* ── Filtros: seleccionar es lo único que enciende el latón ── */
.filtros{
  display:flex;flex-wrap:wrap;gap:.4rem;
  margin:2.5rem 0 4rem;
  position:sticky;top:0;z-index:20;
  padding:.9rem 0;
  background:linear-gradient(var(--void) 72%,rgba(16,15,13,0));
}
.filtro{
  font-family:var(--mono);
  font-size:.7rem;font-weight:500;letter-spacing:.12em;text-transform:uppercase;
  padding:.6rem 1.05rem;
  border:1px solid var(--line);border-radius:0;
  background:transparent;color:var(--faint);
  cursor:pointer;
  transition:color 180ms var(--e),border-color 180ms var(--e);
}
.filtro:hover{color:var(--paper);border-color:var(--line-2)}
.filtro[aria-pressed="true"]{color:var(--brass);border-color:var(--brass-dim)}
/* El punto de color se va con los semáforos. */
.filtro__punto{display:none}

/* ── Ruta: un índice, no una etiqueta de color ── */
.ruta{margin-bottom:5.5rem}
.ruta[hidden]{display:none}
.ruta__cab{
  display:grid;grid-template-columns:auto 1fr auto;align-items:baseline;
  gap:1.2rem;
  padding-bottom:1rem;margin-bottom:2.5rem;
  border-bottom:1px solid var(--line);
}
.ruta__idx{
  font-family:var(--mono);font-size:.7rem;font-weight:500;
  letter-spacing:.14em;color:var(--brass);
}
.ruta__nom{
  font-size:clamp(1.5rem,2.4vw,2.1rem);
  font-weight:500;letter-spacing:-.02em;color:var(--paper);
}
.ruta__dek{
  font-family:var(--mono);font-size:.68rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--faint);text-align:right;
}
@media (max-width:680px){
  .ruta__cab{grid-template-columns:auto 1fr;gap:.8rem}
  .ruta__dek{grid-column:1/-1;text-align:left}
}

/* ── Rejilla ── */
.rejilla{
  display:grid;
  gap:clamp(1.2rem,2.6vw,2.5rem);
  grid-template-columns:repeat(auto-fill,minmax(min(100%,280px),1fr));
  align-items:stretch;
}
/* La pieza líder ocupa fila entera: patrón "líder + colección". */
.gcard--ancla{grid-column:1/-1}
@media (max-width:680px){ .gcard--ancla{grid-column:span 1} }

/* ═══ 2 · LA TARJETA · pieza catalogada ══════════════════════ */

.gcard{
  position:relative;
  display:flex;flex-direction:column;
  background:transparent;
  border:none;
  transition:transform 420ms var(--e);
}
/* El enlace cubre toda la tarjeta: un solo destino, su ficha. */
.gcard__link::after{content:'';position:absolute;inset:0;z-index:2}
.gcard:focus-within{outline:2px solid var(--brass);outline-offset:6px}
.gcard__link:focus-visible{outline:none}

/* 1 · EL OBJETO ─ la portada sobre su peana, no una imagen pegada */
.gcard__visual{
  position:relative;
  aspect-ratio:3/4;
  background:var(--void-2);
  border:1px solid var(--line);
  overflow:hidden;
  display:grid;place-items:center;
  transition:border-color 420ms var(--e);
}
.gcard:hover .gcard__visual{border-color:var(--line-2)}
.gcard__cover{
  width:78%;height:auto;max-height:82%;object-fit:contain;
  /* La portada se levanta un poco del fondo: es un objeto, tiene sombra. */
  box-shadow:0 18px 40px -18px rgba(0,0,0,.85);
  transform:translateY(calc(var(--vel) * -2px));
  transition:transform 420ms var(--e);
}
.gcard:hover .gcard__cover{transform:translateY(-6px)}
.gcard--ancla .gcard__cover{width:62%}

/* La referencia vive sobre la peana, en mono, como número de pieza. */
.gcard__ref{
  position:absolute;top:.9rem;left:.9rem;z-index:3;
  font-family:var(--mono);font-size:.68rem;font-weight:500;
  letter-spacing:.14em;color:var(--faint);
}
.gcard__badge{
  position:absolute;top:.9rem;right:.9rem;z-index:3;
  font-family:var(--mono);
  font-size:.58rem;font-weight:500;letter-spacing:.14em;text-transform:uppercase;
  padding:.28rem .5rem;
  border:1px solid var(--line-2);color:var(--muted);
  background:rgba(16,15,13,.7);
}
.gcard__badge--gratis{color:var(--free);border-color:var(--free)}

/* 2 · EL CUERPO */
.gcard__body{padding:1.15rem 0 0;display:flex;flex-direction:column;gap:.5rem;flex:1}

.gcard__cls{
  font-family:var(--mono);font-size:.64rem;font-weight:500;
  letter-spacing:.16em;text-transform:uppercase;color:var(--muted);
}
.gcard__titulo{
  font-size:clamp(1.15rem,1.6vw,1.4rem);
  font-weight:500;line-height:1.15;letter-spacing:-.02em;color:var(--paper);
}
.gcard--ancla .gcard__titulo{font-size:clamp(1.7rem,2.8vw,2.4rem)}
.gcard__titulo a{color:inherit;text-decoration:none}

/* La promesa es lo único cálido de una tarjeta fría. Cuatro líneas. */
.gcard__promesa{
  color:var(--muted);font-size:.88rem;line-height:1.5;flex:1;
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4;
  line-clamp:4;overflow:hidden;
}
.gcard--ancla .gcard__promesa{-webkit-line-clamp:5;line-clamp:5;font-size:.95rem;max-width:54ch}

/* 3 · LA FICHA TÉCNICA EN UNA LÍNEA */
.gcard__ext{
  font-family:var(--mono);font-size:.68rem;letter-spacing:.08em;
  text-transform:uppercase;color:var(--faint);
}

/* 4 · EL PIE: precio y entrada a la ficha */
.gcard__foot{
  display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  padding-top:.85rem;margin-top:.2rem;
  border-top:1px solid var(--line);
}
.gcard__precio{
  font-family:var(--mono);font-weight:500;font-size:1.1rem;color:var(--paper);
}
.gcard__precio--gratis{
  font-size:.72rem;letter-spacing:.1em;text-transform:uppercase;color:var(--free);
}
.gcard__ficha{
  font-family:var(--mono);font-size:.68rem;letter-spacing:.1em;
  text-transform:uppercase;color:var(--faint);
  transition:color 180ms var(--e);
}
.gcard:hover .gcard__ficha{color:var(--brass)}

/* ═══ 3 · LA FICHA ═══════════════════════════════════════════ */

.ficha{
  max-width:1180px;margin:0 auto;
  padding:5rem clamp(1.2rem,5vw,4.5rem) 7rem;
  background:var(--void);
}
.ficha__volver{
  font-family:var(--mono);font-size:.66rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--faint);text-decoration:none;
}
.ficha__volver:hover{color:var(--brass)}
.ficha__top{
  display:grid;grid-template-columns:minmax(0,.85fr) minmax(0,1fr);
  gap:clamp(2rem,5vw,5rem);margin-top:3rem;
}
@media (max-width:900px){ .ficha__top{grid-template-columns:1fr;gap:2.5rem} }

.ficha__visual{
  background:var(--void-2);border:1px solid var(--line);
  aspect-ratio:3/4;display:grid;place-items:center;overflow:hidden;
}
.ficha__cover{
  width:74%;height:auto;max-height:84%;object-fit:contain;
  box-shadow:0 26px 60px -22px rgba(0,0,0,.9);
}
@media (min-width:900px){ .ficha__visual{position:sticky;top:2rem} }

.ficha__ruta{
  font-family:var(--mono);font-size:.64rem;font-weight:500;
  letter-spacing:.16em;text-transform:uppercase;color:var(--brass);
  margin-bottom:1.2rem;
}
.ficha h1{
  font-size:clamp(2rem,4vw,3.2rem);font-weight:500;
  line-height:1.05;letter-spacing:-.025em;color:var(--paper);
  margin-bottom:1.4rem;
}
.ficha__dek{color:var(--muted);font-size:1.05rem;line-height:1.6;max-width:56ch}

/* La barra de compra: lo único con latón sólido de toda la página. */
.compra{
  display:flex;align-items:center;gap:1.2rem;flex-wrap:wrap;
  margin:2.5rem 0 .6rem;padding:1.2rem 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
}
.compra__precio{font-family:var(--mono);font-size:1.6rem;font-weight:500;color:var(--paper)}
.compra__precio--gratis{color:var(--free);font-size:1rem;letter-spacing:.08em;text-transform:uppercase}
.compra__btn{
  font-family:var(--mono);font-size:.72rem;font-weight:500;
  letter-spacing:.12em;text-transform:uppercase;
  padding:1rem 1.8rem;
  background:var(--brass);color:var(--void);text-decoration:none;
  border:1px solid var(--brass);
  transition:background 180ms var(--e),color 180ms var(--e);
}
.compra__btn:hover{background:transparent;color:var(--brass)}
.compra__nota{font-family:var(--mono);font-size:.68rem;letter-spacing:.06em;color:var(--faint)}

.bloque{margin-top:3rem}
.bloque__h{
  font-family:var(--mono);font-size:.7rem;font-weight:500;
  letter-spacing:.16em;text-transform:uppercase;color:var(--faint);
  padding-bottom:.7rem;margin-bottom:1.4rem;border-bottom:1px solid var(--line);
}
.lista{list-style:none;padding:0;display:grid;gap:.9rem}
.lista li{
  color:var(--muted);line-height:1.6;padding-left:1.5rem;position:relative;
}
.lista li::before{
  content:'';position:absolute;left:0;top:.65em;
  width:.5rem;height:1px;background:var(--brass-dim);
}

/* Ficha técnica: una tabla de datos, no una lista de ventajas. */
.datos{display:grid;gap:0}
.datos__fila{
  display:grid;grid-template-columns:minmax(7rem,.35fr) 1fr;gap:1.5rem;
  padding:.85rem 0;border-bottom:1px solid var(--line);
}
.datos__k{
  font-family:var(--mono);font-size:.68rem;letter-spacing:.12em;
  text-transform:uppercase;color:var(--faint);
}
.datos__v{color:var(--paper);font-size:.92rem;line-height:1.5}

/* La salida del CLI: la prueba. */
.terminal{
  background:#0b0a09;border:1px solid var(--line);
  padding:1.3rem;overflow:hidden;
}
@media (max-width:680px){
  .terminal{padding:.9rem}
  .terminal .term{font-size:.58rem}
}

.vecinas{display:grid;gap:.6rem}
.vecina{
  display:grid;gap:.25rem;padding:1rem;
  border:1px solid var(--line);text-decoration:none;
  transition:border-color 180ms var(--e);
}
.vecina:hover{border-color:var(--brass-dim)}
.vecina__k{font-family:var(--mono);font-size:.66rem;letter-spacing:.12em;color:var(--faint)}
.vecina__t{color:var(--paper);font-size:.95rem}

/* ═══ 4 · MOVIMIENTO ═════════════════════════════════════════
   Dos gestos. Ni uno más. El reveal escalonado al entrar y el
   levantamiento de la portada al pasar por encima. Todo lo demás
   está quieto a propósito: eso es lo que separa a Louis Paquet
   de una plantilla con veinte animaciones.
   ═══════════════════════════════════════════════════════════ */

.rev{opacity:0;transform:translateY(14px)}
.js .rev{transition:opacity 820ms var(--e) var(--d,0ms),transform 820ms var(--e) var(--d,0ms)}
.rev.dentro{opacity:1;transform:none}
/* Sin JS no se esconde nada. Nunca. */
html:not(.js) .rev{opacity:1;transform:none}

@media (prefers-reduced-motion:reduce){
  .gcard,.gcard__cover,.gcard__visual,.filtro,.vecina,.compra__btn{
    transition:none!important;animation:none!important;
  }
  .gcard__cover{transform:none!important}
  /* vital: el contenido se ve siempre */
  .rev{opacity:1!important;transform:none!important;transition:none!important}
}

/* ── La pieza líder es apaisada ───────────────────────────────
 * Ocupa la fila entera, así que con el objeto en 3/4 a todo lo ancho se
 * convertía en un cartel de tres pantallas. Va en dos columnas: el
 * objeto a la izquierda, la ficha a la derecha. */
.gcard--ancla{
  display:grid;
  grid-template-columns:minmax(0,.42fr) minmax(0,1fr);
  gap:clamp(1.5rem,4vw,3.5rem);
  align-items:center;
  border:1px solid var(--line);
  padding:clamp(1.2rem,2.5vw,2rem);
}
.gcard--ancla:hover{border-color:var(--line-2)}
.gcard--ancla .gcard__visual{border:none;background:transparent;aspect-ratio:3/4}
.gcard--ancla .gcard__body{padding:0}
.gcard--ancla .gcard__ref{top:0;left:0}
.gcard--ancla .gcard__badge{top:0;right:0}
@media (max-width:680px){
  .gcard--ancla{grid-template-columns:1fr;padding:0;border:none}
  .gcard--ancla .gcard__visual{border:1px solid var(--line);background:var(--void-2)}
  .gcard--ancla .gcard__ref,.gcard--ancla .gcard__badge{top:.9rem}
  .gcard--ancla .gcard__ref{left:.9rem}
  .gcard--ancla .gcard__badge{right:.9rem}
}
/* La caja 3/4 en la pieza líder dejaba un palmo de vacío arriba y abajo del
 * objeto. Tu respuesta 13: es lujo cuando encuadra una idea, es abandono
 * cuando parece que falta una imagen. Aquí faltaba. La caja se ajusta al
 * objeto y el objeto crece. */
.gcard--ancla .gcard__visual{aspect-ratio:auto}
.gcard--ancla .gcard__cover{width:100%;max-height:none}
/* Al crecer, el objeto se comía la peana entera y la referencia y el sello
 * caían encima de la portada, ilegibles. La peana vuelve, con hueco arriba
 * para los datos: el objeto se apoya, no se pega. */
.gcard--ancla .gcard__visual{
  background:var(--void-2);border:1px solid var(--line);
  padding:2.6rem 1.4rem 1.4rem;
}
.gcard--ancla .gcard__cover{width:100%}

/* ═══ 5 · EL OFICIO ══════════════════════════════════════════
   Aquí es donde la web deja de ser una web negra.
   Cada bloque dice de qué referente sale y qué lo mueve.
   Cero librerías: todo esto son transformaciones CSS movidas por
   custom properties que escribe tienda.js.
   ═══════════════════════════════════════════════════════════ */

/* ── 5.1 · Transición entre documentos ───────────────────────
   LOUIS PAQUET · motion e interacción.
   El generador ya ponía `view-transition-name` en la portada de la
   tarjeta y en la de su ficha, emparejadas por referencia. Faltaba
   esta regla: sin ella el navegador nunca lo usa. Con ella, al abrir
   una ficha la portada NO se recarga, viaja: sale de la rejilla y
   aterriza en la ficha. Nativo, 0 KB, sin librería de transiciones. */
@view-transition{ navigation:auto }

::view-transition-group(*){
  animation-duration:520ms;
  animation-timing-function:var(--e);
}
/* El fondo cruza más rápido que el objeto: así el ojo sigue la portada
   y no la página. Es el truco de toda transición compartida buena. */
::view-transition-old(root),
::view-transition-new(root){ animation-duration:300ms }

/* ── 5.2 · El objeto bajo la luz ─────────────────────────────
   IMMERSIVE GARDEN · dirección artística, materia.
   Ellos lo resuelven con 229 llamadas a WebGL y 126 trozos de GLSL.
   Aquí la misma sensación con perspectiva CSS: la portada es un
   objeto con grosor, se inclina hacia el puntero y recibe un barrido
   de luz que sigue a la mano. --mx y --my las escribe tienda.js. */
.gcard__visual{perspective:1100px}
.gcard__cover{
  transform:
    rotateX(calc(var(--my,0) * -5deg))
    rotateY(calc(var(--mx,0) * 7deg))
    translateY(calc(var(--vel,0) * -6px))
    scaleY(calc(1 - var(--vel,0) * .012));
  transform-style:preserve-3d;
  transition:transform 520ms var(--e),box-shadow 520ms var(--e);
}
.gcard:hover .gcard__cover{
  transition-duration:180ms;
  box-shadow:
    calc(var(--mx,0) * -14px) 22px 48px -20px rgba(0,0,0,.95),
    0 2px 0 rgba(243,239,231,.06);
}
/* El barrido de luz. Solo aparece con el puntero encima: una portada
   quieta no tiene por qué brillar. */
.gcard__visual::after{
  content:'';position:absolute;inset:0;pointer-events:none;z-index:2;
  background:radial-gradient(34% 38% at
    calc(50% + var(--mx,0) * 34%) calc(46% + var(--my,0) * 30%),
    rgba(243,239,231,.16), rgba(243,239,231,0) 68%);
  opacity:0;transition:opacity 420ms var(--e);
  mix-blend-mode:screen;
}
.gcard:hover .gcard__visual::after{opacity:1}

/* ── 5.3 · El barrido de entrada ─────────────────────────────
   BUILD IN AMSTERDAM · 27 clip-path medidos en su bundle.
   No es un fundido: es una cortina que sube. Un fundido lo hace
   cualquiera; una cortina con curva propia se nota. */
.rev{
  opacity:1;
  clip-path:inset(0 0 100% 0);
  transform:translateY(10px);
}
.js .rev{
  transition:
    clip-path 900ms var(--e-peso) var(--d,0ms),
    transform 900ms var(--e) var(--d,0ms);
}
.rev.dentro{clip-path:inset(0 0 0 0);transform:none}
html:not(.js) .rev{clip-path:none;transform:none}

/* ── 5.4 · Botón magnético ───────────────────────────────────
   DENNIS SNELLENBERG · initMagneticButtons / moveMagnet.
   El botón de compra se acerca a la mano antes de que la mano
   llegue. --ix y --iy las escribe tienda.js. */
.iman{
  transform:translate(var(--ix,0),var(--iy,0));
  transition:transform 380ms var(--e),background 180ms var(--e),color 180ms var(--e);
}

/* ── 5.5 · Cursor aumentado ──────────────────────────────────
   DENNIS SNELLENBERG · initStickyCursorWithDelay.
   ACOMPAÑA al cursor nativo, no lo sustituye: sobre botones y campos
   no aparece, porque borrar las señales del puntero es de aficionado.
   El retardo del 0,16 es el efecto entero. */
.cursor{
  position:fixed;top:0;left:0;z-index:60;
  transform:translate(-50%,-50%) scale(.4);
  width:6.5rem;height:6.5rem;border-radius:50%;
  display:grid;place-items:center;
  background:var(--brass);color:var(--void);
  font-family:var(--mono);font-size:.6rem;font-weight:500;
  letter-spacing:.12em;text-transform:uppercase;
  pointer-events:none;opacity:0;
  transition:opacity 260ms var(--e),transform 380ms var(--e);
}
.cursor.visible{opacity:1;transform:translate(-50%,-50%) scale(1)}

@media (prefers-reduced-motion:reduce){
  @view-transition{ navigation:none }
  .gcard__cover,.iman{transform:none!important}
  .gcard__visual::after,.cursor{display:none!important}
  .rev{clip-path:none!important;transform:none!important}
}
@media (hover:none){
  .cursor{display:none}
}

/* ═══ 6 · LA VITRINA ═════════════════════════════════════════
   El lienzo donde las portadas se convierten en objetos.
   Va encima de la página y no intercepta el puntero: la tarjeta
   entera sigue siendo clicable como si no existiera. */
.vitrina{
  position:fixed;inset:0;
  pointer-events:none;
  z-index:4;
}
/* La <img> sigue en el DOM y sigue ocupando su sitio: solo deja de
   pintarse cuando el motor confirma que puede pintar ella. Si WebGL
   falla, esta clase no se pone nunca y no se nota nada. */
.gcard__cover.es-objeto,
.ficha__cover.es-objeto{opacity:0}

/* Con la vitrina viva, el volumen lo hace el shader: la inclinación
   CSS sobra y su `perspective` estorbaba al z-index de los sellos. */
.vitrina-viva .gcard__visual{perspective:none}
.vitrina-viva .gcard__cover{transform:none!important}
.vitrina-viva .gcard__visual::after{display:none}
.vitrina-viva .gcard__ref,
.vitrina-viva .gcard__badge{z-index:10}

@media (prefers-reduced-motion:reduce){
  .vitrina{display:none}
  .gcard__cover.es-objeto,.ficha__cover.es-objeto{opacity:1}
}
/* La nota de la ficha quedaba pegada a la última fila de la tabla, como una
 * línea huérfana que parecía un fallo de maquetación. Respira y se alinea con
 * la columna de valores, que es donde el ojo ya está. */
.ficha__nota{
  font-family:var(--mono);font-size:.68rem;line-height:1.6;
  letter-spacing:.04em;color:var(--faint);
  margin-top:1.4rem;
}
@media (min-width:560px){
  .ficha__nota{margin-left:calc(min(7rem,35%) + 1.5rem)}
}
