/* DB Project — Servicios y precios. Solo lo que vive en esta página; el
   lenguaje compartido (tarjeta, marca de sección, costura, trazo, botones)
   está en css/components.css y css/base.css.

   Ritmo de tramos de la página:
     encabezado + 01   grafito
     costura           grafito → claro
     02 + 03           CLARO, los dos en el mismo material y sin costura entre
                       ellos: el precio de armado y la mensualidad son la misma
                       conversación, y el dinero merece el tramo más legible
     costura           claro → grafito, y ese corte es el que dice que se pasa
                       de la oferta a las condiciones
     04 + 05 + cierre  grafito

   Ninguna de estas reglas anima nada: los tramos son pintura, no presupuesto
   de scroll. */

/* ── Encabezado ──────────────────────────────────────────────────────────── */

.servicios-hero .lead { max-width: 46ch; }
/* Navegación interna, no un segundo llamado a contactar: quien entra a una
   página de precios entra buscando el número. La flecha baja en vez de avanzar
   porque el destino está más abajo en la misma página. */
.servicios-hero__ir { margin-top: var(--space-2); }
.servicios-hero__ir:hover .btn__flecha,
.servicios-hero__ir:focus-visible .btn__flecha { transform: translateY(4px); }

/* ── 01 · Qué construimos ─────────────────────────────────────────────────
   Tres bloques anchos, uno debajo del otro. El dibujo cambia de lado entre
   bloque y bloque para que el recorrido no sea una lista.

   Sin sticky a propósito: el bloque ya lleva parallax por data-speed
   (js/reveals.js), y pegarlo además al viewport haría que dos reglas peleen
   por la misma posición. */

.formato {
  display: grid;
  gap: var(--space-4);
  padding-block: var(--space-6);
  border-top: 1px solid var(--db-linea);
}
.formato:first-of-type { border-top: 0; }
.formato:last-of-type { padding-bottom: 0; }

@media (min-width: 900px) {
  /* El texto pesa más que el dibujo: son dos párrafos contra un esquema. */
  .formato {
    grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
    gap: var(--space-6);
    align-items: center;
    padding-block: var(--space-7);
  }
  /* El invertido no cambia solo el orden: también cambia qué columna es la
     ancha. Sin esto el texto caía en la columna angosta y los tres bloques
     quedaban con medidas de línea distintas. */
  .formato--invertido {
    grid-template-columns: minmax(0, 1.22fr) minmax(0, 0.78fr);
  }
  .formato--invertido .formato__visual { order: 2; }
  .formato--invertido .formato__texto { order: 1; }
}

.formato__visual { justify-items: start; display: grid; gap: var(--space-2); }
@media (min-width: 900px) { .formato__visual { justify-items: center; } }

/* El mismo dibujo del Inicio, con lugar de sobra: allá vive apretado dentro de
   una tarjeta de tres columnas, acá tiene media fila para él. */
.formato__visual .dibujo {
  width: 100%;
  max-width: 420px;
  height: auto;
  aspect-ratio: 200 / 120;
}

/* El trazo en reposo va bajado y sube a pleno el del bloque que se está
   mirando: es el mismo criterio de la 02 del Inicio. Los tres formatos son
   pares entre sí — cuál se lleva el acento lo decide el visitante, no
   nosotros, y siempre hay uno solo.
   .is-entered es el equivalente táctil: sin mouse no hay hover, así que
   js/servicios.js lo pone cuando el bloque entra en pantalla. */

.formato__texto h3 {
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin: 0 0 var(--space-3);
}

/* Qué incluye y para qué sirve, como lista de definiciones y no como dos
   párrafos con un <strong> adelante: son un rótulo y su respuesta, y el <dl>
   es lo que eso significa. El rótulo va en mono y chico, del otro extremo de
   la escala que el título — el mismo contraste que la marca de sección. */

/* ── 02 · Precios de armado ───────────────────────────────────────────────
   Los dos datos más buscados de la página: el número es el elemento grande y
   la palabra va chica al lado. La regla de arriba se dibuja de izquierda a
   derecha cuando el bloque entra, que es el mismo momento en que el número
   arranca a contar. */

/* ── El bloque de precio ──────────────────────────────────────────────────────
   BUG ARREGLADO (2026-09-06, ronda de simplificación): los dos números no se
   veían. Medido: se dibujaban en rgb(27,29,33) sobre un fondo rgb(27,29,33) —
   CONTRASTE 1.00. Grafito sobre grafito. Sólo sobrevivía la palabra "desde",
   que es gris medio, y por eso el bloque se leía como "desde / desde" sin
   ningún número.

   Causa raíz: la ronda anterior metió una LOSA DE GRAFITO dentro del tramo
   claro y le pidió color var(--db-texto-sobre-oscuro). Pero .tramo-claro
   redefine justamente ese token —"texto sobre oscuro" pasa a ser grafito
   dentro de un tramo claro, que es lo correcto para el tramo— así que la losa
   pedía "el color de texto para fondo oscuro" y recibía el del fondo claro.

   La losa se va entera. No se parcha el color: invertir el material dentro del
   tramo era una capa de sistema encima de otra, y el bloque no la necesitaba.
   Lo que lo distingue ahora es tipografía y una regla de acento — que era lo
   único que ya funcionaba de aquella versión. */
.precios__caja { margin-top: var(--space-5); }

.precios__grid {
  display: grid;
  gap: var(--space-4);
}
@media (min-width: 720px) {
  .precios__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-6); }
}

.precio {
  position: relative;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  padding-top: var(--space-4);
}
/* La regla de acento arriba de cada precio. Es un pseudo-elemento a escala y no
   un border-top que aparece: se resuelve en el compositor y se puede dibujar.
   El transform de .precio lo escribe GSAP (parallax de data-speed), así que
   este va en el ::before, que no tiene otro dueño.
   Vuelve a ser una regla POR PRECIO: sin la losa, no hay borde de bloque con el
   que compita. */
.precio::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 2px;
  background: var(--db-acento);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}
.precio.is-marcado::before { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
  /* Sin movimiento la regla está puesta desde el arranque: es el borde del
     bloque, no una decoración. */
  .precio::before { transform: scaleX(1); transition: none; }
}

.precio__eti { display: flex; align-items: baseline; gap: var(--space-2); margin: 0; }
.precio__que {
  font-size: var(--db-fs-body);
  font-weight: 600;
  color: var(--db-texto-sobre-oscuro);
}
.precio__desde {
  font-size: var(--db-fs-eti);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--db-gris-medio);
}

.precio__valor {
  margin: 0;
  font-size: clamp(2.5rem, 6.4vw, 4.25rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.035em;
  color: var(--db-texto-sobre-oscuro);
  font-variant-numeric: tabular-nums;
  /* La respuesta al apuntar. Va sobre el número y no sobre .precio, que ya
     tiene a GSAP escribiéndole el transform del parallax. */
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}
.precio:hover .precio__valor { transform: translateY(-4px); }

/* LA POLÍTICA DE PRECIOS, AL TAMAÑO QUE LE CORRESPONDE.
   Estaba en el cuerpo del sitio, o sea el mismo tamaño que cualquier párrafo de
   apoyo, cuando es la frase que responde la única objeción que tiene alguien
   mirando tres números: "¿y este número de dónde sale?". Sube por encima del
   lead y se apoya en un filete de acento, que es el mismo recurso que marca los
   precios de arriba. No es una nota al pie: es la respuesta. */
.precios__nota {
  margin-top: var(--space-6);
  max-width: 46ch;
  padding-left: var(--space-4);
  border-left: 2px solid var(--db-acento-sobre-claro);
  font-size: clamp(1.25rem, 1.06rem + 0.83vw, 1.625rem);
  line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--db-texto-sobre-claro);
}
.precios__nota a {
  color: inherit;
  text-decoration-color: var(--db-acento-sobre-claro);
  text-underline-offset: 4px;
}
.precios__pago {
  margin-top: var(--space-3);
  padding-left: var(--space-4);
  max-width: 56ch;
  margin-bottom: 0;
  font-size: var(--db-fs-small);
  letter-spacing: 0.04em;
  color: var(--db-gris-medio);
}

/* ── 03 · Mensualidad ─────────────────────────────────────────────────────
   Cuatro planes con el tratamiento único de tarjeta: fondo, borde, radio,
   número en mono arriba y el arco de luz del borde al apuntarlos
   (css/components.css + js/glow.js). Sin botón por plan: serían cuatro
   llamados a contactar repetidos arriba del único que la página necesita. */

.planes { margin-top: var(--space-6); display: grid; gap: var(--space-3); }
@media (min-width: 700px)  { .planes { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .planes { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.plan {
  padding: var(--space-4) var(--space-3);
  gap: var(--space-3);
  /* Columna flex para que las dos acciones se peguen al pie con margin-top:auto.
     Las cuatro listas tienen distinto largo, y con las acciones en el flujo
     quedaban a cuatro alturas distintas: cuatro botones desalineados leen como
     cuatro tarjetas sueltas en vez de como una comparación. */
  display: flex;
  flex-direction: column;
}

/* Las dos acciones de cada plan, al pie. "Ver qué incluye" abre la ficha con el
   detalle completo; "Me interesa" abre WhatsApp con el mensaje de ESE plan.
   El orden importa: primero informarse, después escribir. */
.plan__acciones {
  margin-top: auto;
  padding-top: var(--space-3);
  display: grid;
  gap: var(--space-2);
  justify-items: start;
}
@media (min-width: 1280px) { .plan { padding: var(--space-4); } }

/* Alto fijo de cabecera y de la línea de "para quién": así el precio, la frase
   y el primer ítem de la lista arrancan a la misma altura en las cuatro
   columnas. Con las alturas libres, cuatro listas que empiezan en cuatro
   alturas distintas se leen como cuatro bloques sueltos, no como una
   comparación. Solo desde 1100, que es cuando conviven en fila. */
@media (min-width: 1100px) {
  .plan__head { min-height: 96px; }
  .plan__para { min-height: 4.9em; }
}
.plan__head { display: grid; gap: var(--space-1); }
/* .plan .X y no .X a secas: el plan es una .card, y css/components.css tiene
   una regla .card p (0,1,1) que le fija el color a TODO párrafo de adentro. Un
   selector de clase sola (0,1,0) pierde contra esa, y el precio y la etiqueta
   quedaban en gris de apoyo en vez de llevar su color propio. */
.plan .plan__head h3 { font-size: var(--db-fs-h3); }
.plan .plan__precio {
  margin: 0;
  font-size: 1.75rem;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--db-texto-sobre-oscuro);
  font-variant-numeric: tabular-nums;
}
.plan .plan__precio span {
  font-size: var(--db-fs-small);
  font-weight: 400;
  letter-spacing: 0;
  color: var(--db-gris-medio);
}
.plan .plan__para { font-size: var(--db-fs-small); line-height: 1.55; }

/* El destacado se distingue por borde y por una etiqueta chica, nunca por
   fondo de color: el acento no va de fondo de bloque. Es el único elemento de
   esta sección a plena saturación en reposo.

   Los cuatro estados van juntos a propósito. El borde de .card en reposo es
   apagado y SUBE al apuntarlo (38%) o al tocarlo (.is-lit); el de este plan ya
   nace a pleno, así que esas mismas reglas —que son más específicas— lo hacían
   BAJAR justo cuando se lo estaba mirando. Medido con Playwright: el borde del
   plan Activo pasaba de opaco a 38% de alfa al pasarle el mouse por encima. */
.plan--destacado,
.plan--destacado:hover,
.plan--destacado:focus-within,
.plan--destacado.is-lit,
.plan--destacado.is-entered { border-color: var(--db-acento); }
.plan .plan__flag {
  position: absolute;
  top: calc(var(--space-2) * -1);
  left: var(--space-3);
  margin: 0;
  font-size: var(--db-fs-eti);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--db-acento);
  /* El fondo del tramo, no un color propio: la etiqueta corta el borde de la
     tarjeta y tiene que pisar exactamente el material que hay detrás. */
  background: var(--db-tramo-claro);
  padding-inline: var(--space-1);
}

.plan__items {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
  font-size: var(--db-fs-small);
  line-height: 1.5;
  color: var(--db-gris-medio);
}
.plan__items li {
  position: relative;
  padding-left: var(--space-3);
  transition: opacity 0.35s ease, color 0.35s ease;
}
.plan__items li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 8px;
  height: 1px;
  background: var(--db-acento);
  opacity: 0.55;
  transform-origin: left;
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.3s ease;
}

/* El movimiento que hace útil esta sección. Cada plan arrastra todo lo del
   anterior, así que en reposo los cuatro se ven iguales. Al apuntar uno, la
   línea heredada se apaga y quedan encendidos solo los ítems que ese plan
   SUMA: responde de un vistazo la pregunta real, que es qué gano si subo.
   Es opacidad y una escala, nada de layout — se resuelve en el compositor.
   Equivalente táctil: js/servicios.js pone .is-sumando cuando la tarjeta entra
   en pantalla. */
.plan.is-sumando .plan__items li[data-heredado] { opacity: 0.34; }
.plan.is-sumando .plan__items li:not([data-heredado]) { color: var(--db-texto-sobre-oscuro); }
.plan.is-sumando .plan__items li:not([data-heredado])::before {
  transform: scaleX(2);
  opacity: 1;
}

/* "Qué te avisamos, y cuándo". Cierra la sección 03 en texto, no en tarjetas:
   los cuatro planes ya son la comparación, y una quinta fila de cajas la
   diluye. No estrena escala tipográfica ni marcador propio — el título toma el
   mismo escalón que .ac__titulo (una pregunta dentro de una sección, no un
   título de sección) y los ítems reusan el renglón de acento de .plan__items,
   porque son la misma clase de enunciado: una condición del servicio. */
.avisos { margin-top: var(--space-6); }
.avisos__titulo {
  margin: 0 0 var(--space-3);
  font-size: clamp(1.25rem, 1.5vw, 1.375rem);
  font-weight: 600;
  line-height: 1.3;
  text-wrap: balance;
}
.avisos__items {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
  font-size: var(--db-fs-small);
  line-height: 1.55;
  color: var(--db-gris-medio);
  max-width: 62ch;
}
/* Mismo renglón corto que .plan__items li::before, en reposo. Acá no se
   enciende con el puntero: no hay nada que comparar entre los cuatro ítems,
   son cuatro reglas que valen igual. */
.avisos__items li { position: relative; padding-left: var(--space-3); }
.avisos__items li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.7em;
  width: 8px;
  height: 1px;
  background: var(--db-acento);
  opacity: 0.55;
}
/* Desde 1100 los planes van en cuatro columnas y el bloque queda con toda la
   fila para él: se corre a la mitad derecha, alineado con la tercera columna,
   para que no arranque colgado del borde izquierdo con medio ancho vacío. */
@media (min-width: 1100px) {
  .avisos {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
    gap: var(--space-3) var(--space-6);
    align-items: start;
  }
  .avisos__titulo { margin-bottom: 0; }
}

/* Tres párrafos en un mismo panel del acordeón necesitan aire entre sí:
   .ac__cuerpo p lleva margin 0 (bien, para el panel de un solo párrafo), así
   que el espacio lo pone el contenedor. Solo en esta página. */
.letra-chica .ac__cuerpo { display: grid; gap: var(--space-2); }


/* ── 04 · La letra chica ──────────────────────────────────────────────────
   Acordeón cerrado por defecto, uno abierto a la vez. El encabezado y el
   acordeón se desplazan a distinta velocidad durante el scroll (data-speed):
   esa es la capa que sigue viva sin que nadie toque nada. */

@media (min-width: 1024px) {
  .letra-chica .container {
    display: grid;
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    gap: var(--space-7);
    /* start y no stretch: con las dos columnas estiradas, el parallax de la
       izquierda mueve una caja del alto del acordeón entero y no se percibe. */
    align-items: start;
  }
}
.letra-chica__cab .marca { margin-bottom: var(--space-3); }
.letra-chica__cab h2 { margin-bottom: 0; }
@media (max-width: 1023px) { .acordeon { margin-top: var(--space-5); } }

.ac { border-top: 1px solid var(--db-linea); }
.ac:last-child { border-bottom: 1px solid var(--db-linea); }

.ac__cab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  /* 64px de alto real: el cabezal entero es el objetivo táctil, no la flecha. */
  min-height: 64px;
  padding-block: var(--space-2);
  cursor: pointer;
  list-style: none;
}
.ac__cab::-webkit-details-marker { display: none; }
.ac__cab::marker { content: ""; }
.ac__cab:focus-visible { outline-offset: -2px; }

.ac__titulo {
  margin: 0;
  /* Sube al piso del nivel 3: valía 17px en el celular, que para una pregunta
     que además es el objetivo táctil del acordeón era chico de más. Techo
     propio y bajo porque es una pregunta dentro de una lista, no un título de
     bloque: 20 → 22px. */
  font-size: clamp(1.25rem, 1.5vw, 1.375rem);
  font-weight: 600;
  line-height: 1.3;
  text-wrap: balance;
  transition: color 0.25s ease, transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}
.ac__cab:hover .ac__titulo,
.ac__cab:focus-visible .ac__titulo { color: var(--db-acento); transform: translateX(5px); }
.ac[open] .ac__titulo { color: var(--db-acento); }

.ac__flecha {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--db-linea);
  border-radius: 999px;
  color: var(--db-gris-medio);
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1),
              border-color 0.3s ease, color 0.3s ease;
}
.ac__flecha svg { width: 18px; height: 18px; }
.ac[open] .ac__flecha { transform: rotate(180deg); border-color: var(--db-acento); color: var(--db-acento); }
.ac__cab:hover .ac__flecha { border-color: var(--db-acento); color: var(--db-acento); }

/* clip y no hidden: recorta el panel mientras la altura se anima sin
   convertirlo en un contenedor de scroll. */
.ac__panel { overflow: clip; }
.ac__cuerpo { padding-bottom: var(--space-4); }
.ac__cuerpo p { margin: 0; max-width: 62ch; }

@media (prefers-reduced-motion: reduce) {
  .ac__titulo, .ac__flecha { transition: none; }
  .ac__cab:hover .ac__titulo, .ac__cab:focus-visible .ac__titulo { transform: none; }
}

/* ── 05 · Lo que se puede conectar — pantalla partida ─────────────────────
   A la izquierda una hoja de cálculo de verdad; a la derecha, la porción de
   sitio que corresponde a la fila activa. El scroll ilumina una fila, cambia su
   valor, y la vista de la derecha se actualiza con él. Cuatro veces.

   La estética de hoja de cálculo es literal a propósito: líneas de grilla
   finas, celdas rectangulares (radio cero, el único lugar del sitio donde se
   permite), mono en todo. Es la única forma de que se lea "esto es tu planilla"
   sin escribirlo — y es el caso en que una grilla de líneas finas está
   justificada: hay una herramienta de datos real debajo, no una textura. */

.planilla { margin-top: var(--space-6); }

/* La PISTA es puro recorrido de scroll: no tiene contenido propio, sólo alto. El
   rango efectivo es su alto menos el de la pantalla.
   Estaba en 260svh: 2340px a 900 de alto, o sea que este bloque solo se comía
   2,6 pantallas para mostrar cuatro filas. Medido: la sección entera daba 2732px
   con menos de 400 de contenido visible.
   185svh deja 765px de rango efectivo, unos 190 por paso — bastante más que una
   muesca de rueda (~100px), que era el piso real: por debajo de eso la secuencia
   se pasa de largo antes de que se llegue a leer ninguna de las cuatro
   relaciones. Se recortan 675px sin tocar la legibilidad de la demostración. */
.planilla__pista { height: 185svh; }

/* La ESCENA se queda quieta mientras la pista pasa. Es el sticky del original de
   la biblioteca, que el porteo anterior no había traído. */
/* Los hijos de una grilla nacen con min-width:auto, o sea que no pueden achicarse
   por debajo de su contenido mínimo. La hoja simulada mide 290px de min-content,
   así que a 320px de pantalla empujaba su celda a 316 y desbordaba la página 20px.
   min-width:0 le devuelve el permiso de achicarse; lo que sobra lo recorta el
   overflow:hidden que .sitio ya tenía puesto para eso. */
.planilla__escena > * { min-width: 0; }

.planilla__escena {
  position: sticky;
  /* Debajo de la barra flotante, con el aire que ya calcula --nav-clearance
     (incluye el recorte de pantalla del teléfono). */
  top: var(--nav-clearance);
  min-height: calc(100svh - var(--nav-clearance) - var(--space-6));
  display: grid;
  align-content: center;
  gap: var(--space-4);
}
@media (min-width: 900px) {
  /* La hoja pesa más que el sitio porque tiene cuatro columnas de texto y el
     sitio es una vista sola. La nota cruza las dos: vive DENTRO de la escena
     porque quien llega scrolleando ya dejó atrás el título de la sección, y sin
     ella la demostración es una planilla y una ventana sin explicación. */
  .planilla__escena {
    /* Se da vuelta la proporción. La hoja tiene cuatro columnas de texto y por
       eso pesaba más, pero el efecto NO pasa en la hoja: pasa en el sitio, que
       es la ventana de la derecha. Poniendo la ventana más grande, lo que se
       mira es lo que cambia. */
    grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
    column-gap: var(--space-5);
    align-items: center;
  }
  .planilla__nota { grid-column: 1 / -1; }
}
.planilla__nota { margin-top: var(--space-3); }

.planilla__hoja {
  border: 1px solid color-mix(in srgb, var(--db-gris-medio) 34%, transparent);
  background: color-mix(in srgb, var(--db-blanco) 3%, var(--db-grafito));
  overflow: clip;
}
.hoja { display: grid; }
/* Cuatro columnas: referencia, hoja, contenido, estado. La de contenido es la
   que cede cuando falta ancho — minmax(0,·) en las tres flexibles para que el
   texto largo no las infle y desborde la caja en 375. */
.hoja__fila {
  display: grid;
  grid-template-columns: 28px minmax(0, 0.95fr) minmax(0, 1.15fr) minmax(0, 0.85fr);
  align-items: stretch;
  position: relative;
  font-size: 0.75rem;
}
@media (min-width: 1024px) { .hoja__fila { font-size: 0.9375rem; } }
/* El resaltado de la fila activa es un pseudo-elemento a escala, no un cambio
   de background-color: escalar se resuelve en el compositor y esto se anima con
   scrub, o sea en cada frame de scroll. */
.hoja__fila::before {
  content: "";
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--db-acento) 14%, transparent);
  /* La escala la escribe GSAP a través de --db-fila, no de una clase: así el
     resaltado sigue al scroll con scrub y no salta de 0 a 1. Animar una
     variable CSS deja el trabajo en el compositor igual que un transform. */
  transform: scaleX(var(--db-fila, 0));
  transform-origin: left;
  pointer-events: none;
}
.hoja__fila { --db-fila: 0; }

/* La respuesta al apuntar una fila: un filo de acento en el canto izquierdo.
   No mueve la secuencia —esa la manda el scroll— sino que confirma que la fila
   es una cosa señalable. El equivalente táctil es la secuencia misma: sin
   mouse, cada fila se enciende sola al pasar por ella. */
.hoja__fila[data-fila]::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--db-acento);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}
@media (hover: hover) {
  .hoja__fila[data-fila]:hover::after { transform: scaleY(1); }
  .hoja__fila[data-fila]:hover .hoja__celda { color: var(--db-blanco); }
}

.hoja__celda {
  display: flex;
  align-items: center;
  padding: 10px var(--space-1);
  /* Las hairlines de la grilla. Van en dos bordes por celda y no en un
     background repetido: así siguen a la celda si cambia de alto. */
  border-right: 1px solid color-mix(in srgb, var(--db-gris-medio) 22%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--db-gris-medio) 22%, transparent);
  color: var(--db-gris-claro);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  position: relative;
  transition: color 0.25s ease;
}
.hoja__fila:last-child .hoja__celda { border-bottom: 0; }
.hoja__celda:last-child { border-right: 0; }
/* El gris de los rótulos de la hoja. No es --db-gris-medio: ese está calibrado
   a 4,97:1 contra el grafito de la página, pero acá el fondo son DOS capas más
   claras encima —la hoja (#232529) y el propio tinte de la celda de rótulo—, y
   sobre ese #26282C el mismo gris cae a 3,4:1. Medido con Playwright. Sube lo
   mínimo para volver a pasar AA (5,9:1) sin igualar al gris de los datos, que
   es lo que haría desaparecer la diferencia entre rótulo y contenido. */
.hoja {
  --db-hoja-rotulo: color-mix(in srgb, var(--db-gris-claro) 60%, var(--db-gris-medio));
}

/* La columna de referencia, como el número de fila de una planilla real. */
.hoja__celda--ref {
  justify-content: center;
  color: var(--db-hoja-rotulo);
  background: color-mix(in srgb, var(--db-blanco) 4%, transparent);
  padding-inline: 0;
}
.hoja__fila--enc .hoja__celda {
  color: var(--db-hoja-rotulo);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  /* 11px y no 10: por debajo de 11 un rótulo en mayúsculas con tracking deja de
     leerse en un celular, y es el rótulo el que dice qué es cada columna. */
  font-size: var(--db-fs-eti);
  background: color-mix(in srgb, var(--db-blanco) 4%, transparent);
}

/* La celda de estado es una VENTANA: el valor viejo sale hacia arriba y el
   nuevo entra desde abajo, apilados en la misma caja. Se lee como la celda
   cambiando, no como un texto que desaparece y otro que aparece. */
.hoja__celda--val { padding: 0; display: grid; overflow: hidden; color: var(--db-blanco); }
.hoja__v {
  grid-area: 1 / 1;
  padding: 10px var(--space-1);
  will-change: transform;
}
/* El valor "b" nace invisible, apilado sobre el "a" en la misma celda de
   grilla. Sólo opacidad, sin transform: el desplazamiento lo escribe GSAP, y
   dos dueños del mismo transform hacen que el tween arranque desde un valor que
   no es el que se ve. Sin JS el "b" no aparece nunca, que es lo correcto: el
   estado de reposo de la planilla es el valor original. */
.hoja__v[data-v="b"] { opacity: 0; }

/* Tope de ancho: sólo hay UNA vista a la vez, así que un marco tan ancho como
   la columna quedaba con la vista chiquita en el medio de un vacío. 380px es el
   ancho al que la reseña —la vista más ancha— llena el marco sin estirarse. */
.sitio {
  /* De 460 a 560: la ventana es donde pasa el efecto y era el objeto más chico
     de la escena. Con la columna dada vuelta (ver .planilla__escena) y este
     ancho, la ventana pesa más que la tabla, que es el orden correcto — la
     tabla es la causa y la ventana es lo que se mira. */
  max-width: 560px;
  margin-inline: auto;
  border: 1px solid color-mix(in srgb, var(--db-blanco) 14%, transparent);
  border-radius: var(--db-radius-card);
  overflow: hidden;
  background: color-mix(in srgb, var(--db-blanco) 4%, var(--db-grafito));
  box-shadow: 0 24px 60px -22px rgba(0, 0, 0, 0.6);
}
/* Igual que el mockup del hero: el interior es una pantalla encendida, más
   clara que la página. Es el mismo objeto conceptual, se pinta igual.
   Las cuatro vistas se apilan en la MISMA celda de grilla: el marco mide lo que
   mide la más alta y no hace falta fijarle un alto en píxeles. */
.sitio__cuerpo {
  display: grid;
  padding: var(--space-2);
  /* La ventana crece con la escena. Antes medía 116px porque el bloque vivía
     apretado en el flujo; con la escena quieta y media pantalla libre, la vista
     puede tener el tamaño al que se lee de verdad. Con el alto viejo, la ventana
     quedaba como una tarjetita perdida al lado de una tabla de cuatro filas, y
     la relación entre las dos —que es todo el argumento— se leía descompensada. */
  min-height: clamp(180px, 30svh, 300px);
  background: color-mix(in srgb, var(--db-blanco) 13%, var(--db-grafito));
}
.vista {
  grid-area: 1 / 1;
  align-self: center;
  display: grid;
  gap: var(--space-2);
  justify-items: center;
  will-change: transform;
}
/* Sólo la primera está a la vista de arranque. Sin JS —o sin movimiento— el
   bloque muestra la primera fila y su vista, quietas y coherentes entre sí. */
.vista:not([data-vista="0"]) { opacity: 0; }

/* El par a↔b: los dos estados apilados en la misma celda. Un solo mecanismo
   para las cuatro vistas, sea un texto que cambia o una marca que se enciende.
   inline-grid y no grid: dentro de la píldora del turnero el par convive con
   texto en la misma línea, y un grid de bloque lo bajaría a un renglón propio. */
.vista__par { display: inline-grid; overflow: hidden; vertical-align: bottom; }
.vista__par > * { grid-area: 1 / 1; will-change: transform; }
.vista__par > [data-v="b"] { opacity: 0; }
.vista__par--bloque { width: 100%; max-width: 340px; }

/* 1 · calendario */
.vista__dias { display: flex; gap: 7px; font-size: 0.9375rem; color: var(--db-gris-medio); }
.vista__dias > span {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 5px;
}
/* El día marcado. Las dos marcas son <i> propios detrás del número, no un
   background sobre la celda: así el cambio se anima con transform y opacidad
   —nada de color— y el número queda legible en los dos estados. */
.vista__dia { position: relative; color: var(--db-blanco); }
.vista__dia > b { position: relative; font-weight: 600; }
.vista__marca { position: absolute; inset: 0; border-radius: 4px; }
.vista__marca--libre {
  border: 1px solid var(--db-acento);
  background: color-mix(in srgb, var(--db-acento) 22%, transparent);
}
.vista__marca--tomado {
  border: 1px solid color-mix(in srgb, var(--db-gris-medio) 60%, transparent);
  background: color-mix(in srgb, var(--db-gris-medio) 26%, transparent);
  opacity: 0;
}
.vista__pie { font-size: 0.8125rem; letter-spacing: 0.08em; color: var(--db-gris-claro); margin: 0; }

/* 2 · ficha de producto */
.vista__prod { display: flex; align-items: center; gap: 14px; }
.vista__foto {
  width: 62px;
  height: 50px;
  border-radius: 5px;
  flex-shrink: 0;
  background: color-mix(in srgb, var(--db-gris-medio) 34%, transparent);
}
.vista__lineas { display: grid; gap: 7px; }
.vista__lineas > i { display: block; height: 6px; border-radius: 2px; background: color-mix(in srgb, var(--db-gris-medio) 40%, transparent); }
.vista__lineas > i:first-child { width: 96px; }
.vista__lineas > i:last-child { width: 62px; }
.vista__precio { margin: 0; font-size: 1.375rem; font-weight: 600; color: var(--db-blanco); }

/* 3 · la reseña. El estado de reposo es el hueco: la reseña está cargada en la
   planilla pero no publicada. Al cambiar el estado, aparece. */
.vista__hueco {
  display: block;
  height: 64px;
  border: 1px dashed color-mix(in srgb, var(--db-gris-medio) 40%, transparent);
  border-radius: 8px;
}
.vista__resena {
  display: flex;
  align-items: center;
  gap: 14px;
  height: 64px;
  padding-inline: 14px;
  border: 1px solid color-mix(in srgb, var(--db-blanco) 12%, transparent);
  border-radius: 8px;
  background: color-mix(in srgb, var(--db-grafito) 40%, transparent);
}
.vista__avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  flex-shrink: 0;
  background: color-mix(in srgb, var(--db-gris-medio) 40%, transparent);
}
.vista__resena-txt { display: grid; gap: 6px; }
.vista__estrellas { width: 76px; height: 13px; fill: var(--db-acento); }
.vista__resena-txt > i { display: block; height: 5px; border-radius: 2px; background: color-mix(in srgb, var(--db-gris-medio) 40%, transparent); }
.vista__resena-txt > i:first-of-type { width: 116px; }
.vista__resena-txt > i:last-of-type { width: 78px; }

/* 4 · turnero */
.vista__turnos { display: flex; gap: 8px; font-size: 0.875rem; }
.vista__turno {
  padding: 9px 14px;
  border: 1px solid color-mix(in srgb, var(--db-gris-medio) 34%, transparent);
  border-radius: 999px;
  color: var(--db-gris-medio);
}
.vista__turno--foco { border-color: var(--db-acento); color: var(--db-blanco); }

.planilla__nota {
  margin: 0;
  max-width: 62ch;
  color: var(--db-gris-claro);
}

/* En 375 las cuatro columnas no entran sin cortar palabras a la mitad: quedaba
   "Disponibilida", "Cabaña del río" y "Porcelanato 60x". La fila se parte en dos
   renglones —arriba la hoja, abajo su contenido y su estado— y sigue siendo una
   fila: mismo resaltado, mismo borde, ningún dato perdido. Los encabezados se
   van porque ahí ya no encabezan nada: con la fila partida, la etiqueta de
   arriba ES el encabezado de lo de abajo. */
@media (max-width: 639px) {
  .hoja__fila {
    grid-template-columns: 24px minmax(0, 1fr) auto;
    grid-template-areas:
      "ref hoja      hoja"
      "ref contenido estado";
    /* Los dos renglones se tocaban: medido a 375, el nombre de la hoja y su
       valor se montaban 4px. Poco, pero son dos textos encimados. */
    row-gap: 3px;
  }
  .hoja__fila--enc { display: none; }
  .hoja__celda:nth-child(1) { grid-area: ref; }
  .hoja__celda:nth-child(2) {
    grid-area: hoja;
    padding-bottom: 0;
    border-bottom: 0;
    border-right: 0;
    color: var(--db-blanco);
    letter-spacing: 0.06em;
  }
  .hoja__celda:nth-child(3) { grid-area: contenido; padding-top: 4px; border-right: 0; }
  .hoja__celda--val { grid-area: estado; }
  .hoja__celda--val .hoja__v { padding-top: 4px; }
}

@media (prefers-reduced-motion: reduce) {
  /* Sin movimiento se muestra el estado inicial completo y quieto: la primera
     fila de la planilla al lado de su vista, con la nota abajo diciendo la
     relación. Los valores "b" no quedan a mitad de camino: no existen. */
  .hoja__v[data-v="b"], .vista__par > [data-v="b"] { display: none; }
}

/* El cierre de dos vías (.cierre__acciones y el techo del título) se fue a
   css/components.css: Servicios y Proceso terminan con el mismo llamado, y una
   copia por página es como dejan de parecerse. */

/* ── Toda la tarjeta de formato es el objetivo ───────────────────────────────
   Pieza: "Focus Cards" (db-project-biblioteca, references/tarjetas.md) — en el
   original, al mirar una tarjeta de la grilla las demás se apagan; acá los
   bloques son uno por fila, así que de la pieza se porta lo que aplica: el área
   entera es el objetivo, y el resto de la fila se atenúa mientras se apunta a
   uno. El patrón del área estirada es .todo-clic (css/components.css). */
.formato { position: relative; isolation: isolate; }
/* Acá la variante en capa, no el ::after del título: .formato__texto lleva
   data-speed, o sea un transform de parallax permanente, y un transform crea
   bloque contenedor. Medido: el área estirada cubría sólo la columna de texto,
   así que tres de los cinco puntos de prueba daban ✗ en las tres tarjetas. */
.formato:has(.todo-clic:focus-visible) {
  outline: 2px solid var(--db-acento);
  outline-offset: 6px;
  border-radius: var(--radio-md, 12px);
}
/* Lo decorativo por debajo del área tocable; el texto por encima, para que se
   pueda seleccionar con el dedo. */
.formato__visual { z-index: 0; }
.formato__texto p { position: relative; z-index: 1; }

/* La otra mitad de Focus Cards: al apuntar a un formato, los otros dos bajan.
   Sólo con puntero fino — en el teléfono no hay "el que estoy mirando". */
@media (hover: hover) and (pointer: fine) {
  #construimos .container:hover .formato:not(:hover) { opacity: 0.52; }
  .formato { transition: opacity 0.4s ease; }
}
@media (prefers-reduced-motion: reduce) {
  .formato { transition: none; }
}

/* ── FAMILIA 3 · planes → "Comet Card" ───────────────────────────────────────
   Pieza de db-project-biblioteca, references/tarjetas.md: tilt en 3D con un
   reflejo suave que sigue al puntero, declarada ahí para "un plan destacado".
   Va sólo en el destacado: cuatro columnas inclinándose a la vez son ruido, una
   sola inclinándose es la que estás mirando. El tilt lo escribe js/tarjetas.js;
   acá vive el reflejo, que es CSS puro con dos variables.
   La familia se distingue de las otras cuatro por su forma antes que por esto:
   es la única con precio grande y dos acciones al pie. */
.plan--destacado { position: relative; isolation: isolate; will-change: transform; }
.plan--destacado::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(circle at var(--brillo-x, 50%) var(--brillo-y, 0%),
    color-mix(in srgb, var(--db-blanco) 32%, transparent) 0%,
    transparent 55%);
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
  z-index: 2;
}
.plan--destacado:hover::after { opacity: 1; }

/* Equivalente táctil: sin puntero no hay reflejo que seguir, así que el
   destacado se queda con el frame final del efecto —levantado y con el reflejo
   fijo arriba— en vez de quedarse sin nada. Es lo que la propia ficha recomienda
   para movimiento reducido. */
@media (hover: none), (prefers-reduced-motion: reduce) {
  .plan--destacado { transform: none; }
  .plan--destacado::after { opacity: 0.55; }
}


/* ═════════════════════════════════════════════════════════════════════════════
   LAS HOJAS — la representación de cada formato

   Antes acá iban las mismas miniaturas de ventana del Inicio, en tamaño grande.
   Esa ventana ya aparece en el hero, en las tres tarjetas de la 02, en los
   paneles de Proceso y en las fichas: para cuando alguien llega a esta página,
   una ventanita más no dice nada nuevo.

   Pieza: Images Badge (db-project-biblioteca, references/carruseles-galerias.md)
   — la carpeta cuyos papeles se abanican. Del original se toman los números
   exactos del abanico: y −35px, x (i)·20, rotación (i)·15°, escalonado por
   índice. Lo que cambia es qué se abanica: no fotos de una galería, sino las
   PÁGINAS del sitio. Y la cantidad de hojas es el dato — una landing es una
   hoja, un sitio son varias, y lo que separa a la tienda no es cuántas páginas
   tiene sino que cobra, así que lleva el carro.

   Sin JS: el abanico es una transición de transform sobre :hover del artículo, y
   el equivalente táctil es la misma transición disparada por la clase que pone
   el observador de entrada. Sin listener, sin rAF, sin nada que mantener.
   ═══════════════════════════════════════════════════════════════════════════ */
.hojas {
  position: relative;
  width: min(100%, 300px);
  /* Cuadrada y no 4/3: las hojas son altas (3/4) y al abanicarse suben 24px más.
     Con la caja apaisada el abanico se salía por arriba y el carro quedaba
     recortado abajo. Medido: la hoja arrancaba en y=-1 dentro de una caja de
     225 de alto. */
  aspect-ratio: 1 / 1;
  margin-inline: auto;
  perspective: 900px;
}
.hojas__hoja {
  position: absolute;
  left: 50%;
  bottom: 14%;
  width: 52%;
  /* Proporción de una página: alta, no apaisada. Es lo que la hace leerse como
     una hoja y no como una tarjeta. */
  aspect-ratio: 3 / 4;
  border-radius: 6px;
  border: 1px solid color-mix(in srgb, var(--db-acento) 60%, transparent);
  background: linear-gradient(160deg,
    color-mix(in srgb, var(--db-grafito) 92%, var(--db-acento)),
    color-mix(in srgb, var(--db-grafito) 98%, var(--db-blanco)));
  /* Los renglones de la hoja: tres líneas y un bloque, dibujados con un solo
     background en vez de nodos hijos. */
  box-shadow: inset 0 0 0 0 transparent;
  transform: translateX(-50%) rotate(calc(var(--i) * 5deg));
  transform-origin: bottom center;
  transition: transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}
/* El texto de la hoja. Renglones, no palabras: es una miniatura. */
.hojas__hoja::after {
  content: "";
  position: absolute;
  inset: 14% 16% auto;
  height: 46%;
  background:
    linear-gradient(color-mix(in srgb, var(--db-acento) 55%, transparent) 0 0) 0 0 / 70% 7% no-repeat,
    linear-gradient(color-mix(in srgb, var(--db-acento) 26%, transparent) 0 0) 0 26% / 100% 5% no-repeat,
    linear-gradient(color-mix(in srgb, var(--db-acento) 26%, transparent) 0 0) 0 44% / 88% 5% no-repeat,
    linear-gradient(color-mix(in srgb, var(--db-acento) 26%, transparent) 0 0) 0 62% / 94% 5% no-repeat;
}
/* Una sola hoja no se abanica: se levanta. Abanicar una hoja sola es un gesto
   sin contenido — no hay nada de lo que separarse. */
.hojas--una .hojas__hoja { width: 58%; }

/* EL ABANICO. La rotación es la del original (15° por índice); la separación
   horizontal sube de 20px a 38: los 20 del original son para un badge de unos
   40px de ancho, y acá la caja mide 300 — con 20 las tres hojas se pisan y no se
   distingue que son tres. Es la misma proporción, no otro valor. */
.formato:hover .hojas--varias .hojas__hoja,
.formato.es-visible .hojas--varias .hojas__hoja {
  transform: translateX(calc(-50% + var(--i) * 38px)) translateY(-24px)
             rotate(calc(var(--i) * 15deg));
}
.formato:hover .hojas--una .hojas__hoja,
.formato.es-visible .hojas--una .hojas__hoja {
  transform: translateX(-50%) translateY(-14px) scale(1.04);
}
/* El escalonado por índice del original (delay = índice · 0,03s). Sale de --i,
   que cada hoja ya declara para su rotación: tres reglas nth-child decían lo
   mismo y había que tocarlas si algún formato cambia de cantidad de hojas. */
.hojas__hoja { transition-delay: calc((var(--i) + 1) * 0.03s); }

/* El carro de la tienda. Aparece con el abanico, no antes: primero se ve que
   son páginas, después que además cobran. */
.hojas__carro {
  position: absolute;
  right: 6%;
  bottom: 4%;
  width: 46px;
  height: 40px;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.4s ease 0.12s, transform 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.12s;
}
.hojas__carro::before {
  content: "";
  position: absolute;
  left: 0; top: 6px;
  width: 34px; height: 22px;
  border: 2px solid var(--db-acento);
  border-radius: 2px 2px 8px 8px;
  border-top-color: transparent;
}
.hojas__carro::after {
  content: "";
  position: absolute;
  left: 4px; top: 32px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--db-acento);
  box-shadow: 18px 0 0 var(--db-acento), -2px -28px 0 -1px var(--db-acento);
}
.formato:hover .hojas__carro,
.formato.es-visible .hojas__carro { opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  /* Sin movimiento el abanico queda ABIERTO, no cerrado: cerrado se perdería la
     información de cuántas páginas tiene el formato, que es todo el punto. */
  .hojas__hoja, .hojas__carro { transition: none; }
  .hojas--varias .hojas__hoja {
    transform: translateX(calc(-50% + var(--i) * 38px)) translateY(-24px)
               rotate(calc(var(--i) * 15deg));
  }
  .hojas__carro { opacity: 1; transform: none; }
}


/* ═════════════════════════════════════════════════════════════════════════════
   EL BLOQUE CONECTABLE — tratamiento propio y enganchado al anterior

   Traía la apertura estándar de sección (marca + h2 + lead a la derecha), la
   misma de las otras cinco de la página, así que se leía como una sección más
   empezada de cero. Pero no es independiente: es la continuación de la
   mensualidad — es lo que el plan te deja hacer a vos sin llamarnos. Y es el
   único bloque de la página que MUESTRA algo funcionando en vez de contarlo.
   ═══════════════════════════════════════════════════════════════════════════ */

/* El enganche. Una línea que baja del bloque anterior con su etiqueta al medio:
   el ojo la sigue hacia abajo y entiende que esto viene de arriba. Va como
   pseudo-contenido de un <p> vacío y no como borde de la sección porque tiene
   que quedar CENTRADA y sobresalir hacia arriba del padding. */
.conectable__hilo {
  position: relative;
  display: grid;
  place-items: center;
  height: clamp(72px, 9vw, 112px);
  /* max-width explícito: <p> hereda max-width:68ch de la tipografía del sitio, y
     con eso el "left:50%" de la línea se resuelve contra un bloque angosto
     alineado a la izquierda — medido a 1440, la línea caía en x=537 con el
     centro de la página en 720. Es el mismo caso ya documentado en
     .ap-centro__ir (css/aperturas.css). */
  max-width: none;
  margin: calc(var(--space-5) * -1) auto var(--space-5);
}
.conectable__hilo::before {
  content: "";
  position: absolute;
  inset: 0 auto;
  left: 50%;
  width: 1px;
  background: linear-gradient(to bottom,
    transparent, var(--db-linea) 22%, var(--db-linea) 78%, transparent);
}
.conectable__hilo span {
  position: relative;
  padding: 2px var(--space-2);
  background: var(--db-grafito);
  font-family: var(--db-font-mono);
  font-size: var(--db-fs-eti);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--db-gris-medio);
}

/* La cabecera propia. Centrada y en columna, no en dos columnas como la
   apertura de sección: es un anuncio de lo que vas a ver, no el arranque de un
   tema nuevo. */
.conectable__cab {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: var(--space-2);
  margin-bottom: var(--space-6);
}
.conectable__cab h2 { margin: 0; max-width: 20ch; }
.conectable__bajada { margin: 0; max-width: 54ch; color: var(--db-gris-claro); }

/* El rótulo de "en vivo", con su punto latiendo. El punto es la única cosa del
   sitio que se mueve sin que nadie la haya disparado, y está bien que así sea:
   dice literalmente que lo de abajo está corriendo. */
.conectable__vivo {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: 6px var(--space-3);
  border: 1px solid color-mix(in srgb, var(--db-acento) 34%, transparent);
  border-radius: 999px;
  font-size: var(--db-fs-eti);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--db-acento);
}
.conectable__punto {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--db-acento);
  animation: db-latir 2.4s ease-in-out infinite;
}
@keyframes db-latir {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.35; transform: scale(0.78); }
}

@media (prefers-reduced-motion: reduce) {
  .conectable__punto { animation: none; }
}
