/* ==========================================================================
   Sproochegalerie — Componentes
   ========================================================================== */

/* --- Logo ------------------------------------------------------------------
   El SVG es una sola forma con el texto calado (fill-rule: evenodd), así que
   toma un color solo y el fondo se ve a través de las letras. Es exactamente
   como lo aplica la charte: el logo siempre usa los dos colores de un par. */

.logo { display: block; color: var(--ink); }
.logo svg { width: 100%; height: auto; }
/* El respaldo toma el color del fondo sobre el que está el logo, no el de la
   tinta: es lo que rellena las letras caladas. Por defecto, el papel. */
.logo__fondo { color: var(--paper); }
/* En la barra fija va la versión reducida. La completa mide 117px de alto a
   este ancho y empuja el header a 130px, un quinto de la pantalla del teléfono
   ocupado permanentemente. La reducida existe exactamente para esto. */
.logo--header { width: 60px; }

/* --- Botones ---------------------------------------------------------------
   Sin radio: la charte no redondea nada salvo las pastillas de filtro. */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-5);
  border: var(--border-w) solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-text);
  font-weight: 700;
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.btn--ghost { background: transparent; color: var(--ink); }
/* Secundario: sólo el rótulo y la flecha, sin borde ni relleno, con un
   subrayado fino. Para las salidas que acompañan a otros botones con más peso
   —«Toutes les offres» debajo de las fichas, que ya tienen el suyo—. Conserva
   el alto de los demás para el toque. */
.btn--texto {
  background: transparent;
  border-color: transparent;
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 5px;
}
/* La flecha es la misma que la de los botones del hero (`--flecha`, en
   tokens.css): una máscara sobre `currentColor`, así sigue el color del botón
   en sus dos variantes. */
.btn__arrow {
  display: inline-block;
  width: 17px;
  height: 12px;
  flex: 0 0 auto;
  background: currentColor;
  -webkit-mask-image: var(--flecha);
  mask-image: var(--flecha);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  transition: transform var(--dur-base) var(--ease-out);
}
.btn:hover .btn__arrow,
.btn:focus-visible .btn__arrow { transform: translateX(4px); }

/* --- Bocadillo -------------------------------------------------------------
   La forma de marca: un rectángulo con skewY y una cola abajo a la izquierda.
   El ángulo sale del vectorial del logo (12,58°).

   Ojo con el ancho: el skew levanta el lado derecho `ancho × 0,223`. En un
   bloque de 335px eso son 75px, que a lo alto de una pantalla de teléfono es
   muchísimo. Por eso el ángulo completo se reserva para bloques más o menos
   cuadrados —el destacado, el claim— y los bloques anchos y bajos usan
   `--skew-soft`, que conserva el gesto sin comerse la pantalla. */

.bubble {
  position: relative;
  padding: var(--s-6) var(--s-6) var(--s-10);
  color: var(--paper);
  isolation: isolate;
  /* Sin aire arriba: el bloque se apoya contra la foto. El recorte ya no
     sobresale de su caja —eso era cosa del skew—, así que abajo sólo hace falta
     la separación normal más lo que se lleva el corte. */
  /* Sin margen abajo: el aire que sigue lo pone el `padding` de la banda, y
     sumando los dos quedaban casi 100px de blanco antes de la sección siguiente. */
  margin-block: 0;
  /* Hay que despejar la cuña del borde inferior, pero no con su altura entera:
     el corte se come material sólo contra el borde derecho y a la izquierda el
     bloque llega completo. Reservando los 75px del corte quedaba un hueco
     enorme debajo del botón, que es lo que vive a la izquierda. Se reserva la
     altura de la diagonal a la altura donde termina el contenido —poco más de
     un tercio del ancho— más el aire normal. */
  padding-bottom: calc(var(--s-8) + (100vw - var(--gutter) * 2) * 0.2232 * 0.72);
}
/* Arriba recto y pegado a la foto; abajo, el ángulo de la marca. Va con
   `clip-path` y no con `skewY` porque el skew inclina los dos bordes a la vez:
   el de arriba también, y entonces el bloque no puede apoyarse contra la
   imagen. El recorte deja el borde superior a 0 y sube el inferior derecho.

   La altura del corte es el ancho del bloque por la tangente del ángulo del
   logo —0,2232, el mismo `ancho × 0,223` del skew—, expresada en `vw` porque
   `clip-path` no puede leer el ancho del elemento en un cálculo vertical. El
   contenedor ocupa el ancho de pantalla menos dos márgenes, de ahí el factor. */
.bubble__shape {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--ink);
  --corte: calc((100vw - var(--gutter) * 2) * 0.2232);
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--corte)), 0 100%);
}
/* Sin cola. Con ella, el bloque era literalmente el logo a tamaño gigante y el
   logo ya está en el hero, dos pantallas más arriba: repetirlo acá no agregaba
   marca, la gastaba. Lo que se queda es la inclinación, que es el gesto de la
   identidad —el mismo ángulo que el bocadillo— sin ser el bocadillo. */
.bubble--soft { --skew: -6deg; }
/* La forma va detrás; el resto del contenido, encima. Sin el `:not`, esta
   regla le pisa el `position: absolute` a `.bubble__shape` —misma
   especificidad, y viene después— y el bocadillo se dibuja sin cuerpo. */
.bubble > :not(.bubble__shape) { position: relative; }

/* --- Pastillas de filtro --------------------------------------------------- */

.pills {
  display: flex;
  gap: var(--s-2);
  overflow-x: auto;
  padding-block: var(--s-2);
  /* Sin margen negativo: estas filas cuelgan de la <section>, no del
     `.container`, así que no hay padding de contenedor que cancelar. Con él, el
     carril empezaba 20px a la izquierda del borde y la primera pastilla salía
     pegada al canto de la pantalla en vez de al margen. */
  padding-inline: var(--gutter);
  scroll-padding-inline: var(--gutter);   /* ver la nota del carril */
  scrollbar-width: none;
  /* Scroll con encastre: en el teléfono la fila de filtros se arrastra, y sin
     esto queda siempre una pastilla cortada al borde. */
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
.pills::-webkit-scrollbar { display: none; }

.pill {
  flex: 0 0 auto;
  scroll-snap-align: start;
  display: inline-flex;
  align-items: center;
  padding: var(--s-2) var(--s-4);
  border: var(--border-w) solid var(--ink);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--ink);
  font-weight: 700;
  font-size: var(--fs-sm);
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.pill[aria-pressed="true"] { background: var(--ink); color: var(--paper); }

/* --- Tarjeta de oferta -----------------------------------------------------
   Cada categoría manda a un lado distinto: dos van a sitios externos, una a un
   formulario propio y las walk-in a ninguno. Si la tarjeta no dice adónde va
   antes del clic, el filtro por tipo termina mintiendo. Por eso el destino es
   parte fija de la tarjeta, no un detalle del hover. */

/* Cada tipo de oferta lleva un par de la marca —el mismo que usan las bandas—
   y así se distingue de un vistazo, sin leer la etiqueta: projets en rojo,
   activités en verde, groupes en lila, vacances en azul. Sin borde: el color
   es lo que recorta la ficha contra la banda avena. (Antes eran todas avena
   con filete, foto arriba y caja abajo; se leían genéricas.) */
.card[data-type="projet"]       { --paper: var(--pair-red-paper);   --ink: var(--pair-red-ink); }
.card[data-type="individuelle"] { --paper: var(--pair-green-paper); --ink: var(--pair-green-ink); }
.card[data-type="groupe"]       { --paper: var(--pair-lilac-paper); --ink: var(--pair-lilac-ink); }
.card[data-type="vacances"]     { --paper: var(--pair-blue-paper);  --ink: var(--pair-blue-ink); }

.card {
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--ink);
  text-decoration: none;
  height: 100%;
}
.card__media {
  /* 16:9 y no 4:3: en este tamaño lo que informa es el ambiente, no el
     detalle, y la ficha no se come la pantalla. */
  aspect-ratio: 16 / 9;
  background: color-mix(in srgb, var(--ink) 14%, var(--paper));
  /* `position: relative` y la imagen absoluta, o el `aspect-ratio` no manda:
     el <img> estiraría la caja a su propia proporción. */
  position: relative;
  overflow: hidden;
}
/* El tipo, sobre la foto: es lo primero que se lee. Redondo, como los filtros
   de arriba —son la misma cosa: el tipo de oferta—, y por eso despegado de la
   esquina: una píldora contra el canto se lee cortada. */
.card__tipo {
  position: absolute;
  left: var(--s-3);
  top: var(--s-3);
  margin: 0;
  padding: 6px var(--s-3);
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--ink);
  font-size: var(--fs-label);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.card__body {
  padding: var(--s-4);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  flex: 1;
}
/* Quién organiza —el brief lo pide en cada actividad—, chico, arriba del
   título. */
.card__org {
  margin: 0;
  font-size: var(--fs-label);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  opacity: 0.75;
}
.card__title {
  font-family: var(--font-display-cond);
  font-weight: 700;
  font-size: 34px;
  line-height: 1;
  letter-spacing: -0.01em;
  margin: 0;
}
.card__text { font-size: var(--fs-body); margin: 0 0 var(--s-3); }   /* aire antes del botón */

/* La acción, como un botón chico del ancho de su rótulo, abajo a la izquierda:
   «S'inscrire», «Réserver», «Venir». Corto a propósito —antes decía también
   adónde llevaba («S'inscrire sur colonies.lu») y ocupaba todo el ancho; se
   leía como una barra y no como un botón—. Va en la tinta de la ficha. */
.card__dest {
  align-self: flex-start;
  /* arriba `auto`, para que el botón caiga al pie aunque el texto sea corto;
     el aire de abajo lo pone el padding del cuerpo —un margen acá lo anularía
     `p:last-child` de base.css, que pesa más— */
  margin-top: auto;
  padding: var(--s-2) var(--s-4);
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  background: var(--ink);
  color: var(--paper);
  font-size: var(--fs-label);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
}
.card:hover .card__dest .btn__arrow { transform: translateX(4px); }

/* --- Carrusel horizontal de tarjetas ---------------------------------------
   En mobile las tarjetas se arrastran de costado en vez de apilarse: ocho
   ofertas apiladas son ocho pantallas de scroll. */

.rail {
  display: grid;
  grid-auto-flow: column;
  /* 86 %: con 78 las fichas quedaban chicas; así asoma igual la siguiente,
     que es lo que avisa que la fila se arrastra */
  grid-auto-columns: 86%;
  gap: var(--s-4);
  overflow-x: auto;
  padding-inline: var(--gutter);         /* ver la nota de .pills */
  padding-block: var(--s-2);
  scroll-snap-type: x mandatory;
  /* Sin esto el carril arranca desplazado y la primera tarjeta sale cortada por
     el margen. El encastre alinea el borde de la ficha con el borde del
     scrollport, que está 20px a la izquierda del padding: el navegador corrige
     scrolleando esos 20px. `scroll-padding` le dice dónde empieza de verdad. */
  scroll-padding-inline: var(--gutter);
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.rail::-webkit-scrollbar { display: none; }
.rail > * { scroll-snap-align: start; }

/* --- Navegación ------------------------------------------------------------ */

.site-header {
  /* `fixed`, no `sticky`: sobre el hero la barra no ocupa lugar —el logo ya
     está dentro del tablero y en las mesas no hay barra— y recién se vuelve
     sólida cuando el hero sale de pantalla. */
  position: fixed;
  inset-inline: 0;
  top: 0;
  /* Por encima del panel: con el menú abierto el usuario tiene que seguir
     viendo la X para cerrarlo. Si el panel lo tapa, la única salida es el
     botón de atrás del teléfono. */
  z-index: 70;
  /* El fondo y el filete viven en la barra interior, no acá: al scrollear la
     barra se despega de los bordes y pasa a ser un bloque flotante, así que lo
     que se pinta es ella y no todo el ancho de la pantalla. */
  background: none;
  color: var(--ink);
  transition: top var(--dur-base) var(--ease-out);
}

/* Sobre el hero: transparente, sin filete, sin logo. Hereda el --ink del par
   que esté activo, así el botón de menú siempre contrasta. */
.site-header[data-over-hero="true"] {
  background: transparent;
  border-bottom-color: transparent;
}
.site-header[data-over-hero="true"] .logo--header {
  opacity: 0;
  pointer-events: none;
}
/* Sobre el hero el botón de menú toma la tinta del par que esté activo. */
.site-header[data-over-hero="true"][data-pair="lilac"] { color: var(--purple); }
.site-header[data-over-hero="true"][data-pair="red"]   { color: var(--burgundy); }
.site-header[data-over-hero="true"][data-pair="oat"]   { color: var(--grey); }
.logo--header { transition: opacity var(--dur-base); }
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  height: var(--header-h);
  transition: height var(--dur-base) var(--ease-out),
              margin var(--dur-base) var(--ease-out),
              padding var(--dur-base) var(--ease-out),
              background-color var(--dur-base),
              color var(--dur-base);
}

/* --- Pasado el hero: sólo el botón del menú ---------------------------------
   Al scrollear ya no hay barra ni logo: queda únicamente el botón del menú,
   en el mismo lugar que sobre el hero —así no salta— y metido en un recuadro
   propio, avena con filete gris, para que se vea sobre cualquier banda que
   pase por debajo, clara u oscura. (Antes era una barra flotante con el logo
   asomando por arriba; se descartó: el logo flotando sobre el contenido
   quedaba de más.) */
.site-header[data-over-hero="false"] .logo--header {
  opacity: 0;
  pointer-events: none;
}
.site-header[data-over-hero="false"] .nav-toggle {
  background: var(--oat);
  color: var(--grey);
  border: var(--border-w) solid var(--grey);
  width: 48px;
  height: 48px;
  padding-inline: 11px;
  transition: background var(--dur-base), color var(--dur-base), border-color var(--dur-base);
}
/* El header sigue ocupando todo el ancho de arriba aunque sea transparente:
   que deje pasar los toques al contenido de abajo, salvo en el botón. */
.site-header[data-over-hero="false"] { pointer-events: none; }
.site-header[data-over-hero="false"] .nav-toggle { pointer-events: auto; }
/* Con el menú abierto el recuadro se funde con el panel: queda la X sola. */
body[data-nav-open="true"] .site-header[data-over-hero="false"] .nav-toggle {
  background: transparent;
  border-color: transparent;
  color: var(--pair-green-paper);
}

.nav-toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
/* Dos líneas, como en el .ai: ahí son dos trazos de 42,2 de largo separados
   9,8, o sea proporción 1 a 4,3 respecto de la separación. */
.nav-toggle { gap: 9px; }
.nav-toggle span {
  display: block;
  height: var(--border-w);
  background: currentColor;
  transition: transform var(--dur-base) var(--ease-out);
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { transform: translateY(-5.5px) rotate(-45deg); }

.nav-panel {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: var(--pair-green-ink);
  color: var(--pair-green-paper);
  /* Arranca debajo del header y del logo de la home, que quedan encima: el
     logo mide unos 96 de alto con la cola del bocadillo; con estos 48 de más
     la lista respira debajo de él en vez de colgarle de la cola. */
  padding: calc(var(--header-h) + var(--s-6) + 48px) var(--gutter) var(--s-12);
  display: flex;
  flex-direction: column;
  gap: var(--s-8);
  overflow-y: auto;
  transform: translateY(-100%);
  visibility: hidden;
  transition: transform var(--dur-panel) var(--ease-out), visibility var(--dur-panel);
}
.nav-panel[data-open="true"] { transform: translateY(0); visibility: visible; }

/* Con el panel abierto, el header tiene que pasar al color del panel. Si no, el
   botón —que se dibuja con `currentColor`— conserva el color del par del hero y
   la X queda oscura sobre el verde oscuro: invisible. La especificidad imita la
   de las reglas de par de arriba y le suma el atributo del body, que es lo que
   hace falta para ganarles. */
body[data-nav-open="true"] .site-header[data-over-hero="true"][data-pair],
body[data-nav-open="true"] .site-header {
  color: var(--pair-green-paper);
}
/* Con el menú abierto el logo se va. Flotando queda desalineado respecto del
   panel —su caja sigue la barra, no la lista— y encima duplica el que ya está
   en el pie del propio menú. Se desvanece con la misma transición que usa al
   aparecer sobre el hero. */
body[data-nav-open="true"] .logo--header {
  opacity: 0;
  pointer-events: none;
}
/* En su lugar, el logo de la home, a su tamaño y en su sitio —js/main.js le
   copia la caja del logo del hero—, en los colores del panel. Fijo, como el
   header, y encima de la barra: aunque el menú se abra con la barra flotante,
   el logo aparece donde está en la portada. Entra con un fundido, cuando el
   panel ya está llegando. */
.logo--menu {
  position: fixed;
  left: 17px;
  top: 14px;
  width: 85px;
  z-index: 2;
  color: var(--pair-green-paper);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 180ms var(--ease-out), visibility 0s 180ms;
}
body[data-nav-open="true"] .logo--menu {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity 360ms var(--ease-out) 200ms, visibility 0s;
}



/* --- La entrada del panel ---------------------------------------------------
   El panel entra deslizándose y su contenido detrás, escalonado. El escalonado
   es lo que lo vuelve suave: sin él, el bloque entero aterriza de golpe y la
   lista se lee como un cartel que aparece, no como un menú que se abre.

   Los retrasos van con `:nth-child` y no con una variable puesta por JS: el
   panel es navegación, tiene que funcionar aunque el script falle. */
/* Cada renglón entra deslizándose dentro de su propia ranura, igual que las
   letras del hero. Ésa es la pieza que faltaba: los `steps` sólo se leen como
   mecánica si hay un borde que los recorte. Saltando por espacio abierto —que
   es lo que se probó antes, entrando desde la izquierda— los mismos pasos
   parecen cuadros perdidos, no un mecanismo.

   El <li> recorta y el enlace se desliza dentro. Sin opacidad: la máscara ya
   hace que el texto no exista hasta que entra, y un fundido encima sería un
   segundo movimiento compitiendo con el primero. */
/* `clip` y no `hidden`: con `hidden` el <li> es un contenedor desplazable, y
   al darle el foco al primer enlace —lo hace js/main.js al abrir— el navegador
   lo desplazaba para mostrarlo: À LA UNE aparecía ya puesta, sin entrar. Con
   `clip` recorta igual pero no se puede desplazar. */
.nav-panel .nav-list li { overflow: hidden; overflow: clip; }
.nav-panel .nav-list a {
  transform: translateY(100%);
  /* Una curva que sale rápido y frena larga: el renglón se desliza y se
     asienta. (Antes iba a pasos, steps(7), por la lectura mecánica de las
     fichas del hero; en el menú sobraba.) */
  transition: transform 560ms cubic-bezier(0.22, 1, 0.36, 1);
}
.nav-panel[data-open="true"] .nav-list a { transform: none; }

.nav-panel .lang {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 420ms var(--ease-out), transform 560ms cubic-bezier(0.22, 1, 0.36, 1);
}
.nav-panel[data-open="true"] .lang { opacity: 1; transform: none; }
/* Dos reglas gobiernan estos números y conviene no romperlas al tocarlos.

   La primera: la cascada arranca cuando el panel YA ATERRIZÓ. Si empieza antes,
   la entrada del primer renglón queda tapada por el movimiento grande del panel
   y parece que ese renglón estaba ahí desde el principio.

   La segunda: el escalonado tiene que ser corto. Medido en la versión anterior,
   el primer renglón terminaba a los 750ms y el último a los 1017: el primero se
   quedaba solo en pantalla un cuarto de segundo, que es lo que se lee como que
   «aparece antes». No era un defecto del primero sino de la separación entre
   todos. Con la curva suave el recorrido es más largo (560) y el paso de
   40ms: cada renglón todavía está frenando cuando arranca el siguiente, así
   que se leen juntos, como una sola ola. El menú cierra en ~1040. */
.nav-panel[data-open="true"] .nav-list li:nth-child(1) a { transition-delay: 200ms; }
.nav-panel[data-open="true"] .nav-list li:nth-child(2) a { transition-delay: 240ms; }
.nav-panel[data-open="true"] .nav-list li:nth-child(3) a { transition-delay: 280ms; }
.nav-panel[data-open="true"] .nav-list li:nth-child(4) a { transition-delay: 320ms; }
.nav-panel[data-open="true"] .nav-list li:nth-child(5) a { transition-delay: 360ms; }
.nav-panel[data-open="true"] .nav-list li:nth-child(6) a { transition-delay: 400ms; }
.nav-panel[data-open="true"] .nav-list li:nth-child(7) a { transition-delay: 440ms; }
.nav-panel[data-open="true"] .lang { transition-delay: 480ms; }

/* Al cerrar no hay escalonado: el retraso haría que la lista se quedara flotando
   mientras el panel ya se fue. */
.nav-panel:not([data-open="true"]) .nav-list a,
.nav-panel:not([data-open="true"]) .lang {
  transition-duration: 120ms;
  transition-delay: 0ms;
}

@media (prefers-reduced-motion: reduce) {
  .nav-panel .nav-list a,
  .nav-panel .lang { opacity: 1; transform: none; transition: none; }
  .logo--menu, body[data-nav-open="true"] .logo--menu { transition: none; }
}

.nav-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
/* El separador va en el <li> y no en el enlace: así se queda quieto mientras el
   texto entra. Si viajara con el texto, lo que se vería moverse es la línea. */
/* Al 40 %: a pleno el filete competía con los renglones, y entre siete líneas
   seguidas la lista se leía como una tabla. */
.nav-list li { border-bottom: 1px solid color-mix(in srgb, currentColor 40%, transparent); }
.nav-list a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* 13 arriba y abajo: con 16 la lista se desarmaba en renglones sueltos y con
     10 quedaba apretada. Cada renglón mide más de 44, el mínimo para tocarlo. */
  padding-block: 13px;
  color: inherit;
  text-decoration: none;
  font-family: var(--font-display);
  font-size: clamp(31px, 9.4vw, 42px);
  text-transform: uppercase;
  line-height: var(--lh-tight);
}

/* --- Selector de idioma ----------------------------------------------------
   Cuatro idiomas y ninguno es secundario: LU y DE pesan tanto como FR acá. Van
   los cuatro visibles, no escondidos en un desplegable. */

.lang { display: flex; gap: var(--s-1); align-items: center; }
.lang a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 34px;
  min-height: 44px;
  color: inherit;
  text-decoration: none;
  font-size: var(--fs-sm);
  font-weight: 400;
  text-transform: uppercase;
}
/* El idioma activo se marca con peso y subrayado, no bajándole la opacidad a
   los otros tres: atenuarlos los tira por debajo de 4,5:1. */
.lang a[aria-current="true"] {
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 2px;
}

/* --- Formulario ------------------------------------------------------------ */

.field { display: flex; flex-direction: column; gap: var(--s-2); }
.field label { font-weight: 700; font-size: var(--fs-sm); }
.field input {
  padding: var(--s-3) var(--s-4);
  border: var(--border-w) solid var(--ink);
  border-radius: 0;
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  min-height: 48px;
}
/* El placeholder también es texto y también tiene que pasar AA. Con
   `opacity: 0.5` quedaba en 2,8:1; mezclado al 80% con el fondo da 4,97:1. */
.field input::placeholder {
  color: color-mix(in srgb, currentColor 80%, var(--paper));
  opacity: 1;                    /* Firefox lo baja a 0.54 por defecto */
}

/* --- Fotos -----------------------------------------------------------------
   El `width`/`height` del marcado no es decorativo: reserva el sitio antes de
   que la imagen llegue, y sin eso el texto da un salto al cargar. El
   `aspect-ratio` del contenedor manda sobre el recorte; la imagen lo llena. */
.card__media img,
.destacado__foto img {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.destacado__foto {
  margin: 0;
  position: relative;          /* ver la nota de .card__media */
  /* 3:2. Se probó 2:1 para bajar la card, pero la foto apaisada perdía
     presencia: la altura se recorta en el bocadillo, no acá. */
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: color-mix(in srgb, var(--ink) 14%, var(--paper));
}
