/* ============================================================
   ATLA — diseno-web.css
   Universo propio de Diseño Web: papel técnico, tinta casi negra,
   marino de marca y un azul eléctrico para lo que se toca.

   Las tres referencias del cliente apuntan a lo mismo: **algo técnico**.
   Lambda —el archivo se llama literalmente "estilo tipografía y visual"—
   es monoespaciada de display, esquinas rectas, cuadrícula de puntos y un
   bloque invertido detrás de una línea del titular. Designfly pone un
   cursor escribiendo dentro de una caja de selección. Dominic saca el
   wordmark gigante sangrando por los bordes.

   Marketing también es clara, pero no se parecen en nada: aquélla es
   serif, curva y a todo color; ésta es mono, recta y de una sola tinta.

   ============================================================
   ⚠️ ESTA PÁGINA ROMPE LA §12.1 A PROPÓSITO

   La regla del sitio es que la monoespaciada se usa SOLO para cifras.
   Acá es la tipografía de display. Los motivos:

     1. La referencia que el cliente guardó para esta página se llama
        "Diseño Web estilo TIPOGRAFÍA y visual", y es un sitio de display
        monoespaciada. El pedido es explícito.
     2. En esta página la mono no es decoración: es el oficio que se vende.
     3. Se queda acá: es la única página del sitio con display monoespaciado.

   Si el cliente lo veta, se cambia `--display` por `var(--font-display)`
   y la página sigue en pie: no hay nada más que dependa de esto.
   ============================================================ */

.pag-diseno-web {
  --papel:      #FAFAF8;   /* blanco de papel técnico, más frío que el marfil */
  --papel-2:    #EFEFEB;
  --tinta:      #0E1117;
  --marino:     #16233D;   /* el color de Diseño Web en todo el sitio */
  --electrico:  #2F4BD8;   /* lo que se puede tocar */

  /* Tipografía propia (24/08/2026). El cliente pidió "la letra que estamos
     usando acá", señalando una línea de código de su editor. Eso es Consolas,
     que no se puede servir en la web (no tiene licencia para incrustar), así
     que va JetBrains Mono: la mono que hoy usan los editores de código, con
     el ojo más grande que Consolas —que a tamaño de titular se agradece— y
     variantes de peso, que Consolas no tiene.
     Acá la mono es el display Y las cifras: es la única página del sitio
     donde la monoespaciada no es un guiño sino el argumento (§7sexies). */
  --font-mono:   "JetBrains Mono", ui-monospace, Consolas, monospace;
  --peso-display: 500;
  --track-display: -0.04em;   /* la mono viene ancha: a 7rem hay que cerrarla */
  /* ⚠️ Las cifras NO van en JetBrains Mono, que es la familia de esta página.
     Su cero lleva un punto adentro —normal en una fuente de editor, para no
     confundir 0 con O— y en un precio como "$1.100.000" eso son cinco puntos
     seguidos: se lee sucio. Lo marcó el cliente.

     Van en Inter, el cuerpo de la página, **con cifras tabulares**: elegida
     por el cliente entre seis candidatas. No es monoespaciada, pero
     `tabular-nums` le da a todos los dígitos el mismo ancho, que es lo único
     que la maqueta necesita — los precios de los tres planes siguen alineando
     en columna. Y al no ser mono, los números dejan de competir con el
     titular: la mono se queda para lo que ES código.

     Es el único lugar del sitio donde las cifras no siguen al titular. */
  --font-cifras:  "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* La familia de display de ESTA página. Ver la advertencia de arriba. */
  --display: var(--font-mono);
  /* Y el titular genérico también: si no, un h2 sin regla propia caería en
     la grotesca del Home y sería la única cosa proporcional de la página. */
  --font-display: var(--font-mono);

  background: var(--papel);
  color: var(--tinta);

  --ink: var(--tinta);
  --ink-muted: #545A66;
  --line: rgba(14, 17, 23, 0.16);
  --line-soft: rgba(14, 17, 23, 0.08);
  --accent: var(--electrico);
  --paper: var(--papel);
}

/* El isotipo, casi monocromo: una sola barra en eléctrico y el rombo en
   marino. La página tiene dos tintas y el logo no puede tener cinco. */
.pag-diseno-web {
  --logo-1: rgba(14, 17, 23, 0.30);
  --logo-2: rgba(14, 17, 23, 0.50);
  --logo-3: var(--electrico);
  --logo-4: var(--tinta);
  --logo-diamond: var(--marino);
  --logo-rule: var(--tinta);
}

.pag-diseno-web .topbar.is-scrolled {
  background: var(--papel);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: 0 1px 0 var(--line);
}

/* ============================================================
   0. Reglas duras de la página
   ============================================================
   Nada tiene esquinas redondeadas salvo lo que viene del sistema
   (píldoras y botones). Un sitio que se presenta como técnico y redondea
   todo se contradice solo. */
.pag-diseno-web .caja { border-radius: 0; }

/* ============================================================
   1. Hero
   ============================================================ */
.hero-dw {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* Sangra por debajo de la cabecera (§6). No es por la foto —acá no hay
     foto— sino para que la cuadrícula viva llegue hasta el borde de
     arriba: si el hero arranca debajo de la barra, detrás del header
     queda una franja de blanco muerto de 226px. Ahora la barra flota
     sobre la retícula y se enciende con el resto. */
  margin-top: calc(var(--header-h) * -1);
  padding-top: calc(var(--header-h) + var(--sp-4));
  padding-bottom: clamp(4rem, 9vw, 7rem);
}

.hero-dw__inner { max-width: 46rem; }
.hero-dw__grid .hero-dw__inner { max-width: 100%; }

.hero-dw .label { color: var(--electrico); }

/* El titular. Mono, apretado y en dos pesos: es el gesto de Lambda. */
.hero-dw__titulo {
  font-family: var(--display);
  /* 3.8rem y no 4.6: en mono, "tanto como vos" son 14 caracteres y a
     4.6rem no entraban en la columna del hero de dos columnas. */
  font-size: clamp(2rem, 5.2vw, 3.8rem);
  font-weight: 500;
  line-height: 1.06;
  letter-spacing: -0.03em;
  margin-top: var(--sp-3);
  text-transform: none;
}

/* El bloque invertido detrás de una línea. En Lambda es negro; acá es el
   marino de marca, que es lo mismo pero es NUESTRO. */
.hero-dw__bloque {
  display: inline-block;
  background: var(--marino);
  color: var(--papel);
  padding: 0.06em 0.28em 0.14em;
  /* Sin radio: es un bloque, no una píldora. */
  border-radius: 0;
}

/* La línea que se descifra. Va en versalitas y tenue: es el subtítulo
   técnico de la referencia, no un segundo titular. */
.hero-dw__firma {
  margin-top: var(--sp-4);
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  /* El texto barajado tiene el mismo largo que el real, pero reservar el
     renglón evita cualquier salto si alguna vez deja de ser mono. */
  min-height: 1.4em;
}

.hero-dw__lead {
  margin-top: var(--sp-3);
  max-width: 48ch;
  font-size: var(--fs-lead);
  color: var(--ink-muted);
}

.hero-dw__acciones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-5);
}

/* ---------- La cuadrícula viva (rejilla.js) ----------
   Reemplaza a los cuadraditos punteados, que eran calcados de Lambda.
   Ahora la retícula está apenas insinuada de base y se ENCIENDE alrededor
   del cursor: en una página que vende sitios web, un fondo que responde
   es el argumento; uno que se mueve solo es decoración.

   Cubre el hero entero, no el costado: el efecto sigue al cursor y el
   cursor va donde quiere. Y va con `pointer-events: none` porque el que
   escucha el puntero es el hero, no el canvas (ver nota en rejilla.js). */
.rejilla {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
.rejilla canvas { display: block; }

/* Titular de sección. Estaba repetido cuatro veces como estilo suelto en
   el HTML; en mono conviene un punto menos de tamaño que el `--fs-h2` del
   sistema, porque la monoespaciada corre bastante más ancha que la serif
   y con el tamaño original todo se iba a tres renglones. */
.titulo-dw {
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(1.8rem, 3.9vw, 3rem);
  line-height: 1.1;
  letter-spacing: -0.03em;
  margin-top: var(--sp-2);
}

/* Bloque introductorio de cada sección. */
.intro-dw { max-width: 34rem; }

/* La sección de servicios va OSCURA. El GridScan está pensado para
   fondo negro —así se ve en reactbits— y sobre el papel blanco de la
   página las celdas de la grilla quedaban blancas en vez de negras, que
   es justo lo que el efecto necesita para leerse.

   Es la única banda oscura de la página: por eso "Cómo trabajamos", que
   antes era marino, pasó a claro. Dos bandas oscuras seguidas dejan de
   ser ritmo y son un bloque (§4). */
.obras-oscura {
  background: var(--tinta);
  color: var(--ink-on-dark);
  --ink: var(--ink-on-dark);
  --ink-muted: rgba(244, 242, 238, 0.68);
  --line: rgba(244, 242, 238, 0.18);
  /* El azul eléctrico sobre negro casi no se ve: en esta sección se
     aclara. El verde del barrido ya aporta el acento. */
  --electrico: #7E93F0;
}

/* Cualquier sección que quiera una capa de fondo (rejilla o escáner). */
.con-rejilla { position: relative; isolation: isolate; }

/* ============================================================
   La trama de código — fondo de la sección de Planes
   ============================================================
   Reemplazó a la nieve de píxeles (`nieve.js`), que el cliente pidió cambiar
   por algo "relacionado con el armado de páginas web o la programación".

   Es el minimapa de un editor de código: renglones de largo variable, con
   sangrías, y algunos tokens en el azul eléctrico de la página. A este tamaño
   no se lee como texto —no lo es— pero se reconoce de inmediato, que es
   justo lo que se buscaba: dice "programación" sin ilustrar nada.

   POR QUÉ ASÍ Y NO OTRO EFECTO:
     · Es un SVG embebido: **cero peticiones de red, cero canvas, cero JS**.
       La nieve era WebGL2 con un bucle por cuadro (§7sexies). Acá lo único
       que se mueve es un `transform`, o sea trabajo del compositor.
     · La página ya tiene tres efectos de fondo que reaccionan (rejilla,
       gridscan, luz). Detrás de una tabla de precios lo que hace falta es lo
       contrario: algo quieto que no pida atención.

   El dibujo se generó con semilla fija (1117) para que sea reproducible:
   44 barras en un mosaico de 640×320 que se repite. */
.codigo {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  /* Se apaga contra los bordes de la sección: un mosaico cortado en seco
     delata que es un mosaico. Es la misma regla del hero de Contabilidad —
     que ninguna capa llegue al borde (§7quater). */
  --difumina: linear-gradient(180deg, transparent 0%, #000 14%, #000 84%, transparent 100%);
  -webkit-mask-image: var(--difumina);
  mask-image: var(--difumina);
}

/* La capa que se mueve. Sube 320px —exactamente el alto del mosaico— así el
   bucle cierra sin salto. 96s: tiene que leerse como que respira, no como
   que algo se desplaza. */
.codigo__capa {
  position: absolute;
  left: 0;
  right: 0;
  top: -320px;
  bottom: -320px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='640' height='320' viewBox='0 0 640 320'%3E%3Cg fill='%230E1117' opacity='.055'%3E%3Crect x='14' y='10' width='65' height='6' rx='3'/%3E%3Crect x='92' y='10' width='95' height='6' rx='3'/%3E%3Crect x='202' y='10' width='58' height='6' rx='3'/%3E%3Crect x='32' y='30' width='48' height='6' rx='3'/%3E%3Crect x='89' y='30' width='34' height='6' rx='3'/%3E%3Crect x='132' y='30' width='74' height='6' rx='3'/%3E%3Crect x='14' y='50' width='37' height='6' rx='3'/%3E%3Crect x='64' y='50' width='53' height='6' rx='3'/%3E%3Crect x='131' y='50' width='50' height='6' rx='3'/%3E%3Crect x='50' y='90' width='69' height='6' rx='3'/%3E%3Crect x='128' y='90' width='74' height='6' rx='3'/%3E%3Crect x='217' y='90' width='72' height='6' rx='3'/%3E%3Crect x='14' y='110' width='86' height='6' rx='3'/%3E%3Crect x='14' y='130' width='45' height='6' rx='3'/%3E%3Crect x='72' y='150' width='88' height='6' rx='3'/%3E%3Crect x='174' y='150' width='84' height='6' rx='3'/%3E%3Crect x='270' y='150' width='57' height='6' rx='3'/%3E%3Crect x='14' y='170' width='27' height='6' rx='3'/%3E%3Crect x='52' y='170' width='44' height='6' rx='3'/%3E%3Crect x='118' y='190' width='26' height='6' rx='3'/%3E%3Crect x='157' y='190' width='94' height='6' rx='3'/%3E%3Crect x='14' y='210' width='67' height='6' rx='3'/%3E%3Crect x='190' y='210' width='78' height='6' rx='3'/%3E%3Crect x='278' y='210' width='58' height='6' rx='3'/%3E%3Crect x='68' y='230' width='83' height='6' rx='3'/%3E%3Crect x='164' y='230' width='83' height='6' rx='3'/%3E%3Crect x='68' y='250' width='81' height='6' rx='3'/%3E%3Crect x='50' y='290' width='83' height='6' rx='3'/%3E%3Crect x='149' y='290' width='62' height='6' rx='3'/%3E%3Crect x='301' y='290' width='59' height='6' rx='3'/%3E%3Crect x='119' y='310' width='83' height='6' rx='3'/%3E%3Crect x='210' y='310' width='42' height='6' rx='3'/%3E%3Crect x='268' y='310' width='55' height='6' rx='3'/%3E%3C/g%3E%3Cg fill='%232F4BD8' opacity='.10'%3E%3Crect x='14' y='150' width='42' height='6' rx='3'/%3E%3Crect x='107' y='170' width='37' height='6' rx='3'/%3E%3Crect x='153' y='170' width='22' height='6' rx='3'/%3E%3Crect x='50' y='190' width='54' height='6' rx='3'/%3E%3Crect x='94' y='210' width='84' height='6' rx='3'/%3E%3Crect x='256' y='230' width='39' height='6' rx='3'/%3E%3Crect x='311' y='230' width='80' height='6' rx='3'/%3E%3Crect x='165' y='250' width='65' height='6' rx='3'/%3E%3Crect x='50' y='270' width='93' height='6' rx='3'/%3E%3Crect x='223' y='290' width='64' height='6' rx='3'/%3E%3Crect x='50' y='310' width='56' height='6' rx='3'/%3E%3C/g%3E%3C/svg%3E");
  background-repeat: repeat;
  animation: codigo-sube 96s linear infinite;
  will-change: transform;
}

@keyframes codigo-sube {
  from { transform: translateY(0); }
  to   { transform: translateY(-320px); }
}

@media (prefers-reduced-motion: reduce) {
  .codigo__capa { animation: none; will-change: auto; }
}

/* El GridScan: grilla en perspectiva con barrido (gridscan.js). */
.gridscan {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}
.gridscan canvas { display: block; width: 100%; height: 100%; }

/* ============================================================
   2. Servicios
   ============================================================
   Misma gramática que el resto del sitio (§7ter): el problema en primera
   persona primero, el nombre del producto después.

   Van en DOS PANELES lado a lado, no en filas apiladas. Con solo dos
   servicios, las filas dejaban media página vacía a la derecha — que es
   lo que el cliente marcó como "se siente vacía". Dos paneles ocupan el
   ancho y hacen que la sección se lea deliberada.

   No son tarjetas flotando en una grilla (§5.1): comparten borde, como
   dos celdas de una tabla. Es el mismo criterio que los planes.
   ============================================================ */
.obras {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-top: var(--sp-5);
  /* Sin recuadro y sin fondo: los dos servicios flotan directamente sobre
     el GridScan. El marco competía con la grilla, que ya es una retícula:
     dos rejas superpuestas se anulan. */
  background: transparent;
}

.obra {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  padding: clamp(1.5rem, 3.5vw, 2.75rem);
  min-height: 22rem;
}

.obra__num {
  font-family: var(--font-cifras, var(--font-mono));
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-small);
  letter-spacing: 0.1em;
  color: var(--electrico);
}

.obra__voz {
  margin-top: var(--sp-3);
  font-family: var(--display);
  font-size: clamp(1.25rem, 2.4vw, 1.9rem);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.02em;
  max-width: 20ch;
}

.obra__nombre {
  margin-top: var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.obra__desc { margin-top: var(--sp-2); max-width: 46ch; }

.obra__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  min-height: 44px;
  /* Pegado al fondo del panel: así los dos botones quedan a la misma
     altura aunque los textos midan distinto. */
  margin-top: auto;
  align-self: flex-start;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: 0.06em;
  color: var(--electrico);
  border-bottom: 1px solid color-mix(in srgb, var(--electrico) 45%, transparent);
  transition: border-color var(--dur) var(--ease), gap var(--dur) var(--ease);
}
.obra__cta:hover { border-bottom-color: var(--electrico); gap: 0.9em; }

/* El botón al portfolio, centrado bajo los dos paneles. */
.obras__portfolio {
  margin-top: var(--sp-5);
  text-align: center;
}

@media (max-width: 820px) {
  .obras { grid-template-columns: 1fr; gap: var(--sp-4); }
  .obra { min-height: 0; }

  /* Sin GridScan (ver la nota en gridscan.js), la sección se queda con una
     retícula plana de CSS. No depende del aspecto del contenedor, no gasta
     un cuadro y mantiene la textura que la sección necesita. */
  .obras-oscura {
    background-image:
      linear-gradient(rgba(42, 53, 80, 0.55) 1px, transparent 1px),
      linear-gradient(90deg, rgba(42, 53, 80, 0.55) 1px, transparent 1px);
    background-size: 44px 44px, 44px 44px;
  }
}

/* ============================================================
   3. Proceso — la única banda oscura de la página (§4)
   ============================================================ */
/* Vuelve al marino. La regla de "una sola banda oscura por página" (§4)
   asume que las dos bandas son superficies equivalentes, y acá no lo son:
   la de servicios es una grilla activa que se mueve, y ésta es un plano
   liso. Después de esa sección el marino no compite — descansa. La
   secuencia se lee ruido → silencio, no como un bloque oscuro largo. */
.proceso-dw {
  background: var(--marino);
  color: var(--ink-on-dark);
  --ink: var(--ink-on-dark);
  --ink-muted: rgba(244, 242, 238, 0.68);
  --line: rgba(244, 242, 238, 0.18);
}

.proceso-dw .label { color: #9DB0E8; }

.proceso-dw__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-4);
  margin-top: var(--sp-5);
}

.paso-dw { border-top: 2px solid var(--line); padding-top: var(--sp-3); }

.paso-dw__num {
  font-family: var(--font-cifras, var(--font-mono));
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-small);
  letter-spacing: 0.1em;
  color: #9DB0E8;
}

.paso-dw__nombre {
  margin-top: var(--sp-2);
  font-family: var(--display);
  font-size: var(--fs-h3);
  font-weight: 500;
  letter-spacing: -0.01em;
}

.paso-dw__desc { margin-top: var(--sp-1); font-size: var(--fs-small); color: var(--ink-muted); }

@media (max-width: 860px) {
  .proceso-dw__grid { grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
}
@media (max-width: 520px) {
  .proceso-dw__grid { grid-template-columns: 1fr; }
}

/* ============================================================
   4. Planes
   ============================================================
   Tres FILAS a todo el ancho, separadas por filete (09/09/2026).

   Antes eran tres columnas con `subgrid` y el plan del medio en un bloque
   eléctrico. Medido, dejaba tres problemas: huecos muertos donde un nombre
   ocupaba un renglón y los otros dos, el bloque de color partía la sección
   en dos, y había dos recuadros seguidos (planes + rangos). Es la gramática
   de §5.1 y de los `.caso` de Consultoría: sin cajas, con aire y filetes.

   Cada fila son tres columnas: el argumento (nombre, qué es, por qué cuesta
   eso), los montos, y lo que incluye con el botón. La lectura va de
   izquierda a derecha en el orden en que se decide: qué es → cuánto → qué
   me llevo.

   ⚠️ La trama de código NO puede pasar por detrás del texto. Se probó
   (09/09/2026) y a 5,5% de opacidad igual cruza los precios y los
   renglones: se lee como ruido, no como atmósfera. Pero un fondo liso y
   sin borde deja un rectángulo fantasma donde la trama se corta en seco —
   el defecto del mosaico de §7quater. Va una capa de papel DETRÁS de las
   filas, más ancha que el contenedor y con los cuatro bordes desvanecidos
   (`mask-composite: intersect`, el recurso de §7nonies): la trama vive en
   los márgenes y se apaga suave antes de llegar al texto. */
.planes {
  margin-top: var(--sp-5);
  border-top: 1px solid var(--line);
}

.planes,
.rangos { position: relative; }

.planes::before,
.rangos::before {
  content: "";
  position: absolute;
  /* No pasa del gutter a lo ancho: si se saliera del viewport en móvil,
     sumaría scroll horizontal. */
  inset: -2rem calc(var(--gutter) * -1);
  z-index: -1;
  background: var(--papel);
  --fx: linear-gradient(90deg, transparent, #000 var(--gutter), #000 calc(100% - var(--gutter)), transparent);
  --fy: linear-gradient(180deg, transparent, #000 2rem, #000 calc(100% - 2rem), transparent);
  -webkit-mask-image: var(--fx), var(--fy);
  -webkit-mask-composite: source-in;
  mask-image: var(--fx), var(--fy);
  mask-composite: intersect;
}

.plan {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr) minmax(0, 0.9fr);
  gap: clamp(1.5rem, 4vw, 4rem);
  padding-block: clamp(2rem, 4.5vw, 3.25rem);
  border-bottom: 1px solid var(--line);
}

/* "Más elegido" es una señal tipográfica, no un bloque. Va en eléctrico
   arriba del nombre, con la misma barra corta que usan las viñetas de la
   lista: el color de la página aparece donde hay una decisión que tomar. */
.plan__etiqueta {
  display: flex;
  align-items: center;
  gap: 0.7em;
  margin-bottom: var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--electrico);
}
.plan__etiqueta::before {
  content: "";
  width: 10px;
  height: 2px;
  background: var(--electrico);
}

.plan__nombre {
  font-family: var(--display);
  font-size: var(--fs-h3);
  font-weight: 500;
  letter-spacing: -0.01em;
}

/* Qué ES el plan. Va en tinta plena y antes del precio: primero hay que
   entender qué se compra, después cuánto sale. */
.plan__que {
  margin-top: var(--sp-2);
  max-width: 34ch;
  line-height: 1.5;
}

/* Por qué cuesta eso. Es lo que separa esta tabla de cualquier otra: un
   plan que explica su propio precio. Muted porque es respaldo del
   argumento, pero con el arranque en tinta para que se vea que ahí hay
   una respuesta. */
.plan__porque {
  margin-top: var(--sp-3);
  max-width: 40ch;
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--ink-muted);
}
.plan__porque b { color: var(--ink); font-weight: 500; }

/* --- Los montos --- */
.plan__montos {
  display: grid;
  align-content: start;
  gap: var(--sp-3);
}

/* La etiqueta va ARRIBA del monto, como cabecera de dato: "El proyecto:
   $X". Es la misma familia y tracking que `.rango--cab`, así los dos
   bloques de la sección comparten la misma cabecera. */
.plan__pie {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 0.5rem;
}

/* ⚠️ EL RANGO VA APILADO. "$1.100.000 – $4.000.000" son 23 caracteres:
   a tamaño de precio pide ~340px y la columna del medio mide ~300 en 1240.
   Apilado, el piso conserva su tamaño y el techo baja a 0.72em: se lee
   "arranca en X, llega hasta Y", que además es el orden en que se piensa
   un rango. */
.plan__precio {
  /* `--font-cifras` es Inter en esta página (ver arriba). Las tabulares no
     son un adorno: sin ellas los tres precios dejan de alinear en columna. */
  font-family: var(--font-cifras, var(--font-mono));
  font-variant-numeric: tabular-nums;
  font-size: clamp(1.5rem, 3.4vw, 2rem);
  letter-spacing: -0.03em;
  line-height: 1.12;
}
.plan__precio > span { display: block; }
.plan__techo {
  font-size: 0.72em;
  color: var(--ink-muted);
}
/* El abono no puede pesar lo mismo que el proyecto: es el segundo dato. */
.plan__precio--mes { font-size: clamp(1.1rem, 2.3vw, 1.35rem); }

/* Qué cubre el abono. Sin esto el número mensual queda sin justificar. */
.plan__cubre {
  margin-top: 0.5rem;
  max-width: 30ch;
  font-size: var(--fs-small);
  line-height: 1.45;
  color: var(--ink-muted);
}

/* --- Lo que incluye y el botón --- */
.plan__extra {
  display: grid;
  align-content: start;
}

.plan__lista { display: grid; gap: 0.6rem; }
.plan__lista li {
  display: flex;
  gap: 0.7em;
  font-size: var(--fs-small);
  color: var(--ink-muted);
}
/* Una barra, no una viñeta redonda: coherente con las esquinas rectas. */
.plan__lista li::before {
  content: "";
  width: 10px;
  height: 2px;
  margin-top: 0.62em;
  flex: none;
  background: var(--electrico);
}

.plan__extra .btn {
  margin-top: var(--sp-4);
  justify-self: start;
}

/* En 1000px las tres columnas caen a ~300px y el argumento de la izquierda
   se vuelve una columna de texto angosta y alta. Pasa a dos niveles: el
   argumento arriba a todo el ancho, y debajo los montos y lo que incluye,
   lado a lado. */
@media (max-width: 1000px) {
  .plan {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    row-gap: var(--sp-4);
  }
  .plan__cab { grid-column: 1 / -1; }
  .plan__que, .plan__porque { max-width: 62ch; }
}

/* Una sola columna. Los montos van antes que la lista: en un teléfono el
   precio es lo que se busca, la lista es lo que se confirma. */
@media (max-width: 600px) {
  .plan {
    grid-template-columns: 1fr;
    row-gap: var(--sp-3);
    padding-block: var(--sp-5);
  }
  .plan__montos { gap: var(--sp-2); }
}

/* ============================================================
   5. Cierre
   ============================================================ */
.cierre-dw {
  text-align: center;
  background: var(--papel-2);
}
.cierre-dw__titulo {
  font-family: var(--display);
  font-size: var(--fs-h2);
  font-weight: 500;
  letter-spacing: -0.02em;
  margin: var(--sp-2) auto var(--sp-4);
  max-width: 20ch;
}

/* ============================================================
   6. Los dos efectos de texto
   ============================================================ */

/* --- letras.js: el titular entra letra por letra --- */
.letras__palabra { display: inline-block; white-space: nowrap; }

.letras__letra {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.4em);
  transition:
    opacity 520ms var(--ease),
    transform 520ms cubic-bezier(0.22, 0.61, 0.36, 1);
  transition-delay: var(--d, 0ms);
}
.letras--dentro .letras__letra { opacity: 1; transform: none; }

/* --- descifrar.js: mientras baraja, va en eléctrico --- */
[data-descifrar] { color: var(--electrico); }
[data-descifrar][data-descifrado="true"] {
  color: var(--ink-muted);
  transition: color 600ms var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  .letras__letra { opacity: 1; transform: none; transition: none; }
}

/* ============================================================
   7. Pie
   ============================================================ */
.pag-diseno-web .footer { background: var(--papel-2); border-top-color: var(--line); }

/* ============================================================
   8. Responsive
   ============================================================ */
@media (max-width: 720px) {
  .obra { grid-template-columns: 1fr; gap: var(--sp-2); }
  .hero-dw__inner { max-width: 100%; }
}

/* ============================================================
   9. La maqueta del hero — la demostración
   ============================================================
   Una ventana de navegador que pasa del boceto al sitio terminado,
   detrás de una cortina de píxeles (`pixeles.js`).

   Es el argumento de la página hecho imagen: si lo que se vende es
   construir sitios, la página tiene que mostrar que sabe hacerlo, no
   contarlo. Y está dibujada entera en CSS: ni una imagen, ni un pedido
   de red, y nada que dependa de material que el cliente todavía no tiene.
   ============================================================ */
.maqueta {
  /* El user-agent le pone `margin: 1em 40px` a todo <figure>. Sin esto la
     maqueta perdía 80px de ancho y quedaba chica al lado del titular. */
  margin: 0;
  border: 1px solid var(--line);
  background: var(--papel);
  box-shadow: 0 24px 60px rgba(14, 17, 23, 0.14);
}

.maqueta__barra {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.6rem 0.8rem;
  border-bottom: 1px solid var(--line);
  background: var(--papel-2);
}
.maqueta__barra span {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--line);
  flex: none;
}
.maqueta__url {
  margin-left: 0.6rem;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
}

.maqueta__pantalla {
  aspect-ratio: 16 / 11;
  background: var(--papel);
}

.maqueta__pie {
  padding: 0.7rem 0.9rem;
  border-top: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* ---------- Las dos caras ---------- */
/* Columna FLEXIBLE y no grilla: en grid las filas se empaquetan arriba y
   `margin-top: auto` no empuja nada, porque no hay espacio libre dentro de
   la fila del elemento. En flex sí, y es lo que manda el pie al fondo. */
.maqueta__cara {
  padding: clamp(0.9rem, 2.2vw, 1.4rem);
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.maqueta__cara > * { flex: none; }

/* Cara A — el boceto: todo gris y punteado, como un wireframe. */
.cara-boceto { background: #F3F3F0; }
.cara-boceto .bloque { background: transparent; border: 1.5px dashed rgba(14, 17, 23, 0.28); }
.cara-boceto .bloque--lleno { background: rgba(14, 17, 23, 0.09); border-style: dashed; }

/* Cara B — el sitio terminado, con la paleta de la página. */
.cara-final { background: var(--papel); }
.cara-final .bloque { background: rgba(14, 17, 23, 0.10); border: 0; }
.cara-final .bloque--marca { background: var(--marino); }
.cara-final .bloque--acento { background: var(--electrico); }
.cara-final .bloque--titulo { background: var(--tinta); }

.bloque { border-radius: 0; }
.fila { display: flex; gap: 0.5rem; }
.fila > * { flex: 1; }

/* ---------- La cortina de píxeles ---------- */
.pixeles { position: relative; overflow: hidden; isolation: isolate; }

.pixeles > [data-pixeles-cara] {
  position: absolute;
  inset: 0;
  visibility: hidden;
}
.pixeles > [data-pixeles-cara][data-visible="true"] { visibility: visible; }

.pixeles__cortina { position: absolute; inset: 0; z-index: 2; pointer-events: none; }

.pixeles__cortina i {
  position: absolute;
  display: block;
  transform: scale(0);
  /* 1.04 y no 1: a escala exacta quedan costuras de medio píxel entre
     celdas y se ve una rejilla clara sobre el color. */
  transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1);
  /* ⚠️ SIN `will-change`. Lo tenía, y eran **369 capas promovidas a GPU de
     forma permanente** —una por píxel de la cortina— viviendo en memoria de
     video todo el tiempo, aunque la cortina esté quieta la mayor parte del
     recorrido. Es la misma lección que dejó el eco de Consultoría (§7ter):
     `will-change` puesto siempre reserva una capa siempre.

     No hace falta: el navegador promueve el elemento solo mientras su
     transición de `transform` está corriendo, que es exactamente el rato en
     que sirve. */
}
.pixeles__cortina[data-tapando="true"] i { transform: scale(1.04); }

/* ---------- El hero en dos columnas ---------- */
.hero-dw__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}

@media (max-width: 980px) {
  .hero-dw__grid { grid-template-columns: 1fr; }
  /* En una columna la maqueta va DEBAJO del texto: primero el mensaje. */
  .hero-dw__demo { margin-top: var(--sp-5); }
}

/* ============================================================
   Por que el precio es un rango

   Filas con filete, sin recuadro y sin tarjetas (§5.1). En movil la
   grilla colapsa a una columna y cada celda recupera su etiqueta con
   un ::before, porque sin la cabecera de arriba "15 dias de garantia
   tecnica" suelto no dice de que extremo del rango es.
   ============================================================ */
/* Cuelga de la grilla de planes: por eso el margen de arriba es corto y
   el de abajo lo pone .rangos. No lleva recuadro — es una aclaracion de
   los planes, no un bloque aparte. */
.planes__nota {
  margin-top: var(--sp-3);
  max-width: 62ch;
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--ink-muted);
}
.planes__nota b { color: var(--ink); font-weight: 500; }

.rangos {
  margin-top: var(--sp-7);
  /* Sin recuadro y sin fondo (09/09/2026). Con los planes convertidos en
     filas, una caja acá era el único recuadro de la sección y se leía como
     tarjeta. Es el mismo lenguaje: filas con filete sobre el fondo. */
}

.rangos__titulo {
  font-family: var(--display);
  font-size: var(--fs-h3);
  font-weight: 500;
  letter-spacing: -0.01em;
}
.rangos__lead {
  margin-top: var(--sp-2);
  max-width: 62ch;
  color: var(--ink-muted);
}

.rangos__tabla {
  margin-top: var(--sp-4);
  border-top: 1px solid var(--line);
}

.rango {
  display: grid;
  grid-template-columns: minmax(9rem, 0.9fr) 1.25fr 1.25fr;
  gap: var(--sp-3);
  padding-block: var(--sp-3);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-small);
}

.rango--cab {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding-block: var(--sp-2);
}

.rango__factor { font-weight: 500; }
.rango__piso,
.rango__techo { color: var(--ink-muted); }

/* El techo lleva el color de la pagina: es hacia donde crece el trabajo. */
.rango:not(.rango--cab) .rango__techo { color: var(--ink); }
.rango:not(.rango--cab) .rango__techo::marker { color: var(--electrico); }

@media (max-width: 720px) {
  .rango--cab { display: none; }
  .rango {
    grid-template-columns: 1fr;
    gap: var(--sp-1);
  }
  .rango__factor { font-size: var(--fs-body); }
  .rango__piso::before,
  .rango__techo::before {
    content: "Piso  ";
    display: block;
    font-family: var(--font-mono);
    font-size: var(--fs-label);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--electrico);
    margin-top: 0.5rem;
  }
  .rango__techo::before { content: "Techo  "; }
}
