/* ═══════════════════════════════════════════════════════════════
   BAIREX DIGITAL — Sistema de diseño de la app del cliente (F1)
   Basado en el manual de marca (General Sans + #369140).
   Tema claro/oscuro por horario argentino (D-17); la preferencia
   del usuario siempre gana.
   ═══════════════════════════════════════════════════════════════ */

/* La fuente NO se pide desde acá. Un @import obliga al navegador a bajar este
   archivo, leerlo, y recién entonces empezar a bajar la fuente: dos viajes en
   serie antes de dibujar nada. Va como <link> en el HTML, junto a un
   preconnect, para que los dos bajen en paralelo. */

/* ─────────── TOKENS: tema claro (default) ─────────── */
:root {
  --bg:            #F6F8F8;
  --surface:       #FFFFFF;
  --surface-2:     #F3F8F4;
  --line:          #E5EBE9;
  --line-strong:   #D1DBD7;
  --ink:           #0E1110;
  --ink-2:         #505E58;
  --muted:         #6D7E77;

  --brand:         #369140;
  --brand-strong:  #2D7A36;
  --brand-bright:  #4FBF63;
  --brand-tint:    #E7F2E8;
  --on-brand:      #FFFFFF;

  --battle:        #B42318;
  --battle-tint:   #FEE9E7;
  --warn:          #B45309;
  --info:          #175CD3;

  --shadow-1: 0 1px 2px rgba(14,17,16,.05);
  --shadow-2: 0 6px 18px rgba(14,17,16,.09);
  --shadow-3: 0 18px 44px rgba(14,17,16,.14);
  --scrim:    rgba(14,17,16,.55);
}

/* ─────────── TOKENS: tema oscuro ─────────── */
:root[data-theme="dark"] {
  --bg:            #0E1110;
  --surface:       #171B19;
  --surface-2:     #1E2421;
  --line:          rgba(240,245,242,.09);
  --line-strong:   rgba(240,245,242,.17);
  --ink:           #F4F6F5;
  --ink-2:         #B7C2BE;
  --muted:         #92A09A;

  --brand:         #4FBF63;
  --brand-strong:  #369140;
  --brand-bright:  #6FD583;
  --brand-tint:    rgba(79,191,99,.14);
  --on-brand:      #06210C;

  --battle:        #F0655A;
  --battle-tint:   rgba(240,101,90,.14);
  --warn:          #E9A13B;
  --info:          #6BA5F5;

  --shadow-1: 0 1px 2px rgba(0,0,0,.4);
  --shadow-2: 0 6px 18px rgba(0,0,0,.45);
  --shadow-3: 0 18px 44px rgba(0,0,0,.6);
  --scrim:    rgba(0,0,0,.62);
}

/* ─────────── Escalas del sistema ─────────── */
:root {
  --font: 'General Sans', system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* Tipografía */
  --t-display: 700 clamp(1.6rem, 5vw, 2.1rem)/1.12 var(--font);
  --t-title:   700 1.12rem/1.28 var(--font);
  --t-body:    500 0.95rem/1.5  var(--font);
  --t-small:   500 0.82rem/1.45 var(--font);
  --t-micro:   600 0.7rem/1.35  var(--font);

  /* Radios (curva Railway del manual) */
  --r-sm: 10px; --r-md: 14px; --r-lg: 18px; --r-xl: 24px; --r-pill: 100px;

  /* Espaciado */
  --s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px; --s-5: 24px; --s-6: 32px;

  /* Movimiento — una sola curva para todo el sistema */
  --ease: cubic-bezier(.22, 1, .36, 1);
  --fast: .18s var(--ease);
  --med:  .32s var(--ease);
  --slow: .48s var(--ease);

  --frame: 1180px;
}

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

/* ─────────── Base ─────────── */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  font: var(--t-body);
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--med), color var(--med);
}
img { max-width: 100%; display: block; }
button, input, select, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 4px; }

.wrap { max-width: var(--frame); margin: 0 auto; padding: 0 var(--s-4); }

/* `hidden` tiene que ganarle a cualquier display del sistema. Sin esto, un
   .dock o un .chip con hidden se muestran igual, porque su propia regla de
   display es más específica. Ya rompió dos veces. */
[hidden] { display: none !important; }
.tabular { font-variant-numeric: tabular-nums; }

/* ─────────── Íconos ─────────── */
.ico { width: 22px; height: 22px; flex: none; stroke: currentColor; fill: none;
       stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.ico-sm { width: 17px; height: 17px; }
.ico-lg { width: 26px; height: 26px; }

/* ─────────── Botones ─────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  background: var(--brand); color: var(--on-brand); border: 0; border-radius: var(--r-md);
  padding: 14px 22px; font: 700 1rem/1 var(--font); cursor: pointer;
  transition: transform var(--fast), background var(--fast), box-shadow var(--fast);
  box-shadow: var(--shadow-1);
}
.btn:hover { background: var(--brand-strong); }
.btn:active { transform: scale(.972); }
.btn:disabled { opacity: .45; pointer-events: none; }
.btn--block { width: 100%; }
.btn--ghost { background: transparent; color: var(--ink); border: 1px solid var(--line-strong); box-shadow: none; }
.btn--ghost:hover { background: var(--surface-2); border-color: var(--brand); color: var(--brand); }
.btn--battle { background: var(--battle); color: #fff; }
.btn--lg { padding: 16px 26px; font-size: 1.06rem; }
/* Cancelar: SIN recuadro (Santino, 2026-07-29). El borde le daba una entidad
   que no se merece — con recuadro llama más la atención que sin él. Queda como
   texto gris: presente para el que lo busca, invisible para el que no. */
.btn--cancel { background: transparent; color: var(--muted); border: 0; box-shadow: none; }
.btn--cancel:hover { background: var(--surface-2); color: var(--ink); }
/* Cancelar — variante B (a comparar): en rojo */
.btn--cancel-rojo { background: transparent; color: var(--battle); border: 1px solid var(--battle);
                    box-shadow: none; }
.btn--cancel-rojo:hover { background: var(--battle-tint); }

/* Celda de opción del modal: valor/ícono arriba, etiqueta abajo */
.opt {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  min-height: 78px; padding: 12px 6px; border-radius: var(--r-md); cursor: pointer;
  background: var(--surface); border: 1.5px solid var(--line-strong); color: var(--ink);
  font: var(--t-body); transition: border-color var(--fast), background var(--fast), transform var(--fast);
}
.opt:active { transform: scale(.96); }
.opt b { font: 700 1rem/1 var(--font); }
.opt small { font: var(--t-micro); color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.opt[aria-pressed="true"] { border-color: var(--brand); background: var(--brand-tint); }
.opt[aria-pressed="true"] small { color: var(--brand-strong); }
:root[data-theme="dark"] .opt[aria-pressed="true"] small { color: var(--brand); }
.opt .ico { color: var(--ink-2); }

/* ─────────── Campo de monto ───────────
   El "$" es decoración, no texto: vive en el padding del input, así el cliente
   nunca lo puede borrar ni tiene que esquivarlo para escribir. */
.monto { position: relative; }
.monto__signo {
  position: absolute; left: 15px; top: 50%; transform: translateY(-50%);
  font: 700 1.15rem/1 var(--font); color: var(--muted); pointer-events: none; user-select: none;
}
.monto input {
  width: 100%; box-sizing: border-box; background: var(--surface); color: var(--ink);
  border: 1.5px solid var(--brand); border-radius: var(--r-md);
  padding: 14px 14px 14px 38px; font: 700 1.15rem/1 var(--font);
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
  transition: border-color var(--fast);
}
.monto input:focus { outline: none; border-color: var(--brand-strong); }
.monto[data-mal="true"] input { border-color: var(--battle); }
.monto[data-mal="true"] .monto__signo { color: var(--battle); }

/* Requisito que se evalúa mientras escribís (como el de una contraseña) */
.requisito {
  display: flex; align-items: center; gap: 7px; margin-top: 8px;
  font: var(--t-small); color: var(--muted); transition: color var(--fast);
}
.requisito .ico { width: 1.1em; height: 1.1em; flex: none; }
.requisito[data-ok="true"]  { color: var(--brand-strong); }
:root[data-theme="dark"] .requisito[data-ok="true"] { color: var(--brand); }
.requisito[data-ok="false"] { color: var(--battle); }

/* Salida de página (la transición entra desde la pantalla siguiente) */
body[data-saliendo="true"] { opacity: .55; transition: opacity .13s linear; }

/* ─────────── Superficies ─────────── */
.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
  box-shadow: var(--shadow-1);
  transition: transform var(--med), box-shadow var(--med), border-color var(--med);
}
.card--tap { cursor: pointer; }
.card--tap:active { transform: scale(.978); }
@media (hover: hover) {
  .card--tap:hover { transform: translateY(-3px); box-shadow: var(--shadow-2); border-color: var(--brand); }
}
.panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--s-4); }

/* ─────────── Chips / badges ─────────── */
.chip {
  display: inline-flex; align-items: center; gap: 6px; background: var(--surface);
  border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  padding: 7px 14px; font: var(--t-small); cursor: pointer; white-space: nowrap;
  transition: all var(--fast);
}
.chip:hover { border-color: var(--brand); color: var(--brand); }
.chip[aria-pressed="true"] { background: var(--brand-tint); border-color: var(--brand); color: var(--brand); font-weight: 700; }

.badge {
  display: inline-flex; align-items: center; gap: 5px; border-radius: var(--r-pill);
  padding: 3px 10px; font: var(--t-micro); letter-spacing: .02em; color: #fff;
}
/* El ícono se mide contra la letra que lo acompaña, no en px fijos: si no, en
   una etiqueta de 11px entra un ícono de 20px y parece un globo.
   Con un piso, eso sí: por debajo de 14px un trazo de 1.9 se empasta y el
   dibujo deja de leerse — se ve una mancha, no un ícono. */
.badge .ico { width: max(1.15em, 14px); height: max(1.15em, 14px); stroke-width: 2.2; }
.chip  .ico { width: max(1.15em, 16px); height: max(1.15em, 16px); stroke-width: 2; }
.badge--win    { background: var(--brand); color: var(--on-brand); }
.badge--battle { background: var(--battle); animation: pulse 1.3s ease-in-out infinite; }
.badge--soft   { background: var(--surface-2); color: var(--muted); border: 1px solid var(--line); }
@keyframes pulse { 50% { opacity: .55; } }

.lote-tag {
  font: var(--t-micro); color: var(--muted); border: 1px solid var(--line);
  border-radius: 6px; padding: 1px 6px; letter-spacing: .03em;
}

/* ─────────── Countdown ─────────── */
.cd { font-variant-numeric: tabular-nums; font-weight: 800; color: var(--brand); letter-spacing: .3px; }
.cd--battle { color: var(--battle); }
.cd--xl { font-size: 1.5rem; }

/* ─────────── Precio ─────────── */
.price    { font: 800 1.3rem/1.15 var(--font); letter-spacing: -.4px; font-variant-numeric: tabular-nums; }
.price--xl{ font-size: 2rem; letter-spacing: -1px; }

/* ─────────── Placeholder de foto ─────────── */
.thumb {
  position: relative; background: var(--surface-2); overflow: hidden;
  background-image: linear-gradient(135deg, transparent 45%, rgba(54,145,64,.07) 50%, transparent 55%);
}
.thumb::after {
  content: ""; position: absolute; inset: 0;
  background: repeating-linear-gradient(45deg, rgba(109,126,119,.07) 0 9px, transparent 9px 18px);
}

/* Entrada "Remates" del header: sólo en pantallas anchas — en el celular ya
   está la pestaña de abajo y duplicarla es ruido. */
.appbar__lnk { display: none; font: 600 .9rem/1 var(--font); color: var(--ink-2);
               padding: 9px 13px; border-radius: var(--r-pill); transition: all var(--fast); }
.appbar__lnk:hover { background: var(--surface-2); color: var(--brand); }
.appbar__lnk[aria-current="page"] { color: var(--brand); background: var(--brand-tint); }
@media (min-width: 760px) { .appbar__lnk { display: inline-flex; } }

/* Fila contextual bajo el header: volver, título de la pantalla, flechas.
   Es de la pantalla, no de la app — por eso vive fuera del appbar. */
.subbar { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-3) 0; }
.subbar .title { font-size: 1rem; }

/* Destello de "esto acaba de cambiar" */
@keyframes destello {
  0%   { background: var(--brand-tint); box-shadow: 0 0 0 6px var(--brand-tint); }
  100% { background: transparent; box-shadow: 0 0 0 6px transparent; }
}
.destello { animation: destello 1.1s var(--ease); border-radius: var(--r-sm); }

/* ─────────── Tarjeta de lote ───────────
   La pieza que más se repite en toda la app, así que es una clase y no estilos
   sueltos: si cambia el alto de la foto, cambia en la portada, en el listado y
   en "mis ofertas" a la vez.
   D-05: el precio va antes que el título y más grande — la decisión de mirar o
   seguir de largo se toma en menos de dos segundos y la toma el precio.       */
.lote { overflow: hidden; }
.lote__foto {
  position: relative; aspect-ratio: 4 / 3; width: 100%;
  border-radius: var(--r-md) var(--r-md) 0 0;
}
.lote__foto img { width: 100%; height: 100%; object-fit: cover; display: block; position: relative; z-index: 1; }
.lote__badge { position: absolute; top: 9px; left: 9px; z-index: 2; }
.lote__cuerpo { padding: 11px 13px 13px; }
.lote__titulo {
  font: var(--t-small); color: var(--ink-2); margin: 2px 0 8px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 2.5em;   /* dos renglones fijos: las tarjetas no bailan */
}
.lote__pie { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); }

/* ─────────── Barra fija / sheet / banner ─────────── */
.dock {
  position: sticky; bottom: 0; background: var(--surface); border-top: 1px solid var(--line);
  padding: var(--s-3) var(--s-4) calc(var(--s-3) + env(safe-area-inset-bottom));
  display: flex; gap: var(--s-3); align-items: center; z-index: 20;
  box-shadow: 0 -6px 22px rgba(14,17,16,.08);
  transition: transform var(--med), opacity var(--fast);
}
:root[data-theme="dark"] .dock { box-shadow: 0 -6px 22px rgba(0,0,0,.5); }
/* La entrega: cuando el bloque de oferta de la página está a la vista, la barra
   se retira. Nunca hay dos botones de ofertar en pantalla al mismo tiempo —
   dos botones iguales a diez centímetros no dan más opciones, hacen dudar. */
.dock[data-entregado="true"] { transform: translateY(115%); opacity: 0; pointer-events: none; }

.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  background: var(--surface); border-radius: var(--r-xl) var(--r-xl) 0 0;
  border-top: 1px solid var(--line); padding: var(--s-5) var(--s-4) var(--s-4);
  box-shadow: var(--shadow-3); transform: translateY(101%);
  transition: transform var(--slow);
}
.sheet[data-open="true"] { transform: translateY(0); }
@media (min-width: 720px) {
  .sheet { left: 50%; right: auto; bottom: auto; top: 50%; width: 460px;
           border-radius: var(--r-xl); border: 1px solid var(--line);
           transform: translate(-50%, -46%) scale(.97); opacity: 0; }
  .sheet[data-open="true"] { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}
.scrim { position: fixed; inset: 0; background: var(--scrim); opacity: 0; z-index: 55;
         pointer-events: none; transition: opacity var(--slow); }
.scrim[data-open="true"] { opacity: 1; pointer-events: auto; }

/* Banner (D-21) — ambos tipos comparten EXACTAMENTE la misma altura */
.banner {
  position: fixed; top: 0; left: 0; right: 0; z-index: 80; color: #fff;
  min-height: 66px; box-sizing: content-box;
  padding: env(safe-area-inset-top) 46px 0 var(--s-4);
  display: flex; align-items: center; gap: var(--s-3); justify-content: center;
  transform: translateY(-101%); transition: transform var(--med);
}
.banner[data-open="true"] { transform: translateY(0); }
.banner--win { background: var(--brand); color: var(--on-brand); }
.banner--lose{ background: var(--battle); }
.banner__txt { font: 700 .95rem/1.25 var(--font); }
.banner__txt small { display: block; font: 600 .78rem/1.3 var(--font); opacity: .85; margin-top: 2px; }
.banner__act {
  background: #fff; border: 0; border-radius: var(--r-sm); padding: 9px 14px;
  font: 700 .82rem/1 var(--font); cursor: pointer; white-space: nowrap; flex: none;
  transition: transform var(--fast);
}
.banner--lose .banner__act { color: var(--battle); }
.banner--win  .banner__act { color: var(--brand-strong); }
.banner__act:active { transform: scale(.95); }
.banner__x { position: absolute; top: 50%; right: 14px; transform: translateY(-50%);
             opacity: .85; cursor: pointer; }
.banner__bar { position: absolute; bottom: 0; left: 0; height: 3px; width: 100%;
               background: rgba(255,255,255,.65); transform-origin: left; }
@keyframes drain { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* ─────────── Acciones del modal: siempre en la misma fila ─────────── */
.actions { display: flex; gap: var(--s-2); align-items: stretch; margin-top: var(--s-4); }
.actions .btn { flex: 1; }
.actions .btn--cancel-slot { flex: 0 0 38%; }

/* ─────────── Carga: barra superior + splash (marca) ─────────── */
.loadbar {
  position: fixed; top: 0; left: 0; height: 3px; width: 0; z-index: 95;
  background: linear-gradient(90deg, var(--brand-strong), var(--brand-bright));
  box-shadow: 0 0 12px var(--brand-bright); opacity: 0;
  transition: width .3s var(--ease), opacity .3s;
}
.loadbar[data-on="true"] { opacity: 1; }

.splash {
  position: fixed; inset: 0; z-index: 99; background: var(--bg);
  display: grid; place-items: center; gap: var(--s-4);
  opacity: 1; transition: opacity var(--slow), visibility var(--slow);
}
.splash[data-on="false"] { opacity: 0; visibility: hidden; }
/* Tres puntos que "cargan" (para bloques dentro de una pantalla ya abierta) */
.dots { display: inline-flex; gap: 7px; }
.dots i { width: 8px; height: 8px; border-radius: 50%; background: var(--brand); display: block;
          animation: dotwave 1.1s var(--ease) infinite; }
.dots i:nth-child(2) { animation-delay: .14s; opacity: .8 }
.dots i:nth-child(3) { animation-delay: .28s; opacity: .6 }
@keyframes dotwave { 0%,100% { transform: translateY(0); } 40% { transform: translateY(-7px); } }

/* ─────────── Ícono de la app (favicon / pantalla de inicio) ─────────── */
.ic {
  display: inline-grid; place-items: center; flex: none;
  font-family: var(--font); font-weight: 800; letter-spacing: -.05em;
  border-radius: 22%; overflow: hidden; line-height: 1;
}
.ic b { color: var(--brand-bright); }

/* ─────────── Logo ───────────
   OJO: nada de flex acá. En un contenedor flex cada corrida de texto suelto
   se vuelve un ítem propio y el `gap` mete aire entre "Baire", "X" y ".".
   Es texto corrido y punto: así el kerning de General Sans hace su trabajo.  */
.lg {
  display: inline-block; font-family: var(--font); font-weight: 800;
  font-size: 1.12rem; line-height: 1.02; letter-spacing: -.035em;
  color: var(--ink); white-space: nowrap; font-style: normal;
}
.lg i { font-style: normal; color: var(--brand-strong); }   /* "Digital" */
.lg b { font-style: normal; color: var(--brand); }          /* el punto */
:root[data-theme="dark"] .lg i { color: var(--brand); }
:root[data-theme="dark"] .lg b { color: var(--brand-bright); }

.lg--stack { line-height: 1.06; letter-spacing: -.045em; }
.lg--xl { font-size: 2.2rem; }

/* Carga (D-41): el punto del logo es la PUNTA de tres suspensivos.
   Se mueve sólo en vertical — nunca escala — así que no engorda ni pisa
   la "l" de "Digital". Mismo gesto que .dots, para que sea el mismo idioma. */
.lg--cargando b {
  display: inline-block;
  animation: puntear 1.05s var(--ease) infinite;
}
.lg--cargando b:nth-of-type(2) { animation-delay: .13s; }
.lg--cargando b:nth-of-type(3) { animation-delay: .26s; }
@keyframes puntear {
  0%, 55%, 100% { transform: translateY(0); }
  27%           { transform: translateY(-.3em); }
}

/* ─────────── Header + tab bar ─────────── */
.appbar {
  position: sticky; top: 0; z-index: 30; background: var(--surface);
  border-bottom: 1px solid var(--line);
  padding: calc(var(--s-3) + env(safe-area-inset-top)) 0 var(--s-3);
}
/* El contenido del header respeta el mismo margen que el resto de la página:
   si el logo arranca pegado al borde y el texto de abajo no, se ve descolgado. */
.appbar__in {
  max-width: var(--frame); margin: 0 auto; padding: 0 var(--s-4);
  display: flex; align-items: center; gap: var(--s-3);
}
.wordmark { font: 800 1.06rem/1 var(--font); letter-spacing: -.3px; }
.wordmark em { color: var(--brand); font-style: normal; }
.iconbtn {
  width: 40px; height: 40px; border-radius: var(--r-pill); border: 1px solid var(--line);
  background: transparent; display: grid; place-items: center; cursor: pointer;
  position: relative; transition: all var(--fast); flex: none;
}
.iconbtn:hover { border-color: var(--brand); color: var(--brand); }
.iconbtn__dot { position: absolute; top: 7px; right: 8px; width: 8px; height: 8px;
                border-radius: 50%; background: var(--battle); border: 2px solid var(--surface); }

.tabbar {
  position: sticky; bottom: 0; z-index: 25; display: flex; background: var(--surface);
  border-top: 1px solid var(--line); padding-bottom: env(safe-area-inset-bottom);
}
.tabbar a {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 9px 0 11px; font: var(--t-micro); color: var(--muted);
  transition: color var(--fast);
}
.tabbar a[aria-current="page"] { color: var(--brand); }
@media (min-width: 900px) { .tabbar { display: none; } }

/* ─────────── Grillas ─────────── */
.grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-3); }
@media (min-width: 640px)  { .grid { grid-template-columns: repeat(3, 1fr); gap: var(--s-4); } }
@media (min-width: 1000px) { .grid { grid-template-columns: repeat(4, 1fr); } }
.grid--3 { grid-template-columns: repeat(2, 1fr); }
@media (min-width: 1000px) { .grid--3 { grid-template-columns: repeat(3, 1fr); } }

/* ─────────── Utilidades ─────────── */
.row  { display: flex; align-items: center; gap: var(--s-3); }
.between { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.col  { display: flex; flex-direction: column; }
.grow { flex: 1; min-width: 0; }
.muted{ color: var(--muted); }
.small{ font: var(--t-small); }
.micro{ font: var(--t-micro); color: var(--muted); letter-spacing: .04em; text-transform: uppercase; }
.title{ font: var(--t-title); }
.display { font: var(--t-display); letter-spacing: -.02em; }
.truncate { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stack > * + * { margin-top: var(--s-3); }
.hide { display: none !important; }

/* Entrada suave del contenido */
@keyframes rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.rise { animation: rise var(--med) both; }
.rise:nth-child(2){ animation-delay: .04s } .rise:nth-child(3){ animation-delay: .08s }
.rise:nth-child(4){ animation-delay: .12s } .rise:nth-child(5){ animation-delay: .16s }

/* Skeleton de carga */
@keyframes shimmer { 100% { background-position: -200% 0; } }
.skel { background: linear-gradient(90deg, var(--surface-2) 25%, var(--line) 50%, var(--surface-2) 75%);
        background-size: 200% 100%; animation: shimmer 1.4s infinite; border-radius: var(--r-sm); }
