/* ==========================================================================
   coltanques.css — pagina de caso, en clave de galeria
   --------------------------------------------------------------------------
   Misma arquitectura que `barkys.css` y `bonfibra.css`: hoja unica, sin
   dependencias, con TODO colgado de una clase para que sirva suelta y dentro
   del sitio. Lo que cambia es la marca que se presenta, no el sistema.

   TRES DECISIONES QUE EXPLICAN TODO LO DEMAS

   1. Un solo tema, blanco.  Las piezas de Coltanques estan compuestas sobre
      blanco y sobre fotografia, y casi todas cierran con una barra roja al
      pie. Sobre fondo oscuro esa barra deja de leerse como remate y parece un
      corte. Ademas el caso se presenta como galeria, y una galeria se pinta de
      blanco por la misma razon que un museo.

   2. La pagina calla para que el trabajo hable.  Sin cajas, sin sombras, sin
      degradados, sin rotulos sobre las imagenes. El rojo de marca es el unico
      acento y tiene un solo trabajo: los titulos de seccion y el boton.
      Rojo = lo que pone Coltanques. Negro = lo que dice el estudio.

      OJO CON ESTO EN ESTE CASO. Aqui conviven TRES sistemas graficos: el rojo
      corporativo, el azul indigo de Ponle Freno y los ocho colores de Buen
      Trato. La tentacion era darle a cada seccion el color de su campana. No
      se hizo: esos colores viven dentro de las imagenes, que es donde el
      cliente los puso. Si la pagina tambien cambia de color, deja de haber
      diferencia entre lo que dice el estudio y lo que dice el trabajo.

   3. Radio 0 en todo, sin excepcion.  Incluido el boton. Un borde redondeado
      dentro de una rejilla de cuadrados es ruido.

   PALETA — muestreada de los 316 JPG originales, no elegida de un catalogo:
     #e9082a  el rojo tal como sale en las piezas    #101010  el negro de los
     avisos de vacante. El rojo original da 4,63:1 sobre blanco, que ya pasa
     AA por poco; el token de acento es #d60724, el mismo rojo bajado hasta
     5,36:1, que es practicamente el mismo contraste con el que trabajan
     Barkys (5,26) y Bonfibra (5,26).

   TIPOGRAFIAS — son de la marca presentada, no de Ballestastudio. Lo unico
   propio es el logo:
     Lato 700/900         la que usan los titulares de las piezas: humanista,
                          de x alta, terminales rectas y remates ligeramente
                          suavizados. Se saco mirando ampliadas las letras de
                          "RECUERDOS PARA EL CORAZON", "Alimentacion
                          balanceada" y "Vacante: Analista", no del logotipo
     Archivo 400/500      grotesca de trabajo, estrecha y sobria. Contrasta con
                          la calidez de Lato en vez de duplicarla, y es la que
                          corresponde al registro real de la cuenta, que es
                          normativo: seguridad, procedimiento, convocatoria
     IBM Plex Mono        "1 / 8" es especificacion, no titulo. La mono lo hace
                          leer como ficha tecnica. Es la misma que usan los
                          demas casos: el unico rasgo tipografico que el
                          estudio conserva de pagina a pagina
   ========================================================================== */

/* TODO cuelga de `.caso-coltanques`, no de `:root` ni de `body`. Asi la misma
   hoja sirve para la pagina suelta y para el fragmento incrustado en el sitio,
   sin pisar los tokens ni la tipografia de ballestastudio.com. Integrar es
   enlazar esta hoja y envolver el cuerpo en <div class="caso-coltanques">. */
.caso-coltanques {
  color-scheme: light;

  --tinta:        #131313;   /* 18,58:1 sobre blanco */
  --tinta-media:  #5c5c5c;   /* 6,69:1 sobre blanco */
  --tinta-suave:  #767676;   /* 4,54:1 sobre blanco: el minimo para texto */
  --linea:        #e8e8e8;
  --papel:        #ffffff;
  --papel-alt:    #fafafa;
  --rojo:         #d60724;   /* 5,36:1 sobre blanco. El unico acento */
  --rojo-oscuro:  #b30a20;   /* 7,04:1. Solo el hover del boton */
  --hero:         #141112;   /* fondo del hero, bajo las tiras */
  --hero-brillo:  #78061a;   /* el rojo que sube desde el pie del hero */

  /* Escala de espacio. Todo el ritmo vertical sale de aqui. */
  --e1: .5rem;  --e2: 1rem;   --e3: 1.5rem;  --e4: 2.5rem;
  --e5: 4rem;   --e6: 6rem;   --e7: clamp(5rem, 12vw, 9rem);

  --ancho: 1240px;
  --margen: clamp(1.25rem, 5vw, 3.5rem);

  --display: "Lato", ui-sans-serif, system-ui, sans-serif;
  --texto:   "Archivo", ui-sans-serif, system-ui, sans-serif;
  --dato:    "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --salida: cubic-bezier(.16, 1, .3, 1);
}

.caso-coltanques, .caso-coltanques *, .caso-coltanques *::before,
.caso-coltanques *::after {
  box-sizing: border-box;
}

.caso-coltanques {
  background: var(--papel);
  color: var(--tinta);
  font-family: var(--texto);
  font-weight: 400;
  font-size: clamp(1rem, .96rem + .2vw, 1.075rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* La pagina suelta no tiene mas contenido que el caso, asi que el papel sube
   al <body> para que cubra la ventana entera. En el sitio esta regla no
   aplica: alli el fondo lo pone el sitio. */
body:has(> .caso-coltanques) { margin: 0; background: var(--papel); }

.caso-coltanques img { display: block; max-width: 100%; }

.caso-coltanques a { color: inherit; }

.caso-coltanques ::selection { background: var(--rojo); color: #fff; }

.caso-coltanques :focus-visible { outline: 2px solid var(--rojo); outline-offset: 3px; }

.contenedor { max-width: var(--ancho); margin-inline: auto; padding-inline: var(--margen); }

.salta { position: absolute; left: -9999px; }
.salta:focus {
  left: var(--margen); top: var(--e2); z-index: 60;
  padding: .7rem 1.1rem; background: var(--tinta); color: #fff;
  font-family: var(--dato); font-size: .82rem;
}

/* --- Apertura -----------------------------------------------------------
   El FONDO son las piezas reales desplazandose en tiras a distintas
   velocidades, y encima va una frase corta que invita a bajar. El fondo es el
   trabajo, que es lo que se vino a ver, y no una animacion abstracta pegada
   encima.

   Cuatro tiras y no mas: pasada esa cantidad el efecto no gana profundidad y
   si multiplica el coste de pintado. */

.portada {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: min(78dvh, 760px);
  overflow: hidden;
  background: var(--hero);
  isolation: isolate;
}

.portada__fondo {
  position: absolute; inset: 0;
  z-index: -2;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(8px, 1.2vw, 16px);
  padding: clamp(8px, 1.2vw, 16px);
}
@media (max-width: 699px) {
  .portada__fondo { grid-template-columns: repeat(2, 1fr); }
  .portada__fondo > :nth-child(n+3) { display: none; }
}

.tira {
  display: grid;
  gap: clamp(8px, 1.2vw, 16px);
  align-content: start;
  /* La tira se sale por arriba y por abajo a proposito: asi el bucle nunca
     ensena un borde. El contenedor recorta. */
  will-change: transform;
}
.tira img { width: 100%; height: auto; }

/* El velo. Va aparte del fondo y no como sombra sobre el texto, porque tiene
   que cubrir veinticuatro imagenes de valores muy distintos por igual.

   CONTRASTE GARANTIZADO POR CONSTRUCCION. A 0,88 sobre el peor caso posible
   —un pixel blanco de una pieza— el resultado es rgb(51 47 48), que con texto
   blanco encima da 12,4:1. Cualquier pixel mas oscuro da mas. No depende de
   que imagen toque en cada momento del bucle.

   El rojo NO va en el velo plano sino en el degradado que sube desde el pie:
   un velo rojo cerrado sobre unas piezas que ya son rojas las borra del todo,
   y sobre las fotos de carretera las volvia sepia. */
.portada__velo {
  position: absolute; inset: 0;
  z-index: -1;
  background:
    linear-gradient(to top, rgb(120 6 26 / .58), transparent 64%),
    rgb(20 17 18 / .88);
}

.portada__texto {
  position: relative;
  width: 100%;
  padding-block: clamp(6rem, 14vw, 9rem) clamp(2.5rem, 6vw, 4.5rem);
  color: #fff;
}
.portada__rotulo {
  margin: 0 0 var(--e2);
  font-family: var(--dato);
  font-size: .74rem; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase;
  color: rgb(255 255 255 / .82);
}
.portada__titulo {
  margin: 0;
  max-width: 22ch;
  font-family: var(--display); font-weight: 900;
  font-size: clamp(2.1rem, 5.2vw, 3.9rem);
  line-height: 1.06; letter-spacing: -.03em;
  color: #fff;
  /* `balance` reparte el titular en lineas parejas. Se prefiere a un <br>
     fijo, que corta bien en un idioma y mal en el otro y se rompe en cuanto
     cambia el ancho. */
  text-wrap: balance;
}
.portada__bajada {
  margin: var(--e3) 0 0;
  max-width: 46ch;
  font-size: clamp(1.02rem, .95rem + .35vw, 1.2rem);
  color: rgb(255 255 255 / .92);
  text-wrap: balance;
}

/* --- La marca -----------------------------------------------------------
   El logo y nada mas: sin barra, sin fondo, sin linea y sin quedarse pegado al
   hacer scroll. Va montado sobre el hero, alineado con el margen del
   contenedor. Mismo tratamiento que en Barkys y Bonfibra.

   Usa el lockup INVERTIDO a una tinta, porque sobre el hero oscuro el logo
   normal (negro con "STUDIO" en turquesa) se pierde. */

.marca {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 3;
  max-width: var(--ancho);
  margin-inline: auto;
  padding: clamp(var(--e2), 2.5vw, var(--e4)) var(--margen);
}
/* El enlace se cine al logo. Si la caja clicable fuera toda la franja, medio
   pantallazo llevaria al inicio sin avisar. */
.marca a { display: inline-block; }
.marca img { width: clamp(104px, 11vw, 132px); height: auto; }


/* --- Tira a sangre ------------------------------------------------------
   Ancho completo de la VENTANA, no del contenedor.

   ESTE PROYECTO NO TIENE LAMINAS DE PRESENTACION. En Barkys y en Bonfibra
   este respiro lo daba una lamina de Behance; aqui las tiras se COMPONEN en
   `build_assets.py` con cuatro piezas cuadradas pegadas, sin calle entre
   ellas. Que se toquen es la clave: separadas volverian a leerse como una
   rejilla de galeria, que es justo de lo que la pagina viene a descansar.

   Sin pie de foto a proposito: una linea gris debajo de una imagen que ocupa
   la pantalla la convierte en una ilustracion con leyenda y le quita la
   fuerza.

   Sin trucos de 100vw: la figura es hija directa de <main>, que ya ocupa todo
   el ancho del documento. Un `width: 100vw` aqui solo serviria para sumar los
   pixeles de la barra de scroll y provocar desborde horizontal. */

.tira-sangre {
  margin-block: clamp(2.75rem, 5.5vw, 4.25rem);
  /* El navegador le da a <figure> un margen lateral de 40 px por su cuenta.
     `margin-block` no lo toca, asi que hay que anularlo a mano o la tira se
     queda 80 px angosta y deja de ir a sangre. */
  margin-inline: 0;
  overflow: hidden;
}
.tira-sangre img { width: 100%; height: auto; }

/* --- Bloques de texto ---------------------------------------------------- */

.bloque { margin-block: clamp(2.75rem, 5.5vw, 4.25rem); }

/* Los titulos van en el rojo de la marca. Es el sistema de acento de la
   pagina: rojo = lo que Coltanques pone, negro = lo que dice el estudio. Da
   5,36:1 sobre blanco, de sobra para AA incluso a este tamano.

   EN CAJA ALTA, que es la unica cosa de esta pagina que se aparta de Barkys y
   Bonfibra. La razon es el proyecto: casi todas las piezas de Coltanques
   rotulan en mayuscula, y el registro de la cuenta es normativo (seguridad,
   procedimiento, convocatoria). Un titulo en caja alta se lee como
   senalizacion, que es de lo que va el caso.

   DOS AJUSTES QUE LA CAJA ALTA OBLIGA, y sin los cuales se ve mal:
   - El `letter-spacing` pasa de NEGATIVO a positivo. El -.025em existe para
     cerrar el aire que dejan las minusculas con ascendentes y descendentes; en
     mayusculas, todas las letras miden lo mismo y ese mismo valor las apelmaza.
   - El tamano baja un punto arriba (de 2,75 a 2,5rem). Una linea en caja alta
     ocupa mas ancho a igual cuerpo, y a 2,75 los titulos largos como
     "FUERA DE PANTALLA" empezaban a partirse en dos. */
.bloque__titulo {
  margin: 0 0 var(--e3);
  font-family: var(--display); font-weight: 700;
  font-size: clamp(1.6rem, 1.1rem + 1.8vw, 2.5rem);
  line-height: 1.14;
  text-transform: uppercase;
  letter-spacing: .025em;
  text-wrap: balance;
  color: var(--rojo);
}

/* Cuando el titulo es lo unico que lleva la seccion, va centrado: sin texto al
   lado, un titulo suelto pegado a la izquierda deja un vacio raro a su
   derecha. */
.bloque__titulo--solo { text-align: center; }

/* Los bloques con una linea de apoyo centran titulo y linea, pero NO las
   piezas: esas siguen su propia rejilla. */
.bloque--centrado > .bloque__titulo,
.bloque--centrado > .bloque__texto {
  text-align: center;
  margin-inline: auto;
}
/* `balance` reparte la linea de apoyo en renglones parejos. Sin el, la linea
   de la campana de seguridad rompia dejando "dice dos." solo en el segundo
   renglon: dos palabras sueltas debajo de una linea llena se leen como un
   error de maqueta. Es la misma regla que ya usaba el titular del hero, y aqui
   hacia mas falta todavia, porque estas lineas van centradas y un huerfano
   centrado se nota el doble. */
.bloque__texto {
  margin: 0;
  max-width: 62ch;
  color: var(--tinta-media);
  text-wrap: balance;
}
.bloque__texto + .bloque__texto { margin-top: var(--e2); }
.bloque--centrado > .bloque__texto { margin-bottom: var(--e4); }

/* Dos columnas para el encargo. Es el unico texto largo de la pagina y en una
   sola columna a 1240 px quedaria una linea de 140 caracteres. */
.dos-columnas {
  display: grid; gap: var(--e3) var(--e5);
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .dos-columnas { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); align-items: start; }
}

.alcance { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--e2); }
.alcance li {
  padding-top: var(--e2);
  border-top: 1px solid var(--linea);
  color: var(--tinta-media);
}

/* --- Rejilla de galeria -------------------------------------------------
   Ni pies, ni nombres, ni fechas: solo la imagen y el zoom. Lo que hace una
   galeria es dejar mirar; cada rotulo que se agrega es una interrupcion. La
   descripcion sigue existiendo en el `alt` de cada imagen, o sea que un lector
   de pantalla la lee aunque no se vea. */

.galeria {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(10px, 1.4vw, 20px);
  margin: 0; padding: 0; list-style: none;
  /* `dense` es obligatorio con spans mezclados: sin el, la rejilla deja el
     hueco donde la pieza grande no cabia y se lee como celda vacia. */
  grid-auto-flow: dense;
}

/* Una de cada seis ocupa 2x2. No es decoracion: dieciseis cuadrados iguales en
   fila se leen como hoja de contactos, y lo que se quiere es una galeria. La
   estructura sale de "Bento Box Grid"; su decoracion (radio 24 px, sombras,
   fondo gris) NO se toma, porque esta pagina va a radio 0 y sin sombras. */
@media (min-width: 900px) {
  .galeria:not(.galeria--serie) > li:nth-child(6n + 1) {
    grid-column: span 2;
    grid-row: span 2;
  }
}

/* La campana de seguridad usa la misma rejilla SIN la celda doble. En una
   serie numerada, sacar una pieza al doble de tamano dice que esa importa mas
   que las otras, y no es cierto: las ocho pesan lo mismo y por eso se
   publicaron juntas. */
.galeria--serie { grid-auto-flow: row; }

/* --- Capsulas de Buen Trato --------------------------------------------
   Ocho verticales de 930x1280 en dos filas de cuatro. Van completas y en
   orden: son una escala de color y quitar una rompe la escala. La rejilla es
   fija en cuatro columnas y no `auto-fit`, para que las dos filas queden
   iguales y se vea que es una serie cerrada. */

.capsulas {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(10px, 1.4vw, 20px);
  margin: 0; padding: 0; list-style: none;
}

/* --- Aplicaciones: Ponle Freno, convocatorias y POP ---------------------
   Tres columnas para piezas de formas MEZCLADAS: cuadrados, verticales,
   mockups horizontales. Por eso las celdas se alinean arriba (`start`) y no se
   estiran: estirar obligaria a recortar, y recortar el mockup de un pendon
   deja de ensenar el pendon. */

.aplicaciones {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(12px, 1.8vw, 24px);
  margin: 0; padding: 0; list-style: none;
}

/* TODAS LAS CELDAS, EL MISMO ALTO. Antes cada pieza traia el suyo (360, 393,
   445, 541 px en la misma fila de Ponle Freno) y la seccion parecia sin
   diagramar.

   Cuadrado y `contain`, no `cover`. `cover` igualaria el alto recortando, y
   recortar el mockup de un pendon deja de ensenar el pendon. Con `contain` la
   pieza entra entera y lo que sobra es papel, que es exactamente lo que hay
   detras en el mockup. El cuadrado sale de las propias piezas: tres de las
   seis de Ponle Freno y las seis convocatorias son 1:1, asi que esas no pierden
   ni un pixel de tamano. */
.aplicaciones > li { aspect-ratio: 1; }
.aplicaciones > li > .pieza { height: 100%; }
.aplicaciones > li > .pieza > img { height: 100%; object-fit: contain; }

/* La variante del POP. Tres celdas y no cuatro: las dos gorras son la misma
   pieza vista de dos maneras, asi que comparten celda, apiladas. Con cuatro
   celdas en tres columnas, la cuarta caia sola en una segunda fila y dejaba dos
   huecos del tamano de una pieza.

   La celda apilada respeta el mismo cuadrado que las otras dos, y dentro se
   parte en dos mitades iguales con la misma calle que separa las columnas. Asi
   las tres celdas terminan a la misma altura y no hay nada que cuadrar a ojo. */
.pop-par {
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: clamp(12px, 1.8vw, 24px);
  height: 100%;
}
.pop-par__lado { min-height: 0; }
.pop-par__lado .pieza { height: 100%; }
.pop-par__lado .pieza img { height: 100%; object-fit: contain; }

/* --- Correo interno -----------------------------------------------------
   REJILLA DE CELDAS IGUALES, con la pieza asomando desde arriba.

   La primera version usaba `columns: 4`, o sea multicolumna, para que cada
   correo cayera con su alto real sin recortarse. Tecnicamente correcto y
   visualmente malo: son ocho piezas de proporciones muy distintas repartidas en
   cuatro columnas de dos, asi que las columnas terminaban a alturas muy
   diferentes (la del correo de EPP, que mide 650x1442, casi doblaba a las
   demas) y al pie de la seccion quedaba un vacio de varios cientos de pixeles.
   El balanceo de `columns` no lo arregla: reparte por orden de documento, no
   por altura.

   Ahora la celda manda: 3/4 fija, y la imagen entra con `cover` anclada arriba.
   Ocho celdas iguales en dos filas de cuatro, cero hueco.

   POR QUE 3/4 Y NO OTRA. No es un numero de gusto: SIETE de los ocho correos
   estan entre 0,70 y 0,83 de proporcion, asi que a 0,75 se recortan unos pocos
   pixeles o ninguno. El unico que pierde de verdad es el de EPP, que es una
   infografia larga y ensena su mitad de arriba.

   Y SI, ESTO RECORTA, que es justo lo que la version anterior evitaba. El
   cambio es defendible por una razon concreta: el correo completo sigue estando
   a un clic, entero y sin recortar, en el visor. Lo que se recorta es la
   miniatura, no la pieza. Un correo de 2.900 px de alto metido en una columna
   de 269 px tampoco se leia: ya era un asomo, solo que uno que descuadraba la
   seccion. */

.correos {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(10px, 1.4vw, 20px);
  margin: 0; padding: 0; list-style: none;
}
.correos > li { aspect-ratio: 3 / 4; }
.correos > li > .pieza { height: 100%; }
.correos > li > .pieza > img {
  height: 100%;
  object-fit: cover;
  /* Anclada ARRIBA, no al centro. Un correo se lee de arriba abajo y lo que
     identifica la pieza es su encabezado; centrado, la miniatura ensenaria un
     trozo del medio que no dice de que correo se trata. */
  object-position: top;
}

@media (max-width: 1099px) { .correos { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* --- Video --------------------------------------------------------------
   AGRUPADA POR FORMA, y por eso es flex y no grid.

   Los siete videos no son del mismo formato: cuatro cuadrados de 1080, dos
   verticales y uno 16:9. En una rejilla de tres columnas quedaban escalonados,
   con un cuadrado al lado de un vertical que medía 200 px mas de alto, y la
   seccion parecia sin diagramar.

   La salida NO es recortarlos a todos al mismo cuadrado: un vertical es
   vertical, y meterlo en una caja cuadrada con bandas negras a los lados es
   enseñar el reproductor en vez de la pieza. La salida es AGRUPAR: como
   `seleccion.py` ya lista los videos por forma (cuadrados, verticales,
   horizontal), basta con darle a cada forma su ancho y dejar que el flex
   reparta. Salen tres filas y cada una cuadra sola:

     [cuadrado] [cuadrado] [cuadrado] [cuadrado]
             [vertical] [vertical]
     [        el 16:9, a ancho completo        ]

   La fila de los verticales va centrada. Eso deja aire a los lados, pero es
   aire simetrico y deliberado, no el hueco de una celda que se quedo vacia:
   son dos piezas centradas, no cuatro con dos faltando. */

.videos {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
  gap: clamp(12px, 1.8vw, 24px);
  margin: 0; padding: 0; list-style: none;
  --calle: clamp(12px, 1.8vw, 24px);
}
.videos > li { margin: 0; min-width: 0; }

/* Un cuarto del ancho, descontando las tres calles que hay entre cuatro
   piezas. Los cuatro cuadrados llenan la primera fila exacta. */
.video--cuadrado { flex: 0 0 calc((100% - var(--calle) * 3) / 4); }

/* Los verticales van al MISMO ancho que un cuadrado, no mas anchos: asi la
   fila de abajo se lee como continuacion de la de arriba y no como otra cosa.
   Al ser solo dos, `justify-content: center` los deja centrados. */
.video--vertical { flex: 0 0 calc((100% - var(--calle) * 3) / 4); }

/* Ancho completo para un horizontal. HOY NO LA USA NADIE: el unico 16:9 que
   habia (el institucional de Frontera Energy) salio el 20 ago 2026. Se queda,
   igual que la de `--vertical`, porque cuesta una linea y es lo unico que hace
   falta si vuelve a entrar uno. Al ser flex y no grid, no hay columna que
   recalcular. */
.video--ancho { flex: 0 0 100%; }
/* `display: block` no es cosmetico: <video> es inline por defecto y deja 8 px
   de hueco bajo la caja, el mismo del descendente de una linea de texto. Con
   siete videos alineados arriba, esos 8 px desalinean la fila entera. */
.video video {
  display: block;
  width: 100%; height: auto;
  background: #000;
}
.video--ancho { grid-column: span 2; }

/* A dos por fila: los cuadrados quedan 2 y 2, los verticales 2, y el ancho
   sigue solo. Las tres filas siguen cuadrando. */
@media (max-width: 899px) {
  .video--cuadrado,
  .video--vertical { flex-basis: calc((100% - var(--calle)) / 2); }
}

/* En movil las rejillas de cuatro caen a dos columnas. Las de tres caen a una
   sola: un mockup de libreta a 46vw en un telefono se queda en 170 px y deja
   de verse lo que dice. */
@media (max-width: 899px) {
  .galeria, .capsulas, .correos { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 699px) {
  .aplicaciones { grid-template-columns: 1fr; }
  .video--cuadrado,
  .video--vertical { flex-basis: 100%; }

  /* A una columna se suelta el cuadrado. Ya no hay fila que cuadrar, y forzar
     `contain` dentro de un cuadrado a ancho completo dejaria bandas de papel de
     100 px arriba y abajo de cada pieza. Cada una vuelve a su proporcion. */
  .aplicaciones > li { aspect-ratio: auto; }
  .aplicaciones > li > .pieza > img { height: auto; object-fit: fill; }
  .pop-par { grid-template-rows: auto auto; height: auto; }
  .pop-par__lado .pieza img { height: auto; object-fit: fill; }
}

/* La pieza es un boton que envuelve la imagen. Sin JS sigue siendo un boton
   inerte y la imagen se ve igual: la galeria nunca depende del script para
   mostrar el trabajo. */
.pieza {
  position: relative;
  display: block; width: 100%; padding: 0;
  border: 0; background: var(--papel-alt);
  cursor: zoom-in;
  overflow: hidden;
}
.pieza img {
  width: 100%; height: auto;
  transition: transform .5s var(--salida), opacity .3s ease;
}
.pieza:hover img, .pieza:focus-visible img { transform: scale(1.06); }

/* --- Pares 1:1 y 9:16 ---------------------------------------------------
   Las dos columnas estan en proporcion 1 : 0.5625, o sea la del 9:16 frente al
   cuadrado: asi las dos imagenes terminan exactamente a la misma altura y la
   comparacion es honesta. Si se dejaran a anchos iguales, la story se veria
   mas alta y pareceria otra cosa. En movil se apilan y la story se topa,
   porque a ancho completo mide casi dos pantallas ella sola. */

.pares {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--e5);
  margin: 0; padding: 0; list-style: none;
}
@media (min-width: 900px) {
  .pares {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--e4) var(--e5);
  }
}
.par { margin: 0; }
.par__visor { display: grid; gap: clamp(10px, 1.4vw, 20px); align-items: end; }
@media (min-width: 700px) { .par__visor { grid-template-columns: 1fr .5625fr; } }
@media (max-width: 699px) { .par__lado--story { max-width: 58%; } }

.par__lado { min-width: 0; }

/* --- Nota de creditos ---------------------------------------------------- */

.creditos {
  max-width: 68ch;
  margin: 0;
  padding-left: var(--e3);
  border-left: 2px solid var(--rojo);
  font-size: .95rem;
  color: var(--tinta-media);
}
.creditos strong { font-weight: 600; color: var(--tinta); }

/* --- Cierre -------------------------------------------------------------- */

/* EL AIRE ALREDEDOR DEL FILETE, medido y recortado el 20 ago 2026.

   Antes sobraban unos 120 px repartidos a los dos lados de la linea y el cierre
   se leia despegado del caso, como si fuera otra pagina. Y venian de dos sitios
   distintos, que es por lo que no bastaba con tocar aqui:

     - ARRIBA lo ponia el `margin-bottom` del bloque de creditos (4,25rem), que
       COLAPSA con el `margin-top` de esta seccion y gana el mas grande de los
       dos. Bajar solo el de aqui no hacia nada: seguia mandando el del bloque.
       Por eso el margen de arriba se pone en 0 y el espacio lo decide el bloque
       anterior, con la regla `:has(+ .cierre)` de mas abajo.
     - ABAJO lo pone el `padding-top` de esta seccion, que si se controla aqui.

   Queda en unos 40 px arriba y 32 abajo: suficiente para que el filete separe,
   y poco para que el cierre siga perteneciendo al caso. */
.cierre {
  margin-block: 0;
  /* El de abajo baja de 3rem a 1,75rem: entre el boton y el filete del pie
     habia 104 px (48 de aqui y 56 del pie) y sobraban. Ver `.pie`. */
  padding-block: clamp(1.5rem, 2.5vw, 2rem) clamp(1.25rem, 2vw, 1.75rem);
  border-top: 1px solid var(--linea);
}

/* El bloque que va justo antes del cierre acorta su margen inferior. `:has` es
   lo que permite que la regla viva aca y no haya que marcar ese bloque a mano
   en `generar_pagina.py`: si algun dia se agrega una seccion antes del cierre,
   el espacio se ajusta solo. */
.bloque:has(+ .cierre) { margin-bottom: clamp(1.75rem, 3vw, 2.5rem); }
/* Mismo tratamiento que los titulos de seccion: es uno mas, aunque viva en
   otro bloque. */
.cierre h2 {
  margin: 0 0 var(--e2);
  color: var(--rojo);
  max-width: none;
  font-family: var(--display); font-weight: 700;
  font-size: clamp(1.6rem, 1.1rem + 1.8vw, 2.5rem);
  line-height: 1.14;
  text-transform: uppercase;
  letter-spacing: .025em;
  text-wrap: balance;
}
.cierre p { margin: 0 0 var(--e3); max-width: 60ch; color: var(--tinta-media); }

/* OJO CON EL SELECTOR, que aqui hubo un fallo de verdad.

   Este boton salia con el texto NEGRO sobre el rojo, no blanco. La causa es de
   especificidad y no se ve leyendo esta regla sola:

     .caso-coltanques a { color: inherit; }   ->  (0,1,1)  GANA
     .boton             { color: #fff; }      ->  (0,1,0)

   El boton es un <a>, asi que la regla generica de enlaces le ganaba y le metia
   `inherit`, o sea la tinta del cierre. Y no era solo feo: #131313 sobre
   #d60724 da 3,5:1, que NO pasa AA. En blanco da 5,36:1.

   Por eso el selector lleva la clase del caso delante. No se arregla con
   `!important`: lo que hay que hacer es empatarle la especificidad al selector
   que estaba ganando.

   ESTE MISMO FALLO ESTABA EN `barkys.css` Y EN `bonfibra.css`, que tienen la
   pareja de reglas identica. Corregidos los dos en ago 2026, igual que aqui.
   Los tres daban practicamente el mismo contraste, 3,5:1, y no por casualidad:
   los tres acentos estan calibrados a 5,26-5,36:1 contra blanco, asi que contra
   la tinta #131313 (18,58:1 con blanco) los tres caen en 18,58/5,3 = 3,5. */
.caso-coltanques .boton {
  display: inline-block;
  padding: .95rem 2rem;
  background: var(--rojo); color: #fff;
  font-family: var(--texto); font-weight: 600; font-size: 1rem;
  text-decoration: none;
  transition: background .2s var(--salida), transform .2s var(--salida);
}
.caso-coltanques .boton:hover { background: var(--rojo-oscuro); }
.caso-coltanques .boton:active { transform: translateY(1px); }

/* --- El pie -------------------------------------------------------------
   El mismo patron de Barkys y Bonfibra, que es el pie de las paginas de caso y
   de las landings: filete con la marca partiendo la linea, menu del sitio
   separado por filetes verticales, linea legal y nota de que trabajo fue y de
   que ano.

   Viaja DENTRO del fragmento, no en `shared-components`: al integrar, esta
   pagina conserva el suyo. */

/* El `padding-top` baja de 3,5rem a 2rem. Sumado al `padding-bottom` del
   cierre, el hueco entre el boton y el filete de la marca pasa de 104 px a 60.
   El de abajo NO se toca: es el aire al final del documento y sostiene la linea
   legal. */
.pie {
  padding: clamp(1.5rem, 2.5vw, 2rem) var(--margen) clamp(2rem, 4vw, 3rem);
  background: var(--papel);
  text-align: center;
}
.pie > .contenedor { padding-inline: 0; }

/* Filete con la marca partiendo la linea. */
.pie__filete {
  display: flex;
  align-items: center;
  gap: var(--e3);
  margin-bottom: var(--e4);
}
.pie__filete::before,
.pie__filete::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--linea);
}
.pie__filete img { height: 26px; width: auto; }

/* Menu del pie: enlaces separados por un filete vertical. */
.pie__menu {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--e2) 0;
  margin-bottom: var(--e4);
}
.pie__menu a {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 44px;              /* objetivo tactil */
  padding: 0 clamp(9px, 1.4vw, 17px);
  font-size: .87rem;
  color: var(--tinta-suave);
  text-decoration: none;
  transition: color .2s;
}
.pie__menu a + a::before {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: 1px; height: 11px;
  margin-top: -5px;
  background: var(--linea);
}
.pie__menu a:hover { color: var(--rojo); }

/* En movil el menu cae en dos filas, y el filete de `a + a` deja una rayita
   suelta al empezar la segunda: el selector no sabe donde envuelve el flex.
   Abajo de 700 px se quitan los filetes y separa el espacio. */
@media (max-width: 699px) {
  .pie__menu { gap: 0 var(--e1); }
  .pie__menu a::before { display: none; }
}

.pie__legal { margin: 0; font-size: .8rem; color: var(--tinta-suave); }
.pie__nota { margin: 6px 0 0; font-size: .78rem; color: var(--tinta-suave); opacity: .85; }

/* --- Visor (lightbox) ---------------------------------------------------
   <dialog> nativo: trae el foco atrapado, el Esc y el fondo inerte sin una
   linea de JS. Lo unico que agrega el script es la navegacion con flechas.
   El fondo va oscuro aunque la pagina sea blanca: es la unica manera de que
   una pieza con fondo blanco se lea como pieza y no como parte de la pagina. */

.visor {
  width: 100vw; max-width: 100vw;
  height: 100dvh; max-height: 100dvh;
  padding: 0; border: 0;
  background: transparent;
  overflow: hidden;
}
.visor::backdrop { background: rgb(17 17 17 / .95); }
/* `minmax(0, 1fr)` y no `1fr`: son cosas distintas. `1fr` equivale a
   `minmax(auto, 1fr)`, y ese minimo `auto` es el min-content de lo que hay
   dentro — o sea el alto INTRINSECO de la imagen. Con una pieza vertical la
   fila crecia hasta el tamano real del archivo, la imagen se salia por abajo
   del dialogo y tapaba la barra de navegacion. Medido en Eterna: en un visor
   de 257px de alto, una pieza de 600x1600 se pintaba a 981px.
   El `0` de minimo deja que la fila se encoja y la imagen se ajuste. */
.visor[open] { display: grid; grid-template-rows: minmax(0, 1fr) auto; }

/* Flex y no grid: con `place-items: center` la imagen quedaba de item de
   rejilla y su `max-height: 100%` se resolvia contra una altura que la propia
   imagen estaba estirando. En flex el marco manda y la imagen se ajusta.
   `overflow: hidden` es el cinturon de seguridad por si algo se escapa. */
.visor__marco {
  display: flex; align-items: center; justify-content: center;
  min-height: 0; min-width: 0;
  overflow: hidden;
  padding: clamp(var(--e3), 5vw, var(--e5));
}
.visor__marco img {
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  object-fit: contain;
  background: #fff;
}
.visor__barra {
  display: flex; align-items: center; gap: var(--e3);
  padding: var(--e2) clamp(var(--e2), 4vw, var(--e4)) var(--e4);
  color: #f2f2f2;
}
.visor__cuenta {
  flex: 1;
  font-family: var(--dato); font-size: .78rem;
  color: #9a9a9a; white-space: nowrap;
}
.visor__nav { display: flex; gap: .5rem; }

.visor button {
  display: grid; place-items: center;
  width: 2.6rem; height: 2.6rem;
  color: #fff; background: rgb(255 255 255 / .1);
  border: 0; cursor: pointer;
  font-size: 1.1rem; line-height: 1;
  transition: background .2s var(--salida);
}
.visor button:hover:not(:disabled) { background: rgb(255 255 255 / .24); }
.visor button:disabled { opacity: .3; cursor: default; }
.visor__cerrar {
  position: absolute; top: var(--e2); right: clamp(var(--e2), 4vw, var(--e4));
}

/* ==========================================================================
   MOVIMIENTO
   --------------------------------------------------------------------------
   Hay tres capas y cada una responde a una pregunta distinta. Ninguna esta por
   verse bonita: si no se puede decir en una frase que comunica, sobra.

     1. Entrada al hacer scroll     ¿esto es nuevo? ¿de donde venia?
     2. Profundidad en la galeria   las piezas llegan desde atras y se posan
     3. Secuencia de apertura       jerarquia: marca, titular, contexto

   El motor preferido es `animation-timeline: view()`, o sea animacion ligada
   al scroll HECHA POR EL NAVEGADOR. No hay un solo listener de scroll ni un
   requestAnimationFrame: el compositor la corre fuera del hilo principal y no
   se cae aunque la pagina tenga sesenta imagenes. Donde no exista, el
   observador de `coltanques.js` hace la version simple y nadie se entera.
   ========================================================================== */

/* --- Capa 1: entrada, version de respaldo -------------------------------
   Se oculta SOLO si el JS ya corrio (clase .js en el <html>): sin script no se
   esconde nada, porque una animacion no puede ser el motivo por el que alguien
   vea una pagina en blanco. */

.js [data-entra] {
  opacity: 0;
  transform: translateY(20px) scale(.985);
}
.js [data-entra].visible {
  opacity: 1;
  transform: none;
  transition:
    opacity .75s var(--salida) var(--retraso, 0ms),
    transform .75s var(--salida) var(--retraso, 0ms);
}

/* --- Capa 2: profundidad ligada al scroll -------------------------------
   Las piezas no aparecen: se acercan. Entran inclinadas y desde el fondo, y
   terminan de posarse cuando estan bien dentro de la pantalla, asi que el
   efecto se siente al scrollear y no como un parpadeo al cruzar un umbral.

   Se queda corto a proposito. La pieza se endereza y para: con sesenta
   imagenes, mantenerlas girando convierte la galeria en un carrusel y deja de
   poderse mirar el trabajo, que es para lo que existe la pagina. */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {

    /* `.correos` va en la lista aunque sea multicolumna y no rejilla. Se quedo
       fuera en la primera version y se detecto leyendo `getComputedStyle`: sin
       perspective en el padre, el translate3d en Z y el rotateX de `llega` se
       aplanan, o sea que las piezas de correo subian sin profundidad mientras
       las otras cinco rejillas si la tenian. Se veia como si esa seccion
       estuviera a medio hacer. */
    .galeria, .capsulas, .aplicaciones, .videos, .pares, .correos { perspective: 1500px; }
    .galeria > li, .capsulas > li, .aplicaciones > li, .videos > li,
    .correos > li, .pares > .par { transform-style: preserve-3d; }

    /* La animacion manda sobre el estado de la capa 1: una animacion en curso
       gana sobre el valor declarado y sobre la transicion.
       Solo las IMAGENES llegan con profundidad. El texto sube y ya: una linea
       de texto girando en perspectiva se lee peor y no comunica nada. */
    .js:not(.sin-timeline) .galeria > li,
    .js:not(.sin-timeline) .capsulas > li,
    .js:not(.sin-timeline) .aplicaciones > li,
    .js:not(.sin-timeline) .videos > li,
    .js:not(.sin-timeline) .correos > li,
    .js:not(.sin-timeline) .par {
      opacity: 1;
      transform: none;
      animation: llega linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 24%;
    }

    .js:not(.sin-timeline) .bloque__titulo[data-entra],
    .js:not(.sin-timeline) .bloque__texto[data-entra] {
      opacity: 1;
      transform: none;
      animation: asoma linear both;
      animation-timeline: view();
      animation-range: entry 8% cover 26%;
    }

    /* Las dos mitades del par llegan desde profundidades distintas y se posan
       en el mismo plano. Es literal: son dos versiones de la misma pieza. */
    .js:not(.sin-timeline) .par__lado--story {
      animation: llega-story linear both;
      animation-timeline: view(); animation-range: entry 0% cover 28%;
    }

    /* Las tiras hacen zoom de salida dentro de su marco durante todo el
       recorrido. Da profundidad sin mover nada de sitio, que es lo unico que
       se puede permitir un elemento que ocupa el ancho completo. La figura
       solo aparece: dos movimientos encima de la misma imagen se pelean. */
    .js:not(.sin-timeline) .tira-sangre {
      opacity: 1; transform: none;
      animation: asoma linear both;
      animation-timeline: view(); animation-range: entry 4% cover 22%;
    }

    .js:not(.sin-timeline) .tira-sangre img {
      animation: acerca linear both;
      animation-timeline: view();
      animation-range: entry 0% exit 100%;
      will-change: transform;
    }
  }
}

@keyframes llega {
  from { opacity: 0; transform: translate3d(0, 44px, -150px) rotateX(11deg); }
  to   { opacity: 1; transform: none; }
}
@keyframes llega-story {
  from { opacity: 0; transform: translate3d(0, 44px, -260px) rotateX(11deg); }
  to   { opacity: 1; transform: none; }
}
@keyframes asoma {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: none; }
}
@keyframes acerca {
  from { transform: scale(1.07); }
  to   { transform: scale(1); }
}

/* --- Capa 3: secuencia de apertura --------------------------------------
   Las tiras del fondo del hero. Cada una recorre la mitad de su propia altura
   y vuelve a empezar; como el contenido esta duplicado, el salto es invisible.
   Velocidades distintas por tira: es lo que vende la profundidad. Las pares
   van al reves para que el conjunto no parezca una sola cortina bajando.

   Se anima `transform`, nunca `top`: solo asi el trabajo se queda en el
   compositor y no obliga a recalcular la maqueta en cada fotograma. */

.js .tira { animation: desfilar var(--vel, 70s) linear infinite; }
.js .tira:nth-child(even) { animation-direction: reverse; }
.js .tira:nth-child(1) { --vel: 68s; }
.js .tira:nth-child(2) { --vel: 84s; }
.js .tira:nth-child(3) { --vel: 74s; }
.js .tira:nth-child(4) { --vel: 92s; }

@keyframes desfilar {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, -50%, 0); }
}

/* El texto del hero entra escalonado al cargar: la marca, el rotulo, el
   titular y la bajada. Es la jerarquia de quien mira: de quien es la pagina,
   que trabajo es y de quien es el cliente. */
.js .marca           { animation: sube .7s var(--salida) both; animation-delay: .05s; }
.js .portada__rotulo { animation: sube .8s var(--salida) both; animation-delay: .10s; }
.js .portada__titulo { animation: sube .9s var(--salida) both; animation-delay: .22s; }
.js .portada__bajada { animation: sube .9s var(--salida) both; animation-delay: .38s; }

@keyframes sube {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* --- El interruptor -----------------------------------------------------
   Una sola regla apaga las tres capas. Va al final para que gane siempre. */

@media (prefers-reduced-motion: reduce) {
  .js [data-entra] { opacity: 1; transform: none; transition: none; }
  .js .tira { animation: none; }
  .js .marca, .js .portada__rotulo, .js .portada__titulo,
  .js .portada__bajada,
  .js .galeria > li, .js .capsulas > li, .js .aplicaciones > li,
  .js .videos > li, .js .correos > li, .js .par,
  .js .par__lado--story, .js .tira-sangre, .js .tira-sangre img {
    animation: none;
    opacity: 1;
    transform: none;
    clip-path: none;
  }
  .pieza img, .boton { transition: none; }
  .pieza:hover img, .pieza:focus-visible img { transform: none; }
}

/* --- Impresion ----------------------------------------------------------
   Un caso de portafolio se imprime a PDF mas seguido de lo que parece. */
@media print {
  .visor, .cierre .boton { display: none; }
  .js [data-entra] { opacity: 1; transform: none; }
  .galeria { grid-template-columns: repeat(3, 1fr); }
  /* `.videos` es flex, no grid: `grid-template-columns` aqui no hacia nada. Al
     imprimir, los cuadrados van de a dos y el 16:9 se queda con su fila. */
  .video--cuadrado, .video--vertical { flex-basis: calc((100% - var(--calle)) / 2); }
}
