/* ==========================================================================
   BANA FACES

   Cuatro reglas, sin excepciones:

   1. RADIO — todo a 0. Ni un solo ángulo redondeado.
   2. FILETES — dos únicos usos. `--ink` para los marcos deliberados: la
      parrilla de fotos y el pie. `--rule` para cualquier división de
      interfaz. Ningún tercer gris.
   3. ESCALA — espaciados en múltiplos de 4 y tamaños de la lista de abajo.
      Nada de números sueltos.
   4. CAJA — versal con tracking para navegación, etiquetas y botones.
      Redonda para nombres, titulares y texto corrido. Nunca al revés.

   Tipografía: Favorit (Dinamo). Deja los .woff2 en assets/fonts/ y entra
   sola. Sin ellos cae a Helvetica, y el tracking está medido para que
   aguante en las dos.
   ========================================================================== */

/* Favorit, de la licencia del proyecto de identidad, convertida a woff2.

   El @font-face anterior apuntaba a dos ficheros que no existían: la web
   nunca llegó a usar Favorit y caía a Helvetica. Eso era lo que se veía
   delgado, no el peso.

   Sólo tres cortes: cada uno son unos 55 KB que descarga cada visitante, y
   una familia con italicas y variantes que nadie usa es peso muerto. */
@font-face {
  font-family: "Favorit";
  src: url("../fonts/Favorit-Regular.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Favorit";
  src: url("../fonts/Favorit-Medium.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Favorit";
  src: url("../fonts/Favorit-Bold.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}

:root {
  /* superficies */
  --bone:  #ebeae5;
  --white: #ffffff;
  --ink:   #000000;
  --grey:  #b8b4b0;
  --pink:  #ecc8ca;
  --blue:  #5467c4;
  --green: #295c55;
  --red:   #a32d2f;

  /* texto — el negro es el color principal. La jerarquía se hace con tamaño
     y peso, no aclarando el texto. --off queda sólo para lo deshabilitado. */
  --dim:  #000000;
  --off:  #7d7a76;
  --rule: #000000;

  /* esquinas: sutil en cajas, píldora en botones, círculo en puntos */
  --r-box: 12px;

  /* tamaños — una sola medida para toda la interfaz. Sólo se salen de ella
     el nombre del talento y el texto de los desplegables. */
  --t-ui:      20px;

  /* La navegación medía un 30% más que el resto; ahora todo el texto está a
     ese cuerpo, así que este token apunta al general. Se mantiene como
     nombre propio para poder volver a separarlos sin buscar por el fichero. */
  --t-menu:    var(--t-ui);
  --t-display: clamp(30px, 3.4vw, 44px);
  --t-drop:    20px;

  /* Un solo cuerpo de texto en toda la web. `--t-drop` era el nivel
     secundario —pies, versalitas, datos— y ahora mide lo mismo: la jerarquía
     la marcan el color, la versal y la posición, no el tamaño.

     alias, para no reescribir cada regla */
  --t-title:   var(--t-ui);
  --t-body:    var(--t-ui);
  --t-small:   var(--t-ui);
  --t-micro:   var(--t-ui);

  /* tracking */
  --tr-micro:   .08em;
  --tr-display: -.02em;

  /* filete — un único grosor para toda la web. Las uniones nunca lo suman:
     donde dos cajas se tocan, sólo una de las dos lleva línea. */
  --linea: 2px;

  /* espaciado, múltiplos de 4 */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px; --s8: 64px;

  --head-h: 56px;
  --bar-h:  52px;
  --cols: 4;   /* por defecto, 4 por fila */

  --sans: "Favorit", "ABC Favorit", "Helvetica Neue", Helvetica, Arial, sans-serif;
}

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

/* `hidden` esconde, siempre.

   El navegador aplica `[hidden] { display: none }` en su hoja propia, que es
   la más débil de todas: cualquier regla nuestra con `display` la anula. Y
   como medio fichero declara `display` —`.btn` es `inline-flex`, `.grid` es
   `grid`—, poner el atributo desde el guion no escondía nada y el fallo era
   mudo: el atributo estaba puesto y el elemento seguía a la vista.

   Se venía parcheando clase por clase: `.login__err[hidden]`,
   `.chipbar[hidden]`, `.empty[hidden]`, `.grid[hidden]`, `.pasos[hidden]`,
   `.ticker[hidden]`, `.alta[hidden]`, `.modal[hidden]`. Ocho remiendos del
   mismo agujero, y el noveno apareció al esconder un botón en `/action`.

   El `!important` está justificado aquí y sólo aquí: `hidden` es una
   declaración del documento, no una sugerencia de estilo, y ninguna regla de
   presentación debería poder contradecirla. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  /* Un nombre muy largo sin espacios no puede ensanchar la página.

     `clip` y no `hidden`, y la diferencia no es cosmética: `hidden` convierte
     este elemento en una caja de desplazamiento, y entonces todo `sticky` que
     viva dentro se pega a ESA caja en vez de a la ventana — o sea, no se pega.

     Funcionó durante meses por un rodeo: con `html` en `visible`, el
     `overflow` del `body` se propagaba al viewport y el `body` no llegaba a
     ser contenedor. Al añadir `html { overflow-x: clip }` para el pellizco de
     alejar en móvil, esa propagación se cortó y el rodeo desapareció: la
     cabecera fija y las tres secciones de la landing que se sostienen con
     `position: sticky` dejaron de sostenerse, en todos los anchos.

     `clip` recorta igual sin crear contenedor, que es justo para lo que
     existe. */
  overflow-x: clip;
  /* Columna a altura de ventana como mínimo: con poco contenido, el bloque
     central crece y el pie queda anclado abajo en vez de subir. */
  min-height: 100vh;
  display: flex; flex-direction: column;
  background: var(--bone);
  color: var(--ink);
  font-family: var(--sans);
  /* Medium como base. El Regular se veía demasiado fino a los cuerpos
     pequeños que usa este producto, que son casi todos. */
  font-weight: 500;
  font-size: var(--t-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

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

button, input, select, textarea {
  font-family: inherit; font-size: inherit; color: inherit;
  border-radius: 0; -webkit-appearance: none; appearance: none;
}

/* Las casillas y los redondeles se quedan con su dibujo nativo. La regla de
   arriba se lo quitaba a TODOS los `input`, y una casilla sin apariencia no
   es una casilla vacía: es un elemento que no se ve, marcado o no. En el
   formulario de contacto había dos aceptaciones obligatorias invisibles. */
input[type="checkbox"], input[type="radio"] {
  -webkit-appearance: auto; appearance: auto;
  accent-color: var(--ink);
}

:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

svg { display: block; }

/* Versal pequeña. Un solo mixin conceptual para todas las etiquetas. */
.u-label, .campo__label,
.tile__name, .pickcard__name, .marco__meta, .sel-card__meta,
.drop__marca, .dlg-marca, .sel-bar__saved, .panel__back, .panel__sub, .count,
.specs dt, .btn, .pick-btn, .camp__meta {
  font-size: var(--t-ui); letter-spacing: var(--tr-micro); text-transform: uppercase;
}

/* El espacio sobrante lo absorbe un separador propio, nunca el contenido.
   Si lo absorbiera la parrilla, al ser una retícula repartiría ese sobrante
   entre sus filas y estiraría las casillas: con pocas filas, la caja se
   separa de la imagen. */
.espaciador { flex: 1 0 auto; }
.grid, .model, .page, .empty, .head, .bar, .chipbar, .ctx, .foot { flex: none; }

/* ---------- Cabecera ------------------------------------------------------ */

.head {
  position: sticky; top: 0; z-index: 40;
  height: var(--head-h);
  display: flex; align-items: stretch; gap: var(--s6);
  padding: 0 var(--s5);
  background: var(--bone);
  border-bottom: var(--linea) solid var(--ink);
}

/* El trazo del logotipo no está centrado en su propio lienzo: se compensa. */
/* 144px, un 20% sobre los 120 que tuvo. El dibujo es muy apaisado —4.4 a 1—,
   así que a ese ancho mide 32px de alto y sigue sobrando aire en una cabecera
   de 56. Por encima empezaría a tocar el filete. */
.head__logo { display: flex; align-items: center; width: 144px; flex: none; }
.head__logo svg { position: relative; top: 1px; }
.head__logo svg { width: 100%; height: auto; fill: var(--ink); }

/* La navegación y los segmentos comparten tamaño: son el mismo nivel.
   La sección activa se marca con una pequeña vertical que cruza el filete
   inferior, no con subrayado: así el texto queda centrado de verdad en su
   caja, sin el relleno extra que pedía la línea. */
.head__nav {
  display: flex; align-self: stretch; gap: var(--s5); margin-left: auto;
}
.head__nav a {
  position: relative; display: flex; align-items: center;
  font-size: var(--t-menu); letter-spacing: .01em; text-transform: uppercase;
}
/* Se apoya en el filete por dentro y crece hacia arriba: nunca lo cruza. */
.head__nav a::after {
  content: ""; position: absolute; left: 50%; bottom: 0;
  width: var(--linea); height: 11px; background: var(--ink);
  transform: translateX(-50%) scaleY(0); transform-origin: center bottom;
  transition: transform .18s ease;
}
.head__nav a:hover::after { transform: translateX(-50%) scaleY(.5); }
.head__nav a[aria-current="page"]::after { transform: translateX(-50%) scaleY(1); }

.head__right { display: flex; align-items: center; margin-left: var(--s5); }

.head__user {
  position: relative; display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: 50%;
  border: var(--linea) solid var(--ink); background: none; cursor: pointer; color: var(--ink);
  transition: background .16s;
}
.head__user svg { width: 17px; height: 17px; }
.head__user:hover { background: var(--pink); }

/* Punto verde: hay sesión abierta. El anillo lo separa del botón, así que
   crece con el filete para que el verde siga leyéndose. */
/* La inicial de quien ha entrado. Sustituye a la silueta y al punto verde:
   una letra donde antes había un icono genérico ya dice que hay alguien
   dentro, y además dice quién. El punto además iba pegado al borde del
   círculo y descentraba el conjunto. */
.head__ini {
  font-size: var(--t-ui); line-height: 1;
  letter-spacing: 0; text-transform: uppercase;
}

.drop--cuenta { min-width: 230px; padding: var(--s4); }
.drop__correo { margin: 0 0 var(--s3); font-size: var(--t-small); }
.drop__login { display: flex; flex-direction: column; gap: var(--s2); }
.login__err {
  padding: var(--s1) var(--s2); border-radius: var(--r-box);
  background: var(--pink); color: var(--red); font-size: var(--t-drop);
}
.login__err[hidden] { display: none; }
.drop__login input {
  height: 30px; padding: 0 var(--s3);
  border: var(--linea) solid var(--ink); border-radius: 22px; background: var(--white);
  font-size: var(--t-small);
}
.drop__login input:focus { outline: none; border-color: var(--ink); }
.drop--cuenta .drop__row { justify-content: flex-start; }

/* ---------- Barra de segmentos -------------------------------------------- */

.bar {
  position: sticky; top: var(--head-h); z-index: 35;
  height: var(--bar-h);
  display: flex; align-items: stretch; gap: var(--s5);
  padding: 0 var(--s5);
  background: var(--bone);
  border-bottom: var(--linea) solid var(--ink);
}

/* Texto grande, negro de base, y el recuento en un círculo con el color del
   segmento. Al activarse, el círculo se rellena y el texto toma ese color. */

.segs { display: flex; align-self: stretch; align-items: stretch; gap: var(--s5); }

.seg {
  position: relative; display: inline-flex; align-items: center;
  padding: 0; border: 0; background: none; cursor: pointer;
  color: var(--ink);
  font-size: var(--t-menu); letter-spacing: .01em; text-transform: uppercase;
  transition: color .16s;
}
.seg::after {
  content: ""; position: absolute; left: 50%; bottom: 0;
  width: var(--linea); height: 11px; background: var(--seg-c);
  transform: translateX(-50%) scaleY(0); transform-origin: center bottom;
  transition: transform .18s ease;
}
.seg:hover::after { transform: translateX(-50%) scaleY(.5); }
.seg.is-on::after { transform: translateX(-50%) scaleY(1); }
/* El texto se queda en negro: es la base. El color vive en el círculo, que
   es donde se lee bien a cualquier claridad. */
.seg:hover { color: var(--seg-c); }
.seg.is-on { color: var(--ink); font-weight: 500; }
.seg.is-on:hover { color: var(--ink); }

/* Un segmento sin fichas se lee igual que los demás: que esté vacío hoy no
   lo hace menos navegable. */

/* El subrayado del buscador va como pseudoelemento y no como borde: un
   borde real desplaza el contenido medio píxel y rompe la alineación. */
.bar__search {
  position: relative; display: flex; align-items: center; flex: none;
}
.bar__search.is-open::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 12px;
  height: var(--linea); background: var(--ink);
}

.bar__word {
  padding: 0; border: 0; background: none; cursor: pointer;
  color: var(--ink);
  font-size: var(--t-menu); letter-spacing: .01em; text-transform: uppercase;
}
.bar__word:hover { color: var(--blue); }

.bar__search input {
  width: 0; opacity: 0; pointer-events: none;
  border: 0; background: none; padding: 0;
  font-size: var(--t-menu); letter-spacing: .01em;
  transition: width .3s ease, opacity .2s ease, margin .3s ease;
}
.bar__search input:focus { outline: none; }
.bar__search input::placeholder { color: var(--off); text-transform: none; }

.bar__search.is-open .bar__word { display: none; }
.bar__search.is-open input {
  width: 260px; opacity: 1; pointer-events: auto;
}

/* Modelos por línea. Un círculo por valor, el activo relleno. */

.scaler { display: flex; align-items: center; gap: var(--s1); margin-left: auto; }
.scaler button {
  display: grid; place-items: center;
  width: 32px; height: 32px; border-radius: 50%;
  border: var(--linea) solid var(--ink); background: none; cursor: pointer;
  font-size: var(--t-menu); letter-spacing: 0; color: var(--ink);
  transition: background .16s, color .16s;
}
.scaler button:hover { background: var(--pink); }
.scaler button[aria-pressed="true"] { background: var(--ink); color: var(--white); }
.scaler button[aria-pressed="true"]:hover { background: var(--ink); }

.count { color: var(--ink); white-space: nowrap; }

/* ---------- Filtros de texto ---------------------------------------------- */

.chipbar {
  position: sticky; top: calc(var(--head-h) + var(--bar-h)); z-index: 34;
  padding: var(--s2) var(--s5);
  background: var(--bone);
  border-bottom: var(--linea) solid var(--ink);
}
.chipbar[hidden] { display: none; }

.chips { display: flex; flex-wrap: wrap; gap: var(--s1); align-items: center; }

.chip {
  display: inline-flex; align-items: center; gap: var(--s2);
  height: 24px; padding: 0 var(--s1) 0 var(--s3);
  border: var(--linea) solid var(--ink); border-radius: 12px; background: none;
  font-size: var(--t-micro); letter-spacing: .01em;
}
.chip button {
  border: 0; background: none; cursor: pointer; padding: 0;
  width: 16px; height: 16px; display: grid; place-items: center;
}
.chip button:hover { color: var(--blue); }

.chip--clear {
  border-style: dashed; border-color: var(--rule); color: var(--ink);
  padding: 0 var(--s2); cursor: pointer;
}
.chip--clear:hover { color: var(--ink); border-color: var(--ink); }

/* ---------- Parrilla -------------------------------------------------------
   La imagen conserva su 2:3 exacto y el rótulo va debajo, sobre blanco. Así
   el nombre se lee siempre, también cuando la prenda es negra y llega al
   borde inferior de la foto.                                                */

/* Sin borde superior: la barra de arriba ya aporta el suyo y los dos juntos
   se leían como una línea del doble de grosor. */
.grid {
  position: relative;   /* Flip coloca en absoluto durante la transición */
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  background: var(--white);
  border-left: var(--linea) solid var(--ink);
}

.tile.is-out { display: none; }

.tile {
  display: flex; flex-direction: column;
  background: var(--white);
  border-right: var(--linea) solid var(--ink);
  border-bottom: var(--linea) solid var(--ink);
}

.tile__img { position: relative; aspect-ratio: 2 / 3; overflow: hidden; }
.tile__img img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
}
.tile__hover { opacity: 0; transition: opacity .3s ease; }
@media (hover: hover) { .tile:hover .tile__hover { opacity: 1; } }

.tile { position: relative; }

/* Un candado, no la palabra. «EXCLUSIVE» en versales al cuerpo general medía
   más que el nombre del talento y competía con la cara, que es el producto —
   el mismo razonamiento que dejó la marca de IA en texto lavado sin pastilla.

   Redondo y del tamaño de los demás controles circulares de la casa, pero
   relleno en vez de perfilado: los redondos perfilados son botones y éste no
   se pulsa. La marca a la que pertenece va en el `title`, que es donde
   importa —quien necesita el detalle lo busca; quien recorre la parrilla sólo
   necesita saber que hay una. */
.tile__excl {
  position: absolute; top: var(--s2); left: var(--s2); z-index: 2;
  width: 24px; height: 24px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--green); color: var(--white);
}
.tile__excl svg { width: 12px; height: 12px; }

.tarjeta__excl {
  margin: 0 0 var(--s2);
  font-size: var(--t-drop); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--green);
}

.tile__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s2); height: 41px; padding: 0 var(--s1) 0 var(--s3);
  background: var(--white);
}
.tile__name { display: flex; align-items: center; gap: var(--s2); min-width: 0; }
.tile__name > :first-child, .tile__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tile__age { color: var(--off); letter-spacing: .02em; }

.tile__add {
  flex: none; width: 26px; height: 26px;
  display: grid; place-items: center;
  border: var(--linea) solid transparent; border-radius: 50%;
  background: none; cursor: pointer;
  opacity: 0; transition: opacity .16s, border-color .16s;
}
.tile__add svg { width: 11px; height: 11px; }
@media (hover: hover) { .tile:hover .tile__add { opacity: 1; } }
@media (hover: none)  { .tile__add { opacity: 1; } }
.tile__add:focus-visible { opacity: 1; }
.tile__add:hover { border-color: var(--ink); }

/* El color de campaña ya dice que está guardada: la barra no necesita
   volver a decirlo. Sólo se mantiene el botón siempre visible. */
.tile.is-picked .tile__add { opacity: 1; }

.empty {
  padding: var(--s8) var(--s5); text-align: center; background: var(--bone);
}
.empty[hidden] { display: none; }
.grid[hidden] { display: none; }
.empty p { margin: 0 0 var(--s1); }
.empty span { color: var(--off); font-size: var(--t-small); }

/* ---------- Aviso de contexto --------------------------------------------- */

.ctx {
  position: sticky; top: calc(var(--head-h) + var(--bar-h)); z-index: 33;
  display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap;
  padding: var(--s2) var(--s5);
  background: var(--pink);
  font-size: var(--t-small);
}
.ctx strong { font-weight: 500; }
.ctx a { margin-left: auto; text-decoration: underline; font-size: var(--t-micro); }

/* ---------- Botones -------------------------------------------------------- */

/* Excepción a la regla del radio 0: los botones y los chips van en píldora,
   como en bana.studio. Es una familia entera, no un caso suelto. */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  height: 44px; padding: 0 var(--s5);
  border: var(--linea) solid var(--ink); border-radius: 22px;
  background: none; cursor: pointer;
  transition: background .16s, color .16s, border-color .16s;
}
.btn--ink { background: var(--ink); color: var(--white); }
.btn--ink:hover { background: var(--blue); border-color: var(--blue); }
.btn--line { border-color: var(--rule); }
.btn--line:hover { border-color: var(--red); color: var(--red); }
/* Sólido en claro, para cuando va encima de una fotografía. `--ink` se come
   con los planos oscuros y `--line` es un contorno que depende del fondo:
   ninguno de los dos aguanta cualquier imagen. Va junto a los otros dos
   porque es una variante del botón, no una forma nueva. */
.btn--hueso { background: var(--bone); color: var(--ink); border-color: var(--bone); }
.btn--hueso:hover { background: var(--white); border-color: var(--white); }

.pick-btn {
  width: 100%; height: 34px;
  border: var(--linea) solid var(--ink); border-radius: 17px;
  background: var(--ink); color: var(--white);
  cursor: pointer; transition: background .16s, color .16s;
}
.pick-btn:hover { background: none; color: var(--ink); }

/* ---------- Ficha de talento ------------------------------------------------ */

/* La ficha no parte la pantalla: la fotografía ocupa todo y los datos flotan
   encima como una isla. */
.model { position: relative; }

/* Carrusel de tomas: pegadas entre sí, sin separación ni filete. */
.gallery {
  overflow: hidden; cursor: grab; background: var(--white);
  user-select: none; -webkit-user-select: none;
  /* El eje vertical sigue siendo de la página; el horizontal es del carrusel.
     Sin esto Safari decide él solo hacia dónde va el gesto y se lo queda. */
  touch-action: pan-y;
}
.gallery.is-drag { cursor: grabbing; }
.gallery .track { display: flex; will-change: transform; }

/* 2:3 exacto, como en toda la web. La altura manda y el ancho se deriva. */
.toma {
  margin: 0; flex: none;
  height: calc(100vh - var(--head-h) - 56px);
  aspect-ratio: 2 / 3;
  overflow: hidden; background: var(--white);
}

/* Botón de acción y flechas de las tomas, en la misma fila dentro de la isla.
   Las flechas van sin relleno para que no compitan con la acción principal
   ni con las de cambiar de talento, que son idénticas. */
.tarjeta__acciones { display: flex; align-items: center; gap: var(--s2); }
.tarjeta__acciones .btn-accion { flex: 1; }

.pasos { display: flex; gap: var(--s1); flex: none; }
.pasos[hidden] { display: none; }

.paso {
  width: 30px; height: 30px; display: grid; place-items: center;
  border: var(--linea) solid var(--ink); border-radius: 50%;
  background: none; cursor: pointer; color: var(--ink);
  transition: background .16s;
}
.paso svg { width: 13px; height: 11px; }
.paso:hover { background: var(--pink); }
/* Un vídeo vertical mantiene la altura de la fila y su propio 9:16. */
.toma--video { aspect-ratio: 9 / 16; background: var(--ink); }
.toma--video iframe { width: 100%; height: 100%; border: 0; display: block; }

/* Sin `will-change: transform`: con el paralaje apagado estas imágenes ya no
   se transforman, y la pista —`.gallery .track`, que sí se mueve— lo lleva
   por su cuenta. Reservaba una capa de composición por imagen, y con seis
   copias del carril eso es memoria de vídeo a cambio de nada. Si se recupera
   el paralaje en `modelo.js`, vuelve aquí. */
.toma img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}

/* Panel: una caja compacta, no una banda a toda altura. */
/* Barra fija sobre la fotografía: volver a la izquierda, saltar de talento
   a la derecha. */
.cabo {
  position: absolute; top: var(--s5); left: var(--s5); right: var(--s5); z-index: 6;
  display: flex; align-items: center; justify-content: space-between;
  pointer-events: none;
}
.cabo > *, .cabo__nav > * { pointer-events: auto; }
.cabo__nav { display: flex; gap: var(--s2); }

.cabo__btn {
  display: inline-flex; align-items: center; justify-content: center;
  height: 34px; padding: 0 var(--s4);
  border: var(--linea) solid var(--ink); border-radius: 999px;
  background: var(--bone); color: var(--ink);
  font-size: var(--t-ui); letter-spacing: .01em; text-transform: uppercase;
  transition: background .16s;
}
.cabo__btn:hover { background: var(--pink); }
.cabo__btn--ico { width: 34px; padding: 0; }
.cabo__btn--ico svg { width: 15px; height: 13px; }

/* La isla, con aire alrededor.

   Ancha, no estrecha y larga. Con 340px, una descripción de doce líneas
   dejaba una tarjeta casi tres veces más alta que ancha, que sobre una foto
   a sangre se lee como una columna de texto pegada encima y no como una
   ficha. A 560 el mismo texto ocupa la mitad de líneas y la caja queda
   cerca del cuadrado sin tocar ni una palabra.

   El contenido sigue apilado: descripción y luego datos, en una sola
   columna. Repartirlos en dos hacía la caja más baja, pero partía la lectura
   en dos recorridos paralelos y estrechaba la descripción hasta devolverle
   las líneas que el ancho le había quitado. */
.panel {
  position: absolute; right: var(--s6); bottom: var(--s6); z-index: 5;
  width: 560px; max-width: calc(100% - var(--s6) * 2);
}

.tarjeta {
  border: var(--linea) solid var(--ink); border-radius: var(--r-box);
  padding: var(--s5); background: var(--bone);
  box-shadow: 0 8px 34px rgba(0, 0, 0, .14);
}

.tarjeta__nombre {
  margin: 0; font-size: var(--t-display);
  overflow-wrap: anywhere; hyphens: auto; font-weight: 500;
  letter-spacing: var(--tr-display); line-height: 1;
}
.tarjeta__sub {
  margin: var(--s2) 0 var(--s4);
  font-size: var(--t-micro); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--ink);
}
.tarjeta__nota {
  margin: var(--s4) 0 var(--s5); font-size: var(--t-small); line-height: 1.55;
}

/* Botón de acción, en la línea de bana.studio: píldora azul con filete. */
.btn-accion {
  width: 100%; height: 36px; padding: 0 var(--s4);
  display: flex; align-items: center; justify-content: center; gap: var(--s2);
  border: var(--linea) solid var(--ink); border-radius: 18px;
  background: var(--blue); color: var(--ink); cursor: pointer;
  font-size: var(--t-micro); letter-spacing: var(--tr-micro); text-transform: uppercase;
  transition: background .16s;
}
.btn-accion i { font-style: normal; }
.btn-accion:hover { background: var(--pink); }

.specs { margin: 0; padding: 0; }
.specs div {
  display: flex; justify-content: space-between; gap: var(--s3);
  padding: 3px 0; font-size: var(--t-small);
}
.specs dt { color: var(--ink); }
.specs dd { margin: 0; text-align: right; }

/* Una imagen que no carga deja un hueco marcado, nunca un icono roto. */
.is-rota { background: repeating-linear-gradient(45deg,
  var(--bone), var(--bone) 6px, #e2e0da 6px, #e2e0da 12px); }
.is-rota img { opacity: 0; }

/* ---------- Ticker ----------------------------------------------------------
   Texto, velocidad y dirección se configuran en data.js.                    */

/* La cinta no fija fondo, tinta ni cuerpo: los lee de variables que pone el
   módulo en cada instancia. Así la misma clase sirve para la banda blanca de
   la ficha y para cualquier otra que se configure desde Admin, sin duplicar
   reglas ni inventar modificadores. Los valores de aquí son sólo el recambio
   por si el módulo no llega a escribirlas. */
.ticker {
  overflow: hidden; white-space: nowrap;
  border-top: var(--linea) solid var(--ink); border-bottom: var(--linea) solid var(--ink);
  background: var(--tk-fondo, var(--white));
  color: var(--tk-tinta, var(--ink));
  padding: var(--s3) 0;
}
.ticker[hidden] { display: none; }
.ticker__pista {
  display: inline-block;
  animation: tk var(--tk-dur, 26s) linear infinite;
  animation-direction: var(--tk-dir, normal);
}
.ticker__pista span {
  padding-right: var(--s6);
  font-size: var(--tk-tamano, 22px); letter-spacing: .01em; text-transform: uppercase;
}
@keyframes tk { from { transform: translate3d(0,0,0); } to { transform: translate3d(-50%,0,0); } }
@media (prefers-reduced-motion: reduce) { .ticker__pista { animation: none; } }

/* ---------- Sugerencias ----------------------------------------------------- */

.sugerencias { padding: 0; background: var(--bone); }

/* Misma altura y mismos filetes que el ticker, para que las dos bandas se
   lean como una pareja. */
.sugerencias__t {
  margin: 0; padding: var(--s3) var(--s5);
  border-bottom: var(--linea) solid var(--ink);
  background: var(--bone); text-align: center;
  font-size: var(--t-ui); letter-spacing: .01em;
  text-transform: uppercase; font-weight: 500;
}

/* Desplazamiento normal, no carrusel: si las sugerencias caben, no se mueve
   nada; si no caben, se arrastra hasta el final y se para. El bucle infinito
   repetía las mismas seis caras y hacía creer que había más catálogo. */
.sug-carrusel {
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
  border-bottom: var(--linea) solid var(--ink);
  background: var(--bone);
}
.sug-carrusel .track { display: flex; width: max-content; min-width: 100%; }
/* La última conserva su filete: sin él la tarjeta queda abierta cuando la
   tira no llega a desbordar, que es lo normal con cinco o seis sugerencias.
   Se lo quité pensando en el caso contrario y ese es el raro. */

/* Mismo encuadre que la parrilla: 2:3 y filete entre casillas. */
.sug {
  flex: none; width: 220px; display: flex; flex-direction: column;
  border-right: var(--linea) solid var(--ink); background: var(--bone);
}
/* La primera cierra por la izquierda. Las tarjetas sólo llevan filete a la
   derecha —así dos vecinas nunca suman dos líneas—, pero eso deja la de la
   punta abierta por ese lado. Sólo la primera, y sólo ahí. */
.sug:first-child { border-left: var(--linea) solid var(--ink); }
.sug__img { display: block; aspect-ratio: 2 / 3; overflow: hidden; }
.sug__img img {
  width: 100%; height: 100%; object-fit: cover; display: block; will-change: transform;
}
.sug__n {
  display: flex; align-items: center; height: 34px; padding: 0 var(--s3);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis; display: block; line-height: 34px;
  font-size: var(--t-micro); letter-spacing: var(--tr-micro); text-transform: uppercase;
}

@media (max-width: 860px) {
  .sugerencias { padding: var(--s5) var(--s4) var(--s6); }
  .sugerencias__lista { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---------- Marcas y campañas ---------------------------------------------- */

.page { padding: var(--s6) var(--s5) var(--s8); }

.page__head {
  display: flex; align-items: baseline; gap: var(--s4); flex-wrap: wrap;
  margin-bottom: var(--s6);
}
.page__title {
  margin: 0; font-size: var(--t-display); font-weight: 500;
  letter-spacing: var(--tr-display); line-height: 1;
}
.page__actions { margin-left: auto; display: flex; gap: var(--s2); }

.alta { display: flex; flex-wrap: wrap; gap: var(--s2); margin: 0 0 var(--s6); }
.alta[hidden] { display: none; }
.alta input {
  flex: 1 1 240px; min-width: 0; height: 30px; padding: 0 var(--s3);
  border: var(--linea) solid var(--ink); border-radius: 22px; background: var(--white);
}
.alta input:focus { outline: none; border-color: var(--blue); }
.alta--card { margin: 0; }
.alta--card input { flex: none; }

.marco { margin: 0 0 var(--s7); }
.marco__head {
  display: flex; align-items: center; gap: var(--s4);
  padding-bottom: var(--s2); margin-bottom: var(--s4);
  border-bottom: var(--linea) solid var(--ink);
}
.marco__nombre {
  min-width: 0; max-width: 100%; width: auto; border: 0; background: none; padding: 0;
  font-size: 20px; font-weight: 500; letter-spacing: -.005em;
  field-sizing: content;
}
.marco__nombre:hover, .marco__nombre:focus { color: var(--blue); outline: none; }
.marco__meta { color: var(--ink); }

.marco__x {
  margin-left: auto; width: 24px; height: 24px;
  display: grid; place-items: center;
  border: 0; background: none; cursor: pointer; color: var(--ink);
  opacity: 0; transition: opacity .16s, color .16s;
}
.marco__x svg { width: 11px; height: 11px; }
@media (hover: hover) { .marco:hover .marco__x { opacity: 1; } }
@media (hover: none)  { .marco__x { opacity: 1; } }
.marco__x:hover, .marco__x:focus-visible { opacity: 1; color: var(--red); }

/* Las bandas se apilan a todo el ancho: nada de columnas. */
.sels {
  display: block;
  grid-template-columns: none;
  margin: 0 calc(var(--s5) * -1);
  border-top: 0;
}

/* Sin separación entre tarjetas: el borde de una hace de borde de la
   siguiente, y la fila se lee como una sola pieza. */
.sel-card { position: relative; border-right: var(--linea) solid var(--ink); }
.sel-card:last-of-type { border-right: 0; }
.sel-card__open { display: block; cursor: pointer; }

/* Sin borde propio: el de la fila ya lo enmarca. Y en vertical, que es el
   encuadre del catálogo y deja la cara más grande. */
.sel-card__mosaic {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--linea);
  background: var(--ink); border: 0;
  aspect-ratio: 3 / 4; overflow: hidden;
}
.sel-card__mosaic--0, .sel-card__mosaic--1 { grid-template-columns: 1fr; }
.sel-card__mosaic--2 { grid-template-rows: 1fr; }
.sel-card__mosaic img { width: 100%; height: 100%; object-fit: cover; }
.sel-card__mosaic i { background: var(--white); display: block; }

/* El nombre y el recuento van dentro del margen de la tarjeta, no pegados
   al borde de la pantalla. */
.sel-card__name {
  display: block; margin: var(--s3) var(--s3) 0; font-size: var(--t-small);
}
.sel-card__meta { display: block; margin: 2px var(--s3) var(--s4); color: var(--ink); }

/* El contenedor no debe encoger a su contenido: si es flex, el formulario
   mide lo que miden sus campos y no hay nada que centrar. */
.nueva-wrap { display: block; }
.nueva--fila { align-self: center; }

.sel-card__x {
  position: absolute; top: var(--s2); right: var(--s2); z-index: 2;
  width: 26px; height: 26px; display: grid; place-items: center;
  border: var(--linea) solid var(--ink); background: var(--white);
  cursor: pointer; opacity: 0;
  transition: opacity .16s, color .16s, border-color .16s;
}
.sel-card__x svg { width: 11px; height: 11px; }
@media (hover: hover) { .sel-card:hover .sel-card__x { opacity: 1; } }
@media (hover: none)  { .sel-card__x { opacity: 1; } }
.sel-card__x:focus-visible { opacity: 1; }
.sel-card__x:hover { color: var(--red); border-color: var(--red); }

.nueva {
  width: 100%; aspect-ratio: 3 / 4;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s2);
  border: var(--linea) dashed var(--ink); background: none; cursor: pointer;
  font-size: var(--t-small); color: var(--ink);
  transition: border-color .16s, background .16s;
}
.nueva:hover { background: var(--pink); }
.nueva svg { width: 14px; height: 14px; }
.nueva:hover { border-style: solid; border-color: var(--ink); color: var(--ink); }

/* ---------- Una campaña -----------------------------------------------------
   Pantalla partida: las caras a la izquierda con su propio scroll, el panel
   fijo a la derecha. La página no se desplaza; se desplaza la columna.    */

.camp {
  display: grid; grid-template-columns: minmax(0, 1fr) 320px;
  height: calc(100vh - var(--head-h));
}
/* Con la pantalla partida, la página no crece: se oculta el pie y su hueco. */
body.pantalla-partida .espaciador,
body.pantalla-partida .foot { display: none; }
body.pantalla-partida .page { padding: 0; }

.camp__caras {
  overflow-y: auto; overscroll-behavior: contain;
  padding: var(--s5);
  border-right: var(--linea) solid var(--ink);
}
.camp__caras::-webkit-scrollbar { width: 3px; }
.camp__caras::-webkit-scrollbar-thumb { background: var(--grey); }

.camp__vacio {
  border: var(--linea) dashed var(--ink); padding: var(--s8) var(--s5); text-align: center;
}
.camp__vacio p { margin: 0 0 var(--s4); color: var(--dim); }

.picks {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  border-top: var(--linea) solid var(--ink); border-left: var(--linea) solid var(--ink);
}
.pickcard {
  position: relative; background: var(--white);
  border-right: var(--linea) solid var(--ink); border-bottom: var(--linea) solid var(--ink);
}
.pickcard img { width: 100%; aspect-ratio: 2 / 3; object-fit: cover; }
.pickcard__name {
  display: flex; align-items: center;
  height: 30px; padding: 0 var(--s3);
}

.pickcard__x {
  position: absolute; top: var(--s2); right: var(--s2);
  width: 24px; height: 24px; display: grid; place-items: center;
  border: var(--linea) solid var(--ink); border-radius: 50%; background: var(--white);
  cursor: pointer; opacity: 0; transition: opacity .16s, color .16s, border-color .16s;
}
.pickcard__x svg { width: 10px; height: 10px; }
@media (hover: hover) { .pickcard:hover .pickcard__x { opacity: 1; } }
@media (hover: none)  { .pickcard__x { opacity: 1; } }
.pickcard__x:hover { color: var(--red); border-color: var(--red); }

/* Panel derecho */

.camp__panel {
  overflow-y: auto; overscroll-behavior: contain;
  padding: var(--s5);
  display: flex; flex-direction: column;
}

.camp__nombre {
  width: 100%; max-width: 100%; overflow-wrap: anywhere; margin: var(--s3) 0 0;
  border: 0; border-bottom: var(--linea) solid transparent; background: none;
  padding: 0 0 var(--s1);
  font-size: 24px; font-weight: 500; letter-spacing: var(--tr-display); line-height: 1.15;
}
.camp__nombre:hover { border-bottom-color: var(--rule); }
.camp__nombre:focus { outline: none; border-bottom-color: var(--blue); }

.camp__meta {
  display: flex; gap: var(--s3); margin: var(--s2) 0 var(--s5);
  font-size: var(--t-micro); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--ink);
}

/* Una sola muestra: la elegida, y al pulsarla se abre la rueda del sistema. */
.camp__color {
  position: relative; display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) 0 var(--s4); cursor: pointer;
}
.camp__color .swatch {
  width: 18px; height: 18px; flex: none;
  outline: var(--linea) solid var(--ink); outline-offset: 2px;
}
.camp__color:hover .swatch { outline-color: var(--ink); }
.camp__color__t {
  font-size: var(--t-micro); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--dim);
}
.camp__color input {
  position: absolute; left: 0; top: var(--s2);
  width: 18px; height: 18px; padding: 0; border: 0; opacity: 0; cursor: pointer;
}

.camp__add { width: 100%; margin-bottom: var(--s5); }

/* ---------- Diálogos y desplegable ------------------------------------------ */

.modal {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center; padding: var(--s5);
  background: rgba(0, 0, 0, .5);
}
.modal[hidden] { display: none; }

.modal__box {
  width: 100%; max-width: 400px;
  background: var(--white); border: var(--linea) solid var(--ink);
  border-radius: var(--r-box);
  padding: var(--s5);
}
.modal__t { margin: 0 0 var(--s4); font-size: var(--t-title); font-weight: 500; }
.modal__none { margin: 0 0 var(--s4); font-size: var(--t-small); color: var(--ink); }
.modal__acts { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s5); }
/* Se reparten el ancho, pero nunca por debajo de su rótulo: con `flex: 1` a
   secas, un rótulo largo se parte en dos líneas dentro de la píldora. Y con
   `nowrap` a secas se sale de la caja, que es peor: el rótulo cabe pero la
   fila no. Fue lo que pasó con «Create and invite», que ahora dice «Invite».

   El relleno es `--s4` y no `--s5` porque el diálogo de editar cuenta lleva
   tres botones —Delete, Cancel, Save— y con 24px por lado la fila no entra
   en los 352px útiles de la caja.

   Y `flex-wrap` como red: si algún día un rótulo o un idioma no cabe, el
   botón se va a su propio renglón a todo el ancho. Desbordar nunca es una
   opción; apilarse sí. */
.modal__acts .btn {
  flex: 1 1 auto; min-width: max-content; white-space: nowrap;
  padding: 0 var(--s4);
}
.modal__x {
  margin-top: var(--s4); padding: 0; border: 0; background: none; cursor: pointer;
  font-size: var(--t-micro); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--dim);
}
.modal__x:hover { color: var(--ink); }

.dlg-marca, .drop__marca { margin: var(--s4) 0 var(--s1); color: var(--green); }
.dlg-marca:first-child, .drop__marca:first-child { margin-top: 0; }

.sel-row, .drop__row {
  width: 100%; display: flex; align-items: center;
  gap: var(--s3); padding: var(--s2) 0;
  border: 0; border-bottom: var(--linea) solid var(--ink); background: none;
  cursor: pointer; font-size: var(--t-small); text-align: left;
}
.sel-row:hover, .drop__row:hover { color: var(--ink); }
.drop__row:not(.is-in):hover { background: var(--pink); }
.sel-row__n, .drop__n {
  font-size: var(--t-micro); letter-spacing: var(--tr-micro); color: var(--ink);
}

.drop--pegado {
  border-top-left-radius: 0; border-top-right-radius: 0;
  border-top: 0;
}

.drop {
  font-size: var(--t-drop);
  position: fixed; z-index: 70;
  min-width: 240px; max-width: 290px; max-height: 60vh; overflow-y: auto;
  background: var(--white); border: var(--linea) solid var(--ink);
  border-radius: var(--r-box);
  padding: var(--s3) var(--s4);
}
.drop__row {
  font-size: var(--t-drop);
  padding: var(--s2) var(--s2); margin: 0 calc(var(--s2) * -1);
  width: calc(100% + var(--s2) * 2); border-radius: var(--r-box);
  border-bottom: 0;
}
/* Sin filete entre filas. Llevaba uno, y con el radio de la píldora del
   hover la línea salía curvada por los extremos, como el borde de otra caja
   dentro del panel.

   Enderezarla no era la solución: un filete de 2px entre filas de 30px, en
   un panel de 240px, no separa —parte el panel—. Aquí ya separan el aire y
   el punto de color de cada proyecto, y el rosa al pasar por encima dice
   dónde estás. */
.drop__row + .drop__row { margin-top: 2px; }
.drop__row .drop__n { margin-left: auto; }
.drop__row.is-in { cursor: default; color: var(--ink); }
.drop__row.is-in:hover { color: var(--ink); }
.drop__row:last-child { border-bottom: 0; }
.drop__vacio { margin: 0; font-size: var(--t-small); color: var(--ink); }
.drop__vacio a { text-decoration: underline; color: var(--ink); }


/* ---------- Color de campaña -----------------------------------------------
   Una franja de 3 px bajo la foto, una por campaña. Con varias, se reparten
   el ancho: se lee cuántas son sin contar nada.                            */

.dots { display: inline-flex; gap: 3px; align-items: center; }
.tile__dots:empty { display: none; }
.dot {
  width: 6px; height: 6px; flex: none; display: block;
  border-radius: 50%;   /* excepción deliberada: el punto es un punto */
}
.tile__dots { display: inline-flex; }

.swatch {
  width: 16px; height: 16px; padding: 0; flex: none;
  border: 0; cursor: pointer;
  outline: var(--linea) solid transparent; outline-offset: 2px;
  transition: outline-color .12s;
}
.swatch:hover { outline-color: var(--rule); }
.swatch.is-on { outline-color: var(--ink); }


.drop__cab {
  margin: var(--s4) 0 var(--s1);
  font-size: var(--t-micro); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--ink);
}
.drop__cab:first-child { margin-top: 0; }

.drop__dot { width: 7px; height: 7px; flex: none; display: block; border-radius: 50%; }

.drop__txt { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow-wrap: anywhere; }
.drop__txt em {
  font-style: normal; font-size: var(--t-micro); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--ink);
}

.drop__out {
  flex: none; width: 20px; height: 20px; display: grid; place-items: center;
  border: 0; border-radius: 50%; background: none; cursor: pointer; color: var(--ink);
  transition: color .16s, background .16s;
}
.drop__out:hover { background: var(--pink); }
.drop__out svg { width: 9px; height: 9px; }
.drop__out:hover { color: var(--red); }

/* ---------- Panel de altas -------------------------------------------------- */

.admin__resumen { margin: 0 0 var(--s5); }
.admin__resumen b { font-weight: 500; }

.tabla { width: 100%; border-collapse: collapse; font-size: var(--t-ui); }

.tabla th {
  text-align: left; font-weight: 500; padding: 0 var(--s3) var(--s2);
  border-bottom: var(--linea) solid var(--ink);
  font-size: var(--t-drop); letter-spacing: var(--tr-micro); text-transform: uppercase;
}
.tabla td { padding: var(--s2) var(--s3); border-bottom: var(--linea) solid var(--rule); vertical-align: middle; }

/* Tabla densa: la de personas, y cualquier otra que crezca hasta ser una
   lista que se revisa en vez de leerse.

   El cuerpo de la casa son 20px, pensados para pantallas donde el texto es
   contenido. En una tabla de treinta y cinco filas eso obliga a varios
   renglones por celda y la vista tiene que saltar: el tamaño que ayuda a
   leer un párrafo estorba para comparar una columna.

   Un solo tamaño para todo, y ahí está la gracia. El primer intento bajó el
   cuerpo a 13, las píldoras a 12, las cabeceras y los botones a 11, y el
   resultado era peor que antes: cuatro tamaños en la misma fila obligan a
   reajustar la vista en cada salto de columna. Una tabla se lee rápido
   cuando todo pesa igual y lo único que cambia es el color.

   Por eso las reglas de abajo NO fijan tamaño: lo heredan. Las píldoras y
   los botones traen el suyo de sus componentes y hay que anularlo
   explícitamente; si no, vuelven a los 20 de la casa.

   No se toca `.tabla` a secas porque hay tablas cortas —los vídeos de
   portada, la lista de marcas— donde el cuerpo grande está bien. */
.tabla--densa { font-size: 14px; }
.tabla--densa th,
.tabla--densa td,
.tabla--densa .excl,
.tabla--densa .aviso,
.tabla--densa .falta,
.tabla--densa .btn { font-size: inherit; }

.tabla--densa th { padding-bottom: var(--s2); }
.tabla--densa td { padding: var(--s3); line-height: 1.35; }
/* Los botones bajan de alto, no de letra: lo que sobra en una fila es el
   aire de un botón pensado para pulsarse con el pulgar. */
.tabla--densa .btn { height: 32px; padding: 0 var(--s3); }

/* La barra de herramientas de la pantalla, en una sola línea: buscar a la
   izquierda con su recuento al lado, y el alta a la derecha.

   Los tres comparten altura —36px— porque van alineados y cualquier
   diferencia se lee como un desajuste, no como jerarquía. El buscador es una
   caja corta y no un campo a todo el ancho: se escriben dos o tres letras, y
   un renglón de mil píxeles para eso desequilibra la pantalla. */
.admin__barra {
  display: flex; align-items: center; gap: var(--s3);
  margin: 0 0 var(--s5);
}
.admin__barra .buscador {
  flex: 0 1 300px;
  height: 36px; padding: 0 var(--s4);
  border: var(--linea) solid var(--ink); border-radius: 18px;
  background: none;
  font-size: 14px;
}
.admin__barra .buscador:focus {
  outline: none; border-color: var(--blue);
}
.admin__cuenta {
  flex: 0 0 auto;
  font-size: 14px; color: var(--dim);
  font-variant-numeric: tabular-nums;
}
/* El margen automático es lo que separa los dos grupos: lo de buscar queda a
   la izquierda y el alta se va al extremo, sin medidas fijas que se rompan
   al cambiar el ancho. */
.admin__barra-alta {
  margin-left: auto;
  height: 36px; padding: 0 var(--s4); font-size: 14px;
}
.tabla__mini { width: 44px; padding-left: 0; }

/* Reordenar el catálogo arrastrando filas. La columna del número hace de asa:
   da algo concreto que agarrar y dice en qué puesto está cada ficha. */
.tabla__ord { width: 44px; text-align: right; color: var(--off); }
.es-ordenable tr { cursor: grab; }
.es-ordenable tr.is-llevando { opacity: .4; cursor: grabbing; }
.es-ordenable tr.is-diana td { box-shadow: inset 0 2px 0 var(--blue); }
.tabla__mini img { width: 32px; height: 48px; object-fit: cover; display: block; }
.tabla__n {
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; color: var(--ink); text-decoration: underline; text-underline-offset: 3px;
}
.tabla__n:hover { color: var(--blue); }
.tabla td i { display: block; font-style: normal; font-size: var(--t-drop); color: var(--off); }
.tabla__acc { text-align: right; white-space: nowrap; }
.tabla__x {
  width: 24px; height: 24px; display: inline-grid; place-items: center;
  border: 0; border-radius: 50%; background: none; cursor: pointer; color: var(--ink);
}
.tabla__x svg { width: 10px; height: 10px; }
.tabla__x:hover { background: var(--pink); color: var(--red); }
.falta { color: var(--off); }
.aviso {
  display: inline-block; margin-right: var(--s2); padding: 2px var(--s2);
  background: var(--pink); font-size: var(--t-drop);
}

/* Visibilidad y marcas */
.vis { display: flex; gap: var(--s2); margin-bottom: var(--s3); }
.vis__marcas { padding: var(--s3) 0 0; }
.vis__marcas[hidden] { display: none; }
.vis__grupo {
  margin: var(--s3) 0 var(--s2);
  font-size: var(--t-drop); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--ink);
}
.vis__grupo:first-child { margin-top: 0; }

.excl {
  display: inline-block; padding: 2px var(--s2);
  background: var(--green); color: var(--white); font-size: var(--t-drop);
}
.abierto { color: var(--off); }

.lista-marcas { display: flex; flex-direction: column; gap: var(--s2); }
.marca-fila {
  display: flex; align-items: center; gap: var(--s3);
  padding-bottom: var(--s2); border-bottom: var(--linea) solid var(--rule);
}
.marca-fila__n {
  flex: 1; min-width: 0; border: 0; background: none; padding: 0;
  font-size: var(--t-ui); color: var(--ink);
}
.marca-fila__n:hover, .marca-fila__n:focus { color: var(--blue); outline: none; }
.marca-fila__n2 { font-size: var(--t-drop); color: var(--off); white-space: nowrap; }
.marca-fila__x {
  width: 24px; height: 24px; display: grid; place-items: center;
  border: 0; border-radius: 50%; background: none; cursor: pointer; color: var(--ink);
}
.marca-fila__x svg { width: 10px; height: 10px; }
.marca-fila__x:hover { background: var(--pink); color: var(--red); }

.nueva--fila {
  aspect-ratio: auto; height: 34px; flex-direction: row; gap: var(--s2);
  border-radius: 17px;
}
.nueva--fila svg { width: 11px; height: 11px; }

.previa__v {
  margin: 0; width: 74px; aspect-ratio: 9 / 16;
  display: grid; place-items: center; align-content: center;
  border: var(--linea) solid var(--ink); background: var(--bone);
  font-size: var(--t-drop);
}
.previa__v figcaption { color: var(--off); }
.previa__v.is-rota { border-color: var(--red); color: var(--red); }
.previa__v.is-rota figcaption { color: var(--red); }

/* Formulario */
.ficha-form { max-width: 720px; }
.campo { margin-bottom: var(--s4); }
.campo__pista { display: block; margin-top: var(--s1); font-size: var(--t-drop); color: var(--off); }
.campo__pista code { font-family: inherit; border-bottom: var(--linea) solid var(--rule); }

/* El rótulo separado de su caja, siempre y sea `label` o `span`. Donde
   seguía un `<input>` la separación la daba de rebote el bloque; donde sigue
   una fila de píldoras —Use, Visibility— no la daba nadie y el rótulo salía
   pegado. Es la misma regla que ya tiene el rótulo dentro del modal. */
.ficha-form .campo__label { display: block; margin-bottom: var(--s2); }

.ficha-form input, .ficha-form select, .ficha-form textarea {
  width: 100%; padding: var(--s2) var(--s3);
  border: var(--linea) solid var(--ink); border-radius: var(--r-box); background: var(--white);
  font-size: var(--t-ui);
}
.ficha-form input:focus, .ficha-form select:focus, .ficha-form textarea:focus {
  outline: none; border-color: var(--blue);
}
.ficha-form input[readonly] { background: var(--bone); color: var(--off); }
.ficha-form textarea { resize: vertical; line-height: 1.5; }

.rejilla {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--s3) var(--s4);
  margin-bottom: var(--s4);
}
.rejilla .campo { margin-bottom: 0; }

.chips-form { display: flex; flex-wrap: wrap; gap: var(--s2); }
.chip-check { position: relative; }
.chip-check input { position: absolute; opacity: 0; width: 0; height: 0; }
.chip-check span {
  display: inline-flex; align-items: center; height: 30px; padding: 0 var(--s4);
  border: var(--linea) solid var(--ink); border-radius: 22px; cursor: pointer;
  font-size: var(--t-ui);
}
.chip-check input:checked + span { background: var(--ink); color: var(--white); }
.chip-check input:focus-visible + span { outline: 2px solid var(--blue); outline-offset: 2px; }

/* Añadir un valor al vocabulario de un campo: caja y botón en la misma línea.

   Estuvo dentro de `.campos-linea`, que es la fila de los tickers: sus reglas
   apuntan a `.cinta__campo` y este campo no lo lleva, así que se quedaba con
   el `width: 100%` de `.ficha-form input`, ocupaba la fila entera y tiraba el
   botón al renglón de abajo.

   Los 44px son los de `.btn`: dos alturas distintas en la misma línea se leen
   como un error, y ese criterio ya está escrito para los desplegables. */
.campo__anade {
  display: flex; align-items: center; gap: var(--s2);
  margin-top: var(--s3);
}
.campo__anade input { flex: 1 1 auto; min-width: 0; height: 44px; }
.campo__anade .btn { flex: none; }

.previa { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s3); }
.previa__i { margin: 0; width: 74px; }
.previa__i img {
  width: 100%; aspect-ratio: 2 / 3; object-fit: cover; display: block;
  border: var(--linea) solid var(--ink);
}
.previa__i figcaption { padding-top: 2px; font-size: var(--t-drop); color: var(--off); }
.previa__i.is-rota img { opacity: 0; }
.previa__i.is-rota { position: relative; }
.previa__i.is-rota::after {
  content: "not found"; position: absolute; left: 0; right: 0; top: 40%;
  text-align: center; font-size: var(--t-drop); color: var(--red);
}

.form-error {
  margin: var(--s3) 0 0; padding: var(--s2) var(--s3);
  border: var(--linea) solid var(--red); border-radius: var(--r-box);
  color: var(--red); font-size: var(--t-ui);
}
.form-error[hidden] { display: none; }

@media (max-width: 860px) {
  /* Segmento y altura. Los números son los de Age y Hair contando desde la
     columna de orden, que entró por delante y desplazó a todas: eran el 4 y
     el 6 cuando la primera era la miniatura. Un `nth-child` es una posición,
     no un nombre — al añadir una columna hay que volver aquí. */
  .tabla th:nth-child(5), .tabla td:nth-child(5),
  .tabla th:nth-child(7), .tabla td:nth-child(7) { display: none; }
}

/* ---------- Muro de acceso -------------------------------------------------- */

.muro {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  padding: var(--s5);
  background: var(--bone);
}

.muro__caja { width: 100%; max-width: 360px; }

.muro__cab {
  margin: 0 0 var(--s5);
  font-size: var(--t-ui); letter-spacing: var(--tr-micro); text-transform: uppercase;
}
.muro__t {
  margin: 0 0 var(--s3);
  font-size: 30px; font-weight: 500; letter-spacing: var(--tr-display); line-height: 1.1;
}
.muro__p { margin: 0 0 var(--s5); font-size: var(--t-ui); }
.muro__p a { text-decoration: underline; text-underline-offset: 3px; }

.muro__form { display: flex; flex-direction: column; gap: var(--s2); }
.muro__form input {
  height: 38px; padding: 0 var(--s3);
  border: var(--linea) solid var(--ink); border-radius: 19px; background: var(--white);
  font-size: var(--t-ui);
}
.muro__form input:focus { outline: none; border-color: var(--blue); }
.muro__form button { margin-top: var(--s2); }
.muro__form button[disabled] { opacity: .6; cursor: default; }

/* Aviso flotante. Sin esto, un rechazo de las reglas se quedaba mudo y
   parecía que la acción había funcionado.

   Dos formas, la misma caja: lo que se lee primero no es el texto sino si
   algo salió bien o mal, así que lo único que cambia es el color. */
.aviso-error, .aviso-ok {
  position: fixed; left: 50%; bottom: var(--s5); transform: translateX(-50%);
  z-index: 300; max-width: 420px;
  padding: var(--s3) var(--s4);
  border: var(--linea) solid var(--red); border-radius: var(--r-box);
  background: var(--pink); color: var(--red);
  font-size: var(--t-ui);
}
.aviso-ok {
  border-color: var(--ink); background: var(--white); color: var(--ink);
}

/* ---------- Salto entre secciones ------------------------------------------
   Sin animación: se probó la transición nativa del navegador y Chrome la
   descartaba en la página que llega, seguramente porque el contenido no está
   en el HTML —lo pinta el script— y no hay nada que capturar en el primer
   fotograma. En vez de disimularlo con una animación, lo que se cuida es que
   el salto no dé tumbos: que nada aparezca tarde ni se descoloque.       */

/* La zona de contenido reserva su altura desde el primer fotograma. Sin
   esto, el pie sube hasta arriba mientras el script pinta y baja de golpe
   después: es el salto más visible al cambiar de página.

   Se reserva en el `<main>`, no en cualquier `.page`. La regla decía
   `.page, .grid, .model` a secas y daba por supuesto que hay un solo bloque
   de esos por pantalla. No lo hay: la página compartida emite tres bloques y
   dos de ellos son `.page` —la cabecera y el pie—, así que cada uno reservaba
   una ventana entera y aparecían mil píxeles de hueso entre el titular y las
   caras. El panel emite otros tres.

   Un documento tiene un `<main>` y sólo uno, así que atándolo ahí la reserva
   no se puede aplicar dos veces por mucho que la clase se reutilice dentro.
   `main#page` recoge las pantallas que se pintan con guion y cuyo `<main>`
   no lleva ninguna de esas tres clases. */
main.page, main.grid, main.model, main#page {
  min-height: calc(100vh - var(--head-h) - 120px);
}

/* ---------- Proyectos ------------------------------------------------------
   Sin título grande: la sección ya se sabe por el menú, y ocupaba un tercio
   de la pantalla sin decir nada. En su lugar, una banda fina con el dato y
   la acción, y debajo cada marca como una ficha técnica.                */

/* Franja de herramientas de Projects.

   Va a sangre, con esquinas rectas y celdas separadas por el filete: el
   mismo sistema que la cabecera de una marca y las bandas de campaña que
   vienen debajo.

   Estuvo un rato como isla blanca redondeada flotando encima, y no tenía
   nada que ver con lo demás: aquí no hay tarjetas, hay bandas a sangre.

   El fondo blanco sí se queda —da el contraste contra el hueso de la página
   y separa la herramienta del contenido sin necesidad de una forma nueva. */
/* Sólo el botón de crear marca, sin banda ni filetes. Los tuvo, y con el
   fondo blanco a sangre parecía que el botón ocupaba la página entera: un
   marco que enmarca una sola cosa no la separa, la agranda. */
.barra-marcas {
  display: flex; align-items: center;
  margin-bottom: var(--s5);
}

/* Ficha técnica de la marca: nombre a la izquierda, datos a la derecha en
   pares etiqueta/valor, como en el referente.

   El hueco entre marcas va en blanco puro. Con el hueso del fondo, la
   separación era invisible: dos marcas seguidas se leían como una sola lista
   larga. El blanco es el único color que no aparece en ningún otro sitio de
   esta pantalla, así que funciona como corte sin añadir una línea más —y en
   esta casa las líneas no se acumulan. */
.marco {
  /* A sangre. La página tiene relleno lateral y `.sels` se sale de él con
     margen negativo, así que la banda de color y las campañas llegaban al
     borde pero el blanco de aquí se quedaba dentro: se veía un recuadro
     descuadrado, más estrecho que lo que contiene.

     Se saca el bloque y se le devuelve el relleno, así lo de dentro queda
     donde estaba y el fondo llega hasta el filo. */
  margin: 0 calc(var(--s5) * -1) var(--s7);
  padding: 0 var(--s5) var(--s7);
  background: var(--white);
}
.marco:last-of-type { margin-bottom: 0; }

.marco__datos {
  display: flex; gap: var(--s5); flex: 1; justify-content: flex-end;
  font-size: var(--t-drop);
}
.marco__datos span { white-space: nowrap; }

/* El grupo, pegado a la marca y leído como una sola cosa: «Springfield
   /TENDAM». Estuvo como «GROUP  AWWG» al otro extremo de la banda, con la
   etiqueta ocupando más que el dato y lejos de aquello a lo que pertenece.

   La barra es la misma que la del logotipo, así que la pertenencia se lee sin
   necesidad de la palabra. En versales para que no compita con el nombre. */
.marco__grupo {
  order: 0; margin-left: calc(var(--s3) * -1);
  white-space: nowrap;
  font-size: var(--t-drop); text-transform: uppercase;
  letter-spacing: var(--tr-micro);
  /* Hereda la tinta de la cabecera —blanca o negra según el color de la
     marca— y baja de peso con la opacidad, como `.marco__datos i`. Antes era
     un gris fijo: sobre un verde oscuro no se leía, y con un gris fijo no
     hay valor que funcione a la vez sobre un verde y sobre un rosa. */
  color: inherit; opacity: .65;
}
.marco__datos { order: 2; }
.marco__color { order: 3; }
.marco__x     { order: 4; }
.marco__datos i {
  font-style: normal; color: var(--off);
  letter-spacing: var(--tr-micro); text-transform: uppercase;
  margin-right: var(--s2);
}

.marco__nombre {
  flex: none; min-width: 0; width: auto; max-width: 42%;
  font-size: var(--t-ui);
}

/* Cada campaña es una banda a todo el ancho. La fila de cabecera se lee como
   celdas enmarcadas —nombre a la izquierda, datos a la derecha— y debajo va
   una tira continua de caras que se reparten el ancho, sin hueco muerto. */
.sels { margin: 0 calc(var(--s5) * -1); }

.banda { border-top: var(--linea) solid var(--ink); }
.banda:last-of-type { border-bottom: var(--linea) solid var(--ink); }

.banda__head {
  display: flex; align-items: stretch;
  border-bottom: var(--linea) solid var(--ink);
}
.banda__t {
  flex: 1; min-width: 0; margin: 0;
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s3) var(--s5);
  font-size: var(--t-ui); font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.banda__punto { width: 7px; height: 7px; border-radius: 50%; flex: none; }

/* Cada dato en su celda, con su línea a la izquierda. */
.banda__c {
  flex: none; width: 190px;
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s3) var(--s4);
  border-left: var(--linea) solid var(--ink);
  font-size: var(--t-drop);
}
.banda__c i {
  font-style: normal; color: var(--off);
  letter-spacing: var(--tr-micro); text-transform: uppercase;
}

.banda__x {
  flex: none; width: 46px;
  display: grid; place-items: center;
  border: 0; border-left: var(--linea) solid var(--ink);
  background: none; cursor: pointer; color: var(--ink);
  opacity: 0; transition: opacity .16s, color .16s;
}
.banda__x svg { width: 11px; height: 11px; }
@media (hover: hover) { .banda:hover .banda__x { opacity: 1; } }
@media (hover: none)  { .banda__x { opacity: 1; } }
.banda__x:hover, .banda__x:focus-visible { opacity: 1; color: var(--red); }

/* La tira de caras se define más abajo, en el bloque de Proyectos. */

/* Añadir campaña: una franja con aire, centrada y con marco continuo, igual
   que el resto de la casa. Nada de línea de puntos ni de contenido pegado a
   la izquierda: al ser la única acción de la franja, va en el centro. */
/* La banda que va justo debajo no abre con filete: el botón ya cierra con el
   suyo. Con los dos, se veía una línea doble. */
.nueva-wrap + .banda { border-top: 0; }

.nueva--banda {
  width: 100%; aspect-ratio: auto; height: auto;
  padding: var(--s5) 0;
  flex-direction: row; gap: var(--s2);
  border: var(--linea) solid var(--ink); border-top: 0;
  border-style: solid;
}

.alta--card {
  display: flex; align-items: center; justify-content: center;
  /* La clase base permite que los campos salten de línea; aquí no: los tres
     caben de sobra y al saltar el conjunto se descentraba y crecía a lo
     alto. */
  flex-wrap: nowrap;
  gap: var(--s2);
  padding: var(--s5);
  border: var(--linea) solid var(--ink); border-top: 0;
}
/* Mismo alto y mismo radio que el botón: 44 y 22, la píldora del sistema.
   Iba a 36 y al lado de dos botones de 44 se leía como un elemento de otra
   familia. El radio va con la altura —siempre la mitad— o deja de ser una
   píldora y pasa a ser un rectángulo con las esquinas comidas. */
.alta--card input {
  flex: none; width: 260px;
  height: 44px; padding: 0 var(--s4);
  border: var(--linea) solid var(--ink); border-radius: 22px;
  background: var(--white); font-size: var(--t-ui);
}
.alta--card .btn { flex: none; }

/* La marca es una banda divisoria con su color, a todo el ancho. El color se
   elige al crearla y el texto va en blanco o negro según el contraste, que
   lo calcula el script: con verdes y azules medios acertar a ojo falla.

   El margen se declara arriba, con el sangrado y el fondo blanco. Aquí había
   un `margin: 0 0 var(--s6)` que lo reiniciaba —una regla más abajo gana— y
   dejaba el bloque dentro del relleno de la página mientras su contenido se
   salía: el fondo blanco aparecía más estrecho que lo que contiene. */
/* Sin margen: la separación entre marcas ES el relleno blanco de arriba. Con
   margen además, después del filete venía una franja blanca y luego otra de
   hueso — dos huecos seguidos de distinto color donde debía haber uno. */
.marco { margin-bottom: 0; }

.marco__head {
  display: flex; align-items: center; gap: var(--s3);
  margin: 0 calc(var(--s5) * -1);
  padding: var(--s3) var(--s5);
  border: 0;
}

.marco__plegar {
  flex: none; width: 22px; height: 22px;
  display: grid; place-items: center;
  border: 0; background: none; cursor: pointer; color: inherit;
  transition: transform .2s;
}
.marco__plegar svg { width: 11px; height: 11px; }
.is-plegada .marco__plegar { transform: rotate(-90deg); }

/* Plegada: sólo queda la banda de color. */
.is-plegada .sels { display: none; }

.marco__nombre { background: none; border: 0; }
.marco__nombre:hover, .marco__nombre:focus { color: inherit; opacity: .7; }

.marco__datos i { opacity: .65; color: inherit; }

/* Selector de color: un cuadrado discreto, sin el marco del navegador. */
.marco__color {
  flex: none; width: 20px; height: 20px; overflow: hidden;
  border: var(--linea) solid currentColor; cursor: pointer;
}
.marco__color input {
  width: 200%; height: 200%; margin: -50% 0 0 -50%;
  border: 0; padding: 0; background: none; cursor: pointer;
}

.marco__x { opacity: .55; }

/* La tira es una retícula, no una fila de fichas sueltas: las casillas se
   tocan y cada línea llega hasta el borde. Los huecos que sobran al final se
   rellenan con casillas vacías, para que no quede nada flotando.

   Las columnas son iguales y las imágenes van en su 2:3 de origen, así que
   se reparten el ancho sin recortar ninguna cara. */
/* Sin filete superior: la cabecera de la banda ya cierra por abajo y los dos
   juntos se leerían como una línea del doble de grosor. */
.banda__tira {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 0;
  background: var(--white);
  border-top: 0;
}

.cara {
  position: relative; display: block;
  background: var(--white);
  border-right: var(--linea) solid var(--ink);
}
/* Sin filete entre la foto y el nombre: la casilla se lee como una pieza,
   igual que `.tile` en el catálogo, `.pickcard` en el selector y `.sug` en
   las sugerencias. Era la única de las cinco que lo llevaba. */
.cara__img {
  display: block; aspect-ratio: 2 / 3; overflow: hidden;
  background: var(--bone);
}
.cara__img img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Un 20% más de aire que antes: la franja del nombre pesaba poco frente a
   la imagen que lleva encima. */
.cara__n {
  display: block; padding: 14px var(--s4);
  font-size: var(--t-drop); letter-spacing: var(--tr-micro);
  text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Casilla de relleno: completa la línea sin añadir nada que se pueda pulsar. */
.cara--hueco { background: var(--bone); }
.cara--hueco .cara__img { background: var(--bone); }

/* Redondo, como el resto de controles circulares de la casa. */
.cara__x {
  position: absolute; top: var(--s2); right: var(--s2);
  width: 24px; height: 24px; display: grid; place-items: center;
  border: var(--linea) solid var(--ink); border-radius: 50%;
  background: var(--white);
  cursor: pointer; opacity: 0; transition: opacity .16s, color .16s;
}
.cara__x svg { width: 9px; height: 9px; }
@media (hover: hover) { .cara:hover .cara__x { opacity: 1; } }
@media (hover: none)  { .cara__x { opacity: 1; } }
.cara__x:hover, .cara__x:focus-visible { opacity: 1; color: var(--red); border-color: var(--red); }

/* Añadir a una campaña desde la portada. Es el mismo control que `.tile__add`
   en el catálogo y va en el mismo sitio: dentro de la banda blanca del
   nombre, a la derecha, sin fondo y sin filete hasta que se pasa por encima.
   Un botón que hace lo mismo en dos pantallas tiene que verse igual y estar
   donde ya se ha aprendido a buscarlo.

   `:has()` en vez de un ancestro: la fila sólo se convierte en fila donde de
   verdad hay botón, y las demás `.cara` —Projects, compartidas— siguen siendo
   una línea de texto sin enterarse. */
.cara__n:has(.cara__add) {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s2); padding-right: var(--s1);
}
.cara__n:has(.cara__add) > :first-child {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cara__add {
  flex: none; width: 26px; height: 26px;
  display: grid; place-items: center;
  border: var(--linea) solid transparent; border-radius: 50%;
  background: none; color: inherit; cursor: pointer;
  opacity: 0; transition: opacity .16s, border-color .16s;
}
.cara__add svg { width: 11px; height: 11px; }
@media (hover: hover) { .cara:hover .cara__add { opacity: 1; } }
@media (hover: none)  { .cara__add { opacity: 1; } }
.cara__add:focus-visible { opacity: 1; }
.cara__add:hover { border-color: var(--ink); }

/* La caja de añadir es la acción de la fila, así que se ve: fondo lleno y
   signo en negativo. */
.cara--mas { text-decoration: none; color: var(--ink); }
.cara--mas .cara__img {
  display: grid; place-items: center;
  background: var(--ink); color: var(--white);
  transition: background .16s, color .16s;
}
.cara--mas .cara__img svg { width: 22px; height: 22px; }
.cara--mas:hover .cara__img { background: var(--pink); color: var(--ink); }
.cara--mas .cara__n { font-weight: 500; }

/* Nombre y notas de la campaña, editables en la propia banda. */
.banda__t { flex: none; width: 260px; }
.banda__nombre {
  flex: 1; min-width: 0; border: 0; background: none; padding: 0;
  font-size: var(--t-ui); color: var(--ink);
}
.banda__nombre:hover, .banda__nombre:focus { color: var(--blue); outline: none; }

.banda__nota {
  flex: 1; min-width: 0;
  border: 0; border-left: var(--linea) solid var(--ink); background: none;
  padding: var(--s3) var(--s4);
  font-size: var(--t-drop); color: var(--ink);
}
.banda__nota::placeholder { color: var(--off); }
.banda__nota:focus { outline: none; background: var(--white); }

.banda__color {
  flex: none; width: 14px; height: 14px; overflow: hidden;
  border: var(--linea) solid var(--ink); cursor: pointer;
}
.banda__color input {
  width: 200%; height: 200%; margin: -50% 0 0 -50%;
  border: 0; padding: 0; background: none; cursor: pointer;
}

/* ---------- Proyectos: barra y campañas ajenas --------------------------- */

/* Búsqueda, orden y "sólo las mías" a la izquierda; "New brand" a la
   derecha, separado. Todo mide lo mismo que el botón (44px) para que la fila
   se lea como una sola línea de controles y no como piezas apelotonadas. */
.barra-marcas {
  gap: var(--s5); flex-wrap: wrap; align-items: center;
  justify-content: space-between;
}
.proj-filtro {
  display: flex; flex: 1 1 520px; min-width: 0;
  align-items: center; gap: var(--s4); flex-wrap: wrap;
}
.proj-filtro input[type="search"],
.proj-orden select {
  height: 44px; box-sizing: border-box;
  border: var(--linea) solid var(--ink); border-radius: 22px;
  background: var(--white); color: var(--ink);
  padding: 0 var(--s5);
  font: inherit; font-size: var(--t-ui);
}
.proj-filtro input[type="search"] { flex: 1 1 280px; min-width: 0; }
.proj-filtro input[type="search"]:focus,
.proj-orden select:focus { outline: none; border-color: var(--blue); }

/* El desplegable se declara: sin la flecha del navegador (cambia en cada
   sistema) y con la nuestra, la misma que pliega las marcas. */
.proj-orden { position: relative; flex: none; }
.proj-orden select {
  appearance: none; -webkit-appearance: none;
  padding-right: calc(var(--s5) + 20px); cursor: pointer;
}
.proj-orden > svg {
  position: absolute; right: var(--s4); top: 50%;
  width: 11px; height: 11px; transform: translateY(-50%);
  pointer-events: none;
}

/* "Only mine" es una píldora como "New brand", con el texto dentro: apagada
   es blanca con filete, encendida se rellena de tinta. Mismo tamaño y misma
   forma que el resto de la fila. */
.proj-toggle { display: inline-flex; flex: none; cursor: pointer; }
.proj-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.proj-toggle__pill {
  display: inline-flex; align-items: center;
  height: 44px; padding: 0 var(--s5);
  border: var(--linea) solid var(--ink); border-radius: 22px;
  background: var(--white); color: var(--ink);
  font-size: var(--t-ui); user-select: none;
  transition: background .16s, color .16s, border-color .16s;
}
.proj-toggle:hover .proj-toggle__pill { border-color: var(--blue); color: var(--blue); }
.proj-toggle input:checked + .proj-toggle__pill {
  background: var(--ink); color: var(--white); border-color: var(--ink);
}
.proj-toggle input:checked:hover + .proj-toggle__pill,
.proj-toggle:hover input:checked + .proj-toggle__pill {
  background: var(--blue); border-color: var(--blue); color: var(--white);
}
.proj-toggle input:focus-visible + .proj-toggle__pill {
  outline: 2px solid var(--blue); outline-offset: 2px;
}
/* "New brand" va en la misma fila que "Only mine": misma caja de texto,
   primera mayúscula y sin tracking, para que las dos píldoras sean iguales. */
.barra-marcas .btn { text-transform: none; letter-spacing: 0; }

/* Campaña ajena: se ve, no se toca. Los mismos huecos, sin controles. */
.marco__nombre--fijo, .banda__nombre--fijo, .banda__nota--fijo {
  cursor: default; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.marco__nombre--fijo:hover, .banda__nombre--fijo:hover { color: inherit; opacity: 1; }
.banda__nombre--fijo { display: block; }
.banda__nota--fijo { display: flex; align-items: center; color: var(--off); }
.banda__nota--fijo:empty { padding: 0; }
.banda__color--fijo { cursor: default; }

/* La campaña a la que apunta el enlace de equipo. */
.banda.is-marcada { outline: var(--linea) solid var(--blue); outline-offset: -1px; }
.banda__enlace { opacity: 1; }
.banda__enlace svg { width: 12px; height: 12px; }

/* La X de borrar campaña, siempre a la vista, como el enlace y el sobre.
   Aparecía sólo al pasar el ratón y se leía como si faltara. */
.banda__head > .banda__x { opacity: 1; }

/* La cara entera lleva a la ficha del talento. El enlace hereda el color y
   no subraya: la foto y el nombre ya dicen que es algo que se puede abrir. */
.cara__ficha { display: block; color: inherit; text-decoration: none; }
.cara__ficha:hover .cara__n, .cara__ficha:focus-visible .cara__n { color: var(--blue); }
.cara__ficha:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }

/* ---------- Pie ------------------------------------------------------------- */

.foot {
  background: var(--pink); border-top: var(--linea) solid var(--ink);
  margin-top: var(--s7); color: var(--ink);
}
/* Tras un bloque que ya cierra por abajo, el pie renuncia a su filete: si no,
   los dos se sumarían. La regla es la misma en los tres casos —sugerencias,
   bandas de la home y mosaico—: quien va detrás de una línea no pone otra. */
.sugerencias + .espaciador + .foot,
.sugerencias + .foot,
.banda + .foot,
.banda + .espaciador + .foot,
.mosaico + .foot { margin-top: 0; border-top: 0; }
.foot__mark {
  display: block; width: calc(100% - var(--s5) * 2); height: auto;
  margin: var(--s5) var(--s5) var(--s6);
}
.foot__legal {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s1) var(--s4);
  border-top: var(--linea) solid var(--ink);
  padding: var(--s3) var(--s5) var(--s5);
  font-size: var(--t-small);
}
.foot__legal a:hover { text-decoration: underline; }


/* ---------- Menú de cortina -------------------------------------------------
   Sólo existe en móvil. En escritorio la navegación va en la cabecera.     */

.head__burger { display: none; }

.cortina__fondo {
  position: fixed; inset: 0; z-index: 80;
  background: rgba(0, 0, 0, .45);
  opacity: 0; transition: opacity .26s ease;
}
.cortina__fondo.is-open { opacity: 1; }

.cortina {
  position: fixed; top: 0; bottom: 0; left: 0; z-index: 81;
  width: min(78vw, 320px);
  display: flex; flex-direction: column;
  background: var(--bone);
  border-right: var(--linea) solid var(--ink);
  transform: translateX(-100%);
  transition: transform .28s cubic-bezier(.4, 0, .2, 1);
  overflow-y: auto;
}
.cortina.is-open { transform: translateX(0); }

.cortina__top {
  display: flex; justify-content: flex-end;
  height: var(--head-h); padding: 0 var(--s4);
  border-bottom: var(--linea) solid var(--ink);
}
.cortina__x {
  width: 44px; border: 0; background: none; cursor: pointer; color: var(--ink);
  display: grid; place-items: center;
}
.cortina__x svg { width: 18px; height: 18px; }

.cortina__nav { display: flex; flex-direction: column; }
.cortina__nav a {
  padding: var(--s4) var(--s5);
  border-bottom: var(--linea) solid var(--ink);
  font-size: 22px; letter-spacing: -.01em; text-transform: uppercase;
}
.cortina__nav a[aria-current="page"] { background: var(--pink); }

.cortina__pie { padding: var(--s5); margin-top: auto; }
.cortina__cab {
  margin: 0 0 var(--s3);
  font-size: var(--t-micro); letter-spacing: var(--tr-micro); text-transform: uppercase;
}
.cortina__correo { margin: 0 0 var(--s3); font-size: var(--t-small); }
.cortina__accion {
  padding: 0; border: 0; background: none; cursor: pointer;
  font-size: var(--t-ui); text-transform: uppercase; letter-spacing: .01em; color: var(--ink);
  text-decoration: underline; text-underline-offset: 3px;
}
.cortina__login { display: flex; flex-direction: column; gap: var(--s2); }
.cortina__login .login__err { margin-top: var(--s1); }
.cortina__login input {
  height: 34px; padding: 0 var(--s3);
  border: var(--linea) solid var(--ink); border-radius: 17px; background: var(--white);
  font-size: var(--t-small);
}
.cortina__login input:focus { outline: none; border-color: var(--blue); }

body.sin-scroll { overflow: hidden; }

/* ---------- Pantallas pequeñas ---------------------------------------------- */

@media (max-width: 1100px) {
  .model { grid-template-columns: 1fr; }
  .panel { position: static; height: auto; }
  .toma { height: 66vh; }

  .camp { grid-template-columns: 1fr; height: auto; }
  .camp__panel { order: -1; overflow: visible; border-bottom: var(--linea) solid var(--ink); }
  .camp__caras { overflow: visible; border-right: 0; }
  body.pantalla-partida .espaciador,
  body.pantalla-partida .foot { display: block; }
}

@media (max-width: 860px) {
  /* En el elemento, no en :root: la variable que fija el control se escribe
     en línea sobre <html> y ganaría a cualquier declaración de :root. */
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .head { gap: var(--s4); padding: 0 var(--s4); }
  .head__logo { width: 120px; }
  .head__nav, .head__right { display: none; }
  /* La cabecera estira a sus hijos, así que un botón de altura fija se
     queda pegado arriba: hay que centrarlo a mano. */
  .head__burger {
    display: grid; place-items: center; margin-left: auto; align-self: center;
    width: 34px; height: 34px; border: 0; background: none; cursor: pointer; color: var(--ink);
  }
  .head__burger svg { width: 21px; height: 21px; }
  .head__account { display: none; }

  /* La barra de segmentos desaparece: en móvil vive dentro de la cortina.
     Seis etiquetas no caben en 390 px, y así la parrilla gana esa franja. */
  .bar { display: none; }

  .cortina__segs {
    padding: var(--s5) var(--s5) 0;
    display: flex; flex-wrap: wrap; gap: var(--s2);
  }
  .cortina__segs .cortina__cab { width: 100%; }
  .cortina__segs button {
    padding: var(--s2) var(--s4);
    border: var(--linea) solid var(--ink); border-radius: 17px;
    background: none; cursor: pointer;
    font-size: var(--t-ui); letter-spacing: var(--tr-micro); text-transform: uppercase;
  }
  .cortina__segs button.is-on { background: var(--ink); color: var(--white); }

  /* La altura reservada para el pie es de escritorio: en móvil sobra y deja
     un hueco muerto antes del pie. */
  .page, .grid, .model,
  main.page, main.grid, main.model, main#page { min-height: 0; }
  /* En móvil la parrilla va siempre a 2 columnas: elegir no aporta nada. */
  .scaler { display: none; }
  .chipbar, .ctx { position: static; padding: var(--s2) var(--s4); }

  .page { padding: var(--s5) var(--s4) var(--s7); }
  /* La foto ocupa casi toda la pantalla: la barra de segmentos ya no está,
     así que ese espacio es suyo. */
  .toma { height: calc(100vh - var(--head-h) - 150px); }

  /* La isla deja de flotar: pasa a ser una banda a todo el ancho, con el
     mismo margen a ambos lados que el resto de la página. El ancho de
     escritorio —560px— aquí no cabe. */
  .sug { width: 150px; }
  .panel {
    position: static; width: auto; max-width: none; height: auto;
    /* Mismo margen arriba que abajo: sin él la caja toca la foto a sangre. */
    padding: var(--s4);
  }
  .tarjeta { width: auto; max-width: none; }
  .foot__mark { width: calc(100% - var(--s4) * 2); margin: var(--s4) var(--s4) var(--s5); }
  .foot__legal { padding: var(--s3) var(--s4) var(--s5); }
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}

/* ---------- Compartir por correo --------------------------------------------
   El diálogo de envío y la pantalla que ve el cliente. Mismos filetes, misma
   escala, misma caja: lo que recibe el cliente no puede parecer de otra web,
   porque es lo único de FACES que va a ver.                              */

/* El sobre va antes de la equis y no debe leerse como una acción destructiva:
   comparte el molde de .banda__x pero siempre visible, no sólo al pasar. */
.banda__enviar { opacity: 1; }
.banda__enviar svg { width: 14px; height: 12px; }
.banda__enviar:hover:not(:disabled) { color: var(--blue); }
.banda__enviar:disabled { color: var(--off); cursor: default; }
@media (hover: hover) { .banda:hover .banda__enviar { opacity: 1; } }

/* Formulario del diálogo.
   No inventa formas: el campo de una línea es la misma píldora de 30px que
   `.alta input` y el buscador de cuenta, y la caducidad se elige con los
   mismos `.chip-check` que el resto de opciones de la web. Una caja de
   esquina propia y un desplegable del sistema sonaban a otra aplicación. */
.envio { display: flex; flex-direction: column; gap: var(--s3); }

.envio__para {
  width: 100%; height: 44px; padding: 0 var(--s5);
  border: var(--linea) solid var(--ink); border-radius: 22px;
  background: var(--white); font: inherit; font-size: var(--t-ui);
}

/* El mensaje no puede ser píldora —tiene varias líneas— pero sí conserva el
   filete y el radio de caja del propio modal, para que se lea como parte de
   la misma pieza y no como un injerto. */
.envio__msg {
  width: 100%; padding: var(--s3) var(--s4); min-height: 76px;
  border: var(--linea) solid var(--ink); border-radius: var(--r-box);
  background: var(--white); font: inherit; font-size: var(--t-ui);
  line-height: 1.5; resize: vertical;
}

.envio__para:focus, .envio__msg:focus { outline: none; border-color: var(--blue); }
.envio__enlace { background: var(--bone); margin-top: var(--s2); }

/* La caducidad: rótulo arriba, opciones debajo. En una sola fila los tres
   chips se estrechaban y perdían la forma de píldora. */
.envio__vida { margin-top: var(--s1); }
.envio__et {
  display: block; margin-bottom: var(--s2);
  font-size: var(--t-micro); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--dim);
}
.envio__opts { display: flex; flex-wrap: wrap; gap: var(--s2); }

/* ---------- La pantalla del cliente ----------------------------------------- */

/* Sin navegación, la cabecera es sólo la marca: se le quita el estirado que
   necesitaba para alinear los enlaces. */
.head--suelta { gap: 0; }

.compartida { padding-bottom: var(--s6); }
.compartida__cab { max-width: 620px; }
.compartida__marca {
  display: block; margin-bottom: var(--s2);
  font-size: var(--t-micro); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--off);
}
.compartida__t {
  margin: 0; font-size: var(--t-display); font-weight: 500;
  letter-spacing: var(--tr-display); line-height: 1;
}
.compartida__meta { margin: var(--s3) 0 0; font-size: var(--t-ui); }

/* El mensaje del remitente, en rosa: es lo único de la pantalla que ha
   escrito una persona y tiene que distinguirse del dato. */
.compartida__nota {
  margin: var(--s4) 0 0; padding: var(--s3) var(--s4);
  background: var(--pink); font-size: var(--t-ui); line-height: 1.55;
  white-space: pre-wrap;
}

/* Misma retícula que las bandas de proyectos: las casillas se tocan y la
   línea llega hasta el borde. Aquí el filete superior sí hace falta, porque
   no hay cabecera de banda encima que lo aporte. */
.compartida__tira {
  border-top: var(--linea) solid var(--ink);
  border-bottom: var(--linea) solid var(--ink);
}
.cara--fija { cursor: default; }
.cara--fija .cara__img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cara__d {
  display: block; padding: 0 var(--s4) var(--s3);
  margin-top: calc(var(--s2) * -1);
  font-size: var(--t-drop); color: var(--off);
}

.compartida__pie { padding-top: var(--s6); max-width: 620px; }
.compartida__pie p { margin: 0 0 var(--s2); font-size: var(--t-ui); }
.compartida__pie a { text-decoration: underline; text-underline-offset: 3px; }

/* ---------- Admin · cintas de texto ------------------------------------------ */

.cinta { margin-bottom: var(--s7); }
.cinta__clave {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--t-drop); color: var(--dim);
}
.cinta__aviso {
  padding: var(--s1) var(--s2); border-radius: var(--r-box);
  background: var(--pink); font-size: var(--t-drop);
}

/* La vista previa va sobre tablero de damas: una cinta puede configurarse en
   blanco sobre una página en hueso, y sin fondo neutro detrás no se sabría si
   el blanco es de la cinta o del papel. */
.cinta__previa {
  margin-bottom: var(--s4);
  border: var(--linea) solid var(--ink);
  background: repeating-conic-gradient(#e2e0da 0% 25%, var(--bone) 0% 50%) 50% / 16px 16px;
}
/* Dentro de la previa la cinta no lleva filete propio: ya lo pone la caja. */
.cinta__previa .ticker { border: 0; }

.cinta__campos {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--s3); align-items: end;
}
.cinta__campo { display: flex; flex-direction: column; gap: var(--s2); }
.cinta__campo--ancho { grid-column: 1 / -1; }
.cinta__campo > span {
  font-size: var(--t-micro); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--dim);
}
.cinta__campo--chip { align-self: end; }

/* El selector de color nativo se recorta a la píldora de la casa, para que no
   meta su propia caja gris en mitad de la fila. */
.cinta__campo--color input[type="color"] {
  width: 100%; height: 30px; padding: 2px;
  border: var(--linea) solid var(--ink); border-radius: 22px;
  background: var(--white); cursor: pointer;
}
.cinta__campo--color input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
.cinta__campo--color input[type="color"]::-webkit-color-swatch {
  border: 0; border-radius: 13px;
}

.admin__resumen code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--t-drop);
  padding: 1px var(--s1); background: var(--white);
  border: var(--linea) solid var(--rule); border-radius: 4px;
}

/* ---------- Trabajos: campañas producidas -----------------------------------
   La banda de vídeo de la ficha. Va a sangre, como la galería y las
   sugerencias, para que las tres se lean como bandas de la misma familia. */

.trabajos {
  margin: 0 calc(var(--s5) * -1);
  background: var(--bone);
  border-bottom: var(--linea) solid var(--ink);
}
.trabajos[hidden] { display: none; }

/* Mismo rótulo que SUGGESTIONS: son hermanas, no dos inventos distintos. */
.trabajos__t {
  margin: 0; padding: var(--s3) var(--s5);
  font-size: var(--t-ui); font-weight: 500;
  letter-spacing: var(--tr-micro); text-transform: uppercase; text-align: center;
  border-bottom: var(--linea) solid var(--ink);
}

/* Tira de desplazamiento normal, no el carrusel infinito: con dos campañas,
   repetir el contenido enseñaría el mismo clip una y otra vez. */
.trabajos__tira {
  display: flex; align-items: stretch;
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}

/* La clave de todo el formato mixto: altura común, anchura derivada de la
   proporción real de cada vídeo. Un 16:9 sale tres veces más ancho que un
   9:16 y las dos comparten línea de base. Es como se lee una hoja de
   contactos, y evita tanto las barras negras como el recorte.

   La banda es más baja que la galería a propósito: marca la jerarquía sin
   tener que decirla, y evita que un 16:9 salga descomunal. */
.trabajos__tira { --tr-alto: min(60vh, 520px); }

.trabajo {
  margin: 0; flex: none;
  display: flex; flex-direction: column;
  border-right: var(--linea) solid var(--ink);
  background: var(--white);
}
.trabajo__disparo {
  position: relative; display: block; padding: 0; border: 0; cursor: pointer;
  height: var(--tr-alto);
  width: calc(var(--tr-alto) * var(--w) / var(--h));
  background: var(--ink);
}
.trabajo__disparo img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.trabajo__sinCartel {
  display: block; width: 100%; height: 100%;
  background: repeating-linear-gradient(45deg,
    #1a1a1a, #1a1a1a 6px, #101010 6px, #101010 12px);
}

/* El disparador de reproducción: círculo, como el resto de controles
   circulares de la casa. Blanco sobre la imagen, que puede ser cualquier
   cosa, con una sombra suave para que no se pierda sobre un fondo claro. */
.trabajo__play {
  position: absolute; inset: 0; margin: auto;
  width: 56px; height: 56px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--white); color: var(--ink);
  box-shadow: 0 2px 12px rgba(0, 0, 0, .28);
  transition: transform .18s ease;
}
.trabajo__play svg { width: 14px; height: 16px; margin-left: 3px; }
@media (hover: hover) {
  .trabajo__disparo:hover .trabajo__play { transform: scale(1.08); }
}

/* Ya reproduciendo: el player ocupa el mismo hueco exacto que ocupaba el
   cartel, así que la tira no da ningún salto al pulsar. */
.trabajo iframe {
  height: var(--tr-alto);
  width: calc(var(--tr-alto) * var(--w) / var(--h));
  border: 0; display: block; background: var(--ink);
}

.trabajo__pie {
  display: flex; align-items: baseline; gap: var(--s3);
  padding: var(--s3) var(--s4);
  border-top: var(--linea) solid var(--ink);
}
.trabajo__n { font-size: var(--t-ui); }
.trabajo__m {
  margin-left: auto;
  font-size: var(--t-drop); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--dim);
}

/* En móvil la banda baja de altura: un 16:9 a 60vh no cabe de ancho y
   obligaría a arrastrar mucho para ver una sola pieza. */
@media (max-width: 700px) {
  .trabajos__tira { --tr-alto: min(52vh, 380px); }
  .trabajo__play { width: 44px; height: 44px; }
}

/* Miniatura del cartel en el listado de campañas: sólo para reconocer el
   vídeo de un vistazo, no para lucirlo. */
.tabla__mini { width: 52px; }
.tabla__mini img {
  width: 44px; aspect-ratio: 1; object-fit: cover; display: block;
  border: var(--linea) solid var(--ink);
}

/* Vista previa del formato en el editor de campaña, sobre tablero: hay
   vídeos con fondo blanco y sin él no se sabría dónde acaba la pieza. */
.w-previa {
  margin-bottom: var(--s6);
  border: var(--linea) solid var(--ink);
  background: repeating-conic-gradient(#e2e0da 0% 25%, var(--bone) 0% 50%) 50% / 16px 16px;
}
.w-previa .trabajos__tira { --tr-alto: 260px; }
.w-previa .trabajo { border-right: 0; }

.w-sub {
  margin: 0 0 var(--s3);
  font-size: var(--t-ui); font-weight: 500;
  letter-spacing: var(--tr-micro); text-transform: uppercase;
}
.w-caras { display: flex; flex-wrap: wrap; gap: var(--s2); margin-bottom: var(--s5); }

/* Sello de campaña sobre una toma de la galería. Discreto pero legible: es
   lo que impide que el book se confunda con material de campaña. Píldora
   blanca con filete, como el resto de la casa. */
.toma--campana { position: relative; }
.toma__sello {
  position: absolute; left: var(--s4); bottom: var(--s4);
  padding: 0 var(--s3); height: 24px;
  display: inline-flex; align-items: center;
  border: var(--linea) solid var(--ink); border-radius: 12px;
  background: var(--white); color: var(--ink);
  font-size: var(--t-drop); letter-spacing: var(--tr-micro);
  text-transform: uppercase; white-space: nowrap;
  pointer-events: none;
}

/* Pieza de Instagram dentro de la banda de campañas.

   Se distingue de una de Vimeo a propósito: el icono es de salida, no de
   reproducción, porque al pulsar te vas del catálogo. Prometer un play y
   abrir una pestaña sería mentir con un icono. */
.trabajo--insta .trabajo__play svg { width: 15px; height: 15px; margin: 0; }
.trabajo__medio {
  position: absolute; left: var(--s3); top: var(--s3);
  padding: 0 var(--s2); height: 22px;
  display: inline-flex; align-items: center;
  border: var(--linea) solid var(--ink); border-radius: 11px;
  background: var(--white); color: var(--ink);
  font-size: var(--t-drop); letter-spacing: var(--tr-micro);
  text-transform: uppercase; white-space: nowrap;
}
/* Sin cartel el hueco es oscuro; la pastilla se invierte para no perderse. */
.trabajo--insta .trabajo__sinCartel ~ .trabajo__medio {
  background: transparent; color: var(--white); border-color: var(--white);
}

/* La previa de vídeos del formulario de talento ahora enseña el cartel real
   que devuelve Vimeo, no un número de identificación. */
.previa__v img { width: 100%; aspect-ratio: 2/3; object-fit: cover; display: block; }
.previa__v figcaption { font-size: var(--t-drop); color: var(--dim); }

/* ---------- Admin · subida de imágenes ---------------------------------------
   Zona de arrastre, rejilla de tomas reordenable y barra de progreso. */

.soltar {
  padding: var(--s6) var(--s5); text-align: center; cursor: pointer;
  border: var(--linea) dashed var(--ink); border-radius: var(--r-box);
  background: var(--white); transition: background .15s ease;
}
.soltar:hover, .soltar:focus-visible { background: var(--bone); outline: none; }
/* Al arrastrar encima, el rosa de la casa: dice «suelta aquí» sin texto. */
.soltar.is-diana { background: var(--pink); border-style: solid; }
.soltar__t { margin: 0; font-size: var(--t-ui); }
.soltar__p { margin: var(--s2) 0 0; font-size: var(--t-drop); color: var(--dim); }

.subida {
  margin-top: var(--s2); padding: var(--s2) var(--s3);
  border: var(--linea) solid var(--ink); border-radius: var(--r-box);
  background: var(--white); font-size: var(--t-drop);
}
.subida.is-rota { background: var(--pink); }
.subida__n { display: block; margin-bottom: var(--s2); }
.subida__pista { display: block; height: 4px; background: var(--rule); }
.subida__pista i { display: block; height: 100%; background: var(--ink); transition: width .2s ease; }

.galeria-admin {
  display: flex; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s3);
}
.galeria-admin__i {
  position: relative; margin: 0; width: 110px; cursor: grab;
}
.galeria-admin__i img {
  width: 110px; aspect-ratio: 2/3; object-fit: cover; display: block;
  border: var(--linea) solid var(--ink); background: var(--rule);
}
.galeria-admin__i figcaption {
  padding-top: var(--s2); font-size: var(--t-drop); color: var(--dim);
}
.galeria-admin__i.is-llevando { opacity: .4; }
.galeria-admin__i.is-diana img { border-color: var(--blue); }
.galeria-admin__i.is-rota img { background: var(--pink); }

/* La equis sólo al pasar por encima: doce equis permanentes convierten la
   rejilla en un panel de control en vez de una tira de fotos. */
.galeria-admin__x {
  position: absolute; top: 6px; right: 6px;
  width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center; opacity: 0;
  border: var(--linea) solid var(--ink); background: var(--white);
  cursor: pointer; transition: opacity .15s ease;
}
.galeria-admin__x svg { width: 9px; height: 9px; }
@media (hover: hover) { .galeria-admin__i:hover .galeria-admin__x { opacity: 1; } }
@media (hover: none)  { .galeria-admin__x { opacity: 1; } }

/* ---------- Admin · segunda fila de cabecera --------------------------------

   El submenú del panel usa el mismo componente que la barra de segmentos del
   catálogo: `.bar` con `.segs` y `.seg`, marca vertical incluida. No hay
   estilos propios porque no debe haberlos — si algún día cambia esa barra en
   la web, el panel cambia con ella. Aquí sólo queda el color de la marca,
   que en el catálogo lo pone cada segmento y aquí no hay segmento. */

.subcab { --seg-c: var(--ink); }

/* La cabecera conserva su filete: es lo que separa el menú del submenú. Se
   lo quité pensando que dos filetes partirían la pieza, y era al revés —sin
   él, las dos plantas se leían como una sola fila desordenada. */

/* El contenido ya no necesita separarse de una barra que estaba dentro. */
.page.admin { padding-top: var(--s6); }

.admin-herr {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s5) 0 var(--s4);
}
.admin-herr .btn { flex: none; white-space: nowrap; }
.admin-herr .btn:first-child { margin-left: auto; }
.admin-herr .buscador + .btn { margin-left: 0; }

/* El buscador es un campo, no un botón: filete inferior, sin píldora. */
.buscador {
  flex: 1 1 auto; min-width: 0;
  padding: var(--s2) 0;
  border: 0; border-bottom: var(--linea) solid var(--ink);
  border-radius: 0; background: none;
  font: inherit; font-size: var(--t-ui);
}
.buscador:focus { outline: none; border-bottom-color: var(--blue); }
.buscador::placeholder { color: var(--dim); }
.buscador::-webkit-search-cancel-button { display: none; }

/* Texto de ayuda: se lee una vez en la vida, así que no ocupa el mejor sitio
   de la pantalla. Va al pie de la sección y en cuerpo menor. */
.admin__nota {
  margin: var(--s6) 0 0; max-width: 62ch;
  font-size: var(--t-drop); line-height: 1.5; color: var(--dim);
}
.admin__nota code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  padding: 1px var(--s1); background: var(--white);
  border: var(--linea) solid var(--rule); border-radius: 4px;
}


/* Migas de vuelta dentro del título, no sueltas encima: así el título dice de
   dónde vienes y dónde estás en un solo bloque. */
.page__volver {
  display: block; margin-bottom: var(--s2);
  font-size: var(--t-micro); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--dim); text-decoration: none;
}
.page__volver::before { content: "← "; }
@media (hover: hover) { .page__volver:hover { color: var(--ink); } }

/* Barra de guardado pegada al fondo. En un formulario de esta longitud,
   tener que bajar hasta el final para guardar es la mitad del problema. */
.sel-bar--pegada {
  position: sticky; bottom: 0; z-index: 20;
  display: flex; align-items: center; gap: var(--s3);
  margin: var(--s6) calc(var(--s5) * -1) 0;
  padding: var(--s3) var(--s5);
  background: var(--bone);
  border-top: var(--linea) solid var(--ink);
}
.sel-bar__estado {
  margin-right: auto;
  font-size: var(--t-drop); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--dim);
}
/* Sin guardar: rosa, que es el color de aviso de la casa. Un rojo aquí
   diría «error» y esto no lo es: es sólo trabajo pendiente. */
.sel-bar__estado.is-sucio {
  padding: var(--s1) var(--s3); border-radius: 12px;
  background: var(--pink); color: var(--ink);
}

@media (max-width: 700px) {
  .admin-herr { flex-wrap: wrap; gap: var(--s2); }
  .admin-herr .buscador { flex: 1 0 100%; }
  .sel-bar--pegada { flex-wrap: wrap; }
  .sel-bar__estado { width: 100%; margin: 0 0 var(--s2); }
}

/* ---------- Admin · anchura de trabajo ---------------------------------------

   El panel no es un escaparate: es una herramienta de introducir datos. A
   sangre completa, en un monitor ancho, el nombre de una marca queda a dos
   mil píxeles de su botón de borrar y la vista tiene que cruzar la pantalla
   entera para relacionar dos cosas que van juntas.

   Se acota a una medida de lectura. La parrilla pública sigue a sangre: allí
   la anchura es el producto. */
.page.admin {
  max-width: 1040px;
  padding-left: var(--s5); padding-right: var(--s5);
}

/* La barra pegada iba a sangre con márgenes negativos calculados sobre el
   ancho de página. Dentro de una columna acotada, se ciñe a ella. */
.page.admin .sel-bar--pegada {
  margin-left: calc(var(--s5) * -1);
  margin-right: calc(var(--s5) * -1);
}

/* Las tablas del panel dejan de repartir el sobrante entre columnas: el
   nombre manda y lo accesorio se ciñe a su contenido. */
.page.admin .tabla { table-layout: auto; }
.page.admin .tabla th:last-child,
.page.admin .tabla td:last-child { width: 1%; white-space: nowrap; }
.page.admin .tabla td.tabla__mini { width: 1%; }

/* Las filas de marca y las cabeceras de grupo: el nombre a la izquierda, lo
   demás pegado a él y no al borde de la pantalla. */
.marca-fila__n { flex: 0 1 auto; min-width: 0; }
.marca-fila__n2 { margin-left: auto; }

/* La cabecera de una cinta se apelotonaba: nombre, clave, guardar y equis
   comprimidos en un palmo. El nombre manda, la clave va detrás en gris, y las
   acciones se empujan al extremo. */
.cinta .marco__head {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  padding: 0 0 var(--s3);
  border-bottom: var(--linea) solid var(--ink);
  margin-bottom: var(--s4);
}
.cinta .marco__acts { margin-left: auto; display: flex; align-items: center; gap: var(--s2); }
.cinta .marco__nombre { flex: 0 1 auto; }

/* Sin título, la fila de acciones sube y ocupa el ancho: el buscador se
   estira y los botones se quedan a su medida a la derecha. */

/* ---------- Admin · fila compacta de ajustes ---------------------------------

   Los ajustes de una cinta —cuerpo, velocidad, dirección, colores, visible—
   son seis controles cortos. En la retícula de columnas iguales cada uno se
   estiraba a 180px mínimo y el último caía a una segunda fila, así que un
   ajuste que se lee de un vistazo ocupaba dos.

   Ahora cada campo pide lo que necesita: dos cifras piden poco, un color
   pide una muestra, y el texto se queda con el resto. */
.campos-linea {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  gap: var(--s3) var(--s4);
}
.campos-linea .cinta__campo { flex: 0 0 auto; }
.campos-linea .cinta__campo--ancho { flex: 1 0 100%; }

.campos-linea [name="tamano"],
.campos-linea #tk_tamano      { width: 84px; }
.campos-linea [name="velocidad"],
.campos-linea #tk_velocidad   { width: 84px; }
.campos-linea [name="direccion"],
.campos-linea #tk_direccion   { width: 116px; }

/* Aquí estaba el solape: al fijar 64px la columna, el rótulo «Text colour»
   se salía por encima del vecino. El ancho fijo es de la muestra, no de la
   columna; la columna la marca el rótulo, que es lo más ancho. */
.campos-linea .cinta__campo--color input[type="color"] { width: 64px; }

/* El interruptor se alinea con la base de los campos, no con sus rótulos. */
.campos-linea .cinta__campo--chip { align-self: flex-end; margin-bottom: 0; }

@media (max-width: 700px) {
  .campos-linea .cinta__campo { flex: 1 1 calc(50% - var(--s4)); }
  .campos-linea [name="tamano"], .campos-linea #tk_tamano,
  .campos-linea [name="velocidad"], .campos-linea #tk_velocidad,
  .campos-linea [name="direccion"], .campos-linea #tk_direccion { width: 100%; }
}

/* ---------- Admin · etiquetas de selección ------------------------------------
   Lo elegido en un desplegable tiene que verse fuera de él: un <select> sólo
   enseña un valor, y aquí puede haber varios. */

.vis__elige { max-width: 280px; margin-bottom: var(--s3); }
.vis__elegidas { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; }

.etiqueta {
  display: inline-flex; align-items: center; gap: var(--s2);
  height: 44px; padding: 0 var(--s3) 0 var(--s5);
  border: var(--linea) solid var(--ink); border-radius: 22px;
  background: var(--white); font-size: var(--t-ui); white-space: nowrap;
}
.etiqueta button {
  display: grid; place-items: center;
  width: 20px; height: 20px; padding: 0;
  border: 0; border-radius: 50%; background: none;
  color: var(--dim); cursor: pointer;
}
.etiqueta button svg { width: 9px; height: 9px; }
@media (hover: hover) { .etiqueta button:hover { color: var(--ink); background: var(--rule); } }


/* ---------- Admin · desplegables ---------------------------------------------
   Con altura fija de 30px y el dibujo nativo, el navegador recortaba por
   abajo el texto de la opción. Se le quita la apariencia del sistema, se le
   da la flecha de la casa y sitio para respirar. */
select.envio__para,
.admin-herr select,
.cinta__campos select {
  appearance: none; -webkit-appearance: none;
  height: 32px; line-height: 1;
  padding: 0 var(--s6) 0 var(--s4);
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ink) 50%),
    linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position:
    calc(100% - 18px) calc(50% + 1px),
    calc(100% - 13px) calc(50% + 1px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}
select.envio__para::-ms-expand,
.admin-herr select::-ms-expand { display: none; }

/* ---------- Admin · el catálogo a sangre -------------------------------------
   El panel va acotado a 1040px porque es una herramienta de introducir datos
   y a sangre completa la vista cruza la pantalla para relacionar dos cosas
   que van juntas.

   El listado del catálogo es la excepción: una tabla de trece columnas donde
   cada fila se lee de un tirón. Aquí la anchura no separa, junta. */
.page.admin.admin--ancha { max-width: none; }
.admin--ancha .tabla { font-size: var(--t-drop); }
.admin--ancha .tabla th { white-space: nowrap; }
.admin--ancha .tabla td { vertical-align: middle; }

/* El nombre manda y no se parte; el resto pide lo justo. */
.admin--ancha .tabla__n { white-space: nowrap; }
.admin--ancha .tabla td .excl { white-space: normal; }

/* Por debajo de esta anchura, trece columnas no caben en ninguna pantalla:
   la tabla se desplaza en horizontal en vez de aplastarse. */
@media (max-width: 1100px) {
  .admin--ancha .tabla { display: block; overflow-x: auto; white-space: nowrap; }
}

/* ---------- Admin · cifras de uso -------------------------------------------- */
.datos-fila {
  display: flex; flex-wrap: wrap; gap: 0;
  border: var(--linea) solid var(--ink);
  margin-bottom: var(--s6);
}
.dato {
  flex: 1 1 140px; padding: var(--s4) var(--s5);
  border-right: var(--linea) solid var(--ink);
}
.dato:last-child { border-right: 0; }
/* Rosa para lo que pide una decisión: caras que nadie ha visto o elegido. */
.dato--aviso { background: var(--pink); }
.dato__n { display: block; font-size: var(--t-display); line-height: 1; letter-spacing: var(--tr-display); }
.dato__r {
  display: block; margin-top: var(--s2);
  font-size: var(--t-drop); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--dim);
}
.dato--aviso .dato__r { color: var(--ink); }
@media (max-width: 700px) {
  .dato { flex: 1 1 50%; border-bottom: var(--linea) solid var(--ink); }
}

/* ---------- Condiciones de uso ------------------------------------------------
   No es un aviso, es un requisito: sin equis, sin escape y sin pulsar fuera.
   La única salida que no sea aceptar es cerrar sesión, y está a la vista para
   que no parezca que se encierra a nadie. */
.cond {
  position: fixed; inset: 0; z-index: 90;
  display: grid; place-items: center; padding: var(--s5);
  background: rgba(0, 0, 0, .5);
}
.cond__caja {
  width: min(620px, 100%); max-height: 88vh;
  display: flex; flex-direction: column;
  background: var(--bone);
  border: var(--linea) solid var(--ink); border-radius: var(--r-box);
}
.cond__texto { overflow-y: auto; padding: var(--s6) var(--s6) var(--s4); }
.cond__t { margin: 0 0 var(--s4); font-size: var(--t-h2); font-weight: 500; letter-spacing: -.01em; }
.cond__s {
  margin: var(--s5) 0 var(--s2);
  font-size: var(--t-micro); font-weight: 500;
  letter-spacing: var(--tr-micro); text-transform: uppercase; color: var(--dim);
}
.cond__texto p { margin: 0 0 var(--s3); font-size: var(--t-ui); line-height: 1.55; }
.cond__p { color: var(--dim); }
.cond__texto a { text-decoration: underline; text-underline-offset: 3px; }

.cond__pie {
  /* Dos separaciones distintas: 12px entre los botones, que van juntos
     porque son la misma decisión, y 24px entre renglones. Con una sola, al
     partirse la fila la casilla quedaba pegada a los botones y una
     declaración —acepto— parecía parte de la acción.

     El pie se parte casi siempre: la caja mide 520px y la casilla más los
     dos botones no caben en una línea. */
  display: flex; align-items: center; gap: var(--s5) var(--s3); flex-wrap: wrap;
  padding: var(--s4) var(--s6) var(--s6);
  border-top: var(--linea) solid var(--ink);
}
.cond__acts { margin-left: auto; display: flex; gap: var(--s2); }
.cond .form-error { margin: 0 var(--s6) var(--s5); }

@media (max-width: 700px) {
  .cond__acts { margin-left: 0; width: 100%; }
  .cond__acts .btn { flex: 1; }
}

/* ---------- Admin · los controles piden lo que necesitan ---------------------

   Un control dentro de la barra de herramientas hereda el `width: 100%` de la
   clase de campo y se estira hasta el borde. Un desplegable de dos opciones
   midiendo dos mil píxeles no es un descuido puntual: pasa cada vez que se
   mete algo en esta fila. Se corta aquí, de una vez, para todos.

   La regla: en una barra, el ancho lo marca el contenido. Sólo el buscador
   se estira, porque lo que se escribe dentro sí puede ser largo — y aun así
   con techo. */

.admin-herr > select,
.admin-herr > input:not(.buscador) {
  width: auto; min-width: 160px; max-width: 260px;
  flex: 0 0 auto;
}

/* El buscador se estira, pero hasta un límite de lectura; el resto de la
   fila queda libre y empuja los botones al extremo. */
.admin-herr .buscador { flex: 0 1 400px; margin-right: auto; }

/* Un control solo en la fila no debe ocupar la fila. */
.admin-herr > select:only-child { margin-right: auto; }

/* ---------- Admin · plan de importación --------------------------------------
   El diálogo normal es estrecho porque suele llevar una pregunta. Aquí lleva
   una tabla que hay que poder leer antes de decidir. */
.modal__box--ancha { max-width: min(860px, 92vw); }
.plan {
  max-height: 46vh; overflow: auto;
  border: var(--linea) solid var(--ink); margin-bottom: var(--s4);
}
.plan .tabla { margin: 0; font-size: var(--t-drop); }
.plan .tabla th {
  position: sticky; top: 0; z-index: 1;
  background: var(--bone); border-bottom: var(--linea) solid var(--ink);
}
/* Las filas con problema en rosa: se ven de un vistazo sin leer la columna
   de errores, que es lo que se mira cuando ya sabes dónde mirar. */
.plan .is-mala { background: var(--pink); }

/* Cabeceras que ordenan. Son botones, pero no deben parecerlo: el rótulo
   manda y la flecha sólo aparece en la columna activa. */
.orden {
  display: inline-flex; align-items: baseline; gap: 4px;
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
}
.orden i { font-style: normal; font-size: 9px; }
.orden.is-on { text-decoration: underline; text-underline-offset: 4px; }
@media (hover: hover) { .orden:hover { color: var(--blue); } }


/* ---------- Diálogos con formulario -------------------------------------------
   Campos apilados sin gap: se tocaban entre sí y el conjunto se leía como un
   bloque en vez de como campos distintos. */
.form-col { display: flex; flex-direction: column; gap: var(--s3); }
.modal__box .campo { margin-top: var(--s5); }
.modal__box .campo__label { display: block; margin-bottom: var(--s2); }
.modal__box .vis { display: flex; gap: var(--s2); margin-bottom: var(--s2); }
.modal__box .campo__pista { display: block; margin-bottom: var(--s3); }
.modal__box .vis__elegidas { margin-top: var(--s2); }

/* ---------- Imágenes: fricción -----------------------------------------------
   Complementa a `guarda.js`. Impide seleccionar, arrastrar y el menú de
   guardar al mantener pulsado en iOS, que es la vía más cómoda para llevarse
   una foto desde el móvil.

   Se aplica al catálogo, no al panel: quien administra necesita poder
   arrastrar y guardar sus propias imágenes. */
body:not(.es-admin) .toma img,
body:not(.es-admin) .tile img,
body:not(.es-admin) .sug img,
body:not(.es-admin) .cara img,
body:not(.es-admin) .trabajo img,
body:not(.es-admin) .previa__i img {
  -webkit-user-drag: none;
  user-select: none; -webkit-user-select: none;
  -webkit-touch-callout: none;
  pointer-events: none;
}

/* ---------- Marca de contenido generado con IA -------------------------------

   Desde el 2 de agosto de 2026 el artículo 50 del Reglamento europeo de IA
   obliga a que el contenido sintético sea reconocible como tal. La obligación
   de marcado legible por máquina recae sobre quien fabrica el generador; a
   quien publica le toca que se vea.

   Se pinta desde el CSS y no desde las plantillas a propósito: hay seis
   sitios distintos que pintan imágenes y una vista nueva se olvidaría de
   ponerla. Aquí la impone el contenedor.

   `:has(img)` es deliberado: sin él, la marca saldría también en los huecos
   vacíos —la casilla de «añadir», una imagen rota— diciendo que hay IA donde
   no hay nada. */

.toma:has(img),
.tile__img:has(img),
.sug__img:has(img),
.cara__img:has(img),
.trabajo__disparo:has(img) { position: relative; }

.toma:has(img)::after,
.tile__img:has(img)::after,
.sug__img:has(img)::after,
.cara__img:has(img)::after,
.trabajo__disparo:has(img)::after {
  content: "IA";
  position: absolute; left: 10px; bottom: 9px; z-index: 2;
  /* Sin píldora, sin filete y sin fondo: sólo el texto, lavado. Tiene que
     cumplirse la divulgación sin competir con la cara, que es el producto.
     Una pastilla con borde de 2px pesaba más que el nombre del talento. */
  color: rgba(0, 0, 0, .34);
  font-size: 18px; font-weight: 700; letter-spacing: .12em; line-height: 1;
  pointer-events: none; user-select: none;
}

/* En las tomas grandes de la ficha respira un poco más. */
.toma:has(img)::after { left: var(--s4); bottom: var(--s4); }

/* En el panel no: son miniaturas de 44px donde la pastilla taparía la cara,
   y quien administra ya sabe de sobra lo que está mirando. */
.page.admin .tile__img::after,
.page.admin .cara__img::after,
.galeria-admin__i::after { content: none; }

/* ---------- Página de acceso -------------------------------------------------
   La caja flota en el centro y detrás corre una tira horizontal sin final que
   se mueve con el ratón. Tuvo una pantalla partida, después una isla sobre un
   collage velado y después un campo de caras a distintas profundidades; ésta
   es la cuarta. La anterior está guardada en `archivo/`.

   Todo el movimiento va en `transform`, que el navegador resuelve en la
   tarjeta gráfica sin recalcular el diseño. Mover treinta y seis imágenes con
   `left` a cada gesto del ratón sería recalcular la página entera cien veces
   por segundo. */

body.entrar {
  min-height: 100vh; margin: 0;
  padding: 0;
  background: var(--pink);
  overflow: hidden;
}

/* El pie no entra aquí. `app.js` lo inyecta en todas las páginas, y en ésta
   metía la marca rosa abajo y descolocaba la caja: al ser un segundo
   elemento de la rejilla, el centrado dejaba de ser el de la pantalla. */
body.entrar .foot { display: none; }

/* La tira. Ocupa la pantalla entera por detrás de todo y no recibe el ratón:
   se mueve con él, pero no se pincha ni se selecciona. */
.tira {
  position: fixed; inset: 0; z-index: 0;
  overflow: hidden; pointer-events: none;
  transition: opacity .45s ease;
}

/* Cada pieza, a la altura entera. El ancho lo escribe el script en `--pieza`
   porque depende de la ventana y de si es un teléfono, y esa cuenta ya la
   hace el motor: tenerla también aquí serían dos sitios donde cambiarla y
   uno de los dos se olvidaría.

   El filete va en la pieza y no en la imagen. La imagen se escala, y con el
   trazo encima se escalaría con ella: dos píxeles en el centro y cinco en
   los lados. El sistema dice 2px, no «2px a veces».

   Y va sólo a la izquierda. Con filete a los dos lados, cada junta entre dos
   piezas sumaba el derecho de una y el izquierdo de la siguiente: 4px donde
   toda la web tiene 2. Las líneas de esta casa ni se pisan ni se suman. */
.tira__pieza {
  position: absolute; top: 0; left: 0;
  width: var(--pieza, 42vw); height: 100%;
  overflow: hidden;
  border-left: var(--linea) solid var(--ink);
  will-change: transform;
}

.tira__pieza img {
  width: 100%; height: 100%;
  object-fit: cover; display: block;
  transform-origin: center center;
  will-change: transform;
}

/* Al entrar, el fondo se retira: la puerta se abre en vez de cortarse. */
body.es-dentro .tira { opacity: 0; }
body.es-dentro .entrar__caja { opacity: 0; transform: translate(-50%, -50%) scale(.98); }

/* La caja, flotando. Sí lleva su marco aquí: no hay ninguna otra estructura
   en la pantalla de la que colgarla, y sin borde se perdería sobre las
   caras. Es lo contrario del caso de Projects, donde el marco enmarcaba algo
   que ya estaba dentro de otra cosa. */
/* La caja, centrada de verdad en la pantalla y no dentro de un reparto que
   compartía con el pie. */
.entrar__caja {
  position: fixed; z-index: 1;
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(440px, calc(100% - var(--s5) * 2));
  padding: var(--s6);
  background: var(--bone);
  border: var(--linea) solid var(--ink);
  border-radius: var(--r-box);
  transition: opacity .4s ease;
}
.entrar__logo { display: block; width: 140px; margin-bottom: var(--s6); }
.entrar__logo svg { width: 100%; height: auto; fill: var(--ink); display: block; }

.entrar__cab {
  margin: 0 0 var(--s2);
  font-size: var(--t-drop); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--dim);
}
.entrar__t {
  margin: 0 0 var(--s5);
  font-size: var(--t-h2); font-weight: 500; letter-spacing: -.015em; line-height: 1.1;
}

.entrar__form { display: flex; flex-direction: column; gap: var(--s3); }

/* El ojo, dentro de la caja de la contraseña.

   Va dentro y no al lado porque el formulario es una columna de píldoras de
   44px: poner otra al lado se leería como un segundo campo. El campo reserva
   sitio a la derecha para que el texto largo no pase por debajo del icono. */
.entrar__clave { position: relative; display: block; }
.entrar__clave input { padding-right: 46px; }
.entrar__ojo {
  position: absolute; right: var(--s2); top: 50%; transform: translateY(-50%);
  width: 32px; height: 32px; display: grid; place-items: center;
  padding: 0; border: 0; background: none; cursor: pointer;
  color: var(--off); border-radius: 50%;
}
.entrar__ojo:hover { color: var(--ink); }
.entrar__ojo:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.entrar__ojo svg { width: 16px; height: 12px; display: block; }

.entrar__ok { width: 100%; margin-top: var(--s2); }
.entrar__olvido {
  padding: 0; border: 0; background: none; cursor: pointer; text-align: left;
  font: inherit; font-size: var(--t-drop); color: var(--dim);
  text-decoration: underline; text-underline-offset: 3px;
}
@media (hover: hover) { .entrar__olvido:hover { color: var(--ink); } }

.form-error.es-bueno { background: none; color: var(--dim); }

.entrar__pie { margin: var(--s5) 0 0; font-size: var(--t-drop); color: var(--dim); }
.entrar__pie a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

@media (max-width: 700px) {
  .entrar__caja { padding: var(--s5); }
  .entrar__logo { width: 118px; margin-bottom: var(--s5); }
}

/* ---------- Portada del cliente ----------------------------------------------
   Manda la imagen. La versión anterior era un panel de control: miniaturas de
   150px, versalitas y una frase de gestor de tareas. Esto se le enseña a un
   director de arte, y lo que vende es una cara, no el número de proyectos
   abiertos.

   Sigue siendo el lenguaje de la casa —filete de 2px, hueso, sin sombras—,
   pero a la escala del producto. */

.inicio { padding-bottom: var(--s8); }

/* ---- La portada -------------------------------------------------------------- */

.hero {
  position: relative;
  height: min(78vh, 720px);
  border-bottom: var(--linea) solid var(--ink);
  overflow: hidden;
  background: var(--rule);
}
.hero__img { display: block; width: 100%; height: 100%; }
.hero__img img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* Un acercamiento muy lento: da vida sin llamar la atención sobre sí mismo. */
  animation: heroZoom 24s ease-out forwards;
}
@keyframes heroZoom { from { transform: scale(1.06); } to { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .hero__img img { animation: none; } }

/* El texto sobre la foto, no en una caja: una caja lo convertiría en un
   cartel pegado encima. El velo sólo donde hace falta leer. */
.hero__txt {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: var(--s7) var(--s5) var(--s5);
  background: linear-gradient(to top, rgba(0,0,0,.62), rgba(0,0,0,.28) 55%, transparent);
  color: var(--tinta, var(--white));
  pointer-events: none;
}
/* Una portada compuesta puede traer ya su propia zona limpia para el texto;
   en ese caso el velo sobra y sólo ensucia el trabajo de quien la diseñó. */
.hero__txt--sinvelo { background: none; }
.hero__txt a { pointer-events: auto; }
.hero__hola, .hero__motivo {
  margin: 0; font-size: var(--t-drop);
  letter-spacing: var(--tr-micro); text-transform: uppercase;
}
.hero__hola { opacity: .7; }
.hero__motivo { margin-top: 2px; }
.hero__t {
  margin: var(--s2) 0 var(--s3);
  font-size: clamp(48px, 9vw, 132px); font-weight: 500;
  letter-spacing: -.03em; line-height: .9;
}
.hero__ir {
  color: var(--tinta, var(--white)); font-size: var(--t-ui);
  text-decoration: underline; text-underline-offset: 5px;
}

/* La portada es siempre una pieza de promoción de la plataforma, compuesta
   por el estudio. Nunca una cara del catálogo: eso convertía un espacio de
   marca en un escaparate más, y el escaparate ya está debajo.

   Manda la proporción de la imagen. Se ve entera, sin
   recorte, porque es una pieza diseñada y sus extremos son parte del trabajo.

   El tope de altura evita que un cuadrado en un monitor ancho empuje todo lo
   demás fuera de la pantalla. */
/* Ajustada al ancho y escalada en altura: la caja toma la proporción exacta
   de la imagen y crece con la ventana. Sin tope.

   Llevaba un `max-height` del 82% de la pantalla para que un formato
   cuadrado no empujara todo lo demás fuera de vista; pero ese tope recortaba
   la pieza, y una portada compuesta hay que verla entera. Si algún día subes
   una casi cuadrada y ocupa demasiado, la solución es recomponerla más
   apaisada, no que el navegador decida dónde cortarla. */
.hero--fija {
  height: auto;
  aspect-ratio: var(--w) / var(--h);
}
.hero--fija .hero__img img { object-fit: contain; background: var(--bone); }
/* Sólo si el tope recorta algo, se prefiere llenar antes que dejar bandas. */
@supports (aspect-ratio: 1) {
  .hero--fija .hero__img img { object-fit: cover; }
}

/* En móvil también escala: la altura sale del ancho, sin mínimos que
   recorten. Un 16:9 en un teléfono queda bajo —es la consecuencia de
   escalar de verdad—; para eso está el hueco de la versión vertical. */



/* ---- Franjas de caras --------------------------------------------------------- */

.franja { padding: var(--s7) var(--s5) 0; }
.franja:last-child { padding-bottom: var(--s7); }
.franja__cab {
  display: flex; align-items: baseline; gap: var(--s4);
  padding-bottom: var(--s3); margin-bottom: var(--s4);
  border-bottom: var(--linea) solid var(--ink);
}
.franja__t {
  margin: 0; font-size: var(--t-h2); font-weight: 500;
  letter-spacing: -.015em; line-height: 1;
}
.franja__p { margin-left: auto; font-size: var(--t-drop); color: var(--dim); }
.franja__mas { text-decoration: underline; text-underline-offset: 3px; }
@media (hover: hover) { .franja__mas:hover { color: var(--ink); } }

/* Las bandas de la home reutilizan `.banda` de Projects: caja cerrada, celdas
   que se tocan, a sangre. Aquí sólo va lo que cambia.

   Antes usaba `.tile`, la celda de la parrilla del catálogo, que está pensada
   para una retícula que ocupa la página entera y crece hasta llenarla. En una
   franja de seis caras eso dejaba media pantalla en blanco debajo, que es el
   hueco que se veía. */

/* Sin margen negativo: lo llevaba para salir a sangre desde una página con
   relleno lateral, y esta ya no lo tiene. El resultado era que la primera
   celda de cada banda quedaba medio fuera de la pantalla y su texto cortado. */
/* Sólo cierra por abajo. Llevaba filete arriba y abajo, así que entre dos
   bandas seguidas se sumaban 4px. El borde superior de la primera lo pone
   siempre lo que hay encima: la portada o la propia cabecera del sitio. */
.banda--home {
  border-top: 0;
}
/* Cada banda cierra por abajo, y sólo por abajo: encadenadas, cada filete
   hace de suelo de una y de techo de la siguiente. */
.banda--home { border-bottom: var(--linea) solid var(--ink); }

/* Las columnas que sobran cuando hay menos celdas que huecos —dos proyectos
   en una fila de seis— llevaban fondo blanco y se leían como un agujero.
   Con el hueso de la banda quedan dentro de la caja. */
/* Las celdas no se estiran a la altura de la fila. Con el estirón por
   defecto de la retícula, una caja con proporción 1:1 la perdía: la altura
   se la imponía la fila y el cuadrado salía rectángulo. */
.banda--home .banda__tira { background: var(--bone); align-items: start; }

/* La última celda cierra por su derecha sólo si la fila está llena; si sobra
   sitio, ese filete quedaría suspendido en mitad del vacío. */
.banda--home .cara:last-child { border-right: var(--linea) solid var(--ink); }

/* Las franjas de caras de la portada son una sola fila que se desplaza en
   horizontal, sin salto de línea. Cada cara mide lo mismo que una columna de
   siete; si hay más de las que caben, se arrastra. */
.banda__tira--fila {
  display: flex; overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x proximity; scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.banda__tira--fila > .cara {
  flex: 0 0 max(200px, calc(100% / 7));
  scroll-snap-align: start;
  border-bottom: 0;
}

/* La cabecera de la banda con el mismo aire que en Projects. */
/* Las celdas estiran a toda la altura. Con alineación por base, el filete
   que separa los dos textos quedaba flotando en medio sin tocar ni arriba ni
   abajo: una raya suelta, no una división. */
.banda--home .banda__head {
  display: flex; align-items: stretch; gap: 0;
  border-bottom: var(--linea) solid var(--ink);
}
.banda--home .banda__t {
  display: flex; align-items: center;
  padding: var(--s3) var(--s5); min-width: 320px;
}
.banda--home .banda__nota {
  display: flex; align-items: center;
  flex: 1; padding: var(--s3) var(--s5);
  border-left: var(--linea) solid var(--ink);
}
.banda__t { font-size: var(--t-ui); }
.banda--home .banda__nota { margin-left: auto; font-size: var(--t-drop); color: var(--dim); }
.banda__mas { text-decoration: underline; text-underline-offset: 3px; }
@media (hover: hover) { .banda__mas:hover { color: var(--ink); } }

/* Celda de proyecto: cuadrado partido en vertical. A la izquierda el texto
   sobre el color del proyecto; a la derecha la cara.

   La mitad de un cuadrado es un 1:2, que para un retrato de cuerpo entero es
   el encuadre natural — el mismo que tienen las tomas del catálogo. */
/* Los proyectos dejan de ser celdas pegadas y pasan a ser piezas sueltas:
   el doble de tamaño, con aire alrededor y esquina redondeada. Redondear y
   pegar no se pueden a la vez —dos radios enfrentados dejan un rombo de
   fondo entre ellos—, así que esta tira lleva separación y su propio
   respiro contra los bordes de la banda. */
/* En horizontal, no plegando a varias filas: los proyectos son una lista
   que crece, y apilarlos empujaría el resto de la home hacia abajo sin fin.
   Al no caber, se arrastra. */
.banda__tira--proy {
  display: flex;
  gap: var(--s4);
  padding: var(--s4) var(--s5) var(--s5);
  background: var(--bone);
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: thin; -webkit-overflow-scrolling: touch;
}
.banda__tira--proy .proy-cel { flex: 0 0 420px; }

.proy-cel {
  position: relative; display: grid; grid-template-columns: 1fr 1fr;
  aspect-ratio: 1 / 1;
  border: var(--linea) solid var(--ink);
  border-radius: var(--r-box);
  /* Sin esto, las mitades de color e imagen se salen por la esquina
     redondeada y el radio no se ve. */
  overflow: hidden;
  /* Una celda de retícula lleva por defecto altura mínima igual a su
     contenido, y esa mínima manda sobre la proporción. Sin esto el cuadrado
     no llega a aplicarse nunca. */
  min-height: 0; min-width: 0;
  background: var(--white); text-decoration: none;
}

.proy-cel__txt {
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: var(--s5);
  background: var(--fondo, var(--ink));
  color: var(--tinta, #fff);
  border-right: var(--linea) solid var(--ink);
  min-width: 0;
}
.proy-cel__n {
  font-size: var(--t-h2); line-height: 1.05; letter-spacing: -.015em;
  /* `break-word` y no `anywhere`: los dos parten una palabra que no cabe,
     pero `anywhere` además la parte cuando cabría entera en la línea de
     abajo, y de ahí salía «Ecommerc / e AW16». */
  overflow-wrap: break-word;
}
.proy-cel__m, .proy-cel__c {
  font-size: var(--t-drop); letter-spacing: var(--tr-micro);
  text-transform: uppercase; opacity: .78;
}
.proy-cel__m { margin-top: var(--s2); }

.proy-cel__img { overflow: hidden; background: var(--bone); min-width: 0; }
.proy-cel__img img {
  width: 100%; height: 100%; display: block; object-fit: cover;
  /* Encuadre alto: en un recorte estrecho, el centro geométrico de un
     cuerpo entero cae por la cintura. */
  object-position: 50% 18%;
}
@media (hover: hover) {
  .proy-cel__img img { transition: transform .5s cubic-bezier(.2,.7,.3,1); }
  .proy-cel:hover .proy-cel__img img { transform: scale(1.05); }
}

.banda--invita { padding: var(--s6) var(--s5); }
.banda--invita p { margin: var(--s3) 0 var(--s4); max-width: 46ch; font-size: var(--t-ui); }

/* ---- Aparición ---------------------------------------------------------------- */

[data-revela] {
  opacity: 0; transform: translateY(16px);
  transition: opacity .6s ease, transform .6s cubic-bezier(.2,.7,.3,1);
}
[data-revela].visto { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  [data-revela] { opacity: 1; transform: none; transition: none; }
}

@media (max-width: 700px) {
  /* Sólo la portada personal, la que recorta una cara del catálogo. La
     compuesta (`.hero--fija`) escala con su proporción y no lleva altura.
     Sin el `:not`, esta regla la anulaba —misma especificidad, más abajo en
     el fichero— y la dejaba recortada a 520px en vertical, que es donde peor
     sienta: de una pieza apaisada sólo se veía la franja central. */
  .hero:not(.hero--fija) { height: min(70vh, 520px); }
  .franja { padding-top: var(--s6); }
  .franja__cab { flex-wrap: wrap; gap: var(--s2); }
  .franja__p { margin-left: 0; }
  .cara-g { width: 62vw; }
}


/* ---------- Admin · portada ---------------------------------------------------
   La previa reproduce la cabecera real y no un esquema: es la única forma de
   saber si el texto se lee sobre esa imagen antes de publicarla. */
.port-previa { margin-bottom: var(--s4); border: var(--linea) solid var(--ink); }
.hero--previa { height: 340px; border-bottom: 0; }
.hero--previa .hero__t { font-size: clamp(32px, 5vw, 64px); }
.hero--previa .hero__img { cursor: default; }

/* ---------- Mosaico de piezas ------------------------------------------------
   Vídeo y piezas gráficas del estudio, en los cuatro formatos que produce:
   9:16, 1:1, 2:3 y 4:5, más algún apaisado.

   La clave es que cada hueco declara su proporción y ocupa columnas en
   proporción a su anchura. Así conviven un vertical de Instagram y un
   apaisado en la misma fila sin que ninguno se recorte, que es lo que pasa
   cuando se meten en una retícula de celdas iguales. */

.mosaico {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--linea);
  background: var(--ink);
  border-bottom: var(--linea) solid var(--ink);
}
.hueco {
  grid-column: span 3;
  display: block; position: relative;
  background: var(--bone); text-decoration: none;
}
/* Los anchos mandan sobre el reparto: un 16:9 pide el doble que un vertical. */
.hueco[style*="--w:16"] { grid-column: span 6; }
.hueco[style*="--w:9"]  { grid-column: span 3; }
.hueco[style*="--w:4"],
.hueco[style*="--w:2"],
.hueco[style*="--w:1;"] { grid-column: span 3; }

.hueco__caja {
  display: block; width: 100%;
  aspect-ratio: var(--w) / var(--h);
  overflow: hidden; background: var(--bone);
}
.hueco__caja img, .hueco__caja video {
  width: 100%; height: 100%; object-fit: cover; display: block;
}

/* Vacío se ve como vacío, con su formato escrito. Un blanco sin marcar
   parecería un fallo de carga; así se lee como sitio reservado. */
.hueco:not(.is-lleno) .hueco__caja {
  display: grid; place-items: center;
  background: repeating-linear-gradient(45deg,
    var(--bone), var(--bone) 10px, #e3e1db 10px, #e3e1db 20px);
}
.hueco__marca {
  font-size: var(--t-drop); letter-spacing: var(--tr-micro);
  color: var(--dim); background: var(--bone);
  padding: var(--s1) var(--s3); border: var(--linea) solid var(--rule);
  border-radius: var(--r-box);
}

.hueco__pie {
  display: block; padding: var(--s2) var(--s3) var(--s3);
  font-size: var(--t-drop); color: var(--ink); background: var(--bone);
}
@media (hover: hover) {
  .hueco.is-lleno img, .hueco.is-lleno video { transition: transform .6s cubic-bezier(.2,.7,.3,1); }
  a.hueco.is-lleno:hover img, a.hueco.is-lleno:hover video { transform: scale(1.04); }
}

@media (max-width: 900px) {
  .mosaico { grid-template-columns: repeat(6, 1fr); }
  .hueco, .hueco[style*="--w:16"] { grid-column: span 3; }
}


@media (max-width: 700px) {
  .banda__tira--proy { padding: var(--s3) var(--s4) var(--s4); }
  .banda__tira--proy .proy-cel { flex: 0 0 86vw; }

  /* En vertical el reparto a mitades no da de sí: sobre una tarjeta de 78vw
     la columna de texto quedaba en unos 100px útiles, y ahí no cabe ni
     «SPRINGFIELD» en versales. La foto cede lo que le sobra —sigue
     reconociéndose una cara— y el relleno baja un escalón. */
  .proy-cel { grid-template-columns: 1.25fr 1fr; }
  .proy-cel__txt { padding: var(--s4); }
}

/* ---------- Portada: carrusel -------------------------------------------------
   Cambia por opacidad y no por desplazamiento. Una portada que se desliza
   pide un gesto, y esto no se maneja: se mira. */

.hero__pila { position: absolute; inset: 0; }
.hero__d {
  position: absolute; inset: 0;
  opacity: 0; transition: opacity .9s ease;
  pointer-events: none;
}
.hero__d.is-viva { opacity: 1; }
.hero__d img, .hero__d iframe {
  width: 100%; height: 100%; display: block; border: 0;
}
/* Centrado: al ser la caja más apaisada que la imagen, se recorta lo mismo
   por arriba que por abajo. */
.hero__d img { object-fit: cover; object-position: 50% 50%; }

/* El vídeo de Vimeo en modo portada mantiene su 16:9 pase lo que pase, así
   que se agranda hasta cubrir la caja y se recorta por donde sobre. Sin
   esto aparecen bandas negras arriba y abajo. */
.hero__d[data-tipo="vimeo"] { overflow: hidden; }
.hero__d[data-tipo="vimeo"] iframe {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 100vw; height: 56.25vw; min-height: 100%; min-width: 177.78vh;
  pointer-events: none;
}

/* El enlace cubre la portada por debajo del texto: con un iframe encima, un
   enlace normal dejaría de recibir el clic. */
.hero__ir-todo { position: absolute; inset: 0; z-index: 1; }
.hero__txt { z-index: 2; }

.hero__puntos {
  position: absolute; right: var(--s5); bottom: var(--s5); z-index: 3;
  display: flex; gap: var(--s2);
}
.hero__punto {
  width: 8px; height: 8px; padding: 0; border-radius: 50%;
  border: var(--linea) solid var(--tinta, #fff);
  background: none; cursor: pointer; opacity: .55;
  transition: opacity .2s, background .2s;
}
.hero__punto.is-viva { background: var(--tinta, #fff); opacity: 1; }
@media (hover: hover) { .hero__punto:hover { opacity: 1; } }

/* ---------- Admin · piezas de la portada -------------------------------------- */
.piezas { margin-bottom: var(--s3); }
.pieza {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) var(--s3);
  border: var(--linea) solid var(--ink); border-radius: var(--r-box);
  background: var(--white); margin-bottom: var(--s2);
}
.pieza__n {
  width: 22px; text-align: center;
  font-size: var(--t-drop); color: var(--dim);
}
.pieza__mini {
  width: 64px; height: 40px; overflow: hidden; flex: none;
  border: var(--linea) solid var(--rule); background: var(--rule);
}
.pieza__mini img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pieza__d { font-size: var(--t-drop); color: var(--dim); }
.pieza__d b { color: var(--ink); font-weight: 500; }
.pieza__acts { margin-left: auto; display: flex; align-items: center; gap: var(--s2); }
.pieza__acts .btn { padding: 0 var(--s3); }

@media (max-width: 700px) {
  .hero__puntos { right: var(--s4); bottom: var(--s4); }
  .pieza__d { display: none; }
}

/* ---------- Admin · portada por tamaño de pantalla ---------------------------
   Tres juegos de piezas, uno por tamaño. Las pestañas usan la misma marca
   vertical que el submenú: es la forma que ya tiene la casa de decir «estás
   aquí». */
.pant-tabs {
  display: flex; gap: var(--s5); align-items: flex-end;
  padding-bottom: var(--s3); margin-bottom: var(--s4);
  border-bottom: var(--linea) solid var(--ink);
}
.pant-tab {
  position: relative; padding: 0 0 var(--s2); border: 0; background: none;
  cursor: pointer; text-align: left; color: var(--dim); font: inherit;
  font-size: var(--t-ui);
}
.pant-tab i {
  display: block; font-style: normal;
  font-size: var(--t-drop); letter-spacing: var(--tr-micro);
  text-transform: uppercase; opacity: .7;
}
.pant-tab.is-on { color: var(--ink); }
.pant-tab.is-on::after {
  content: ""; position: absolute; left: 0; bottom: calc(var(--s3) * -1 - 2px);
  width: 100%; height: var(--linea); background: var(--ink);
}
@media (hover: hover) { .pant-tab:hover { color: var(--ink); } }

@media (max-width: 700px) {
  .pant-tabs { gap: var(--s4); overflow-x: auto; }
}

/* ---------- Projects: excepción de cuerpo -------------------------------------
   Las celdas de Projects van a 14px, no a los 20 del resto de la web.

   Aquí hay mucha más densidad que en ninguna otra pantalla —nombre de marca,
   grupo, recuentos, notas, fecha, y una fila de caras por campaña— y a 20px
   cada dato pide una línea propia.

   Se hace redefiniendo los tokens dentro del bloque en vez de tocando regla
   por regla: todo lo que hay dentro los hereda, y el día que cambie el cuerpo
   general esta excepción sigue siendo una sola cifra. */
.marco {
  --t-ui:   14px;
  --t-drop: 14px;
  --t-menu: 14px;
}

/* ============ Landing pública ================================================
   Ritmo de pantallas, no una pila de secciones. Cada tramo ocupa la vista
   entera: tipografía plantada, retícula que se atraviesa, palabras sueltas
   con su párrafo diminuto, un panel que invade, y el cierre.

   Todo el movimiento sale de `--p`, que el script publica en cada tramo con
   lo recorrido de 0 a 1. Aquí sólo se decide qué hace ese número. */

body.landing { margin: 0; background: var(--bone); }

/* La landing usa la cabecera de la web —`.head`, `.head__logo`,
   `.head__nav`— y no una propia. Tuvo una: fija, translúcida y con
   desenfoque por debajo. Funcionaba, pero era un segundo lenguaje de
   navegación para el mismo sitio.

   Aquí sólo queda lo que cambia: sin círculo de cuenta, porque nadie ha
   entrado todavía, y el hueco de la cabecera lo reserva ya el flujo. */
.landing .head__right { display: flex; align-items: center; }


/* ---- 1 · Portada ---- */
/* La portada: un vídeo de fondo y dos líneas encima.

   El vídeo va a 16:9 ajustado al ancho, así que la ALTURA DE LA PORTADA LA
   MARCA EL VÍDEO, no la ventana. Es lo que se pidió y tiene consecuencia:
   ya no es una pantalla completa: es el encuadre entero, sin recortar. En
   pantallas apaisadas normales eso queda muy cerca del alto de ventana; en
   una muy ancha, algo más bajo. A cambio no se pierde nada del plano.

   Tuvo un titular de tres líneas sobre hueso y una entradilla debajo. */
.lp-hero {
  position: relative;
  width: 100%; aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--bone);
}

.lp-hero__fondo { position: absolute; inset: 0; }

.lp-hero__poster,
.lp-hero__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; display: block;
}

/* El póster aguanta hasta que el vídeo tiene un fotograma que enseñar. Si se
   retirase al empezar la descarga habría un hueco vacío en la primera
   pantalla, que es la que no puede fallar. */
.lp-hero__fondo.es-video .lp-hero__poster { opacity: 0; }
.lp-hero__poster { transition: opacity .6s ease; }

/* Los dos vídeos se solapan y sólo uno está visible. El relevo es un fundido
   de uno a otro: con un solo elemento habría un parpadeo negro en cada
   cambio, porque cambiar el `src` vacía el fotograma. */
.lp-hero__video { opacity: 0; transition: opacity 1.2s ease; }
.lp-hero__video.es-on { opacity: 1; }

/* En un teléfono, 16:9 al ancho son unos doscientos píxeles de alto: el
   titular no cabe. Ahí sí cubre la pantalla y se recorta el plano, que es el
   menor de los dos males. */
@media (max-width: 860px) {
  .lp-hero { aspect-ratio: auto; min-height: 100svh; }
}

.lp-baja {
  position: absolute; bottom: var(--s5); left: var(--s5);
  font-size: var(--t-drop); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--dim);
}

/* ---- Tramos con recorrido ---- */
.lp-recorrido { height: 210vh; }
/* El tramo del panel que crece. Más largo que el normal a propósito: ahí
   pasan dos cosas seguidas —el panel se abre y después entra el rótulo—, y el
   rato de lectura del final sale de esta altura. */
.lp-recorrido--corto { height: 330vh; }
/* El renglón de «How we work» mide varias pantallas de ancho: con el
   recorrido normal cruzaría demasiado deprisa para leerlo. */
.lp-recorrido--largo { height: 420vh; }
.lp-tira, .lp-crece { position: relative; }
.lp-tira__fijo, .lp-crece__fijo {
  position: sticky; top: 0; height: 100vh; overflow: hidden;
}

/* ---- 2 · La tira lateral ----
   Al bajar, las piezas cruzan de derecha a izquierda. Cada una va a toda la
   altura y a su proporción real: no se recorta nada, que es lo que pedía este
   material —todas las piezas son apaisadas y una cara cortada no vende—.

   El desplazamiento sale en CSS puro: `100%` del carril es su ancho de
   contenido, así que `100vw - 100%` es exactamente lo que sobra por recorrer.
   No hace falta medir nada desde el script. */
/* La banda es 16:9 al ancho, la misma medida que la portada. Tuvo el alto de
   la ventana con fondo negro y las piezas flotando dentro, y ese negro era un
   marco que no pinta nada: la web es hueso, y una caja negra a media bajada
   se lee como si faltara algo por cargar. */
.lp-tira__fijo {
  /* Pegada POR DEBAJO de la cabecera, no debajo del todo. La cabecera también
     es pegajosa y va por encima: con `top: 0` se comía la franja alta de las
     fotos. */
  top: var(--head-h);
  height: auto; aspect-ratio: 16 / 9;
  display: flex; align-items: stretch;
  /* Para que el carril pueda medir el recorrido contra ESTE ancho y no
     contra `100vw`, que incluye la barra de desplazamiento: con `100vw` la
     última pieza se quedaba una quincena de píxeles sin llegar al borde. */
  container-type: inline-size;
}

/* Las piezas se tocan y llegan a los dos bordes: ni separación ni margen
   lateral. El carril es una sola imagen larga partida en dos, no dos fotos
   colocadas juntas.

   El recorrido sigue saliendo de CSS puro: `100%` del carril es su ancho de
   contenido, así que `100vw - 100%` es exactamente lo que sobra por cruzar.
   Nada que medir desde el script. */
.lp-tira__carril {
  display: flex; gap: 0;
  width: max-content; padding: 0;
  transform: translateX(calc(var(--p, 0) * (100cqw - 100%)));
  will-change: transform;
}
/* Cada pieza mide EXACTAMENTE una banda. Es lo que hace que la cuenta salga
   redonda: con dos piezas el carril mide dos bandas y el recorrido es una
   justa, así que la segunda termina pegada al borde derecho y no a medias.

   Antes las imágenes iban a `width: auto` y mandaban su proporción. Suena
   mejor —no se recorta nada— pero ata la geometría del tramo a lo que mida
   cada fichero: `cerca-4` es cuadrada, así que la segunda pieza ocupaba poco
   más de media banda y el carril nunca llegaba a cruzar lo que parecía que
   tenía que cruzar. Y `width: max-content` empeoraba la mezcla, porque mide
   el ancho NATIVO del fichero, no el que acaba dibujándose. */
.lp-tira__carril figure {
  margin: 0; flex: none;
  width: 100cqw; height: 100%;
  overflow: hidden;
}
/* `fill` y no `cover`: las piezas ya vienen exportadas al fotograma que se
   quiere ver. Con `cover`, el navegador volvería a recortar lo que ya está
   encuadrado, y en un grupo de caras ese recorte se come a alguien. Si algún
   día entra una pieza que no sea 16:9, se deformaría —el aviso queda aquí. */
.lp-tira__carril img {
  width: 100%; height: 100%;
  object-fit: fill; display: block;
}

/* En estrecho, 16:9 al ancho es una tira demasiado baja para que se lea nada.
   Ahí recupera altura, aunque signifique que las piezas asomen menos. */
/* En un teléfono, la tira deja de cruzar y se apila.

   Cruzando, cada pieza medía el ancho de la pantalla por el alto de la banda,
   y como las imágenes van a `fill` —encuadradas ya al exportarlas— salían
   estiradas. Además el recorrido pedía dos pantallas y media de scroll para
   una banda de doscientos píxeles.

   Apiladas se ven enteras, a su proporción y a tamaño decente. Se pierde el
   gesto, que en horizontal necesita ancho que aquí no hay. */
/* En estrecho la tira SIGUE CRUZANDO. Se probó a apilarla y perdía el gesto,
   que es lo único que hace esa sección.

   Lo que estaba mal no era el cruce sino la proporción: le quité el 16:9 y le
   puse alto fijo, y como las imágenes van a `fill` —encuadradas ya al
   exportarlas— salían estiradas. Con el 16:9 puesto, cruzan sin deformarse.
   La banda queda baja en un teléfono; es el precio de no recortar. */
/* En vertical la banda ocupa la pantalla entera, no una franja de 16:9.

   A 16:9 sobre un móvil salían doscientos píxeles de imagen y el resto hueso
   vacío. Aquí manda el alto: la banda llena lo que queda bajo la cabecera y
   cada pieza conserva su 16:9, así que sale MÁS ANCHA que la pantalla. Eso es
   justo lo que le da sentido al cruce en un teléfono: se recorre una imagen
   grande de lado a lado en vez de mirar una postal. */
@media (max-width: 860px) {
  .lp-tira__fijo {
    aspect-ratio: auto;
    height: calc(100svh - var(--head-h));
  }
  /* El ancho, escrito y no deducido. Con `width: auto` más `aspect-ratio`, el
     navegador tiene que saber el alto para calcular el ancho, y el alto venía
     en porcentaje del carril, cuyo ancho es `max-content`: circular. El
     carril salía con un ancho mal calculado y el recorrido no cuadraba.

     Aquí el ancho se dice: el alto de la banda por 16/9. Misma proporción,
     pero sin que dependa de nada que esté por resolverse. */
  .lp-tira__carril figure {
    width: calc((100svh - var(--head-h)) * 16 / 9);
    height: 100%; aspect-ratio: auto;
  }
  .lp-tira .lp-recorrido { height: 190vh; }
}

/* ---- 3 · Fragmentos ----
   Palabra grande, párrafo diminuto y una pieza al lado. Estuvieron solos
   sobre el fondo y la página se quedaba en blanco entre uno y otro: el texto
   manda, pero necesita suelo. */
/* La cabecera ocupa su sitio en el flujo, así que no hace falta reservarlo. */
.lp-frags { padding: var(--s8) var(--s5); }
/* Arriba y no centrado: el titular tiene que arrancar a la misma altura que
   la foto. Centrado, cada bloque se colocaba según lo largo que fuera su
   párrafo, y las tres parejas empezaban a alturas distintas.

   `start` alinea el borde de la caja del texto, pero lo que se ve arrancar
   es la letra, y encima de ella hay un hueco: la diferencia entre el alto de
   línea y el alto real del carácter. Ese hueco se descuenta más abajo. */
.lp-frag {
  display: grid; grid-template-columns: minmax(0, 42%) minmax(0, 1fr);
  align-items: start; gap: var(--s6);
  margin-bottom: 18vh;
  opacity: 0; transform: translateY(22px);
  transition: opacity .8s ease, transform .8s cubic-bezier(.2,.7,.3,1);
}
.lp-frag.visto { opacity: 1; transform: none; }
.lp-frag:last-child { margin-bottom: 0; }
/* Alterna el lado: el mismo reparto tres veces seguidas se lee como una
   tabla, no como un ritmo.

   Y se invierten TAMBIÉN las columnas, no sólo el orden de las piezas. Con
   `order` a secas, la primera columna seguía midiendo 42% y la segunda 1fr,
   así que en las filas invertidas la imagen caía en la columna estrecha y el
   texto en la ancha: las fotos salían de dos tamaños distintos según la
   fila. El texto siempre en la estrecha, la imagen siempre en la ancha. */
.lp-frag--der { grid-template-columns: minmax(0, 1fr) minmax(0, 42%); }
.lp-frag--der .lp-frag__txt { order: 2; text-align: right; }
.lp-frag--der .lp-frag__im  { order: 1; }

/* La misma medida que «This is FACES.» y que «Built from nothing.»: los
   titulares grandes de esta página miden todos lo mismo. Estaba un tercio
   por encima.

   El margen negativo de arriba sube la caja para que la MAYÚSCULA quede a
   ras de la foto. Con `line-height: .84` sobra algo menos de la mitad de la
   diferencia hasta 1, y eso es lo que se descuenta. */
.lp-frag h2 {
  /* El margen negativo sube la caja para que la MAYÚSCULA quede a ras de la
     foto. Va con la interlínea: al pasar de .84 a .92 la caja crece, y con
     ella el hueco sobre la letra, así que hay que descontar más. */
  margin: -.12em 0 var(--s5);
  font-size: clamp(30px, 7vw, 104px); font-weight: 500;
  letter-spacing: -.04em; line-height: .92;
}
/* Cuerpo de lectura, no letra pequeña. La palabra sigue siendo el mensaje
   por tamaño y peso; el párrafo no tiene por qué esconderse para que se note.
   Y en caja baja: una versalita de tres líneas se lee peor que la misma
   frase en redonda. */
.lp-frag p {
  margin: 0; max-width: 30ch;
  font-size: 24px; line-height: 1.45; letter-spacing: -.005em;
}
.lp-frag--der p { margin-left: auto; }
/* Las tres con la misma forma. Los ficheros vienen a 1.79, 1.55 y 1.24, y a
   proporción natural cada foto salía de un alto distinto: el bloque se leía
   descuadrado aunque las columnas fueran iguales.

   3:2 porque es la que menos violenta a las tres: la de 1.55 casi no se
   toca, a la panorámica se le quitan los lados y a la vertical algo de
   arriba y abajo. */
.lp-frag__im { margin: 0; overflow: hidden; aspect-ratio: 3 / 2; }
.lp-frag__im img {
  width: 100%; height: 100%; display: block;
  /* Alto: al recortar un grupo, el centro geométrico cae por los cuerpos y
     deja las caras fuera. */
  object-fit: cover; object-position: 50% 32%;
}

/* ---- 4 · El panel que invade ---- */
.lp-crece__fijo { display: grid; place-items: center; background: var(--bone); }
/* El panel termina de abrirse en el 75% del recorrido, no al final. El cuarto
   que queda es lo que le da sitio al rótulo: si la apertura ocupara el tramo
   entero, el texto tendría que aparecer a la vez que crece —que es lo que
   hacía— o quedarse para un instante en el que la sección ya se está yendo.

   `min()` corta la cuenta en 1: a partir de ahí el panel ya está entero y
   deja de moverse. */
.lp-panel {
  --e: min(1, calc(var(--p, 0) / .75));
  position: relative; margin: 0; overflow: hidden;
  width: calc(26vw + 74vw * var(--e));
  height: calc(42vh + 58vh * var(--e));
  will-change: width, height;
}
/* Encuadre alto y centrado: al recortar un grupo, el centro geométrico cae
   por los cuerpos y deja las caras fuera. Lo decide el panel; el valor de
   aquí es la red por si la página se sirviera sin sustituir.

   Este recorte no tiene una proporción fija: el panel crece desde 26vw×42vh
   hasta la ventana entera, así que cuánto se recorta —y por dónde— depende
   del tamaño de la pantalla. En una ventana más alta que 16:9 corta por los
   lados; en una más apaisada, por arriba y abajo.

   Por eso hay dos encuadres y no uno. En un teléfono la pieza acaba en 9:19 y
   no existe un punto que sirva para las dos formas: lo que en apaisado sobra
   por arriba, en vertical sobra por los lados.

   El atributo `style` de la página no puede llevar media queries, así que no
   escribe la propiedad sino dos variables, y es aquí donde se elige cuál. */
.lp-panel img {
  width: 100%; height: 100%; display: block;
  object-fit: cover; object-position: var(--foco, 50% 30%);
}
/* El margen de arriba descuenta la cabecera. Es pegajosa y va por encima de
   todo, así que un rótulo a `--s5` del borde del panel queda debajo de ella y
   no se puede leer. Abajo no pasaba; al subirlo, sí. */
.lp-panel__t {
  position: absolute; left: var(--s5); top: calc(var(--head-h) + var(--s5));
  /* Negro, como la portada y como el resto de la web. La sombra es clara y
     muy abierta: no se ve, sólo separa la letra si detrás cae algo oscuro.
     Ojo al cambiar esta foto —aquí la esquina alta es cielo claro; sobre un
     plano oscuro habría que volver al blanco. */
  color: var(--ink);
  text-shadow: 0 2px 40px rgba(255,255,255,.35);
  font-size: clamp(30px, 7vw, 104px); font-weight: 500;
  letter-spacing: -.04em; line-height: .92;
  /* Entra con el panel ya abierto del todo, no mientras crece: empezaba en el
     45% del recorrido y el rótulo se leía encima de un encuadre que todavía
     se movía.

     Arranca en el 75% —justo cuando el panel termina— y llega al 100% de
     opacidad en el 82%. Ese 18% que queda es el rato de leerlo: antes llegaba
     al 89% y sólo había un 11%, así que aparecía y se iba con el scroll sin
     dar tiempo. */
  opacity: calc((var(--p, 0) - .75) * 14);
}

/* ---- 5 y 6 · Afirmaciones ---- */
.lp-dicho { min-height: 100vh; display: flex; flex-direction: column; justify-content: center;
  padding: var(--s8) var(--s5); }
.lp-dicho--oscuro { background: var(--ink); color: var(--bone); }
.lp-dicho__cab {
  margin: 0 0 var(--s5);
  font-size: var(--t-ui); letter-spacing: var(--tr-micro);
  text-transform: uppercase; color: var(--off);
}
.lp-dicho__t {
  margin: 0 0 var(--s6);
  font-size: clamp(46px, 10vw, 150px); font-weight: 500;
  letter-spacing: -.045em; line-height: .88;
}
.lp-dicho__pie { display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); gap: var(--s6); }
.lp-dicho__pie p {
  margin: 0; max-width: 38ch;
  font-size: 24px; line-height: 1.45; letter-spacing: -.005em;
}

[data-revela] { opacity: 0; transform: translateY(20px);
  transition: opacity .8s ease, transform .8s cubic-bezier(.2,.7,.3,1); }
[data-revela].visto { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  [data-revela] { opacity: 1; transform: none; transition: none; }
}

.lp-pie {
  display: flex; align-items: center; gap: var(--s5); flex-wrap: wrap;
  padding: var(--s5);
  border-top: var(--linea) solid var(--ink);
  font-size: var(--t-drop); color: var(--dim);
}
.lp-pie nav { margin-left: auto; display: flex; gap: var(--s5); }
.lp-pie a { color: var(--ink); }

/* Los fragmentos, uno debajo de otro. En dos columnas, la del texto medía un
   42% —unos 160px en un teléfono— y el párrafo salía en columna de periódico
   de dos palabras por línea. Y la imagen primero: al apilarse, entra antes la
   pieza y después lo que la explica. */
@media (max-width: 860px) {
  .lp-frag, .lp-frag--der { grid-template-columns: 1fr; gap: var(--s5); }
  .lp-frag .lp-frag__txt, .lp-frag--der .lp-frag__txt { order: 2; text-align: left; }
  .lp-frag .lp-frag__im,  .lp-frag--der .lp-frag__im  { order: 1; }

  .lp-zoom__malla { width: 210vw; gap: var(--s2); }
  .lp-panel { width: calc(64vw + 36vw * var(--p, 0)); }

  /* Las dos piezas que acaban llenando la ventana usan aquí su propio
     encuadre. Si no se ha puesto ninguno, cae al de escritorio y de ahí al
     de la hoja: nunca se queda sin valor. */
  .lp-panel img   { object-position: var(--foco-m, var(--foco, 50% 30%)); }
  .lp-cierre__im  { object-position: var(--foco-m, var(--foco, 50% 22%)); }
  .lp-frag { margin-bottom: 22vh; }
  .lp-pie nav { margin-left: 0; width: 100%; }
}


@media (max-width: 860px) {
  .lp-frag p, .lp-dicho__pie p { font-size: 20px; }
}


/* La cabecera de la landing en estrecho.

   En el catálogo, el menú y el botón se esconden tras el desplegable. En la
   landing el botón se queda —es la única puerta— y ahí «Client access» no
   cabe en una línea: partía en dos y se salía de la barra, que tiene altura
   fija. Se le prohíbe partir y se estrecha lo justo. */
@media (max-width: 700px) {
  .landing .head__right { margin-left: auto; }
  .landing .head__right .btn {
    white-space: nowrap;
    height: 36px; padding: 0 var(--s4);
    font-size: var(--t-drop); border-radius: 18px;
  }
}

/* ---------- El ticker -------------------------------------------------------

   Una banda que cruza sin parar entre la portada y la tira. Filete arriba y
   abajo, y nada más: no es una sección, es una junta entre dos.

   El truco del bucle: el texto va repetido un número PAR de veces y el carril
   se desplaza justo la mitad de su ancho. Al llegar ahí, la segunda mitad
   está exactamente donde estaba la primera, así que al reiniciar no se ve el
   salto. Si se cambia el número de repeticiones, tiene que seguir siendo par.

   Va con animación propia y no con el recorrido de la página: un ticker se
   mueve solo, no porque alguien baje. */

.lp-ticker {
  overflow: hidden;
  padding: var(--s4) 0;
  border-top: var(--linea) solid var(--ink);
  border-bottom: var(--linea) solid var(--ink);
  background: var(--bone);
}

/* La duración la escribe la función desde lo guardado en el panel; el 38 de
   aquí es la reserva por si llegara sin valor. */
.lp-ticker__carril {
  display: flex; width: max-content;
  animation: ticker var(--vuelta, 38s) linear infinite;
}
/* Hacia la derecha: la misma animación al revés. Se invierte el sentido en
   vez de escribir un segundo juego de fotogramas. */
.lp-ticker__carril.es-derecha { animation-direction: reverse; }

/* La medida del titular de la portada. */
/* El `h1` de la página vive aquí, así que hay que anular su margen. */
.lp-ticker__t {
  flex: none; margin: 0;
  padding-right: .32em;
  font-size: clamp(30px, 7vw, 104px); font-weight: 500;
  letter-spacing: -.04em; line-height: .92;
  white-space: nowrap;
}

@keyframes ticker {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Quien pide menos movimiento se queda con la banda quieta: la frase se lee
   igual, que es de lo que se trata. */
@media (prefers-reduced-motion: reduce) {
  .lp-ticker__carril { animation: none; }
}

/* ---------- «How we work»: las frases en persiana --------------------------

   Tres frases apiladas, cada una ocupando el ancho entero: la letra es más
   grande cuanto más corta es la frase. Se descubren una detrás de otra según
   se baja, y los dos subtextos entran al final y cierran la pieza.

   Pasó por fondo negro con diez caras al lado, por texto montándose letra a
   letra, por dos renglones en paralelo, por un renglón horizontal, por una
   columna subiendo y por una onda. Los cinco primeros compartían el mismo
   error: el texto entraba desde fuera de pantalla y pasaba más tiempo roto
   que legible. Aquí cada frase aparece ya compuesta y no se mueve más.

   Fondo rosa, el de la casa. */

.lp-comose { position: relative; }
.lp-comose__fijo {
  position: sticky; top: 0; min-height: 100svh;
  display: flex; flex-direction: column; justify-content: center;
  padding: var(--s8) var(--s5);
  background: var(--pink);
}

/* Apretadas: son un bloque, no tres titulares sueltos. */
.lp-comose__lineas { display: flex; flex-direction: column; }

/* El cuerpo lo escribe el script, que es quien puede medir el texto. Lo de
   aquí es la reserva por si no llega a ejecutarse. */
.lp-comose__t {
  margin: 0;
  font-size: clamp(30px, 7vw, 104px); font-weight: 500;
  letter-spacing: -.04em;
  /* Interlínea cerrada: las líneas casi se tocan. Estuvo por encima de 1
     mientras la persiana recortaba los rabos de las «g», pero eso se resolvió
     agrandando la caja del recorte —el relleno de aquí abajo—, no separando
     las líneas. Apretado es lo que convierte cuatro frases sueltas en un
     bloque. */
  line-height: .92;
  white-space: nowrap;

  /* El relleno de abajo, y el margen negativo que lo compensa.

     `clip-path` recorta a la caja del elemento, y el rabo de la «g» de
     «photography» sobresale de esa caja: por muy separadas que estén las
     líneas, la persiana se lo cortaba igual. El relleno agranda la caja del
     recorte lo justo para que quepa el trazo, y el margen negativo devuelve
     el hueco para que la composición no se mueva. */
  padding-bottom: .24em;
  margin-bottom: -.24em;

  /* La persiana: la frase se descubre de abajo arriba. `--r` es lo que lleva
     abierta esta línea, de 0 a 1, y su turno lo da `--i`. Cada una tarda un
     octavo del recorrido y arrancan escalonadas. */
  --r: clamp(0, calc((var(--p, 0) - var(--i, 0) * .16) * 8), 1);
  clip-path: inset(calc((1 - var(--r)) * 100%) 0 0 0);
}
.lp-comose__t:nth-child(2) { --i: 1; }
.lp-comose__t:nth-child(3) { --i: 2; }
.lp-comose__t:nth-child(4) { --i: 3; }

/* En estrecho no se ajusta al ancho: cuatro líneas de 27 caracteres metidas
   en 350px salen a 24px, que para una afirmación a pantalla completa es
   letra de pie de página. Se dejan partir en varias líneas y el cuerpo lo
   pone el `clamp`. El script no toca el tamaño por debajo de este ancho. */
@media (max-width: 860px) {
  .lp-comose__fijo { padding: var(--s7) var(--s5); }
}

/* Sin movimiento, todo abierto y visible desde el primer momento. */
@media (prefers-reduced-motion: reduce) {
  .lp-comose__t { clip-path: none; }
}

/* ---------- La puerta: de la página pública al acceso ---------------------

   `bienvenida.html` y `entrar.html` son las dos únicas páginas del sitio que
   están enteras en el HTML: ni una sola parte se pinta con JavaScript. Por
   eso aquí sí funciona lo que se abandonó dentro del catálogo —allí el
   navegador no tenía nada que fotografiar en el primer fotograma y descartaba
   la transición sin avisar.

   La activación va página a página, con un `@view-transition` en el `<head>`
   de cada una. No se pone en esta hoja a propósito: es una regla de
   documento, no de selector, y puesta aquí la heredarían el catálogo y los
   proyectos, que sí se pintan con JavaScript. Volvería el problema.

   Todo se funde y nada se desplaza. El logotipo llegó a viajar de la esquina
   de la cabecera hasta el centro de la caja, y el recorrido en diagonal
   llamaba más la atención que el cambio de página: el ojo seguía al
   logotipo en vez de darse cuenta de que había llegado al acceso. Ahora se
   apaga donde estaba y aparece donde toca.

   Para eso hace falta justamente NO emparejarlo. Un `view-transition-name`
   compartido es lo que le dice al navegador «esto de aquí y esto de allí son
   la misma cosa, llévala de un sitio al otro». Sin nombre, cada logotipo se
   queda dentro de la fotografía a la que pertenece —el del menú en el fondo
   que sale, el de la isla en la caja que entra— y cada uno se funde con
   ella.                                                                    */

/* La caja no viene de ningún sitio de la landing, así que no se empareja con
   nada: entra sola. */
body.entrar .entrar__caja { view-transition-name: puerta; }

/* El fondo entero: la cabecera con su logotipo se va, y detrás aparecen el
   rosa y la tira de caras. */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: .40s;
  animation-timing-function: ease;
}

/* La isla aparece y desaparece, sin crecer ni encoger. Tuvo un `scale` de
   fondo, y era el mismo error en pequeño: un movimiento que no significaba
   nada compitiendo con el que sí. Entra algo más lenta que el fondo, para
   que se lea como que aparece encima y no a la vez. */
::view-transition-new(puerta) { animation: puerta-abre .46s ease both; }
::view-transition-old(puerta) { animation: puerta-cierra .26s ease both; }
@keyframes puerta-abre  { from { opacity: 0; } to { opacity: 1; } }
@keyframes puerta-cierra { to { opacity: 0; } }

/* Quien pide menos movimiento sigue teniendo el cambio de página, pero
   instantáneo. No se puede quitar la transición a medias: o se anima o se
   corta, y cortar es lo que esa preferencia pide. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation-duration: 1ms !important; }
}


/* ---------- Contacto: el cierre de la página pública ----------------------

   El bloque de cierre deja de ser una afirmación a pantalla completa y pasa
   a ser dos cosas a la vez: la frase grande a la izquierda y el formulario a
   la derecha. Apilados no cabían —el titular solo ya mide 150px— y el
   formulario quedaba debajo del pliegue, que es exactamente donde no sirve.

   Los campos son los mismos de `.envio`: la píldora de 44px del diálogo de
   compartir y la caja de mensaje con el radio de la casa. Ninguna forma
   nueva. Sin rótulos encima, como en `entrar.html`: es la otra puerta
   pública del sitio y las dos tienen que leerse igual. El nombre del campo
   viaja en `aria-label`, así que el lector de pantalla lo sigue anunciando
   aunque al escribir desaparezca el marcador de posición.                 */

/* El cierre de la landing vuelve a ser lo que era: la frase y una puerta.
   La rejilla de dos columnas se ha ido con el formulario a su página. */
/* ---------- El cierre: la imagen a sangre con la frase encima ---------------

   La imagen iba suelta sobre el cierre, sin llegar a los bordes, y la frase
   debajo sobre el hueso: dos piezas contando lo mismo con una costura en
   medio. Juntas son un solo remate.

   La foto es cuadrada —2048×2048— y aquí ocupa el ancho entero, así que se
   recorta por arriba y abajo. El encuadre lo decide el panel: al recortar un
   grupo, el centro geométrico cae por los cuerpos y deja las caras fuera, y
   cuánto hay que subir depende de la foto que haya puesta.

   El 22% que queda abajo es sólo la red: la página llega con su encuadre
   escrito en el atributo y ése manda. Sirve por si alguna vez se sirviera
   sin sustituir. */
.lp-cierre {
  position: relative;
  min-height: 100svh;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: var(--s8) var(--s5);
  overflow: hidden;
  background: var(--ink);
}
.lp-cierre__im {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: var(--foco, 50% 22%);
  display: block;
}

/* Un asiento oscuro sólo en la franja de abajo. El titular estaba a media
   altura, que es donde están las caras: por grande que sea la sombra, texto
   blanco encima de un rostro se lee sucio y tapa lo que la página vende.

   Abajo hay cuerpos y pared, no caras. El degradado muere antes de la mitad,
   así que la parte alta de la foto se ve limpia. */
.lp-cierre::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: 62%;
  background: linear-gradient(to top,
    rgba(0,0,0,.62) 0%, rgba(0,0,0,.34) 42%, rgba(0,0,0,0) 100%);
}

/* En blanco, con la misma sombra ancha y suave que el resto de titulares
   sobre foto de esta página: no se ve como sombra, sólo despega la letra si
   el plano es claro. */
/* Encima del asiento. */
.lp-cierre__txt { position: relative; z-index: 1; }

/* A la escala de los otros dos titulares que van sobre foto en esta página:
   la portada y «Born from imagination.». Estaba en la de los titulares sobre
   fondo liso —un tercio más grande— y a ese tamaño ocupaba la franja de las
   caras hiciera lo que hiciera. */
.lp-cierre .lp-dicho__t {
  margin-bottom: var(--s5);
  font-size: clamp(30px, 7vw, 104px);
  letter-spacing: -.04em; line-height: .92;
  color: var(--white);
  text-shadow: 0 2px 40px rgba(0,0,0,.38);
}
.lp-cierre__cta { align-self: flex-start; }

/* ---------- La página de contacto ------------------------------------------

   Una columna centrada y nada más. Pasó por dos columnas con el formulario
   pegado al borde derecho, y después por una retícula de celdas con fotos y
   bloques de color. Las dos sobraban por el mismo motivo: en una página cuyo
   único trabajo es recoger un mensaje, todo lo que no es el mensaje compite
   con él.

   La estructura es la de cualquier pantalla del panel —`.page` con su
   cabecera— y los campos son los de la casa. Ninguna forma nueva.

   El ancho se acota a 1040px, que es el mismo tope que usa el panel: por
   encima, una línea de texto cruza la pantalla y el ojo pierde dónde
   empieza la siguiente.

   Y va centrado en los dos ejes. En horizontal con márgenes automáticos; en
   vertical dejando que este bloque se coma el espacio que sobra entre la
   cabecera y el pie —el cuerpo ya es una columna flexible de alto de
   ventana— en vez de calcular a mano la altura de las dos. Sin esto, el
   formulario se apelotonaba arriba a la izquierda con media pantalla vacía
   debajo.

   `safe center` y no `center` a secas: si la ventana es más baja que el
   formulario, centrar recorta por arriba y el título deja de alcanzarse.
   Con `safe`, en ese caso se apoya arriba y se puede leer entero. */
.pg-contacto {
  width: 100%; max-width: 1040px;
  margin-inline: auto;
  flex: 1 1 auto;
  display: flex; flex-direction: column; justify-content: safe center;
  padding-top: var(--s8);
  padding-bottom: var(--s8);
}
.pg-contacto__p {
  margin: 0 0 var(--s7); max-width: 52ch;
  font-size: 24px; line-height: 1.45; letter-spacing: -.005em;
}

/* El tope de caracteres, dicho antes de chocarse con él. Es lo único que me
   llevo del referente además de la estructura: sin avisar, quien escriba de
   más descubre el límite cuando el campo deja de responder. */
.lp-form__tope {
  margin: calc(var(--s1) * -1) 0 0;
  font-size: var(--t-drop); color: var(--off);
}

/* A todo el ancho, como el botón de la página de acceso. Es la única acción
   de la pantalla: no hay nada de lo que tenga que diferenciarse por tamaño,
   y un botón pequeño al final de una columna larga se busca. */
.lp-form__enviar { width: 100%; margin-top: var(--s4); }


.lp-form { display: flex; flex-direction: column; gap: var(--s3); }
.lp-form__par { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); }

/* El desplegable se queda en 32px por la regla del panel, donde convive con
   barras de herramientas. Aquí va en fila con dos píldoras de 44 y tiene que
   medir lo mismo: dos alturas en la misma línea se leen como un error. */
.lp-form select.envio__para { height: 44px; }

.lp-form .envio__msg { min-height: 128px; }

/* Ni oculto con `display:none` ni fuera de pantalla con `position:absolute`:
   lo primero hace que algunos programas lo ignoren —y entonces no atrapa
   nada— y lo segundo lo deja alcanzable con el tabulador. Ocupa cero y no
   recibe foco. */
.lp-form__trampa {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

.lp-form__ok {
  display: flex; align-items: flex-start; gap: var(--s3);
  margin-top: var(--s2); cursor: pointer;
  font-size: var(--t-drop); line-height: 1.4;
}
.lp-form__ok input {
  flex: none; width: 22px; height: 22px; margin: 1px 0 0;
  accent-color: var(--ink); cursor: pointer;
}


.lp-form__nota {
  margin: 0; max-width: 46ch;
  font-size: var(--t-drop); line-height: 1.45; color: var(--off);
}
.lp-form__nota a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

/* Al mandarse, el formulario se sustituye por el acuse. Se cambia lo que
   había en vez de añadir un mensaje debajo: dejar los campos rellenos
   invita a volver a darle, y el segundo mensaje ya no lo lee nadie. */
.lp-gracias { padding: var(--s6) 0; }
.lp-gracias h3 {
  margin: 0 0 var(--s3);
  font-size: var(--t-h2); font-weight: 500; letter-spacing: -.015em; line-height: 1.1;
}
.lp-gracias p { margin: 0; font-size: 24px; line-height: 1.45; color: var(--dim); }


@media (max-width: 560px) {
  .lp-form__par { grid-template-columns: 1fr; }
}



/* ---------- Páginas legales -------------------------------------------------

   Términos y privacidad. Son documentos para leer, no para sobrevivir, así
   que la medida se acota a 68 caracteres: es lo que el ojo recorre sin
   perder dónde empieza la línea siguiente, y es la diferencia real entre un
   texto legal que se lee y uno que se acepta sin mirar.

   Sin componentes nuevos: la estructura es `.page` con su cabecera, como
   cualquier otra pantalla. */
.legal { max-width: 68ch; }
.legal__fecha {
  margin: calc(var(--s5) * -1) 0 var(--s6);
  font-size: var(--t-drop); color: var(--off);
}
.legal__entrada { font-size: 24px; line-height: 1.45; margin: 0 0 var(--s7); }

.legal h2 {
  margin: var(--s7) 0 var(--s3);
  font-size: var(--t-h2); font-weight: 500;
  letter-spacing: -.015em; line-height: 1.15;
}
.legal h3 {
  margin: var(--s6) 0 var(--s2);
  font-size: var(--t-ui); font-weight: 500;
}
.legal p, .legal li { line-height: 1.55; }
.legal p { margin: 0 0 var(--s4); }
.legal ul { margin: 0 0 var(--s4); padding-left: var(--s5); }
.legal li { margin-bottom: var(--s2); }
.legal a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

.legal__ver {
  margin-top: var(--s7); padding-top: var(--s5);
  border-top: var(--linea) solid var(--rule);
  color: var(--off);
}

/* La identificación de la sociedad. Va en bloque y no corrida dentro del
   párrafo: es el dato que alguien viene a buscar —para una factura, para una
   reclamación— y en medio de una frase se pierde. */
.legal__ident { display: block; line-height: 1.5; }

/* Las dos aceptaciones van juntas y la de novedades aparte. Pegadas a las
   otras, la opcional se lee como un tercer requisito y se marca sin querer,
   y un consentimiento de marketing marcado por inercia no vale. */
.lp-form__oks { display: flex; flex-direction: column; gap: var(--s2); }
.lp-form__ok--suelta { margin-top: var(--s4); }
.lp-form__ok a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }


/* ---------- Site: contenido de las páginas públicas -------------------------

   Sin formas nuevas: los campos son la píldora de `.envio` y la parrilla de
   tomas es `.grid` con `.tile`, la misma del catálogo. Elegir una cara aquí
   se ve igual que verla en Talents, que es donde se ha visto siempre.

   El primer intento metía la imagen dentro de `.cara` a pelo, y `.cara` es
   sólo el envoltorio: la proporción y el recorte viven en `.cara__img`. Sin
   ese hijo, las fotos salían a tamaño natural unas encima de otras.       */

.pub-campos {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4);
  margin-bottom: var(--s6);
  max-width: 720px;
}
.pub-campo { display: grid; gap: var(--s2); }
.pub-campo__et { font-size: var(--t-drop); color: var(--off); }

.pub-sub {
  margin: 0 0 var(--s4);
  padding-bottom: var(--s3);
  border-bottom: var(--linea) solid var(--rule);
}

/* Seis por fila: son tomas para reconocer de un vistazo, no fichas que haya
   que leer. Con las cuatro del catálogo ocupan el doble de alto sin decir
   más. */
.pub-grid { --cols: 6; }

/* La no elegida se apaga. Nada de filete de otro color alrededor: al lado
   del que ya lleva la celda sería la línea doble que el sistema no admite
   en ningún sitio. */
.pub-tile { padding: 0; cursor: pointer; text-align: left; font: inherit; }
.pub-tile .tile__img img { transition: opacity .2s ease; }
.pub-tile:not(.es-on) .tile__img img { opacity: .3; }
.pub-tile:not(.es-on) .tile__bar { color: var(--off); }

/* El número es el orden, que es lo que importa: la tira se recorre en el
   orden en que se eligieron, no en el del catálogo. */
.pub-tile__n {
  flex: none;
  min-width: 24px; height: 24px; padding: 0 6px;
  display: grid; place-items: center;
  background: var(--ink); color: var(--bone);
  border-radius: 12px;
  font-size: var(--t-drop); line-height: 1;
}

@media (max-width: 1100px) { .pub-grid { --cols: 4; } }
@media (max-width: 700px) {
  .pub-campos { grid-template-columns: 1fr; }
  .pub-grid { --cols: 3; }
}

/* ---------- Site · landing --------------------------------------------------

   Las pestañas son `.bar` con `.segs` y `.seg`, el mismo componente que
   separa secciones en el resto del panel. Los campos, la píldora y la caja
   de `.envio`. Ninguna forma nueva.                                       */

.pub-tabs { margin-bottom: var(--s6); }

.pub-nota {
  margin: 0 0 var(--s6); max-width: 60ch;
  font-size: var(--t-drop); color: var(--off);
}

/* El titular de un tramo va a lo ancho, el título corto no: un campo para
   escribir «Ready» ocupando media pantalla no dice qué se espera dentro. */
.pub-campo--ancho { grid-column: 1 / -1; }
.pub-campos .envio__msg { min-height: 92px; }

.pub-imgs {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s5);
  max-width: 900px;
}
/* Rótulo, marco y botón en tres filas comunes a toda la rejilla, no tres
   dentro de cada celda. Así los seis marcos empiezan a la misma altura y los
   seis botones acaban a la misma: antes cada celda se apilaba por su cuenta y
   un rótulo de tres líneas desplazaba su columna entera.

   `subgrid` es lo que hace que las filas sean las del padre. Donde no exista,
   el reparto sigue siendo el de antes y sólo se pierde la alineación fina. */
.pub-imgs { grid-template-rows: auto auto auto; }
.pub-img {
  display: grid; gap: var(--s2); justify-items: start;
  grid-row: span 3; grid-template-rows: subgrid;
}

/* Proporción fija y recorte: sin ellos, seis fotografías de tamaños
   distintos dejarían la rejilla a saltos. */
.pub-img__marco {
  width: 100%; aspect-ratio: 3 / 2; overflow: hidden;
  display: grid; place-items: center;
  border: var(--linea) solid var(--ink);
  background: var(--bone);
}
.pub-img__marco img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pub-img__no { font-size: var(--t-drop); color: var(--off); }

/* El marco encuadrable. La cruz marca el punto que se conserva al recortar, y
   se pone donde se pulse. No hay vista previa que imaginar: este marco es 3:2
   y `cover`, exactamente lo mismo que hace la página con esa pieza. */
.pub-img__marco--mueve { cursor: crosshair; position: relative; }
.pub-img__foco {
  position: absolute; width: 14px; height: 14px; margin: -7px 0 0 -7px;
  border: var(--linea) solid var(--white); border-radius: 50%;
  box-shadow: 0 0 0 2px var(--ink);
  pointer-events: none;
}

/* ---------- Site · el encuadre de teléfono ----------------------------------

   Marco vertical, porque lo que se está decidiendo es qué sobrevive en un
   teléfono. Con el marco apaisado de arriba no se podría juzgar: la pregunta
   es justo la contraria.

   9:16 y no 9:19,5: la proporción exacta de un teléfono deja una tira
   larguísima al lado de las demás fichas del panel, y para elegir un punto
   basta con que la forma sea claramente vertical. */
.pub-movil {
  display: grid; grid-template-columns: repeat(2, minmax(0, 200px));
  gap: var(--s5); margin-bottom: var(--s7);
}
.pub-movil__marco {
  position: relative; cursor: crosshair;
  width: 100%; aspect-ratio: 9 / 16; overflow: hidden;
  display: grid; place-items: center;
  border: var(--linea) solid var(--ink);
  background: var(--bone);
}
.pub-movil__marco img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 700px) { .pub-movil { grid-template-columns: 1fr; } }

@media (max-width: 900px) { .pub-imgs { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 700px) { .pub-imgs { grid-template-columns: 1fr; } }

/* ---------- Site · vídeos de la portada ------------------------------------ */

.pub-vids {
  display: flex; flex-wrap: wrap; gap: var(--s4); align-items: flex-start;
  margin-bottom: var(--s7);
}
.pub-vid { position: relative; display: grid; gap: var(--s2); justify-items: start; }
.pub-vid video {
  width: 240px; aspect-ratio: 16 / 9; object-fit: cover; display: block;
  border: var(--linea) solid var(--ink); background: var(--ink);
}
/* El número es el orden de relevo, que es la única propiedad que importa
   cuando hay más de uno. Lo comparten los vídeos y las piezas de la tira:
   en las dos listas el orden es lo que se está editando. */
.pub-vid__n, .pub-tira__n {
  position: absolute; left: var(--s2); top: var(--s2);
  min-width: 24px; height: 24px; padding: 0 6px;
  display: grid; place-items: center;
  background: var(--ink); color: var(--bone);
  border-radius: 12px; font-size: var(--t-drop); line-height: 1;
}

/* ---------- Site · la tira lateral ------------------------------------------

   Misma forma que los vídeos, y por la misma razón: es una lista ordenada de
   piezas que se añaden y se quitan, no un juego fijo de huecos como el bloque
   de imágenes de arriba. Ahí cada imagen tiene su sitio y su nombre —«Ready»,
   «Together»— y sólo se reemplaza; aquí no hay nombres, hay un orden.

   Las piezas de la tira son apaisadas por diseño: cruzan la pantalla a toda
   altura y sin recorte, así que el marco las enseña en 16:9, que es lo que
   miden. */
.pub-tira {
  display: flex; flex-wrap: wrap; gap: var(--s4); align-items: flex-start;
  margin-bottom: var(--s7);
}
.pub-tira__i { position: relative; display: grid; gap: var(--s2); justify-items: start; }
.pub-tira__i img {
  width: 240px; aspect-ratio: 16 / 9; object-fit: cover; display: block;
  border: var(--linea) solid var(--ink); background: var(--bone);
}
.pub-tira__acc { display: flex; gap: var(--s2); }


/* ---------- Projects en vertical --------------------------------------------

   La banda es una fila de celdas de ancho fijo: el nombre a 260px y cada dato
   —grupo, campañas, talentos— a 190. Sumadas pasan de los mil píxeles, así
   que en un teléfono la página entera se ensanchaba: aparecía barra
   horizontal, el contenido se salía por la derecha y el navegador dejaba
   alejar con dos dedos porque el documento medía más que la pantalla.

   Aquí las celdas dejan de tener ancho fijo y la cabecera puede partir en
   varias líneas. Nada se recorta; se apila.                                */

@media (max-width: 860px) {

  /* La cabecera de la banda se parte. El nombre ocupa su renglón entero y los
     datos van debajo, repartidos. */
  .banda__head { flex-wrap: wrap; }
  .banda__t {
    flex: 1 1 100%; width: auto;
    border-bottom: var(--linea) solid var(--ink);
  }
  .banda__c {
    flex: 1 1 auto; width: auto; min-width: 0;
    padding: var(--s2) var(--s4);
  }
  /* La primera celda de la fila de datos no lleva filete: si no, se sumaría
     con el borde izquierdo de la banda. Las líneas no se pisan. */
  .banda__t + .banda__c { border-left: 0; }

  .banda__x { width: 40px; }

  /* La cabecera de MARCA es otro componente —`.marco__head`, con la banda de
     color— y tenía el mismo problema: una fila que no se parte, con los datos
     empujados a la derecha y cada uno en `nowrap`. Lo que no cabía se salía
     por el borde.

     Aquí el nombre ocupa su renglón y los datos caen debajo, alineados a la
     izquierda, partiendo cuando haga falta. */
  /* Arriba: plegar, nombre, grupo y el selector de color. Debajo: las cuentas
     y la equis. El renglón del nombre iba sobradísimo de sitio y el grupo y el
     selector estaban tirados en la línea de abajo, lejos de lo que nombran. */
  .marco__head { flex-wrap: wrap; gap: var(--s2) var(--s4); }
  .marco__nombre { flex: 0 1 auto; }
  /* El grupo no se muestra: en una pantalla estrecha compite con el nombre de
     la marca, que es lo que se busca, y el dato está a un toque en el
     escritorio. */
  .marco__grupo  { display: none; }
  .marco__color  { order: 0; margin-left: auto; }
  /* La equis, arriba con todo lo demás. Sola en su renglón dejaba una franja
     de color vacía a lo ancho de la pantalla que no decía nada. */
  .marco__x { order: 0; margin-left: 0; }
  .marco__datos {
    order: 1; flex: 1 1 100%; justify-content: flex-start;
    flex-wrap: wrap; gap: var(--s2) var(--s4);
  }

  /* El nombre y la nota de la campaña, uno debajo del otro: en la misma línea
     quedaban dos campos de treinta píxeles cada uno. */
  /* Sin filete arriba: el nombre, que va justo encima, ya cierra por abajo.
     Puestos los dos salían dos líneas pegadas, que es lo que esta casa no
     hace en ningún sitio. */
  .banda__nota { flex: 1 1 100%; border-left: 0; }

  /* La fila de datos abre con su propio filete. Al bajar a un renglón propio
     se quedaba sin nada por arriba y la caja aparecía abierta: las notas, que
     van justo encima, no cierran por abajo. */
  .banda__c, .banda__enviar, .banda__x {
    border-top: var(--linea) solid var(--ink);
  }

  /* La parrilla de caras, a dos por fila. `minmax(200px, 1fr)` pedía 200px de
     mínimo, y con dos columnas en un teléfono de 390 no caben: la rejilla se
     desbordaba en vez de reducirse. */
  /* Crear campaña: el campo ocupa el renglón y los dos botones van debajo.

     Lleva `flex-wrap: nowrap` y el campo pide 260px fijos, así que con los
     dos botones al lado pasaba del ancho de un teléfono y se salía por la
     derecha —el «CANCEL» quedaba medio fuera de la pantalla—. En escritorio
     los tres caben de sobra y no se toca. */
  /* Ningún campo por debajo de 16px.

     Safari en iOS amplía la página al enfocar un campo cuya letra mide menos
     de 16, y al ampliar descuadra todo lo que hay alrededor: es el «zoom»
     que se ve al tocar «Campaign name». Projects usa una escala más densa
     —`.marco` baja `--t-ui` a 14— y por eso saltaba justo aquí.

     Se sube el cuerpo de los campos, no se prohíbe ampliar: bloquear el zoom
     con `maximum-scale` quita a cualquiera la posibilidad de acercarse a leer,
     y eso es peor que un campo dos píxeles más grande. */
  /* Los campos por nombre, no sólo por etiqueta. Un `input { font-size }` a
     secas lo gana cualquier regla con clase —`.alta--card input` fija 14px— y
     el zoom seguía saltando. Aquí van los que existen. */
  input, select, textarea,
  .alta input, .alta--card input,
  .banda__nombre, .banda__nota,
  .envio__para, .envio__msg { font-size: 16px; }

  /* El sangrado, recalculado. En vertical el relleno de la página baja de
     `--s5` a `--s4`, pero `.marco` y `.sels` seguían restando `--s5`: ocho
     píxeles de más por lado, y dos veces, porque uno anida dentro del otro.
     De ahí que el formulario se saliera aunque los campos cupieran. */
  .marco { margin-inline: calc(var(--s4) * -1); padding-inline: var(--s4); }
  .sels  { margin-inline: calc(var(--s4) * -1); }

  /* Crear campaña: bloque centrado y estrecho. El campo ocupaba el ancho
     entero y los botones se estiraban con él, así que al ampliar Safari el
     conjunto se salía por los dos lados. Acotado y centrado, aguanta el zoom
     sin descuadrarse y se lee como una pieza, no como una barra. */
  .alta--card {
    flex-wrap: wrap; justify-content: center;
    padding: var(--s4); gap: var(--s3);
  }
  .alta--card input {
    flex: 1 1 100%; width: auto; max-width: 320px;
  }
  .alta--card .btn { flex: 0 1 auto; }

  .banda__tira { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* Con dos columnas hay más de una fila, y la celda sólo lleva filete a la
     derecha: entre EDU e IVÁN no había nada. Se añade abajo.

     A las de la última fila NO: ahí ya cierra el filete de la banda, y dos
     líneas juntas es lo que esta casa no hace. `nth-last-child(-n+2)` son las
     dos últimas de una rejilla de dos columnas. */
  .banda__tira .cara { border-bottom: var(--linea) solid var(--ink); }
  .banda__tira .cara:nth-last-child(-n+2) { border-bottom: 0; }

  /* La fila horizontal de la portada no se parte en dos columnas: sigue
     siendo una fila, con caras algo más estrechas que la pantalla. */
  .banda__tira--fila { display: flex; }
  .banda__tira--fila > .cara { flex: 0 0 42vw; border-bottom: 0; }

  /* Las celdas de la campaña —talentos, fecha, enviar, cerrar— se reparten el
     renglón en vez de pedir su ancho: la fecha era la que empujaba al resto
     fuera de la pantalla. */
  .banda__c { flex: 1 1 auto; }
  .banda__c i { margin-right: var(--s1); }
  .banda__enviar, .banda__x { flex: none; }

  /* El carril de caras de una campaña ya se desplaza solo; lo que hacía falta
     es que no arrastre a la página con él. */
  .banda__tira--proy { padding: var(--s3) var(--s4) var(--s4); }
}

/* `body` ya corta el desbordamiento lateral desde la línea 111. Falta el
   elemento raíz: en un teléfono, `html` puede ensancharse aunque `body` no, y
   entonces el navegador deja alejar con dos dedos porque el documento sigue
   midiendo más que la pantalla. Es la red por si mañana alguien añade una
   celda ancha; el arreglo de verdad son las reglas de arriba. */
html { max-width: 100%; overflow-x: clip; }
